github.com/erriapo/terraform@v0.6.12-0.20160203182612-0340ea72354f/builtin/providers/azurerm/resource_arm_cdn_endpoint.go (about)

     1  package azurerm
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"net/http"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/Azure/azure-sdk-for-go/arm/cdn"
    12  	"github.com/hashicorp/terraform/helper/hashcode"
    13  	"github.com/hashicorp/terraform/helper/resource"
    14  	"github.com/hashicorp/terraform/helper/schema"
    15  )
    16  
    17  func resourceArmCdnEndpoint() *schema.Resource {
    18  	return &schema.Resource{
    19  		Create: resourceArmCdnEndpointCreate,
    20  		Read:   resourceArmCdnEndpointRead,
    21  		Update: resourceArmCdnEndpointUpdate,
    22  		Delete: resourceArmCdnEndpointDelete,
    23  
    24  		Schema: map[string]*schema.Schema{
    25  			"name": &schema.Schema{
    26  				Type:     schema.TypeString,
    27  				Required: true,
    28  				ForceNew: true,
    29  			},
    30  
    31  			"location": &schema.Schema{
    32  				Type:      schema.TypeString,
    33  				Required:  true,
    34  				ForceNew:  true,
    35  				StateFunc: azureRMNormalizeLocation,
    36  			},
    37  
    38  			"resource_group_name": &schema.Schema{
    39  				Type:     schema.TypeString,
    40  				Required: true,
    41  				ForceNew: true,
    42  			},
    43  
    44  			"profile_name": &schema.Schema{
    45  				Type:     schema.TypeString,
    46  				Required: true,
    47  				ForceNew: true,
    48  			},
    49  
    50  			"origin_host_header": &schema.Schema{
    51  				Type:     schema.TypeString,
    52  				Optional: true,
    53  				Computed: true,
    54  			},
    55  
    56  			"is_http_allowed": &schema.Schema{
    57  				Type:     schema.TypeBool,
    58  				Optional: true,
    59  				Default:  true,
    60  			},
    61  
    62  			"is_https_allowed": &schema.Schema{
    63  				Type:     schema.TypeBool,
    64  				Optional: true,
    65  				Default:  true,
    66  			},
    67  
    68  			"origin": &schema.Schema{
    69  				Type:     schema.TypeSet,
    70  				Required: true,
    71  				Elem: &schema.Resource{
    72  					Schema: map[string]*schema.Schema{
    73  						"name": &schema.Schema{
    74  							Type:     schema.TypeString,
    75  							Required: true,
    76  						},
    77  
    78  						"host_name": &schema.Schema{
    79  							Type:     schema.TypeString,
    80  							Required: true,
    81  						},
    82  
    83  						"http_port": &schema.Schema{
    84  							Type:     schema.TypeInt,
    85  							Optional: true,
    86  							Computed: true,
    87  						},
    88  
    89  						"https_port": &schema.Schema{
    90  							Type:     schema.TypeInt,
    91  							Optional: true,
    92  							Computed: true,
    93  						},
    94  					},
    95  				},
    96  				Set: resourceArmCdnEndpointOriginHash,
    97  			},
    98  
    99  			"origin_path": &schema.Schema{
   100  				Type:     schema.TypeString,
   101  				Optional: true,
   102  				Computed: true,
   103  			},
   104  
   105  			"querystring_caching_behaviour": &schema.Schema{
   106  				Type:         schema.TypeString,
   107  				Optional:     true,
   108  				Default:      "IgnoreQueryString",
   109  				ValidateFunc: validateCdnEndpointQuerystringCachingBehaviour,
   110  			},
   111  
   112  			"content_types_to_compress": &schema.Schema{
   113  				Type:     schema.TypeSet,
   114  				Optional: true,
   115  				Computed: true,
   116  				Elem:     &schema.Schema{Type: schema.TypeString},
   117  				Set:      schema.HashString,
   118  			},
   119  
   120  			"is_compression_enabled": &schema.Schema{
   121  				Type:     schema.TypeBool,
   122  				Optional: true,
   123  				Default:  false,
   124  			},
   125  
   126  			"host_name": &schema.Schema{
   127  				Type:     schema.TypeString,
   128  				Computed: true,
   129  			},
   130  
   131  			"tags": tagsSchema(),
   132  		},
   133  	}
   134  }
   135  
   136  func resourceArmCdnEndpointCreate(d *schema.ResourceData, meta interface{}) error {
   137  	client := meta.(*ArmClient)
   138  	cdnEndpointsClient := client.cdnEndpointsClient
   139  
   140  	log.Printf("[INFO] preparing arguments for Azure ARM CDN EndPoint creation.")
   141  
   142  	name := d.Get("name").(string)
   143  	location := d.Get("location").(string)
   144  	resGroup := d.Get("resource_group_name").(string)
   145  	profileName := d.Get("profile_name").(string)
   146  	http_allowed := d.Get("is_http_allowed").(bool)
   147  	https_allowed := d.Get("is_https_allowed").(bool)
   148  	compression_enabled := d.Get("is_compression_enabled").(bool)
   149  	caching_behaviour := d.Get("querystring_caching_behaviour").(string)
   150  	tags := d.Get("tags").(map[string]interface{})
   151  
   152  	properties := cdn.EndpointPropertiesCreateUpdateParameters{
   153  		IsHTTPAllowed:              &http_allowed,
   154  		IsHTTPSAllowed:             &https_allowed,
   155  		IsCompressionEnabled:       &compression_enabled,
   156  		QueryStringCachingBehavior: cdn.QueryStringCachingBehavior(caching_behaviour),
   157  	}
   158  
   159  	origins, originsErr := expandAzureRmCdnEndpointOrigins(d)
   160  	if originsErr != nil {
   161  		return fmt.Errorf("Error Building list of CDN Endpoint Origins: %s", originsErr)
   162  	}
   163  	if len(origins) > 0 {
   164  		properties.Origins = &origins
   165  	}
   166  
   167  	if v, ok := d.GetOk("origin_host_header"); ok {
   168  		host_header := v.(string)
   169  		properties.OriginHostHeader = &host_header
   170  	}
   171  
   172  	if v, ok := d.GetOk("origin_path"); ok {
   173  		origin_path := v.(string)
   174  		properties.OriginPath = &origin_path
   175  	}
   176  
   177  	if v, ok := d.GetOk("content_types_to_compress"); ok {
   178  		var content_types []string
   179  		ctypes := v.(*schema.Set).List()
   180  		for _, ct := range ctypes {
   181  			str := ct.(string)
   182  			content_types = append(content_types, str)
   183  		}
   184  
   185  		properties.ContentTypesToCompress = &content_types
   186  	}
   187  
   188  	cdnEndpoint := cdn.EndpointCreateParameters{
   189  		Location:   &location,
   190  		Properties: &properties,
   191  		Tags:       expandTags(tags),
   192  	}
   193  
   194  	resp, err := cdnEndpointsClient.Create(name, cdnEndpoint, profileName, resGroup)
   195  	if err != nil {
   196  		return err
   197  	}
   198  
   199  	d.SetId(*resp.ID)
   200  
   201  	log.Printf("[DEBUG] Waiting for CDN Endpoint (%s) to become available", name)
   202  	stateConf := &resource.StateChangeConf{
   203  		Pending: []string{"Accepted", "Updating", "Creating"},
   204  		Target:  []string{"Succeeded"},
   205  		Refresh: cdnEndpointStateRefreshFunc(client, resGroup, profileName, name),
   206  		Timeout: 10 * time.Minute,
   207  	}
   208  	if _, err := stateConf.WaitForState(); err != nil {
   209  		return fmt.Errorf("Error waiting for CDN Endpoint (%s) to become available: %s", name, err)
   210  	}
   211  
   212  	return resourceArmCdnEndpointRead(d, meta)
   213  }
   214  
   215  func resourceArmCdnEndpointRead(d *schema.ResourceData, meta interface{}) error {
   216  	cdnEndpointsClient := meta.(*ArmClient).cdnEndpointsClient
   217  
   218  	id, err := parseAzureResourceID(d.Id())
   219  	if err != nil {
   220  		return err
   221  	}
   222  	resGroup := id.ResourceGroup
   223  	name := id.Path["endpoints"]
   224  	profileName := id.Path["profiles"]
   225  	if profileName == "" {
   226  		profileName = id.Path["Profiles"]
   227  	}
   228  	log.Printf("[INFO] Trying to find the AzureRM CDN Endpoint %s (Profile: %s, RG: %s)", name, profileName, resGroup)
   229  	resp, err := cdnEndpointsClient.Get(name, profileName, resGroup)
   230  	if resp.StatusCode == http.StatusNotFound {
   231  		d.SetId("")
   232  		return nil
   233  	}
   234  	if err != nil {
   235  		return fmt.Errorf("Error making Read request on Azure CDN Endpoint %s: %s", name, err)
   236  	}
   237  
   238  	d.Set("name", resp.Name)
   239  	d.Set("host_name", resp.Properties.HostName)
   240  	d.Set("is_compression_enabled", resp.Properties.IsCompressionEnabled)
   241  	d.Set("is_http_allowed", resp.Properties.IsHTTPAllowed)
   242  	d.Set("is_https_allowed", resp.Properties.IsHTTPSAllowed)
   243  	d.Set("querystring_caching_behaviour", resp.Properties.QueryStringCachingBehavior)
   244  	if resp.Properties.OriginHostHeader != nil && *resp.Properties.OriginHostHeader != "" {
   245  		d.Set("origin_host_header", resp.Properties.OriginHostHeader)
   246  	}
   247  	if resp.Properties.OriginPath != nil && *resp.Properties.OriginPath != "" {
   248  		d.Set("origin_path", resp.Properties.OriginPath)
   249  	}
   250  	if resp.Properties.ContentTypesToCompress != nil && len(*resp.Properties.ContentTypesToCompress) > 0 {
   251  		d.Set("content_types_to_compress", flattenAzureRMCdnEndpointContentTypes(resp.Properties.ContentTypesToCompress))
   252  	}
   253  	d.Set("origin", flattenAzureRMCdnEndpointOrigin(resp.Properties.Origins))
   254  
   255  	flattenAndSetTags(d, resp.Tags)
   256  
   257  	return nil
   258  }
   259  
   260  func resourceArmCdnEndpointUpdate(d *schema.ResourceData, meta interface{}) error {
   261  	cdnEndpointsClient := meta.(*ArmClient).cdnEndpointsClient
   262  
   263  	if !d.HasChange("tags") {
   264  		return nil
   265  	}
   266  
   267  	name := d.Get("name").(string)
   268  	resGroup := d.Get("resource_group_name").(string)
   269  	profileName := d.Get("profile_name").(string)
   270  	http_allowed := d.Get("is_http_allowed").(bool)
   271  	https_allowed := d.Get("is_https_allowed").(bool)
   272  	compression_enabled := d.Get("is_compression_enabled").(bool)
   273  	caching_behaviour := d.Get("querystring_caching_behaviour").(string)
   274  	newTags := d.Get("tags").(map[string]interface{})
   275  
   276  	properties := cdn.EndpointPropertiesCreateUpdateParameters{
   277  		IsHTTPAllowed:              &http_allowed,
   278  		IsHTTPSAllowed:             &https_allowed,
   279  		IsCompressionEnabled:       &compression_enabled,
   280  		QueryStringCachingBehavior: cdn.QueryStringCachingBehavior(caching_behaviour),
   281  	}
   282  
   283  	if d.HasChange("origin") {
   284  		origins, originsErr := expandAzureRmCdnEndpointOrigins(d)
   285  		if originsErr != nil {
   286  			return fmt.Errorf("Error Building list of CDN Endpoint Origins: %s", originsErr)
   287  		}
   288  		if len(origins) > 0 {
   289  			properties.Origins = &origins
   290  		}
   291  	}
   292  
   293  	if d.HasChange("origin_host_header") {
   294  		host_header := d.Get("origin_host_header").(string)
   295  		properties.OriginHostHeader = &host_header
   296  	}
   297  
   298  	if d.HasChange("origin_path") {
   299  		origin_path := d.Get("origin_path").(string)
   300  		properties.OriginPath = &origin_path
   301  	}
   302  
   303  	if d.HasChange("content_types_to_compress") {
   304  		var content_types []string
   305  		ctypes := d.Get("content_types_to_compress").(*schema.Set).List()
   306  		for _, ct := range ctypes {
   307  			str := ct.(string)
   308  			content_types = append(content_types, str)
   309  		}
   310  
   311  		properties.ContentTypesToCompress = &content_types
   312  	}
   313  
   314  	updateProps := cdn.EndpointUpdateParameters{
   315  		Tags:       expandTags(newTags),
   316  		Properties: &properties,
   317  	}
   318  
   319  	_, err := cdnEndpointsClient.Update(name, updateProps, profileName, resGroup)
   320  	if err != nil {
   321  		return fmt.Errorf("Error issuing Azure ARM update request to update CDN Endpoint %q: %s", name, err)
   322  	}
   323  
   324  	return resourceArmCdnEndpointRead(d, meta)
   325  }
   326  
   327  func resourceArmCdnEndpointDelete(d *schema.ResourceData, meta interface{}) error {
   328  	client := meta.(*ArmClient).cdnEndpointsClient
   329  
   330  	id, err := parseAzureResourceID(d.Id())
   331  	if err != nil {
   332  		return err
   333  	}
   334  	resGroup := id.ResourceGroup
   335  	profileName := id.Path["profiles"]
   336  	if profileName == "" {
   337  		profileName = id.Path["Profiles"]
   338  	}
   339  	name := id.Path["endpoints"]
   340  
   341  	accResp, err := client.DeleteIfExists(name, profileName, resGroup)
   342  	if err != nil {
   343  		if accResp.StatusCode == http.StatusNotFound {
   344  			return nil
   345  		}
   346  		return fmt.Errorf("Error issuing AzureRM delete request for CDN Endpoint %q: %s", name, err)
   347  	}
   348  	_, err = pollIndefinitelyAsNeeded(client.Client, accResp.Response, http.StatusNotFound)
   349  	if err != nil {
   350  		return fmt.Errorf("Error polling for AzureRM delete request for CDN Endpoint %q: %s", name, err)
   351  	}
   352  
   353  	return err
   354  }
   355  
   356  func cdnEndpointStateRefreshFunc(client *ArmClient, resourceGroupName string, profileName string, name string) resource.StateRefreshFunc {
   357  	return func() (interface{}, string, error) {
   358  		res, err := client.cdnEndpointsClient.Get(name, profileName, resourceGroupName)
   359  		if err != nil {
   360  			return nil, "", fmt.Errorf("Error issuing read request in cdnEndpointStateRefreshFunc to Azure ARM for CDN Endpoint '%s' (RG: '%s'): %s", name, resourceGroupName, err)
   361  		}
   362  		return res, string(res.Properties.ProvisioningState), nil
   363  	}
   364  }
   365  
   366  func validateCdnEndpointQuerystringCachingBehaviour(v interface{}, k string) (ws []string, errors []error) {
   367  	value := strings.ToLower(v.(string))
   368  	cachingTypes := map[string]bool{
   369  		"ignorequerystring": true,
   370  		"bypasscaching":     true,
   371  		"usequerystring":    true,
   372  	}
   373  
   374  	if !cachingTypes[value] {
   375  		errors = append(errors, fmt.Errorf("CDN Endpoint querystringCachingBehaviours can only be IgnoreQueryString, BypassCaching or UseQueryString"))
   376  	}
   377  	return
   378  }
   379  
   380  func resourceArmCdnEndpointOriginHash(v interface{}) int {
   381  	var buf bytes.Buffer
   382  	m := v.(map[string]interface{})
   383  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   384  	buf.WriteString(fmt.Sprintf("%s-", m["host_name"].(string)))
   385  
   386  	return hashcode.String(buf.String())
   387  }
   388  
   389  func expandAzureRmCdnEndpointOrigins(d *schema.ResourceData) ([]cdn.DeepCreatedOrigin, error) {
   390  	configs := d.Get("origin").(*schema.Set).List()
   391  	origins := make([]cdn.DeepCreatedOrigin, 0, len(configs))
   392  
   393  	for _, configRaw := range configs {
   394  		data := configRaw.(map[string]interface{})
   395  
   396  		host_name := data["host_name"].(string)
   397  
   398  		properties := cdn.DeepCreatedOriginProperties{
   399  			HostName: &host_name,
   400  		}
   401  
   402  		if v, ok := data["https_port"]; ok {
   403  			https_port := v.(int)
   404  			properties.HTTPSPort = &https_port
   405  
   406  		}
   407  
   408  		if v, ok := data["http_port"]; ok {
   409  			http_port := v.(int)
   410  			properties.HTTPPort = &http_port
   411  		}
   412  
   413  		name := data["name"].(string)
   414  
   415  		origin := cdn.DeepCreatedOrigin{
   416  			Name:       &name,
   417  			Properties: &properties,
   418  		}
   419  
   420  		origins = append(origins, origin)
   421  	}
   422  
   423  	return origins, nil
   424  }
   425  
   426  func flattenAzureRMCdnEndpointOrigin(list *[]cdn.DeepCreatedOrigin) []map[string]interface{} {
   427  	result := make([]map[string]interface{}, 0, len(*list))
   428  	for _, i := range *list {
   429  		l := map[string]interface{}{
   430  			"name":      *i.Name,
   431  			"host_name": *i.Properties.HostName,
   432  		}
   433  
   434  		if i.Properties.HTTPPort != nil {
   435  			l["http_port"] = *i.Properties.HTTPPort
   436  		}
   437  		if i.Properties.HTTPSPort != nil {
   438  			l["https_port"] = *i.Properties.HTTPSPort
   439  		}
   440  		result = append(result, l)
   441  	}
   442  	return result
   443  }
   444  
   445  func flattenAzureRMCdnEndpointContentTypes(list *[]string) []interface{} {
   446  	vs := make([]interface{}, 0, len(*list))
   447  	for _, v := range *list {
   448  		vs = append(vs, v)
   449  	}
   450  	return vs
   451  }