Skip to content

Commit

Permalink
add ignore_default_tags option to s3 object
Browse files Browse the repository at this point in the history
  • Loading branch information
walteh committed Aug 31, 2023
1 parent 1b29b6e commit f789c4c
Show file tree
Hide file tree
Showing 2 changed files with 210 additions and 2 deletions.
25 changes: 23 additions & 2 deletions internal/service/s3/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func ResourceObject() *schema.Resource {

CustomizeDiff: customdiff.Sequence(
resourceObjectCustomizeDiff,
verify.SetTagsDiff,
resourceObjectCustomizeTagDiff,
),

Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -119,6 +119,11 @@ func ResourceObject() *schema.Resource {
Optional: true,
Default: false,
},
"ignore_default_tags": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"key": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -401,7 +406,14 @@ func resourceObjectUpload(ctx context.Context, d *schema.ResourceData, meta inte
conn := meta.(*conns.AWSClient).S3Conn(ctx)
uploader := s3manager.NewUploaderWithClient(conn)
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
tags := defaultTagsConfig.MergeTags(tftags.New(ctx, d.Get("tags").(map[string]interface{})))

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

if d.Get("ignore_default_tags").(bool) {
tags = tags.RemoveDefaultConfig(defaultTagsConfig)
} else {
tags = defaultTagsConfig.MergeTags(tags)
}

var body io.ReadSeeker

Expand Down Expand Up @@ -567,6 +579,15 @@ func resourceObjectCustomizeDiff(_ context.Context, d *schema.ResourceDiff, meta
return nil
}

func resourceObjectCustomizeTagDiff(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error {

if d.Get("ignore_default_tags").(bool) {
return d.SetNew("tags_all", d.Get("tags"))
}

return verify.SetTagsDiff(ctx, d, meta)
}

func hasObjectContentChanges(d verify.ResourceDiffer) bool {
for _, key := range []string{
"bucket_key_enabled",
Expand Down
187 changes: 187 additions & 0 deletions internal/service/s3/object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,139 @@ func TestAccS3Object_tagsMultipleSlashes(t *testing.T) {
})
}

func TestAccS3Object_ignoreDefaultTags_create(t *testing.T) {
ctx := acctest.Context(t)
var obj1, obj2, obj3, obj4 s3.GetObjectOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_s3_object.object"
key := "test-ignore-default-tags-key"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckObjectDestroy(ctx),
Steps: []resource.TestStep{
{
PreConfig: func() {},
Config: testAccObjectConfig_withIgnoreDefaultTags(rName, key, "stuff", true, "X", 8, 2),
Check: resource.ComposeTestCheckFunc(
testAccCheckObjectExists(ctx, resourceName, &obj1),
testAccCheckObjectBody(&obj1, "stuff"),
resource.TestCheckResourceAttr(resourceName, "tags_all.%", "2"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey1", "CustomX1"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey2", "CustomX2"),
),
},
{
PreConfig: func() {},
Config: testAccObjectConfig_withIgnoreDefaultTags(rName, key, "stuff", false, "X", 3, 2),
Check: resource.ComposeTestCheckFunc(
testAccCheckObjectExists(ctx, resourceName, &obj2),
testAccCheckObjectVersionIdEquals(&obj2, &obj1),
testAccCheckObjectBody(&obj2, "stuff"),
resource.TestCheckResourceAttr(resourceName, "tags_all.%", "5"),
resource.TestCheckResourceAttr(resourceName, "tags_all.DefaultKey1", "DefaultX1"),
resource.TestCheckResourceAttr(resourceName, "tags_all.DefaultKey2", "DefaultX2"),
resource.TestCheckResourceAttr(resourceName, "tags_all.DefaultKey3", "DefaultX3"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey1", "CustomX1"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey2", "CustomX2"),
),
},
{
PreConfig: func() {},
Config: testAccObjectConfig_withIgnoreDefaultTags(rName, key, "changed stuff", true, "X", 10, 2),
Check: resource.ComposeTestCheckFunc(
testAccCheckObjectExists(ctx, resourceName, &obj3),
testAccCheckObjectVersionIdDiffers(&obj3, &obj2),
testAccCheckObjectBody(&obj3, "changed stuff"),
resource.TestCheckResourceAttr(resourceName, "tags_all.%", "2"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey1", "CustomX1"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey2", "CustomX2"),
),
},
{
PreConfig: func() {},
Config: testAccObjectConfig_withIgnoreDefaultTags(rName, key, "changed stuff", false, "X", 0, 0),
Check: resource.ComposeTestCheckFunc(
testAccCheckObjectExists(ctx, resourceName, &obj4),
testAccCheckObjectVersionIdEquals(&obj4, &obj3),
testAccCheckObjectBody(&obj4, "changed stuff"),
resource.TestCheckResourceAttr(resourceName, "tags_all.%", "0"),
),
},
},
})
}

func TestAccS3Object_ignoreDefaultTags_existing(t *testing.T) {
ctx := acctest.Context(t)
var obj1, obj2, obj3, obj4 s3.GetObjectOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_s3_object.object"
key := "test-ignore-default-tags-key"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckObjectDestroy(ctx),
Steps: []resource.TestStep{
{
PreConfig: func() {},
Config: testAccObjectConfig_withIgnoreDefaultTags(rName, key, "stuff", false, "Y", 2, 2),
Check: resource.ComposeTestCheckFunc(
testAccCheckObjectExists(ctx, resourceName, &obj1),
testAccCheckObjectBody(&obj1, "stuff"),
resource.TestCheckResourceAttr(resourceName, "tags_all.%", "4"),
resource.TestCheckResourceAttr(resourceName, "tags_all.DefaultKey1", "DefaultY1"),
resource.TestCheckResourceAttr(resourceName, "tags_all.DefaultKey2", "DefaultY2"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey1", "CustomY1"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey2", "CustomY2"),
),
},
{
PreConfig: func() {},
Config: testAccObjectConfig_withIgnoreDefaultTags(rName, key, "stuff", true, "Y", 2, 2),
Check: resource.ComposeTestCheckFunc(
testAccCheckObjectExists(ctx, resourceName, &obj2),
testAccCheckObjectVersionIdEquals(&obj2, &obj1),
testAccCheckObjectBody(&obj2, "stuff"),
resource.TestCheckResourceAttr(resourceName, "tags_all.%", "2"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey1", "CustomY1"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey2", "CustomY2"),
),
},
{
PreConfig: func() {},
Config: testAccObjectConfig_withIgnoreDefaultTags(rName, key, "changed stuff", false, "Y", 3, 3),
Check: resource.ComposeTestCheckFunc(
testAccCheckObjectExists(ctx, resourceName, &obj3),
testAccCheckObjectVersionIdDiffers(&obj3, &obj2),
testAccCheckObjectBody(&obj3, "changed stuff"),
resource.TestCheckResourceAttr(resourceName, "tags_all.%", "6"),
resource.TestCheckResourceAttr(resourceName, "tags_all.DefaultKey1", "DefaultY1"),
resource.TestCheckResourceAttr(resourceName, "tags_all.DefaultKey2", "DefaultY2"),
resource.TestCheckResourceAttr(resourceName, "tags_all.DefaultKey3", "DefaultY3"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey1", "CustomY1"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey2", "CustomY2"),
resource.TestCheckResourceAttr(resourceName, "tags_all.CustomKey3", "CustomY3"),
),
},
{
PreConfig: func() {},
Config: testAccObjectConfig_withIgnoreDefaultTags(rName, key, "changed stuff", true, "Y", 2, 0),
Check: resource.ComposeTestCheckFunc(
testAccCheckObjectExists(ctx, resourceName, &obj4),
testAccCheckObjectVersionIdEquals(&obj4, &obj3),
testAccCheckObjectBody(&obj4, "changed stuff"),
resource.TestCheckResourceAttr(resourceName, "tags_all.%", "0"),
),
},
},
})
}

