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  }