From 74be9191a37ebdf1077d4ee08a9dd7332cbb32dd Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Wed, 13 Nov 2019 20:18:11 -0500 Subject: [PATCH 1/2] internal/keyvaluetags: Fix dlm service tagging for resource tags The service did not previously support resource tagging (slice based Tag types were used for other structures not relevant to the purpose of this package). Here we generate all functionality related to DLM resource tagging including listing and updating. Updated via: ``` make gen ``` --- .../keyvaluetags/generators/listtags/main.go | 1 + .../generators/servicetags/main.go | 2 +- .../generators/updatetags/main.go | 1 + aws/internal/keyvaluetags/key_value_tags.go | 2 +- aws/internal/keyvaluetags/list_tags_gen.go | 18 +++++++++ .../service_generation_customizations.go | 3 ++ aws/internal/keyvaluetags/service_tags_gen.go | 38 +++++-------------- aws/internal/keyvaluetags/update_tags_gen.go | 37 ++++++++++++++++++ 8 files changed, 72 insertions(+), 30 deletions(-) diff --git a/aws/internal/keyvaluetags/generators/listtags/main.go b/aws/internal/keyvaluetags/generators/listtags/main.go index ea6a7fc65cb..ba44df015c2 100644 --- a/aws/internal/keyvaluetags/generators/listtags/main.go +++ b/aws/internal/keyvaluetags/generators/listtags/main.go @@ -40,6 +40,7 @@ var serviceNames = []string{ "dax", "devicefarm", "directoryservice", + "dlm", "docdb", "dynamodb", "ecr", diff --git a/aws/internal/keyvaluetags/generators/servicetags/main.go b/aws/internal/keyvaluetags/generators/servicetags/main.go index a074e68aad8..3a9fab9f879 100644 --- a/aws/internal/keyvaluetags/generators/servicetags/main.go +++ b/aws/internal/keyvaluetags/generators/servicetags/main.go @@ -40,7 +40,6 @@ var sliceServiceNames = []string{ "devicefarm", "directconnect", "directoryservice", - "dlm", "docdb", "dynamodb", "ec2", @@ -103,6 +102,7 @@ var mapServiceNames = []string{ "codecommit", "cognitoidentity", "cognitoidentityprovider", + "dlm", "eks", "glacier", "glue", diff --git a/aws/internal/keyvaluetags/generators/updatetags/main.go b/aws/internal/keyvaluetags/generators/updatetags/main.go index 9e8cef5c391..f218cc8d364 100644 --- a/aws/internal/keyvaluetags/generators/updatetags/main.go +++ b/aws/internal/keyvaluetags/generators/updatetags/main.go @@ -44,6 +44,7 @@ var serviceNames = []string{ "devicefarm", "directconnect", "directoryservice", + "dlm", "docdb", "dynamodb", "ec2", diff --git a/aws/internal/keyvaluetags/key_value_tags.go b/aws/internal/keyvaluetags/key_value_tags.go index 63e9ad5fc1d..1e4e5be9310 100644 --- a/aws/internal/keyvaluetags/key_value_tags.go +++ b/aws/internal/keyvaluetags/key_value_tags.go @@ -1,5 +1,5 @@ -//go:generate go run generators/listtags/main.go //go:generate go run generators/servicetags/main.go +//go:generate go run generators/listtags/main.go //go:generate go run generators/updatetags/main.go package keyvaluetags diff --git a/aws/internal/keyvaluetags/list_tags_gen.go b/aws/internal/keyvaluetags/list_tags_gen.go index 71899c8a4f7..387284b4d8e 100644 --- a/aws/internal/keyvaluetags/list_tags_gen.go +++ b/aws/internal/keyvaluetags/list_tags_gen.go @@ -27,6 +27,7 @@ import ( "github.com/aws/aws-sdk-go/service/dax" "github.com/aws/aws-sdk-go/service/devicefarm" "github.com/aws/aws-sdk-go/service/directoryservice" + "github.com/aws/aws-sdk-go/service/dlm" "github.com/aws/aws-sdk-go/service/docdb" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/ecr" @@ -468,6 +469,23 @@ func DirectoryserviceListTags(conn *directoryservice.DirectoryService, identifie return DirectoryserviceKeyValueTags(output.Tags), nil } +// DlmListTags lists dlm service tags. +// The identifier is typically the Amazon Resource Name (ARN), although +// it may also be a different identifier depending on the service. +func DlmListTags(conn *dlm.DLM, identifier string) (KeyValueTags, error) { + input := &dlm.ListTagsForResourceInput{ + ResourceArn: aws.String(identifier), + } + + output, err := conn.ListTagsForResource(input) + + if err != nil { + return New(nil), err + } + + return DlmKeyValueTags(output.Tags), nil +} + // DocdbListTags lists docdb service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. diff --git a/aws/internal/keyvaluetags/service_generation_customizations.go b/aws/internal/keyvaluetags/service_generation_customizations.go index c2851e2a12e..8321bab3b1f 100644 --- a/aws/internal/keyvaluetags/service_generation_customizations.go +++ b/aws/internal/keyvaluetags/service_generation_customizations.go @@ -34,6 +34,7 @@ import ( "github.com/aws/aws-sdk-go/service/devicefarm" "github.com/aws/aws-sdk-go/service/directconnect" "github.com/aws/aws-sdk-go/service/directoryservice" + "github.com/aws/aws-sdk-go/service/dlm" "github.com/aws/aws-sdk-go/service/docdb" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/ec2" @@ -155,6 +156,8 @@ func ServiceClientType(serviceName string) string { funcType = reflect.TypeOf(directconnect.New) case "directoryservice": funcType = reflect.TypeOf(directoryservice.New) + case "dlm": + funcType = reflect.TypeOf(dlm.New) case "docdb": funcType = reflect.TypeOf(docdb.New) case "dynamodb": diff --git a/aws/internal/keyvaluetags/service_tags_gen.go b/aws/internal/keyvaluetags/service_tags_gen.go index 2a31af4a643..597bc03ce12 100644 --- a/aws/internal/keyvaluetags/service_tags_gen.go +++ b/aws/internal/keyvaluetags/service_tags_gen.go @@ -25,7 +25,6 @@ import ( "github.com/aws/aws-sdk-go/service/devicefarm" "github.com/aws/aws-sdk-go/service/directconnect" "github.com/aws/aws-sdk-go/service/directoryservice" - "github.com/aws/aws-sdk-go/service/dlm" "github.com/aws/aws-sdk-go/service/docdb" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/ec2" @@ -187,6 +186,16 @@ func CognitoidentityproviderKeyValueTags(tags map[string]*string) KeyValueTags { return New(tags) } +// DlmTags returns dlm service tags. +func (tags KeyValueTags) DlmTags() map[string]*string { + return aws.StringMap(tags.Map()) +} + +// DlmKeyValueTags creates KeyValueTags from dlm service tags. +func DlmKeyValueTags(tags map[string]*string) KeyValueTags { + return New(tags) +} + // EksTags returns eks service tags. func (tags KeyValueTags) EksTags() map[string]*string { return aws.StringMap(tags.Map()) @@ -926,33 +935,6 @@ func DirectoryserviceKeyValueTags(tags []*directoryservice.Tag) KeyValueTags { return New(m) } -// DlmTags returns dlm service tags. -func (tags KeyValueTags) DlmTags() []*dlm.Tag { - result := make([]*dlm.Tag, 0, len(tags)) - - for k, v := range tags.Map() { - tag := &dlm.Tag{ - Key: aws.String(k), - Value: aws.String(v), - } - - result = append(result, tag) - } - - return result -} - -// DlmKeyValueTags creates KeyValueTags from dlm service tags. -func DlmKeyValueTags(tags []*dlm.Tag) KeyValueTags { - m := make(map[string]*string, len(tags)) - - for _, tag := range tags { - m[aws.StringValue(tag.Key)] = tag.Value - } - - return New(m) -} - // DocdbTags returns docdb service tags. func (tags KeyValueTags) DocdbTags() []*docdb.Tag { result := make([]*docdb.Tag, 0, len(tags)) diff --git a/aws/internal/keyvaluetags/update_tags_gen.go b/aws/internal/keyvaluetags/update_tags_gen.go index 676e748edde..79500f80141 100644 --- a/aws/internal/keyvaluetags/update_tags_gen.go +++ b/aws/internal/keyvaluetags/update_tags_gen.go @@ -33,6 +33,7 @@ import ( "github.com/aws/aws-sdk-go/service/devicefarm" "github.com/aws/aws-sdk-go/service/directconnect" "github.com/aws/aws-sdk-go/service/directoryservice" + "github.com/aws/aws-sdk-go/service/dlm" "github.com/aws/aws-sdk-go/service/docdb" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/ec2" @@ -1059,6 +1060,42 @@ func DirectoryserviceUpdateTags(conn *directoryservice.DirectoryService, identif return nil } +// DlmUpdateTags updates dlm service tags. +// The identifier is typically the Amazon Resource Name (ARN), although +// it may also be a different identifier depending on the service. +func DlmUpdateTags(conn *dlm.DLM, identifier string, oldTagsMap interface{}, newTagsMap interface{}) error { + oldTags := New(oldTagsMap) + newTags := New(newTagsMap) + + if removedTags := oldTags.Removed(newTags); len(removedTags) > 0 { + input := &dlm.UntagResourceInput{ + ResourceArn: aws.String(identifier), + TagKeys: aws.StringSlice(removedTags.Keys()), + } + + _, err := conn.UntagResource(input) + + if err != nil { + return fmt.Errorf("error untagging resource (%s): %w", identifier, err) + } + } + + if updatedTags := oldTags.Updated(newTags); len(updatedTags) > 0 { + input := &dlm.TagResourceInput{ + ResourceArn: aws.String(identifier), + Tags: updatedTags.IgnoreAws().DlmTags(), + } + + _, err := conn.TagResource(input) + + if err != nil { + return fmt.Errorf("error tagging resource (%s): %w", identifier, err) + } + } + + return nil +} + // DocdbUpdateTags updates docdb service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. From c83aa41b0c339a5d9e23e49f31be0f03f9e076ca Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Wed, 13 Nov 2019 20:48:09 -0500 Subject: [PATCH 2/2] resource/aws_dlm_lifecycle_policy: Add tags argument and arn attribute Reference: https://github.com/terraform-providers/terraform-provider-aws/blob/master/.github/CONTRIBUTING.md#adding-resource-tagging-support Output from acceptance testing: ``` --- PASS: TestAccAWSDlmLifecyclePolicy_Basic (14.81s) --- PASS: TestAccAWSDlmLifecyclePolicy_Full (22.48s) --- PASS: TestAccAWSDlmLifecyclePolicy_Tags (32.00s) ``` --- aws/resource_aws_dlm_lifecycle_policy.go | 37 ++++- aws/resource_aws_dlm_lifecycle_policy_test.go | 153 ++++++++++++++++++ website/docs/r/dlm_lifecycle_policy.markdown | 6 +- 3 files changed, 191 insertions(+), 5 deletions(-) diff --git a/aws/resource_aws_dlm_lifecycle_policy.go b/aws/resource_aws_dlm_lifecycle_policy.go index 0dbfd6cf052..8b4f1e305bd 100644 --- a/aws/resource_aws_dlm_lifecycle_policy.go +++ b/aws/resource_aws_dlm_lifecycle_policy.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/service/dlm" "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 resourceAwsDlmLifecyclePolicy() *schema.Resource { @@ -22,6 +23,10 @@ func resourceAwsDlmLifecyclePolicy() *schema.Resource { }, Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, "description": { Type: schema.TypeString, Required: true, @@ -130,6 +135,7 @@ func resourceAwsDlmLifecyclePolicy() *schema.Resource { dlm.SettablePolicyStateValuesEnabled, }, false), }, + "tags": tagsSchema(), }, } } @@ -144,6 +150,10 @@ func resourceAwsDlmLifecyclePolicyCreate(d *schema.ResourceData, meta interface{ State: aws.String(d.Get("state").(string)), } + if v := d.Get("tags").(map[string]interface{}); len(v) > 0 { + input.Tags = keyvaluetags.New(v).IgnoreAws().DlmTags() + } + log.Printf("[INFO] Creating DLM lifecycle policy: %s", input) out, err := conn.CreateLifecyclePolicy(&input) if err != nil { @@ -173,6 +183,7 @@ func resourceAwsDlmLifecyclePolicyRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("error reading DLM Lifecycle Policy (%s): %s", d.Id(), err) } + d.Set("arn", out.Policy.PolicyArn) d.Set("description", out.Policy.Description) d.Set("execution_role_arn", out.Policy.ExecutionRoleArn) d.Set("state", out.Policy.State) @@ -180,6 +191,10 @@ func resourceAwsDlmLifecyclePolicyRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("error setting policy details %s", err) } + if err := d.Set("tags", keyvaluetags.DlmKeyValueTags(out.Policy.Tags).IgnoreAws().Map()); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + return nil } @@ -189,24 +204,38 @@ func resourceAwsDlmLifecyclePolicyUpdate(d *schema.ResourceData, meta interface{ input := dlm.UpdateLifecyclePolicyInput{ PolicyId: aws.String(d.Id()), } + updateLifecyclePolicy := false if d.HasChange("description") { input.Description = aws.String(d.Get("description").(string)) + updateLifecyclePolicy = true } if d.HasChange("execution_role_arn") { input.ExecutionRoleArn = aws.String(d.Get("execution_role_arn").(string)) + updateLifecyclePolicy = true } if d.HasChange("state") { input.State = aws.String(d.Get("state").(string)) + updateLifecyclePolicy = true } if d.HasChange("policy_details") { input.PolicyDetails = expandDlmPolicyDetails(d.Get("policy_details").([]interface{})) + updateLifecyclePolicy = true } - log.Printf("[INFO] Updating lifecycle policy %s", d.Id()) - _, err := conn.UpdateLifecyclePolicy(&input) - if err != nil { - return fmt.Errorf("error updating DLM Lifecycle Policy (%s): %s", d.Id(), err) + if updateLifecyclePolicy { + log.Printf("[INFO] Updating lifecycle policy %s", d.Id()) + _, err := conn.UpdateLifecyclePolicy(&input) + if err != nil { + return fmt.Errorf("error updating DLM Lifecycle Policy (%s): %s", d.Id(), err) + } + } + + if d.HasChange("tags") { + o, n := d.GetChange("tags") + if err := keyvaluetags.DlmUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) + } } return resourceAwsDlmLifecyclePolicyRead(d, meta) diff --git a/aws/resource_aws_dlm_lifecycle_policy_test.go b/aws/resource_aws_dlm_lifecycle_policy_test.go index a859a14a454..10b84f5be56 100644 --- a/aws/resource_aws_dlm_lifecycle_policy_test.go +++ b/aws/resource_aws_dlm_lifecycle_policy_test.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -24,6 +25,7 @@ func TestAccAWSDlmLifecyclePolicy_Basic(t *testing.T) { Config: dlmLifecyclePolicyBasicConfig(rName), Check: resource.ComposeTestCheckFunc( checkDlmLifecyclePolicyExists(resourceName), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "dlm", regexp.MustCompile(`policy/.+`)), resource.TestCheckResourceAttr(resourceName, "description", "tf-acc-basic"), resource.TestCheckResourceAttrSet(resourceName, "execution_role_arn"), resource.TestCheckResourceAttr(resourceName, "state", "ENABLED"), @@ -34,6 +36,7 @@ func TestAccAWSDlmLifecyclePolicy_Basic(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "policy_details.0.schedule.0.create_rule.0.times.0"), resource.TestCheckResourceAttr(resourceName, "policy_details.0.schedule.0.retain_rule.0.count", "10"), resource.TestCheckResourceAttr(resourceName, "policy_details.0.target_tags.tf-acc-test", "basic"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), }, { @@ -94,6 +97,49 @@ func TestAccAWSDlmLifecyclePolicy_Full(t *testing.T) { }) } +func TestAccAWSDlmLifecyclePolicy_Tags(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_dlm_lifecycle_policy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSDlm(t) }, + Providers: testAccProviders, + CheckDestroy: dlmLifecyclePolicyDestroy, + Steps: []resource.TestStep{ + { + Config: dlmLifecyclePolicyConfigTags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + checkDlmLifecyclePolicyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: dlmLifecyclePolicyConfigTags2(rName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + checkDlmLifecyclePolicyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: dlmLifecyclePolicyConfigTags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + checkDlmLifecyclePolicyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + func dlmLifecyclePolicyDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).dlmconn @@ -327,3 +373,110 @@ resource "aws_dlm_lifecycle_policy" "full" { } `, rName) } + +func dlmLifecyclePolicyConfigTags1(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_iam_role" "test" { + name = %[1]q + + assume_role_policy = <