diff --git a/aws/resource_aws_opsworks_stack.go b/aws/resource_aws_opsworks_stack.go index 2bd7b28001b..d884210bbbd 100644 --- a/aws/resource_aws_opsworks_stack.go +++ b/aws/resource_aws_opsworks_stack.go @@ -171,7 +171,8 @@ func resourceAwsOpsworksStack() *schema.Resource { Default: "Layer_Dependent", }, - "tags": tagsSchema(), + "tags": tagsSchema(), + "tags_all": tagsSchemaComputed(), "use_custom_cookbooks": { Type: schema.TypeBool, @@ -197,6 +198,8 @@ func resourceAwsOpsworksStack() *schema.Resource { Computed: true, }, }, + + CustomizeDiff: SetTagsDiff, } } @@ -272,6 +275,7 @@ func resourceAwsOpsworksSetStackCustomCookbooksSource(d *schema.ResourceData, v func resourceAwsOpsworksStackRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*AWSClient).opsworksconn + defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig var conErr error @@ -381,8 +385,15 @@ func resourceAwsOpsworksStackRead(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("error listing tags for Opsworks stack (%s): %s", arn, err) } - if err := d.Set("tags", tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { - return fmt.Errorf("error setting tags: %s", err) + tags = tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig) + + //lintignore:AWSR002 + if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil { + return fmt.Errorf("error setting tags: %w", err) + } + + if err := d.Set("tags_all", tags.Map()); err != nil { + return fmt.Errorf("error setting tags_all: %w", err) } return nil @@ -571,8 +582,8 @@ func resourceAwsOpsworksStackUpdate(d *schema.ResourceData, meta interface{}) er AccountID: meta.(*AWSClient).accountid, Resource: fmt.Sprintf("stack/%s/", d.Id()), }.String() - if d.HasChange("tags") { - o, n := d.GetChange("tags") + if d.HasChange("tags_all") { + o, n := d.GetChange("tags_all") if err := keyvaluetags.OpsworksUpdateTags(client, arn, o, n); err != nil { return fmt.Errorf("error updating Opsworks stack (%s) tags: %s", arn, err) diff --git a/aws/resource_aws_organizations_account.go b/aws/resource_aws_organizations_account.go index 8a4678d0bec..47029fb8b37 100644 --- a/aws/resource_aws_organizations_account.go +++ b/aws/resource_aws_organizations_account.go @@ -74,19 +74,25 @@ func resourceAwsOrganizationsAccount() *schema.Resource { Optional: true, ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[\w+=,.@-]{1,64}$`), "must consist of uppercase letters, lowercase letters, digits with no spaces, and any of the following characters"), }, - "tags": tagsSchema(), + "tags": tagsSchema(), + "tags_all": tagsSchemaComputed(), }, + + CustomizeDiff: SetTagsDiff, } } func resourceAwsOrganizationsAccountCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).organizationsconn + defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig + tags := defaultTagsConfig.MergeTags(keyvaluetags.New(d.Get("tags").(map[string]interface{}))) // Create the account createOpts := &organizations.CreateAccountInput{ AccountName: aws.String(d.Get("name").(string)), Email: aws.String(d.Get("email").(string)), } + if role, ok := d.GetOk("role_name"); ok { createOpts.RoleName = aws.String(role.(string)) } @@ -95,6 +101,10 @@ func resourceAwsOrganizationsAccountCreate(d *schema.ResourceData, meta interfac createOpts.IamUserAccessToBilling = aws.String(iam_user.(string)) } + if len(tags) > 0 { + createOpts.Tags = tags.IgnoreAws().OrganizationsTags() + } + log.Printf("[DEBUG] Creating AWS Organizations Account: %s", createOpts) var resp *organizations.CreateAccountOutput @@ -167,17 +177,12 @@ func resourceAwsOrganizationsAccountCreate(d *schema.ResourceData, meta interfac } } - if v := d.Get("tags").(map[string]interface{}); len(v) > 0 { - if err := keyvaluetags.OrganizationsUpdateTags(conn, d.Id(), nil, v); err != nil { - return fmt.Errorf("error adding AWS Organizations Account (%s) tags: %s", d.Id(), err) - } - } - return resourceAwsOrganizationsAccountRead(d, meta) } func resourceAwsOrganizationsAccountRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).organizationsconn + defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig describeOpts := &organizations.DescribeAccountInput{ @@ -221,8 +226,15 @@ func resourceAwsOrganizationsAccountRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("error listing tags for AWS Organizations Account (%s): %s", d.Id(), err) } - if err := d.Set("tags", tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { - return fmt.Errorf("error setting tags: %s", err) + tags = tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig) + + //lintignore:AWSR002 + if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil { + return fmt.Errorf("error setting tags: %w", err) + } + + if err := d.Set("tags_all", tags.Map()); err != nil { + return fmt.Errorf("error setting tags_all: %w", err) } return nil @@ -245,8 +257,8 @@ func resourceAwsOrganizationsAccountUpdate(d *schema.ResourceData, meta interfac } } - if d.HasChange("tags") { - o, n := d.GetChange("tags") + if d.HasChange("tags_all") { + o, n := d.GetChange("tags_all") if err := keyvaluetags.OrganizationsUpdateTags(conn, d.Id(), o, n); err != nil { return fmt.Errorf("error updating AWS Organizations Account (%s) tags: %s", d.Id(), err) diff --git a/aws/resource_aws_organizations_policy.go b/aws/resource_aws_organizations_policy.go index 88f5b303784..eb7a4034c83 100644 --- a/aws/resource_aws_organizations_policy.go +++ b/aws/resource_aws_organizations_policy.go @@ -51,13 +51,18 @@ func resourceAwsOrganizationsPolicy() *schema.Resource { Default: organizations.PolicyTypeServiceControlPolicy, ValidateFunc: validation.StringInSlice(organizations.PolicyType_Values(), false), }, - "tags": tagsSchema(), + "tags": tagsSchema(), + "tags_all": tagsSchemaComputed(), }, + + CustomizeDiff: SetTagsDiff, } } func resourceAwsOrganizationsPolicyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*AWSClient).organizationsconn + defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig + tags := defaultTagsConfig.MergeTags(keyvaluetags.New(d.Get("tags").(map[string]interface{}))) name := d.Get("name").(string) @@ -66,7 +71,7 @@ func resourceAwsOrganizationsPolicyCreate(ctx context.Context, d *schema.Resourc Description: aws.String(d.Get("description").(string)), Name: aws.String(name), Type: aws.String(d.Get("type").(string)), - Tags: keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().OrganizationsTags(), + Tags: tags.IgnoreAws().OrganizationsTags(), } log.Printf("[DEBUG] Creating Organizations Policy (%s): %v", name, input) @@ -102,6 +107,7 @@ func resourceAwsOrganizationsPolicyCreate(ctx context.Context, d *schema.Resourc func resourceAwsOrganizationsPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*AWSClient).organizationsconn + defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig input := &organizations.DescribePolicyInput{ @@ -146,8 +152,15 @@ func resourceAwsOrganizationsPolicyRead(ctx context.Context, d *schema.ResourceD return diag.FromErr(fmt.Errorf("error listing tags for Organizations policy (%s): %w", d.Id(), err)) } - if err := d.Set("tags", tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { - return diag.FromErr(fmt.Errorf("error setting tags for Organizations policy (%s): %w", d.Id(), err)) + tags = tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig) + + //lintignore:AWSR002 + if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil { + return diag.FromErr(fmt.Errorf("error setting tags: %w", err)) + } + + if err := d.Set("tags_all", tags.Map()); err != nil { + return diag.FromErr(fmt.Errorf("error setting tags_all: %w", err)) } return nil @@ -178,8 +191,8 @@ func resourceAwsOrganizationsPolicyUpdate(ctx context.Context, d *schema.Resourc return diag.FromErr(fmt.Errorf("error updating Organizations policy (%s): %w", d.Id(), err)) } - if d.HasChange("tags") { - o, n := d.GetChange("tags") + if d.HasChange("tags_all") { + o, n := d.GetChange("tags_all") if err := keyvaluetags.OrganizationsUpdateTags(conn, d.Id(), o, n); err != nil { return diag.FromErr(fmt.Errorf("error updating tags for Organizations policy (%s): %w", d.Id(), err)) } diff --git a/website/docs/r/opsworks_stack.html.markdown b/website/docs/r/opsworks_stack.html.markdown index d3f7b5e1d3f..289d0caf714 100644 --- a/website/docs/r/opsworks_stack.html.markdown +++ b/website/docs/r/opsworks_stack.html.markdown @@ -60,7 +60,7 @@ The following arguments are supported: * `hostname_theme` - (Optional) Keyword representing the naming scheme that will be used for instance hostnames within this stack. * `manage_berkshelf` - (Optional) Boolean value controlling whether Opsworks will run Berkshelf for this stack. -* `tags` - (Optional) A map of tags to assign to the resource. +* `tags` - (Optional) A map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. * `use_custom_cookbooks` - (Optional) Boolean value controlling whether the custom cookbook settings are enabled. * `use_opsworks_security_groups` - (Optional) Boolean value controlling whether the standard OpsWorks @@ -82,6 +82,7 @@ The `custom_cookbooks_source` block supports the following arguments: In addition to all arguments above, the following attributes are exported: * `id` - The id of the stack. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block). ## Import diff --git a/website/docs/r/organizations_account.html.markdown b/website/docs/r/organizations_account.html.markdown index 64923978fed..0722ee1e575 100644 --- a/website/docs/r/organizations_account.html.markdown +++ b/website/docs/r/organizations_account.html.markdown @@ -32,7 +32,7 @@ The following arguments are supported: * `iam_user_access_to_billing` - (Optional) If set to `ALLOW`, the new account enables IAM users to access account billing information if they have the required permissions. If set to `DENY`, then only the root user of the new account can access account billing information. * `parent_id` - (Optional) Parent Organizational Unit ID or Root ID for the account. Defaults to the Organization default Root ID. A configuration must be present for this argument to perform drift detection. * `role_name` - (Optional) The name of an IAM role that Organizations automatically preconfigures in the new member account. This role trusts the master account, allowing users in the master account to assume the role, as permitted by the master account administrator. The role has administrator permissions in the new member account. The Organizations API provides no method for reading this information after account creation, so Terraform cannot perform drift detection on its value and will always show a difference for a configured value after import unless [`ignore_changes`](https://www.terraform.io/docs/configuration/meta-arguments/lifecycle.html#ignore_changes) is used. -* `tags` - (Optional) Key-value map of resource tags. +* `tags` - (Optional) Key-value map of resource tags. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. ## Attributes Reference @@ -40,6 +40,7 @@ In addition to all arguments above, the following attributes are exported: * `arn` - The ARN for this account. * `id` - The AWS account id +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block). ## Import diff --git a/website/docs/r/organizations_policy.html.markdown b/website/docs/r/organizations_policy.html.markdown index 8ed34e750ad..80c1d0f1e30 100644 --- a/website/docs/r/organizations_policy.html.markdown +++ b/website/docs/r/organizations_policy.html.markdown @@ -37,7 +37,7 @@ The following arguments are supported: * `name` - (Required) The friendly name to assign to the policy. * `description` - (Optional) A description to assign to the policy. * `type` - (Optional) The type of policy to create. Valid values are `AISERVICES_OPT_OUT_POLICY`, `BACKUP_POLICY`, `SERVICE_CONTROL_POLICY` (SCP), and `TAG_POLICY`. Defaults to `SERVICE_CONTROL_POLICY`. -* `tags` - (Optional) Key-value map of resource tags. +* `tags` - (Optional) Key-value map of resource tags. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. ## Attributes Reference @@ -45,6 +45,7 @@ In addition to all arguments above, the following attributes are exported: * `id` - The unique identifier (ID) of the policy. * `arn` - Amazon Resource Name (ARN) of the policy. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block). ## Import