updates based on feedback

This commit is contained in:
Aaron J. Smith 2018-12-04 23:17:22 -06:00
parent 1b5f12bab6
commit 9915503d9a
No known key found for this signature in database
GPG Key ID: DA7EEB938E9FF8FB
6 changed files with 80 additions and 36 deletions

View File

@ -34,6 +34,11 @@ type CombinedConfig struct {
func (c *CombinedConfig) godoClient() *godo.Client { return c.client } func (c *CombinedConfig) godoClient() *godo.Client { return c.client }
func (c *CombinedConfig) spacesClient(region string) (*session.Session, error) { func (c *CombinedConfig) spacesClient(region string) (*session.Session, error) {
if c.accessID == "" || c.secretKey == "" {
err := fmt.Errorf("Spaces credentials not configured")
return &session.Session{}, err
}
endpoint := fmt.Sprintf("https://%s.digitaloceanspaces.com", region) endpoint := fmt.Sprintf("https://%s.digitaloceanspaces.com", region)
client, err := session.NewSession(&aws.Config{ client, err := session.NewSession(&aws.Config{
Region: aws.String("us-east-1"), Region: aws.String("us-east-1"),

View File

@ -1,13 +1,16 @@
package digitalocean package digitalocean
import ( import (
"fmt"
"testing" "testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/resource"
) )
func TestAccDigitalOceanBucket_importBasic(t *testing.T) { func TestAccDigitalOceanBucket_importBasic(t *testing.T) {
resourceName := "digitalocean_bucket.foobar" resourceName := "digitalocean_bucket.bucket"
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },
@ -15,13 +18,15 @@ func TestAccDigitalOceanBucket_importBasic(t *testing.T) {
CheckDestroy: testAccCheckDigitalOceanBucketDestroy, CheckDestroy: testAccCheckDigitalOceanBucketDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: testAccDigitalOceanBucketConfigWithAcl, Config: testAccDigitalOceanBucketConfigImport(rInt),
}, },
{ {
ResourceName: resourceName, ResourceName: resourceName,
ImportState: true, ImportState: true,
ImportStateVerify: true, ImportStateVerify: true,
ImportStateIdPrefix: fmt.Sprintf("%s,", "nyc3"),
ImportStateVerifyIgnore: []string{"acl"}, // ACLs are not saved to tf state
}, },
}, },
}) })

View File

@ -17,13 +17,13 @@ func Provider() terraform.ResourceProvider {
}, },
"access_id": { "access_id": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DO_ACCESS_KEY_ID", nil), DefaultFunc: schema.EnvDefaultFunc("DO_ACCESS_KEY_ID", nil),
Description: "The access key ID for Spaces API operations.", Description: "The access key ID for Spaces API operations.",
}, },
"secret_key": { "secret_key": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Optional: true,
DefaultFunc: schema.EnvDefaultFunc("DO_SECRET_ACCESS_KEY", nil), DefaultFunc: schema.EnvDefaultFunc("DO_SECRET_ACCESS_KEY", nil),
Description: "The secret access key for Spaces API operations.", Description: "The secret access key for Spaces API operations.",
}, },

View File

