291 lines
8.1 KiB
Go
291 lines
8.1 KiB
Go
![]() |
package digitalocean
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"log"
|
||
![]() |
"os"
|
||
![]() |
"strings"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/hashicorp/terraform/helper/acctest"
|
||
|
"github.com/hashicorp/terraform/helper/resource"
|
||
|
"github.com/hashicorp/terraform/terraform"
|
||
|
|
||
|
"github.com/aws/aws-sdk-go/aws"
|
||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||
|
"github.com/aws/aws-sdk-go/aws/session"
|
||
|
"github.com/aws/aws-sdk-go/service/s3"
|
||
|
"github.com/hashicorp/terraform/helper/schema"
|
||
|
)
|
||
|
|
||
|
func TestAccDigitalOceanBucket_basic(t *testing.T) {
|
||
|
rInt := acctest.RandInt()
|
||
|
|
||
|
resource.Test(t, resource.TestCase{
|
||
|
PreCheck: func() { testAccPreCheck(t) },
|
||
|
/*
|
||
![]() |
IDRefreshName: "digitalocean_spaces_bucket.bucket",
|
||
![]() |
IDRefreshIgnore: []string{"force_destroy"},
|
||
|
*/
|
||
|
Providers: testAccProviders,
|
||
|
CheckDestroy: testAccCheckDigitalOceanBucketDestroy,
|
||
|
Steps: []resource.TestStep{
|
||
|
{
|
||
|
Config: testAccDigitalOceanBucketConfig(rInt),
|
||
|
Check: resource.ComposeTestCheckFunc(
|
||
![]() |
testAccCheckDigitalOceanBucketExists("digitalocean_spaces_bucket.bucket"),
|
||
![]() |
resource.TestCheckResourceAttr(
|
||
![]() |
"digitalocean_spaces_bucket.bucket", "region", "nyc3"),
|
||
![]() |
resource.TestCheckResourceAttr(
|
||
![]() |
"digitalocean_spaces_bucket.bucket", "name", testAccBucketName(rInt)),
|
||
![]() |
),
|
||
|
},
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestAccDigitalOceanBucket_region(t *testing.T) {
|
||
|
rInt := acctest.RandInt()
|
||
|
|
||
|
resource.Test(t, resource.TestCase{
|
||
|
PreCheck: func() { testAccPreCheck(t) },
|
||
|
Providers: testAccProviders,
|
||
|
CheckDestroy: testAccCheckDigitalOceanBucketDestroy,
|
||
|
Steps: []resource.TestStep{
|
||
|
{
|
||
|
Config: testAccDigitalOceanBucketConfigWithRegion(rInt),
|
||
|
Check: resource.ComposeTestCheckFunc(
|
||
![]() |
testAccCheckDigitalOceanBucketExists("digitalocean_spaces_bucket.bucket"),
|
||
|
resource.TestCheckResourceAttr("digitalocean_spaces_bucket.bucket", "region", "ams3"),
|
||
![]() |
),
|
||
|
},
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestAccDigitalOceanBucket_UpdateAcl(t *testing.T) {
|
||
|
ri := acctest.RandInt()
|
||
![]() |
preConfig := fmt.Sprintf(testAccDigitalOceanBucketConfigWithACL, ri)
|
||
|
postConfig := fmt.Sprintf(testAccDigitalOceanBucketConfigWithACLUpdate, ri)
|
||
![]() |
|
||
|
resource.Test(t, resource.TestCase{
|
||
|
PreCheck: func() { testAccPreCheck(t) },
|
||
|
Providers: testAccProviders,
|
||
|
CheckDestroy: testAccCheckDigitalOceanBucketDestroy,
|
||
|
Steps: []resource.TestStep{
|
||
|
{
|
||
|
Config: preConfig,
|
||
|
Check: resource.ComposeTestCheckFunc(
|
||
![]() |
testAccCheckDigitalOceanBucketExists("digitalocean_spaces_bucket.bucket"),
|
||
![]() |
resource.TestCheckResourceAttr(
|
||
![]() |
"digitalocean_spaces_bucket.bucket", "acl", "public-read"),
|
||
![]() |
),
|
||
|
},
|
||
|
{
|
||
|
Config: postConfig,
|
||
|
Check: resource.ComposeTestCheckFunc(
|
||
![]() |
testAccCheckDigitalOceanBucketExists("digitalocean_spaces_bucket.bucket"),
|
||
![]() |
resource.TestCheckResourceAttr(
|
||
![]() |
"digitalocean_spaces_bucket.bucket", "acl", "private"),
|
||
![]() |
),
|
||
|
},
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
|
||
|
// Test TestAccDigitalOceanBucket_shouldFailNotFound is designed to fail with a "plan
|
||
|
// not empty" error in Terraform, to check against regresssions.
|
||
|
// See https://github.com/hashicorp/terraform/pull/2925
|
||
|
func TestAccDigitalOceanBucket_shouldFailNotFound(t *testing.T) {
|
||
|
rInt := acctest.RandInt()
|
||
|
resource.Test(t, resource.TestCase{
|
||
|
PreCheck: func() { testAccPreCheck(t) },
|
||
|
Providers: testAccProviders,
|
||
|
CheckDestroy: testAccCheckDigitalOceanBucketDestroy,
|
||
|
Steps: []resource.TestStep{
|
||
|
{
|
||
|
Config: testAccDigitalOceanBucketDestroyedConfig(rInt),
|
||
|
Check: resource.ComposeTestCheckFunc(
|
||
![]() |
testAccCheckDigitalOceanBucketExists("digitalocean_spaces_bucket.bucket"),
|
||
|
testAccCheckDigitalOceanDestroyBucket("digitalocean_spaces_bucket.bucket"),
|
||
![]() |
),
|
||
|
ExpectNonEmptyPlan: true,
|
||
|
},
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func testAccCheckDigitalOceanBucketDestroy(s *terraform.State) error {
|
||
|
return testAccCheckDigitalOceanBucketDestroyWithProvider(s, testAccProvider)
|
||
|
}
|
||
|
|
||
|
func testAccCheckDigitalOceanBucketDestroyWithProvider(s *terraform.State, provider *schema.Provider) error {
|
||
|
|
||
|
for _, rs := range s.RootModule().Resources {
|
||
![]() |
sesh, err := session.NewSession(&aws.Config{
|
||
|
Region: aws.String(rs.Primary.Attributes["region"]),
|
||
![]() |
Credentials: credentials.NewStaticCredentials(os.Getenv("SPACES_ACCESS_KEY_ID"), os.Getenv("SPACES_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_spaces_bucket" {
|
||
![]() |
continue
|
||
|
}
|
||
![]() |
_, err = svc.DeleteBucket(&s3.DeleteBucketInput{
|
||
![]() |
Bucket: aws.String(rs.Primary.ID),
|
||
|
})
|
||
|
if err != nil {
|
||
|
if isAWSErr(err, s3.ErrCodeNoSuchBucket, "") {
|
||
|
return nil
|
||
|
}
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func testAccCheckDigitalOceanBucketExists(n string) resource.TestCheckFunc {
|
||
|
return testAccCheckDigitalOceanBucketExistsWithProvider(n, func() *schema.Provider { return testAccProvider })
|
||
|
}
|
||
|
|
||
|
func testAccCheckDigitalOceanBucketExistsWithProvider(n string, providerF func() *schema.Provider) resource.TestCheckFunc {
|
||
|
return func(s *terraform.State) error {
|
||
|
rs, ok := s.RootModule().Resources[n]
|
||
|
if !ok {
|
||
|
return fmt.Errorf("Not found: %s", n)
|
||
|
}
|
||
|
|
||
|
if rs.Primary.ID == "" {
|
||
|
return fmt.Errorf("No ID is set")
|
||
|
}
|
||
|
|
||
|
sesh, err := session.NewSession(&aws.Config{
|
||
![]() |
Region: aws.String(rs.Primary.Attributes["region"]),
|
||
![]() |
Credentials: credentials.NewStaticCredentials(os.Getenv("SPACES_ACCESS_KEY_ID"), os.Getenv("SPACES_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)
|
||
|
}
|
||
|
|
||
|
_, err = svc.HeadBucket(&s3.HeadBucketInput{
|
||
|
Bucket: aws.String(rs.Primary.ID),
|
||
|
})
|
||
|
|
||
|
if err != nil {
|
||
|
if isAWSErr(err, s3.ErrCodeNoSuchBucket, "") {
|
||
|
return fmt.Errorf("Spaces bucket not found")
|
||
|
}
|
||
|
return err
|
||
|
}
|
||
|
return nil
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testAccCheckDigitalOceanDestroyBucket(n string) resource.TestCheckFunc {
|
||
|
return func(s *terraform.State) error {
|
||
|
rs, ok := s.RootModule().Resources[n]
|
||
|
if !ok {
|
||
|
return fmt.Errorf("Not found: %s", n)
|
||
|
}
|
||
|
|
||
|
if rs.Primary.ID == "" {
|
||
|
return fmt.Errorf("No Spaces Bucket ID is set")
|
||
|
}
|
||
|
|
||
|
sesh, err := session.NewSession(&aws.Config{
|
||
![]() |
Region: aws.String(rs.Primary.Attributes["region"]),
|
||
![]() |
Credentials: credentials.NewStaticCredentials(os.Getenv("SPACES_ACCESS_KEY_ID"), os.Getenv("SPACES_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)
|
||
|
}
|
||
|
|
||
|
_, err = svc.DeleteBucket(&s3.DeleteBucketInput{
|
||
|
Bucket: aws.String(rs.Primary.ID),
|
||
|
})
|
||
|
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("Error destroying Bucket (%s) in testAccCheckDigitalOceanDestroyBucket: %s", rs.Primary.ID, err)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func isAWSErr(err error, code string, message string) bool {
|
||
|
if err, ok := err.(awserr.Error); ok {
|
||
|
return err.Code() == code && strings.Contains(err.Message(), message)
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// These need a bit of randomness as the name can only be used once globally
|
||
|
func testAccBucketName(randInt int) string {
|
||
|
return fmt.Sprintf("tf-test-bucket-%d", randInt)
|
||
|
}
|
||
|
|
||
|
func testAccDigitalOceanBucketConfig(randInt int) string {
|
||
|
return fmt.Sprintf(`
|
||
![]() |
resource "digitalocean_spaces_bucket" "bucket" {
|
||
![]() |
name = "tf-test-bucket-%d"
|
||
![]() |
acl = "public-read"
|
||
|
}
|
||
|
`, randInt)
|
||
|
}
|
||
|
|
||
|
func testAccDigitalOceanBucketDestroyedConfig(randInt int) string {
|
||
|
return fmt.Sprintf(`
|
||
![]() |
resource "digitalocean_spaces_bucket" "bucket" {
|
||
![]() |
name = "tf-test-bucket-%d"
|
||
![]() |
acl = "public-read"
|
||
|
}
|
||
|
`, randInt)
|
||
|
}
|
||
|
|
||
|
func testAccDigitalOceanBucketConfigWithRegion(randInt int) string {
|
||
|
return fmt.Sprintf(`
|
||
![]() |
resource "digitalocean_spaces_bucket" "bucket" {
|
||
![]() |
name = "tf-test-bucket-%d"
|
||
|
region = "ams3"
|
||
![]() |
}
|
||
|
`, randInt)
|
||
|
}
|
||
|
|
||
![]() |
func testAccDigitalOceanBucketConfigImport(randInt int) string {
|
||
|
return fmt.Sprintf(`
|
||
![]() |
resource "digitalocean_spaces_bucket" "bucket" {
|
||
![]() |
name = "tf-test-bucket-%d"
|
||
|
}
|
||
|
`, randInt)
|
||
|
}
|
||
|
|
||
|
var testAccDigitalOceanBucketConfigWithACL = `
|
||
![]() |
resource "digitalocean_spaces_bucket" "bucket" {
|
||
![]() |
name = "tf-test-bucket-%d"
|
||
![]() |
acl = "public-read"
|
||
|
}
|
||
|
`
|
||
|
|
||
![]() |
var testAccDigitalOceanBucketConfigWithACLUpdate = `
|
||
![]() |
resource "digitalocean_spaces_bucket" "bucket" {
|
||
![]() |
name = "tf-test-bucket-%d"
|
||
![]() |
acl = "private"
|
||
|
}
|
||
|
`
|