github.com/gabrielperezs/terraform@v0.7.0-rc2.0.20160715084931-f7da2612946f/builtin/providers/aws/resource_aws_cloudfront_distribution.go (about) 1 package aws 2 3 import ( 4 "log" 5 "time" 6 7 "github.com/aws/aws-sdk-go/aws" 8 "github.com/aws/aws-sdk-go/service/cloudfront" 9 "github.com/hashicorp/terraform/helper/resource" 10 "github.com/hashicorp/terraform/helper/schema" 11 ) 12 13 func resourceAwsCloudFrontDistribution() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceAwsCloudFrontDistributionCreate, 16 Read: resourceAwsCloudFrontDistributionRead, 17 Update: resourceAwsCloudFrontDistributionUpdate, 18 Delete: resourceAwsCloudFrontDistributionDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "aliases": &schema.Schema{ 22 Type: schema.TypeSet, 23 Optional: true, 24 Elem: &schema.Schema{Type: schema.TypeString}, 25 Set: aliasesHash, 26 }, 27 "cache_behavior": &schema.Schema{ 28 Type: schema.TypeSet, 29 Optional: true, 30 Set: cacheBehaviorHash, 31 Elem: &schema.Resource{ 32 Schema: map[string]*schema.Schema{ 33 "allowed_methods": &schema.Schema{ 34 Type: schema.TypeList, 35 Required: true, 36 Elem: &schema.Schema{Type: schema.TypeString}, 37 }, 38 "cached_methods": &schema.Schema{ 39 Type: schema.TypeList, 40 Required: true, 41 Elem: &schema.Schema{Type: schema.TypeString}, 42 }, 43 "compress": &schema.Schema{ 44 Type: schema.TypeBool, 45 Optional: true, 46 Default: false, 47 }, 48 "default_ttl": &schema.Schema{ 49 Type: schema.TypeInt, 50 Required: true, 51 }, 52 "forwarded_values": &schema.Schema{ 53 Type: schema.TypeSet, 54 Required: true, 55 Set: forwardedValuesHash, 56 MaxItems: 1, 57 Elem: &schema.Resource{ 58 Schema: map[string]*schema.Schema{ 59 "cookies": &schema.Schema{ 60 Type: schema.TypeSet, 61 Required: true, 62 Set: cookiePreferenceHash, 63 MaxItems: 1, 64 Elem: &schema.Resource{ 65 Schema: map[string]*schema.Schema{ 66 "forward": &schema.Schema{ 67 Type: schema.TypeString, 68 Required: true, 69 }, 70 "whitelisted_names": &schema.Schema{ 71 Type: schema.TypeList, 72 Optional: true, 73 Elem: &schema.Schema{Type: schema.TypeString}, 74 }, 75 }, 76 }, 77 }, 78 "headers": &schema.Schema{ 79 Type: schema.TypeList, 80 Optional: true, 81 Elem: &schema.Schema{Type: schema.TypeString}, 82 }, 83 "query_string": &schema.Schema{ 84 Type: schema.TypeBool, 85 Required: true, 86 }, 87 }, 88 }, 89 }, 90 "max_ttl": &schema.Schema{ 91 Type: schema.TypeInt, 92 Required: true, 93 }, 94 "min_ttl": &schema.Schema{ 95 Type: schema.TypeInt, 96 Required: true, 97 }, 98 "path_pattern": &schema.Schema{ 99 Type: schema.TypeString, 100 Required: true, 101 }, 102 "smooth_streaming": &schema.Schema{ 103 Type: schema.TypeBool, 104 Optional: true, 105 }, 106 "target_origin_id": &schema.Schema{ 107 Type: schema.TypeString, 108 Required: true, 109 }, 110 "trusted_signers": &schema.Schema{ 111 Type: schema.TypeList, 112 Optional: true, 113 Elem: &schema.Schema{Type: schema.TypeString}, 114 }, 115 "viewer_protocol_policy": &schema.Schema{ 116 Type: schema.TypeString, 117 Required: true, 118 }, 119 }, 120 }, 121 }, 122 "comment": &schema.Schema{ 123 Type: schema.TypeString, 124 Optional: true, 125 }, 126 "custom_error_response": &schema.Schema{ 127 Type: schema.TypeSet, 128 Optional: true, 129 Set: customErrorResponseHash, 130 Elem: &schema.Resource{ 131 Schema: map[string]*schema.Schema{ 132 "error_caching_min_ttl": &schema.Schema{ 133 Type: schema.TypeInt, 134 Optional: true, 135 }, 136 "error_code": &schema.Schema{ 137 Type: schema.TypeInt, 138 Required: true, 139 }, 140 "response_code": &schema.Schema{ 141 Type: schema.TypeInt, 142 Optional: true, 143 }, 144 "response_page_path": &schema.Schema{ 145 Type: schema.TypeString, 146 Optional: true, 147 }, 148 }, 149 }, 150 }, 151 "default_cache_behavior": &schema.Schema{ 152 Type: schema.TypeSet, 153 Required: true, 154 Set: defaultCacheBehaviorHash, 155 MaxItems: 1, 156 Elem: &schema.Resource{ 157 Schema: map[string]*schema.Schema{ 158 "allowed_methods": &schema.Schema{ 159 Type: schema.TypeList, 160 Required: true, 161 Elem: &schema.Schema{Type: schema.TypeString}, 162 }, 163 "cached_methods": &schema.Schema{ 164 Type: schema.TypeList, 165 Required: true, 166 Elem: &schema.Schema{Type: schema.TypeString}, 167 }, 168 "compress": &schema.Schema{ 169 Type: schema.TypeBool, 170 Optional: true, 171 Default: false, 172 }, 173 "default_ttl": &schema.Schema{ 174 Type: schema.TypeInt, 175 Required: true, 176 }, 177 "forwarded_values": &schema.Schema{ 178 Type: schema.TypeSet, 179 Required: true, 180 Set: forwardedValuesHash, 181 MaxItems: 1, 182 Elem: &schema.Resource{ 183 Schema: map[string]*schema.Schema{ 184 "cookies": &schema.Schema{ 185 Type: schema.TypeSet, 186 Optional: true, 187 Set: cookiePreferenceHash, 188 MaxItems: 1, 189 Elem: &schema.Resource{ 190 Schema: map[string]*schema.Schema{ 191 "forward": &schema.Schema{ 192 Type: schema.TypeString, 193 Required: true, 194 }, 195 "whitelisted_names": &schema.Schema{ 196 Type: schema.TypeList, 197 Optional: true, 198 Elem: &schema.Schema{Type: schema.TypeString}, 199 }, 200 }, 201 }, 202 }, 203 "headers": &schema.Schema{ 204 Type: schema.TypeList, 205 Optional: true, 206 Elem: &schema.Schema{Type: schema.TypeString}, 207 }, 208 "query_string": &schema.Schema{ 209 Type: schema.TypeBool, 210 Required: true, 211 }, 212 }, 213 }, 214 }, 215 "max_ttl": &schema.Schema{ 216 Type: schema.TypeInt, 217 Required: true, 218 }, 219 "min_ttl": &schema.Schema{ 220 Type: schema.TypeInt, 221 Required: true, 222 }, 223 "smooth_streaming": &schema.Schema{ 224 Type: schema.TypeBool, 225 Optional: true, 226 }, 227 "target_origin_id": &schema.Schema{ 228 Type: schema.TypeString, 229 Required: true, 230 }, 231 "trusted_signers": &schema.Schema{ 232 Type: schema.TypeList, 233 Optional: true, 234 Elem: &schema.Schema{Type: schema.TypeString}, 235 }, 236 "viewer_protocol_policy": &schema.Schema{ 237 Type: schema.TypeString, 238 Required: true, 239 }, 240 }, 241 }, 242 }, 243 "default_root_object": &schema.Schema{ 244 Type: schema.TypeString, 245 Optional: true, 246 }, 247 "enabled": &schema.Schema{ 248 Type: schema.TypeBool, 249 Required: true, 250 }, 251 "logging_config": &schema.Schema{ 252 Type: schema.TypeSet, 253 Optional: true, 254 Set: loggingConfigHash, 255 MaxItems: 1, 256 Elem: &schema.Resource{ 257 Schema: map[string]*schema.Schema{ 258 "bucket": &schema.Schema{ 259 Type: schema.TypeString, 260 Required: true, 261 }, 262 "include_cookies": &schema.Schema{ 263 Type: schema.TypeBool, 264 Optional: true, 265 Default: false, 266 }, 267 "prefix": &schema.Schema{ 268 Type: schema.TypeString, 269 Optional: true, 270 Default: "", 271 }, 272 }, 273 }, 274 }, 275 "origin": &schema.Schema{ 276 Type: schema.TypeSet, 277 Required: true, 278 Set: originHash, 279 Elem: &schema.Resource{ 280 Schema: map[string]*schema.Schema{ 281 "custom_origin_config": &schema.Schema{ 282 Type: schema.TypeSet, 283 Optional: true, 284 ConflictsWith: []string{"origin.s3_origin_config"}, 285 Set: customOriginConfigHash, 286 MaxItems: 1, 287 Elem: &schema.Resource{ 288 Schema: map[string]*schema.Schema{ 289 "http_port": &schema.Schema{ 290 Type: schema.TypeInt, 291 Required: true, 292 }, 293 "https_port": &schema.Schema{ 294 Type: schema.TypeInt, 295 Required: true, 296 }, 297 "origin_protocol_policy": &schema.Schema{ 298 Type: schema.TypeString, 299 Required: true, 300 }, 301 "origin_ssl_protocols": &schema.Schema{ 302 Type: schema.TypeList, 303 Required: true, 304 Elem: &schema.Schema{Type: schema.TypeString}, 305 }, 306 }, 307 }, 308 }, 309 "domain_name": &schema.Schema{ 310 Type: schema.TypeString, 311 Required: true, 312 }, 313 "custom_header": &schema.Schema{ 314 Type: schema.TypeSet, 315 Optional: true, 316 Set: originCustomHeaderHash, 317 Elem: &schema.Resource{ 318 Schema: map[string]*schema.Schema{ 319 "name": &schema.Schema{ 320 Type: schema.TypeString, 321 Required: true, 322 }, 323 "value": &schema.Schema{ 324 Type: schema.TypeString, 325 Required: true, 326 }, 327 }, 328 }, 329 }, 330 "origin_id": &schema.Schema{ 331 Type: schema.TypeString, 332 Required: true, 333 }, 334 "origin_path": &schema.Schema{ 335 Type: schema.TypeString, 336 Optional: true, 337 }, 338 "s3_origin_config": &schema.Schema{ 339 Type: schema.TypeSet, 340 Optional: true, 341 ConflictsWith: []string{"origin.custom_origin_config"}, 342 Set: s3OriginConfigHash, 343 MaxItems: 1, 344 Elem: &schema.Resource{ 345 Schema: map[string]*schema.Schema{ 346 "origin_access_identity": &schema.Schema{ 347 Type: schema.TypeString, 348 Optional: true, 349 Default: "", 350 }, 351 }, 352 }, 353 }, 354 }, 355 }, 356 }, 357 "price_class": &schema.Schema{ 358 Type: schema.TypeString, 359 Optional: true, 360 Default: "PriceClass_All", 361 }, 362 "restrictions": &schema.Schema{ 363 Type: schema.TypeSet, 364 Required: true, 365 Set: restrictionsHash, 366 MaxItems: 1, 367 Elem: &schema.Resource{ 368 Schema: map[string]*schema.Schema{ 369 "geo_restriction": &schema.Schema{ 370 Type: schema.TypeSet, 371 Required: true, 372 Set: geoRestrictionHash, 373 MaxItems: 1, 374 Elem: &schema.Resource{ 375 Schema: map[string]*schema.Schema{ 376 "locations": &schema.Schema{ 377 Type: schema.TypeList, 378 Optional: true, 379 Elem: &schema.Schema{Type: schema.TypeString}, 380 }, 381 "restriction_type": &schema.Schema{ 382 Type: schema.TypeString, 383 Required: true, 384 }, 385 }, 386 }, 387 }, 388 }, 389 }, 390 }, 391 "viewer_certificate": &schema.Schema{ 392 Type: schema.TypeSet, 393 Required: true, 394 Set: viewerCertificateHash, 395 MaxItems: 1, 396 Elem: &schema.Resource{ 397 Schema: map[string]*schema.Schema{ 398 "acm_certificate_arn": &schema.Schema{ 399 Type: schema.TypeString, 400 Optional: true, 401 ConflictsWith: []string{"viewer_certificate.cloudfront_default_certificate", "viewer_certificate.iam_certificate_id"}, 402 }, 403 "cloudfront_default_certificate": &schema.Schema{ 404 Type: schema.TypeBool, 405 Optional: true, 406 ConflictsWith: []string{"viewer_certificate.acm_certificate_arn", "viewer_certificate.iam_certificate_id"}, 407 }, 408 "iam_certificate_id": &schema.Schema{ 409 Type: schema.TypeString, 410 Optional: true, 411 ConflictsWith: []string{"viewer_certificate.acm_certificate_arn", "viewer_certificate.cloudfront_default_certificate"}, 412 }, 413 "minimum_protocol_version": &schema.Schema{ 414 Type: schema.TypeString, 415 Optional: true, 416 Default: "SSLv3", 417 }, 418 "ssl_support_method": &schema.Schema{ 419 Type: schema.TypeString, 420 Optional: true, 421 }, 422 }, 423 }, 424 }, 425 "web_acl_id": &schema.Schema{ 426 Type: schema.TypeString, 427 Optional: true, 428 }, 429 "caller_reference": &schema.Schema{ 430 Type: schema.TypeString, 431 Computed: true, 432 }, 433 "status": &schema.Schema{ 434 Type: schema.TypeString, 435 Computed: true, 436 }, 437 "active_trusted_signers": &schema.Schema{ 438 Type: schema.TypeMap, 439 Computed: true, 440 }, 441 "domain_name": &schema.Schema{ 442 Type: schema.TypeString, 443 Computed: true, 444 }, 445 "last_modified_time": &schema.Schema{ 446 Type: schema.TypeString, 447 Computed: true, 448 }, 449 "in_progress_validation_batches": &schema.Schema{ 450 Type: schema.TypeInt, 451 Computed: true, 452 }, 453 "etag": &schema.Schema{ 454 Type: schema.TypeString, 455 Computed: true, 456 }, 457 "hosted_zone_id": &schema.Schema{ 458 Type: schema.TypeString, 459 Computed: true, 460 }, 461 // retain_on_delete is a non-API attribute that may help facilitate speedy 462 // deletion of a resoruce. It's mainly here for testing purposes, so 463 // enable at your own risk. 464 "retain_on_delete": &schema.Schema{ 465 Type: schema.TypeBool, 466 Optional: true, 467 Default: false, 468 }, 469 }, 470 } 471 } 472 473 func resourceAwsCloudFrontDistributionCreate(d *schema.ResourceData, meta interface{}) error { 474 conn := meta.(*AWSClient).cloudfrontconn 475 params := &cloudfront.CreateDistributionInput{ 476 DistributionConfig: expandDistributionConfig(d), 477 } 478 479 resp, err := conn.CreateDistribution(params) 480 if err != nil { 481 return err 482 } 483 d.SetId(*resp.Distribution.Id) 484 return resourceAwsCloudFrontDistributionRead(d, meta) 485 } 486 487 func resourceAwsCloudFrontDistributionRead(d *schema.ResourceData, meta interface{}) error { 488 conn := meta.(*AWSClient).cloudfrontconn 489 params := &cloudfront.GetDistributionInput{ 490 Id: aws.String(d.Id()), 491 } 492 493 resp, err := conn.GetDistribution(params) 494 if err != nil { 495 return err 496 } 497 498 // Update attributes from DistributionConfig 499 err = flattenDistributionConfig(d, resp.Distribution.DistributionConfig) 500 if err != nil { 501 return err 502 } 503 // Update other attributes outside of DistributionConfig 504 d.SetId(*resp.Distribution.Id) 505 err = d.Set("active_trusted_signers", flattenActiveTrustedSigners(resp.Distribution.ActiveTrustedSigners)) 506 if err != nil { 507 return err 508 } 509 d.Set("status", resp.Distribution.Status) 510 d.Set("domain_name", resp.Distribution.DomainName) 511 d.Set("last_modified_time", aws.String(resp.Distribution.LastModifiedTime.String())) 512 d.Set("in_progress_validation_batches", resp.Distribution.InProgressInvalidationBatches) 513 d.Set("etag", resp.ETag) 514 return nil 515 } 516 517 func resourceAwsCloudFrontDistributionUpdate(d *schema.ResourceData, meta interface{}) error { 518 conn := meta.(*AWSClient).cloudfrontconn 519 params := &cloudfront.UpdateDistributionInput{ 520 Id: aws.String(d.Id()), 521 DistributionConfig: expandDistributionConfig(d), 522 IfMatch: aws.String(d.Get("etag").(string)), 523 } 524 _, err := conn.UpdateDistribution(params) 525 if err != nil { 526 return err 527 } 528 529 return resourceAwsCloudFrontDistributionRead(d, meta) 530 } 531 532 func resourceAwsCloudFrontDistributionDelete(d *schema.ResourceData, meta interface{}) error { 533 conn := meta.(*AWSClient).cloudfrontconn 534 535 // manually disable the distribution first 536 d.Set("enabled", false) 537 err := resourceAwsCloudFrontDistributionUpdate(d, meta) 538 if err != nil { 539 return err 540 } 541 542 // skip delete if retain_on_delete is enabled 543 if d.Get("retain_on_delete").(bool) { 544 log.Printf("[WARN] Removing Distribtuion ID %s with retain_on_delete set. Please delete this distribution manually.", d.Id()) 545 d.SetId("") 546 return nil 547 } 548 549 // Distribution needs to be in deployed state again before it can be deleted. 550 err = resourceAwsCloudFrontDistributionWaitUntilDeployed(d.Id(), meta) 551 if err != nil { 552 return err 553 } 554 555 // now delete 556 params := &cloudfront.DeleteDistributionInput{ 557 Id: aws.String(d.Id()), 558 IfMatch: aws.String(d.Get("etag").(string)), 559 } 560 561 _, err = conn.DeleteDistribution(params) 562 if err != nil { 563 return err 564 } 565 566 // Done 567 d.SetId("") 568 return nil 569 } 570 571 // resourceAwsCloudFrontWebDistributionWaitUntilDeployed blocks until the 572 // distribution is deployed. It currently takes exactly 15 minutes to deploy 573 // but that might change in the future. 574 func resourceAwsCloudFrontDistributionWaitUntilDeployed(id string, meta interface{}) error { 575 stateConf := &resource.StateChangeConf{ 576 Pending: []string{"InProgress", "Deployed"}, 577 Target: []string{"Deployed"}, 578 Refresh: resourceAwsCloudFrontWebDistributionStateRefreshFunc(id, meta), 579 Timeout: 40 * time.Minute, 580 MinTimeout: 15 * time.Second, 581 Delay: 10 * time.Minute, 582 } 583 584 _, err := stateConf.WaitForState() 585 return err 586 } 587 588 // The refresh function for resourceAwsCloudFrontWebDistributionWaitUntilDeployed. 589 func resourceAwsCloudFrontWebDistributionStateRefreshFunc(id string, meta interface{}) resource.StateRefreshFunc { 590 return func() (interface{}, string, error) { 591 conn := meta.(*AWSClient).cloudfrontconn 592 params := &cloudfront.GetDistributionInput{ 593 Id: aws.String(id), 594 } 595 596 resp, err := conn.GetDistribution(params) 597 if err != nil { 598 log.Printf("Error on retrieving CloudFront distribution when waiting: %s", err) 599 return nil, "", err 600 } 601 602 if resp == nil { 603 return nil, "", nil 604 } 605 606 return resp.Distribution, *resp.Distribution.Status, nil 607 } 608 }