github.com/anfernee/terraform@v0.6.16-0.20160430000239-06e5085a92f2/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 Optional: 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 // retain_on_delete is a non-API attribute that may help facilitate speedy 458 // deletion of a resoruce. It's mainly here for testing purposes, so 459 // enable at your own risk. 460 "retain_on_delete": &schema.Schema{ 461 Type: schema.TypeBool, 462 Optional: true, 463 Default: false, 464 }, 465 }, 466 } 467 } 468 469 func resourceAwsCloudFrontDistributionCreate(d *schema.ResourceData, meta interface{}) error { 470 conn := meta.(*AWSClient).cloudfrontconn 471 params := &cloudfront.CreateDistributionInput{ 472 DistributionConfig: expandDistributionConfig(d), 473 } 474 475 resp, err := conn.CreateDistribution(params) 476 if err != nil { 477 return err 478 } 479 d.SetId(*resp.Distribution.Id) 480 return resourceAwsCloudFrontDistributionRead(d, meta) 481 } 482 483 func resourceAwsCloudFrontDistributionRead(d *schema.ResourceData, meta interface{}) error { 484 conn := meta.(*AWSClient).cloudfrontconn 485 params := &cloudfront.GetDistributionInput{ 486 Id: aws.String(d.Id()), 487 } 488 489 resp, err := conn.GetDistribution(params) 490 if err != nil { 491 return err 492 } 493 494 // Update attributes from DistributionConfig 495 err = flattenDistributionConfig(d, resp.Distribution.DistributionConfig) 496 if err != nil { 497 return err 498 } 499 // Update other attributes outside of DistributionConfig 500 d.SetId(*resp.Distribution.Id) 501 err = d.Set("active_trusted_signers", flattenActiveTrustedSigners(resp.Distribution.ActiveTrustedSigners)) 502 if err != nil { 503 return err 504 } 505 d.Set("status", resp.Distribution.Status) 506 d.Set("domain_name", resp.Distribution.DomainName) 507 d.Set("last_modified_time", aws.String(resp.Distribution.LastModifiedTime.String())) 508 d.Set("in_progress_validation_batches", resp.Distribution.InProgressInvalidationBatches) 509 d.Set("etag", resp.ETag) 510 return nil 511 } 512 513 func resourceAwsCloudFrontDistributionUpdate(d *schema.ResourceData, meta interface{}) error { 514 conn := meta.(*AWSClient).cloudfrontconn 515 params := &cloudfront.UpdateDistributionInput{ 516 Id: aws.String(d.Id()), 517 DistributionConfig: expandDistributionConfig(d), 518 IfMatch: aws.String(d.Get("etag").(string)), 519 } 520 _, err := conn.UpdateDistribution(params) 521 if err != nil { 522 return err 523 } 524 525 return resourceAwsCloudFrontDistributionRead(d, meta) 526 } 527 528 func resourceAwsCloudFrontDistributionDelete(d *schema.ResourceData, meta interface{}) error { 529 conn := meta.(*AWSClient).cloudfrontconn 530 531 // manually disable the distribution first 532 d.Set("enabled", false) 533 err := resourceAwsCloudFrontDistributionUpdate(d, meta) 534 if err != nil { 535 return err 536 } 537 538 // skip delete if retain_on_delete is enabled 539 if d.Get("retain_on_delete").(bool) { 540 log.Printf("[WARN] Removing Distribtuion ID %s with retain_on_delete set. Please delete this distribution manually.", d.Id()) 541 d.SetId("") 542 return nil 543 } 544 545 // Distribution needs to be in deployed state again before it can be deleted. 546 err = resourceAwsCloudFrontDistributionWaitUntilDeployed(d.Id(), meta) 547 if err != nil { 548 return err 549 } 550 551 // now delete 552 params := &cloudfront.DeleteDistributionInput{ 553 Id: aws.String(d.Id()), 554 IfMatch: aws.String(d.Get("etag").(string)), 555 } 556 557 _, err = conn.DeleteDistribution(params) 558 if err != nil { 559 return err 560 } 561 562 // Done 563 d.SetId("") 564 return nil 565 } 566 567 // resourceAwsCloudFrontWebDistributionWaitUntilDeployed blocks until the 568 // distribution is deployed. It currently takes exactly 15 minutes to deploy 569 // but that might change in the future. 570 func resourceAwsCloudFrontDistributionWaitUntilDeployed(id string, meta interface{}) error { 571 stateConf := &resource.StateChangeConf{ 572 Pending: []string{"InProgress", "Deployed"}, 573 Target: []string{"Deployed"}, 574 Refresh: resourceAwsCloudFrontWebDistributionStateRefreshFunc(id, meta), 575 Timeout: 40 * time.Minute, 576 MinTimeout: 15 * time.Second, 577 Delay: 10 * time.Minute, 578 } 579 580 _, err := stateConf.WaitForState() 581 return err 582 } 583 584 // The refresh function for resourceAwsCloudFrontWebDistributionWaitUntilDeployed. 585 func resourceAwsCloudFrontWebDistributionStateRefreshFunc(id string, meta interface{}) resource.StateRefreshFunc { 586 return func() (interface{}, string, error) { 587 conn := meta.(*AWSClient).cloudfrontconn 588 params := &cloudfront.GetDistributionInput{ 589 Id: aws.String(id), 590 } 591 592 resp, err := conn.GetDistribution(params) 593 if err != nil { 594 log.Printf("Error on retrieving CloudFront distribution when waiting: %s", err) 595 return nil, "", err 596 } 597 598 if resp == nil { 599 return nil, "", nil 600 } 601 602 return resp.Distribution, *resp.Distribution.Status, nil 603 } 604 }