diff --git a/builtin/providers/aws/resource_aws_api_gateway_integration.go b/builtin/providers/aws/resource_aws_api_gateway_integration.go index b06982880916..f782e11ea673 100644 --- a/builtin/providers/aws/resource_aws_api_gateway_integration.go +++ b/builtin/providers/aws/resource_aws_api_gateway_integration.go @@ -11,87 +11,94 @@ import ( "github.com/aws/aws-sdk-go/service/apigateway" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" + "strings" ) func resourceAwsApiGatewayIntegration() *schema.Resource { return &schema.Resource{ Create: resourceAwsApiGatewayIntegrationCreate, Read: resourceAwsApiGatewayIntegrationRead, - Update: resourceAwsApiGatewayIntegrationCreate, + Update: resourceAwsApiGatewayIntegrationUpdate, Delete: resourceAwsApiGatewayIntegrationDelete, Schema: map[string]*schema.Schema{ - "rest_api_id": &schema.Schema{ + "rest_api_id": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "resource_id": &schema.Schema{ + "resource_id": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "http_method": &schema.Schema{ + "http_method": { Type: schema.TypeString, Required: true, ForceNew: true, ValidateFunc: validateHTTPMethod, }, - "type": &schema.Schema{ + "type": { Type: schema.TypeString, Required: true, + ForceNew: true, ValidateFunc: validateApiGatewayIntegrationType, }, - "uri": &schema.Schema{ + "uri": { Type: schema.TypeString, Optional: true, + ForceNew: true, }, - "credentials": &schema.Schema{ + "credentials": { Type: schema.TypeString, Optional: true, + ForceNew: true, }, - "integration_http_method": &schema.Schema{ + "integration_http_method": { Type: schema.TypeString, Optional: true, + ForceNew: true, ValidateFunc: validateHTTPMethod, }, - "request_templates": &schema.Schema{ + "request_templates": { Type: schema.TypeMap, Optional: true, Elem: schema.TypeString, }, - "request_parameters": &schema.Schema{ + "request_parameters": { Type: schema.TypeMap, Elem: schema.TypeString, Optional: true, ConflictsWith: []string{"request_parameters_in_json"}, }, - "request_parameters_in_json": &schema.Schema{ + "request_parameters_in_json": { Type: schema.TypeString, Optional: true, ConflictsWith: []string{"request_parameters"}, Deprecated: "Use field request_parameters instead", }, - "content_handling": &schema.Schema{ + "content_handling": { Type: schema.TypeString, Optional: true, + ForceNew: true, ValidateFunc: validateApiGatewayIntegrationContentHandling, }, - "passthrough_behavior": &schema.Schema{ + "passthrough_behavior": { Type: schema.TypeString, Optional: true, Computed: true, + ForceNew: true, ValidateFunc: validateApiGatewayIntegrationPassthroughBehavior, }, }, @@ -101,6 +108,7 @@ func resourceAwsApiGatewayIntegration() *schema.Resource { func resourceAwsApiGatewayIntegrationCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).apigateway + log.Print("[DEBUG] Creating API Gateway Integration") var integrationHttpMethod *string if v, ok := d.GetOk("integration_http_method"); ok { integrationHttpMethod = aws.String(v.(string)) @@ -163,13 +171,13 @@ func resourceAwsApiGatewayIntegrationCreate(d *schema.ResourceData, meta interfa d.SetId(fmt.Sprintf("agi-%s-%s-%s", d.Get("rest_api_id").(string), d.Get("resource_id").(string), d.Get("http_method").(string))) - return nil + return resourceAwsApiGatewayIntegrationRead(d, meta) } func resourceAwsApiGatewayIntegrationRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).apigateway - log.Printf("[DEBUG] Reading API Gateway Integration %s", d.Id()) + log.Printf("[DEBUG] Reading API Gateway Integration: %s", d.Id()) integration, err := conn.GetIntegration(&apigateway.GetIntegrationInput{ HttpMethod: aws.String(d.Get("http_method").(string)), ResourceId: aws.String(d.Get("resource_id").(string)), @@ -191,17 +199,127 @@ func resourceAwsApiGatewayIntegrationRead(d *schema.ResourceData, meta interface } d.Set("request_templates", aws.StringValueMap(integration.RequestTemplates)) - d.Set("credentials", integration.Credentials) d.Set("type", integration.Type) - d.Set("uri", integration.Uri) d.Set("request_parameters", aws.StringValueMap(integration.RequestParameters)) d.Set("request_parameters_in_json", aws.StringValueMap(integration.RequestParameters)) d.Set("passthrough_behavior", integration.PassthroughBehavior) - d.Set("content_handling", integration.ContentHandling) + + if integration.Uri != nil { + d.Set("uri", integration.Uri) + } + + if integration.Credentials != nil { + d.Set("credentials", integration.Credentials) + } + + if integration.ContentHandling != nil { + d.Set("content_handling", integration.ContentHandling) + } return nil } +func resourceAwsApiGatewayIntegrationUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).apigateway + + log.Printf("[DEBUG] Updating API Gateway Integration: %s", d.Id()) + operations := make([]*apigateway.PatchOperation, 0) + + // https://docs.aws.amazon.com/apigateway/api-reference/link-relation/integration-update/#remarks + // According to the above documentation, only a few parts are addable / removable. + if d.HasChange("request_templates") { + o, n := d.GetChange("request_templates") + prefix := "requestTemplates" + + os := o.(map[string]interface{}) + ns := n.(map[string]interface{}) + + // Handle Removal + for k := range os { + if _, ok := ns[k]; !ok { + operations = append(operations, &apigateway.PatchOperation{ + Op: aws.String("remove"), + Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), + }) + } + } + + for k, v := range ns { + // Handle replaces + if _, ok := os[k]; ok { + operations = append(operations, &apigateway.PatchOperation{ + Op: aws.String("replace"), + Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), + Value: aws.String(v.(string)), + }) + } + + // Handle additions + if _, ok := os[k]; !ok { + operations = append(operations, &apigateway.PatchOperation{ + Op: aws.String("add"), + Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), + Value: aws.String(v.(string)), + }) + } + } + } + + if d.HasChange("request_parameters") { + o, n := d.GetChange("request_parameters") + prefix := "requestParameters" + + os := o.(map[string]interface{}) + ns := n.(map[string]interface{}) + + // Handle Removal + for k := range os { + if _, ok := ns[k]; !ok { + operations = append(operations, &apigateway.PatchOperation{ + Op: aws.String("remove"), + Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), + }) + } + } + + for k, v := range ns { + // Handle replaces + if _, ok := os[k]; ok { + operations = append(operations, &apigateway.PatchOperation{ + Op: aws.String("replace"), + Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), + Value: aws.String(v.(string)), + }) + } + + // Handle additions + if _, ok := os[k]; !ok { + operations = append(operations, &apigateway.PatchOperation{ + Op: aws.String("add"), + Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), + Value: aws.String(v.(string)), + }) + } + } + } + + params := &apigateway.UpdateIntegrationInput{ + HttpMethod: aws.String(d.Get("http_method").(string)), + ResourceId: aws.String(d.Get("resource_id").(string)), + RestApiId: aws.String(d.Get("rest_api_id").(string)), + PatchOperations: operations, + } + + _, err := conn.UpdateIntegration(params) + if err != nil { + return fmt.Errorf("Error updating API Gateway Integration: %s", err) + } + + d.SetId(fmt.Sprintf("agi-%s-%s-%s", d.Get("rest_api_id").(string), d.Get("resource_id").(string), d.Get("http_method").(string))) + + return resourceAwsApiGatewayIntegrationRead(d, meta) +} + func resourceAwsApiGatewayIntegrationDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).apigateway log.Printf("[DEBUG] Deleting API Gateway Integration: %s", d.Id()) diff --git a/builtin/providers/aws/resource_aws_api_gateway_integration_test.go b/builtin/providers/aws/resource_aws_api_gateway_integration_test.go index 153ed13b4152..ff9c23387198 100644 --- a/builtin/providers/aws/resource_aws_api_gateway_integration_test.go +++ b/builtin/providers/aws/resource_aws_api_gateway_integration_test.go @@ -19,86 +19,78 @@ func TestAccAWSAPIGatewayIntegration_basic(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSAPIGatewayIntegrationDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSAPIGatewayIntegrationConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSAPIGatewayIntegrationExists("aws_api_gateway_integration.test", &conf), - testAccCheckAWSAPIGatewayIntegrationAttributes(&conf), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "type", "HTTP"), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "integration_http_method", "GET"), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "uri", "https://www.google.de"), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "request_templates.application/json", ""), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "request_templates.application/xml", "#set($inputRoot = $input.path('$'))\n{ }"), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "passthrough_behavior", "WHEN_NO_MATCH"), - resource.TestCheckNoResourceAttr( - "aws_api_gateway_integration.test", "content_handling"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "type", "HTTP"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "integration_http_method", "GET"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "uri", "https://www.google.de"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "passthrough_behavior", "WHEN_NO_MATCH"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "content_handling", "CONVERT_TO_TEXT"), + resource.TestCheckNoResourceAttr("aws_api_gateway_integration.test", "credentials"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.%", "2"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.integration.request.header.X-Authorization", "'static'"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.integration.request.header.X-Foo", "'Bar'"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.%", "2"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.application/json", ""), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.application/xml", "#set($inputRoot = $input.path('$'))\n{ }"), ), }, - resource.TestStep{ + { Config: testAccAWSAPIGatewayIntegrationConfigUpdate, Check: resource.ComposeTestCheckFunc( testAccCheckAWSAPIGatewayIntegrationExists("aws_api_gateway_integration.test", &conf), - testAccCheckAWSAPIGatewayMockIntegrationAttributes(&conf), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "type", "MOCK"), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "integration_http_method", ""), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "uri", ""), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "passthrough_behavior", "NEVER"), - resource.TestCheckResourceAttr( - "aws_api_gateway_integration.test", "content_handling", "CONVERT_TO_BINARY"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "type", "HTTP"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "integration_http_method", "GET"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "uri", "https://www.google.de"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "passthrough_behavior", "WHEN_NO_MATCH"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "content_handling", "CONVERT_TO_TEXT"), + resource.TestCheckNoResourceAttr("aws_api_gateway_integration.test", "credentials"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.%", "2"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.integration.request.header.X-Authorization", "'updated'"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.integration.request.header.X-FooBar", "'Baz'"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.%", "2"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.application/json", "{'foobar': 'bar}"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.text/html", "Foo"), ), }, - }, - }) -} -func testAccCheckAWSAPIGatewayMockIntegrationAttributes(conf *apigateway.Integration) resource.TestCheckFunc { - return func(s *terraform.State) error { - if *conf.Type != "MOCK" { - return fmt.Errorf("Wrong Type: %q", *conf.Type) - } - if *conf.RequestParameters["integration.request.header.X-Authorization"] != "'updated'" { - return fmt.Errorf("wrong updated RequestParameters for header.X-Authorization") - } - if *conf.ContentHandling != "CONVERT_TO_BINARY" { - return fmt.Errorf("wrong ContentHandling: %q", *conf.ContentHandling) - } - return nil - } -} + { + Config: testAccAWSAPIGatewayIntegrationConfigUpdateNoTemplates, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayIntegrationExists("aws_api_gateway_integration.test", &conf), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "type", "HTTP"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "integration_http_method", "GET"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "uri", "https://www.google.de"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "passthrough_behavior", "WHEN_NO_MATCH"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "content_handling", "CONVERT_TO_TEXT"), + resource.TestCheckNoResourceAttr("aws_api_gateway_integration.test", "credentials"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.%", "0"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.%", "0"), + ), + }, -func testAccCheckAWSAPIGatewayIntegrationAttributes(conf *apigateway.Integration) resource.TestCheckFunc { - return func(s *terraform.State) error { - if *conf.HttpMethod == "" { - return fmt.Errorf("empty HttpMethod") - } - if *conf.Uri != "https://www.google.de" { - return fmt.Errorf("wrong Uri") - } - if *conf.Type != "HTTP" { - return fmt.Errorf("wrong Type") - } - if conf.RequestTemplates["application/json"] != nil { - return fmt.Errorf("wrong RequestTemplate for application/json") - } - if *conf.RequestTemplates["application/xml"] != "#set($inputRoot = $input.path('$'))\n{ }" { - return fmt.Errorf("wrong RequestTemplate for application/xml") - } - if *conf.RequestParameters["integration.request.header.X-Authorization"] != "'static'" { - return fmt.Errorf("wrong RequestParameters for header.X-Authorization") - } - return nil - } + { + Config: testAccAWSAPIGatewayIntegrationConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayIntegrationExists("aws_api_gateway_integration.test", &conf), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "type", "HTTP"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "integration_http_method", "GET"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "uri", "https://www.google.de"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "passthrough_behavior", "WHEN_NO_MATCH"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "content_handling", "CONVERT_TO_TEXT"), + resource.TestCheckNoResourceAttr("aws_api_gateway_integration.test", "credentials"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.%", "2"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_parameters.integration.request.header.X-Authorization", "'static'"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.%", "2"), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.application/json", ""), + resource.TestCheckResourceAttr("aws_api_gateway_integration.test", "request_templates.application/xml", "#set($inputRoot = $input.path('$'))\n{ }"), + ), + }, + }, + }) } func testAccCheckAWSAPIGatewayIntegrationExists(n string, res *apigateway.Integration) resource.TestCheckFunc { @@ -196,13 +188,15 @@ resource "aws_api_gateway_integration" "test" { } request_parameters = { - "integration.request.header.X-Authorization" = "'static'" + "integration.request.header.X-Authorization" = "'static'" + "integration.request.header.X-Foo" = "'Bar'" } type = "HTTP" uri = "https://www.google.de" integration_http_method = "GET" passthrough_behavior = "WHEN_NO_MATCH" + content_handling = "CONVERT_TO_TEXT" } ` @@ -233,13 +227,55 @@ resource "aws_api_gateway_integration" "test" { resource_id = "${aws_api_gateway_resource.test.id}" http_method = "${aws_api_gateway_method.test.http_method}" + request_templates = { + "application/json" = "{'foobar': 'bar}" + "text/html" = "Foo" + } + request_parameters = { - "integration.request.header.X-Authorization" = "'updated'" + "integration.request.header.X-Authorization" = "'updated'" + "integration.request.header.X-FooBar" = "'Baz'" } - type = "MOCK" - passthrough_behavior = "NEVER" - content_handling = "CONVERT_TO_BINARY" + type = "HTTP" + uri = "https://www.google.de" + integration_http_method = "GET" + passthrough_behavior = "WHEN_NO_MATCH" + content_handling = "CONVERT_TO_TEXT" +} +` + +const testAccAWSAPIGatewayIntegrationConfigUpdateNoTemplates = ` +resource "aws_api_gateway_rest_api" "test" { + name = "test" +} + +resource "aws_api_gateway_resource" "test" { + rest_api_id = "${aws_api_gateway_rest_api.test.id}" + parent_id = "${aws_api_gateway_rest_api.test.root_resource_id}" + path_part = "test" +} + +resource "aws_api_gateway_method" "test" { + rest_api_id = "${aws_api_gateway_rest_api.test.id}" + resource_id = "${aws_api_gateway_resource.test.id}" + http_method = "GET" + authorization = "NONE" + request_models = { + "application/json" = "Error" + } +} + +resource "aws_api_gateway_integration" "test" { + rest_api_id = "${aws_api_gateway_rest_api.test.id}" + resource_id = "${aws_api_gateway_resource.test.id}" + http_method = "${aws_api_gateway_method.test.http_method}" + + type = "HTTP" + uri = "https://www.google.de" + integration_http_method = "GET" + passthrough_behavior = "WHEN_NO_MATCH" + content_handling = "CONVERT_TO_TEXT" } ` diff --git a/website/source/docs/providers/aws/r/api_gateway_integration.html.markdown b/website/source/docs/providers/aws/r/api_gateway_integration.html.markdown index 4281260ad365..cbb2102bb467 100644 --- a/website/source/docs/providers/aws/r/api_gateway_integration.html.markdown +++ b/website/source/docs/providers/aws/r/api_gateway_integration.html.markdown @@ -3,12 +3,12 @@ layout: "aws" page_title: "AWS: aws_api_gateway_integration" sidebar_current: "docs-aws-resource-api-gateway-integration" description: |- - Provides an HTTP Method Integration for an API Gateway Resource. + Provides an HTTP Method Integration for an API Gateway Integration. --- # aws\_api\_gateway\_integration -Provides an HTTP Method Integration for an API Gateway Resource. +Provides an HTTP Method Integration for an API Gateway Integration. ## Example Usage @@ -37,6 +37,10 @@ resource "aws_api_gateway_integration" "MyDemoIntegration" { http_method = "${aws_api_gateway_method.MyDemoMethod.http_method}" type = "MOCK" + request_parameters = { + "integration.request.header.X-Authorization" = "'static'" + } + # Transforms the incoming XML request to JSON request_templates { "application/xml" = <