From 501660baeef3cfd2b32c40855a8a1513205b8083 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Thu, 31 Mar 2022 19:37:43 -0400 Subject: [PATCH 1/2] r/s3_bucket: make 'versioning' configurable --- internal/service/s3/bucket.go | 109 +++++++++- internal/service/s3/bucket_test.go | 170 +++++++++++++++- internal/service/s3/bucket_versioning_test.go | 188 ++++++++++++++++++ website/docs/r/s3_bucket.html.markdown | 32 ++- 4 files changed, 487 insertions(+), 12 deletions(-) diff --git a/internal/service/s3/bucket.go b/internal/service/s3/bucket.go index f597462022e..6e9254f33f0 100644 --- a/internal/service/s3/bucket.go +++ b/internal/service/s3/bucket.go @@ -216,19 +216,21 @@ func ResourceBucket() *schema.Resource { "versioning": { Type: schema.TypeList, + Optional: true, Computed: true, + MaxItems: 1, Deprecated: "Use the aws_s3_bucket_versioning resource instead", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "enabled": { - Type: schema.TypeBool, - Computed: true, - Deprecated: "Use the aws_s3_bucket_versioning resource instead", + Type: schema.TypeBool, + Optional: true, + Default: false, }, "mfa_delete": { - Type: schema.TypeBool, - Computed: true, - Deprecated: "Use the aws_s3_bucket_versioning resource instead", + Type: schema.TypeBool, + Optional: true, + Default: false, }, }, }, @@ -797,6 +799,23 @@ func resourceBucketUpdate(d *schema.ResourceData, meta interface{}) error { } } + if d.HasChange("versioning") { + v := d.Get("versioning").([]interface{}) + + if d.IsNewResource() { + if versioning := expandVersioningWhenIsNewResource(v); versioning != nil { + err := resourceBucketInternalVersioningUpdate(conn, d.Id(), versioning) + if err != nil { + return fmt.Errorf("error updating (new) S3 Bucket (%s) Versioning: %w", d.Id(), err) + } + } + } else { + if err := resourceBucketInternalVersioningUpdate(conn, d.Id(), expandVersioning(v)); err != nil { + return fmt.Errorf("error updating S3 Bucket (%s) Versioning: %w", d.Id(), err) + } + } + } + return resourceBucketRead(d, meta) } @@ -1809,6 +1828,19 @@ func resourceBucketInternalObjectLockConfigurationUpdate(conn *s3.S3, d *schema. return err } +func resourceBucketInternalVersioningUpdate(conn *s3.S3, bucket string, versioningConfig *s3.VersioningConfiguration) error { + input := &s3.PutBucketVersioningInput{ + Bucket: aws.String(bucket), + VersioningConfiguration: versioningConfig, + } + + _, err := verify.RetryOnAWSCode(s3.ErrCodeNoSuchBucket, func() (interface{}, error) { + return conn.PutBucketVersioning(input) + }) + + return err +} + ///////////////////////////////////////////// Expand and Flatten functions ///////////////////////////////////////////// // Cors Rule functions @@ -2376,6 +2408,71 @@ func flattenServerSideEncryptionConfigurationRules(rules []*s3.ServerSideEncrypt // Versioning functions +func expandVersioning(l []interface{}) *s3.VersioningConfiguration { + if len(l) == 0 || l[0] == nil { + return nil + } + + tfMap, ok := l[0].(map[string]interface{}) + + if !ok { + return nil + } + + output := &s3.VersioningConfiguration{} + + if v, ok := tfMap["enabled"].(bool); ok { + if v { + output.Status = aws.String(s3.BucketVersioningStatusEnabled) + } else { + output.Status = aws.String(s3.BucketVersioningStatusSuspended) + } + } + + if v, ok := tfMap["mfa_delete"].(bool); ok { + if v { + output.MFADelete = aws.String(s3.MFADeleteEnabled) + } else { + output.MFADelete = aws.String(s3.MFADeleteDisabled) + } + } + + return output +} + +func expandVersioningWhenIsNewResource(l []interface{}) *s3.VersioningConfiguration { + if len(l) == 0 || l[0] == nil { + return nil + } + + tfMap, ok := l[0].(map[string]interface{}) + + if !ok { + return nil + } + + output := &s3.VersioningConfiguration{} + + // Only set and return a non-nil VersioningConfiguration with at least one of + // MFADelete or Status enabled as the PutBucketVersioning API request + // does not need to be made for new buckets that don't require versioning. + // Reference: https://github.com/hashicorp/terraform-provider-aws/issues/4494 + + if v, ok := tfMap["enabled"].(bool); ok && v { + output.Status = aws.String(s3.BucketVersioningStatusEnabled) + } + + if v, ok := tfMap["mfa_delete"].(bool); ok && v { + output.MFADelete = aws.String(s3.MFADeleteEnabled) + } + + if output.MFADelete == nil && output.Status == nil { + return nil + } + + return output +} + func flattenVersioning(versioning *s3.GetBucketVersioningOutput) []interface{} { if versioning == nil { return []interface{}{} diff --git a/internal/service/s3/bucket_test.go b/internal/service/s3/bucket_test.go index 4d5f393c74b..21bec5f38cd 100644 --- a/internal/service/s3/bucket_test.go +++ b/internal/service/s3/bucket_test.go @@ -850,8 +850,139 @@ func TestAccS3Bucket_Manage_objectLockWithVersioning_deprecatedEnabled(t *testin }) } +func TestAccS3Bucket_Manage_versioning(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withVersioning(bucketName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "versioning.#", "1"), + resource.TestCheckResourceAttr(resourceName, "versioning.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "versioning.0.mfa_delete", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy", "acl"}, + }, + { + Config: testAccBucketConfig_withVersioning(bucketName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "versioning.#", "1"), + resource.TestCheckResourceAttr(resourceName, "versioning.0.enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "versioning.0.mfa_delete", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy", "acl"}, + }, + }, + }) +} + +func TestAccS3Bucket_Manage_versioningDisabled(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withVersioning(bucketName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "versioning.#", "1"), + resource.TestCheckResourceAttr(resourceName, "versioning.0.enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "versioning.0.mfa_delete", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy", "acl"}, + }, + }, + }) +} + +func TestAccS3Bucket_Manage_MfaDeleteDisabled(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withVersioningMfaDelete(bucketName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "versioning.#", "1"), + resource.TestCheckResourceAttr(resourceName, "versioning.0.enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "versioning.0.mfa_delete", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy", "acl"}, + }, + }, + }) +} + +func TestAccS3Bucket_Manage_versioningAndMfaDeleteDisabled(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_s3_bucket.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withVersioningDisabledAndMfaDelete(bucketName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "versioning.#", "1"), + resource.TestCheckResourceAttr(resourceName, "versioning.0.enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "versioning.0.mfa_delete", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy", "acl"}, + }, + }, + }) +} + func TestAccS3Bucket_Security_updateACL(t *testing.T) { - bucketName := sdkacctest.RandomWithPrefix("tf-test-bucket") + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_s3_bucket.test" resource.ParallelTest(t, resource.TestCase{ @@ -2013,6 +2144,43 @@ resource "aws_s3_bucket" "test" { `, bucketName) } +func testAccBucketConfig_withVersioning(bucketName string, enabled bool) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q + + versioning { + enabled = %[2]t + } +} +`, bucketName, enabled) +} + +func testAccBucketConfig_withVersioningMfaDelete(bucketName string, mfaDelete bool) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q + + versioning { + mfa_delete = %[2]t + } +} +`, bucketName, mfaDelete) +} + +func testAccBucketConfig_withVersioningDisabledAndMfaDelete(bucketName string, mfaDelete bool) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q + + versioning { + enabled = false + mfa_delete = %[2]t + } +} +`, bucketName, mfaDelete) +} + func testAccBucketConfig_withNoTags(bucketName string) string { return fmt.Sprintf(` resource "aws_s3_bucket" "test" { diff --git a/internal/service/s3/bucket_versioning_test.go b/internal/service/s3/bucket_versioning_test.go index 09bb6c3029d..67e1f407831 100644 --- a/internal/service/s3/bucket_versioning_test.go +++ b/internal/service/s3/bucket_versioning_test.go @@ -135,6 +135,163 @@ func TestAccS3BucketVersioning_MFADelete(t *testing.T) { }) } +func TestAccS3BucketVersioning_migrate_versioningDisabledNoChange(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + bucketResourceName := "aws_s3_bucket.test" + resourceName := "aws_s3_bucket_versioning.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withVersioning(bucketName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(bucketResourceName), + resource.TestCheckResourceAttr(bucketResourceName, "versioning.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "versioning.0.enabled", "false"), + ), + }, + { + Config: testAccBucketVersioning_Migrate_VersioningEnabledConfig(bucketName, tfs3.BucketVersioningStatusDisabled), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketVersioningExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "versioning_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "versioning_configuration.0.status", tfs3.BucketVersioningStatusDisabled), + ), + }, + }, + }) +} + +func TestAccS3BucketVersioning_migrate_versioningDisabledWithChange(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + bucketResourceName := "aws_s3_bucket.test" + resourceName := "aws_s3_bucket_versioning.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withVersioning(bucketName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(bucketResourceName), + resource.TestCheckResourceAttr(bucketResourceName, "versioning.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "versioning.0.enabled", "false"), + ), + }, + { + Config: testAccBucketVersioning_Migrate_VersioningEnabledConfig(bucketName, s3.BucketVersioningStatusEnabled), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketVersioningExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "versioning_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "versioning_configuration.0.status", s3.BucketVersioningStatusEnabled), + ), + }, + }, + }) +} + +func TestAccS3BucketVersioning_migrate_versioningEnabledNoChange(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + bucketResourceName := "aws_s3_bucket.test" + resourceName := "aws_s3_bucket_versioning.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withVersioning(bucketName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(bucketResourceName), + resource.TestCheckResourceAttr(bucketResourceName, "versioning.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "versioning.0.enabled", "true"), + ), + }, + { + Config: testAccBucketVersioning_Migrate_VersioningEnabledConfig(bucketName, s3.BucketVersioningStatusEnabled), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketVersioningExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "versioning_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "versioning_configuration.0.status", s3.BucketVersioningStatusEnabled), + ), + }, + }, + }) +} + +func TestAccS3BucketVersioning_migrate_versioningEnabledWithChange(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + bucketResourceName := "aws_s3_bucket.test" + resourceName := "aws_s3_bucket_versioning.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withVersioning(bucketName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(bucketResourceName), + resource.TestCheckResourceAttr(bucketResourceName, "versioning.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "versioning.0.enabled", "true"), + ), + }, + { + Config: testAccBucketVersioning_Migrate_VersioningEnabledConfig(bucketName, s3.BucketVersioningStatusSuspended), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketVersioningExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "versioning_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "versioning_configuration.0.status", s3.BucketVersioningStatusSuspended), + ), + }, + }, + }) +} + +// TestAccS3BucketVersioning_migrate_mfaDeleteNoChange can only test for a "Disabled" +// mfa_delete configuration as the "mfa" argument is required if it's enabled +func TestAccS3BucketVersioning_migrate_mfaDeleteNoChange(t *testing.T) { + bucketName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + bucketResourceName := "aws_s3_bucket.test" + resourceName := "aws_s3_bucket_versioning.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckBucketDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBucketConfig_withVersioningMfaDelete(bucketName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketExists(bucketResourceName), + resource.TestCheckResourceAttr(bucketResourceName, "versioning.#", "1"), + resource.TestCheckResourceAttr(bucketResourceName, "versioning.0.mfa_delete", "false"), + ), + }, + { + Config: testAccBucketVersioning_Migrate_MfaDeleteConfig(bucketName, s3.MFADeleteDisabled), + Check: resource.ComposeTestCheckFunc( + testAccCheckBucketVersioningExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "versioning_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "versioning_configuration.0.mfa_delete", s3.MFADeleteDisabled), + ), + }, + }, + }) +} + func TestAccS3BucketVersioning_Status_disabled(t *testing.T) { rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_s3_bucket_versioning.test" @@ -385,3 +542,34 @@ resource "aws_s3_bucket_versioning" "test" { } `, rName, mfaDelete) } + +func testAccBucketVersioning_Migrate_VersioningEnabledConfig(rName, status string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q +} + +resource "aws_s3_bucket_versioning" "test" { + bucket = aws_s3_bucket.test.id + versioning_configuration { + status = %[2]q + } +} +`, rName, status) +} + +func testAccBucketVersioning_Migrate_MfaDeleteConfig(rName, mfaDelete string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q +} + +resource "aws_s3_bucket_versioning" "test" { + bucket = aws_s3_bucket.test.id + versioning_configuration { + mfa_delete = %[2]q + status = "Enabled" + } +} +`, rName, mfaDelete) +} diff --git a/website/docs/r/s3_bucket.html.markdown b/website/docs/r/s3_bucket.html.markdown index 27c0a7cff9f..41383de7aee 100644 --- a/website/docs/r/s3_bucket.html.markdown +++ b/website/docs/r/s3_bucket.html.markdown @@ -36,6 +36,10 @@ Configuring with both will cause inconsistencies and may overwrite configuration or with the deprecated parameter `logging` in the resource `aws_s3_bucket`. Configuring with both will cause inconsistencies and may overwrite configuration. +~> **NOTE on S3 Bucket Versioning Configuration:** S3 Bucket versioning can be configured in either the standalone resource [`aws_s3_bucket_versioning`](s3_bucket_versioning.html.markdown) +or with the deprecated parameter `versioning` in the resource `aws_s3_bucket`. +Configuring with both will cause inconsistencies and may overwrite configuration. + ## Example Usage ### Private Bucket w/ Tags @@ -83,8 +87,19 @@ resource "aws_s3_bucket" "b" { ### Using versioning -The `versioning` argument is read-only as of version 4.0 of the Terraform AWS Provider. -See the [`aws_s3_bucket_versioning` resource](s3_bucket_versioning.html.markdown) for configuration details. +-> **NOTE:** The parameter `versioning` is deprecated. +Use the resource [`aws_s3_bucket_versioning`](s3_bucket_versioning.html.markdown) instead. + +```terraform +resource "aws_s3_bucket" "b" { + bucket = "my-tf-test-bucket" + acl = "private" + + versioning { + enabled = true + } +} +``` ### Enable Logging @@ -244,6 +259,7 @@ The following arguments are supported: Use the resource [`aws_s3_bucket_logging`](s3_bucket_logging.html.markdown) instead. * `object_lock_enabled` - (Optional, Default:`false`, Forces new resource) Indicates whether this bucket has an Object Lock configuration enabled. * `object_lock_configuration` - (Optional) A configuration of [S3 object locking](https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock.html). See [Object Lock Configuration](#object-lock-configuration) below. +* `versioning` - (Optional, **Deprecated**) A configuration of the [S3 bucket versioning state](https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html). See [Versioning](#versioning) below for details. Terraform will only perform drift detection if a configuration value is provided. Use the resource [`aws_s3_bucket_versioning`](s3_bucket_versioning.html.markdown) instead. * `tags` - (Optional) A map of tags to assign to the bucket. 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. ### CORS Rule @@ -336,6 +352,15 @@ The `object_lock_configuration` configuration block supports the following argum * `object_lock_enabled` - (Optional, **Deprecated**) Indicates whether this bucket has an Object Lock configuration enabled. Valid value is `Enabled`. Use the top-level argument `object_lock_enabled` instead. +### Versioning + +~> **NOTE:** Currently, changes to the `versioning` configuration of _existing_ resources cannot be automatically detected by Terraform. To manage changes of versioning state to an S3 bucket, use the `aws_s3_bucket_versioning` resource instead. If you use `versioning` on an `aws_s3_bucket`, Terraform will assume management over the versioning state of the S3 bucket, treating additional versioning state changes as drift. For this reason, `versioning` cannot be mixed with the external `aws_s3_bucket_versioning` resource for a given S3 bucket. + +The `versioning` configuration block supports the following arguments: + +* `enabled` - (Optional) Enable versioning. Once you version-enable a bucket, it can never return to an unversioned state. You can, however, suspend versioning on that bucket. +* `mfa_delete` - (Optional) Enable MFA delete for either `Change the versioning state of your bucket` or `Permanently delete an object version`. Default is `false`. This cannot be used to toggle this setting but is available to allow managed buckets to reflect the state in AWS + ## Attributes Reference In addition to all arguments above, the following attributes are exported: @@ -388,9 +413,6 @@ In addition to all arguments above, the following attributes are exported: * `sse_algorithm` - (required) The server-side encryption algorithm used. * `bucket_key_enabled` - (Optional) Whether an [Amazon S3 Bucket Key](https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-key.html) is used for SSE-KMS. * `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). -* `versioning` - The [versioning](https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html) state of the bucket. - * `enabled` - Whether versioning is enabled. - * `mfa_delete` - Whether MFA delete is enabled. * `website` - The website configuration, if configured. * `error_document` - The name of the error document for the website. * `index_document` - The name of the index document for the website. From dbeae56d9c862e6ae4e50804a8028a95b77c642f Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Thu, 31 Mar 2022 19:37:47 -0400 Subject: [PATCH 2/2] Update CHANGELOG for #23820 --- .changelog/23820.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/23820.txt diff --git a/.changelog/23820.txt b/.changelog/23820.txt new file mode 100644 index 00000000000..e53b49cf787 --- /dev/null +++ b/.changelog/23820.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_s3_bucket: Update `versioning` parameter to be configurable. Please refer to the documentation for details on drift detection and potential conflicts when configuring this parameter with the standalone `aws_s3_bucket_versioning` resource. +``` \ No newline at end of file