Skip to content

Commit

Permalink
allow duplicate tags
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsonaj committed Apr 20, 2023
1 parent b5be0d2 commit 19dda85
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 6 deletions.
2 changes: 1 addition & 1 deletion internal/provider/intercept.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ func (r tagsInterceptor) run(ctx context.Context, d schemaResourceData, meta any
tags := tagsInContext.TagsOut.UnwrapOrDefault().IgnoreSystem(inContext.ServicePackageName).IgnoreConfig(tagsInContext.IgnoreConfig)

// The resource's configured tags do not include any provider configured default_tags.
if err := d.Set(names.AttrTags, tags.RemoveDefaultConfig(tagsInContext.DefaultConfig).Map()); err != nil {
if err := d.Set(names.AttrTags, tags.RemoveDefaultConfig(tagsInContext.DefaultConfig).RemoveDuplicates(ctx, tagsInContext.DefaultConfig, d).Map()); err != nil {
return ctx, sdkdiag.AppendErrorf(diags, "setting %s: %s", names.AttrTags, err)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/provider/tags_interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func tagsReadFunc(ctx context.Context, d schemaResourceData, sp conns.ServicePac
toAdd := tagsInContext.TagsOut.UnwrapOrDefault().IgnoreSystem(inContext.ServicePackageName).IgnoreConfig(tagsInContext.IgnoreConfig)

// The resource's configured tags do not include any provider configured default_tags.
if err := d.Set(names.AttrTags, toAdd.RemoveDefaultConfig(tagsInContext.DefaultConfig).Map()); err != nil {
if err := d.Set(names.AttrTags, toAdd.RemoveDefaultConfig(tagsInContext.DefaultConfig).RemoveDuplicates(ctx, tagsInContext.DefaultConfig, d).Map()); err != nil {
return ctx, sdkdiag.AppendErrorf(diags, "setting %s: %s", names.AttrTags, err)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/service/ec2/vpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func TestAccVPC_tags(t *testing.T) {
})
}

func TestAccVPC_DefaultTags_providerOnly(t *testing.T) {
func TestAccVPC_DefaultTags_providerOnlyTestAccVPC_DefaultTags_providerOnly(t *testing.T) {
ctx := acctest.Context(t)
var vpc ec2.Vpc
resourceName := "aws_vpc.test"
Expand Down
50 changes: 50 additions & 0 deletions internal/tags/key_value_tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package tags
import (
"context"
"fmt"
"log"
"net/url"
"reflect"
"regexp"
"sort"
"strings"

"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-provider-aws/internal/create"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
Expand Down Expand Up @@ -737,6 +739,54 @@ func (td *TagData) String() string {
return fmt.Sprintf("TagData{%s}", strings.Join(fields, ", "))
}

// schemaResourceData is an interface that implements functions from schema.ResourceData
type schemaResourceData interface {
GetRawConfig() cty.Value
GetRawPlan() cty.Value
GetRawState() cty.Value
Get(string) interface{}
}

func (tags KeyValueTags) RemoveDuplicates(ctx context.Context, defaultConfig *DefaultConfig, d schemaResourceData) KeyValueTags {
result := make(map[string]string)
for k, v := range tags {
result[k] = v.ValueString()
}

configTags := make(map[string]string)
if config := d.GetRawPlan(); !config.IsNull() && config.IsKnown() {
c := config.GetAttr("tags")
if !c.IsNull() {
for k, v := range c.AsValueMap() {
configTags[k] = v.AsString()
}
}
}

if config := d.GetRawConfig(); !config.IsNull() && config.IsKnown() {
c := config.GetAttr("tags")
if !c.IsNull() {
for k, v := range c.AsValueMap() {
if _, ok := configTags[k]; !ok {
configTags[k] = v.AsString()
}
}
}
}

log.Printf("[DEBUG] config_tags: %v", configTags)
log.Printf("[DEBUG] tags_incoming: %v", result)
for k, v := range configTags {
if _, ok := result[k]; !ok {
log.Printf("[DEBUG] tags_diff: key(%s), value(%s)", k, v)
result[k] = v
}
}

log.Printf("[DEBUG] tags_outgoing: %v", result)
return New(ctx, result)
}

// ToSnakeCase converts a string to snake case.
//
// For example, AWS Go SDK field names are in PascalCase,
Expand Down
6 changes: 3 additions & 3 deletions internal/verify/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ func SetTagsDiff(ctx context.Context, diff *schema.ResourceDiff, meta interface{

resourceTags := tftags.New(ctx, diff.Get("tags").(map[string]interface{}))

if defaultTagsConfig.TagsEqual(resourceTags) {
return fmt.Errorf(`"tags" are identical to those in the "default_tags" configuration block of the provider: please de-duplicate and try again`)
}
//if defaultTagsConfig.TagsEqual(resourceTags) {
// return fmt.Errorf(`"tags" are identical to those in the "default_tags" configuration block of the provider: please de-duplicate and try again`)
//}

allTags := defaultTagsConfig.MergeTags(resourceTags).IgnoreConfig(ignoreTagsConfig)
// To ensure "tags_all" is correctly computed, we explicitly set the attribute diff
Expand Down

0 comments on commit 19dda85

Please sign in to comment.