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