github.com/gwilym/terraform@v0.3.8-0.20151231151641-c7573de75b19/builtin/providers/aws/resource_aws_s3_bucket_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"math/rand"
     7  	"reflect"
     8  	"regexp"
     9  	"strconv"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/hashicorp/terraform/helper/resource"
    14  	"github.com/hashicorp/terraform/terraform"
    15  
    16  	"github.com/aws/aws-sdk-go/aws"
    17  	"github.com/aws/aws-sdk-go/aws/awserr"
    18  	"github.com/aws/aws-sdk-go/service/s3"
    19  )
    20  
    21  func TestAccAWSS3Bucket_basic(t *testing.T) {
    22  
    23  	arnRegexp := regexp.MustCompile(
    24  		"^arn:aws:s3:::")
    25  
    26  	resource.Test(t, resource.TestCase{
    27  		PreCheck:     func() { testAccPreCheck(t) },
    28  		Providers:    testAccProviders,
    29  		CheckDestroy: testAccCheckAWSS3BucketDestroy,
    30  		Steps: []resource.TestStep{
    31  			resource.TestStep{
    32  				Config: testAccAWSS3BucketConfig,
    33  				Check: resource.ComposeTestCheckFunc(
    34  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
    35  					resource.TestCheckResourceAttr(
    36  						"aws_s3_bucket.bucket", "hosted_zone_id", HostedZoneIDForRegion("us-west-2")),
    37  					resource.TestCheckResourceAttr(
    38  						"aws_s3_bucket.bucket", "region", "us-west-2"),
    39  					resource.TestCheckResourceAttr(
    40  						"aws_s3_bucket.bucket", "website_endpoint", ""),
    41  					resource.TestMatchResourceAttr(
    42  						"aws_s3_bucket.bucket", "arn", arnRegexp),
    43  				),
    44  			},
    45  		},
    46  	})
    47  }
    48  
    49  func TestAccAWSS3Bucket_Policy(t *testing.T) {
    50  	resource.Test(t, resource.TestCase{
    51  		PreCheck:     func() { testAccPreCheck(t) },
    52  		Providers:    testAccProviders,
    53  		CheckDestroy: testAccCheckAWSS3BucketDestroy,
    54  		Steps: []resource.TestStep{
    55  			resource.TestStep{
    56  				Config: testAccAWSS3BucketConfigWithPolicy,
    57  				Check: resource.ComposeTestCheckFunc(
    58  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
    59  					testAccCheckAWSS3BucketPolicy(
    60  						"aws_s3_bucket.bucket", testAccAWSS3BucketPolicy),
    61  				),
    62  			},
    63  			resource.TestStep{
    64  				Config: testAccAWSS3BucketConfig,
    65  				Check: resource.ComposeTestCheckFunc(
    66  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
    67  					testAccCheckAWSS3BucketPolicy(
    68  						"aws_s3_bucket.bucket", ""),
    69  				),
    70  			},
    71  		},
    72  	})
    73  }
    74  
    75  func TestAccAWSS3Bucket_UpdateAcl(t *testing.T) {
    76  
    77  	ri := genRandInt()
    78  	preConfig := fmt.Sprintf(testAccAWSS3BucketConfigWithAcl, ri)
    79  	postConfig := fmt.Sprintf(testAccAWSS3BucketConfigWithAclUpdate, ri)
    80  
    81  	resource.Test(t, resource.TestCase{
    82  		PreCheck:     func() { testAccPreCheck(t) },
    83  		Providers:    testAccProviders,
    84  		CheckDestroy: testAccCheckAWSS3BucketDestroy,
    85  		Steps: []resource.TestStep{
    86  			resource.TestStep{
    87  				Config: preConfig,
    88  				Check: resource.ComposeTestCheckFunc(
    89  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
    90  					resource.TestCheckResourceAttr(
    91  						"aws_s3_bucket.bucket", "acl", "public-read"),
    92  				),
    93  			},
    94  			resource.TestStep{
    95  				Config: postConfig,
    96  				Check: resource.ComposeTestCheckFunc(
    97  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
    98  					resource.TestCheckResourceAttr(
    99  						"aws_s3_bucket.bucket", "acl", "private"),
   100  				),
   101  			},
   102  		},
   103  	})
   104  }
   105  
   106  func TestAccAWSS3Bucket_Website_Simple(t *testing.T) {
   107  	resource.Test(t, resource.TestCase{
   108  		PreCheck:     func() { testAccPreCheck(t) },
   109  		Providers:    testAccProviders,
   110  		CheckDestroy: testAccCheckAWSS3BucketDestroy,
   111  		Steps: []resource.TestStep{
   112  			resource.TestStep{
   113  				Config: testAccAWSS3BucketWebsiteConfig,
   114  				Check: resource.ComposeTestCheckFunc(
   115  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
   116  					testAccCheckAWSS3BucketWebsite(
   117  						"aws_s3_bucket.bucket", "index.html", "", ""),
   118  					resource.TestCheckResourceAttr(
   119  						"aws_s3_bucket.bucket", "website_endpoint", testAccWebsiteEndpoint),
   120  				),
   121  			},
   122  			resource.TestStep{
   123  				Config: testAccAWSS3BucketWebsiteConfigWithError,
   124  				Check: resource.ComposeTestCheckFunc(
   125  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
   126  					testAccCheckAWSS3BucketWebsite(
   127  						"aws_s3_bucket.bucket", "index.html", "error.html", ""),
   128  					resource.TestCheckResourceAttr(
   129  						"aws_s3_bucket.bucket", "website_endpoint", testAccWebsiteEndpoint),
   130  				),
   131  			},
   132  			resource.TestStep{
   133  				Config: testAccAWSS3BucketConfig,
   134  				Check: resource.ComposeTestCheckFunc(
   135  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
   136  					testAccCheckAWSS3BucketWebsite(
   137  						"aws_s3_bucket.bucket", "", "", ""),
   138  					resource.TestCheckResourceAttr(
   139  						"aws_s3_bucket.bucket", "website_endpoint", ""),
   140  				),
   141  			},
   142  		},
   143  	})
   144  }
   145  
   146  func TestAccAWSS3Bucket_WebsiteRedirect(t *testing.T) {
   147  	resource.Test(t, resource.TestCase{
   148  		PreCheck:     func() { testAccPreCheck(t) },
   149  		Providers:    testAccProviders,
   150  		CheckDestroy: testAccCheckAWSS3BucketDestroy,
   151  		Steps: []resource.TestStep{
   152  			resource.TestStep{
   153  				Config: testAccAWSS3BucketWebsiteConfigWithRedirect,
   154  				Check: resource.ComposeTestCheckFunc(
   155  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
   156  					testAccCheckAWSS3BucketWebsite(
   157  						"aws_s3_bucket.bucket", "", "", "hashicorp.com"),
   158  					resource.TestCheckResourceAttr(
   159  						"aws_s3_bucket.bucket", "website_endpoint", testAccWebsiteEndpoint),
   160  				),
   161  			},
   162  			resource.TestStep{
   163  				Config: testAccAWSS3BucketConfig,
   164  				Check: resource.ComposeTestCheckFunc(
   165  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
   166  					testAccCheckAWSS3BucketWebsite(
   167  						"aws_s3_bucket.bucket", "", "", ""),
   168  					resource.TestCheckResourceAttr(
   169  						"aws_s3_bucket.bucket", "website_endpoint", ""),
   170  				),
   171  			},
   172  		},
   173  	})
   174  }
   175  
   176  // Test TestAccAWSS3Bucket_shouldFailNotFound is designed to fail with a "plan
   177  // not empty" error in Terraform, to check against regresssions.
   178  // See https://github.com/hashicorp/terraform/pull/2925
   179  func TestAccAWSS3Bucket_shouldFailNotFound(t *testing.T) {
   180  	resource.Test(t, resource.TestCase{
   181  		PreCheck:     func() { testAccPreCheck(t) },
   182  		Providers:    testAccProviders,
   183  		CheckDestroy: testAccCheckAWSS3BucketDestroy,
   184  		Steps: []resource.TestStep{
   185  			resource.TestStep{
   186  				Config: testAccAWSS3BucketDestroyedConfig,
   187  				Check: resource.ComposeTestCheckFunc(
   188  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
   189  					testAccCheckAWSS3DestroyBucket("aws_s3_bucket.bucket"),
   190  				),
   191  			},
   192  		},
   193  	})
   194  }
   195  
   196  func TestAccAWSS3Bucket_Versioning(t *testing.T) {
   197  	resource.Test(t, resource.TestCase{
   198  		PreCheck:     func() { testAccPreCheck(t) },
   199  		Providers:    testAccProviders,
   200  		CheckDestroy: testAccCheckAWSS3BucketDestroy,
   201  		Steps: []resource.TestStep{
   202  			resource.TestStep{
   203  				Config: testAccAWSS3BucketConfig,
   204  				Check: resource.ComposeTestCheckFunc(
   205  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
   206  					testAccCheckAWSS3BucketVersioning(
   207  						"aws_s3_bucket.bucket", ""),
   208  				),
   209  			},
   210  			resource.TestStep{
   211  				Config: testAccAWSS3BucketConfigWithVersioning,
   212  				Check: resource.ComposeTestCheckFunc(
   213  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
   214  					testAccCheckAWSS3BucketVersioning(
   215  						"aws_s3_bucket.bucket", s3.BucketVersioningStatusEnabled),
   216  				),
   217  			},
   218  			resource.TestStep{
   219  				Config: testAccAWSS3BucketConfigWithDisableVersioning,
   220  				Check: resource.ComposeTestCheckFunc(
   221  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
   222  					testAccCheckAWSS3BucketVersioning(
   223  						"aws_s3_bucket.bucket", s3.BucketVersioningStatusSuspended),
   224  				),
   225  			},
   226  		},
   227  	})
   228  }
   229  
   230  func TestAccAWSS3Bucket_Cors(t *testing.T) {
   231  	resource.Test(t, resource.TestCase{
   232  		PreCheck:     func() { testAccPreCheck(t) },
   233  		Providers:    testAccProviders,
   234  		CheckDestroy: testAccCheckAWSS3BucketDestroy,
   235  		Steps: []resource.TestStep{
   236  			resource.TestStep{
   237  				Config: testAccAWSS3BucketConfigWithCORS,
   238  				Check: resource.ComposeTestCheckFunc(
   239  					testAccCheckAWSS3BucketExists("aws_s3_bucket.bucket"),
   240  					testAccCheckAWSS3BucketCors(
   241  						"aws_s3_bucket.bucket",
   242  						[]*s3.CORSRule{
   243  							&s3.CORSRule{
   244  								AllowedHeaders: []*string{aws.String("*")},
   245  								AllowedMethods: []*string{aws.String("PUT"), aws.String("POST")},
   246  								AllowedOrigins: []*string{aws.String("https://www.example.com")},
   247  								ExposeHeaders:  []*string{aws.String("x-amz-server-side-encryption"), aws.String("ETag")},
   248  								MaxAgeSeconds:  aws.Int64(3000),
   249  							},
   250  						},
   251  					),
   252  				),
   253  			},
   254  		},
   255  	})
   256  }
   257  
   258  func testAccCheckAWSS3BucketDestroy(s *terraform.State) error {
   259  	conn := testAccProvider.Meta().(*AWSClient).s3conn
   260  
   261  	for _, rs := range s.RootModule().Resources {
   262  		if rs.Type != "aws_s3_bucket" {
   263  			continue
   264  		}
   265  		_, err := conn.DeleteBucket(&s3.DeleteBucketInput{
   266  			Bucket: aws.String(rs.Primary.ID),
   267  		})
   268  		if err != nil {
   269  			if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoSuchBucket" {
   270  				return nil
   271  			}
   272  			return err
   273  		}
   274  	}
   275  	return nil
   276  }
   277  
   278  func testAccCheckAWSS3BucketExists(n string) resource.TestCheckFunc {
   279  	return func(s *terraform.State) error {
   280  		rs, ok := s.RootModule().Resources[n]
   281  		if !ok {
   282  			return fmt.Errorf("Not found: %s", n)
   283  		}
   284  
   285  		if rs.Primary.ID == "" {
   286  			return fmt.Errorf("No S3 Bucket ID is set")
   287  		}
   288  
   289  		conn := testAccProvider.Meta().(*AWSClient).s3conn
   290  		_, err := conn.HeadBucket(&s3.HeadBucketInput{
   291  			Bucket: aws.String(rs.Primary.ID),
   292  		})
   293  
   294  		if err != nil {
   295  			return fmt.Errorf("S3Bucket error: %v", err)
   296  		}
   297  		return nil
   298  	}
   299  }
   300  
   301  func testAccCheckAWSS3DestroyBucket(n string) resource.TestCheckFunc {
   302  	return func(s *terraform.State) error {
   303  		rs, ok := s.RootModule().Resources[n]
   304  		if !ok {
   305  			return fmt.Errorf("Not found: %s", n)
   306  		}
   307  
   308  		if rs.Primary.ID == "" {
   309  			return fmt.Errorf("No S3 Bucket ID is set")
   310  		}
   311  
   312  		conn := testAccProvider.Meta().(*AWSClient).s3conn
   313  		_, err := conn.DeleteBucket(&s3.DeleteBucketInput{
   314  			Bucket: aws.String(rs.Primary.ID),
   315  		})
   316  
   317  		if err != nil {
   318  			return fmt.Errorf("Error destroying Bucket (%s) in testAccCheckAWSS3DestroyBucket: %s", rs.Primary.ID, err)
   319  		}
   320  		return nil
   321  	}
   322  }
   323  
   324  func testAccCheckAWSS3BucketPolicy(n string, policy string) resource.TestCheckFunc {
   325  	return func(s *terraform.State) error {
   326  		rs, _ := s.RootModule().Resources[n]
   327  		conn := testAccProvider.Meta().(*AWSClient).s3conn
   328  
   329  		out, err := conn.GetBucketPolicy(&s3.GetBucketPolicyInput{
   330  			Bucket: aws.String(rs.Primary.ID),
   331  		})
   332  
   333  		if err != nil {
   334  			if policy == "" {
   335  				// expected
   336  				return nil
   337  			} else {
   338  				return fmt.Errorf("GetBucketPolicy error: %v, expected %s", err, policy)
   339  			}
   340  		}
   341  
   342  		if v := out.Policy; v == nil {
   343  			if policy != "" {
   344  				return fmt.Errorf("bad policy, found nil, expected: %s", policy)
   345  			}
   346  		} else {
   347  			expected := make(map[string]interface{})
   348  			if err := json.Unmarshal([]byte(policy), &expected); err != nil {
   349  				return err
   350  			}
   351  			actual := make(map[string]interface{})
   352  			if err := json.Unmarshal([]byte(*v), &actual); err != nil {
   353  				return err
   354  			}
   355  
   356  			if !reflect.DeepEqual(expected, actual) {
   357  				return fmt.Errorf("bad policy, expected: %#v, got %#v", expected, actual)
   358  			}
   359  		}
   360  
   361  		return nil
   362  	}
   363  }
   364  func testAccCheckAWSS3BucketWebsite(n string, indexDoc string, errorDoc string, redirectTo string) resource.TestCheckFunc {
   365  	return func(s *terraform.State) error {
   366  		rs, _ := s.RootModule().Resources[n]
   367  		conn := testAccProvider.Meta().(*AWSClient).s3conn
   368  
   369  		out, err := conn.GetBucketWebsite(&s3.GetBucketWebsiteInput{
   370  			Bucket: aws.String(rs.Primary.ID),
   371  		})
   372  
   373  		if err != nil {
   374  			if indexDoc == "" {
   375  				// If we want to assert that the website is not there, than
   376  				// this error is expected
   377  				return nil
   378  			} else {
   379  				return fmt.Errorf("S3BucketWebsite error: %v", err)
   380  			}
   381  		}
   382  
   383  		if v := out.IndexDocument; v == nil {
   384  			if indexDoc != "" {
   385  				return fmt.Errorf("bad index doc, found nil, expected: %s", indexDoc)
   386  			}
   387  		} else {
   388  			if *v.Suffix != indexDoc {
   389  				return fmt.Errorf("bad index doc, expected: %s, got %#v", indexDoc, out.IndexDocument)
   390  			}
   391  		}
   392  
   393  		if v := out.ErrorDocument; v == nil {
   394  			if errorDoc != "" {
   395  				return fmt.Errorf("bad error doc, found nil, expected: %s", errorDoc)
   396  			}
   397  		} else {
   398  			if *v.Key != errorDoc {
   399  				return fmt.Errorf("bad error doc, expected: %s, got %#v", errorDoc, out.ErrorDocument)
   400  			}
   401  		}
   402  
   403  		if v := out.RedirectAllRequestsTo; v == nil {
   404  			if redirectTo != "" {
   405  				return fmt.Errorf("bad redirect to, found nil, expected: %s", redirectTo)
   406  			}
   407  		} else {
   408  			if *v.HostName != redirectTo {
   409  				return fmt.Errorf("bad redirect to, expected: %s, got %#v", redirectTo, out.RedirectAllRequestsTo)
   410  			}
   411  		}
   412  
   413  		return nil
   414  	}
   415  }
   416  
   417  func testAccCheckAWSS3BucketVersioning(n string, versioningStatus string) resource.TestCheckFunc {
   418  	return func(s *terraform.State) error {
   419  		rs, _ := s.RootModule().Resources[n]
   420  		conn := testAccProvider.Meta().(*AWSClient).s3conn
   421  
   422  		out, err := conn.GetBucketVersioning(&s3.GetBucketVersioningInput{
   423  			Bucket: aws.String(rs.Primary.ID),
   424  		})
   425  
   426  		if err != nil {
   427  			return fmt.Errorf("GetBucketVersioning error: %v", err)
   428  		}
   429  
   430  		if v := out.Status; v == nil {
   431  			if versioningStatus != "" {
   432  				return fmt.Errorf("bad error versioning status, found nil, expected: %s", versioningStatus)
   433  			}
   434  		} else {
   435  			if *v != versioningStatus {
   436  				return fmt.Errorf("bad error versioning status, expected: %s, got %s", versioningStatus, *v)
   437  			}
   438  		}
   439  
   440  		return nil
   441  	}
   442  }
   443  func testAccCheckAWSS3BucketCors(n string, corsRules []*s3.CORSRule) resource.TestCheckFunc {
   444  	return func(s *terraform.State) error {
   445  		rs, _ := s.RootModule().Resources[n]
   446  		conn := testAccProvider.Meta().(*AWSClient).s3conn
   447  
   448  		out, err := conn.GetBucketCors(&s3.GetBucketCorsInput{
   449  			Bucket: aws.String(rs.Primary.ID),
   450  		})
   451  
   452  		if err != nil {
   453  			return fmt.Errorf("GetBucketCors error: %v", err)
   454  		}
   455  
   456  		if !reflect.DeepEqual(out.CORSRules, corsRules) {
   457  			return fmt.Errorf("bad error cors rule, expected: %v, got %v", corsRules, out.CORSRules)
   458  		}
   459  
   460  		return nil
   461  	}
   462  }
   463  
   464  // These need a bit of randomness as the name can only be used once globally
   465  // within AWS
   466  var randInt = rand.New(rand.NewSource(time.Now().UnixNano())).Int()
   467  var testAccWebsiteEndpoint = fmt.Sprintf("tf-test-bucket-%d.s3-website-us-west-2.amazonaws.com", randInt)
   468  var testAccAWSS3BucketPolicy = fmt.Sprintf(`{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::tf-test-bucket-%d/*" } ] }`, randInt)
   469  
   470  var testAccAWSS3BucketConfig = fmt.Sprintf(`
   471  resource "aws_s3_bucket" "bucket" {
   472  	bucket = "tf-test-bucket-%d"
   473  	acl = "public-read"
   474  }
   475  `, randInt)
   476  
   477  var testAccAWSS3BucketWebsiteConfig = fmt.Sprintf(`
   478  resource "aws_s3_bucket" "bucket" {
   479  	bucket = "tf-test-bucket-%d"
   480  	acl = "public-read"
   481  
   482  	website {
   483  		index_document = "index.html"
   484  	}
   485  }
   486  `, randInt)
   487  
   488  var testAccAWSS3BucketWebsiteConfigWithError = fmt.Sprintf(`
   489  resource "aws_s3_bucket" "bucket" {
   490  	bucket = "tf-test-bucket-%d"
   491  	acl = "public-read"
   492  
   493  	website {
   494  		index_document = "index.html"
   495  		error_document = "error.html"
   496  	}
   497  }
   498  `, randInt)
   499  
   500  var testAccAWSS3BucketWebsiteConfigWithRedirect = fmt.Sprintf(`
   501  resource "aws_s3_bucket" "bucket" {
   502  	bucket = "tf-test-bucket-%d"
   503  	acl = "public-read"
   504  
   505  	website {
   506  		redirect_all_requests_to = "hashicorp.com"
   507  	}
   508  }
   509  `, randInt)
   510  
   511  var testAccAWSS3BucketConfigWithPolicy = fmt.Sprintf(`
   512  resource "aws_s3_bucket" "bucket" {
   513  	bucket = "tf-test-bucket-%d"
   514  	acl = "public-read"
   515  	policy = %s
   516  }
   517  `, randInt, strconv.Quote(testAccAWSS3BucketPolicy))
   518  
   519  var destroyedName = fmt.Sprintf("tf-test-bucket-%d", randInt)
   520  var testAccAWSS3BucketDestroyedConfig = fmt.Sprintf(`
   521  resource "aws_s3_bucket" "bucket" {
   522  	bucket = "%s"
   523  	acl = "public-read"
   524  }
   525  `, destroyedName)
   526  var testAccAWSS3BucketConfigWithVersioning = fmt.Sprintf(`
   527  resource "aws_s3_bucket" "bucket" {
   528  	bucket = "tf-test-bucket-%d"
   529  	acl = "public-read"
   530  	versioning {
   531  	  enabled = true
   532  	}
   533  }
   534  `, randInt)
   535  
   536  var testAccAWSS3BucketConfigWithDisableVersioning = fmt.Sprintf(`
   537  resource "aws_s3_bucket" "bucket" {
   538  	bucket = "tf-test-bucket-%d"
   539  	acl = "public-read"
   540  	versioning {
   541  	  enabled = false
   542  	}
   543  }
   544  `, randInt)
   545  
   546  var testAccAWSS3BucketConfigWithCORS = fmt.Sprintf(`
   547  resource "aws_s3_bucket" "bucket" {
   548  	bucket = "tf-test-bucket-%d"
   549  	acl = "public-read"
   550  	cors_rule {
   551  			allowed_headers = ["*"]
   552  			allowed_methods = ["PUT","POST"]
   553  			allowed_origins = ["https://www.example.com"]
   554  			expose_headers = ["x-amz-server-side-encryption","ETag"]
   555  			max_age_seconds = 3000
   556  	}
   557  }
   558  `, randInt)
   559  
   560  var testAccAWSS3BucketConfigWithAcl = `
   561  resource "aws_s3_bucket" "bucket" {
   562  	bucket = "tf-test-bucket-%d"
   563  	acl = "public-read"
   564  }
   565  `
   566  
   567  var testAccAWSS3BucketConfigWithAclUpdate = `
   568  resource "aws_s3_bucket" "bucket" {
   569  	bucket = "tf-test-bucket-%d"
   570  	acl = "private"
   571  }
   572  `