Terraform: API Gatewayでdeploymentとstageでstage_nameがconflictする

2020/01/12
2021/02/25

プライベートでVPSを借りて動かしている古いAPIがある。これをAWSに移行しようと考えており、その過程でTerraformを使ってコード化を進めている。

その中で API Gateway を使っているのだが、stagedeployment のresourceを普通に定義していったところ、conflictしてしまい正常に実行できなかった。

GitHub でも issue が見つかり stage_name”" とするという解法も見つけた。
Error creating API Gateway Stage: ConflictException: Stage already exists #2918

以下のような形になる。

resource  "aws_api_gateway_stage"  "stage"  {
  depends_on = ["aws_cloudwatch_log_group.log-group-api-gateway-rest-api"]
  stage_name =  "${var.stage-name}"
  rest_api_id =  "${aws_api_gateway_rest_api.api-gateway-rest-api.id}"
  deployment_id =  "${aws_api_gateway_deployment.api-gateway-deployment.id}"
}

resource  "aws_api_gateway_deployment"  "api-gateway-deployment"  {
  depends_on = ["aws_api_gateway_integration.api-gateway-integration"]
  rest_api_id =  "${aws_api_gateway_rest_api.api-gateway-rest-api.id}"
  stage_name =  ""
}

一見これで解決するようにも思えたが、API Gateway の設定を変更してデプロイしなければならないときには deploymentを更新する必要があり、そのときには stage_name が空では動かない。

対策として、stageの定義自体は実は deployment にも情報が含まれているため、stageに含まれていた depends_ondeployment に移し、deployment に統合してstageのresource定義を廃止した。

resource "aws_api_gateway_deployment" "api-gateway-deployment" {
  depends_on        = ["aws_cloudwatch_log_group.log-group-api-gateway-rest-api", "aws_api_gateway_integration.api-gateway-integration"]
  rest_api_id       = "${aws_api_gateway_rest_api.api-gateway-rest-api.id}"
  stage_name        = "${var.api-gateway-rest-api-stage-name}"
  stage_description = "${md5(file("../../modules/apigateway.tf"))}"
  lifecycle {
    create_before_destroy = true
  }
}

なお、設定変更しても deploy してくれない問題を避けるため、deploymentstage_description は tf ファイルの内容が変わったら変更が入ったとみなされるようにしている。

© 2010 ksoichiro