@ -3,6 +3,7 @@ package digitalocean
import ( import (
"fmt" "fmt"
"log" "log"
"strings"
"time" "time"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
@ -19,7 +20,7 @@ func resourceDigitalOceanBucket() *schema.Resource {
Update: resourceDigitalOceanBucketUpdate, Update: resourceDigitalOceanBucketUpdate,
Delete: resourceDigitalOceanBucketDelete, Delete: resourceDigitalOceanBucketDelete,
Importer: &schema.ResourceImporter{ Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough, State: resourceDigitalOceanBucketImport,
}, },
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -47,12 +48,13 @@ func resourceDigitalOceanBucket() *schema.Resource {
func resourceDigitalOceanBucketCreate(d *schema.ResourceData, meta interface{}) error { func resourceDigitalOceanBucketCreate(d *schema.ResourceData, meta interface{}) error {
region := d.Get("region").(string) region := d.Get("region").(string)
client, err := meta.(*CombinedConfig).spacesClient(region) client, err := meta.(*CombinedConfig).spacesClient(region)
svc := s3.New(client)
if err != nil { if err != nil {
return fmt.Errorf("Error creating bucket: %s", err) return fmt.Errorf("Error creating bucket: %s", err)
} }
svc := s3.New(client)
input := &s3.CreateBucketInput{ input := &s3.CreateBucketInput{
Bucket: aws.String(d.Get("name").(string)), Bucket: aws.String(d.Get("name").(string)),
ACL: aws.String(d.Get("acl").(string)), ACL: aws.String(d.Get("acl").(string)),
@ -88,14 +90,15 @@ func resourceDigitalOceanBucketCreate(d *schema.ResourceData, meta interface{})
func resourceDigitalOceanBucketUpdate(d *schema.ResourceData, meta interface{}) error { func resourceDigitalOceanBucketUpdate(d *schema.ResourceData, meta interface{}) error {
region := d.Get("region").(string) region := d.Get("region").(string)
client, err := meta.(*CombinedConfig).spacesClient(region) client, err := meta.(*CombinedConfig).spacesClient(region)
svc := s3.New(client)
if err != nil { if err != nil {
return fmt.Errorf("Error updating bucket: %s", err) return fmt.Errorf("Error updating bucket: %s", err)
} }
svc := s3.New(client)
if d.HasChange("acl") { if d.HasChange("acl") {
if err := resourceDigitalOceanBucketAclUpdate(svc, d); err != nil { if err := resourceDigitalOceanBucketACLUpdate(svc, d); err != nil {
return err return err
} }
} }
@ -106,12 +109,13 @@ func resourceDigitalOceanBucketUpdate(d *schema.ResourceData, meta interface{})
func resourceDigitalOceanBucketRead(d *schema.ResourceData, meta interface{}) error { func resourceDigitalOceanBucketRead(d *schema.ResourceData, meta interface{}) error {
region := d.Get("region").(string) region := d.Get("region").(string)
client, err := meta.(*CombinedConfig).spacesClient(region) client, err := meta.(*CombinedConfig).spacesClient(region)
svc := s3.New(client)
if err != nil { if err != nil {
return fmt.Errorf("Error reading bucket: %s", err) return fmt.Errorf("Error reading bucket: %s", err)
} }
svc := s3.New(client)
_, err = retryOnAwsCode("NoSuchBucket", func() (interface{}, error) { _, err = retryOnAwsCode("NoSuchBucket", func() (interface{}, error) {
return svc.HeadBucket(&s3.HeadBucketInput{ return svc.HeadBucket(&s3.HeadBucketInput{
Bucket: aws.String(d.Id()), Bucket: aws.String(d.Id()),
@ -165,12 +169,13 @@ func resourceDigitalOceanBucketRead(d *schema.ResourceData, meta interface{}) er
func resourceDigitalOceanBucketDelete(d *schema.ResourceData, meta interface{}) error { func resourceDigitalOceanBucketDelete(d *schema.ResourceData, meta interface{}) error {
region := d.Get("region").(string) region := d.Get("region").(string)
client, err := meta.(*CombinedConfig).spacesClient(region) client, err := meta.(*CombinedConfig).spacesClient(region)
svc := s3.New(client)
if err != nil { if err != nil {
return fmt.Errorf("Error deleting bucket: %s", err) return fmt.Errorf("Error deleting bucket: %s", err)
} }
svc := s3.New(client)
log.Printf("[DEBUG] Spaces Delete Bucket: %s", d.Id()) log.Printf("[DEBUG] Spaces Delete Bucket: %s", d.Id())
_, err = svc.DeleteBucket(&s3.DeleteBucketInput{ _, err = svc.DeleteBucket(&s3.DeleteBucketInput{
Bucket: aws.String(d.Id()), Bucket: aws.String(d.Id()),
@ -239,7 +244,7 @@ func resourceDigitalOceanBucketDelete(d *schema.ResourceData, meta interface{})
return nil return nil
} }
func resourceDigitalOceanBucketAclUpdate(svc *s3.S3, d *schema.ResourceData) error { func resourceDigitalOceanBucketACLUpdate(svc *s3.S3, d *schema.ResourceData) error {
acl := d.Get("acl").(string) acl := d.Get("acl").(string)
bucket := d.Get("name").(string) bucket := d.Get("name").(string)
@ -259,6 +264,25 @@ func resourceDigitalOceanBucketAclUpdate(svc *s3.S3, d *schema.ResourceData) err
return nil return nil
} }
func resourceDigitalOceanBucketImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
if strings.Contains(d.Id(), ",") {
s := strings.Split(d.Id(), ",")
d.SetId(s[1])
d.Set("region", s[0])
}
err := resourceDigitalOceanBucketRead(d, meta)
if err != nil {
return nil, fmt.Errorf("unable to import bucket: %v", err)
}
results := make([]*schema.ResourceData, 0)
results = append(results, d)
return results, nil
}
func bucketDomainName(bucket string, region string) string { func bucketDomainName(bucket string, region string) string {
return fmt.Sprintf("%q.%q.digitaloceanspaces.com", bucket, region) return fmt.Sprintf("%q.%q.digitaloceanspaces.com", bucket, region)
} }

View File

@ -66,8 +66,8 @@ func TestAccDigitalOceanBucket_region(t *testing.T) {
func TestAccDigitalOceanBucket_UpdateAcl(t *testing.T) { func TestAccDigitalOceanBucket_UpdateAcl(t *testing.T) {
ri := acctest.RandInt() ri := acctest.RandInt()
preConfig := fmt.Sprintf(testAccDigitalOceanBucketConfigWithAcl, ri) preConfig := fmt.Sprintf(testAccDigitalOceanBucketConfigWithACL, ri)
postConfig := fmt.Sprintf(testAccDigitalOceanBucketConfigWithAclUpdate, ri) postConfig := fmt.Sprintf(testAccDigitalOceanBucketConfigWithACLUpdate, ri)
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },
@ -121,23 +121,25 @@ func testAccCheckDigitalOceanBucketDestroy(s *terraform.State) error {
} }
func testAccCheckDigitalOceanBucketDestroyWithProvider(s *terraform.State, provider *schema.Provider) error { func testAccCheckDigitalOceanBucketDestroyWithProvider(s *terraform.State, provider *schema.Provider) error {
sesh, err := session.NewSession(&aws.Config{
Region: aws.String("nyc3"),
Credentials: credentials.NewStaticCredentials(os.Getenv("DO_ACCESS_KEY_ID"), os.Getenv("DO_SECRET_ACCESS_KEY"), "")},
)
svc := s3.New(sesh, &aws.Config{
Endpoint: aws.String("https://nyc3.digitaloceanspaces.com")},
)
if err != nil {
log.Fatal(err)
}
for _, rs := range s.RootModule().Resources { for _, rs := range s.RootModule().Resources {
sesh, err := session.NewSession(&aws.Config{
Region: aws.String(rs.Primary.Attributes["region"]),
Credentials: credentials.NewStaticCredentials(os.Getenv("DO_ACCESS_KEY_ID"), os.Getenv("DO_SECRET_ACCESS_KEY"), "")},
)
svc := s3.New(sesh, &aws.Config{
Endpoint: aws.String(fmt.Sprintf("https://%s.digitaloceanspaces.com", rs.Primary.Attributes["region"]))},
)
if err != nil {
log.Fatal(err)
}
if rs.Type != "digitalocean_bucket" { if rs.Type != "digitalocean_bucket" {
continue continue
} }
_, err := svc.DeleteBucket(&s3.DeleteBucketInput{ _, err = svc.DeleteBucket(&s3.DeleteBucketInput{
Bucket: aws.String(rs.Primary.ID), Bucket: aws.String(rs.Primary.ID),
}) })
if err != nil { if err != nil {
@ -166,11 +168,11 @@ func testAccCheckDigitalOceanBucketExistsWithProvider(n string, providerF func()
} }
sesh, err := session.NewSession(&aws.Config{ sesh, err := session.NewSession(&aws.Config{
Region: aws.String("nyc3"), Region: aws.String(rs.Primary.Attributes["region"]),
Credentials: credentials.NewStaticCredentials(os.Getenv("DO_ACCESS_KEY_ID"), os.Getenv("DO_SECRET_ACCESS_KEY"), "")}, Credentials: credentials.NewStaticCredentials(os.Getenv("DO_ACCESS_KEY_ID"), os.Getenv("DO_SECRET_ACCESS_KEY"), "")},
) )
svc := s3.New(sesh, &aws.Config{ svc := s3.New(sesh, &aws.Config{
Endpoint: aws.String("https://nyc3.digitaloceanspaces.com")}, Endpoint: aws.String(fmt.Sprintf("https://%s.digitaloceanspaces.com", rs.Primary.Attributes["region"]))},
) )
if err != nil { if err != nil {
@ -204,11 +206,11 @@ func testAccCheckDigitalOceanDestroyBucket(n string) resource.TestCheckFunc {
} }
sesh, err := session.NewSession(&aws.Config{ sesh, err := session.NewSession(&aws.Config{
Region: aws.String("nyc3"), Region: aws.String(rs.Primary.Attributes["region"]),
Credentials: credentials.NewStaticCredentials(os.Getenv("DO_ACCESS_KEY_ID"), os.Getenv("DO_SECRET_ACCESS_KEY"), "")}, Credentials: credentials.NewStaticCredentials(os.Getenv("DO_ACCESS_KEY_ID"), os.Getenv("DO_SECRET_ACCESS_KEY"), "")},
) )
svc := s3.New(sesh, &aws.Config{ svc := s3.New(sesh, &aws.Config{
Endpoint: aws.String("https://nyc3.digitaloceanspaces.com")}, Endpoint: aws.String(fmt.Sprintf("https://%s.digitaloceanspaces.com", rs.Primary.Attributes["region"]))},
) )
if err != nil { if err != nil {
@ -266,14 +268,22 @@ resource "digitalocean_bucket" "bucket" {
`, randInt) `, randInt)
} }
var testAccDigitalOceanBucketConfigWithAcl = ` func testAccDigitalOceanBucketConfigImport(randInt int) string {
return fmt.Sprintf(`
resource "digitalocean_bucket" "bucket" {
name = "tf-test-bucket-%d"
}
`, randInt)
}
var testAccDigitalOceanBucketConfigWithACL = `
resource "digitalocean_bucket" "bucket" { resource "digitalocean_bucket" "bucket" {
name = "tf-test-bucket-%d" name = "tf-test-bucket-%d"
acl = "public-read" acl = "public-read"
} }
` `
var testAccDigitalOceanBucketConfigWithAclUpdate = ` var testAccDigitalOceanBucketConfigWithACLUpdate = `
resource "digitalocean_bucket" "bucket" { resource "digitalocean_bucket" "bucket" {
name = "tf-test-bucket-%d" name = "tf-test-bucket-%d"
acl = "private" acl = "private"

View File

@ -49,8 +49,8 @@ The following attributes are exported:
## Import ## Import
Buckets can be imported using the `name`, e.g. Buckets can be imported using the `region` and `name` attributes (delimited by a comma):
``` ```
terraform import digitalocean_bucket.foobar `name` terraform import digitalocean_bucket.foobar `region`,`name`
``` ```