diff --git a/aws/provider_test.go b/aws/provider_test.go index c98da9c9d91d..7ab6632fa66f 100644 --- a/aws/provider_test.go +++ b/aws/provider_test.go @@ -128,6 +128,26 @@ func testAccMatchResourceAttrRegionalARN(resourceName, attributeName, arnService } } +// testAccMatchResourceAttrRegionalARN ensures the Terraform state regexp matches a formatted ARN with region and no account id +func testAccMatchResourceAttrRegionalARNNoAccount(resourceName, attributeName, arnService string, arnResourceRegexp *regexp.Regexp) resource.TestCheckFunc { + return func(s *terraform.State) error { + arnRegexp := arn.ARN{ + Partition: testAccGetPartition(), + Region: testAccGetRegion(), + Resource: arnResourceRegexp.String(), + Service: arnService, + }.String() + + attributeMatch, err := regexp.Compile(arnRegexp) + + if err != nil { + return fmt.Errorf("Unable to compile ARN regexp (%s): %s", arnRegexp, err) + } + + return resource.TestMatchResourceAttr(resourceName, attributeName, attributeMatch)(s) + } +} + // testAccCheckResourceAttrGlobalARN ensures the Terraform state exactly matches a formatted ARN without region func testAccCheckResourceAttrGlobalARN(resourceName, attributeName, arnService, arnResource string) resource.TestCheckFunc { return func(s *terraform.State) error { diff --git a/aws/resource_aws_api_gateway_api_key.go b/aws/resource_aws_api_gateway_api_key.go index 8655efe4e692..574576b867fc 100644 --- a/aws/resource_aws_api_gateway_api_key.go +++ b/aws/resource_aws_api_gateway_api_key.go @@ -6,9 +6,11 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/apigateway" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) func resourceAwsApiGatewayApiKey() *schema.Resource { @@ -77,6 +79,11 @@ func resourceAwsApiGatewayApiKey() *schema.Resource { Sensitive: true, ValidateFunc: validation.StringLenBetween(30, 128), }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "tags": tagsSchema(), }, } } @@ -90,9 +97,10 @@ func resourceAwsApiGatewayApiKeyCreate(d *schema.ResourceData, meta interface{}) Description: aws.String(d.Get("description").(string)), Enabled: aws.Bool(d.Get("enabled").(bool)), Value: aws.String(d.Get("value").(string)), + Tags: keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().ApigatewayTags(), }) if err != nil { - return fmt.Errorf("Error creating API Gateway: %s", err) + return fmt.Errorf("Error creating API Gateway API Key: %s", err) } d.SetId(aws.StringValue(apiKey.Id)) @@ -118,6 +126,18 @@ func resourceAwsApiGatewayApiKeyRead(d *schema.ResourceData, meta interface{}) e return err } + if err := d.Set("tags", keyvaluetags.ApigatewayKeyValueTags(apiKey.Tags).IgnoreAws().Map()); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + + arn := arn.ARN{ + Partition: meta.(*AWSClient).partition, + Service: "apigateway", + Region: meta.(*AWSClient).region, + Resource: fmt.Sprintf("/apikeys/%s", d.Id()), + }.String() + d.Set("arn", arn) + d.Set("name", apiKey.Name) d.Set("description", apiKey.Description) d.Set("enabled", apiKey.Enabled) @@ -164,6 +184,13 @@ func resourceAwsApiGatewayApiKeyUpdate(d *schema.ResourceData, meta interface{}) log.Printf("[DEBUG] Updating API Gateway API Key: %s", d.Id()) + if d.HasChange("tags") { + o, n := d.GetChange("tags") + if err := keyvaluetags.ApigatewayUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) + } + } + _, err := conn.UpdateApiKey(&apigateway.UpdateApiKeyInput{ ApiKey: aws.String(d.Id()), PatchOperations: resourceAwsApiGatewayApiKeyUpdateOperations(d), diff --git a/aws/resource_aws_api_gateway_api_key_test.go b/aws/resource_aws_api_gateway_api_key_test.go index bf0d886d5425..1b32bf46da70 100644 --- a/aws/resource_aws_api_gateway_api_key_test.go +++ b/aws/resource_aws_api_gateway_api_key_test.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -26,6 +27,7 @@ func TestAccAWSAPIGatewayApiKey_basic(t *testing.T) { Config: testAccAWSAPIGatewayApiKeyConfig(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSAPIGatewayApiKeyExists(resourceName, &apiKey1), + testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/apikeys/+.`)), resource.TestCheckResourceAttrSet(resourceName, "created_date"), resource.TestCheckResourceAttr(resourceName, "description", "Managed by Terraform"), resource.TestCheckResourceAttr(resourceName, "enabled", "true"), @@ -43,6 +45,50 @@ func TestAccAWSAPIGatewayApiKey_basic(t *testing.T) { }) } +func TestAccAWSAPIGatewayApiKey_Tags(t *testing.T) { + var apiKey1 apigateway.ApiKey + resourceName := "aws_api_gateway_api_key.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayApiKeyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayApiKeyConfigTags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayApiKeyExists(resourceName, &apiKey1), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + Config: testAccAWSAPIGatewayApiKeyConfigTags2(rName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayApiKeyExists(resourceName, &apiKey1), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccAWSAPIGatewayApiKeyConfigTags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayApiKeyExists(resourceName, &apiKey1), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAWSAPIGatewayApiKey_Description(t *testing.T) { var apiKey1, apiKey2 apigateway.ApiKey resourceName := "aws_api_gateway_api_key.test" @@ -217,6 +263,31 @@ resource "aws_api_gateway_api_key" "test" { `, rName) } +func testAccAWSAPIGatewayApiKeyConfigTags1(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_api_gateway_api_key" "test" { + name = %[1]q + + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1) +} + +func testAccAWSAPIGatewayApiKeyConfigTags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_api_gateway_api_key" "test" { + name = %[1]q + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +} + func testAccAWSAPIGatewayApiKeyConfigDescription(rName, description string) string { return fmt.Sprintf(` resource "aws_api_gateway_api_key" "test" { diff --git a/website/docs/r/api_gateway_api_key.html.markdown b/website/docs/r/api_gateway_api_key.html.markdown index 06a338a45a6a..3281cfb3ff16 100644 --- a/website/docs/r/api_gateway_api_key.html.markdown +++ b/website/docs/r/api_gateway_api_key.html.markdown @@ -27,6 +27,7 @@ The following arguments are supported: * `description` - (Optional) The API key description. Defaults to "Managed by Terraform". * `enabled` - (Optional) Specifies whether the API key can be used by callers. Defaults to `true`. * `value` - (Optional) The value of the API key. If not specified, it will be automatically generated by AWS on creation. +* `tags` - (Optional) Key-value mapping of resource tags ## Attribute Reference @@ -36,6 +37,7 @@ In addition to all arguments above, the following attributes are exported: * `created_date` - The creation date of the API key * `last_updated_date` - The last update date of the API key * `value` - The value of the API key +* `arn` - Amazon Resource Name (ARN) ## Import