LoginSignup
8

More than 5 years have passed since last update.

Terraformで作った Amazon API Gatewayに変更があっても再デプロイされない問題に対処する

Posted at

前提

  • aws_api_gateway_deployment リソースを使ってデプロイまでTerraformで実行している

    api.tf
    resource "aws_api_gateway_deployment" "production" {
      depends_on = [
        "aws_api_gateway_integration.lambda_integration",
      ]
    
      rest_api_id = "${aws_api_gateway_rest_api.main.id}"
      stage_name  = "prod"
    }
    
  • 1回以上 terraform apply しているときにAPI Gatewayに関する変更を加えた

問題

aws_api_gateway_rest_api などに変更が追加しても、デプロイは初回に実行されているので aws_api_gateway_deployment に変更は生じず、再デプロイされない
(再デプロイされないのでAPIにアクセスしても意図した動作にならない)

再デプロイが必要になる変更例

バイナリサポートを有効化 するために AWS: aws_api_gateway_rest_apiのbinary_media_types を追加

api.tf
resource "aws_api_gateway_rest_api" "main" {
  name = "${var.prefix}"
+
+  binary_media_types = [
+    "*/*",
+  ]
}

解決策

API Gateway に関係する tfファイルのハッシュを stage_description に含める。

api.tf
resource "aws_api_gateway_deployment" "production" {
  depends_on = [
    "aws_api_gateway_integration.lambda_integration",
  ]

  rest_api_id = "${aws_api_gateway_rest_api.main.id}"
  stage_name  = "prod"
+
+  # API Gatewayの変更時に再デプロイさせるためのハック
+  stage_description = "setting file hash = ${md5(file("api.tf"))}"
}

tfを書き換えてAPI Gatewayの設定が変更するためファイルハッシュをチェックすれば再デプロイが必要かどうか判定できる。

リソースが再生成される条件

  • stage_description に変更がある場合、 forces new resource となりリソースが再生成 == 再デプロイとなる
stage_description変更時のplan結果
-/+ aws_api_gateway_deployment.production (new resource required)
      id:                "4s1vdj" => <computed> (forces new resource)
      created_date:      "2019-02-03T02:22:17Z" => <computed>
      execution_arn:     "arn:aws:execute-api:ap-northeast-1:991090258880:al17cenlok/prod" => <computed>
      invoke_url:        "https://al17cenlok.execute-api.ap-northeast-1.amazonaws.com/prod" => <computed>
      rest_api_id:       "al17cenlok" => "al17cenlok"
      stage_description: "setting file hash = 104b824aa7f41a9f55658a512b8c229f" => "setting file hash = af89ba1e8a8db87c195ee35796b8e0c1" (forces new resource)
      stage_name:        "prod" => "prod"


Plan: 1 to add, 0 to change, 1 to destroy.
  • description はリソースの再作成ではなく変更となるため再デプロイされないのでNG
description変更時のplan結果
  ~ aws_api_gateway_deployment.production
      description: "setting file hash = ed3085ab0ec5ea2f6dfda005fe5009ea" => "setting file hash = 86934e55913dcfa50cf8dc975d4662ab"


Plan: 0 to add, 1 to change, 0 to destroy.

※ 変更があったときに再実行させる方法としては triggers があるが、これは Provisioners: null_resource 専用であるため、AWS: aws_api_gateway_deployment では使えない

triggersを設定した場合のplan結果
Error: aws_api_gateway_deployment.production: : invalid or unknown key: triggers

注意点

API Gatewayに関するtfファイルのみをチェック対象にしているため、対象ファイル中で使用されている Input Variables ("${var.hoge}") に変更があった場合は再デプロイされない。
この場合は、 Input Variablesstage_description に含めればOK。
あるいは、timestamp() を使うことで、毎回必ず再デプロイさせることも可能1

aws_api_gateway_deployment
  stage_description = "timestamp = ${timestamp()}"

参考

ソースコード2

Terraform-Amazon-API-Gateway-AWS-Lambda/api.tf

関連Issue

関連記事


  1. ${timestamp()}を使う方法は、変更がない場合もリソースが再生成されてしまうのでおすすめしません 

  2. Qiitaではterraform(HCL)をcodeのlangに指定できないらしいので、本記事中では見やすいshを指定しています 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8