From 8fc70e051929ff62be039d50e67235a239fc8ae1 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Wed, 16 May 2018 15:07:08 -0700 Subject: [PATCH] resource/aws_api_gateway_rest_api: Switch implementation from single string endpoint_type to endpoint_configuration with types list --- aws/resource_aws_api_gateway_rest_api.go | 85 +++++++++++--- aws/resource_aws_api_gateway_rest_api_test.go | 110 +++++++++++++++--- .../docs/r/api_gateway_rest_api.html.markdown | 22 +++- 3 files changed, 180 insertions(+), 37 deletions(-) diff --git a/aws/resource_aws_api_gateway_rest_api.go b/aws/resource_aws_api_gateway_rest_api.go index 83b5546113a..1788c8932bc 100644 --- a/aws/resource_aws_api_gateway_rest_api.go +++ b/aws/resource_aws_api_gateway_rest_api.go @@ -72,14 +72,30 @@ func resourceAwsApiGatewayRestApi() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "endpoint_type": { - Type: schema.TypeString, + + "endpoint_configuration": { + Type: schema.TypeList, Optional: true, - Default: apigateway.EndpointTypeEdge, - ValidateFunc: validation.StringInSlice([]string{ - apigateway.EndpointTypeEdge, - apigateway.EndpointTypeRegional, - }, false), + Computed: true, + MinItems: 1, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "types": { + Type: schema.TypeList, + Required: true, + MinItems: 1, + MaxItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + apigateway.EndpointTypeEdge, + apigateway.EndpointTypeRegional, + }, false), + }, + }, + }, + }, }, }, } @@ -97,9 +113,10 @@ func resourceAwsApiGatewayRestApiCreate(d *schema.ResourceData, meta interface{} params := &apigateway.CreateRestApiInput{ Name: aws.String(d.Get("name").(string)), Description: description, - EndpointConfiguration: &apigateway.EndpointConfiguration{ - Types: []*string{aws.String(d.Get("endpoint_type").(string))}, - }, + } + + if v, ok := d.GetOk("endpoint_configuration"); ok { + params.EndpointConfiguration = expandApiGatewayEndpointConfiguration(v.([]interface{})) } if v, ok := d.GetOk("policy"); ok && v.(string) != "" { @@ -209,6 +226,10 @@ func resourceAwsApiGatewayRestApiRead(d *schema.ResourceData, meta interface{}) log.Printf("[DEBUG] Error setting created_date: %s", err) } + if err := d.Set("endpoint_configuration", flattenApiGatewayEndpointConfiguration(api.EndpointConfiguration)); err != nil { + return fmt.Errorf("error setting endpoint_configuration: %s", err) + } + return nil } @@ -279,12 +300,18 @@ func resourceAwsApiGatewayRestApiUpdateOperations(d *schema.ResourceData) []*api } } - if d.HasChange("endpoint_type") { - operations = append(operations, &apigateway.PatchOperation{ - Op: aws.String("replace"), - Path: aws.String("/endpointConfiguration/types/0"), - Value: aws.String(d.Get("endpoint_type").(string)), - }) + if d.HasChange("endpoint_configuration.0.types") { + // The REST API must have an endpoint type. + // If attempting to remove the configuration, do nothing. + if v, ok := d.GetOk("endpoint_configuration"); ok && len(v.([]interface{})) > 0 { + m := v.([]interface{})[0].(map[string]interface{}) + + operations = append(operations, &apigateway.PatchOperation{ + Op: aws.String("replace"), + Path: aws.String("/endpointConfiguration/types/0"), + Value: aws.String(m["types"].([]interface{})[0].(string)), + }) + } } return operations @@ -340,3 +367,29 @@ func resourceAwsApiGatewayRestApiDelete(d *schema.ResourceData, meta interface{} return resource.NonRetryableError(err) }) } + +func expandApiGatewayEndpointConfiguration(l []interface{}) *apigateway.EndpointConfiguration { + if len(l) == 0 { + return nil + } + + m := l[0].(map[string]interface{}) + + endpointConfiguration := &apigateway.EndpointConfiguration{ + Types: expandStringList(m["types"].([]interface{})), + } + + return endpointConfiguration +} + +func flattenApiGatewayEndpointConfiguration(endpointConfiguration *apigateway.EndpointConfiguration) []interface{} { + if endpointConfiguration == nil { + return []interface{}{} + } + + m := map[string]interface{}{ + "types": flattenStringList(endpointConfiguration.Types), + } + + return []interface{}{m} +} diff --git a/aws/resource_aws_api_gateway_rest_api_test.go b/aws/resource_aws_api_gateway_rest_api_test.go index 3edcd89cf2b..c1882ef3f5a 100644 --- a/aws/resource_aws_api_gateway_rest_api_test.go +++ b/aws/resource_aws_api_gateway_rest_api_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/apigateway" + "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" ) @@ -94,7 +95,6 @@ func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf), testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "bar"), - testAccCheckAWSAPIGatewayRestAPIEndpointConfiguration(&conf, apigateway.EndpointTypeRegional), testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(&conf, 0), resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "bar"), resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", ""), @@ -102,6 +102,7 @@ func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) { resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"), resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "execution_arn"), resource.TestCheckNoResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types"), + resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "endpoint_configuration.#", "1"), ), }, @@ -111,7 +112,6 @@ func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) { testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf), testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"), testAccCheckAWSAPIGatewayRestAPIDescriptionAttribute(&conf, "test"), - testAccCheckAWSAPIGatewayRestAPIEndpointConfiguration(&conf, apigateway.EndpointTypeEdge), testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(&conf, 10485760), resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "test"), resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", "test"), @@ -135,6 +135,75 @@ func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) { }) } +func TestAccAWSAPIGatewayRestApi_EndpointConfiguration(t *testing.T) { + var restApi apigateway.RestApi + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfig_EndpointConfiguration(rName, "REGIONAL"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &restApi), + resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "endpoint_configuration.#", "1"), + resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "endpoint_configuration.0.types.#", "1"), + resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "endpoint_configuration.0.types.0", "REGIONAL"), + ), + }, + // For backwards compatibility, test removing endpoint_configuration, which should do nothing + { + Config: testAccAWSAPIGatewayRestAPIConfig_Name(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &restApi), + resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "endpoint_configuration.#", "1"), + resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "endpoint_configuration.0.types.#", "1"), + resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "endpoint_configuration.0.types.0", "REGIONAL"), + ), + }, + // Test updating endpoint type + { + PreConfig: func() { + // Ensure region supports EDGE endpoint + // This can eventually be moved to a PreCheck function + // If the region does not support EDGE endpoint type, this test will either show + // SKIP (if REGIONAL passed) or FAIL (if REGIONAL failed) + conn := testAccProvider.Meta().(*AWSClient).apigateway + output, err := conn.CreateRestApi(&apigateway.CreateRestApiInput{ + Name: aws.String(acctest.RandomWithPrefix("tf-acc-test-edge-endpoint-precheck")), + EndpointConfiguration: &apigateway.EndpointConfiguration{ + Types: []*string{aws.String("EDGE")}, + }, + }) + if err != nil { + if isAWSErr(err, apigateway.ErrCodeBadRequestException, "Endpoint Configuration type EDGE is not supported in this region") { + t.Skip("Region does not support EDGE endpoint type") + } + t.Fatal(err) + } + + // Be kind and rewind. :) + _, err = conn.DeleteRestApi(&apigateway.DeleteRestApiInput{ + RestApiId: output.Id, + }) + if err != nil { + t.Fatal(err) + } + }, + Config: testAccAWSAPIGatewayRestAPIConfig_EndpointConfiguration(rName, "EDGE"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &restApi), + resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "endpoint_configuration.#", "1"), + resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "endpoint_configuration.0.types.#", "1"), + resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "endpoint_configuration.0.types.0", "EDGE"), + ), + }, + }, + }) +} + func TestAccAWSAPIGatewayRestApi_policy(t *testing.T) { expectedPolicyText := `{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"*"},"Action":"execute-api:Invoke","Resource":"*"}]}` expectedUpdatePolicyText := `{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Principal":{"AWS":"*"},"Action":"execute-api:Invoke","Resource":"*"}]}` @@ -179,7 +248,6 @@ func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) { testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf), testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"), testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/test"}), - testAccCheckAWSAPIGatewayRestAPIEndpointConfiguration(&conf, apigateway.EndpointTypeEdge), resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "test"), resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", ""), resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"), @@ -194,7 +262,6 @@ func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) { testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf), testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"), testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/update"}), - testAccCheckAWSAPIGatewayRestAPIEndpointConfiguration(&conf, apigateway.EndpointTypeRegional), resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "test"), resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"), resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "execution_arn"), @@ -333,24 +400,33 @@ func testAccCheckAWSAPIGatewayRestAPIDestroy(s *terraform.State) error { return nil } -func testAccCheckAWSAPIGatewayRestAPIEndpointConfiguration(conf *apigateway.RestApi, endpointType string) resource.TestCheckFunc { - return func(s *terraform.State) error { - if *conf.EndpointConfiguration.Types[0] != endpointType { - return fmt.Errorf("Wrong endpoint type: %q", *conf.EndpointConfiguration.Types[0]) - } - - return nil - } -} - const testAccAWSAPIGatewayRestAPIConfig = ` resource "aws_api_gateway_rest_api" "test" { name = "bar" - endpoint_type = "REGIONAL" minimum_compression_size = 0 } ` +func testAccAWSAPIGatewayRestAPIConfig_EndpointConfiguration(rName, endpointType string) string { + return fmt.Sprintf(` +resource "aws_api_gateway_rest_api" "test" { + name = "%s" + + endpoint_configuration { + types = ["%s"] + } +} +`, rName, endpointType) +} + +func testAccAWSAPIGatewayRestAPIConfig_Name(rName string) string { + return fmt.Sprintf(` +resource "aws_api_gateway_rest_api" "test" { + name = "%s" +} +`, rName) +} + const testAccAWSAPIGatewayRestAPIConfigWithPolicy = ` resource "aws_api_gateway_rest_api" "test" { name = "bar" @@ -400,7 +476,6 @@ resource "aws_api_gateway_rest_api" "test" { name = "test" description = "test" binary_media_types = ["application/octet-stream"] - endpoint_type = "EDGE" minimum_compression_size = 10485760 } ` @@ -455,8 +530,7 @@ EOF const testAccAWSAPIGatewayRestAPIUpdateConfigOpenAPI = ` resource "aws_api_gateway_rest_api" "test" { - name = "test" - endpoint_type = "REGIONAL" + name = "test" body = <