Skip to content

Commit

Permalink
Merge pull request #22026 from hashicorp/b-s3-bucket-replication-conf…
Browse files Browse the repository at this point in the history
…ig-without-prefix

r/s3_bucket_replication_configuration: ensure rule can be created without specifying `prefix` or `filter`
  • Loading branch information
anGie44 authored Dec 3, 2021
2 parents 05d8a1f + 4e40be4 commit 83f1d84
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .changelog/22026.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/aws_s3_bucket_replication_configuration: Fix `MalformedXML` errors for replication rules using XML schema V1
```
81 changes: 65 additions & 16 deletions internal/service/s3/bucket_replication_configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestAccS3BucketReplicationConfiguration_basic(t *testing.T) {
},
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationBasic(rName, s3.StorageClassStandard),
Expand Down Expand Up @@ -132,7 +132,7 @@ func TestAccS3BucketReplicationConfiguration_multipleDestinationsEmptyFilter(t *
},
ErrorCheck: testAccErrorCheckSkipS3(t),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationWithMultipleDestinationsEmptyFilter(rName),
Expand Down Expand Up @@ -191,7 +191,7 @@ func TestAccS3BucketReplicationConfiguration_multipleDestinationsNonEmptyFilter(
},
ErrorCheck: testAccErrorCheckSkipS3(t),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationWithMultipleDestinationsNonEmptyFilter(rName),
Expand Down Expand Up @@ -242,7 +242,7 @@ func TestAccS3BucketReplicationConfiguration_twoDestination(t *testing.T) {
},
ErrorCheck: testAccErrorCheckSkipS3(t),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationWithMultipleDestinationsTwoDestination(rName),
Expand Down Expand Up @@ -296,7 +296,7 @@ func TestAccS3BucketReplicationConfiguration_configurationRuleDestinationAccessC
},
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationWithAccessControlTranslation(rName),
Expand Down Expand Up @@ -373,7 +373,7 @@ func TestAccS3BucketReplicationConfiguration_configurationRuleDestinationAddAcce
},
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationRulesDestination(rName),
Expand Down Expand Up @@ -441,7 +441,7 @@ func TestAccS3BucketReplicationConfiguration_replicationTimeControl(t *testing.T
},
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationRTC(rName),
Expand Down Expand Up @@ -494,7 +494,7 @@ func TestAccS3BucketReplicationConfiguration_replicaModifications(t *testing.T)
},
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationReplicaMods(rName),
Expand Down Expand Up @@ -543,7 +543,7 @@ func TestAccS3BucketReplicationConfiguration_withoutStorageClass(t *testing.T) {
},
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationWithoutStorageClass(rName),
Expand Down Expand Up @@ -585,7 +585,7 @@ func TestAccS3BucketReplicationConfiguration_schemaV2(t *testing.T) {
},
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationWithV2ConfigurationNoTags(rName),
Expand Down Expand Up @@ -629,7 +629,7 @@ func TestAccS3BucketReplicationConfiguration_schemaV2SameRegion(t *testing.T) {
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfiguration_schemaV2SameRegion(rName, rNameDestination),
Expand Down Expand Up @@ -673,7 +673,7 @@ func TestAccS3BucketReplicationConfiguration_schemaV2DestinationMetrics(t *testi
},
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfiguration_schemaV2DestinationMetrics_statusOnly(rName, s3.StorageClassStandard),
Expand Down Expand Up @@ -712,7 +712,7 @@ func TestAccS3BucketReplicationConfiguration_existingObjectReplication(t *testin
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfiguration_existingObjectReplication(rName, rNameDestination),
Expand Down Expand Up @@ -757,7 +757,7 @@ func TestAccS3BucketReplicationConfiguration_filter_tagFilter(t *testing.T) {
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfiguration_filter_tag(rName, "testkey", "testvalue"),
Expand Down Expand Up @@ -801,7 +801,7 @@ func TestAccS3BucketReplicationConfiguration_filter_andOperator(t *testing.T) {
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckReplicationConfigDestroy, &providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfiguration_filter_andOperator_prefixAndTags(rName, "testkey1", "testvalue1", "testkey2", "testvalue2"),
Expand Down Expand Up @@ -860,7 +860,36 @@ func TestAccS3BucketReplicationConfiguration_filter_andOperator(t *testing.T) {
})
}

func testAccCheckReplicationConfigDestroy(s *terraform.State, provider *schema.Provider) error {
// Reference: https://github.com/hashicorp/terraform-provider-aws/issues/21961
func TestAccS3BucketReplicationConfiguration_withoutPrefix(t *testing.T) {
resourceName := "aws_s3_bucket_replication_configuration.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

// record the initialized providers so that we can use them to check for the instances in each region
var providers []*schema.Provider

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
ProviderFactories: acctest.FactoriesAlternate(&providers),
CheckDestroy: acctest.CheckWithProviders(testAccCheckBucketReplicationConfigurationDestroy, &providers),
Steps: []resource.TestStep{
{
Config: testAccBucketReplicationConfigurationWithoutPrefix(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckBucketReplicationConfigurationExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckBucketReplicationConfigurationDestroy(s *terraform.State, provider *schema.Provider) error {
conn := provider.Meta().(*conns.AWSClient).S3Conn

for _, rs := range s.RootModule().Resources {
Expand Down Expand Up @@ -1713,3 +1742,23 @@ resource "aws_s3_bucket_replication_configuration" "test" {
}
}`, storageClass)
}

func testAccBucketReplicationConfigurationWithoutPrefix(rName string) string {
return acctest.ConfigCompose(
testAccBucketReplicationConfigurationBase(rName),
`
resource "aws_s3_bucket_replication_configuration" "test" {
bucket = aws_s3_bucket.source.id
role = aws_iam_role.test.arn
rule {
id = "foobar"
status = "Enabled"
destination {
bucket = aws_s3_bucket.destination.arn
storage_class = "STANDARD"
}
}
}`)
}
21 changes: 9 additions & 12 deletions internal/service/s3/flex.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,22 +298,10 @@ func ExpandRules(l []interface{}) []*s3.ReplicationRule {
rule.ExistingObjectReplication = ExpandExistingObjectReplication(v)
}

if v, ok := tfMap["filter"].([]interface{}); ok && len(v) > 0 && v[0] != nil {
rule.Filter = ExpandFilter(v)
}

if v, ok := tfMap["id"].(string); ok && v != "" {
rule.ID = aws.String(v)
}

if v, ok := tfMap["prefix"].(string); ok && v != "" {
rule.Prefix = aws.String(v)
}

if v, ok := tfMap["priority"].(int); ok && rule.Filter != nil {
rule.Priority = aws.Int64(int64(v))
}

if v, ok := tfMap["source_selection_criteria"].([]interface{}); ok && len(v) > 0 && v[0] != nil {
rule.SourceSelectionCriteria = ExpandSourceSelectionCriteria(v)
}
Expand All @@ -322,6 +310,15 @@ func ExpandRules(l []interface{}) []*s3.ReplicationRule {
rule.Status = aws.String(v)
}

if v, ok := tfMap["filter"].([]interface{}); ok && len(v) > 0 && v[0] != nil {
// XML schema V2
rule.Filter = ExpandFilter(v)
rule.Priority = aws.Int64(int64(tfMap["priority"].(int)))
} else {
// XML schema V1
rule.Prefix = aws.String(tfMap["prefix"].(string))
}

rules = append(rules, rule)
}

Expand Down

0 comments on commit 83f1d84

Please sign in to comment.