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 `