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 Answers
0
Accepted Answer

@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
}


answered a year ago
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
EXPERT
iBehr
answered a year ago
  • 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
EXPERT
answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions