From 0bcd73ef32fd1a18424239088d998a28e8cf99a4 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Wed, 13 Jan 2021 20:54:31 -0500 Subject: [PATCH] resource/aws_api_gateway_rest_api: Additional OpenAPI specification acceptance testing and fix various attributes after import Reference: https://github.com/hashicorp/terraform-provider-aws/issues/5364 Reference: https://github.com/hashicorp/terraform-provider-aws/issues/7161 Reference: https://github.com/hashicorp/terraform-provider-aws/issues/9722 Reference: https://github.com/hashicorp/terraform-provider-aws/issues/10766 Reference: https://github.com/hashicorp/terraform-provider-aws/pull/12432 Reference: https://github.com/hashicorp/terraform-provider-aws/issues/13841 Reference: https://github.com/hashicorp/terraform-provider-aws/issues/14290 Reference: https://github.com/hashicorp/terraform-provider-aws/issues/14660 Changes: ``` * resource/aws_api_gateway_rest_api: Ensure `api_key_source`, `binary_media_types`, `description`, `minimum_compression_size`, `name`, and `policy` configuration values are correctly applied as an override after OpenAPI specification import (`body` argument) * resource/aws_api_gateway_rest_api: Allow `api_key_source`, `binary_media_types`, and `description` arguments to be omitted from configuration with OpenAPI specification import (`body` argument) ``` The overall testing changes are: * Ensuring the basic test covers all attributes * Refactoring the basic test into per-attribute testing * Adding per-attribute tests to cover OpenAPI specificiations (`body` argument) being set without Terraform configurations -- these should be allowed with Terraform showing a planned difference * Adding per-attribute tests to cover OpenAPI specificiations (`body` argument) being set with Terraform configurations -- these should be allowed with the Terraform configuration value overriding the OpenAPI specification * Removing extraneous API object `TestCheckFunc` (covered by `ImportStateVerify` testing) It is worth mentioning that this does not cover the `disable_execute_api_endpoint` or `tags` attributes that can also be specified by OpenAPI since this change set is already very large. The `minimum_compression_size` attribute also needs an additional update to support OpenAPI-only configuration. Further updates can improve on this effort. Before code updates, these new acceptance tests show how the Terraform configuration value would not be applied if an OpenAPI specification was imported: ``` === CONT TestAccAWSAPIGatewayRestApi_ApiKeySource_OverrideBody resource_aws_api_gateway_rest_api_test.go:428: Step 1/4 error: Check failed: 1 error occurred: * Check 2/2 error: aws_api_gateway_rest_api.test: Attribute 'api_key_source' expected "AUTHORIZER", got "HEADER" --- FAIL: TestAccAWSAPIGatewayRestApi_ApiKeySource_OverrideBody (8.82s) === CONT TestAccAWSAPIGatewayRestApi_BinaryMediaTypes_OverrideBody resource_aws_api_gateway_rest_api_test.go:464: Step 1/4 error: Check failed: 1 error occurred: * Check 3/3 error: aws_api_gateway_rest_api.test: Attribute 'binary_media_types.0' expected "application/octet-stream", got "image/jpeg" === CONT TestAccAWSAPIGatewayRestApi_Description_OverrideBody resource_aws_api_gateway_rest_api_test.go:527: Step 1/4 error: Check failed: 1 error occurred: * Check 2/2 error: aws_api_gateway_rest_api.test: Attribute 'description' expected "tfdescription1", got "oasdescription1" --- FAIL: TestAccAWSAPIGatewayRestApi_Description_OverrideBody (9.60s) === CONT TestAccAWSAPIGatewayRestApi_MinimumCompressionSize_OverrideBody resource_aws_api_gateway_rest_api_test.go:688: Step 1/4 error: Check failed: 1 error occurred: * Check 2/2 error: aws_api_gateway_rest_api.test: Attribute 'minimum_compression_size' expected "1", got "5242880" --- FAIL: TestAccAWSAPIGatewayRestApi_MinimumCompressionSize_OverrideBody (8.41s) === CONT TestAccAWSAPIGatewayRestApi_Name_OverrideBody resource_aws_api_gateway_rest_api_test.go:528: Step 1/4 error: Check failed: 1 error occurred: * Check 2/2 error: aws_api_gateway_rest_api.test: Attribute 'name' expected "tf-acc-test-4252368909257291928", got "title1" --- FAIL: TestAccAWSAPIGatewayRestApi_Name_OverrideBody (8.57s) === CONT TestAccAWSAPIGatewayRestApi_Policy_OverrideBody resource_aws_api_gateway_rest_api_test.go:593: Step 1/4 error: Check failed: 1 error occurred: * Check 4/4 error: aws_api_gateway_rest_api.test: Attribute 'policy' didn't match "\"Allow\"", got "" --- FAIL: TestAccAWSAPIGatewayRestApi_Policy_OverrideBody (9.37s) ``` Before code updates, these acceptance tests show how the Terraform resource would report an unexpected difference for missing configurations that were imported by the OpenAPI specification: ``` === CONT TestAccAWSAPIGatewayRestApi_ApiKeySource_SetByBody resource_aws_api_gateway_rest_api_test.go:471: Step 1/2 error: After applying this test step, the plan was not empty. stdout: An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_api_gateway_rest_api.test will be updated in-place ~ resource "aws_api_gateway_rest_api" "test" { ~ api_key_source = "AUTHORIZER" -> "HEADER" id = "5ja4mnzxta" name = "tf-acc-test-4415455482847955650" # (8 unchanged attributes hidden) # (1 unchanged block hidden) } Plan: 0 to add, 1 to change, 0 to destroy. --- FAIL: TestAccAWSAPIGatewayRestApi_ApiKeySource_SetByBody (20.65s) === CONT TestAccAWSAPIGatewayRestApi_BinaryMediaTypes_SetByBody resource_aws_api_gateway_rest_api_test.go:510: Step 1/2 error: After applying this test step, the plan was not empty. stdout: An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_api_gateway_rest_api.test will be updated in-place ~ resource "aws_api_gateway_rest_api" "test" { ~ binary_media_types = [ - "application/octet-stream", ] id = "7we4bv4s8b" name = "tf-acc-test-2053199682951305540" # (8 unchanged attributes hidden) # (1 unchanged block hidden) } Plan: 0 to add, 1 to change, 0 to destroy. === CONT TestAccAWSAPIGatewayRestApi_Description_SetByBody resource_aws_api_gateway_rest_api_test.go:570: Step 1/2 error: After applying this test step, the plan was not empty. stdout: An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_api_gateway_rest_api.test will be updated in-place ~ resource "aws_api_gateway_rest_api" "test" { - description = "oasdescription1" -> null id = "3k0fykhp76" name = "tf-acc-test-2107985362088533117" # (8 unchanged attributes hidden) # (1 unchanged block hidden) } Plan: 0 to add, 1 to change, 0 to destroy. --- FAIL: TestAccAWSAPIGatewayRestApi_Description_SetByBody (10.02s) === CONT TestAccAWSAPIGatewayRestApi_MinimumCompressionSize_SetByBody resource_aws_api_gateway_rest_api_test.go:731: Step 1/2 error: After applying this test step, the plan was not empty. stdout: An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_api_gateway_rest_api.test will be updated in-place ~ resource "aws_api_gateway_rest_api" "test" { id = "bcmvzz0jfi" ~ minimum_compression_size = 1048576 -> -1 name = "tf-acc-test-2006611344091675720" # (7 unchanged attributes hidden) # (1 unchanged block hidden) } Plan: 0 to add, 1 to change, 0 to destroy. --- FAIL: TestAccAWSAPIGatewayRestApi_MinimumCompressionSize_SetByBody (10.99s) ``` Additionally these new acceptance tests show how the Terraform resource already respected missing configurations that were imported by the OpenAPI specification: ``` --- PASS: TestAccAWSAPIGatewayRestApi_Policy_SetByBody (15.03s) ``` Output from acceptance testing: ``` --- PASS: TestAccAWSAPIGatewayRestApi_ApiKeySource (28.57s) --- PASS: TestAccAWSAPIGatewayRestApi_ApiKeySource_OverrideBody (52.53s) --- PASS: TestAccAWSAPIGatewayRestApi_ApiKeySource_SetByBody (25.48s) --- PASS: TestAccAWSAPIGatewayRestApi_basic (23.16s) --- PASS: TestAccAWSAPIGatewayRestApi_BinaryMediaTypes (80.33s) --- PASS: TestAccAWSAPIGatewayRestApi_BinaryMediaTypes_OverrideBody (34.45s) --- PASS: TestAccAWSAPIGatewayRestApi_BinaryMediaTypes_SetByBody (24.16s) --- PASS: TestAccAWSAPIGatewayRestApi_Body (26.69s) --- PASS: TestAccAWSAPIGatewayRestApi_Description (765.29s) --- PASS: TestAccAWSAPIGatewayRestApi_Description_OverrideBody (32.87s) --- PASS: TestAccAWSAPIGatewayRestApi_Description_SetByBody (51.31s) --- PASS: TestAccAWSAPIGatewayRestApi_DisableExecuteApiEndpoint (30.21s) --- PASS: TestAccAWSAPIGatewayRestApi_disappears (38.64s) --- PASS: TestAccAWSAPIGatewayRestApi_EndpointConfiguration (58.23s) --- PASS: TestAccAWSAPIGatewayRestApi_EndpointConfiguration_Private (15.02s) --- PASS: TestAccAWSAPIGatewayRestApi_EndpointConfiguration_VPCEndpoint (305.78s) --- PASS: TestAccAWSAPIGatewayRestApi_MinimumCompressionSize (42.89s) --- PASS: TestAccAWSAPIGatewayRestApi_MinimumCompressionSize_OverrideBody (35.97s) --- PASS: TestAccAWSAPIGatewayRestApi_MinimumCompressionSize_SetByBody (106.39s) --- PASS: TestAccAWSAPIGatewayRestApi_Name_OverrideBody (86.16s) --- PASS: TestAccAWSAPIGatewayRestApi_Parameters (39.90s) --- PASS: TestAccAWSAPIGatewayRestApi_Policy (683.47s) --- PASS: TestAccAWSAPIGatewayRestApi_Policy_OverrideBody (905.68s) --- PASS: TestAccAWSAPIGatewayRestApi_Policy_SetByBody (28.12s) --- PASS: TestAccAWSAPIGatewayRestApi_tags (32.94s) ``` --- aws/resource_aws_api_gateway_rest_api.go | 173 ++- aws/resource_aws_api_gateway_rest_api_test.go | 1332 ++++++++++++++--- .../docs/r/api_gateway_rest_api.html.markdown | 14 +- 3 files changed, 1260 insertions(+), 259 deletions(-) diff --git a/aws/resource_aws_api_gateway_rest_api.go b/aws/resource_aws_api_gateway_rest_api.go index 7b33b745866d..72c3f0355cb4 100644 --- a/aws/resource_aws_api_gateway_rest_api.go +++ b/aws/resource_aws_api_gateway_rest_api.go @@ -34,16 +34,14 @@ func resourceAwsApiGatewayRestApi() *schema.Resource { "description": { Type: schema.TypeString, Optional: true, + Computed: true, }, "api_key_source": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - apigateway.ApiKeySourceTypeAuthorizer, - apigateway.ApiKeySourceTypeHeader, - }, true), - Default: apigateway.ApiKeySourceTypeHeader, + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice(apigateway.ApiKeySourceType_Values(), false), }, "policy": { @@ -57,6 +55,7 @@ func resourceAwsApiGatewayRestApi() *schema.Resource { "binary_media_types": { Type: schema.TypeList, Optional: true, + Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, @@ -204,20 +203,84 @@ func resourceAwsApiGatewayRestApiCreate(d *schema.ResourceData, meta interface{} input.Parameters = stringMapToPointers(v.(map[string]interface{})) } - _, err := conn.PutRestApi(input) + output, err := conn.PutRestApi(input) if err != nil { return fmt.Errorf("error creating API Gateway specification: %s", err) } - // Due to PutRestApi removing the policy from the rest api - _, err = conn.UpdateRestApi(&apigateway.UpdateRestApiInput{ + + // Using PutRestApi with mode overwrite will remove any configuration + // that was done with CreateRestApi. Reconcile these changes by having + // any Terraform configured values overwrite imported configuration. + + updateInput := &apigateway.UpdateRestApiInput{ RestApiId: aws.String(d.Id()), - PatchOperations: resourceAwsApiGatewayRestApiUpdateOperations(d), - }) - if err != nil { - return err + PatchOperations: []*apigateway.PatchOperation{}, + } + + if v, ok := d.GetOk("api_key_source"); ok && v.(string) != aws.StringValue(output.ApiKeySource) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpReplace), + Path: aws.String("/apiKeySource"), + Value: aws.String(v.(string)), + }) + } + + if v, ok := d.GetOk("binary_media_types"); ok && len(v.([]interface{})) > 0 { + for _, elem := range aws.StringValueSlice(output.BinaryMediaTypes) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpRemove), + Path: aws.String("/binaryMediaTypes/" + escapeJsonPointer(elem)), + }) + } + + for _, elem := range v.([]interface{}) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpAdd), + Path: aws.String("/binaryMediaTypes/" + escapeJsonPointer(elem.(string))), + }) + } + } + + if v, ok := d.GetOk("description"); ok && v.(string) != aws.StringValue(output.Description) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpReplace), + Path: aws.String("/description"), + Value: aws.String(v.(string)), + }) + } + + if v := d.Get("minimum_compression_size").(int); v > -1 && int64(v) != aws.Int64Value(output.MinimumCompressionSize) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpReplace), + Path: aws.String("/minimumCompressionSize"), + Value: aws.String(strconv.Itoa(v)), + }) + } + + if v, ok := d.GetOk("name"); ok && v.(string) != aws.StringValue(output.Name) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpReplace), + Path: aws.String("/name"), + Value: aws.String(v.(string)), + }) + } + + if v, ok := d.GetOk("policy"); ok && v.(string) != aws.StringValue(output.Policy) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpReplace), + Path: aws.String("/policy"), + Value: aws.String(v.(string)), + }) + } + + if len(updateInput.PatchOperations) > 0 { + _, err := conn.UpdateRestApi(updateInput) + + if err != nil { + return fmt.Errorf("error updating REST API (%s) after OpenAPI import: %w", d.Id(), err) + } } - log.Printf("[DEBUG] Updated API Gateway policy %s", d.Id()) } return resourceAwsApiGatewayRestApiRead(d, meta) @@ -467,11 +530,86 @@ func resourceAwsApiGatewayRestApiUpdate(d *schema.ResourceData, meta interface{} input.Parameters = stringMapToPointers(v.(map[string]interface{})) } - _, err := conn.PutRestApi(input) + output, err := conn.PutRestApi(input) if err != nil { return fmt.Errorf("error updating API Gateway specification: %s", err) } + + // Using PutRestApi with mode overwrite will remove any configuration + // that was done previously. Reconcile these changes by having + // any Terraform configured values overwrite imported configuration. + + updateInput := &apigateway.UpdateRestApiInput{ + RestApiId: aws.String(d.Id()), + PatchOperations: []*apigateway.PatchOperation{}, + } + + if v, ok := d.GetOk("api_key_source"); ok && v.(string) != aws.StringValue(output.ApiKeySource) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpReplace), + Path: aws.String("/apiKeySource"), + Value: aws.String(v.(string)), + }) + } + + if v, ok := d.GetOk("binary_media_types"); ok && len(v.([]interface{})) > 0 { + for _, elem := range aws.StringValueSlice(output.BinaryMediaTypes) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpRemove), + Path: aws.String("/binaryMediaTypes/" + escapeJsonPointer(elem)), + }) + } + + for _, elem := range v.([]interface{}) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpAdd), + Path: aws.String("/binaryMediaTypes/" + escapeJsonPointer(elem.(string))), + }) + } + } + + if v, ok := d.GetOk("description"); ok && v.(string) != aws.StringValue(output.Description) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpReplace), + Path: aws.String("/description"), + Value: aws.String(v.(string)), + }) + } + + if v := d.Get("minimum_compression_size").(int); v > -1 && int64(v) != aws.Int64Value(output.MinimumCompressionSize) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpReplace), + Path: aws.String("/minimumCompressionSize"), + Value: aws.String(strconv.Itoa(v)), + }) + } + + if v, ok := d.GetOk("name"); ok && v.(string) != aws.StringValue(output.Name) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpReplace), + Path: aws.String("/name"), + Value: aws.String(v.(string)), + }) + } + + if v, ok := d.GetOk("policy"); ok && v.(string) != aws.StringValue(output.Policy) { + updateInput.PatchOperations = append(updateInput.PatchOperations, &apigateway.PatchOperation{ + Op: aws.String(apigateway.OpReplace), + Path: aws.String("/policy"), + Value: aws.String(v.(string)), + }) + } + + if len(updateInput.PatchOperations) > 0 { + _, err := conn.UpdateRestApi(updateInput) + + if err != nil { + return fmt.Errorf("error updating REST API (%s) after OpenAPI import: %w", d.Id(), err) + } + } + + return resourceAwsApiGatewayRestApiRead(d, meta) } } @@ -481,9 +619,8 @@ func resourceAwsApiGatewayRestApiUpdate(d *schema.ResourceData, meta interface{} }) if err != nil { - return err + return fmt.Errorf("error updating REST API (%s): %w", d.Id(), err) } - log.Printf("[DEBUG] Updated API Gateway %s", d.Id()) return resourceAwsApiGatewayRestApiRead(d, meta) } diff --git a/aws/resource_aws_api_gateway_rest_api_test.go b/aws/resource_aws_api_gateway_rest_api_test.go index 820cefcb3b78..b4e2a602b726 100644 --- a/aws/resource_aws_api_gateway_rest_api_test.go +++ b/aws/resource_aws_api_gateway_rest_api_test.go @@ -75,21 +75,23 @@ func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) { CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSAPIGatewayRestAPIConfig(rName), + Config: testAccAWSAPIGatewayRestAPIConfigName(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "api_key_source", "HEADER"), testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/restapis/+.`)), - testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, rName), - testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(&conf, 0), - resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.#", "0"), + resource.TestCheckNoResourceAttr(resourceName, "body"), + testAccCheckResourceAttrRfc3339(resourceName, "created_date"), resource.TestCheckResourceAttr(resourceName, "description", ""), - resource.TestCheckResourceAttr(resourceName, "api_key_source", "HEADER"), - resource.TestCheckResourceAttr(resourceName, "disable_execute_api_endpoint", `false`), - resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "0"), - resource.TestCheckResourceAttrSet(resourceName, "created_date"), - resource.TestCheckResourceAttrSet(resourceName, "execution_arn"), - resource.TestCheckNoResourceAttr(resourceName, "binary_media_types"), + resource.TestCheckResourceAttr(resourceName, "disable_execute_api_endpoint", "false"), resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.#", "1"), + testAccMatchResourceAttrRegionalARN(resourceName, "execution_arn", "execute-api", regexp.MustCompile(`[a-z0-9]+`)), + resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "-1"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "parameters.%", "0"), + resource.TestMatchResourceAttr(resourceName, "root_resource_id", regexp.MustCompile(`[a-z0-9]+`)), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), }, { @@ -99,28 +101,9 @@ func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) { }, { - Config: testAccAWSAPIGatewayRestAPIUpdateConfig(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), - testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, rName), - testAccCheckAWSAPIGatewayRestAPIDescriptionAttribute(&conf, "test"), - testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(&conf, 10485760), - resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestCheckResourceAttr(resourceName, "description", "test"), - resource.TestCheckResourceAttr(resourceName, "disable_execute_api_endpoint", `false`), - resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "10485760"), - resource.TestCheckResourceAttrSet(resourceName, "created_date"), - resource.TestCheckResourceAttrSet(resourceName, "execution_arn"), - resource.TestCheckResourceAttr(resourceName, "binary_media_types.#", "1"), - resource.TestCheckResourceAttr(resourceName, "binary_media_types.0", "application/octet-stream"), - ), - }, - - { - Config: testAccAWSAPIGatewayRestAPIDisableCompressionConfig(rName), + Config: testAccAWSAPIGatewayRestAPIConfigMinimumCompressionSize(rName, -1), Check: resource.ComposeTestCheckFunc( testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), - testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttributeIsNil(&conf), resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "-1"), ), }, @@ -188,7 +171,7 @@ func TestAccAWSAPIGatewayRestApi_disappears(t *testing.T) { CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSAPIGatewayRestAPIConfig(rName), + Config: testAccAWSAPIGatewayRestAPIConfigName(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &restApi), testAccCheckResourceDisappears(testAccProvider, resourceAwsApiGatewayRestApi(), resourceName), @@ -401,9 +384,7 @@ func TestAccAWSAPIGatewayRestApi_EndpointConfiguration_VPCEndpoint(t *testing.T) }) } -func TestAccAWSAPIGatewayRestApi_api_key_source(t *testing.T) { - expectedAPIKeySource := "HEADER" - expectedUpdateAPIKeySource := "AUTHORIZER" +func TestAccAWSAPIGatewayRestApi_ApiKeySource(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_api_gateway_rest_api.test" @@ -413,9 +394,9 @@ func TestAccAWSAPIGatewayRestApi_api_key_source(t *testing.T) { CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSAPIGatewayRestAPIConfigWithAPIKeySource(rName), + Config: testAccAWSAPIGatewayRestAPIConfigApiKeySource(rName, "AUTHORIZER"), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "api_key_source", expectedAPIKeySource), + resource.TestCheckResourceAttr(resourceName, "api_key_source", "AUTHORIZER"), ), }, { @@ -424,22 +405,23 @@ func TestAccAWSAPIGatewayRestApi_api_key_source(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSAPIGatewayRestAPIConfigWithUpdateAPIKeySource(rName), + Config: testAccAWSAPIGatewayRestAPIConfigApiKeySource(rName, "HEADER"), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "api_key_source", expectedUpdateAPIKeySource), + resource.TestCheckResourceAttr(resourceName, "api_key_source", "HEADER"), ), }, { - Config: testAccAWSAPIGatewayRestAPIConfig(rName), + Config: testAccAWSAPIGatewayRestAPIConfigName(rName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "api_key_source", expectedAPIKeySource), + resource.TestCheckResourceAttr(resourceName, "api_key_source", "HEADER"), ), }, }, }) } -func TestAccAWSAPIGatewayRestApi_disable_execute_api_endpoint(t *testing.T) { +func TestAccAWSAPIGatewayRestApi_ApiKeySource_OverrideBody(t *testing.T) { + var conf apigateway.RestApi rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_api_gateway_rest_api.test" @@ -449,37 +431,69 @@ func TestAccAWSAPIGatewayRestApi_disable_execute_api_endpoint(t *testing.T) { CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSAPIGatewayRestAPIConfig_DisableExecuteApiEndpoint(rName, false), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "disable_execute_api_endpoint", `false`), + Config: testAccAWSAPIGatewayRestAPIConfigApiKeySourceOverrideBody(rName, "AUTHORIZER", "HEADER"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "api_key_source", "AUTHORIZER"), ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, }, + // Verify updated API key source still overrides { - Config: testAccAWSAPIGatewayRestAPIConfig_DisableExecuteApiEndpoint(rName, true), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "disable_execute_api_endpoint", `true`), + Config: testAccAWSAPIGatewayRestAPIConfigApiKeySourceOverrideBody(rName, "HEADER", "HEADER"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "api_key_source", "HEADER"), ), }, + // Verify updated body API key source is still overridden { - Config: testAccAWSAPIGatewayRestAPIConfig_DisableExecuteApiEndpoint(rName, false), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "disable_execute_api_endpoint", `false`), + Config: testAccAWSAPIGatewayRestAPIConfigApiKeySourceOverrideBody(rName, "HEADER", "AUTHORIZER"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "api_key_source", "HEADER"), ), }, }, }) } -func TestAccAWSAPIGatewayRestApi_policy(t *testing.T) { +func TestAccAWSAPIGatewayRestApi_ApiKeySource_SetByBody(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_api_gateway_rest_api.test" - expectedPolicyText := `{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"*"},"Action":"execute-api:Invoke","Resource":"*","Condition":{"IpAddress":{"aws:SourceIp":"123.123.123.123/32"}}}]}` - expectedUpdatePolicyText := `{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Principal":{"AWS":"*"},"Action":"execute-api:Invoke","Resource":"*"}]}` + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigApiKeySourceSetByBody(rName, "AUTHORIZER"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "api_key_source", "AUTHORIZER"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_BinaryMediaTypes(t *testing.T) { + var conf apigateway.RestApi rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, @@ -487,27 +501,106 @@ func TestAccAWSAPIGatewayRestApi_policy(t *testing.T) { CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSAPIGatewayRestAPIConfigWithPolicy(rName), + Config: testAccAWSAPIGatewayRestAPIConfigBinaryMediaTypes1(rName, "application/octet-stream"), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "policy", expectedPolicyText), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.0", "application/octet-stream"), ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, }, { - Config: testAccAWSAPIGatewayRestAPIConfigUpdatePolicy(rName), + Config: testAccAWSAPIGatewayRestAPIConfigBinaryMediaTypes1(rName, "application/octet"), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "policy", expectedUpdatePolicyText), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.0", "application/octet"), + ), + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_BinaryMediaTypes_OverrideBody(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigBinaryMediaTypes1OverrideBody(rName, "application/octet-stream", "image/jpeg"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.0", "application/octet-stream"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, + // Verify updated minimum compression size still overrides + { + Config: testAccAWSAPIGatewayRestAPIConfigBinaryMediaTypes1OverrideBody(rName, "application/octet", "image/jpeg"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.0", "application/octet"), + ), + }, + // Verify updated body minimum compression size is still overridden + { + Config: testAccAWSAPIGatewayRestAPIConfigBinaryMediaTypes1OverrideBody(rName, "application/octet", "image/png"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.0", "application/octet"), + ), + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_BinaryMediaTypes_SetByBody(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigBinaryMediaTypes1SetByBody(rName, "application/octet-stream"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "binary_media_types.0", "application/octet-stream"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, }, }) } -func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) { +func TestAccAWSAPIGatewayRestApi_Body(t *testing.T) { var conf apigateway.RestApi rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_api_gateway_rest_api.test" @@ -517,11 +610,11 @@ func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, Steps: []resource.TestStep{ + // The body is expected to only set a title (name) and one route { - Config: testAccAWSAPIGatewayRestAPIConfigOpenAPI(rName), + Config: testAccAWSAPIGatewayRestAPIConfigBody(rName, "/test"), Check: resource.ComposeTestCheckFunc( testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), - testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, rName), testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/test"}), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "description", ""), @@ -537,10 +630,9 @@ func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) { ImportStateVerifyIgnore: []string{"body"}, }, { - Config: testAccAWSAPIGatewayRestAPIUpdateConfigOpenAPI(rName), + Config: testAccAWSAPIGatewayRestAPIConfigBody(rName, "/update"), Check: resource.ComposeTestCheckFunc( testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), - testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, rName), testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/update"}), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttrSet(resourceName, "created_date"), @@ -551,7 +643,7 @@ func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) { }) } -func TestAccAWSAPIGatewayRestApi_Parameters(t *testing.T) { +func TestAccAWSAPIGatewayRestApi_Description(t *testing.T) { var conf apigateway.RestApi rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_api_gateway_rest_api.test" @@ -562,70 +654,429 @@ func TestAccAWSAPIGatewayRestApi_Parameters(t *testing.T) { CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSAPIGatewayRestAPIConfigParameters1(rName, "basepath", "prepend"), - Check: resource.ComposeTestCheckFunc( + Config: testAccAWSAPIGatewayRestAPIConfigDescription(rName, "description1"), + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), - testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/foo", "/foo/bar", "/foo/bar/baz", "/foo/bar/baz/test"}), + resource.TestCheckResourceAttr(resourceName, "description", "description1"), ), }, { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"body", "parameters"}, + ImportStateVerifyIgnore: []string{"body"}, }, { - Config: testAccAWSAPIGatewayRestAPIConfigParameters1(rName, "basepath", "ignore"), - Check: resource.ComposeTestCheckFunc( + Config: testAccAWSAPIGatewayRestAPIConfigDescription(rName, "description2"), + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), - testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/test"}), + resource.TestCheckResourceAttr(resourceName, "description", "description2"), ), }, }, }) } -func testAccCheckAWSAPIGatewayRestAPINameAttribute(conf *apigateway.RestApi, name string) resource.TestCheckFunc { - return func(s *terraform.State) error { - if *conf.Name != name { - return fmt.Errorf("Wrong Name: %q instead of %s", *conf.Name, name) - } +func TestAccAWSAPIGatewayRestApi_Description_OverrideBody(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" - return nil - } + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigDescriptionOverrideBody(rName, "tfdescription1", "oasdescription1"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "description", "tfdescription1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, + // Verify updated description still overrides + { + Config: testAccAWSAPIGatewayRestAPIConfigDescriptionOverrideBody(rName, "tfdescription2", "oasdescription1"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "description", "tfdescription2"), + ), + }, + // Verify updated body description is still overridden + { + Config: testAccAWSAPIGatewayRestAPIConfigDescriptionOverrideBody(rName, "tfdescription2", "oasdescription2"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "description", "tfdescription2"), + ), + }, + }, + }) } -func testAccCheckAWSAPIGatewayRestAPIDescriptionAttribute(conf *apigateway.RestApi, description string) resource.TestCheckFunc { - return func(s *terraform.State) error { - if *conf.Description != description { - return fmt.Errorf("Wrong Description: %q", *conf.Description) - } +func TestAccAWSAPIGatewayRestApi_Description_SetByBody(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" - return nil - } + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigDescriptionSetByBody(rName, "oasdescription1"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "description", "oasdescription1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, + }, + }) } -func testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(conf *apigateway.RestApi, minimumCompressionSize int64) resource.TestCheckFunc { - return func(s *terraform.State) error { - if conf.MinimumCompressionSize == nil { - return fmt.Errorf("MinimumCompressionSize should not be nil") - } - if *conf.MinimumCompressionSize != minimumCompressionSize { - return fmt.Errorf("Wrong MinimumCompressionSize: %d", *conf.MinimumCompressionSize) - } +func TestAccAWSAPIGatewayRestApi_DisableExecuteApiEndpoint(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" - return nil - } + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfig_DisableExecuteApiEndpoint(rName, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "disable_execute_api_endpoint", `false`), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSAPIGatewayRestAPIConfig_DisableExecuteApiEndpoint(rName, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "disable_execute_api_endpoint", `true`), + ), + }, + { + Config: testAccAWSAPIGatewayRestAPIConfig_DisableExecuteApiEndpoint(rName, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "disable_execute_api_endpoint", `false`), + ), + }, + }, + }) } -func testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttributeIsNil(conf *apigateway.RestApi) resource.TestCheckFunc { - return func(s *terraform.State) error { - if conf.MinimumCompressionSize != nil { - return fmt.Errorf("MinimumCompressionSize should be nil: %d", *conf.MinimumCompressionSize) - } +func TestAccAWSAPIGatewayRestApi_MinimumCompressionSize(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" - return nil - } + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigMinimumCompressionSize(rName, 0), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, + { + Config: testAccAWSAPIGatewayRestAPIConfigMinimumCompressionSize(rName, -1), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "-1"), + ), + }, + { + Config: testAccAWSAPIGatewayRestAPIConfigMinimumCompressionSize(rName, 5242880), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "5242880"), + ), + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_MinimumCompressionSize_OverrideBody(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigMinimumCompressionSizeOverrideBody(rName, 1, 5242880), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, + // Verify updated minimum compression size still overrides + { + Config: testAccAWSAPIGatewayRestAPIConfigMinimumCompressionSizeOverrideBody(rName, 2, 5242880), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "2"), + ), + }, + // Verify updated body minimum compression size is still overridden + { + Config: testAccAWSAPIGatewayRestAPIConfigMinimumCompressionSizeOverrideBody(rName, 2, 1048576), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "2"), + ), + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_MinimumCompressionSize_SetByBody(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigMinimumCompressionSizeSetByBody(rName, 1048576), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "1048576"), + ), + // TODO: The attribute type must be changed to NullableTypeInt so it can be Computed properly. + ExpectNonEmptyPlan: true, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_Name_OverrideBody(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + rName2 := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigNameOverrideBody(rName, "title1"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "name", rName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, + // Verify updated name still overrides + { + Config: testAccAWSAPIGatewayRestAPIConfigNameOverrideBody(rName2, "title1"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "name", rName2), + ), + }, + // Verify updated title still overrides + { + Config: testAccAWSAPIGatewayRestAPIConfigNameOverrideBody(rName2, "title2"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, "name", rName2), + ), + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_Parameters(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigParameters1(rName, "basepath", "prepend"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/foo", "/foo/bar", "/foo/bar/baz", "/foo/bar/baz/test"}), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body", "parameters"}, + }, + { + Config: testAccAWSAPIGatewayRestAPIConfigParameters1(rName, "basepath", "ignore"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/test"}), + ), + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_Policy(t *testing.T) { + resourceName := "aws_api_gateway_rest_api.test" + expectedPolicyText := `{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"*"},"Action":"execute-api:Invoke","Resource":"*","Condition":{"IpAddress":{"aws:SourceIp":"123.123.123.123/32"}}}]}` + expectedUpdatePolicyText := `{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Principal":{"AWS":"*"},"Action":"execute-api:Invoke","Resource":"*"}]}` + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigWithPolicy(rName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "policy", expectedPolicyText), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSAPIGatewayRestAPIConfigUpdatePolicy(rName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "policy", expectedUpdatePolicyText), + ), + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_Policy_OverrideBody(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigPolicyOverrideBody(rName, "/test", "Allow"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/test"}), + resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`"Allow"`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, + // Verify updated body still has override policy + { + Config: testAccAWSAPIGatewayRestAPIConfigPolicyOverrideBody(rName, "/test2", "Allow"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/test2"}), + resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`"Allow"`)), + ), + }, + // Verify updated policy still overrides body + { + Config: testAccAWSAPIGatewayRestAPIConfigPolicyOverrideBody(rName, "/test2", "Deny"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/test2"}), + resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`"Deny"`)), + ), + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_Policy_SetByBody(t *testing.T) { + var conf apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAPIGatewayTypeEDGEPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigPolicySetByBody(rName, "Allow"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + resource.TestMatchResourceAttr(resourceName, "policy", regexp.MustCompile(`"Allow"`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"body"}, + }, + }, + }) } func testAccCheckAWSAPIGatewayRestAPIRoutes(conf *apigateway.RestApi, routes []string) resource.TestCheckFunc { @@ -721,15 +1172,6 @@ func testAccAPIGatewayTypeEDGEPreCheck(t *testing.T) { } } -func testAccAWSAPIGatewayRestAPIConfig(rName string) string { - return fmt.Sprintf(` -resource "aws_api_gateway_rest_api" "test" { - name = "%s" - minimum_compression_size = 0 -} -`, rName) -} - func testAccAWSAPIGatewayRestAPIConfig_EndpointConfiguration(rName, endpointType string) string { return fmt.Sprintf(` resource "aws_api_gateway_rest_api" "test" { @@ -927,29 +1369,10 @@ resource "aws_api_gateway_rest_api" "test" { `, rName, tagKey1, tagValue1, tagKey2, tagValue2) } -func testAccAWSAPIGatewayRestAPIConfigWithAPIKeySource(rName string) string { - return fmt.Sprintf(` -resource "aws_api_gateway_rest_api" "test" { - name = "%s" - api_key_source = "HEADER" -} -`, rName) -} - -func testAccAWSAPIGatewayRestAPIConfigWithUpdateAPIKeySource(rName string) string { - return fmt.Sprintf(` -resource "aws_api_gateway_rest_api" "test" { - name = "%s" - api_key_source = "AUTHORIZER" -} -`, rName) -} - func testAccAWSAPIGatewayRestAPIConfigWithPolicy(rName string) string { return fmt.Sprintf(` resource "aws_api_gateway_rest_api" "test" { name = "%s" - minimum_compression_size = 0 policy = <