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
}


답변함 일 년 전
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
답변함 일 년 전
  • 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
전문가
답변함 일 년 전

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인