diff --git a/CHANGELOG.md b/CHANGELOG.md index ffa94233870..e3a7d18a909 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,22 @@ ENHANCEMENTS: +* resource/aws_api_gateway_rest_api: Add `tags` argument and `arn` attribute [GH-10581] +* resource/aws_db_instance: Add `ca_cert_identifier` argument [GH-10490] * resource/aws_dlm_lifecycle_policy: Add `tags` argument and `arn` attribute [GH-10864] +* resource/aws_efs_file_system: Add `AFTER_7_DAYS` as a valid `lifecycle_policy` configuratio block `transition_to_ia` argument value [GH-10825] * resource/aws_glue_crawler: Add `tags` argument [GH-10805] +* resource/aws_s3_bucket_inventory: Add `IntelligentTieringAccessTier` as valid value for `optional_fields` argument [GH-10746] +* resource/aws_waf_geo_match_set: Support resource import and add `arn` attribute [GH-10480] +* resource/aws_waf_regex_match_set: Support resource import and add `arn` attribute [GH-10481] +* resource/aws_waf_regex_pattern_set: Support resource import and add `arn` attribute [GH-10482] +* resource/aws_waf_size_constraint_set: Support resource import and add `arn` attribute [GH-10484] +* resource/aws_waf_xss_match_set: Support resource import and add `arn` attribute [GH-10485] +* resource/aws_wafregional_rate_based_rule: Add `tags` argument and `arn` attribute [GH-10897] +* resource/aws_wafregional_rule_group: Add `tags` argument and `arn` attribute [GH-10896] +* resource/aws_wafregional_rule: Add `tags` argument and `arn` attribute [GH-10895] +* resource/aws_wafregional_web_acl: Add `tags` argument [GH-10889] +* resource/aws_wafregional_web_acl_association: Support resource import [GH-10538] BUG FIXES: diff --git a/aws/data_source_aws_secretsmanager_secret.go b/aws/data_source_aws_secretsmanager_secret.go index 2aa573be3a7..898191a9d8b 100644 --- a/aws/data_source_aws_secretsmanager_secret.go +++ b/aws/data_source_aws_secretsmanager_secret.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/service/secretsmanager" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/structure" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) func dataSourceAwsSecretsManagerSecret() *schema.Resource { @@ -131,7 +132,7 @@ func dataSourceAwsSecretsManagerSecretRead(d *schema.ResourceData, meta interfac return fmt.Errorf("error setting rotation_rules: %s", err) } - if err := d.Set("tags", tagsToMapSecretsManager(output.Tags)); err != nil { + if err := d.Set("tags", keyvaluetags.SecretsmanagerKeyValueTags(output.Tags).IgnoreAws().Map()); err != nil { return fmt.Errorf("error setting tags: %s", err) } diff --git a/aws/provider_test.go b/aws/provider_test.go index 9509ad85791..b7672f3db0d 100644 --- a/aws/provider_test.go +++ b/aws/provider_test.go @@ -128,7 +128,7 @@ func testAccMatchResourceAttrRegionalARN(resourceName, attributeName, arnService } } -// testAccMatchResourceAttrRegionalARN ensures the Terraform state regexp matches a formatted ARN with region and no account id +// testAccMatchResourceAttrRegionalARNNoAccount ensures the Terraform state regexp matches a formatted ARN with region but without account ID func testAccMatchResourceAttrRegionalARNNoAccount(resourceName, attributeName, arnService string, arnResourceRegexp *regexp.Regexp) resource.TestCheckFunc { return func(s *terraform.State) error { arnRegexp := arn.ARN{ @@ -161,6 +161,18 @@ func testAccCheckResourceAttrGlobalARN(resourceName, attributeName, arnService, } } +// testAccCheckResourceAttrGlobalARNNoAccount ensures the Terraform state exactly matches a formatted ARN without region or account ID +func testAccCheckResourceAttrGlobalARNNoAccount(resourceName, attributeName, arnService, arnResource string) resource.TestCheckFunc { + return func(s *terraform.State) error { + attributeValue := arn.ARN{ + Partition: testAccGetPartition(), + Resource: arnResource, + Service: arnService, + }.String() + return resource.TestCheckResourceAttr(resourceName, attributeName, attributeValue)(s) + } +} + // testAccMatchResourceAttrGlobalARN ensures the Terraform state regexp matches a formatted ARN without region func testAccMatchResourceAttrGlobalARN(resourceName, attributeName, arnService string, arnResourceRegexp *regexp.Regexp) resource.TestCheckFunc { return func(s *terraform.State) error { diff --git a/aws/resource_aws_api_gateway_rest_api.go b/aws/resource_aws_api_gateway_rest_api.go index fac0cc06d52..71923f71da5 100644 --- a/aws/resource_aws_api_gateway_rest_api.go +++ b/aws/resource_aws_api_gateway_rest_api.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) func resourceAwsApiGatewayRestApi() *schema.Resource { @@ -38,7 +39,11 @@ func resourceAwsApiGatewayRestApi() *schema.Resource { "api_key_source": { Type: schema.TypeString, Optional: true, - Default: "HEADER", + ValidateFunc: validation.StringInSlice([]string{ + apigateway.ApiKeySourceTypeAuthorizer, + apigateway.ApiKeySourceTypeHeader, + }, true), + Default: apigateway.ApiKeySourceTypeHeader, }, "policy": { @@ -105,6 +110,11 @@ func resourceAwsApiGatewayRestApi() *schema.Resource { }, }, }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "tags": tagsSchema(), }, } } @@ -135,6 +145,10 @@ func resourceAwsApiGatewayRestApiCreate(d *schema.ResourceData, meta interface{} params.Policy = aws.String(v.(string)) } + if v, ok := d.GetOk("tags"); ok { + params.Tags = keyvaluetags.New(v.(map[string]interface{})).IgnoreAws().ApigatewayTags() + } + binaryMediaTypes, binaryMediaTypesOk := d.GetOk("binary_media_types") if binaryMediaTypesOk { params.BinaryMediaTypes = expandStringList(binaryMediaTypes.([]interface{})) @@ -221,14 +235,14 @@ func resourceAwsApiGatewayRestApiRead(d *schema.ResourceData, meta interface{}) d.Set("binary_media_types", api.BinaryMediaTypes) - arn := arn.ARN{ + execution_arn := arn.ARN{ Partition: meta.(*AWSClient).partition, Service: "execute-api", Region: meta.(*AWSClient).region, AccountID: meta.(*AWSClient).accountid, Resource: d.Id(), }.String() - d.Set("execution_arn", arn) + d.Set("execution_arn", execution_arn) if api.MinimumCompressionSize == nil { d.Set("minimum_compression_size", -1) @@ -243,6 +257,18 @@ func resourceAwsApiGatewayRestApiRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("error setting endpoint_configuration: %s", err) } + if err := d.Set("tags", keyvaluetags.ApigatewayKeyValueTags(api.Tags).IgnoreAws().Map()); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + + rest_api_arn := arn.ARN{ + Partition: meta.(*AWSClient).partition, + Service: "apigateway", + Region: meta.(*AWSClient).region, + Resource: fmt.Sprintf("/restapis/%s", d.Id()), + }.String() + d.Set("arn", rest_api_arn) + return nil } @@ -342,6 +368,13 @@ func resourceAwsApiGatewayRestApiUpdate(d *schema.ResourceData, meta interface{} conn := meta.(*AWSClient).apigateway log.Printf("[DEBUG] Updating API Gateway %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) + } + } + if d.HasChange("body") { if body, ok := d.GetOk("body"); ok { log.Printf("[DEBUG] Updating API Gateway from OpenAPI spec: %s", d.Id()) diff --git a/aws/resource_aws_api_gateway_rest_api_test.go b/aws/resource_aws_api_gateway_rest_api_test.go index d576edf765c..4ea59bbcdc0 100644 --- a/aws/resource_aws_api_gateway_rest_api_test.go +++ b/aws/resource_aws_api_gateway_rest_api_test.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "regexp" "testing" "time" @@ -64,6 +65,7 @@ func testSweepAPIGatewayRestApis(region string) error { func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) { var conf apigateway.RestApi + resourceName := "aws_api_gateway_rest_api.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -73,21 +75,22 @@ func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) { { Config: testAccAWSAPIGatewayRestAPIConfig, Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/restapis/+.`)), testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "bar"), testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(&conf, 0), - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "bar"), - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", ""), - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "api_key_source", "HEADER"), - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "minimum_compression_size", "0"), - 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"), + resource.TestCheckResourceAttr(resourceName, "name", "bar"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + resource.TestCheckResourceAttr(resourceName, "api_key_source", "HEADER"), + 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, "endpoint_configuration.#", "1"), ), }, { - ResourceName: "aws_api_gateway_rest_api.test", + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, }, @@ -95,26 +98,75 @@ func TestAccAWSAPIGatewayRestApi_basic(t *testing.T) { { Config: testAccAWSAPIGatewayRestAPIUpdateConfig, Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"), testAccCheckAWSAPIGatewayRestAPIDescriptionAttribute(&conf, "test"), testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttribute(&conf, 10485760), - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "name", "test"), - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "description", "test"), - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "minimum_compression_size", "10485760"), - resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "created_date"), - resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "execution_arn"), - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types.#", "1"), - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types.0", "application/octet-stream"), + resource.TestCheckResourceAttr(resourceName, "name", "test"), + resource.TestCheckResourceAttr(resourceName, "description", "test"), + 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, Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), testAccCheckAWSAPIGatewayRestAPIMinimumCompressionSizeAttributeIsNil(&conf), - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "minimum_compression_size", "-1"), + resource.TestCheckResourceAttr(resourceName, "minimum_compression_size", "-1"), + ), + }, + }, + }) +} + +func TestAccAWSAPIGatewayRestApi_tags(t *testing.T) { + var conf apigateway.RestApi + resourceName := "aws_api_gateway_rest_api.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAPIGatewayRestAPIDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAPIGatewayRestAPIConfigTags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/restapis/+.`)), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + + { + Config: testAccAWSAPIGatewayRestAPIConfigTags2(rName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/restapis/+.`)), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + + { + Config: testAccAWSAPIGatewayRestAPIConfigTags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), + testAccMatchResourceAttrRegionalARNNoAccount(resourceName, "arn", "apigateway", regexp.MustCompile(`/restapis/+.`)), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), ), }, }, @@ -145,6 +197,7 @@ func TestAccAWSAPIGatewayRestApi_disappears(t *testing.T) { func TestAccAWSAPIGatewayRestApi_EndpointConfiguration(t *testing.T) { var restApi apigateway.RestApi rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -154,14 +207,14 @@ func TestAccAWSAPIGatewayRestApi_EndpointConfiguration(t *testing.T) { { 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"), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &restApi), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.0.types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.0.types.0", "REGIONAL"), ), }, { - ResourceName: "aws_api_gateway_rest_api.test", + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, }, @@ -169,10 +222,10 @@ func TestAccAWSAPIGatewayRestApi_EndpointConfiguration(t *testing.T) { { 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"), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &restApi), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.0.types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.0.types.0", "REGIONAL"), ), }, // Test updating endpoint type @@ -206,10 +259,10 @@ func TestAccAWSAPIGatewayRestApi_EndpointConfiguration(t *testing.T) { }, 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"), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &restApi), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.0.types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.0.types.0", "EDGE"), ), }, }, @@ -219,6 +272,7 @@ func TestAccAWSAPIGatewayRestApi_EndpointConfiguration(t *testing.T) { func TestAccAWSAPIGatewayRestApi_EndpointConfiguration_Private(t *testing.T) { var restApi apigateway.RestApi rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_api_gateway_rest_api.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -253,14 +307,14 @@ func TestAccAWSAPIGatewayRestApi_EndpointConfiguration_Private(t *testing.T) { }, Config: testAccAWSAPIGatewayRestAPIConfig_EndpointConfiguration(rName, "PRIVATE"), 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", "PRIVATE"), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &restApi), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.0.types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.0.types.0", "PRIVATE"), ), }, { - ResourceName: "aws_api_gateway_rest_api.test", + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, }, @@ -271,6 +325,8 @@ func TestAccAWSAPIGatewayRestApi_EndpointConfiguration_Private(t *testing.T) { func TestAccAWSAPIGatewayRestApi_api_key_source(t *testing.T) { expectedAPIKeySource := "HEADER" expectedUpdateAPIKeySource := "AUTHORIZER" + resourceName := "aws_api_gateway_rest_api.test" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -279,24 +335,24 @@ func TestAccAWSAPIGatewayRestApi_api_key_source(t *testing.T) { { Config: testAccAWSAPIGatewayRestAPIConfigWithAPIKeySource, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "api_key_source", expectedAPIKeySource), + resource.TestCheckResourceAttr(resourceName, "api_key_source", expectedAPIKeySource), ), }, { - ResourceName: "aws_api_gateway_rest_api.test", + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, }, { Config: testAccAWSAPIGatewayRestAPIConfigWithUpdateAPIKeySource, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "api_key_source", expectedUpdateAPIKeySource), + resource.TestCheckResourceAttr(resourceName, "api_key_source", expectedUpdateAPIKeySource), ), }, { Config: testAccAWSAPIGatewayRestAPIConfig, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "api_key_source", expectedAPIKeySource), + resource.TestCheckResourceAttr(resourceName, "api_key_source", expectedAPIKeySource), ), }, }, @@ -304,8 +360,10 @@ func TestAccAWSAPIGatewayRestApi_api_key_source(t *testing.T) { } 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":"*"}]}` + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -314,24 +372,24 @@ func TestAccAWSAPIGatewayRestApi_policy(t *testing.T) { { Config: testAccAWSAPIGatewayRestAPIConfigWithPolicy, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "policy", expectedPolicyText), + resource.TestCheckResourceAttr(resourceName, "policy", expectedPolicyText), ), }, { - ResourceName: "aws_api_gateway_rest_api.test", + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, }, { Config: testAccAWSAPIGatewayRestAPIConfigUpdatePolicy, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "policy", expectedUpdatePolicyText), + resource.TestCheckResourceAttr(resourceName, "policy", expectedUpdatePolicyText), ), }, { Config: testAccAWSAPIGatewayRestAPIConfig, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aws_api_gateway_rest_api.test", "policy", ""), + resource.TestCheckResourceAttr(resourceName, "policy", ""), ), }, }, @@ -340,6 +398,7 @@ func TestAccAWSAPIGatewayRestApi_policy(t *testing.T) { func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) { var conf apigateway.RestApi + resourceName := "aws_api_gateway_rest_api.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -349,18 +408,18 @@ func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) { { Config: testAccAWSAPIGatewayRestAPIConfigOpenAPI, Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"), testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/test"}), - 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"), - resource.TestCheckResourceAttrSet("aws_api_gateway_rest_api.test", "execution_arn"), - resource.TestCheckNoResourceAttr("aws_api_gateway_rest_api.test", "binary_media_types"), + resource.TestCheckResourceAttr(resourceName, "name", "test"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "execution_arn"), + resource.TestCheckNoResourceAttr(resourceName, "binary_media_types"), ), }, { - ResourceName: "aws_api_gateway_rest_api.test", + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"body"}, @@ -368,12 +427,12 @@ func TestAccAWSAPIGatewayRestApi_openapi(t *testing.T) { { Config: testAccAWSAPIGatewayRestAPIUpdateConfigOpenAPI, Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAPIGatewayRestAPIExists("aws_api_gateway_rest_api.test", &conf), + testAccCheckAWSAPIGatewayRestAPIExists(resourceName, &conf), testAccCheckAWSAPIGatewayRestAPINameAttribute(&conf, "test"), testAccCheckAWSAPIGatewayRestAPIRoutes(&conf, []string{"/", "/update"}), - 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"), + resource.TestCheckResourceAttr(resourceName, "name", "test"), + resource.TestCheckResourceAttrSet(resourceName, "created_date"), + resource.TestCheckResourceAttrSet(resourceName, "execution_arn"), ), }, }, @@ -550,6 +609,31 @@ resource "aws_api_gateway_rest_api" "test" { `, rName) } +func testAccAWSAPIGatewayRestAPIConfigTags1(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_api_gateway_rest_api" "test" { + name = "%s" + + tags = { + %q = %q + } +} +`, rName, tagKey1, tagValue1) +} + +func testAccAWSAPIGatewayRestAPIConfigTags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_api_gateway_rest_api" "test" { + name = "%s" + + tags = { + %q = %q + %q = %q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +} + const testAccAWSAPIGatewayRestAPIConfigWithAPIKeySource = ` resource "aws_api_gateway_rest_api" "test" { name = "bar" diff --git a/aws/resource_aws_db_instance.go b/aws/resource_aws_db_instance.go index 921f2a48374..19186e25475 100644 --- a/aws/resource_aws_db_instance.go +++ b/aws/resource_aws_db_instance.go @@ -81,6 +81,12 @@ func resourceAwsDbInstance() *schema.Resource { DiffSuppressFunc: suppressAwsDbEngineVersionDiffs, }, + "ca_cert_identifier": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "character_set_name": { Type: schema.TypeString, Optional: true, @@ -422,11 +428,6 @@ func resourceAwsDbInstance() *schema.Resource { Computed: true, }, - "ca_cert_identifier": { - Type: schema.TypeString, - Computed: true, - }, - "enabled_cloudwatch_logs_exports": { Type: schema.TypeList, Optional: true, @@ -1043,6 +1044,7 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error if _, ok := d.GetOk("username"); !ok { return fmt.Errorf(`provider.aws: aws_db_instance: %s: "username": required field is not set`, d.Get("name").(string)) } + opts := rds.CreateDBInstanceInput{ AllocatedStorage: aws.Int64(int64(d.Get("allocated_storage").(int))), DBName: aws.String(d.Get("name").(string)), @@ -1176,8 +1178,9 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error log.Printf("[DEBUG] DB Instance create configuration: %#v", opts) var err error + var createdDBInstanceOutput *rds.CreateDBInstanceOutput err = resource.Retry(5*time.Minute, func() *resource.RetryError { - _, err = conn.CreateDBInstance(&opts) + createdDBInstanceOutput, err = conn.CreateDBInstance(&opts) if err != nil { if isAWSErr(err, "InvalidParameterValue", "ENHANCED_MONITORING") { return resource.RetryableError(err) @@ -1196,6 +1199,11 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error } return fmt.Errorf("Error creating DB Instance: %s", err) } + // This is added here to avoid unnecessary modification when ca_cert_identifier is the default one + if attr, ok := d.GetOk("ca_cert_identifier"); ok && attr.(string) != aws.StringValue(createdDBInstanceOutput.DBInstance.CACertificateIdentifier) { + modifyDbInstanceInput.CACertificateIdentifier = aws.String(attr.(string)) + requiresModifyDbInstance = true + } } d.SetId(d.Get("identifier").(string)) @@ -1484,6 +1492,11 @@ func resourceAwsDbInstanceUpdate(d *schema.ResourceData, meta interface{}) error req.CopyTagsToSnapshot = aws.Bool(d.Get("copy_tags_to_snapshot").(bool)) requestUpdate = true } + if d.HasChange("ca_cert_identifier") { + d.SetPartial("ca_cert_identifier") + req.CACertificateIdentifier = aws.String(d.Get("ca_cert_identifier").(string)) + requestUpdate = true + } if d.HasChange("deletion_protection") { d.SetPartial("deletion_protection") req.DeletionProtection = aws.Bool(d.Get("deletion_protection").(bool)) diff --git a/aws/resource_aws_db_instance_test.go b/aws/resource_aws_db_instance_test.go index 0a1a6153c51..fe8374052fd 100644 --- a/aws/resource_aws_db_instance_test.go +++ b/aws/resource_aws_db_instance_test.go @@ -2583,6 +2583,35 @@ func TestAccAWSDBInstance_SnapshotIdentifier_PerformanceInsightsEnabled(t *testi }) } +func TestAccAWSDBInstance_CACertificateIdentifier(t *testing.T) { + var dbInstance rds.DBInstance + + resourceName := "aws_db_instance.bar" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSDBInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccAWSDBInstanceConfigWithCACertificateIdentifier, "rds-ca-2015"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSDBInstanceExists(resourceName, &dbInstance), + resource.TestCheckResourceAttr(resourceName, "ca_cert_identifier", "rds-ca-2015"), + ), + }, + // Ensure we are able to modify the CACertIdentifier + { + Config: fmt.Sprintf(testAccAWSDBInstanceConfigWithCACertificateIdentifier, "rds-ca-2019"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSDBInstanceExists(resourceName, &dbInstance), + resource.TestCheckResourceAttr(resourceName, "ca_cert_identifier", "rds-ca-2019"), + ), + }, + }, + }) +} + // Database names cannot collide, and deletion takes so long, that making the // name a bit random helps so able we can kill a test that's just waiting for a // delete and not be blocked on kicking off another one. @@ -2690,6 +2719,22 @@ resource "aws_db_instance" "bar" { } ` +const testAccAWSDBInstanceConfigWithCACertificateIdentifier = ` +resource "aws_db_instance" "bar" { + allocated_storage = 10 + engine = "MySQL" + instance_class = "db.t2.micro" + name = "baz" + password = "barbarbarbar" + username = "foo" + ca_cert_identifier = "%s" + apply_immediately = true + skip_final_snapshot = true + timeouts { + create = "30m" + } +}` + func testAccAWSDBInstanceConfigWithOptionGroup(rName string) string { return fmt.Sprintf(` resource "aws_db_option_group" "bar" { diff --git a/aws/resource_aws_ecs_cluster.go b/aws/resource_aws_ecs_cluster.go index 4de16d92968..c7f89963a9e 100644 --- a/aws/resource_aws_ecs_cluster.go +++ b/aws/resource_aws_ecs_cluster.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "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 resourceAwsEcsCluster() *schema.Resource { @@ -78,7 +79,7 @@ func resourceAwsEcsClusterCreate(d *schema.ResourceData, meta interface{}) error input := ecs.CreateClusterInput{ ClusterName: aws.String(clusterName), - Tags: tagsFromMapECS(d.Get("tags").(map[string]interface{})), + Tags: keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().EcsTags(), } if v, ok := d.GetOk("setting"); ok { @@ -89,9 +90,9 @@ func resourceAwsEcsClusterCreate(d *schema.ResourceData, meta interface{}) error if err != nil { return err } - log.Printf("[DEBUG] ECS cluster %s created", *out.Cluster.ClusterArn) + log.Printf("[DEBUG] ECS cluster %s created", aws.StringValue(out.Cluster.ClusterArn)) - d.SetId(*out.Cluster.ClusterArn) + d.SetId(aws.StringValue(out.Cluster.ClusterArn)) return resourceAwsEcsClusterRead(d, meta) } @@ -165,7 +166,7 @@ func resourceAwsEcsClusterRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("error setting setting: %s", err) } - if err := d.Set("tags", tagsToMapECS(cluster.Tags)); err != nil { + if err := d.Set("tags", keyvaluetags.EcsKeyValueTags(cluster.Tags).IgnoreAws().Map()); err != nil { return fmt.Errorf("error setting tags: %s", err) } @@ -188,38 +189,10 @@ func resourceAwsEcsClusterUpdate(d *schema.ResourceData, meta interface{}) error } if d.HasChange("tags") { - oldTagsRaw, newTagsRaw := d.GetChange("tags") - oldTagsMap := oldTagsRaw.(map[string]interface{}) - newTagsMap := newTagsRaw.(map[string]interface{}) - createTags, removeTags := diffTagsECS(tagsFromMapECS(oldTagsMap), tagsFromMapECS(newTagsMap)) - - if len(removeTags) > 0 { - removeTagKeys := make([]*string, len(removeTags)) - for i, removeTag := range removeTags { - removeTagKeys[i] = removeTag.Key - } - - input := &ecs.UntagResourceInput{ - ResourceArn: aws.String(d.Id()), - TagKeys: removeTagKeys, - } + o, n := d.GetChange("tags") - log.Printf("[DEBUG] Untagging ECS Cluster: %s", input) - if _, err := conn.UntagResource(input); err != nil { - return fmt.Errorf("error untagging ECS Cluster (%s): %s", d.Id(), err) - } - } - - if len(createTags) > 0 { - input := &ecs.TagResourceInput{ - ResourceArn: aws.String(d.Id()), - Tags: createTags, - } - - log.Printf("[DEBUG] Tagging ECS Cluster: %s", input) - if _, err := conn.TagResource(input); err != nil { - return fmt.Errorf("error tagging ECS Cluster (%s): %s", d.Id(), err) - } + if err := keyvaluetags.EcsUpdateTags(conn, d.Id(), o, n); err != nil { + return fmt.Errorf("error updating ECS Cluster (%s) tags: %s", d.Id(), err) } } diff --git a/aws/resource_aws_ecs_service.go b/aws/resource_aws_ecs_service.go index ae10d1f38f6..7eeb5d0861b 100644 --- a/aws/resource_aws_ecs_service.go +++ b/aws/resource_aws_ecs_service.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "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 resourceAwsEcsService() *schema.Resource { @@ -362,7 +363,7 @@ func resourceAwsEcsServiceCreate(d *schema.ResourceData, meta interface{}) error DeploymentController: expandEcsDeploymentController(d.Get("deployment_controller").([]interface{})), SchedulingStrategy: aws.String(schedulingStrategy), ServiceName: aws.String(d.Get("name").(string)), - Tags: tagsFromMapECS(d.Get("tags").(map[string]interface{})), + Tags: keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().EcsTags(), TaskDefinition: aws.String(d.Get("task_definition").(string)), EnableECSManagedTags: aws.Bool(d.Get("enable_ecs_managed_tags").(bool)), } @@ -495,8 +496,8 @@ func resourceAwsEcsServiceCreate(d *schema.ResourceData, meta interface{}) error service := *out.Service - log.Printf("[DEBUG] ECS service created: %s", *service.ServiceArn) - d.SetId(*service.ServiceArn) + log.Printf("[DEBUG] ECS service created: %s", aws.StringValue(service.ServiceArn)) + d.SetId(aws.StringValue(service.ServiceArn)) return resourceAwsEcsServiceRead(d, meta) } @@ -565,7 +566,7 @@ func resourceAwsEcsServiceRead(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] Received ECS service %s", service) - d.SetId(*service.ServiceArn) + d.SetId(aws.StringValue(service.ServiceArn)) d.Set("name", service.ServiceName) // Save task definition in the same format @@ -631,7 +632,7 @@ func resourceAwsEcsServiceRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error setting service_registries for (%s): %s", d.Id(), err) } - if err := d.Set("tags", tagsToMapECS(service.Tags)); err != nil { + if err := d.Set("tags", keyvaluetags.EcsKeyValueTags(service.Tags).IgnoreAws().Map()); err != nil { return fmt.Errorf("error setting tags: %s", err) } @@ -867,38 +868,10 @@ func resourceAwsEcsServiceUpdate(d *schema.ResourceData, meta interface{}) error } if d.HasChange("tags") { - oldTagsRaw, newTagsRaw := d.GetChange("tags") - oldTagsMap := oldTagsRaw.(map[string]interface{}) - newTagsMap := newTagsRaw.(map[string]interface{}) - createTags, removeTags := diffTagsECS(tagsFromMapECS(oldTagsMap), tagsFromMapECS(newTagsMap)) - - if len(removeTags) > 0 { - removeTagKeys := make([]*string, len(removeTags)) - for i, removeTag := range removeTags { - removeTagKeys[i] = removeTag.Key - } - - input := &ecs.UntagResourceInput{ - ResourceArn: aws.String(d.Id()), - TagKeys: removeTagKeys, - } + o, n := d.GetChange("tags") - log.Printf("[DEBUG] Untagging ECS Cluster: %s", input) - if _, err := conn.UntagResource(input); err != nil { - return fmt.Errorf("error untagging ECS Cluster (%s): %s", d.Id(), err) - } - } - - if len(createTags) > 0 { - input := &ecs.TagResourceInput{ - ResourceArn: aws.String(d.Id()), - Tags: createTags, - } - - log.Printf("[DEBUG] Tagging ECS Cluster: %s", input) - if _, err := conn.TagResource(input); err != nil { - return fmt.Errorf("error tagging ECS Cluster (%s): %s", d.Id(), err) - } + if err := keyvaluetags.EcsUpdateTags(conn, d.Id(), o, n); err != nil { + return fmt.Errorf("error updating ECS Service (%s) tags: %s", d.Id(), err) } } diff --git a/aws/resource_aws_ecs_task_definition.go b/aws/resource_aws_ecs_task_definition.go index da4dfdce311..f29925ec33e 100644 --- a/aws/resource_aws_ecs_task_definition.go +++ b/aws/resource_aws_ecs_task_definition.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) func resourceAwsEcsTaskDefinition() *schema.Resource { @@ -291,7 +292,7 @@ func resourceAwsEcsTaskDefinitionCreate(d *schema.ResourceData, meta interface{} // ClientException: Tags can not be empty. if v, ok := d.GetOk("tags"); ok { - input.Tags = tagsFromMapECS(v.(map[string]interface{})) + input.Tags = keyvaluetags.New(v.(map[string]interface{})).IgnoreAws().EcsTags() } if v, ok := d.GetOk("task_role_arn"); ok { @@ -389,9 +390,9 @@ func resourceAwsEcsTaskDefinitionCreate(d *schema.ResourceData, meta interface{} taskDefinition := *out.TaskDefinition log.Printf("[DEBUG] ECS task definition registered: %q (rev. %d)", - *taskDefinition.TaskDefinitionArn, *taskDefinition.Revision) + aws.StringValue(taskDefinition.TaskDefinitionArn), aws.Int64Value(taskDefinition.Revision)) - d.SetId(*taskDefinition.Family) + d.SetId(aws.StringValue(taskDefinition.Family)) d.Set("arn", taskDefinition.TaskDefinitionArn) return resourceAwsEcsTaskDefinitionRead(d, meta) @@ -419,7 +420,7 @@ func resourceAwsEcsTaskDefinitionRead(d *schema.ResourceData, meta interface{}) return nil } - d.SetId(*taskDefinition.Family) + d.SetId(aws.StringValue(taskDefinition.Family)) d.Set("arn", taskDefinition.TaskDefinitionArn) d.Set("family", taskDefinition.Family) d.Set("revision", taskDefinition.Revision) @@ -439,7 +440,7 @@ func resourceAwsEcsTaskDefinitionRead(d *schema.ResourceData, meta interface{}) d.Set("memory", taskDefinition.Memory) d.Set("network_mode", taskDefinition.NetworkMode) - if err := d.Set("tags", tagsToMapECS(out.Tags)); err != nil { + if err := d.Set("tags", keyvaluetags.EcsKeyValueTags(out.Tags).IgnoreAws().Map()); err != nil { return fmt.Errorf("error setting tags: %s", err) } @@ -502,38 +503,10 @@ func resourceAwsEcsTaskDefinitionUpdate(d *schema.ResourceData, meta interface{} conn := meta.(*AWSClient).ecsconn if d.HasChange("tags") { - oldTagsRaw, newTagsRaw := d.GetChange("tags") - oldTagsMap := oldTagsRaw.(map[string]interface{}) - newTagsMap := newTagsRaw.(map[string]interface{}) - createTags, removeTags := diffTagsECS(tagsFromMapECS(oldTagsMap), tagsFromMapECS(newTagsMap)) - - if len(removeTags) > 0 { - removeTagKeys := make([]*string, len(removeTags)) - for i, removeTag := range removeTags { - removeTagKeys[i] = removeTag.Key - } - - input := &ecs.UntagResourceInput{ - ResourceArn: aws.String(d.Get("arn").(string)), - TagKeys: removeTagKeys, - } + o, n := d.GetChange("tags") - log.Printf("[DEBUG] Untagging ECS Cluster: %s", input) - if _, err := conn.UntagResource(input); err != nil { - return fmt.Errorf("error untagging ECS Cluster (%s): %s", d.Get("arn").(string), err) - } - } - - if len(createTags) > 0 { - input := &ecs.TagResourceInput{ - ResourceArn: aws.String(d.Get("arn").(string)), - Tags: createTags, - } - - log.Printf("[DEBUG] Tagging ECS Cluster: %s", input) - if _, err := conn.TagResource(input); err != nil { - return fmt.Errorf("error tagging ECS Cluster (%s): %s", d.Get("arn").(string), err) - } + if err := keyvaluetags.EcsUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating ECS Task Definition (%s) tags: %s", d.Id(), err) } } diff --git a/aws/resource_aws_ecs_task_definition_test.go b/aws/resource_aws_ecs_task_definition_test.go index 7ccfeaacbf9..3093a3c9404 100644 --- a/aws/resource_aws_ecs_task_definition_test.go +++ b/aws/resource_aws_ecs_task_definition_test.go @@ -161,8 +161,6 @@ func TestAccAWSEcsTaskDefinition_withTaskScopedDockerVolume(t *testing.T) { "aws_ecs_task_definition.sleep", "volume.584193650.docker_volume_configuration.#", "1"), resource.TestCheckResourceAttr( "aws_ecs_task_definition.sleep", "volume.584193650.docker_volume_configuration.0.scope", "task"), - resource.TestCheckResourceAttr( - "aws_ecs_task_definition.sleep", "volume.584193650.docker_volume_configuration.0.driver", "local"), ), }, }, diff --git a/aws/resource_aws_efs_file_system.go b/aws/resource_aws_efs_file_system.go index 30edf28a711..c4c43cea32e 100644 --- a/aws/resource_aws_efs_file_system.go +++ b/aws/resource_aws_efs_file_system.go @@ -105,6 +105,7 @@ func resourceAwsEfsFileSystem() *schema.Resource { Type: schema.TypeString, Optional: true, ValidateFunc: validation.StringInSlice([]string{ + efs.TransitionToIARulesAfter7Days, efs.TransitionToIARulesAfter14Days, efs.TransitionToIARulesAfter30Days, efs.TransitionToIARulesAfter60Days, diff --git a/aws/resource_aws_s3_bucket_inventory.go b/aws/resource_aws_s3_bucket_inventory.go index 79f2201a30f..f503e3ff0f7 100644 --- a/aws/resource_aws_s3_bucket_inventory.go +++ b/aws/resource_aws_s3_bucket_inventory.go @@ -82,8 +82,9 @@ func resourceAwsS3BucketInventory() *schema.Resource { ValidateFunc: validateArn, }, "account_id": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateAwsAccountId, }, "prefix": { Type: schema.TypeString, @@ -172,6 +173,7 @@ func resourceAwsS3BucketInventory() *schema.Resource { s3.InventoryOptionalFieldObjectLockMode, s3.InventoryOptionalFieldObjectLockRetainUntilDate, s3.InventoryOptionalFieldObjectLockLegalHoldStatus, + s3.InventoryOptionalFieldIntelligentTieringAccessTier, }, false), }, Set: schema.HashString, diff --git a/aws/resource_aws_s3_bucket_inventory_test.go b/aws/resource_aws_s3_bucket_inventory_test.go index 0add90ae6bb..960a0e67e1d 100644 --- a/aws/resource_aws_s3_bucket_inventory_test.go +++ b/aws/resource_aws_s3_bucket_inventory_test.go @@ -44,8 +44,8 @@ func TestAccAWSS3BucketInventory_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "destination.#", "1"), resource.TestCheckResourceAttr(resourceName, "destination.0.bucket.#", "1"), - resource.TestCheckResourceAttr(resourceName, "destination.0.bucket.0.bucket_arn", "arn:aws:s3:::"+bucketName), - resource.TestCheckResourceAttrSet(resourceName, "destination.0.bucket.0.account_id"), + testAccCheckResourceAttrGlobalARNNoAccount(resourceName, "destination.0.bucket.0.bucket_arn", "s3", bucketName), + testAccCheckResourceAttrAccountID(resourceName, "destination.0.bucket.0.account_id"), resource.TestCheckResourceAttr(resourceName, "destination.0.bucket.0.format", "ORC"), resource.TestCheckResourceAttr(resourceName, "destination.0.bucket.0.prefix", "inventory"), ), @@ -191,21 +191,20 @@ func testAccCheckAWSS3BucketInventoryDestroy(s *terraform.State) error { func testAccAWSS3BucketInventoryConfigBucket(name string) string { return fmt.Sprintf(` -resource "aws_s3_bucket" "bucket" { - bucket = "%s" +resource "aws_s3_bucket" "test" { + bucket = %[1]q acl = "private" } `, name) } func testAccAWSS3BucketInventoryConfig(bucketName, inventoryName string) string { - return fmt.Sprintf(` -%s + return testAccAWSS3BucketInventoryConfigBucket(bucketName) + fmt.Sprintf(` data "aws_caller_identity" "current" {} resource "aws_s3_bucket_inventory" "test" { - bucket = "${aws_s3_bucket.bucket.id}" - name = "%s" + bucket = "${aws_s3_bucket.test.id}" + name = %[1]q included_object_versions = "All" @@ -225,21 +224,20 @@ resource "aws_s3_bucket_inventory" "test" { destination { bucket { format = "ORC" - bucket_arn = "${aws_s3_bucket.bucket.arn}" + bucket_arn = "${aws_s3_bucket.test.arn}" account_id = "${data.aws_caller_identity.current.account_id}" prefix = "inventory" } } } -`, testAccAWSS3BucketInventoryConfigBucket(bucketName), inventoryName) +`, inventoryName) } func testAccAWSS3BucketInventoryConfigEncryptWithSSES3(bucketName, inventoryName string) string { - return fmt.Sprintf(` -%s + return testAccAWSS3BucketInventoryConfigBucket(bucketName) + fmt.Sprintf(` resource "aws_s3_bucket_inventory" "test" { - bucket = "${aws_s3_bucket.bucket.id}" - name = "%s" + bucket = "${aws_s3_bucket.test.id}" + name = %[1]q included_object_versions = "Current" @@ -250,7 +248,7 @@ resource "aws_s3_bucket_inventory" "test" { destination { bucket { format = "CSV" - bucket_arn = "${aws_s3_bucket.bucket.arn}" + bucket_arn = "${aws_s3_bucket.test.arn}" encryption { sse_s3 {} @@ -258,20 +256,19 @@ resource "aws_s3_bucket_inventory" "test" { } } } -`, testAccAWSS3BucketInventoryConfigBucket(bucketName), inventoryName) +`, inventoryName) } func testAccAWSS3BucketInventoryConfigEncryptWithSSEKMS(bucketName, inventoryName string) string { - return fmt.Sprintf(` -%s -resource "aws_kms_key" "inventory" { - description = "Terraform acc test S3 inventory SSE-KMS encryption: %s" + return testAccAWSS3BucketInventoryConfigBucket(bucketName) + fmt.Sprintf(` +resource "aws_kms_key" "test" { + description = "Terraform acc test S3 inventory SSE-KMS encryption: %[1]s" deletion_window_in_days = 7 } resource "aws_s3_bucket_inventory" "test" { - bucket = "${aws_s3_bucket.bucket.id}" - name = "%s" + bucket = "${aws_s3_bucket.test.id}" + name = %[2]q included_object_versions = "Current" @@ -282,15 +279,15 @@ resource "aws_s3_bucket_inventory" "test" { destination { bucket { format = "Parquet" - bucket_arn = "${aws_s3_bucket.bucket.arn}" + bucket_arn = "${aws_s3_bucket.test.arn}" encryption { sse_kms { - key_id = "${aws_kms_key.inventory.arn}" + key_id = "${aws_kms_key.test.arn}" } } } } } -`, testAccAWSS3BucketInventoryConfigBucket(bucketName), bucketName, inventoryName) +`, bucketName, inventoryName) } diff --git a/aws/resource_aws_secretsmanager_secret.go b/aws/resource_aws_secretsmanager_secret.go index d6ce9b179cd..7395059f16e 100644 --- a/aws/resource_aws_secretsmanager_secret.go +++ b/aws/resource_aws_secretsmanager_secret.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) func resourceAwsSecretsManagerSecret() *schema.Resource { @@ -118,8 +119,7 @@ func resourceAwsSecretsManagerSecretCreate(d *schema.ResourceData, meta interfac } if v, ok := d.GetOk("tags"); ok { - input.Tags = tagsFromMapSecretsManager(v.(map[string]interface{})) - log.Printf("[DEBUG] Tagging Secrets Manager Secret: %s", input.Tags) + input.Tags = keyvaluetags.New(v.(map[string]interface{})).IgnoreAws().SecretsmanagerTags() } if v, ok := d.GetOk("kms_key_id"); ok && v.(string) != "" { @@ -248,7 +248,7 @@ func resourceAwsSecretsManagerSecretRead(d *schema.ResourceData, meta interface{ d.Set("rotation_rules", []interface{}{}) } - if err := d.Set("tags", tagsToMapSecretsManager(output.Tags)); err != nil { + if err := d.Set("tags", keyvaluetags.SecretsmanagerKeyValueTags(output.Tags).IgnoreAws().Map()); err != nil { return fmt.Errorf("error setting tags: %s", err) } @@ -344,35 +344,9 @@ func resourceAwsSecretsManagerSecretUpdate(d *schema.ResourceData, meta interfac } if d.HasChange("tags") { - oraw, nraw := d.GetChange("tags") - o := oraw.(map[string]interface{}) - n := nraw.(map[string]interface{}) - create, remove := diffTagsSecretsManager(tagsFromMapSecretsManager(o), tagsFromMapSecretsManager(n)) - - if len(remove) > 0 { - log.Printf("[DEBUG] Removing Secrets Manager Secret %q tags: %#v", d.Id(), remove) - k := make([]*string, len(remove)) - for i, t := range remove { - k[i] = t.Key - } - - _, err := conn.UntagResource(&secretsmanager.UntagResourceInput{ - SecretId: aws.String(d.Id()), - TagKeys: k, - }) - if err != nil { - return fmt.Errorf("error updating Secrets Manager Secrets %q tags: %s", d.Id(), err) - } - } - if len(create) > 0 { - log.Printf("[DEBUG] Creating Secrets Manager Secret %q tags: %#v", d.Id(), create) - _, err := conn.TagResource(&secretsmanager.TagResourceInput{ - SecretId: aws.String(d.Id()), - Tags: create, - }) - if err != nil { - return fmt.Errorf("error updating Secrets Manager Secrets %q tags: %s", d.Id(), err) - } + o, n := d.GetChange("tags") + if err := keyvaluetags.SecretsmanagerUpdateTags(conn, d.Id(), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) } } diff --git a/aws/resource_aws_sfn_activity.go b/aws/resource_aws_sfn_activity.go index 7f01931d292..3eb5afb5a2d 100644 --- a/aws/resource_aws_sfn_activity.go +++ b/aws/resource_aws_sfn_activity.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "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 resourceAwsSfnActivity() *schema.Resource { @@ -46,7 +47,7 @@ func resourceAwsSfnActivityCreate(d *schema.ResourceData, meta interface{}) erro params := &sfn.CreateActivityInput{ Name: aws.String(d.Get("name").(string)), - Tags: tagsFromMapSfn(d.Get("tags").(map[string]interface{})), + Tags: keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().SfnTags(), } activity, err := conn.CreateActivity(params) @@ -63,38 +64,9 @@ func resourceAwsSfnActivityUpdate(d *schema.ResourceData, meta interface{}) erro conn := meta.(*AWSClient).sfnconn if d.HasChange("tags") { - oldTagsRaw, newTagsRaw := d.GetChange("tags") - oldTagsMap := oldTagsRaw.(map[string]interface{}) - newTagsMap := newTagsRaw.(map[string]interface{}) - createTags, removeTags := diffTagsSfn(tagsFromMapSfn(oldTagsMap), tagsFromMapSfn(newTagsMap)) - - if len(removeTags) > 0 { - removeTagKeys := make([]*string, len(removeTags)) - for i, removeTag := range removeTags { - removeTagKeys[i] = removeTag.Key - } - - input := &sfn.UntagResourceInput{ - ResourceArn: aws.String(d.Id()), - TagKeys: removeTagKeys, - } - - log.Printf("[DEBUG] Untagging State Function Activity: %s", input) - if _, err := conn.UntagResource(input); err != nil { - return fmt.Errorf("error untagging State Function Activity (%s): %s", d.Id(), err) - } - } - - if len(createTags) > 0 { - input := &sfn.TagResourceInput{ - ResourceArn: aws.String(d.Id()), - Tags: createTags, - } - - log.Printf("[DEBUG] Tagging State Function Activity: %s", input) - if _, err := conn.TagResource(input); err != nil { - return fmt.Errorf("error tagging State Function Activity (%s): %s", d.Id(), err) - } + o, n := d.GetChange("tags") + if err := keyvaluetags.SfnUpdateTags(conn, d.Id(), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) } } @@ -122,17 +94,13 @@ func resourceAwsSfnActivityRead(d *schema.ResourceData, meta interface{}) error log.Printf("[DEBUG] Error setting creation_date: %s", err) } - tagsResp, err := conn.ListTagsForResource( - &sfn.ListTagsForResourceInput{ - ResourceArn: aws.String(d.Id()), - }, - ) + tags, err := keyvaluetags.SfnListTags(conn, d.Id()) if err != nil { - return fmt.Errorf("error listing SFN Activity (%s) tags: %s", d.Id(), err) + return fmt.Errorf("error listing tags for SFN Activity (%s): %s", d.Id(), err) } - if err := d.Set("tags", tagsToMapSfn(tagsResp.Tags)); err != nil { + if err := d.Set("tags", tags.IgnoreAws().Map()); err != nil { return fmt.Errorf("error setting tags: %s", err) } diff --git a/aws/resource_aws_sfn_state_machine.go b/aws/resource_aws_sfn_state_machine.go index 1d735651982..bbeb5ed6e34 100644 --- a/aws/resource_aws_sfn_state_machine.go +++ b/aws/resource_aws_sfn_state_machine.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "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 resourceAwsSfnStateMachine() *schema.Resource { @@ -65,7 +66,7 @@ func resourceAwsSfnStateMachineCreate(d *schema.ResourceData, meta interface{}) Definition: aws.String(d.Get("definition").(string)), Name: aws.String(d.Get("name").(string)), RoleArn: aws.String(d.Get("role_arn").(string)), - Tags: tagsFromMapSfn(d.Get("tags").(map[string]interface{})), + Tags: keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().SfnTags(), } var activity *sfn.CreateStateMachineOutput @@ -127,23 +128,13 @@ func resourceAwsSfnStateMachineRead(d *schema.ResourceData, meta interface{}) er log.Printf("[DEBUG] Error setting creation_date: %s", err) } - tags := map[string]string{} - - tagsResp, err := conn.ListTagsForResource( - &sfn.ListTagsForResourceInput{ - ResourceArn: aws.String(d.Id()), - }, - ) + tags, err := keyvaluetags.SfnListTags(conn, d.Id()) if err != nil && !isAWSErr(err, "UnknownOperationException", "") { - return fmt.Errorf("error listing SFN Activity (%s) tags: %s", d.Id(), err) - } - - if tagsResp != nil { - tags = tagsToMapSfn(tagsResp.Tags) + return fmt.Errorf("error listing tags for SFN State Machine (%s): %s", d.Id(), err) } - if err := d.Set("tags", tags); err != nil { + if err := d.Set("tags", tags.IgnoreAws().Map()); err != nil { return fmt.Errorf("error setting tags: %s", err) } @@ -171,40 +162,12 @@ func resourceAwsSfnStateMachineUpdate(d *schema.ResourceData, meta interface{}) } if d.HasChange("tags") { - oldTagsRaw, newTagsRaw := d.GetChange("tags") - oldTagsMap := oldTagsRaw.(map[string]interface{}) - newTagsMap := newTagsRaw.(map[string]interface{}) - createTags, removeTags := diffTagsSfn(tagsFromMapSfn(oldTagsMap), tagsFromMapSfn(newTagsMap)) - - if len(removeTags) > 0 { - removeTagKeys := make([]*string, len(removeTags)) - for i, removeTag := range removeTags { - removeTagKeys[i] = removeTag.Key - } - - input := &sfn.UntagResourceInput{ - ResourceArn: aws.String(d.Id()), - TagKeys: removeTagKeys, - } - - log.Printf("[DEBUG] Untagging State Function: %s", input) - if _, err := conn.UntagResource(input); err != nil { - return fmt.Errorf("error untagging State Function (%s): %s", d.Id(), err) - } - } - - if len(createTags) > 0 { - input := &sfn.TagResourceInput{ - ResourceArn: aws.String(d.Id()), - Tags: createTags, - } - - log.Printf("[DEBUG] Tagging State Function: %s", input) - if _, err := conn.TagResource(input); err != nil { - return fmt.Errorf("error tagging State Function (%s): %s", d.Id(), err) - } + o, n := d.GetChange("tags") + if err := keyvaluetags.SfnUpdateTags(conn, d.Id(), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) } } + return resourceAwsSfnStateMachineRead(d, meta) } diff --git a/aws/resource_aws_sns_topic.go b/aws/resource_aws_sns_topic.go index a3f593d6e18..271aafad90b 100644 --- a/aws/resource_aws_sns_topic.go +++ b/aws/resource_aws_sns_topic.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) // Mutable attributes @@ -151,7 +152,7 @@ func resourceAwsSnsTopic() *schema.Resource { func resourceAwsSnsTopicCreate(d *schema.ResourceData, meta interface{}) error { snsconn := meta.(*AWSClient).snsconn - tags := tagsFromMapSNS(d.Get("tags").(map[string]interface{})) + tags := keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().SnsTags() var name string if v, ok := d.GetOk("name"); ok { name = v.(string) @@ -174,7 +175,18 @@ func resourceAwsSnsTopicCreate(d *schema.ResourceData, meta interface{}) error { } d.SetId(*output.TopicArn) - return resourceAwsSnsTopicUpdate(d, meta) + + for terraformAttrName, snsAttrName := range SNSAttributeMap { + if d.HasChange(terraformAttrName) { + _, terraformAttrValue := d.GetChange(terraformAttrName) + err := updateAwsSnsTopicAttribute(d.Id(), snsAttrName, terraformAttrValue, snsconn) + if err != nil { + return err + } + } + } + + return resourceAwsSnsTopicRead(d, meta) } func resourceAwsSnsTopicUpdate(d *schema.ResourceData, meta interface{}) error { @@ -189,9 +201,11 @@ func resourceAwsSnsTopicUpdate(d *schema.ResourceData, meta interface{}) error { } } } - if !d.IsNewResource() { - if err := setTagsSNS(conn, d); err != nil { - return fmt.Errorf("error updating SNS Topic tags for %s: %s", d.Id(), err) + + if d.HasChange("tags") { + o, n := d.GetChange("tags") + if err := keyvaluetags.SnsUpdateTags(conn, d.Id(), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) } } @@ -237,15 +251,13 @@ func resourceAwsSnsTopicRead(d *schema.ResourceData, meta interface{}) error { } } - // List tags + tags, err := keyvaluetags.SnsListTags(snsconn, d.Id()) - tagList, err := snsconn.ListTagsForResource(&sns.ListTagsForResourceInput{ - ResourceArn: aws.String(d.Id()), - }) if err != nil { - return fmt.Errorf("error listing SNS Topic tags for %s: %s", d.Id(), err) + return fmt.Errorf("error listing tags for resource (%s): %s", d.Id(), err) } - if err := d.Set("tags", tagsToMapSNS(tagList.Tags)); err != nil { + + if err := d.Set("tags", tags.IgnoreAws().Map()); err != nil { return fmt.Errorf("error setting tags: %s", err) } diff --git a/aws/resource_aws_transfer_server.go b/aws/resource_aws_transfer_server.go index f2db50b259d..eea94fb1571 100644 --- a/aws/resource_aws_transfer_server.go +++ b/aws/resource_aws_transfer_server.go @@ -8,10 +8,10 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/transfer" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "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 resourceAwsTransferServer() *schema.Resource { @@ -110,7 +110,7 @@ func resourceAwsTransferServer() *schema.Resource { func resourceAwsTransferServerCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).transferconn - tags := tagsFromMapTransfer(d.Get("tags").(map[string]interface{})) + tags := keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().TransferTags() createOpts := &transfer.CreateServerInput{} if len(tags) != 0 { @@ -192,7 +192,7 @@ func resourceAwsTransferServerRead(d *schema.ResourceData, meta interface{}) err d.Set("identity_provider_type", resp.Server.IdentityProviderType) d.Set("logging_role", resp.Server.LoggingRole) - if err := d.Set("tags", tagsToMapTransfer(resp.Server.Tags)); err != nil { + if err := d.Set("tags", keyvaluetags.TransferKeyValueTags(resp.Server.Tags).IgnoreAws().Map()); err != nil { return fmt.Errorf("Error setting tags: %s", err) } return nil @@ -249,8 +249,11 @@ func resourceAwsTransferServerUpdate(d *schema.ResourceData, meta interface{}) e } } - if err := setTagsTransfer(conn, d); err != nil { - return fmt.Errorf("Error update tags: %s", err) + if d.HasChange("tags") { + o, n := d.GetChange("tags") + if err := keyvaluetags.TransferUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) + } } return resourceAwsTransferServerRead(d, meta) diff --git a/aws/resource_aws_transfer_user.go b/aws/resource_aws_transfer_user.go index cd9df67f417..4747829b4e1 100644 --- a/aws/resource_aws_transfer_user.go +++ b/aws/resource_aws_transfer_user.go @@ -8,10 +8,10 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/transfer" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "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 resourceAwsTransferUser() *schema.Resource { @@ -89,7 +89,7 @@ func resourceAwsTransferUserCreate(d *schema.ResourceData, meta interface{}) err } if attr, ok := d.GetOk("tags"); ok { - createOpts.Tags = tagsFromMapTransfer(attr.(map[string]interface{})) + createOpts.Tags = keyvaluetags.New(attr.(map[string]interface{})).IgnoreAws().TransferTags() } log.Printf("[DEBUG] Create Transfer User Option: %#v", createOpts) @@ -135,7 +135,7 @@ func resourceAwsTransferUserRead(d *schema.ResourceData, meta interface{}) error d.Set("policy", resp.User.Policy) d.Set("role", resp.User.Role) - if err := d.Set("tags", tagsToMapTransfer(resp.User.Tags)); err != nil { + if err := d.Set("tags", keyvaluetags.TransferKeyValueTags(resp.User.Tags).IgnoreAws().Map()); err != nil { return fmt.Errorf("Error setting tags: %s", err) } return nil @@ -181,8 +181,11 @@ func resourceAwsTransferUserUpdate(d *schema.ResourceData, meta interface{}) err } } - if err := setTagsTransfer(conn, d); err != nil { - return fmt.Errorf("Error update tags: %s", err) + if d.HasChange("tags") { + o, n := d.GetChange("tags") + if err := keyvaluetags.TransferUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) + } } return resourceAwsTransferUserRead(d, meta) diff --git a/aws/resource_aws_waf_geo_match_set.go b/aws/resource_aws_waf_geo_match_set.go index 86933b6eae8..6c99f9bad5f 100644 --- a/aws/resource_aws_waf_geo_match_set.go +++ b/aws/resource_aws_waf_geo_match_set.go @@ -5,6 +5,7 @@ import ( "log" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/waf" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -15,6 +16,9 @@ func resourceAwsWafGeoMatchSet() *schema.Resource { Read: resourceAwsWafGeoMatchSetRead, Update: resourceAwsWafGeoMatchSetUpdate, Delete: resourceAwsWafGeoMatchSetDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: map[string]*schema.Schema{ "name": { @@ -22,6 +26,10 @@ func resourceAwsWafGeoMatchSet() *schema.Resource { Required: true, ForceNew: true, }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, "geo_match_constraint": { Type: schema.TypeSet, Optional: true, @@ -75,9 +83,7 @@ func resourceAwsWafGeoMatchSetRead(d *schema.ResourceData, meta interface{}) err resp, err := conn.GetGeoMatchSet(params) if err != nil { - // TODO: Replace with constant once it's available - // See https://github.com/aws/aws-sdk-go/issues/1856 - if isAWSErr(err, "WAFNonexistentItemException", "") { + if isAWSErr(err, waf.ErrCodeNonexistentItemException, "") { log.Printf("[WARN] WAF GeoMatchSet (%s) not found, removing from state", d.Id()) d.SetId("") return nil @@ -89,6 +95,14 @@ func resourceAwsWafGeoMatchSetRead(d *schema.ResourceData, meta interface{}) err d.Set("name", resp.GeoMatchSet.Name) d.Set("geo_match_constraint", flattenWafGeoMatchConstraint(resp.GeoMatchSet.GeoMatchConstraints)) + arn := arn.ARN{ + Partition: meta.(*AWSClient).partition, + Service: "waf", + AccountID: meta.(*AWSClient).accountid, + Resource: fmt.Sprintf("geomatchset/%s", d.Id()), + } + d.Set("arn", arn.String()) + return nil } diff --git a/aws/resource_aws_waf_geo_match_set_test.go b/aws/resource_aws_waf_geo_match_set_test.go index fd04c14fa98..c48ef971bfa 100644 --- a/aws/resource_aws_waf_geo_match_set_test.go +++ b/aws/resource_aws_waf_geo_match_set_test.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -15,6 +16,7 @@ import ( func TestAccAWSWafGeoMatchSet_basic(t *testing.T) { var v waf.GeoMatchSet geoMatchSet := fmt.Sprintf("geoMatchSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_geo_match_set.geo_match_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -24,21 +26,21 @@ func TestAccAWSWafGeoMatchSet_basic(t *testing.T) { { Config: testAccAWSWafGeoMatchSetConfig(geoMatchSet), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafGeoMatchSetExists("aws_waf_geo_match_set.geo_match_set", &v), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "name", geoMatchSet), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.#", "2"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.384465307.type", "Country"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.384465307.value", "US"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.1991628426.type", "Country"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.1991628426.value", "CA"), + testAccCheckAWSWafGeoMatchSetExists(resourceName, &v), + testAccMatchResourceAttrGlobalARN(resourceName, "arn", "waf", regexp.MustCompile(`geomatchset/.+`)), + resource.TestCheckResourceAttr(resourceName, "name", geoMatchSet), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.#", "2"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.384465307.type", "Country"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.384465307.value", "US"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.1991628426.type", "Country"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.1991628426.value", "CA"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -47,6 +49,7 @@ func TestAccAWSWafGeoMatchSet_changeNameForceNew(t *testing.T) { var before, after waf.GeoMatchSet geoMatchSet := fmt.Sprintf("geoMatchSet-%s", acctest.RandString(5)) geoMatchSetNewName := fmt.Sprintf("geoMatchSetNewName-%s", acctest.RandString(5)) + resourceName := "aws_waf_geo_match_set.geo_match_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -56,23 +59,24 @@ func TestAccAWSWafGeoMatchSet_changeNameForceNew(t *testing.T) { { Config: testAccAWSWafGeoMatchSetConfig(geoMatchSet), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafGeoMatchSetExists("aws_waf_geo_match_set.geo_match_set", &before), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "name", geoMatchSet), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.#", "2"), + testAccCheckAWSWafGeoMatchSetExists(resourceName, &before), + resource.TestCheckResourceAttr(resourceName, "name", geoMatchSet), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.#", "2"), ), }, { Config: testAccAWSWafGeoMatchSetConfigChangeName(geoMatchSetNewName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafGeoMatchSetExists("aws_waf_geo_match_set.geo_match_set", &after), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "name", geoMatchSetNewName), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.#", "2"), + testAccCheckAWSWafGeoMatchSetExists(resourceName, &after), + resource.TestCheckResourceAttr(resourceName, "name", geoMatchSetNewName), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.#", "2"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -80,6 +84,7 @@ func TestAccAWSWafGeoMatchSet_changeNameForceNew(t *testing.T) { func TestAccAWSWafGeoMatchSet_disappears(t *testing.T) { var v waf.GeoMatchSet geoMatchSet := fmt.Sprintf("geoMatchSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_geo_match_set.geo_match_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -89,7 +94,7 @@ func TestAccAWSWafGeoMatchSet_disappears(t *testing.T) { { Config: testAccAWSWafGeoMatchSetConfig(geoMatchSet), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafGeoMatchSetExists("aws_waf_geo_match_set.geo_match_set", &v), + testAccCheckAWSWafGeoMatchSetExists(resourceName, &v), testAccCheckAWSWafGeoMatchSetDisappears(&v), ), ExpectNonEmptyPlan: true, @@ -101,6 +106,7 @@ func TestAccAWSWafGeoMatchSet_disappears(t *testing.T) { func TestAccAWSWafGeoMatchSet_changeConstraints(t *testing.T) { var before, after waf.GeoMatchSet setName := fmt.Sprintf("geoMatchSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_geo_match_set.geo_match_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -110,39 +116,32 @@ func TestAccAWSWafGeoMatchSet_changeConstraints(t *testing.T) { { Config: testAccAWSWafGeoMatchSetConfig(setName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafGeoMatchSetExists("aws_waf_geo_match_set.geo_match_set", &before), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "name", setName), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.#", "2"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.384465307.type", "Country"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.384465307.value", "US"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.1991628426.type", "Country"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.1991628426.value", "CA"), + testAccCheckAWSWafGeoMatchSetExists(resourceName, &before), + resource.TestCheckResourceAttr(resourceName, "name", setName), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.#", "2"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.384465307.type", "Country"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.384465307.value", "US"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.1991628426.type", "Country"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.1991628426.value", "CA"), ), }, { Config: testAccAWSWafGeoMatchSetConfig_changeConstraints(setName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafGeoMatchSetExists("aws_waf_geo_match_set.geo_match_set", &after), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "name", setName), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.#", "2"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.1174390936.type", "Country"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.1174390936.value", "RU"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.4046309957.type", "Country"), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.4046309957.value", "CN"), + testAccCheckAWSWafGeoMatchSetExists(resourceName, &after), + resource.TestCheckResourceAttr(resourceName, "name", setName), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.#", "2"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.1174390936.type", "Country"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.1174390936.value", "RU"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.4046309957.type", "Country"), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.4046309957.value", "CN"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -150,6 +149,7 @@ func TestAccAWSWafGeoMatchSet_changeConstraints(t *testing.T) { func TestAccAWSWafGeoMatchSet_noConstraints(t *testing.T) { var ipset waf.GeoMatchSet setName := fmt.Sprintf("geoMatchSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_geo_match_set.geo_match_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -159,13 +159,16 @@ func TestAccAWSWafGeoMatchSet_noConstraints(t *testing.T) { { Config: testAccAWSWafGeoMatchSetConfig_noConstraints(setName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafGeoMatchSetExists("aws_waf_geo_match_set.geo_match_set", &ipset), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "name", setName), - resource.TestCheckResourceAttr( - "aws_waf_geo_match_set.geo_match_set", "geo_match_constraint.#", "0"), + testAccCheckAWSWafGeoMatchSetExists(resourceName, &ipset), + resource.TestCheckResourceAttr(resourceName, "name", setName), + resource.TestCheckResourceAttr(resourceName, "geo_match_constraint.#", "0"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -259,7 +262,7 @@ func testAccCheckAWSWafGeoMatchSetDestroy(s *terraform.State) error { } // Return nil if the GeoMatchSet is already destroyed - if isAWSErr(err, "WAFNonexistentItemException", "") { + if isAWSErr(err, waf.ErrCodeNonexistentItemException, "") { return nil } diff --git a/aws/resource_aws_waf_regex_match_set.go b/aws/resource_aws_waf_regex_match_set.go index 0806319f867..af8ef7ff054 100644 --- a/aws/resource_aws_waf_regex_match_set.go +++ b/aws/resource_aws_waf_regex_match_set.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/waf" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -16,6 +17,9 @@ func resourceAwsWafRegexMatchSet() *schema.Resource { Read: resourceAwsWafRegexMatchSetRead, Update: resourceAwsWafRegexMatchSetUpdate, Delete: resourceAwsWafRegexMatchSetDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: map[string]*schema.Schema{ "name": { @@ -23,6 +27,10 @@ func resourceAwsWafRegexMatchSet() *schema.Resource { Required: true, ForceNew: true, }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, "regex_match_tuple": { Type: schema.TypeSet, Optional: true, @@ -96,7 +104,7 @@ func resourceAwsWafRegexMatchSetRead(d *schema.ResourceData, meta interface{}) e resp, err := conn.GetRegexMatchSet(params) if err != nil { - if isAWSErr(err, "WAFNonexistentItemException", "") { + if isAWSErr(err, waf.ErrCodeNonexistentItemException, "") { log.Printf("[WARN] WAF Regex Match Set (%s) not found, removing from state", d.Id()) d.SetId("") return nil @@ -108,6 +116,14 @@ func resourceAwsWafRegexMatchSetRead(d *schema.ResourceData, meta interface{}) e d.Set("name", resp.RegexMatchSet.Name) d.Set("regex_match_tuple", flattenWafRegexMatchTuples(resp.RegexMatchSet.RegexMatchTuples)) + arn := arn.ARN{ + Partition: meta.(*AWSClient).partition, + Service: "waf", + AccountID: meta.(*AWSClient).accountid, + Resource: fmt.Sprintf("regexmatchset/%s", d.Id()), + } + d.Set("arn", arn.String()) + return nil } diff --git a/aws/resource_aws_waf_regex_match_set_test.go b/aws/resource_aws_waf_regex_match_set_test.go index d4ecb252104..e5ccc50ae32 100644 --- a/aws/resource_aws_waf_regex_match_set_test.go +++ b/aws/resource_aws_waf_regex_match_set_test.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -99,6 +100,7 @@ func testAccAWSWafRegexMatchSet_basic(t *testing.T) { matchSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) patternSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) + resourceName := "aws_waf_regex_match_set.test" fieldToMatch := waf.FieldToMatch{ Data: aws.String("User-Agent"), @@ -113,17 +115,23 @@ func testAccAWSWafRegexMatchSet_basic(t *testing.T) { { Config: testAccAWSWafRegexMatchSetConfig(matchSetName, patternSetName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafRegexMatchSetExists("aws_waf_regex_match_set.test", &matchSet), + testAccCheckAWSWafRegexMatchSetExists(resourceName, &matchSet), testAccCheckAWSWafRegexPatternSetExists("aws_waf_regex_pattern_set.test", &patternSet), + testAccMatchResourceAttrGlobalARN(resourceName, "arn", "waf", regexp.MustCompile(`regexmatchset/.+`)), computeWafRegexMatchSetTuple(&patternSet, &fieldToMatch, "NONE", &idx), - resource.TestCheckResourceAttr("aws_waf_regex_match_set.test", "name", matchSetName), - resource.TestCheckResourceAttr("aws_waf_regex_match_set.test", "regex_match_tuple.#", "1"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.field_to_match.#", &idx, "1"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.field_to_match.0.data", &idx, "user-agent"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.field_to_match.0.type", &idx, "HEADER"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.text_transformation", &idx, "NONE"), + resource.TestCheckResourceAttr(resourceName, "name", matchSetName), + resource.TestCheckResourceAttr(resourceName, "regex_match_tuple.#", "1"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.field_to_match.#", &idx, "1"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.field_to_match.0.data", &idx, "user-agent"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.field_to_match.0.type", &idx, "HEADER"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.text_transformation", &idx, "NONE"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -135,6 +143,7 @@ func testAccAWSWafRegexMatchSet_changePatterns(t *testing.T) { matchSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) patternSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) + resourceName := "aws_waf_regex_match_set.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -144,31 +153,36 @@ func testAccAWSWafRegexMatchSet_changePatterns(t *testing.T) { { Config: testAccAWSWafRegexMatchSetConfig(matchSetName, patternSetName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafRegexMatchSetExists("aws_waf_regex_match_set.test", &before), + testAccCheckAWSWafRegexMatchSetExists(resourceName, &before), testAccCheckAWSWafRegexPatternSetExists("aws_waf_regex_pattern_set.test", &patternSet), computeWafRegexMatchSetTuple(&patternSet, &waf.FieldToMatch{Data: aws.String("User-Agent"), Type: aws.String("HEADER")}, "NONE", &idx1), - resource.TestCheckResourceAttr("aws_waf_regex_match_set.test", "name", matchSetName), - resource.TestCheckResourceAttr("aws_waf_regex_match_set.test", "regex_match_tuple.#", "1"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.field_to_match.#", &idx1, "1"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.field_to_match.0.data", &idx1, "user-agent"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.field_to_match.0.type", &idx1, "HEADER"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.text_transformation", &idx1, "NONE"), + resource.TestCheckResourceAttr(resourceName, "name", matchSetName), + resource.TestCheckResourceAttr(resourceName, "regex_match_tuple.#", "1"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.field_to_match.#", &idx1, "1"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.field_to_match.0.data", &idx1, "user-agent"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.field_to_match.0.type", &idx1, "HEADER"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.text_transformation", &idx1, "NONE"), ), }, { Config: testAccAWSWafRegexMatchSetConfig_changePatterns(matchSetName, patternSetName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafRegexMatchSetExists("aws_waf_regex_match_set.test", &after), - resource.TestCheckResourceAttr("aws_waf_regex_match_set.test", "name", matchSetName), - resource.TestCheckResourceAttr("aws_waf_regex_match_set.test", "regex_match_tuple.#", "1"), + testAccCheckAWSWafRegexMatchSetExists(resourceName, &after), + resource.TestCheckResourceAttr(resourceName, "name", matchSetName), + resource.TestCheckResourceAttr(resourceName, "regex_match_tuple.#", "1"), computeWafRegexMatchSetTuple(&patternSet, &waf.FieldToMatch{Data: aws.String("Referer"), Type: aws.String("HEADER")}, "COMPRESS_WHITE_SPACE", &idx2), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.field_to_match.#", &idx2, "1"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.field_to_match.0.data", &idx2, "referer"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.field_to_match.0.type", &idx2, "HEADER"), - testCheckResourceAttrWithIndexesAddr("aws_waf_regex_match_set.test", "regex_match_tuple.%d.text_transformation", &idx2, "COMPRESS_WHITE_SPACE"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.field_to_match.#", &idx2, "1"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.field_to_match.0.data", &idx2, "referer"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.field_to_match.0.type", &idx2, "HEADER"), + testCheckResourceAttrWithIndexesAddr(resourceName, "regex_match_tuple.%d.text_transformation", &idx2, "COMPRESS_WHITE_SPACE"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -176,6 +190,7 @@ func testAccAWSWafRegexMatchSet_changePatterns(t *testing.T) { func testAccAWSWafRegexMatchSet_noPatterns(t *testing.T) { var matchSet waf.RegexMatchSet matchSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) + resourceName := "aws_waf_regex_match_set.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -185,11 +200,16 @@ func testAccAWSWafRegexMatchSet_noPatterns(t *testing.T) { { Config: testAccAWSWafRegexMatchSetConfig_noPatterns(matchSetName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafRegexMatchSetExists("aws_waf_regex_match_set.test", &matchSet), - resource.TestCheckResourceAttr("aws_waf_regex_match_set.test", "name", matchSetName), - resource.TestCheckResourceAttr("aws_waf_regex_match_set.test", "regex_match_tuple.#", "0"), + testAccCheckAWSWafRegexMatchSetExists(resourceName, &matchSet), + resource.TestCheckResourceAttr(resourceName, "name", matchSetName), + resource.TestCheckResourceAttr(resourceName, "regex_match_tuple.#", "0"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -198,6 +218,7 @@ func testAccAWSWafRegexMatchSet_disappears(t *testing.T) { var matchSet waf.RegexMatchSet matchSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) patternSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) + resourceName := "aws_waf_regex_match_set.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -207,7 +228,7 @@ func testAccAWSWafRegexMatchSet_disappears(t *testing.T) { { Config: testAccAWSWafRegexMatchSetConfig(matchSetName, patternSetName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafRegexMatchSetExists("aws_waf_regex_match_set.test", &matchSet), + testAccCheckAWSWafRegexMatchSetExists(resourceName, &matchSet), testAccCheckAWSWafRegexMatchSetDisappears(&matchSet), ), ExpectNonEmptyPlan: true, @@ -316,7 +337,7 @@ func testAccCheckAWSWafRegexMatchSetDestroy(s *terraform.State) error { } // Return nil if the Regex Pattern Set is already destroyed - if isAWSErr(err, "WAFNonexistentItemException", "") { + if isAWSErr(err, waf.ErrCodeNonexistentItemException, "") { return nil } diff --git a/aws/resource_aws_waf_regex_pattern_set.go b/aws/resource_aws_waf_regex_pattern_set.go index e7e247eaccf..0767255f221 100644 --- a/aws/resource_aws_waf_regex_pattern_set.go +++ b/aws/resource_aws_waf_regex_pattern_set.go @@ -5,6 +5,7 @@ import ( "log" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/waf" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -15,6 +16,9 @@ func resourceAwsWafRegexPatternSet() *schema.Resource { Read: resourceAwsWafRegexPatternSetRead, Update: resourceAwsWafRegexPatternSetUpdate, Delete: resourceAwsWafRegexPatternSetDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: map[string]*schema.Schema{ "name": { @@ -22,6 +26,10 @@ func resourceAwsWafRegexPatternSet() *schema.Resource { Required: true, ForceNew: true, }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, "regex_pattern_strings": { Type: schema.TypeSet, Optional: true, @@ -63,9 +71,7 @@ func resourceAwsWafRegexPatternSetRead(d *schema.ResourceData, meta interface{}) resp, err := conn.GetRegexPatternSet(params) if err != nil { - // TODO: Replace with a constant once available - // See https://github.com/aws/aws-sdk-go/issues/1856 - if isAWSErr(err, "WAFNonexistentItemException", "") { + if isAWSErr(err, waf.ErrCodeNonexistentItemException, "") { log.Printf("[WARN] WAF Regex Pattern Set (%s) not found, removing from state", d.Id()) d.SetId("") return nil @@ -77,6 +83,14 @@ func resourceAwsWafRegexPatternSetRead(d *schema.ResourceData, meta interface{}) d.Set("name", resp.RegexPatternSet.Name) d.Set("regex_pattern_strings", aws.StringValueSlice(resp.RegexPatternSet.RegexPatternStrings)) + arn := arn.ARN{ + Partition: meta.(*AWSClient).partition, + Service: "waf", + AccountID: meta.(*AWSClient).accountid, + Resource: fmt.Sprintf("regexpatternset/%s", d.Id()), + } + d.Set("arn", arn.String()) + return nil } diff --git a/aws/resource_aws_waf_regex_pattern_set_test.go b/aws/resource_aws_waf_regex_pattern_set_test.go index 8be45a0332d..d8214b62c56 100644 --- a/aws/resource_aws_waf_regex_pattern_set_test.go +++ b/aws/resource_aws_waf_regex_pattern_set_test.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -32,6 +33,7 @@ func TestAccAWSWafRegexPatternSet(t *testing.T) { func testAccAWSWafRegexPatternSet_basic(t *testing.T) { var v waf.RegexPatternSet patternSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) + resourceName := "aws_waf_regex_pattern_set.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -41,13 +43,19 @@ func testAccAWSWafRegexPatternSet_basic(t *testing.T) { { Config: testAccAWSWafRegexPatternSetConfig(patternSetName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafRegexPatternSetExists("aws_waf_regex_pattern_set.test", &v), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "name", patternSetName), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.#", "2"), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.2848565413", "one"), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.3351840846", "two"), + testAccCheckAWSWafRegexPatternSetExists(resourceName, &v), + testAccMatchResourceAttrGlobalARN(resourceName, "arn", "waf", regexp.MustCompile(`regexpatternset/.+`)), + resource.TestCheckResourceAttr(resourceName, "name", patternSetName), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.#", "2"), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.2848565413", "one"), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.3351840846", "two"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -55,6 +63,7 @@ func testAccAWSWafRegexPatternSet_basic(t *testing.T) { func testAccAWSWafRegexPatternSet_changePatterns(t *testing.T) { var before, after waf.RegexPatternSet patternSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) + resourceName := "aws_waf_regex_pattern_set.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -64,24 +73,29 @@ func testAccAWSWafRegexPatternSet_changePatterns(t *testing.T) { { Config: testAccAWSWafRegexPatternSetConfig(patternSetName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafRegexPatternSetExists("aws_waf_regex_pattern_set.test", &before), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "name", patternSetName), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.#", "2"), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.2848565413", "one"), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.3351840846", "two"), + testAccCheckAWSWafRegexPatternSetExists(resourceName, &before), + resource.TestCheckResourceAttr(resourceName, "name", patternSetName), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.#", "2"), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.2848565413", "one"), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.3351840846", "two"), ), }, { Config: testAccAWSWafRegexPatternSetConfig_changePatterns(patternSetName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafRegexPatternSetExists("aws_waf_regex_pattern_set.test", &after), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "name", patternSetName), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.#", "3"), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.3351840846", "two"), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.2929247714", "three"), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.1294846542", "four"), + testAccCheckAWSWafRegexPatternSetExists(resourceName, &after), + resource.TestCheckResourceAttr(resourceName, "name", patternSetName), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.#", "3"), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.3351840846", "two"), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.2929247714", "three"), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.1294846542", "four"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -89,6 +103,7 @@ func testAccAWSWafRegexPatternSet_changePatterns(t *testing.T) { func testAccAWSWafRegexPatternSet_noPatterns(t *testing.T) { var patternSet waf.RegexPatternSet patternSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) + resourceName := "aws_waf_regex_pattern_set.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -98,11 +113,16 @@ func testAccAWSWafRegexPatternSet_noPatterns(t *testing.T) { { Config: testAccAWSWafRegexPatternSetConfig_noPatterns(patternSetName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafRegexPatternSetExists("aws_waf_regex_pattern_set.test", &patternSet), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "name", patternSetName), - resource.TestCheckResourceAttr("aws_waf_regex_pattern_set.test", "regex_pattern_strings.#", "0"), + testAccCheckAWSWafRegexPatternSetExists(resourceName, &patternSet), + resource.TestCheckResourceAttr(resourceName, "name", patternSetName), + resource.TestCheckResourceAttr(resourceName, "regex_pattern_strings.#", "0"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -110,6 +130,7 @@ func testAccAWSWafRegexPatternSet_noPatterns(t *testing.T) { func testAccAWSWafRegexPatternSet_disappears(t *testing.T) { var v waf.RegexPatternSet patternSetName := fmt.Sprintf("tfacc-%s", acctest.RandString(5)) + resourceName := "aws_waf_regex_pattern_set.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -119,7 +140,7 @@ func testAccAWSWafRegexPatternSet_disappears(t *testing.T) { { Config: testAccAWSWafRegexPatternSetConfig(patternSetName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafRegexPatternSetExists("aws_waf_regex_pattern_set.test", &v), + testAccCheckAWSWafRegexPatternSetExists(resourceName, &v), testAccCheckAWSWafRegexPatternSetDisappears(&v), ), ExpectNonEmptyPlan: true, @@ -215,7 +236,7 @@ func testAccCheckAWSWafRegexPatternSetDestroy(s *terraform.State) error { } // Return nil if the Regex Pattern Set is already destroyed - if isAWSErr(err, "WAFNonexistentItemException", "") { + if isAWSErr(err, waf.ErrCodeNonexistentItemException, "") { return nil } diff --git a/aws/resource_aws_waf_size_constraint_set.go b/aws/resource_aws_waf_size_constraint_set.go index deb78c7a965..f14ee9ddb52 100644 --- a/aws/resource_aws_waf_size_constraint_set.go +++ b/aws/resource_aws_waf_size_constraint_set.go @@ -5,6 +5,7 @@ import ( "log" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/waf" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -16,6 +17,9 @@ func resourceAwsWafSizeConstraintSet() *schema.Resource { Read: resourceAwsWafSizeConstraintSetRead, Update: resourceAwsWafSizeConstraintSetUpdate, Delete: resourceAwsWafSizeConstraintSetDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: wafSizeConstraintSetSchema(), } @@ -54,7 +58,7 @@ func resourceAwsWafSizeConstraintSetRead(d *schema.ResourceData, meta interface{ resp, err := conn.GetSizeConstraintSet(params) if err != nil { - if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "WAFNonexistentItemException" { + if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == waf.ErrCodeNonexistentItemException { log.Printf("[WARN] WAF SizeConstraintSet (%s) not found, removing from state", d.Id()) d.SetId("") return nil @@ -66,6 +70,14 @@ func resourceAwsWafSizeConstraintSetRead(d *schema.ResourceData, meta interface{ d.Set("name", resp.SizeConstraintSet.Name) d.Set("size_constraints", flattenWafSizeConstraints(resp.SizeConstraintSet.SizeConstraints)) + arn := arn.ARN{ + Partition: meta.(*AWSClient).partition, + Service: "waf", + AccountID: meta.(*AWSClient).accountid, + Resource: fmt.Sprintf("sizeconstraintset/%s", d.Id()), + } + d.Set("arn", arn.String()) + return nil } diff --git a/aws/resource_aws_waf_size_constraint_set_test.go b/aws/resource_aws_waf_size_constraint_set_test.go index 374793a5185..a506cc44d87 100644 --- a/aws/resource_aws_waf_size_constraint_set_test.go +++ b/aws/resource_aws_waf_size_constraint_set_test.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -16,6 +17,7 @@ import ( func TestAccAWSWafSizeConstraintSet_basic(t *testing.T) { var v waf.SizeConstraintSet sizeConstraintSet := fmt.Sprintf("sizeConstraintSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_size_constraint_set.size_constraint_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -25,25 +27,23 @@ func TestAccAWSWafSizeConstraintSet_basic(t *testing.T) { { Config: testAccAWSWafSizeConstraintSetConfig(sizeConstraintSet), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafSizeConstraintSetExists("aws_waf_size_constraint_set.size_constraint_set", &v), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "name", sizeConstraintSet), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.comparison_operator", "EQ"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.field_to_match.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.field_to_match.281401076.data", ""), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.field_to_match.281401076.type", "BODY"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.size", "4096"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.text_transformation", "NONE"), + testAccCheckAWSWafSizeConstraintSetExists(resourceName, &v), + testAccMatchResourceAttrGlobalARN(resourceName, "arn", "waf", regexp.MustCompile(`sizeconstraintset/.+`)), + resource.TestCheckResourceAttr(resourceName, "name", sizeConstraintSet), + resource.TestCheckResourceAttr(resourceName, "size_constraints.#", "1"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.comparison_operator", "EQ"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.field_to_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.field_to_match.281401076.data", ""), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.field_to_match.281401076.type", "BODY"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.size", "4096"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.text_transformation", "NONE"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -52,6 +52,7 @@ func TestAccAWSWafSizeConstraintSet_changeNameForceNew(t *testing.T) { var before, after waf.SizeConstraintSet sizeConstraintSet := fmt.Sprintf("sizeConstraintSet-%s", acctest.RandString(5)) sizeConstraintSetNewName := fmt.Sprintf("sizeConstraintSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_size_constraint_set.size_constraint_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -61,23 +62,24 @@ func TestAccAWSWafSizeConstraintSet_changeNameForceNew(t *testing.T) { { Config: testAccAWSWafSizeConstraintSetConfig(sizeConstraintSet), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafSizeConstraintSetExists("aws_waf_size_constraint_set.size_constraint_set", &before), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "name", sizeConstraintSet), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.#", "1"), + testAccCheckAWSWafSizeConstraintSetExists(resourceName, &before), + resource.TestCheckResourceAttr(resourceName, "name", sizeConstraintSet), + resource.TestCheckResourceAttr(resourceName, "size_constraints.#", "1"), ), }, { Config: testAccAWSWafSizeConstraintSetConfigChangeName(sizeConstraintSetNewName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafSizeConstraintSetExists("aws_waf_size_constraint_set.size_constraint_set", &after), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "name", sizeConstraintSetNewName), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.#", "1"), + testAccCheckAWSWafSizeConstraintSetExists(resourceName, &after), + resource.TestCheckResourceAttr(resourceName, "name", sizeConstraintSetNewName), + resource.TestCheckResourceAttr(resourceName, "size_constraints.#", "1"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -85,6 +87,7 @@ func TestAccAWSWafSizeConstraintSet_changeNameForceNew(t *testing.T) { func TestAccAWSWafSizeConstraintSet_disappears(t *testing.T) { var v waf.SizeConstraintSet sizeConstraintSet := fmt.Sprintf("sizeConstraintSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_size_constraint_set.size_constraint_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -94,7 +97,7 @@ func TestAccAWSWafSizeConstraintSet_disappears(t *testing.T) { { Config: testAccAWSWafSizeConstraintSetConfig(sizeConstraintSet), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafSizeConstraintSetExists("aws_waf_size_constraint_set.size_constraint_set", &v), + testAccCheckAWSWafSizeConstraintSetExists(resourceName, &v), testAccCheckAWSWafSizeConstraintSetDisappears(&v), ), ExpectNonEmptyPlan: true, @@ -106,6 +109,7 @@ func TestAccAWSWafSizeConstraintSet_disappears(t *testing.T) { func TestAccAWSWafSizeConstraintSet_changeConstraints(t *testing.T) { var before, after waf.SizeConstraintSet setName := fmt.Sprintf("sizeConstraintSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_size_constraint_set.size_constraint_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -115,47 +119,36 @@ func TestAccAWSWafSizeConstraintSet_changeConstraints(t *testing.T) { { Config: testAccAWSWafSizeConstraintSetConfig(setName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafSizeConstraintSetExists("aws_waf_size_constraint_set.size_constraint_set", &before), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "name", setName), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.comparison_operator", "EQ"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.field_to_match.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.field_to_match.281401076.data", ""), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.field_to_match.281401076.type", "BODY"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.size", "4096"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.2029852522.text_transformation", "NONE"), + testAccCheckAWSWafSizeConstraintSetExists(resourceName, &before), + resource.TestCheckResourceAttr(resourceName, "name", setName), + resource.TestCheckResourceAttr(resourceName, "size_constraints.#", "1"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.comparison_operator", "EQ"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.field_to_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.field_to_match.281401076.data", ""), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.field_to_match.281401076.type", "BODY"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.size", "4096"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.2029852522.text_transformation", "NONE"), ), }, { Config: testAccAWSWafSizeConstraintSetConfig_changeConstraints(setName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafSizeConstraintSetExists("aws_waf_size_constraint_set.size_constraint_set", &after), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "name", setName), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.3222308386.comparison_operator", "GE"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.3222308386.field_to_match.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.3222308386.field_to_match.281401076.data", ""), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.3222308386.field_to_match.281401076.type", "BODY"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.3222308386.size", "1024"), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.3222308386.text_transformation", "NONE"), + testAccCheckAWSWafSizeConstraintSetExists(resourceName, &after), + resource.TestCheckResourceAttr(resourceName, "name", setName), + resource.TestCheckResourceAttr(resourceName, "size_constraints.#", "1"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.3222308386.comparison_operator", "GE"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.3222308386.field_to_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.3222308386.field_to_match.281401076.data", ""), + resource.TestCheckResourceAttr(resourceName, "size_constraints.3222308386.field_to_match.281401076.type", "BODY"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.3222308386.size", "1024"), + resource.TestCheckResourceAttr(resourceName, "size_constraints.3222308386.text_transformation", "NONE"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -163,6 +156,7 @@ func TestAccAWSWafSizeConstraintSet_changeConstraints(t *testing.T) { func TestAccAWSWafSizeConstraintSet_noConstraints(t *testing.T) { var contraints waf.SizeConstraintSet setName := fmt.Sprintf("sizeConstraintSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_size_constraint_set.size_constraint_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -172,13 +166,16 @@ func TestAccAWSWafSizeConstraintSet_noConstraints(t *testing.T) { { Config: testAccAWSWafSizeConstraintSetConfig_noConstraints(setName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafSizeConstraintSetExists("aws_waf_size_constraint_set.size_constraint_set", &contraints), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "name", setName), - resource.TestCheckResourceAttr( - "aws_waf_size_constraint_set.size_constraint_set", "size_constraints.#", "0"), + testAccCheckAWSWafSizeConstraintSetExists(resourceName, &contraints), + resource.TestCheckResourceAttr(resourceName, "name", setName), + resource.TestCheckResourceAttr(resourceName, "size_constraints.#", "0"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -273,7 +270,7 @@ func testAccCheckAWSWafSizeConstraintSetDestroy(s *terraform.State) error { // Return nil if the SizeConstraintSet is already destroyed if awsErr, ok := err.(awserr.Error); ok { - if awsErr.Code() == "WAFNonexistentItemException" { + if awsErr.Code() == waf.ErrCodeNonexistentItemException { return nil } } diff --git a/aws/resource_aws_waf_xss_match_set.go b/aws/resource_aws_waf_xss_match_set.go index 823cac3514d..da671ca09b2 100644 --- a/aws/resource_aws_waf_xss_match_set.go +++ b/aws/resource_aws_waf_xss_match_set.go @@ -5,6 +5,7 @@ import ( "log" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/waf" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -16,6 +17,9 @@ func resourceAwsWafXssMatchSet() *schema.Resource { Read: resourceAwsWafXssMatchSetRead, Update: resourceAwsWafXssMatchSetUpdate, Delete: resourceAwsWafXssMatchSetDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: map[string]*schema.Schema{ "name": { @@ -23,6 +27,10 @@ func resourceAwsWafXssMatchSet() *schema.Resource { Required: true, ForceNew: true, }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, "xss_match_tuples": { Type: schema.TypeSet, Optional: true, @@ -89,7 +97,7 @@ func resourceAwsWafXssMatchSetRead(d *schema.ResourceData, meta interface{}) err resp, err := conn.GetXssMatchSet(params) if err != nil { - if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "WAFNonexistentItemException" { + if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == waf.ErrCodeNonexistentItemException { log.Printf("[WARN] WAF IPSet (%s) not found, removing from state", d.Id()) d.SetId("") return nil @@ -101,6 +109,14 @@ func resourceAwsWafXssMatchSetRead(d *schema.ResourceData, meta interface{}) err d.Set("name", resp.XssMatchSet.Name) d.Set("xss_match_tuples", flattenWafXssMatchTuples(resp.XssMatchSet.XssMatchTuples)) + arn := arn.ARN{ + Partition: meta.(*AWSClient).partition, + Service: "waf", + AccountID: meta.(*AWSClient).accountid, + Resource: fmt.Sprintf("xssmatchset/%s", d.Id()), + } + d.Set("arn", arn.String()) + return nil } diff --git a/aws/resource_aws_waf_xss_match_set_test.go b/aws/resource_aws_waf_xss_match_set_test.go index 84df10e330c..4c19716d84a 100644 --- a/aws/resource_aws_waf_xss_match_set_test.go +++ b/aws/resource_aws_waf_xss_match_set_test.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -16,6 +17,7 @@ import ( func TestAccAWSWafXssMatchSet_basic(t *testing.T) { var v waf.XssMatchSet xssMatchSet := fmt.Sprintf("xssMatchSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_xss_match_set.xss_match_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -25,29 +27,25 @@ func TestAccAWSWafXssMatchSet_basic(t *testing.T) { { Config: testAccAWSWafXssMatchSetConfig(xssMatchSet), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafXssMatchSetExists("aws_waf_xss_match_set.xss_match_set", &v), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "name", xssMatchSet), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.#", "2"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2018581549.field_to_match.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2018581549.field_to_match.2316364334.data", ""), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2018581549.field_to_match.2316364334.type", "QUERY_STRING"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2018581549.text_transformation", "NONE"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2786024938.field_to_match.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2786024938.field_to_match.3756326843.data", ""), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2786024938.field_to_match.3756326843.type", "URI"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2786024938.text_transformation", "NONE"), + testAccCheckAWSWafXssMatchSetExists(resourceName, &v), + testAccMatchResourceAttrGlobalARN(resourceName, "arn", "waf", regexp.MustCompile(`xssmatchset/.+`)), + resource.TestCheckResourceAttr(resourceName, "name", xssMatchSet), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.#", "2"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2018581549.field_to_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2018581549.field_to_match.2316364334.data", ""), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2018581549.field_to_match.2316364334.type", "QUERY_STRING"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2018581549.text_transformation", "NONE"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2786024938.field_to_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2786024938.field_to_match.3756326843.data", ""), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2786024938.field_to_match.3756326843.type", "URI"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2786024938.text_transformation", "NONE"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -56,6 +54,7 @@ func TestAccAWSWafXssMatchSet_changeNameForceNew(t *testing.T) { var before, after waf.XssMatchSet xssMatchSet := fmt.Sprintf("xssMatchSet-%s", acctest.RandString(5)) xssMatchSetNewName := fmt.Sprintf("xssMatchSetNewName-%s", acctest.RandString(5)) + resourceName := "aws_waf_xss_match_set.xss_match_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -65,23 +64,24 @@ func TestAccAWSWafXssMatchSet_changeNameForceNew(t *testing.T) { { Config: testAccAWSWafXssMatchSetConfig(xssMatchSet), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafXssMatchSetExists("aws_waf_xss_match_set.xss_match_set", &before), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "name", xssMatchSet), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.#", "2"), + testAccCheckAWSWafXssMatchSetExists(resourceName, &before), + resource.TestCheckResourceAttr(resourceName, "name", xssMatchSet), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.#", "2"), ), }, { Config: testAccAWSWafXssMatchSetConfigChangeName(xssMatchSetNewName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafXssMatchSetExists("aws_waf_xss_match_set.xss_match_set", &after), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "name", xssMatchSetNewName), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.#", "2"), + testAccCheckAWSWafXssMatchSetExists(resourceName, &after), + resource.TestCheckResourceAttr(resourceName, "name", xssMatchSetNewName), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.#", "2"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -89,6 +89,7 @@ func TestAccAWSWafXssMatchSet_changeNameForceNew(t *testing.T) { func TestAccAWSWafXssMatchSet_disappears(t *testing.T) { var v waf.XssMatchSet xssMatchSet := fmt.Sprintf("xssMatchSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_xss_match_set.xss_match_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -98,7 +99,7 @@ func TestAccAWSWafXssMatchSet_disappears(t *testing.T) { { Config: testAccAWSWafXssMatchSetConfig(xssMatchSet), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSWafXssMatchSetExists("aws_waf_xss_match_set.xss_match_set", &v), + testAccCheckAWSWafXssMatchSetExists(resourceName, &v), testAccCheckAWSWafXssMatchSetDisappears(&v), ), ExpectNonEmptyPlan: true, @@ -110,6 +111,7 @@ func TestAccAWSWafXssMatchSet_disappears(t *testing.T) { func TestAccAWSWafXssMatchSet_changeTuples(t *testing.T) { var before, after waf.XssMatchSet setName := fmt.Sprintf("xssMatchSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_xss_match_set.xss_match_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -119,55 +121,40 @@ func TestAccAWSWafXssMatchSet_changeTuples(t *testing.T) { { Config: testAccAWSWafXssMatchSetConfig(setName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafXssMatchSetExists("aws_waf_xss_match_set.xss_match_set", &before), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "name", setName), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.#", "2"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2018581549.field_to_match.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2018581549.field_to_match.2316364334.data", ""), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2018581549.field_to_match.2316364334.type", "QUERY_STRING"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2018581549.text_transformation", "NONE"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2786024938.field_to_match.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2786024938.field_to_match.3756326843.data", ""), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2786024938.field_to_match.3756326843.type", "URI"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2786024938.text_transformation", "NONE"), + testAccCheckAWSWafXssMatchSetExists(resourceName, &before), + resource.TestCheckResourceAttr(resourceName, "name", setName), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.#", "2"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2018581549.field_to_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2018581549.field_to_match.2316364334.data", ""), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2018581549.field_to_match.2316364334.type", "QUERY_STRING"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2018581549.text_transformation", "NONE"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2786024938.field_to_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2786024938.field_to_match.3756326843.data", ""), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2786024938.field_to_match.3756326843.type", "URI"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2786024938.text_transformation", "NONE"), ), }, { Config: testAccAWSWafXssMatchSetConfig_changeTuples(setName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafXssMatchSetExists("aws_waf_xss_match_set.xss_match_set", &after), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "name", setName), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.#", "2"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2893682529.field_to_match.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2893682529.field_to_match.4253810390.data", "GET"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2893682529.field_to_match.4253810390.type", "METHOD"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.2893682529.text_transformation", "HTML_ENTITY_DECODE"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.4270311415.field_to_match.#", "1"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.4270311415.field_to_match.281401076.data", ""), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.4270311415.field_to_match.281401076.type", "BODY"), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.4270311415.text_transformation", "CMD_LINE"), + testAccCheckAWSWafXssMatchSetExists(resourceName, &after), + resource.TestCheckResourceAttr(resourceName, "name", setName), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.#", "2"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2893682529.field_to_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2893682529.field_to_match.4253810390.data", "GET"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2893682529.field_to_match.4253810390.type", "METHOD"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.2893682529.text_transformation", "HTML_ENTITY_DECODE"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.4270311415.field_to_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.4270311415.field_to_match.281401076.data", ""), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.4270311415.field_to_match.281401076.type", "BODY"), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.4270311415.text_transformation", "CMD_LINE"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -175,6 +162,7 @@ func TestAccAWSWafXssMatchSet_changeTuples(t *testing.T) { func TestAccAWSWafXssMatchSet_noTuples(t *testing.T) { var ipset waf.XssMatchSet setName := fmt.Sprintf("xssMatchSet-%s", acctest.RandString(5)) + resourceName := "aws_waf_xss_match_set.xss_match_set" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSWaf(t) }, @@ -184,13 +172,16 @@ func TestAccAWSWafXssMatchSet_noTuples(t *testing.T) { { Config: testAccAWSWafXssMatchSetConfig_noTuples(setName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckAWSWafXssMatchSetExists("aws_waf_xss_match_set.xss_match_set", &ipset), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "name", setName), - resource.TestCheckResourceAttr( - "aws_waf_xss_match_set.xss_match_set", "xss_match_tuples.#", "0"), + testAccCheckAWSWafXssMatchSetExists(resourceName, &ipset), + resource.TestCheckResourceAttr(resourceName, "name", setName), + resource.TestCheckResourceAttr(resourceName, "xss_match_tuples.#", "0"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -285,7 +276,7 @@ func testAccCheckAWSWafXssMatchSetDestroy(s *terraform.State) error { // Return nil if the XssMatchSet is already destroyed if awsErr, ok := err.(awserr.Error); ok { - if awsErr.Code() == "WAFNonexistentItemException" { + if awsErr.Code() == waf.ErrCodeNonexistentItemException { return nil } } diff --git a/aws/resource_aws_wafregional_rate_based_rule.go b/aws/resource_aws_wafregional_rate_based_rule.go index e329751a4d6..a6fe9f72063 100644 --- a/aws/resource_aws_wafregional_rate_based_rule.go +++ b/aws/resource_aws_wafregional_rate_based_rule.go @@ -5,10 +5,12 @@ import ( "log" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/waf" "github.com/aws/aws-sdk-go/service/wafregional" "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 resourceAwsWafRegionalRateBasedRule() *schema.Resource { @@ -64,6 +66,11 @@ func resourceAwsWafRegionalRateBasedRule() *schema.Resource { Required: true, ValidateFunc: validation.IntAtLeast(100), }, + "tags": tagsSchema(), + "arn": { + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -71,6 +78,7 @@ func resourceAwsWafRegionalRateBasedRule() *schema.Resource { func resourceAwsWafRegionalRateBasedRuleCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).wafregionalconn region := meta.(*AWSClient).region + tags := keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().WafregionalTags() wr := newWafRegionalRetryer(conn, region) out, err := wr.RetryWithToken(func(token *string) (interface{}, error) { @@ -82,6 +90,10 @@ func resourceAwsWafRegionalRateBasedRuleCreate(d *schema.ResourceData, meta inte RateLimit: aws.Int64(int64(d.Get("rate_limit").(int))), } + if len(tags) > 0 { + params.Tags = tags + } + return conn.CreateRateBasedRule(params) }) if err != nil { @@ -89,7 +101,17 @@ func resourceAwsWafRegionalRateBasedRuleCreate(d *schema.ResourceData, meta inte } resp := out.(*waf.CreateRateBasedRuleOutput) d.SetId(*resp.Rule.RuleId) - return resourceAwsWafRegionalRateBasedRuleUpdate(d, meta) + + newPredicates := d.Get("predicate").(*schema.Set).List() + if len(newPredicates) > 0 { + noPredicates := []interface{}{} + err := updateWafRateBasedRuleResourceWR(d.Id(), noPredicates, newPredicates, d.Get("rate_limit"), conn, region) + if err != nil { + return fmt.Errorf("Error Updating WAF Rate Based Rule: %s", err) + } + } + + return resourceAwsWafRegionalRateBasedRuleRead(d, meta) } func resourceAwsWafRegionalRateBasedRuleRead(d *schema.ResourceData, meta interface{}) error { @@ -119,6 +141,23 @@ func resourceAwsWafRegionalRateBasedRuleRead(d *schema.ResourceData, meta interf }) } + arn := arn.ARN{ + AccountID: meta.(*AWSClient).accountid, + Partition: meta.(*AWSClient).partition, + Region: meta.(*AWSClient).region, + Resource: fmt.Sprintf("ratebasedrule/%s", d.Id()), + Service: "waf-regional", + }.String() + d.Set("arn", arn) + + tagList, err := keyvaluetags.WafregionalListTags(conn, arn) + if err != nil { + return fmt.Errorf("Failed to get WAF Regional Rated Based Rule parameter tags for %s: %s", d.Get("name"), err) + } + if err := d.Set("tags", tagList.IgnoreAws().Map()); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + d.Set("predicate", predicates) d.Set("name", resp.Rule.Name) d.Set("metric_name", resp.Rule.MetricName) @@ -148,6 +187,14 @@ func resourceAwsWafRegionalRateBasedRuleUpdate(d *schema.ResourceData, meta inte } } + if d.HasChange("tags") { + o, n := d.GetChange("tags") + + if err := keyvaluetags.WafregionalUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) + } + } + return resourceAwsWafRegionalRateBasedRuleRead(d, meta) } diff --git a/aws/resource_aws_wafregional_rate_based_rule_test.go b/aws/resource_aws_wafregional_rate_based_rule_test.go index 5157d2025cd..4c45493e926 100644 --- a/aws/resource_aws_wafregional_rate_based_rule_test.go +++ b/aws/resource_aws_wafregional_rate_based_rule_test.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -130,12 +131,10 @@ func TestAccAWSWafRegionalRateBasedRule_basic(t *testing.T) { Config: testAccAWSWafRegionalRateBasedRuleConfig(wafRuleName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &v), - resource.TestCheckResourceAttr( - resourceName, "name", wafRuleName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafRuleName), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "waf-regional", regexp.MustCompile(`ratebasedrule/.+`)), + resource.TestCheckResourceAttr(resourceName, "name", wafRuleName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafRuleName), ), }, { @@ -147,6 +146,49 @@ func TestAccAWSWafRegionalRateBasedRule_basic(t *testing.T) { }) } +func TestAccAWSWafRegionalRateBasedRule_tags(t *testing.T) { + var v waf.RateBasedRule + resourceName := "aws_wafregional_rate_based_rule.wafrule" + wafRuleName := fmt.Sprintf("wafrule%s", acctest.RandString(5)) + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSWafRegionalRateBasedRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSWafRegionalRateBasedRuleConfigTags1(wafRuleName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSWafRegionalRateBasedRuleConfigTags2(wafRuleName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccAWSWafRegionalRateBasedRuleConfigTags1(wafRuleName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + func TestAccAWSWafRegionalRateBasedRule_changeNameForceNew(t *testing.T) { var before, after waf.RateBasedRule resourceName := "aws_wafregional_rate_based_rule.wafrule" @@ -162,12 +204,9 @@ func TestAccAWSWafRegionalRateBasedRule_changeNameForceNew(t *testing.T) { Config: testAccAWSWafRegionalRateBasedRuleConfig(wafRuleName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &before), - resource.TestCheckResourceAttr( - resourceName, "name", wafRuleName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafRuleName), + resource.TestCheckResourceAttr(resourceName, "name", wafRuleName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafRuleName), ), }, { @@ -175,12 +214,9 @@ func TestAccAWSWafRegionalRateBasedRule_changeNameForceNew(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &after), testAccCheckAWSWafRateBasedRuleIdDiffers(&before, &after), - resource.TestCheckResourceAttr( - resourceName, "name", wafRuleNewName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafRuleNewName), + resource.TestCheckResourceAttr(resourceName, "name", wafRuleNewName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafRuleNewName), ), }, { @@ -349,10 +385,8 @@ func TestAccAWSWafRegionalRateBasedRule_noPredicates(t *testing.T) { Config: testAccAWSWafRegionalRateBasedRuleConfig_noPredicates(ruleName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &rule), - resource.TestCheckResourceAttr( - resourceName, "name", ruleName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "0"), + resource.TestCheckResourceAttr(resourceName, "name", ruleName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "0"), ), }, { @@ -479,7 +513,7 @@ func testAccCheckAWSWafRegionalRateBasedRuleExists(n string, v *waf.RateBasedRul func testAccAWSWafRegionalRateBasedRuleConfig(name string) string { return fmt.Sprintf(` resource "aws_wafregional_ipset" "ipset" { - name = "%s" + name = %[1]q ip_set_descriptor { type = "IPV4" @@ -488,8 +522,34 @@ resource "aws_wafregional_ipset" "ipset" { } resource "aws_wafregional_rate_based_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q + rate_key = "IP" + rate_limit = 2000 + + predicate { + data_id = "${aws_wafregional_ipset.ipset.id}" + negated = false + type = "IPMatch" + } +} +`, name) +} + +func testAccAWSWafRegionalRateBasedRuleConfigTags1(name, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_wafregional_ipset" "ipset" { + name = %[1]q + + ip_set_descriptor { + type = "IPV4" + value = "192.0.7.0/24" + } +} + +resource "aws_wafregional_rate_based_rule" "wafrule" { + name = %[1]q + metric_name = %[1]q rate_key = "IP" rate_limit = 2000 @@ -498,14 +558,49 @@ resource "aws_wafregional_rate_based_rule" "wafrule" { negated = false type = "IPMatch" } + + tags = { + %[2]q = %[3]q + } } -`, name, name, name) +`, name, tagKey1, tagValue1) +} + +func testAccAWSWafRegionalRateBasedRuleConfigTags2(name, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_wafregional_ipset" "ipset" { + name = %[1]q + + ip_set_descriptor { + type = "IPV4" + value = "192.0.7.0/24" + } +} + +resource "aws_wafregional_rate_based_rule" "wafrule" { + name = %[1]q + metric_name = %[1]q + rate_key = "IP" + rate_limit = 2000 + + predicate { + data_id = "${aws_wafregional_ipset.ipset.id}" + negated = false + type = "IPMatch" + } + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, name, tagKey1, tagValue1, tagKey2, tagValue2) } func testAccAWSWafRegionalRateBasedRuleConfigChangeName(name string) string { return fmt.Sprintf(` resource "aws_wafregional_ipset" "ipset" { - name = "%s" + name = %[1]q ip_set_descriptor { type = "IPV4" @@ -514,8 +609,8 @@ resource "aws_wafregional_ipset" "ipset" { } resource "aws_wafregional_rate_based_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q rate_key = "IP" rate_limit = 2000 @@ -525,13 +620,13 @@ resource "aws_wafregional_rate_based_rule" "wafrule" { type = "IPMatch" } } -`, name, name, name) +`, name) } func testAccAWSWafRegionalRateBasedRuleConfig_changePredicates(name string) string { return fmt.Sprintf(` resource "aws_wafregional_ipset" "ipset" { - name = "%s" + name = %[1]q ip_set_descriptor { type = "IPV4" @@ -540,7 +635,7 @@ resource "aws_wafregional_ipset" "ipset" { } resource "aws_wafregional_byte_match_set" "set" { - name = "%s" + name = %[1]q byte_match_tuples { text_transformation = "NONE" @@ -555,8 +650,8 @@ resource "aws_wafregional_byte_match_set" "set" { } resource "aws_wafregional_rate_based_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q rate_key = "IP" rate_limit = 2000 @@ -566,18 +661,18 @@ resource "aws_wafregional_rate_based_rule" "wafrule" { type = "ByteMatch" } } -`, name, name, name, name) +`, name) } func testAccAWSWafRegionalRateBasedRuleConfig_noPredicates(name string) string { return fmt.Sprintf(` resource "aws_wafregional_rate_based_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q rate_key = "IP" rate_limit = 2000 } -`, name, name) +`, name) } func testAccAWSWafRegionalRateBasedRuleWithRateLimitConfig(name string, limit string) string { diff --git a/aws/resource_aws_wafregional_rule.go b/aws/resource_aws_wafregional_rule.go index 7b139c555f4..b16703e3468 100644 --- a/aws/resource_aws_wafregional_rule.go +++ b/aws/resource_aws_wafregional_rule.go @@ -4,12 +4,13 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/service/wafregional" - "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/waf" + "github.com/aws/aws-sdk-go/service/wafregional" "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 resourceAwsWafRegionalRule() *schema.Resource { @@ -55,6 +56,11 @@ func resourceAwsWafRegionalRule() *schema.Resource { }, }, }, + "tags": tagsSchema(), + "arn": { + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -62,6 +68,7 @@ func resourceAwsWafRegionalRule() *schema.Resource { func resourceAwsWafRegionalRuleCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).wafregionalconn region := meta.(*AWSClient).region + tags := keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().WafregionalTags() wr := newWafRegionalRetryer(conn, region) out, err := wr.RetryWithToken(func(token *string) (interface{}, error) { @@ -71,6 +78,10 @@ func resourceAwsWafRegionalRuleCreate(d *schema.ResourceData, meta interface{}) Name: aws.String(d.Get("name").(string)), } + if len(tags) > 0 { + params.Tags = tags + } + return conn.CreateRule(params) }) if err != nil { @@ -78,7 +89,16 @@ func resourceAwsWafRegionalRuleCreate(d *schema.ResourceData, meta interface{}) } resp := out.(*waf.CreateRuleOutput) d.SetId(*resp.Rule.RuleId) - return resourceAwsWafRegionalRuleUpdate(d, meta) + + newPredicates := d.Get("predicate").(*schema.Set).List() + if len(newPredicates) > 0 { + noPredicates := []interface{}{} + err := updateWafRegionalRuleResource(d.Id(), noPredicates, newPredicates, meta) + if err != nil { + return fmt.Errorf("Error Updating WAF Regional Rule: %s", err) + } + } + return resourceAwsWafRegionalRuleRead(d, meta) } func resourceAwsWafRegionalRuleRead(d *schema.ResourceData, meta interface{}) error { @@ -99,6 +119,25 @@ func resourceAwsWafRegionalRuleRead(d *schema.ResourceData, meta interface{}) er return err } + arn := arn.ARN{ + AccountID: meta.(*AWSClient).accountid, + Partition: meta.(*AWSClient).partition, + Region: meta.(*AWSClient).region, + Resource: fmt.Sprintf("rule/%s", d.Id()), + Service: "waf-regional", + }.String() + d.Set("arn", arn) + + tags, err := keyvaluetags.WafregionalListTags(conn, arn) + + if err != nil { + return fmt.Errorf("error listing tags for WAF Regional Rule (%s): %s", arn, err) + } + + if err := d.Set("tags", tags.IgnoreAws().Map()); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + d.Set("predicate", flattenWafPredicates(resp.Rule.Predicates)) d.Set("name", resp.Rule.Name) d.Set("metric_name", resp.Rule.MetricName) @@ -107,6 +146,8 @@ func resourceAwsWafRegionalRuleRead(d *schema.ResourceData, meta interface{}) er } func resourceAwsWafRegionalRuleUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).wafregionalconn + if d.HasChange("predicate") { o, n := d.GetChange("predicate") oldP, newP := o.(*schema.Set).List(), n.(*schema.Set).List() @@ -116,6 +157,15 @@ func resourceAwsWafRegionalRuleUpdate(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error Updating WAF Rule: %s", err) } } + + if d.HasChange("tags") { + o, n := d.GetChange("tags") + + if err := keyvaluetags.WafregionalUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) + } + } + return resourceAwsWafRegionalRuleRead(d, meta) } diff --git a/aws/resource_aws_wafregional_rule_group.go b/aws/resource_aws_wafregional_rule_group.go index 5d01c1204dd..48b5d97e906 100644 --- a/aws/resource_aws_wafregional_rule_group.go +++ b/aws/resource_aws_wafregional_rule_group.go @@ -5,9 +5,11 @@ import ( "log" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/waf" "github.com/aws/aws-sdk-go/service/wafregional" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) func resourceAwsWafRegionalRuleGroup() *schema.Resource { @@ -66,6 +68,11 @@ func resourceAwsWafRegionalRuleGroup() *schema.Resource { }, }, }, + "tags": tagsSchema(), + "arn": { + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -73,6 +80,7 @@ func resourceAwsWafRegionalRuleGroup() *schema.Resource { func resourceAwsWafRegionalRuleGroupCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).wafregionalconn region := meta.(*AWSClient).region + tags := keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().WafregionalTags() wr := newWafRegionalRetryer(conn, region) out, err := wr.RetryWithToken(func(token *string) (interface{}, error) { @@ -82,6 +90,10 @@ func resourceAwsWafRegionalRuleGroupCreate(d *schema.ResourceData, meta interfac Name: aws.String(d.Get("name").(string)), } + if len(tags) > 0 { + params.Tags = tags + } + return conn.CreateRuleGroup(params) }) if err != nil { @@ -89,7 +101,18 @@ func resourceAwsWafRegionalRuleGroupCreate(d *schema.ResourceData, meta interfac } resp := out.(*waf.CreateRuleGroupOutput) d.SetId(*resp.RuleGroup.RuleGroupId) - return resourceAwsWafRegionalRuleGroupUpdate(d, meta) + + activatedRule := d.Get("activated_rule").(*schema.Set).List() + if len(activatedRule) > 0 { + noActivatedRules := []interface{}{} + + err := updateWafRuleGroupResourceWR(d.Id(), noActivatedRules, activatedRule, conn, region) + if err != nil { + return fmt.Errorf("Error Updating WAF Regional Rule Group: %s", err) + } + } + + return resourceAwsWafRegionalRuleGroupRead(d, meta) } func resourceAwsWafRegionalRuleGroupRead(d *schema.ResourceData, meta interface{}) error { @@ -117,6 +140,23 @@ func resourceAwsWafRegionalRuleGroupRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("error listing activated rules in WAF Regional Rule Group (%s): %s", d.Id(), err) } + arn := arn.ARN{ + AccountID: meta.(*AWSClient).accountid, + Partition: meta.(*AWSClient).partition, + Region: meta.(*AWSClient).region, + Resource: fmt.Sprintf("rulegroup/%s", d.Id()), + Service: "waf-regional", + }.String() + d.Set("arn", arn) + + tags, err := keyvaluetags.WafregionalListTags(conn, arn) + if err != nil { + return fmt.Errorf("error listing tags for WAF Regional Rule Group (%s): %s", arn, err) + } + if err := d.Set("tags", tags.IgnoreAws().Map()); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + d.Set("activated_rule", flattenWafActivatedRules(rResp.ActivatedRules)) d.Set("name", resp.RuleGroup.Name) d.Set("metric_name", resp.RuleGroup.MetricName) @@ -138,6 +178,14 @@ func resourceAwsWafRegionalRuleGroupUpdate(d *schema.ResourceData, meta interfac } } + if d.HasChange("tags") { + o, n := d.GetChange("tags") + + if err := keyvaluetags.WafregionalUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) + } + } + return resourceAwsWafRegionalRuleGroupRead(d, meta) } diff --git a/aws/resource_aws_wafregional_rule_group_test.go b/aws/resource_aws_wafregional_rule_group_test.go index 2a20ef01e75..780fc656e60 100644 --- a/aws/resource_aws_wafregional_rule_group_test.go +++ b/aws/resource_aws_wafregional_rule_group_test.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -78,6 +79,7 @@ func TestAccAWSWafRegionalRuleGroup_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRuleExists("aws_wafregional_rule.test", &rule), testAccCheckAWSWafRegionalRuleGroupExists(resourceName, &group), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "waf-regional", regexp.MustCompile(`rulegroup/.+`)), resource.TestCheckResourceAttr(resourceName, "name", groupName), resource.TestCheckResourceAttr(resourceName, "activated_rule.#", "1"), resource.TestCheckResourceAttr(resourceName, "metric_name", groupName), @@ -96,6 +98,56 @@ func TestAccAWSWafRegionalRuleGroup_basic(t *testing.T) { }) } +func TestAccAWSWafRegionalRuleGroup_tags(t *testing.T) { + var rule waf.Rule + var group waf.RuleGroup + + ruleName := fmt.Sprintf("tfacc%s", acctest.RandString(5)) + groupName := fmt.Sprintf("tfacc%s", acctest.RandString(5)) + resourceName := "aws_wafregional_rule_group.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSWafRegionalRuleGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSWafRegionalRuleGroupConfigTags1(ruleName, groupName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRuleExists("aws_wafregional_rule.test", &rule), + testAccCheckAWSWafRegionalRuleGroupExists(resourceName, &group), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSWafRegionalRuleGroupConfigTags2(ruleName, groupName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRuleExists("aws_wafregional_rule.test", &rule), + testAccCheckAWSWafRegionalRuleGroupExists(resourceName, &group), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccAWSWafRegionalRuleGroupConfigTags1(ruleName, groupName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRuleExists("aws_wafregional_rule.test", &rule), + testAccCheckAWSWafRegionalRuleGroupExists(resourceName, &group), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + func TestAccAWSWafRegionalRuleGroup_changeNameForceNew(t *testing.T) { var before, after waf.RuleGroup @@ -237,10 +289,8 @@ func TestAccAWSWafRegionalRuleGroup_noActivatedRules(t *testing.T) { Config: testAccAWSWafRegionalRuleGroupConfig_noActivatedRules(groupName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSWafRegionalRuleGroupExists(resourceName, &group), - resource.TestCheckResourceAttr( - resourceName, "name", groupName), - resource.TestCheckResourceAttr( - resourceName, "activated_rule.#", "0"), + resource.TestCheckResourceAttr(resourceName, "name", groupName), + resource.TestCheckResourceAttr(resourceName, "activated_rule.#", "0"), ), }, }, @@ -373,6 +423,61 @@ resource "aws_wafregional_rule_group" "test" { `, ruleName, groupName) } +func testAccAWSWafRegionalRuleGroupConfigTags1(ruleName, groupName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_wafregional_rule" "test" { + name = %[1]q + metric_name = %[1]q +} + +resource "aws_wafregional_rule_group" "test" { + name = %[2]q + metric_name = %[2]q + + activated_rule { + action { + type = "COUNT" + } + + priority = 50 + rule_id = "${aws_wafregional_rule.test.id}" + } + + tags = { + %[3]q = %[4]q + } +} +`, ruleName, groupName, tagKey1, tagValue1) +} + +func testAccAWSWafRegionalRuleGroupConfigTags2(ruleName, groupName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_wafregional_rule" "test" { + name = %[1]q + metric_name = %[1]q +} + +resource "aws_wafregional_rule_group" "test" { + name = %[2]q + metric_name = %[2]q + + activated_rule { + action { + type = "COUNT" + } + + priority = 50 + rule_id = "${aws_wafregional_rule.test.id}" + } + + tags = { + %[3]q = %[4]q + %[5]q = %[6]q + } +} +`, ruleName, groupName, tagKey1, tagValue1, tagKey2, tagValue2) +} + func testAccAWSWafRegionalRuleGroupConfig_changeActivatedRules(ruleName1, ruleName2, ruleName3, groupName string) string { return fmt.Sprintf(` resource "aws_wafregional_rule" "test" { diff --git a/aws/resource_aws_wafregional_rule_test.go b/aws/resource_aws_wafregional_rule_test.go index 236700d9397..899b4da9374 100644 --- a/aws/resource_aws_wafregional_rule_test.go +++ b/aws/resource_aws_wafregional_rule_test.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -130,12 +131,10 @@ func TestAccAWSWafRegionalRule_basic(t *testing.T) { Config: testAccAWSWafRegionalRuleConfig(wafRuleName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRuleExists(resourceName, &v), - resource.TestCheckResourceAttr( - resourceName, "name", wafRuleName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafRuleName), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "waf-regional", regexp.MustCompile(`rule/.+`)), + resource.TestCheckResourceAttr(resourceName, "name", wafRuleName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafRuleName), ), }, { @@ -147,6 +146,50 @@ func TestAccAWSWafRegionalRule_basic(t *testing.T) { }) } +func TestAccAWSWafRegionalRule_tags(t *testing.T) { + var v waf.Rule + wafRuleName := fmt.Sprintf("wafrule%s", acctest.RandString(5)) + resourceName := "aws_wafregional_rule.wafrule" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSWafRegionalRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSWafRegionalRuleConfigTags1(wafRuleName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRuleExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSWafRegionalRuleConfigTags2(wafRuleName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRuleExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccAWSWafRegionalRuleConfigTags1(wafRuleName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRuleExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + func TestAccAWSWafRegionalRule_changeNameForceNew(t *testing.T) { var before, after waf.Rule wafRuleName := fmt.Sprintf("wafrule%s", acctest.RandString(5)) @@ -162,24 +205,18 @@ func TestAccAWSWafRegionalRule_changeNameForceNew(t *testing.T) { Config: testAccAWSWafRegionalRuleConfig(wafRuleName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRuleExists(resourceName, &before), - resource.TestCheckResourceAttr( - resourceName, "name", wafRuleName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafRuleName), + resource.TestCheckResourceAttr(resourceName, "name", wafRuleName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafRuleName), ), }, { Config: testAccAWSWafRegionalRuleConfigChangeName(wafRuleNewName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRuleExists(resourceName, &after), - resource.TestCheckResourceAttr( - resourceName, "name", wafRuleNewName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafRuleNewName), + resource.TestCheckResourceAttr(resourceName, "name", wafRuleNewName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafRuleNewName), ), }, { @@ -227,10 +264,8 @@ func TestAccAWSWafRegionalRule_noPredicates(t *testing.T) { Config: testAccAWSWafRegionalRule_noPredicates(wafRuleName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSWafRegionalRuleExists(resourceName, &v), - resource.TestCheckResourceAttr( - resourceName, "name", wafRuleName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "0"), + resource.TestCheckResourceAttr(resourceName, "name", wafRuleName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "0"), ), }, { @@ -414,7 +449,31 @@ func testAccCheckAWSWafRegionalRuleExists(n string, v *waf.Rule) resource.TestCh func testAccAWSWafRegionalRuleConfig(name string) string { return fmt.Sprintf(` resource "aws_wafregional_ipset" "ipset" { - name = "%s" + name = %[1]q + + ip_set_descriptor { + type = "IPV4" + value = "192.0.7.0/24" + } +} + +resource "aws_wafregional_rule" "wafrule" { + name = %[1]q + metric_name = %[1]q + + predicate { + data_id = "${aws_wafregional_ipset.ipset.id}" + negated = false + type = "IPMatch" + } +} +`, name) +} + +func testAccAWSWafRegionalRuleConfigTags1(name, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_wafregional_ipset" "ipset" { + name = %[1]q ip_set_descriptor { type = "IPV4" @@ -423,22 +482,55 @@ resource "aws_wafregional_ipset" "ipset" { } resource "aws_wafregional_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q predicate { data_id = "${aws_wafregional_ipset.ipset.id}" negated = false type = "IPMatch" } + + tags = { + %[2]q = %[3]q + } +} +`, name, tagKey1, tagValue1) +} + +func testAccAWSWafRegionalRuleConfigTags2(name, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_wafregional_ipset" "ipset" { + name = %[1]q + + ip_set_descriptor { + type = "IPV4" + value = "192.0.7.0/24" + } +} + +resource "aws_wafregional_rule" "wafrule" { + name = %[1]q + metric_name = %[1]q + + predicate { + data_id = "${aws_wafregional_ipset.ipset.id}" + negated = false + type = "IPMatch" + } + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } } -`, name, name, name) +`, name, tagKey1, tagValue1, tagKey2, tagValue2) } func testAccAWSWafRegionalRuleConfigChangeName(name string) string { return fmt.Sprintf(` resource "aws_wafregional_ipset" "ipset" { - name = "%s" + name = %[1]q ip_set_descriptor { type = "IPV4" @@ -447,8 +539,8 @@ resource "aws_wafregional_ipset" "ipset" { } resource "aws_wafregional_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q predicate { data_id = "${aws_wafregional_ipset.ipset.id}" @@ -456,22 +548,22 @@ resource "aws_wafregional_rule" "wafrule" { type = "IPMatch" } } -`, name, name, name) +`, name) } func testAccAWSWafRegionalRule_noPredicates(name string) string { return fmt.Sprintf(` resource "aws_wafregional_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q } -`, name, name) +`, name) } func testAccAWSWafRegionalRule_changePredicates(name string) string { return fmt.Sprintf(` resource "aws_wafregional_ipset" "ipset" { - name = "%s" + name = %[1]q ip_set_descriptor { type = "IPV4" @@ -480,7 +572,7 @@ resource "aws_wafregional_ipset" "ipset" { } resource "aws_wafregional_xss_match_set" "xss_match_set" { - name = "%s" + name = %[1]q xss_match_tuple { text_transformation = "NONE" @@ -492,8 +584,8 @@ resource "aws_wafregional_xss_match_set" "xss_match_set" { } resource "aws_wafregional_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q predicate { data_id = "${aws_wafregional_xss_match_set.xss_match_set.id}" @@ -507,5 +599,5 @@ resource "aws_wafregional_rule" "wafrule" { type = "IPMatch" } } -`, name, name, name, name) +`, name) } diff --git a/aws/resource_aws_wafregional_web_acl.go b/aws/resource_aws_wafregional_web_acl.go index b23f26fa69a..8308b40f23f 100644 --- a/aws/resource_aws_wafregional_web_acl.go +++ b/aws/resource_aws_wafregional_web_acl.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/wafregional" "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 resourceAwsWafRegionalWebAcl() *schema.Resource { @@ -140,6 +141,7 @@ func resourceAwsWafRegionalWebAcl() *schema.Resource { }, }, }, + "tags": tagsSchema(), }, } } @@ -147,6 +149,7 @@ func resourceAwsWafRegionalWebAcl() *schema.Resource { func resourceAwsWafRegionalWebAclCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).wafregionalconn region := meta.(*AWSClient).region + tags := keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().WafregionalTags() wr := newWafRegionalRetryer(conn, region) out, err := wr.RetryWithToken(func(token *string) (interface{}, error) { @@ -157,6 +160,10 @@ func resourceAwsWafRegionalWebAclCreate(d *schema.ResourceData, meta interface{} Name: aws.String(d.Get("name").(string)), } + if len(tags) > 0 { + params.Tags = tags + } + return conn.CreateWebACL(params) }) if err != nil { @@ -176,10 +183,38 @@ func resourceAwsWafRegionalWebAclCreate(d *schema.ResourceData, meta interface{} Service: "waf-regional", }.String() } - // Set for update - d.Set("arn", webACLARN) - return resourceAwsWafRegionalWebAclUpdate(d, meta) + loggingConfiguration := d.Get("logging_configuration").([]interface{}) + + if len(loggingConfiguration) == 1 { + input := &waf.PutLoggingConfigurationInput{ + LoggingConfiguration: expandWAFRegionalLoggingConfiguration(loggingConfiguration, webACLARN), + } + + log.Printf("[DEBUG] Updating WAF Regional Web ACL (%s) Logging Configuration: %s", d.Id(), input) + if _, err := conn.PutLoggingConfiguration(input); err != nil { + return fmt.Errorf("error Updating WAF Regional Web ACL (%s) Logging Configuration: %s", d.Id(), err) + } + } + + rules := d.Get("rule").(*schema.Set).List() + if len(rules) > 0 { + wr := newWafRegionalRetryer(conn, region) + _, err := wr.RetryWithToken(func(token *string) (interface{}, error) { + req := &waf.UpdateWebACLInput{ + ChangeToken: token, + DefaultAction: expandWafAction(d.Get("default_action").([]interface{})), + Updates: diffWafWebAclRules([]interface{}{}, rules), + WebACLId: aws.String(d.Id()), + } + return conn.UpdateWebACL(req) + }) + if err != nil { + return fmt.Errorf("Error Updating WAF Regional ACL: %s", err) + } + } + + return resourceAwsWafRegionalWebAclRead(d, meta) } func resourceAwsWafRegionalWebAclRead(d *schema.ResourceData, meta interface{}) error { @@ -227,6 +262,14 @@ func resourceAwsWafRegionalWebAclRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("error setting rule: %s", err) } + tags, err := keyvaluetags.WafregionalListTags(conn, webACLARN) + if err != nil { + return fmt.Errorf("error listing tags for WAF Regional ACL (%s): %s", webACLARN, err) + } + if err := d.Set("tags", tags.IgnoreAws().Map()); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + getLoggingConfigurationInput := &waf.GetLoggingConfigurationInput{ ResourceArn: aws.String(d.Get("arn").(string)), } @@ -297,6 +340,14 @@ func resourceAwsWafRegionalWebAclUpdate(d *schema.ResourceData, meta interface{} } } + if d.HasChange("tags") { + o, n := d.GetChange("tags") + + if err := keyvaluetags.WafregionalUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) + } + } + return resourceAwsWafRegionalWebAclRead(d, meta) } diff --git a/aws/resource_aws_wafregional_web_acl_association.go b/aws/resource_aws_wafregional_web_acl_association.go index f69d90682a6..c7814f654e4 100644 --- a/aws/resource_aws_wafregional_web_acl_association.go +++ b/aws/resource_aws_wafregional_web_acl_association.go @@ -17,6 +17,9 @@ func resourceAwsWafRegionalWebAclAssociation() *schema.Resource { Create: resourceAwsWafRegionalWebAclAssociationCreate, Read: resourceAwsWafRegionalWebAclAssociationRead, Delete: resourceAwsWafRegionalWebAclAssociationDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: map[string]*schema.Schema{ "web_acl_id": { diff --git a/aws/resource_aws_wafregional_web_acl_association_test.go b/aws/resource_aws_wafregional_web_acl_association_test.go index 20186062b4d..89de08fbc78 100644 --- a/aws/resource_aws_wafregional_web_acl_association_test.go +++ b/aws/resource_aws_wafregional_web_acl_association_test.go @@ -13,6 +13,8 @@ import ( ) func TestAccAWSWafRegionalWebAclAssociation_basic(t *testing.T) { + resourceName := "aws_wafregional_web_acl_association.foo" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -21,9 +23,14 @@ func TestAccAWSWafRegionalWebAclAssociation_basic(t *testing.T) { { Config: testAccCheckWafRegionalWebAclAssociationConfig_basic, Check: resource.ComposeTestCheckFunc( - testAccCheckWafRegionalWebAclAssociationExists("aws_wafregional_web_acl_association.foo"), + testAccCheckWafRegionalWebAclAssociationExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -47,6 +54,8 @@ func TestAccAWSWafRegionalWebAclAssociation_disappears(t *testing.T) { } func TestAccAWSWafRegionalWebAclAssociation_multipleAssociations(t *testing.T) { + resourceName := "aws_wafregional_web_acl_association.foo" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -55,10 +64,15 @@ func TestAccAWSWafRegionalWebAclAssociation_multipleAssociations(t *testing.T) { { Config: testAccCheckWafRegionalWebAclAssociationConfig_multipleAssociations, Check: resource.ComposeTestCheckFunc( - testAccCheckWafRegionalWebAclAssociationExists("aws_wafregional_web_acl_association.foo"), + testAccCheckWafRegionalWebAclAssociationExists(resourceName), testAccCheckWafRegionalWebAclAssociationExists("aws_wafregional_web_acl_association.bar"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -78,6 +92,11 @@ func TestAccAWSWafRegionalWebAclAssociation_ResourceArn_ApiGatewayStage(t *testi testAccCheckWafRegionalWebAclAssociationExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/aws/resource_aws_wafregional_web_acl_test.go b/aws/resource_aws_wafregional_web_acl_test.go index 9fecc6b533a..0373989ff77 100644 --- a/aws/resource_aws_wafregional_web_acl_test.go +++ b/aws/resource_aws_wafregional_web_acl_test.go @@ -131,18 +131,12 @@ func TestAccAWSWafRegionalWebAcl_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalWebAclExists(resourceName, &v), testAccMatchResourceAttrRegionalARN(resourceName, "arn", "waf-regional", regexp.MustCompile(`webacl/.+`)), - resource.TestCheckResourceAttr( - resourceName, "default_action.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "default_action.0.type", "ALLOW"), - resource.TestCheckResourceAttr( - resourceName, "name", wafAclName), - resource.TestCheckResourceAttr( - resourceName, "rule.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafAclName), - resource.TestCheckResourceAttr( - resourceName, "logging_configuration.#", "0"), + resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.0.type", "ALLOW"), + resource.TestCheckResourceAttr(resourceName, "name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", "0"), ), }, { @@ -154,6 +148,50 @@ func TestAccAWSWafRegionalWebAcl_basic(t *testing.T) { }) } +func TestAccAWSWafRegionalWebAcl_tags(t *testing.T) { + var v waf.WebACL + wafAclName := fmt.Sprintf("wafacl%s", acctest.RandString(5)) + resourceName := "aws_wafregional_web_acl.waf_acl" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSWafRegionalWebAclDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSWafRegionalWebAclConfigTags1(wafAclName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalWebAclExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSWafRegionalWebAclConfigTags2(wafAclName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalWebAclExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccAWSWafRegionalWebAclConfigTags1(wafAclName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalWebAclExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + func TestAccAWSWafRegionalWebAcl_createRateBased(t *testing.T) { var v waf.WebACL wafAclName := fmt.Sprintf("wafacl%s", acctest.RandString(5)) @@ -168,16 +206,11 @@ func TestAccAWSWafRegionalWebAcl_createRateBased(t *testing.T) { Config: testAccAWSWafRegionalWebAclConfigRateBased(wafAclName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalWebAclExists(resourceName, &v), - resource.TestCheckResourceAttr( - resourceName, "default_action.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "default_action.0.type", "ALLOW"), - resource.TestCheckResourceAttr( - resourceName, "name", wafAclName), - resource.TestCheckResourceAttr( - resourceName, "rule.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.0.type", "ALLOW"), + resource.TestCheckResourceAttr(resourceName, "name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafAclName), ), }, }, @@ -198,16 +231,11 @@ func TestAccAWSWafRegionalWebAcl_createGroup(t *testing.T) { Config: testAccAWSWafRegionalWebAclConfigGroup(wafAclName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalWebAclExists(resourceName, &v), - resource.TestCheckResourceAttr( - resourceName, "default_action.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "default_action.0.type", "ALLOW"), - resource.TestCheckResourceAttr( - resourceName, "name", wafAclName), - resource.TestCheckResourceAttr( - resourceName, "rule.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.0.type", "ALLOW"), + resource.TestCheckResourceAttr(resourceName, "name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafAclName), ), }, { @@ -234,32 +262,22 @@ func TestAccAWSWafRegionalWebAcl_changeNameForceNew(t *testing.T) { Config: testAccAWSWafRegionalWebAclConfig(wafAclName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalWebAclExists(resourceName, &before), - resource.TestCheckResourceAttr( - resourceName, "default_action.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "default_action.0.type", "ALLOW"), - resource.TestCheckResourceAttr( - resourceName, "name", wafAclName), - resource.TestCheckResourceAttr( - resourceName, "rule.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.0.type", "ALLOW"), + resource.TestCheckResourceAttr(resourceName, "name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafAclName), ), }, { Config: testAccAWSWafRegionalWebAclConfig_changeName(wafAclNewName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalWebAclExists(resourceName, &after), - resource.TestCheckResourceAttr( - resourceName, "default_action.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "default_action.0.type", "ALLOW"), - resource.TestCheckResourceAttr( - resourceName, "name", wafAclNewName), - resource.TestCheckResourceAttr( - resourceName, "rule.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafAclNewName), + resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.0.type", "ALLOW"), + resource.TestCheckResourceAttr(resourceName, "name", wafAclNewName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafAclNewName), ), }, { @@ -286,32 +304,22 @@ func TestAccAWSWafRegionalWebAcl_changeDefaultAction(t *testing.T) { Config: testAccAWSWafRegionalWebAclConfig(wafAclName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalWebAclExists(resourceName, &before), - resource.TestCheckResourceAttr( - resourceName, "default_action.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "default_action.0.type", "ALLOW"), - resource.TestCheckResourceAttr( - resourceName, "name", wafAclName), - resource.TestCheckResourceAttr( - resourceName, "rule.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.0.type", "ALLOW"), + resource.TestCheckResourceAttr(resourceName, "name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafAclName), ), }, { Config: testAccAWSWafRegionalWebAclConfig_changeDefaultAction(wafAclNewName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalWebAclExists(resourceName, &after), - resource.TestCheckResourceAttr( - resourceName, "default_action.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "default_action.0.type", "BLOCK"), - resource.TestCheckResourceAttr( - resourceName, "name", wafAclNewName), - resource.TestCheckResourceAttr( - resourceName, "rule.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafAclNewName), + resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.0.type", "BLOCK"), + resource.TestCheckResourceAttr(resourceName, "name", wafAclNewName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafAclNewName), ), }, { @@ -359,14 +367,10 @@ func TestAccAWSWafRegionalWebAcl_noRules(t *testing.T) { Config: testAccAWSWafRegionalWebAclConfig_noRules(wafAclName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalWebAclExists(resourceName, &v), - resource.TestCheckResourceAttr( - resourceName, "default_action.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "default_action.0.type", "ALLOW"), - resource.TestCheckResourceAttr( - resourceName, "name", wafAclName), - resource.TestCheckResourceAttr( - resourceName, "rule.#", "0"), + resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.0.type", "ALLOW"), + resource.TestCheckResourceAttr(resourceName, "name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "0"), ), }, { @@ -395,14 +399,10 @@ func TestAccAWSWafRegionalWebAcl_changeRules(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRuleExists("aws_wafregional_rule.wafrule", &r), testAccCheckAWSWafRegionalWebAclExists(resourceName, &v), - resource.TestCheckResourceAttr( - resourceName, "default_action.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "default_action.0.type", "ALLOW"), - resource.TestCheckResourceAttr( - resourceName, "name", wafAclName), - resource.TestCheckResourceAttr( - resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.0.type", "ALLOW"), + resource.TestCheckResourceAttr(resourceName, "name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), computeWafRegionalWebAclRuleIndex(&r.RuleId, 1, "REGULAR", "BLOCK", &idx), testCheckResourceAttrWithIndexesAddr(resourceName, "rule.%d.priority", &idx, "1"), ), @@ -411,14 +411,10 @@ func TestAccAWSWafRegionalWebAcl_changeRules(t *testing.T) { Config: testAccAWSWafRegionalWebAclConfig_changeRules(wafAclName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalWebAclExists(resourceName, &v), - resource.TestCheckResourceAttr( - resourceName, "default_action.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "default_action.0.type", "ALLOW"), - resource.TestCheckResourceAttr( - resourceName, "name", wafAclName), - resource.TestCheckResourceAttr( - resourceName, "rule.#", "2"), + resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "default_action.0.type", "ALLOW"), + resource.TestCheckResourceAttr(resourceName, "name", wafAclName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "2"), ), }, { @@ -602,13 +598,40 @@ func testAccCheckAWSWafRegionalWebAclExists(n string, v *waf.WebACL) resource.Te func testAccAWSWafRegionalWebAclConfig(name string) string { return fmt.Sprintf(` resource "aws_wafregional_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q +} + +resource "aws_wafregional_web_acl" "waf_acl" { + name = %[1]q + metric_name = %[1]q + + default_action { + type = "ALLOW" + } + + rule { + action { + type = "BLOCK" + } + + priority = 1 + rule_id = "${aws_wafregional_rule.wafrule.id}" + } +} +`, name) +} + +func testAccAWSWafRegionalWebAclConfigTags1(name, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_wafregional_rule" "wafrule" { + name = %[1]q + metric_name = %[1]q } resource "aws_wafregional_web_acl" "waf_acl" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q default_action { type = "ALLOW" @@ -622,23 +645,59 @@ resource "aws_wafregional_web_acl" "waf_acl" { priority = 1 rule_id = "${aws_wafregional_rule.wafrule.id}" } + + tags = { + %[2]q = %[3]q + } } -`, name, name, name, name) +`, name, tagKey1, tagValue1) +} + +func testAccAWSWafRegionalWebAclConfigTags2(name, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_wafregional_rule" "wafrule" { + name = %[1]q + metric_name = %[1]q +} + +resource "aws_wafregional_web_acl" "waf_acl" { + name = %[1]q + metric_name = %[1]q + + default_action { + type = "ALLOW" + } + + rule { + action { + type = "BLOCK" + } + + priority = 1 + rule_id = "${aws_wafregional_rule.wafrule.id}" + } + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, name, tagKey1, tagValue1, tagKey2, tagValue2) } func testAccAWSWafRegionalWebAclConfigRateBased(name string) string { return fmt.Sprintf(` resource "aws_wafregional_rate_based_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q rate_key = "IP" rate_limit = 2000 } resource "aws_wafregional_web_acl" "waf_acl" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q default_action { type = "ALLOW" @@ -654,19 +713,19 @@ resource "aws_wafregional_web_acl" "waf_acl" { rule_id = "${aws_wafregional_rate_based_rule.wafrule.id}" } } -`, name, name, name, name) +`, name) } func testAccAWSWafRegionalWebAclConfigGroup(name string) string { return fmt.Sprintf(` resource "aws_wafregional_rule_group" "wafrulegroup" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q } resource "aws_wafregional_web_acl" "waf_acl" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q default_action { type = "ALLOW" @@ -682,19 +741,19 @@ resource "aws_wafregional_web_acl" "waf_acl" { rule_id = "${aws_wafregional_rule_group.wafrulegroup.id}" # todo } } -`, name, name, name, name) +`, name) } func testAccAWSWafRegionalWebAclConfig_changeName(name string) string { return fmt.Sprintf(` resource "aws_wafregional_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q } resource "aws_wafregional_web_acl" "waf_acl" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q default_action { type = "ALLOW" @@ -709,19 +768,19 @@ resource "aws_wafregional_web_acl" "waf_acl" { rule_id = "${aws_wafregional_rule.wafrule.id}" } } -`, name, name, name, name) +`, name) } func testAccAWSWafRegionalWebAclConfig_changeDefaultAction(name string) string { return fmt.Sprintf(` resource "aws_wafregional_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q } resource "aws_wafregional_web_acl" "waf_acl" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q default_action { type = "BLOCK" @@ -736,32 +795,32 @@ resource "aws_wafregional_web_acl" "waf_acl" { rule_id = "${aws_wafregional_rule.wafrule.id}" } } -`, name, name, name, name) +`, name) } func testAccAWSWafRegionalWebAclConfig_noRules(name string) string { return fmt.Sprintf(` resource "aws_wafregional_web_acl" "waf_acl" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q default_action { type = "ALLOW" } } -`, name, name) +`, name) } func testAccAWSWafRegionalWebAclConfig_changeRules(name string) string { return fmt.Sprintf(` resource "aws_wafregional_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q } resource "aws_wafregional_web_acl" "waf_acl" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q default_action { type = "ALLOW" @@ -785,7 +844,7 @@ resource "aws_wafregional_web_acl" "waf_acl" { rule_id = "${aws_wafregional_rule.wafrule.id}" } } -`, name, name, name, name) +`, name) } func testAccAWSWafRegionalWebAclConfigLoggingConfiguration(rName string) string { diff --git a/aws/tagsECS.go b/aws/tagsECS.go deleted file mode 100644 index 67a924155ff..00000000000 --- a/aws/tagsECS.go +++ /dev/null @@ -1,78 +0,0 @@ -package aws - -import ( - "log" - "regexp" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ecs" -) - -// diffTags takes our tags locally and the ones remotely and returns -// the set of tags that must be created, and the set of tags that must -// be destroyed. -func diffTagsECS(oldTags, newTags []*ecs.Tag) ([]*ecs.Tag, []*ecs.Tag) { - // First, we're creating everything we have - create := make(map[string]interface{}) - for _, t := range newTags { - create[aws.StringValue(t.Key)] = aws.StringValue(t.Value) - } - - // Build the list of what to remove - var remove []*ecs.Tag - for _, t := range oldTags { - old, ok := create[aws.StringValue(t.Key)] - if !ok || old != aws.StringValue(t.Value) { - // Delete it! - remove = append(remove, t) - } else if ok { - // already present so remove from new - delete(create, aws.StringValue(t.Key)) - } - } - - return tagsFromMapECS(create), remove -} - -// tagsFromMap returns the tags for the given map of data. -func tagsFromMapECS(tagMap map[string]interface{}) []*ecs.Tag { - tags := make([]*ecs.Tag, 0, len(tagMap)) - for tagKey, tagValueRaw := range tagMap { - tag := &ecs.Tag{ - Key: aws.String(tagKey), - Value: aws.String(tagValueRaw.(string)), - } - if !tagIgnoredECS(tag) { - tags = append(tags, tag) - } - } - - return tags -} - -// tagsToMap turns the list of tags into a map. -func tagsToMapECS(tags []*ecs.Tag) map[string]string { - tagMap := make(map[string]string) - for _, tag := range tags { - if !tagIgnoredECS(tag) { - tagMap[aws.StringValue(tag.Key)] = aws.StringValue(tag.Value) - } - } - - return tagMap -} - -// compare a tag against a list of strings and checks if it should -// be ignored or not -func tagIgnoredECS(t *ecs.Tag) bool { - filter := []string{"^aws:"} - for _, v := range filter { - log.Printf("[DEBUG] Matching %v with %v\n", v, aws.StringValue(t.Key)) - r, _ := regexp.MatchString(v, aws.StringValue(t.Key)) - if r { - log.Printf("[DEBUG] Found AWS specific tag %s (val: %s), ignoring.\n", aws.StringValue(t.Key), aws.StringValue(t.Value)) - return true - } - } - return false -} diff --git a/aws/tagsECS_test.go b/aws/tagsECS_test.go deleted file mode 100644 index cc9289df4a7..00000000000 --- a/aws/tagsECS_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package aws - -import ( - "reflect" - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ecs" -) - -func TestDiffECSTags(t *testing.T) { - cases := []struct { - Old, New map[string]interface{} - Create, Remove map[string]string - }{ - // Add - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "foo": "bar", - "bar": "baz", - }, - Create: map[string]string{ - "bar": "baz", - }, - Remove: map[string]string{}, - }, - - // Modify - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "foo": "baz", - }, - Create: map[string]string{ - "foo": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Overlap - { - Old: map[string]interface{}{ - "foo": "bar", - "hello": "world", - }, - New: map[string]interface{}{ - "foo": "baz", - "hello": "world", - }, - Create: map[string]string{ - "foo": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Remove - { - Old: map[string]interface{}{ - "foo": "bar", - "bar": "baz", - }, - New: map[string]interface{}{ - "foo": "bar", - }, - Create: map[string]string{}, - Remove: map[string]string{ - "bar": "baz", - }, - }, - } - - for i, tc := range cases { - c, r := diffTagsECS(tagsFromMapECS(tc.Old), tagsFromMapECS(tc.New)) - cm := tagsToMapECS(c) - rm := tagsToMapECS(r) - if !reflect.DeepEqual(cm, tc.Create) { - t.Fatalf("%d: bad create: %#v", i, cm) - } - if !reflect.DeepEqual(rm, tc.Remove) { - t.Fatalf("%d: bad remove: %#v", i, rm) - } - } -} - -func TestIgnoringTagsECS(t *testing.T) { - ignoredTags := []*ecs.Tag{ - { - Key: aws.String("aws:cloudformation:logical-id"), - Value: aws.String("foo"), - }, - { - Key: aws.String("aws:foo:bar"), - Value: aws.String("baz"), - }, - } - for _, tag := range ignoredTags { - if !tagIgnoredECS(tag) { - t.Fatalf("Tag %v with value %v not ignored, but should be!", *tag.Key, *tag.Value) - } - } -} diff --git a/aws/tagsSNS.go b/aws/tagsSNS.go deleted file mode 100644 index d8862fc2f1f..00000000000 --- a/aws/tagsSNS.go +++ /dev/null @@ -1,118 +0,0 @@ -package aws - -import ( - "log" - "regexp" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/sns" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" -) - -// setTags is a helper to set the tags for a resource. It expects the -// tags field to be named "tags" and the ARN field to be named "arn". -func setTagsSNS(conn *sns.SNS, d *schema.ResourceData) error { - if d.HasChange("tags") { - oraw, nraw := d.GetChange("tags") - o := oraw.(map[string]interface{}) - n := nraw.(map[string]interface{}) - create, remove := diffTagsSNS(tagsFromMapSNS(o), tagsFromMapSNS(n)) - - // Set tags - if len(remove) > 0 { - log.Printf("[DEBUG] Removing tags: %#v", remove) - k := make([]*string, len(remove)) - for i, t := range remove { - k[i] = t.Key - } - - _, err := conn.UntagResource(&sns.UntagResourceInput{ - ResourceArn: aws.String(d.Get("arn").(string)), - TagKeys: k, - }) - if err != nil { - return err - } - } - if len(create) > 0 { - log.Printf("[DEBUG] Creating tags: %#v", create) - _, err := conn.TagResource(&sns.TagResourceInput{ - ResourceArn: aws.String(d.Get("arn").(string)), - Tags: create, - }) - if err != nil { - return err - } - } - } - - return nil -} - -// diffTags takes our tags locally and the ones remotely and returns -// the set of tags that must be created, and the set of tags that must -// be destroyed. -func diffTagsSNS(oldTags, newTags []*sns.Tag) ([]*sns.Tag, []*sns.Tag) { - // First, we're creating everything we have - create := make(map[string]interface{}) - for _, t := range newTags { - create[aws.StringValue(t.Key)] = aws.StringValue(t.Value) - } - - // Build the list of what to remove - var remove []*sns.Tag - for _, t := range oldTags { - old, ok := create[aws.StringValue(t.Key)] - if !ok || old != aws.StringValue(t.Value) { - remove = append(remove, t) - } else if ok { - // already present so remove from new - delete(create, aws.StringValue(t.Key)) - } - } - - return tagsFromMapSNS(create), remove -} - -// tagsFromMap returns the tags for the given map of data. -func tagsFromMapSNS(m map[string]interface{}) []*sns.Tag { - result := make([]*sns.Tag, 0, len(m)) - for k, v := range m { - t := &sns.Tag{ - Key: aws.String(k), - Value: aws.String(v.(string)), - } - if !tagIgnoredSNS(t) { - result = append(result, t) - } - } - - return result -} - -// tagsToMap turns the list of tags into a map. -func tagsToMapSNS(ts []*sns.Tag) map[string]string { - result := make(map[string]string) - for _, t := range ts { - if !tagIgnoredSNS(t) { - result[aws.StringValue(t.Key)] = aws.StringValue(t.Value) - } - } - - return result -} - -// compare a tag against a list of strings and checks if it should -// be ignored or not -func tagIgnoredSNS(t *sns.Tag) bool { - filter := []string{"^aws:"} - for _, v := range filter { - log.Printf("[DEBUG] Matching %v with %v\n", v, *t.Key) - r, _ := regexp.MatchString(v, *t.Key) - if r { - log.Printf("[DEBUG] Found AWS specific tag %s (val: %s), ignoring.\n", *t.Key, *t.Value) - return true - } - } - return false -} diff --git a/aws/tagsSNS_test.go b/aws/tagsSNS_test.go deleted file mode 100644 index 77a9c149750..00000000000 --- a/aws/tagsSNS_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package aws - -import ( - "reflect" - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/sns" -) - -func TestDiffSNSTags(t *testing.T) { - cases := []struct { - Old, New map[string]interface{} - Create, Remove map[string]string - }{ - // Add - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "foo": "bar", - "bar": "baz", - }, - Create: map[string]string{ - "bar": "baz", - }, - Remove: map[string]string{}, - }, - - // Modify - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "foo": "baz", - }, - Create: map[string]string{ - "foo": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Overlap - { - Old: map[string]interface{}{ - "foo": "bar", - "hello": "world", - }, - New: map[string]interface{}{ - "foo": "baz", - "hello": "world", - }, - Create: map[string]string{ - "foo": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Remove - { - Old: map[string]interface{}{ - "foo": "bar", - "bar": "baz", - }, - New: map[string]interface{}{ - "foo": "bar", - }, - Create: map[string]string{}, - Remove: map[string]string{ - "bar": "baz", - }, - }, - } - - for i, tc := range cases { - c, r := diffTagsSNS(tagsFromMapSNS(tc.Old), tagsFromMapSNS(tc.New)) - cm := tagsToMapSNS(c) - rm := tagsToMapSNS(r) - if !reflect.DeepEqual(cm, tc.Create) { - t.Fatalf("%d: bad create: %#v", i, cm) - } - if !reflect.DeepEqual(rm, tc.Remove) { - t.Fatalf("%d: bad remove: %#v", i, rm) - } - } -} - -func TestIgnoringTagsSNS(t *testing.T) { - ignoredTags := []*sns.Tag{ - { - Key: aws.String("aws:cloudformation:logical-id"), - Value: aws.String("foo"), - }, - { - Key: aws.String("aws:foo:bar"), - Value: aws.String("baz"), - }, - } - for _, tag := range ignoredTags { - if !tagIgnoredSNS(tag) { - t.Fatalf("Tag %v with value %v not ignored, but should be!", *tag.Key, *tag.Value) - } - } -} diff --git a/aws/tagsSecretsManager.go b/aws/tagsSecretsManager.go deleted file mode 100644 index e7547ad7fe6..00000000000 --- a/aws/tagsSecretsManager.go +++ /dev/null @@ -1,75 +0,0 @@ -package aws - -import ( - "log" - "regexp" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" -) - -// diffTags takes our tags locally and the ones remotely and returns -// the set of tags that must be created, and the set of tags that must -// be destroyed. -func diffTagsSecretsManager(oldTags, newTags []*secretsmanager.Tag) ([]*secretsmanager.Tag, []*secretsmanager.Tag) { - // First, we're creating everything we have - create := make(map[string]interface{}) - for _, t := range newTags { - create[*t.Key] = *t.Value - } - - // Build the list of what to remove - var remove []*secretsmanager.Tag - for _, t := range oldTags { - old, ok := create[*t.Key] - if !ok || old != *t.Value { - // Delete it! - remove = append(remove, t) - } - } - - return tagsFromMapSecretsManager(create), remove -} - -// tagsFromMap returns the tags for the given map of data. -func tagsFromMapSecretsManager(m map[string]interface{}) []*secretsmanager.Tag { - result := make([]*secretsmanager.Tag, 0, len(m)) - for k, v := range m { - t := &secretsmanager.Tag{ - Key: aws.String(k), - Value: aws.String(v.(string)), - } - if !tagIgnoredSecretsManager(t) { - result = append(result, t) - } - } - - return result -} - -// tagsToMap turns the list of tags into a map. -func tagsToMapSecretsManager(ts []*secretsmanager.Tag) map[string]string { - result := make(map[string]string) - for _, t := range ts { - if !tagIgnoredSecretsManager(t) { - result[*t.Key] = *t.Value - } - } - - return result -} - -// compare a tag against a list of strings and checks if it should -// be ignored or not -func tagIgnoredSecretsManager(t *secretsmanager.Tag) bool { - filter := []string{"^aws:"} - for _, v := range filter { - log.Printf("[DEBUG] Matching %v with %v\n", v, *t.Key) - r, _ := regexp.MatchString(v, *t.Key) - if r { - log.Printf("[DEBUG] Found AWS specific tag %s (val: %s), ignoring.\n", *t.Key, *t.Value) - return true - } - } - return false -} diff --git a/aws/tagsSecretsManager_test.go b/aws/tagsSecretsManager_test.go deleted file mode 100644 index d6eebe5343c..00000000000 --- a/aws/tagsSecretsManager_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package aws - -import ( - "reflect" - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/secretsmanager" -) - -// go test -v -run="TestDiffSecretsManagerTags" -func TestDiffSecretsManagerTags(t *testing.T) { - cases := []struct { - Old, New map[string]interface{} - Create, Remove map[string]string - }{ - // Basic add/remove - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "bar": "baz", - }, - Create: map[string]string{ - "bar": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Modify - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "foo": "baz", - }, - Create: map[string]string{ - "foo": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - } - - for i, tc := range cases { - c, r := diffTagsSecretsManager(tagsFromMapSecretsManager(tc.Old), tagsFromMapSecretsManager(tc.New)) - cm := tagsToMapSecretsManager(c) - rm := tagsToMapSecretsManager(r) - if !reflect.DeepEqual(cm, tc.Create) { - t.Fatalf("%d: bad create: %#v", i, cm) - } - if !reflect.DeepEqual(rm, tc.Remove) { - t.Fatalf("%d: bad remove: %#v", i, rm) - } - } -} - -// go test -v -run="TestIgnoringTagsSecretsManager" -func TestIgnoringTagsSecretsManager(t *testing.T) { - var ignoredTags []*secretsmanager.Tag - ignoredTags = append(ignoredTags, &secretsmanager.Tag{ - Key: aws.String("aws:cloudformation:logical-id"), - Value: aws.String("foo"), - }) - ignoredTags = append(ignoredTags, &secretsmanager.Tag{ - Key: aws.String("aws:foo:bar"), - Value: aws.String("baz"), - }) - for _, tag := range ignoredTags { - if !tagIgnoredSecretsManager(tag) { - t.Fatalf("Tag %v with value %v not ignored, but should be!", *tag.Key, *tag.Value) - } - } -} diff --git a/aws/tagsSfn.go b/aws/tagsSfn.go deleted file mode 100644 index 093fbc78fa4..00000000000 --- a/aws/tagsSfn.go +++ /dev/null @@ -1,78 +0,0 @@ -package aws - -import ( - "log" - "regexp" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/sfn" -) - -// diffTags takes our tags locally and the ones remotely and returns -// the set of tags that must be created, and the set of tags that must -// be destroyed. -func diffTagsSfn(oldTags, newTags []*sfn.Tag) ([]*sfn.Tag, []*sfn.Tag) { - // First, we're creating everything we have - create := make(map[string]interface{}) - for _, t := range newTags { - create[aws.StringValue(t.Key)] = aws.StringValue(t.Value) - } - - // Build the list of what to remove - var remove []*sfn.Tag - for _, t := range oldTags { - old, ok := create[aws.StringValue(t.Key)] - if !ok || old != aws.StringValue(t.Value) { - // Delete it! - remove = append(remove, t) - } else if ok { - // already present so remove from new - delete(create, aws.StringValue(t.Key)) - } - } - - return tagsFromMapSfn(create), remove -} - -// tagsFromMap returns the tags for the given map of data. -func tagsFromMapSfn(tagMap map[string]interface{}) []*sfn.Tag { - tags := make([]*sfn.Tag, 0, len(tagMap)) - for tagKey, tagValueRaw := range tagMap { - tag := &sfn.Tag{ - Key: aws.String(tagKey), - Value: aws.String(tagValueRaw.(string)), - } - if !tagIgnoredSfn(tag) { - tags = append(tags, tag) - } - } - - return tags -} - -// tagsToMap turns the list of tags into a map. -func tagsToMapSfn(tags []*sfn.Tag) map[string]string { - tagMap := make(map[string]string) - for _, tag := range tags { - if !tagIgnoredSfn(tag) { - tagMap[aws.StringValue(tag.Key)] = aws.StringValue(tag.Value) - } - } - - return tagMap -} - -// compare a tag against a list of strings and checks if it should -// be ignored or not -func tagIgnoredSfn(t *sfn.Tag) bool { - filter := []string{"^aws:"} - for _, v := range filter { - log.Printf("[DEBUG] Matching %v with %v\n", v, aws.StringValue(t.Key)) - r, _ := regexp.MatchString(v, aws.StringValue(t.Key)) - if r { - log.Printf("[DEBUG] Found AWS specific tag %s (val: %s), ignoring.\n", aws.StringValue(t.Key), aws.StringValue(t.Value)) - return true - } - } - return false -} diff --git a/aws/tagsSfn_test.go b/aws/tagsSfn_test.go deleted file mode 100644 index cdb727ef7ec..00000000000 --- a/aws/tagsSfn_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package aws - -import ( - "reflect" - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/sfn" -) - -func TestDiffSfnTags(t *testing.T) { - cases := []struct { - Old, New map[string]interface{} - Create, Remove map[string]string - }{ - // Add - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "foo": "bar", - "bar": "baz", - }, - Create: map[string]string{ - "bar": "baz", - }, - Remove: map[string]string{}, - }, - - // Modify - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "foo": "baz", - }, - Create: map[string]string{ - "foo": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Overlap - { - Old: map[string]interface{}{ - "foo": "bar", - "hello": "world", - }, - New: map[string]interface{}{ - "foo": "baz", - "hello": "world", - }, - Create: map[string]string{ - "foo": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Remove - { - Old: map[string]interface{}{ - "foo": "bar", - "bar": "baz", - }, - New: map[string]interface{}{ - "foo": "bar", - }, - Create: map[string]string{}, - Remove: map[string]string{ - "bar": "baz", - }, - }, - } - - for i, tc := range cases { - c, r := diffTagsSfn(tagsFromMapSfn(tc.Old), tagsFromMapSfn(tc.New)) - cm := tagsToMapSfn(c) - rm := tagsToMapSfn(r) - if !reflect.DeepEqual(cm, tc.Create) { - t.Fatalf("%d: bad create: %#v", i, cm) - } - if !reflect.DeepEqual(rm, tc.Remove) { - t.Fatalf("%d: bad remove: %#v", i, rm) - } - } -} - -func TestIgnoringTagsSfn(t *testing.T) { - ignoredTags := []*sfn.Tag{ - { - Key: aws.String("aws:cloudformation:logical-id"), - Value: aws.String("foo"), - }, - { - Key: aws.String("aws:foo:bar"), - Value: aws.String("baz"), - }, - } - for _, tag := range ignoredTags { - if !tagIgnoredSfn(tag) { - t.Fatalf("Tag %v with value %v not ignored, but should be!", *tag.Key, *tag.Value) - } - } -} diff --git a/aws/tagsTransfer.go b/aws/tagsTransfer.go deleted file mode 100644 index 941e542fc92..00000000000 --- a/aws/tagsTransfer.go +++ /dev/null @@ -1,118 +0,0 @@ -package aws - -import ( - "log" - "regexp" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/transfer" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" -) - -// setTags is a helper to set the tags for a resource. It expects the -// tags field to be named "tags" -func setTagsTransfer(conn *transfer.Transfer, d *schema.ResourceData) error { - if d.HasChange("tags") { - oraw, nraw := d.GetChange("tags") - o := oraw.(map[string]interface{}) - n := nraw.(map[string]interface{}) - create, remove := diffTagsTransfer(tagsFromMapTransfer(o), tagsFromMapTransfer(n)) - - // Set tags - if len(remove) > 0 { - log.Printf("[DEBUG] Removing tags: %#v", remove) - k := make([]*string, len(remove)) - for i, t := range remove { - k[i] = t.Key - } - - _, err := conn.UntagResource(&transfer.UntagResourceInput{ - Arn: aws.String(d.Get("arn").(string)), - TagKeys: k, - }) - if err != nil { - return err - } - } - if len(create) > 0 { - log.Printf("[DEBUG] Creating tags: %#v", create) - _, err := conn.TagResource(&transfer.TagResourceInput{ - Arn: aws.String(d.Get("arn").(string)), - Tags: create, - }) - if err != nil { - return err - } - } - } - - return nil -} - -// diffTags takes our tags locally and the ones remotely and returns -// the set of tags that must be created, and the set of tags that must -// be destroyed. -func diffTagsTransfer(oldTags, newTags []*transfer.Tag) ([]*transfer.Tag, []*transfer.Tag) { - // First, we're creating everything we have - create := make(map[string]interface{}) - for _, t := range newTags { - create[aws.StringValue(t.Key)] = aws.StringValue(t.Value) - } - - // Build the list of what to remove - var remove []*transfer.Tag - for _, t := range oldTags { - old, ok := create[aws.StringValue(t.Key)] - if !ok || old != aws.StringValue(t.Value) { - // Delete it! - remove = append(remove, t) - } else if ok { - // already present so remove from new - delete(create, aws.StringValue(t.Key)) - } - } - - return tagsFromMapTransfer(create), remove -} - -// tagsFromMap returns the tags for the given map of data. -func tagsFromMapTransfer(m map[string]interface{}) []*transfer.Tag { - result := make([]*transfer.Tag, 0, len(m)) - for k, v := range m { - t := &transfer.Tag{ - Key: aws.String(k), - Value: aws.String(v.(string)), - } - if !tagIgnoredTransfer(t) { - result = append(result, t) - } - } - - return result -} - -// tagsToMap turns the list of tags into a map. -func tagsToMapTransfer(ts []*transfer.Tag) map[string]string { - result := make(map[string]string) - for _, t := range ts { - if !tagIgnoredTransfer(t) { - result[aws.StringValue(t.Key)] = aws.StringValue(t.Value) - } - } - - return result -} - -// compare a tag against a list of strings and checks if it should -// be ignored or not -func tagIgnoredTransfer(t *transfer.Tag) bool { - filter := []string{"^aws:"} - for _, v := range filter { - log.Printf("[DEBUG] Matching %v with %v\n", v, aws.StringValue(t.Key)) - if r, _ := regexp.MatchString(v, aws.StringValue(t.Key)); r { - log.Printf("[DEBUG] Found AWS specific tag %s (val: %s), ignoring.\n", aws.StringValue(t.Key), aws.StringValue(t.Value)) - return true - } - } - return false -} diff --git a/aws/tagsTransfer_test.go b/aws/tagsTransfer_test.go deleted file mode 100644 index abb8cf19638..00000000000 --- a/aws/tagsTransfer_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package aws - -import ( - "reflect" - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/transfer" -) - -// go test -v -run="TestDiffTransferTags" -func TestDiffTransferTags(t *testing.T) { - cases := []struct { - Old, New map[string]interface{} - Create, Remove map[string]string - }{ - // Basic add/remove - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "bar": "baz", - }, - Create: map[string]string{ - "bar": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Modify - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "foo": "baz", - }, - Create: map[string]string{ - "foo": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Overlap - { - Old: map[string]interface{}{ - "foo": "bar", - "hello": "world", - }, - New: map[string]interface{}{ - "foo": "baz", - "hello": "world", - }, - Create: map[string]string{ - "foo": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Remove - { - Old: map[string]interface{}{ - "foo": "bar", - "bar": "baz", - }, - New: map[string]interface{}{ - "foo": "bar", - }, - Create: map[string]string{}, - Remove: map[string]string{ - "bar": "baz", - }, - }, - } - - for i, tc := range cases { - c, r := diffTagsTransfer(tagsFromMapTransfer(tc.Old), tagsFromMapTransfer(tc.New)) - cm := tagsToMapTransfer(c) - rm := tagsToMapTransfer(r) - if !reflect.DeepEqual(cm, tc.Create) { - t.Fatalf("%d: bad create: %#v", i, cm) - } - if !reflect.DeepEqual(rm, tc.Remove) { - t.Fatalf("%d: bad remove: %#v", i, rm) - } - } -} - -// go test -v -run="TestIgnoringTagsTransfer" -func TestIgnoringTagsTransfer(t *testing.T) { - var ignoredTags []*transfer.Tag - ignoredTags = append(ignoredTags, &transfer.Tag{ - Key: aws.String("aws:cloudformation:logical-id"), - Value: aws.String("foo"), - }) - ignoredTags = append(ignoredTags, &transfer.Tag{ - Key: aws.String("aws:foo:bar"), - Value: aws.String("baz"), - }) - for _, tag := range ignoredTags { - if !tagIgnoredTransfer(tag) { - t.Fatalf("Tag %v with value %v not ignored, but should be!", *tag.Key, *tag.Value) - } - } -} diff --git a/aws/waf_helpers.go b/aws/waf_helpers.go index 0e7b3437536..917f44f480f 100644 --- a/aws/waf_helpers.go +++ b/aws/waf_helpers.go @@ -18,7 +18,10 @@ func wafSizeConstraintSetSchema() map[string]*schema.Schema { Required: true, ForceNew: true, }, - + "arn": { + Type: schema.TypeString, + Computed: true, + }, "size_constraints": { Type: schema.TypeSet, Optional: true, diff --git a/website/docs/r/api_gateway_domain_name.html.markdown b/website/docs/r/api_gateway_domain_name.html.markdown index 1178931316a..00d8a29aa37 100644 --- a/website/docs/r/api_gateway_domain_name.html.markdown +++ b/website/docs/r/api_gateway_domain_name.html.markdown @@ -29,6 +29,12 @@ the `regional_domain_name` attribute. ~> **Note:** API Gateway requires the use of AWS Certificate Manager (ACM) certificates instead of Identity and Access Management (IAM) certificates in regions that support ACM. Regions that support ACM can be found in the [Regions and Endpoints Documentation](https://docs.aws.amazon.com/general/latest/gr/rande.html#acm_region). To import an existing private key and certificate into ACM or request an ACM certificate, see the [`aws_acm_certificate` resource](/docs/providers/aws/r/acm_certificate.html). +~> **Note:** The `aws_api_gateway_domain_name` resource expects dependency on the `aws_acm_certificate_validation` as +only verified certificates can be used. This can be made either explicitly by adding the +`depends_on = [aws_acm_certificate_validation.cert]` attribute. Or implicitly by referring certificate ARN +from the validation resource where it will be available after the resource creation: +`regional_certificate_arn = aws_acm_certificate_validation.cert.certificate_arn`. + ~> **Note:** All arguments including the private key will be stored in the raw state as plain-text. [Read more about sensitive data in state](/docs/state/sensitive-data.html). diff --git a/website/docs/r/api_gateway_integration_response.html.markdown b/website/docs/r/api_gateway_integration_response.html.markdown index dba69bd664d..39f806030f5 100644 --- a/website/docs/r/api_gateway_integration_response.html.markdown +++ b/website/docs/r/api_gateway_integration_response.html.markdown @@ -55,7 +55,7 @@ resource "aws_api_gateway_integration_response" "MyDemoIntegrationResponse" { status_code = "${aws_api_gateway_method_response.response_200.status_code}" # Transforms the backend JSON response to XML - response_templates { + response_templates = { "application/xml" = < diff --git a/website/docs/r/api_gateway_rest_api.html.markdown b/website/docs/r/api_gateway_rest_api.html.markdown index da857979198..b46c7eca6dc 100644 --- a/website/docs/r/api_gateway_rest_api.html.markdown +++ b/website/docs/r/api_gateway_rest_api.html.markdown @@ -45,6 +45,7 @@ The following arguments are supported: * `body` - (Optional) An OpenAPI specification that defines the set of routes and integrations to create as part of the REST API. * `policy` - (Optional) JSON formatted policy document that controls access to the API Gateway. For more information about building AWS IAM policy documents with Terraform, see the [AWS IAM Policy Document Guide](https://learn.hashicorp.com/terraform/aws/iam-policy) * `api_key_source` - (Optional) The source of the API key for requests. Valid values are HEADER (default) and AUTHORIZER. +* `tags` - (Optional) Key-value mapping of resource tags __Note__: If the `body` argument is provided, the OpenAPI specification will be used to configure the resources, methods and integrations for the Rest API. If this argument is provided, the following resources should not be managed as separate ones, as updates may cause manual resource updates to be overwritten: @@ -71,6 +72,7 @@ In addition to all arguments above, the following attributes are exported: * `execution_arn` - The execution ARN part to be used in [`lambda_permission`](/docs/providers/aws/r/lambda_permission.html)'s `source_arn` when allowing API Gateway to invoke a Lambda function, e.g. `arn:aws:execute-api:eu-west-2:123456789012:z4675bid1j`, which can be concatenated with allowed stage, method and resource path. +* `arn` - Amazon Resource Name (ARN) ## Import diff --git a/website/docs/r/db_instance.html.markdown b/website/docs/r/db_instance.html.markdown index 0ae598a5ae4..d47012a0484 100644 --- a/website/docs/r/db_instance.html.markdown +++ b/website/docs/r/db_instance.html.markdown @@ -89,6 +89,7 @@ between `0` and `35`. Must be greater than `0` if the database is used as a sour * `backup_window` - (Optional) The daily time range (in UTC) during which automated backups are created if they are enabled. Example: "09:46-10:16". Must not overlap with `maintenance_window`. +* `ca_cert_identifier` - (Optional) The identifier of the CA certificate for the DB instance. * `character_set_name` - (Optional) The character set name to use for DB encoding in Oracle instances. This can't be changed. See [Oracle Character Sets Supported in Amazon diff --git a/website/docs/r/efs_file_system.html.markdown b/website/docs/r/efs_file_system.html.markdown index 9fbc9428c11..8e9eda97d82 100644 --- a/website/docs/r/efs_file_system.html.markdown +++ b/website/docs/r/efs_file_system.html.markdown @@ -55,7 +55,7 @@ system creation. By default generated by Terraform. See [Elastic File System] ### Lifecycle Policy Arguments For **lifecycle_policy** the following attributes are supported: -* `transition_to_ia` - (Optional) Indicates how long it takes to transition files to the IA storage class. Valid values: `AFTER_14_DAYS`, `AFTER_30_DAYS`, `AFTER_60_DAYS`, or `AFTER_90_DAYS`. +* `transition_to_ia` - (Optional) Indicates how long it takes to transition files to the IA storage class. Valid values: `AFTER_7_DAYS`, `AFTER_14_DAYS`, `AFTER_30_DAYS`, `AFTER_60_DAYS`, or `AFTER_90_DAYS`. ## Attributes Reference diff --git a/website/docs/r/mq_broker.html.markdown b/website/docs/r/mq_broker.html.markdown index 8b9f08f5ccd..10b85163d84 100644 --- a/website/docs/r/mq_broker.html.markdown +++ b/website/docs/r/mq_broker.html.markdown @@ -60,7 +60,7 @@ The following arguments are supported: * `deployment_mode` - (Optional) The deployment mode of the broker. Supported: `SINGLE_INSTANCE` and `ACTIVE_STANDBY_MULTI_AZ`. Defaults to `SINGLE_INSTANCE`. * `encryption_options` - (Optional) Configuration block containing encryption options. See below. * `engine_type` - (Required) The type of broker engine. Currently, Amazon MQ supports only `ActiveMQ`. -* `engine_version` - (Required) The version of the broker engine. Currently, See the [AmazonMQ Broker Engine docs](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/broker-engine.html) for supported versions. +* `engine_version` - (Required) The version of the broker engine. See the [AmazonMQ Broker Engine docs](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/broker-engine.html) for supported versions. * `host_instance_type` - (Required) The broker's instance type. e.g. `mq.t2.micro` or `mq.m4.large` * `publicly_accessible` - (Optional) Whether to enable connections from applications outside of the VPC that hosts the broker's subnets. * `security_groups` - (Required) The list of security group IDs assigned to the broker. diff --git a/website/docs/r/s3_bucket_inventory.html.markdown b/website/docs/r/s3_bucket_inventory.html.markdown index f482aa183ef..024ed15e434 100644 --- a/website/docs/r/s3_bucket_inventory.html.markdown +++ b/website/docs/r/s3_bucket_inventory.html.markdown @@ -81,22 +81,23 @@ resource "aws_s3_bucket_inventory" "test-prefix" { The following arguments are supported: -* `bucket` - (Required) The name of the bucket to put inventory configuration. +* `bucket` - (Required) The name of the bucket where the inventory configuration will be stored. * `name` - (Required) Unique identifier of the inventory configuration for the bucket. -* `included_object_versions` - (Required) Object filtering that accepts a prefix (documented below). Can be `All` or `Current`. -* `schedule` - (Required) Contains the frequency for generating inventory results (documented below). -* `destination` - (Required) Destination bucket where inventory list files are written (documented below). -* `enabled` - (Optional, Default: true) Specifies whether the inventory is enabled or disabled. -* `filter` - (Optional) Object filtering that accepts a prefix (documented below). -* `optional_fields` - (Optional) Contains the optional fields that are included in the inventory results. +* `included_object_versions` - (Required) Object versions to include in the inventory list. Valid values: `All`, `Current`. +* `schedule` - (Required) Specifies the schedule for generating inventory results (documented below). +* `destination` - (Required) Contains information about where to publish the inventory results (documented below). +* `enabled` - (Optional, Default: `true`) Specifies whether the inventory is enabled or disabled. +* `filter` - (Optional) Specifies an inventory filter. The inventory only includes objects that meet the filter's criteria (documented below). +* `optional_fields` - (Optional) List of optional fields that are included in the inventory results. +Valid values: `Size`, `LastModifiedDate`, `StorageClass`, `ETag`, `IsMultipartUploaded`, `ReplicationStatus`, `EncryptionStatus`, `ObjectLockRetainUntilDate`, `ObjectLockMode`, `ObjectLockLegalHoldStatus`, `IntelligentTieringAccessTier`. The `filter` configuration supports the following: -* `prefix` - (Optional) Object prefix for filtering (singular). +* `prefix` - (Optional) The prefix that an object must have to be included in the inventory results. The `schedule` configuration supports the following: -* `frequency` - (Required) Specifies how frequently inventory results are produced. Can be `Daily` or `Weekly`. +* `frequency` - (Required) Specifies how frequently inventory results are produced. Valid values: `Daily`, `Weekly`. The `destination` configuration supports the following: diff --git a/website/docs/r/waf_geo_match_set.html.markdown b/website/docs/r/waf_geo_match_set.html.markdown index a02daa818db..05c2e31fa12 100644 --- a/website/docs/r/waf_geo_match_set.html.markdown +++ b/website/docs/r/waf_geo_match_set.html.markdown @@ -53,3 +53,12 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: * `id` - The ID of the WAF GeoMatchSet. +* `arn` - Amazon Resource Name (ARN) + +## Import + +WAF Geo Match Set can be imported using their ID, e.g. + +``` +$ terraform import aws_waf_geo_match_set.example a1b2c3d4-d5f6-7777-8888-9999aaaabbbbcccc +``` diff --git a/website/docs/r/waf_regex_match_set.html.markdown b/website/docs/r/waf_regex_match_set.html.markdown index b43b798f9e5..fad1c7ed18c 100644 --- a/website/docs/r/waf_regex_match_set.html.markdown +++ b/website/docs/r/waf_regex_match_set.html.markdown @@ -66,3 +66,12 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: * `id` - The ID of the WAF Regex Match Set. +* `arn` - Amazon Resource Name (ARN) + +## Import + +WAF Regex Match Set can be imported using their ID, e.g. + +``` +$ terraform import aws_waf_regex_match_set.example a1b2c3d4-d5f6-7777-8888-9999aaaabbbbcccc +``` \ No newline at end of file diff --git a/website/docs/r/waf_regex_pattern_set.html.markdown b/website/docs/r/waf_regex_pattern_set.html.markdown index b0625705aad..4b41feb3117 100644 --- a/website/docs/r/waf_regex_pattern_set.html.markdown +++ b/website/docs/r/waf_regex_pattern_set.html.markdown @@ -31,3 +31,12 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: * `id` - The ID of the WAF Regex Pattern Set. +* `arn` - Amazon Resource Name (ARN) + +## Import + +AWS WAF Regex Pattern Set can be imported using their ID, e.g. + +``` +$ terraform import aws_waf_regex_pattern_set.example a1b2c3d4-d5f6-7777-8888-9999aaaabbbbcccc +``` diff --git a/website/docs/r/waf_size_constraint_set.html.markdown b/website/docs/r/waf_size_constraint_set.html.markdown index b67da4c0a98..4b26a49b26b 100644 --- a/website/docs/r/waf_size_constraint_set.html.markdown +++ b/website/docs/r/waf_size_constraint_set.html.markdown @@ -70,3 +70,12 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: * `id` - The ID of the WAF Size Constraint Set. +* `arn` - Amazon Resource Name (ARN) + +## Import + +AWS WAF Size Constraint Set can be imported using their ID, e.g. + +``` +$ terraform import aws_waf_size_constraint_set.example a1b2c3d4-d5f6-7777-8888-9999aaaabbbbcccc +``` diff --git a/website/docs/r/waf_xss_match_set.html.markdown b/website/docs/r/waf_xss_match_set.html.markdown index 334d332e74a..001eef59691 100644 --- a/website/docs/r/waf_xss_match_set.html.markdown +++ b/website/docs/r/waf_xss_match_set.html.markdown @@ -71,3 +71,12 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: * `id` - The ID of the WAF XssMatchSet. +* `arn` - Amazon Resource Name (ARN) + +## Import + +WAF XSS Match Set can be imported using their ID, e.g. + +``` +$ terraform import aws_waf_xss_match_set.example a1b2c3d4-d5f6-7777-8888-9999aaaabbbbcccc +``` \ No newline at end of file diff --git a/website/docs/r/wafregional_rate_based_rule.html.markdown b/website/docs/r/wafregional_rate_based_rule.html.markdown index bca2206b2a3..71f05a7ce0b 100644 --- a/website/docs/r/wafregional_rate_based_rule.html.markdown +++ b/website/docs/r/wafregional_rate_based_rule.html.markdown @@ -47,6 +47,7 @@ The following arguments are supported: * `rate_key` - (Required) Valid value is IP. * `rate_limit` - (Required) The maximum number of requests, which have an identical value in the field specified by the RateKey, allowed in a five-minute period. Minimum value is 100. * `predicate` - (Optional) The objects to include in a rule (documented below). +* `tags` - (Optional) Key-value mapping of resource tags ## Nested Blocks @@ -67,7 +68,8 @@ See the [WAF Documentation](https://docs.aws.amazon.com/waf/latest/APIReference/ In addition to all arguments above, the following attributes are exported: -* `id` - The ID of the WAF Regional rate based rule. +* `id` - The ID of the WAF Regional Rate Based Rule. +* `arn` - The ARN of the WAF Regional Rate Based Rule. ## Import diff --git a/website/docs/r/wafregional_rule.html.markdown b/website/docs/r/wafregional_rule.html.markdown index 3c7eff003b7..df887bcf187 100644 --- a/website/docs/r/wafregional_rule.html.markdown +++ b/website/docs/r/wafregional_rule.html.markdown @@ -41,6 +41,7 @@ The following arguments are supported: * `name` - (Required) The name or description of the rule. * `metric_name` - (Required) The name or description for the Amazon CloudWatch metric of this rule. * `predicate` - (Optional) The objects to include in a rule (documented below). +* `tags` - (Optional) Key-value mapping of resource tags ## Nested Fields @@ -61,6 +62,7 @@ See the [WAF Documentation](https://docs.aws.amazon.com/waf/latest/APIReference/ In addition to all arguments above, the following attributes are exported: * `id` - The ID of the WAF Regional Rule. +* `arn` - The ARN of the WAF Regional Rule. ## Import diff --git a/website/docs/r/wafregional_rule_group.html.markdown b/website/docs/r/wafregional_rule_group.html.markdown index 17049bee2fa..bd98bccf8a0 100644 --- a/website/docs/r/wafregional_rule_group.html.markdown +++ b/website/docs/r/wafregional_rule_group.html.markdown @@ -40,6 +40,7 @@ The following arguments are supported: * `name` - (Required) A friendly name of the rule group * `metric_name` - (Required) A friendly name for the metrics from the rule group * `activated_rule` - (Optional) A list of activated rules, see below +* `tags` - (Optional) Key-value mapping of resource tags ## Nested Blocks @@ -58,6 +59,7 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: * `id` - The ID of the WAF Regional Rule Group. +* `arn` - The ARN of the WAF Regional Rule Group. ## Import diff --git a/website/docs/r/wafregional_web_acl.html.markdown b/website/docs/r/wafregional_web_acl.html.markdown index 3899775e402..90e2981be9c 100644 --- a/website/docs/r/wafregional_web_acl.html.markdown +++ b/website/docs/r/wafregional_web_acl.html.markdown @@ -112,6 +112,7 @@ The following arguments are supported: * `name` - (Required) The name or description of the web ACL. * `logging_configuration` - (Optional) Configuration block to enable WAF logging. Detailed below. * `rule` - (Optional) Set of configuration blocks containing rules for the web ACL. Detailed below. +* `tags` - (Optional) Key-value mapping of resource tags ### `default_action` Configuration Block diff --git a/website/docs/r/wafregional_web_acl_association.html.markdown b/website/docs/r/wafregional_web_acl_association.html.markdown index a37e4d835d9..ce6f4eedddb 100644 --- a/website/docs/r/wafregional_web_acl_association.html.markdown +++ b/website/docs/r/wafregional_web_acl_association.html.markdown @@ -94,3 +94,11 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: * `id` - The ID of the association + +## Import + +WAF Regional Web ACL Association can be imported using their `web_acl_id:resource_arn`, e.g. + +``` +$ terraform import aws_wafregional_web_acl_association.foo web_acl_id:resource_arn +``` \ No newline at end of file