Create API Gateway Using Terraform

0

Hi,

I am trying to create API Gateway with two methods PUT and POST using Terraform. Here is my code: Simply I want to create below methods under same API gateway using terraform but getting error Put - /events/updatetags/{object_id} Post - /events/wafacl/add_ipset

Not sure, how to handle stage when creating more than one method using Terraform. Code works for one method.

Error:

│ Error: creating API Gateway Stage (dev): ConflictException: Stage already exists
│ 
│   with module.api_gateway.aws_api_gateway_stage.events_waf_apig_stages,
│   on api_gateway/main.tf line 389, in resource "aws_api_gateway_stage" "events_waf_apig_stages":
│  389: resource "aws_api_gateway_stage" "events_waf_apig_stages" {

Terraform Code

resource "aws_api_gateway_rest_api" "events_apig" {
  name = "demo-events-handler-apig-${var.environment}"
  api_key_source = "HEADER"
  endpoint_configuration {
    types = ["REGIONAL"]
  }
}

resource "aws_api_gateway_resource" "events_apig_resources_event" {
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  parent_id = aws_api_gateway_rest_api.events_apig.root_resource_id
  path_part = "events"
  # path = "/events"
}



resource "aws_api_gateway_resource" "events_apig_resources_updatetags" {
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  parent_id = aws_api_gateway_resource.events_apig_resources_event.id
  path_part = "updatetags"
  # path = "/events/updatetags"
}

resource "aws_api_gateway_resource" "events_apig_resources_objectid" {
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  parent_id = aws_api_gateway_resource.events_apig_resources_updatetags.id
  path_part = "{object_id}"
  # path = "/events/updatetags/{object_id}"
}

resource "aws_api_gateway_request_validator" "updatetag_request_validator" {
  name = "updatetag_request_validator"
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  validate_request_body = true
  validate_request_parameters = false
}



resource "aws_api_gateway_method" "events_apig_method" {
    authorization = "AWS_IAM"
    http_method = "PUT"
    resource_id = aws_api_gateway_resource.events_apig_resources_objectid.id
    rest_api_id = aws_api_gateway_rest_api.events_apig.id
    # api_key_required = ""
    request_parameters = {
      "method.request.header.x-key" = true
    }
    request_validator_id = aws_api_gateway_request_validator.updatetag_request_validator.id
    # request_models = { "application/json" = "${aws_api_gateway_model.demos_event_requestbody_model.name}"}
}

resource "aws_api_gateway_integration" "integration_updatetags" {
    # demos_event_handler_invoke_arn
  http_method = aws_api_gateway_method.events_apig_method.http_method
  resource_id = aws_api_gateway_resource.events_apig_resources_objectid.id
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  integration_http_method = "POST"
  type = "AWS_PROXY"
  request_templates = {}
  uri = var.demos_event_handler_invoke_arn

}

resource "aws_api_gateway_method_response" "events_response_200" {
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  resource_id = aws_api_gateway_resource.events_apig_resources_objectid.id
  http_method = aws_api_gateway_method.events_apig_method.http_method
  response_models = {}
  status_code = "200"
}


resource "aws_api_gateway_integration_response" "integration_updatetags_response" {
    depends_on = [
      aws_api_gateway_integration.integration_updatetags
    ]
    rest_api_id = aws_api_gateway_rest_api.events_apig.id
  resource_id = aws_api_gateway_resource.events_apig_resources_objectid.id
  http_method = aws_api_gateway_method.events_apig_method.http_method
  status_code = aws_api_gateway_method_response.events_response_200.status_code
  response_templates = {}
}


resource "aws_api_gateway_deployment" "integration_updatetags_deploy" {
      rest_api_id = aws_api_gateway_rest_api.events_apig.id

depends_on = [
    aws_api_gateway_resource.events_apig_resources_objectid
  ]

  triggers = {
    redeployment = sha1(jsonencode([
        aws_api_gateway_resource.events_apig_resources_objectid.id,
        aws_api_gateway_method.events_apig_method.id,
        aws_api_gateway_integration.integration_updatetags.id,
    ]))
  }
    lifecycle {
    create_before_destroy = true
  }
}

resource "aws_api_gateway_stage" "events_apig_stages" {
      deployment_id = aws_api_gateway_deployment.integration_updatetags_deploy.id
  rest_api_id   = aws_api_gateway_rest_api.events_apig.id
  stage_name    = var.environment
}





# @ PATH:Update Tags
# @Consumer: ServiceNow

resource "aws_api_gateway_resource" "waf_events_apig_resources" {
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  parent_id = aws_api_gateway_resource.events_apig_resources_event.id
  path_part = "wafacl"
  # path = "/events/wafacl"
}

resource "aws_api_gateway_resource" "waf_events_apig_resources_objectid" {
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  parent_id = aws_api_gateway_resource.waf_events_apig_resources.id
  path_part = "add_ipset"
  # path = "/events/wafacl/add_ipset"
}

resource "aws_api_gateway_request_validator" "add_ipset_request_validator" {
  name = "add_ipset_request_validator"
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  validate_request_body = true
  validate_request_parameters = false
}



resource "aws_api_gateway_method" "waf_events_apig_method" {
    authorization = "AWS_IAM"
    http_method = "POST"
    resource_id = aws_api_gateway_resource.waf_events_apig_resources_objectid.id
    rest_api_id = aws_api_gateway_rest_api.events_apig.id
    # api_key_required = ""
    request_parameters = {
      "method.request.header.x-servicenow" = true
    }
    request_validator_id = aws_api_gateway_request_validator.add_ipset_request_validator.id
    # request_models = { "application/json" = "${aws_api_gateway_model.demos_event_requestbody_model.name}"}
}

resource "aws_api_gateway_integration" "waf_event_api_integration" {
    # demos_event_handler_invoke_arn
  http_method = aws_api_gateway_method.waf_events_apig_method.http_method
  resource_id = aws_api_gateway_resource.waf_events_apig_resources_objectid.id
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  integration_http_method = "POST"
  type = "AWS_PROXY"
  request_templates = {}
  uri = var.gateway_publicip_handler_invoke_arn

}

resource "aws_api_gateway_method_response" "waf_events_response_200" {
  rest_api_id = aws_api_gateway_rest_api.events_apig.id
  resource_id = aws_api_gateway_resource.waf_events_apig_resources_objectid.id
  http_method = aws_api_gateway_method.waf_events_apig_method.http_method
  response_models = {}
  status_code = "200"
}


resource "aws_api_gateway_integration_response" "waf_integration_response" {
    depends_on = [
      aws_api_gateway_integration.waf_event_api_integration
    ]
    rest_api_id = aws_api_gateway_rest_api.events_apig.id
  resource_id = aws_api_gateway_resource.waf_events_apig_resources_objectid.id
  http_method = aws_api_gateway_method.waf_events_apig_method.http_method
  status_code = aws_api_gateway_method_response.waf_events_response_200.status_code
  response_templates = {}
}


resource "aws_api_gateway_deployment" "waf_integration_deploy" {
      rest_api_id = aws_api_gateway_rest_api.events_apig.id

depends_on = [
    aws_api_gateway_resource.waf_events_apig_resources_objectid
  ]

  triggers = {
    redeployment = sha1(jsonencode([
        aws_api_gateway_resource.waf_events_apig_resources_objectid.id,
        aws_api_gateway_method.waf_events_apig_method.id,
        aws_api_gateway_integration.waf_event_api_integration.id,
    ]))
  }
    lifecycle {
    create_before_destroy = true
  }
}

resource "aws_api_gateway_stage" "events_waf_apig_stages" {
  deployment_id = aws_api_gateway_deployment.waf_integration_deploy.id
  rest_api_id   = aws_api_gateway_rest_api.events_apig.id
  stage_name    = var.environment
}
3 回答
0
已接受的回答

@alatech and @iBehr thanks for quick reply.

I think, I found the solution and it worked nicely. There is no such example in official documentation.

Here is updated deployment block. We can list as multiple methods and respective resource and integration in trigger redeployment so it can deploy the all methods at same stage.

resource "aws_api_gateway_deployment" "waf_integration_deploy" {
      rest_api_id = aws_api_gateway_rest_api.events_apig.id

depends_on = [
    aws_api_gateway_resource.waf_events_apig_resources_objectid
  ]

  triggers = {
    redeployment = sha1(jsonencode([
        aws_api_gateway_resource.resource1.id,
        aws_api_gateway_method.method1.id,
        aws_api_gateway_integration.integration1.id,
        aws_api_gateway_resource.resource2.id,
        aws_api_gateway_method.method2.id,
        aws_api_gateway_integration.integration2.id,
    ]))
  }
    lifecycle {
    create_before_destroy = true
  }
}



resource "aws_api_gateway_stage" "events_waf_apig_stages" {
  deployment_id = aws_api_gateway_deployment.waf_integration_deploy.id
  rest_api_id   = aws_api_gateway_rest_api.events_apig.id
  stage_name    = var.environment
}


已回答 1 年前
0

Looks like you are trying to create two stages with the same name.

resource "aws_api_gateway_stage" "events_apig_stages" {
  deployment_id = aws_api_gateway_deployment.integration_updatetags_deploy.id
  rest_api_id   = aws_api_gateway_rest_api.events_apig.id
  stage_name    = var.environment
}

and

resource "aws_api_gateway_stage" "events_waf_apig_stages" {
  deployment_id = aws_api_gateway_deployment.waf_integration_deploy.id
  rest_api_id   = aws_api_gateway_rest_api.events_apig.id
  stage_name    = var.environment
}

Both of these resources are creating stages with the name set to the value of var.environment. Stage names have to be unique so the second attempts fails. You should be able to remove it and just refer to aws_api_gateway_stage.events_apig_stages.id.

Hope this helps!

profile pictureAWS
专家
iBehr
已回答 1 年前
  • Hi @iBehr

    Thanks for reply. I tried with one block i.e. first block but after terraform apply when I looked at API Gateway, I do not see second method under API => Stages. I had to re-deploy API manually to same stage i.e. Dev to see both methods. I am sure, I am missing something here. Terraform documentation does not help much in this case.

0

Hi,

apart from removing the stage, can you try using the below deployment?

resource "aws_api_gateway_deployment" "my_api_gw_deployment" {
  rest_api_id = aws_api_gateway_rest_api.my_api_gw.id

  triggers = {
    redeployment = sha1(jsonencode(aws_api_gateway_rest_api.my_api_gw.body))
  }

  lifecycle {
    create_before_destroy = true
  }
}

Hope it helps ;)

profile picture
专家
已回答 1 年前

您未登录。 登录 发布回答。

一个好的回答可以清楚地解答问题和提供建设性反馈,并能促进提问者的职业发展。

回答问题的准则