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