diff --git a/builtin/providers/aws/resource_aws_s3_bucket.go b/builtin/providers/aws/resource_aws_s3_bucket.go new file mode 100644 index 000000000..3dc3f7a2f --- /dev/null +++ b/builtin/providers/aws/resource_aws_s3_bucket.go @@ -0,0 +1,93 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform/helper/config" + "github.com/hashicorp/terraform/helper/diff" + "github.com/hashicorp/terraform/terraform" + "github.com/mitchellh/goamz/s3" +) + +func resource_aws_s3_bucket_validation() *config.Validator { + return &config.Validator{ + Required: []string{ + "bucket", + }, + Optional: []string{ + "acl", + }, + } +} + +func resource_aws_s3_bucket_create( + s *terraform.ResourceState, + d *terraform.ResourceDiff, + meta interface{}) (*terraform.ResourceState, error) { + p := meta.(*ResourceProvider) + s3conn := p.s3conn + + // Merge the diff into the state so that we have all the attributes + // properly. + rs := s.MergeDiff(d) + + // Get the bucket and optional acl + bucket := rs.Attributes["bucket"] + acl := "private" + if other, ok := rs.Attributes["acl"]; ok { + acl = other + } + + log.Printf("[DEBUG] S3 bucket create: %s, ACL: %s", bucket, acl) + s3Bucket := s3conn.Bucket(bucket) + err := s3Bucket.PutBucket(s3.ACL(acl)) + if err != nil { + return nil, fmt.Errorf("Error creating S3 bucket: %s", err) + } + + // Assign the bucket name as the resource ID + rs.ID = bucket + return rs, nil +} + +func resource_aws_s3_bucket_destroy( + s *terraform.ResourceState, + meta interface{}) error { + p := meta.(*ResourceProvider) + s3conn := p.s3conn + + name := s.Attributes["bucket"] + bucket := s3conn.Bucket(name) + + log.Printf("[DEBUG] S3 Delete Bucket: %s", name) + return bucket.DelBucket() +} + +func resource_aws_s3_bucket_refresh( + s *terraform.ResourceState, + meta interface{}) (*terraform.ResourceState, error) { + p := meta.(*ResourceProvider) + s3conn := p.s3conn + + bucket := s3conn.Bucket(s.Attributes["bucket"]) + resp, err := bucket.Head("/") + if err != nil { + return s, err + } + defer resp.Body.Close() + return s, nil +} + +func resource_aws_s3_bucket_diff( + s *terraform.ResourceState, + c *terraform.ResourceConfig, + meta interface{}) (*terraform.ResourceDiff, error) { + + b := &diff.ResourceBuilder{ + Attrs: map[string]diff.AttrType{ + "bucket": diff.AttrTypeCreate, + }, + } + return b.Diff(s, c) +} diff --git a/builtin/providers/aws/resource_aws_s3_bucket_test.go b/builtin/providers/aws/resource_aws_s3_bucket_test.go new file mode 100644 index 000000000..99b65ceae --- /dev/null +++ b/builtin/providers/aws/resource_aws_s3_bucket_test.go @@ -0,0 +1,72 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSS3Bucket(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.bar"), + ), + }, + }, + }) +} + +func testAccCheckAWSS3BucketDestroy(s *terraform.State) error { + conn := testAccProvider.s3conn + + for _, rs := range s.Resources { + if rs.Type != "aws_s3_bucket" { + continue + } + + bucket := conn.Bucket(rs.ID) + resp, err := bucket.Head("/") + if err == nil { + return fmt.Errorf("S3Bucket still exists") + } + defer resp.Body.Close() + } + return nil +} + +func testAccCheckAWSS3BucketExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.ID == "" { + return fmt.Errorf("No S3 Bucket ID is set") + } + + conn := testAccProvider.s3conn + bucket := conn.Bucket(rs.ID) + resp, err := bucket.Head("/") + if err != nil { + return fmt.Errorf("S3Bucket error: %v", err) + } + defer resp.Body.Close() + return nil + } +} + +const testAccAWSS3BucketConfig = ` +resource "aws_s3_bucket" "bar" { + bucket = "tf-test-bucket" + acl = "public-read" +} +` diff --git a/builtin/providers/aws/resource_provider.go b/builtin/providers/aws/resource_provider.go index 38ddbeba7..2a640a2a7 100644 --- a/builtin/providers/aws/resource_provider.go +++ b/builtin/providers/aws/resource_provider.go @@ -9,6 +9,7 @@ import ( "github.com/mitchellh/goamz/autoscaling" "github.com/mitchellh/goamz/ec2" "github.com/mitchellh/goamz/elb" + "github.com/mitchellh/goamz/s3" ) type ResourceProvider struct { @@ -17,6 +18,7 @@ type ResourceProvider struct { ec2conn *ec2.EC2 elbconn *elb.ELB autoscalingconn *autoscaling.AutoScaling + s3conn *s3.S3 } func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) { @@ -63,6 +65,8 @@ func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error { p.elbconn = elb.New(auth, region) log.Println("[INFO] Initializing AutoScaling connection") p.autoscalingconn = autoscaling.New(auth, region) + log.Println("[INFO] Initializing S3 connection") + p.s3conn = s3.New(auth, region) } if len(errs) > 0 { diff --git a/builtin/providers/aws/resources.go b/builtin/providers/aws/resources.go index d49953de0..1a442b669 100644 --- a/builtin/providers/aws/resources.go +++ b/builtin/providers/aws/resources.go @@ -94,6 +94,14 @@ func init() { Update: resource_aws_route_table_association_update, }, + "aws_s3_bucket": resource.Resource{ + ConfigValidator: resource_aws_s3_bucket_validation(), + Create: resource_aws_s3_bucket_create, + Destroy: resource_aws_s3_bucket_destroy, + Diff: resource_aws_s3_bucket_diff, + Refresh: resource_aws_s3_bucket_refresh, + }, + "aws_security_group": resource.Resource{ ConfigValidator: resource_aws_security_group_validation(), Create: resource_aws_security_group_create,