From 0fbfd71f9670c800c35299f9e0e40986bbe8abbf Mon Sep 17 00:00:00 2001 From: Kazunori Kojima Date: Wed, 5 Aug 2015 11:09:31 +0900 Subject: [PATCH] Allows S3 bucket versioning configuration --- .../providers/aws/resource_aws_s3_bucket.go | 56 ++++++++++++++ .../aws/resource_aws_s3_bucket_test.go | 76 +++++++++++++++++++ 2 files changed, 132 insertions(+) diff --git a/builtin/providers/aws/resource_aws_s3_bucket.go b/builtin/providers/aws/resource_aws_s3_bucket.go index 0e07ee733..134efb7aa 100644 --- a/builtin/providers/aws/resource_aws_s3_bucket.go +++ b/builtin/providers/aws/resource_aws_s3_bucket.go @@ -88,6 +88,12 @@ func resourceAwsS3Bucket() *schema.Resource { Computed: true, }, + "versioning": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "tags": tagsSchema(), "force_destroy": &schema.Schema{ @@ -151,6 +157,12 @@ func resourceAwsS3BucketUpdate(d *schema.ResourceData, meta interface{}) error { } } + if d.HasChange("versioning") { + if err := resourceAwsS3BucketVersioningUpdate(s3conn, d); err != nil { + return err + } + } + return resourceAwsS3BucketRead(d, meta) } @@ -218,6 +230,26 @@ func resourceAwsS3BucketRead(d *schema.ResourceData, meta interface{}) error { return err } + // Read the versioning configuration + versioning, err := s3conn.GetBucketVersioning(&s3.GetBucketVersioningInput{ + Bucket: aws.String(d.Id()), + }) + if err != nil { + return err + } + log.Printf("[DEBUG] S3 Bucket: %s, versioning: %v", d.Id(), versioning) + if versioning.Status != nil { + var versioningStatus bool + if *versioning.Status == s3.BucketVersioningStatusEnabled { + versioningStatus = true + } else { + versioningStatus = false + } + if err := d.Set("versioning", versioningStatus); err != nil { + return err + } + } + // Add the region as an attribute location, err := s3conn.GetBucketLocation( &s3.GetBucketLocationInput{ @@ -459,6 +491,30 @@ func WebsiteDomainUrl(region string) string { return fmt.Sprintf("s3-website-%s.amazonaws.com", region) } +func resourceAwsS3BucketVersioningUpdate(s3conn *s3.S3, d *schema.ResourceData) error { + v := d.Get("versioning").(bool) + bucket := d.Get("bucket").(string) + + vc := &s3.VersioningConfiguration{} + if v { + vc.Status = aws.String(s3.BucketVersioningStatusEnabled) + } else { + vc.Status = aws.String(s3.BucketVersioningStatusSuspended) + } + i := &s3.PutBucketVersioningInput{ + Bucket: aws.String(bucket), + VersioningConfiguration: vc, + } + log.Printf("[DEBUG] S3 put bucket versioning: %#v", i) + + _, err := s3conn.PutBucketVersioning(i) + if err != nil { + return fmt.Errorf("Error putting S3 versioning: %s", err) + } + + return nil +} + func normalizeJson(jsonString interface{}) string { if jsonString == nil { return "" diff --git a/builtin/providers/aws/resource_aws_s3_bucket_test.go b/builtin/providers/aws/resource_aws_s3_bucket_test.go index 69b061986..04c126d54 100644 --- a/builtin/providers/aws/resource_aws_s3_bucket_test.go +++ b/builtin/providers/aws/resource_aws_s3_bucket_test.go @@ -154,6 +154,40 @@ func TestAccAWSS3Bucket_shouldFailNotFound(t *testing.T) { }) } +func TestAccAWSS3Bucket_Versioning(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSS3BucketDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSS3BucketConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"), + testAccCheckAWSS3BucketVersioning( + "aws_s3_bucket.bucket", ""), + ), + }, + resource.TestStep{ + Config: testAccAWSS3BucketConfigWithVersioning, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"), + testAccCheckAWSS3BucketVersioning( + "aws_s3_bucket.bucket", s3.BucketVersioningStatusEnabled), + ), + }, + resource.TestStep{ + Config: testAccAWSS3BucketConfigWithDisableVersioning, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"), + testAccCheckAWSS3BucketVersioning( + "aws_s3_bucket.bucket", s3.BucketVersioningStatusSuspended), + ), + }, + }, + }) +} + func testAccCheckAWSS3BucketDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).s3conn @@ -310,6 +344,33 @@ func testAccCheckAWSS3BucketWebsite(n string, indexDoc string, errorDoc string, } } +func testAccCheckAWSS3BucketVersioning(n string, versioningStatus string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, _ := s.RootModule().Resources[n] + conn := testAccProvider.Meta().(*AWSClient).s3conn + + out, err := conn.GetBucketVersioning(&s3.GetBucketVersioningInput{ + Bucket: aws.String(rs.Primary.ID), + }) + + if err != nil { + return fmt.Errorf("GetBucketVersioning error: %v", err) + } + + if v := out.Status; v == nil { + if versioningStatus != "" { + return fmt.Errorf("bad error versioning status, found nil, expected: %s", versioningStatus) + } + } else { + if *v != versioningStatus { + return fmt.Errorf("bad error versioning status, expected: %s, got %s", versioningStatus, *v) + } + } + + return nil + } +} + // These need a bit of randomness as the name can only be used once globally // within AWS var randInt = rand.New(rand.NewSource(time.Now().UnixNano())).Int() @@ -372,3 +433,18 @@ resource "aws_s3_bucket" "bucket" { acl = "public-read" } `, destroyedName) +var testAccAWSS3BucketConfigWithVersioning = fmt.Sprintf(` +resource "aws_s3_bucket" "bucket" { + bucket = "tf-test-bucket-%d" + acl = "public-read" + versioning = true +} +`, randInt) + +var testAccAWSS3BucketConfigWithDisableVersioning = fmt.Sprintf(` +resource "aws_s3_bucket" "bucket" { + bucket = "tf-test-bucket-%d" + acl = "public-read" + versioning = false +} +`, randInt)