func TestAccS3Object_objectLockLegalHoldStartWithNone(t *testing.T) {
ctx := acctest.Context(t)
var obj1, obj2, obj3 s3.GetObjectOutput
Expand Down Expand Up @@ -1961,6 +2094,60 @@ resource "aws_s3_object" "object" {
`, rName, key, content)
}

func testAccObjectConfig_withIgnoreDefaultTags(rName, key, content string, ignore bool, label string, numDefault, numCustom int) string {

var defaultTags string
for i := 1; i <= numDefault; i++ {
defaultTags += fmt.Sprintf(`
DefaultKey%d = "Default%s%d"`, i, label, i)
}

var customTags string
for i := 1; i <= numCustom; i++ {
customTags += fmt.Sprintf(`
CustomKey%d = "Custom%s%d"`, i, label, i)
}

return fmt.Sprintf(`
provider "aws" {
alias = "ignore_default_tags"
default_tags {
tags = {
%[5]s
}
}
}
resource "aws_s3_bucket" "test" {
provider = aws.ignore_default_tags
bucket = %[1]q
force_destroy = true
}
resource "aws_s3_bucket_versioning" "test" {
provider = aws.ignore_default_tags
bucket = aws_s3_bucket.test.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_object" "object" {
provider = aws.ignore_default_tags
# Must have bucket versioning enabled first
bucket = aws_s3_bucket_versioning.test.bucket
key = %[2]q
content = %[3]q
tags = {
%[6]s
}
ignore_default_tags = %[4]t
}
`, rName, key, content, ignore, defaultTags, customTags)
}

func testAccObjectConfig_metadata(rName string, metadataKey1, metadataValue1, metadataKey2, metadataValue2 string) string {
return fmt.Sprintf(`
resource "aws_s3_bucket" "test" {
Expand Down

0 comments on commit f789c4c

Please sign in to comment.