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