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

     1  package azurerm
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"net/http"
     7  	"regexp"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/Azure/azure-sdk-for-go/arm/network"
    12  	"github.com/hashicorp/terraform/helper/resource"
    13  	"github.com/hashicorp/terraform/helper/schema"
    14  )
    15  
    16  func resourceArmPublicIp() *schema.Resource {
    17  	return &schema.Resource{
    18  		Create: resourceArmPublicIpCreate,
    19  		Read:   resourceArmPublicIpRead,
    20  		Update: resourceArmPublicIpCreate,
    21  		Delete: resourceArmPublicIpDelete,
    22  
    23  		Schema: map[string]*schema.Schema{
    24  			"name": &schema.Schema{
    25  				Type:     schema.TypeString,
    26  				Required: true,
    27  				ForceNew: true,
    28  			},
    29  
    30  			"location": &schema.Schema{
    31  				Type:      schema.TypeString,
    32  				Required:  true,
    33  				ForceNew:  true,
    34  				StateFunc: azureRMNormalizeLocation,
    35  			},
    36  
    37  			"resource_group_name": &schema.Schema{
    38  				Type:     schema.TypeString,
    39  				Required: true,
    40  				ForceNew: true,
    41  			},
    42  
    43  			"public_ip_address_allocation": &schema.Schema{
    44  				Type:         schema.TypeString,
    45  				Required:     true,
    46  				ValidateFunc: validatePublicIpAllocation,
    47  			},
    48  
    49  			"idle_timeout_in_minutes": &schema.Schema{
    50  				Type:     schema.TypeInt,
    51  				Optional: true,
    52  				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
    53  					value := v.(int)
    54  					if value < 4 || value > 30 {
    55  						errors = append(errors, fmt.Errorf(
    56  							"The idle timeout must be between 4 and 30 minutes"))
    57  					}
    58  					return
    59  				},
    60  			},
    61  
    62  			"domain_name_label": &schema.Schema{
    63  				Type:         schema.TypeString,
    64  				Optional:     true,
    65  				ValidateFunc: validatePublicIpDomainNameLabel,
    66  			},
    67  
    68  			"reverse_fqdn": &schema.Schema{
    69  				Type:     schema.TypeString,
    70  				Optional: true,
    71  			},
    72  
    73  			"fqdn": &schema.Schema{
    74  				Type:     schema.TypeString,
    75  				Computed: true,
    76  			},
    77  
    78  			"ip_address": &schema.Schema{
    79  				Type:     schema.TypeString,
    80  				Computed: true,
    81  			},
    82  
    83  			"tags": tagsSchema(),
    84  		},
    85  	}
    86  }
    87  
    88  func resourceArmPublicIpCreate(d *schema.ResourceData, meta interface{}) error {
    89  	client := meta.(*ArmClient)
    90  	publicIPClient := client.publicIPClient
    91  
    92  	log.Printf("[INFO] preparing arguments for Azure ARM Public IP creation.")
    93  
    94  	name := d.Get("name").(string)
    95  	location := d.Get("location").(string)
    96  	resGroup := d.Get("resource_group_name").(string)
    97  	tags := d.Get("tags").(map[string]interface{})
    98  
    99  	properties := network.PublicIPAddressPropertiesFormat{
   100  		PublicIPAllocationMethod: network.IPAllocationMethod(d.Get("public_ip_address_allocation").(string)),
   101  	}
   102  
   103  	dnl, hasDnl := d.GetOk("domain_name_label")
   104  	rfqdn, hasRfqdn := d.GetOk("reverse_fqdn")
   105  
   106  	if hasDnl || hasRfqdn {
   107  		dnsSettings := network.PublicIPAddressDNSSettings{}
   108  
   109  		if hasRfqdn {
   110  			reverse_fqdn := rfqdn.(string)
   111  			dnsSettings.ReverseFqdn = &reverse_fqdn
   112  		}
   113  
   114  		if hasDnl {
   115  			domain_name_label := dnl.(string)
   116  			dnsSettings.DomainNameLabel = &domain_name_label
   117  
   118  		}
   119  
   120  		properties.DNSSettings = &dnsSettings
   121  	}
   122  
   123  	if v, ok := d.GetOk("idle_timeout_in_minutes"); ok {
   124  		idle_timeout := v.(int)
   125  		properties.IdleTimeoutInMinutes = &idle_timeout
   126  	}
   127  
   128  	publicIp := network.PublicIPAddress{
   129  		Name:       &name,
   130  		Location:   &location,
   131  		Properties: &properties,
   132  		Tags:       expandTags(tags),
   133  	}
   134  
   135  	resp, err := publicIPClient.CreateOrUpdate(resGroup, name, publicIp)
   136  	if err != nil {
   137  		return err
   138  	}
   139  
   140  	d.SetId(*resp.ID)
   141  
   142  	log.Printf("[DEBUG] Waiting for Public IP (%s) to become available", name)
   143  	stateConf := &resource.StateChangeConf{
   144  		Pending: []string{"Accepted", "Updating"},
   145  		Target:  []string{"Succeeded"},
   146  		Refresh: publicIPStateRefreshFunc(client, resGroup, name),
   147  		Timeout: 10 * time.Minute,
   148  	}
   149  	if _, err := stateConf.WaitForState(); err != nil {
   150  		return fmt.Errorf("Error waiting for Public IP (%s) to become available: %s", name, err)
   151  	}
   152  
   153  	return resourceArmPublicIpRead(d, meta)
   154  }
   155  
   156  func resourceArmPublicIpRead(d *schema.ResourceData, meta interface{}) error {
   157  	publicIPClient := meta.(*ArmClient).publicIPClient
   158  
   159  	id, err := parseAzureResourceID(d.Id())
   160  	if err != nil {
   161  		return err
   162  	}
   163  	resGroup := id.ResourceGroup
   164  	name := id.Path["publicIPAddresses"]
   165  
   166  	resp, err := publicIPClient.Get(resGroup, name, "")
   167  	if resp.StatusCode == http.StatusNotFound {
   168  		d.SetId("")
   169  		return nil
   170  	}
   171  	if err != nil {
   172  		return fmt.Errorf("Error making Read request on Azure public ip %s: %s", name, err)
   173  	}
   174  
   175  	if resp.Properties.DNSSettings != nil && resp.Properties.DNSSettings.Fqdn != nil && *resp.Properties.DNSSettings.Fqdn != "" {
   176  		d.Set("fqdn", resp.Properties.DNSSettings.Fqdn)
   177  	}
   178  
   179  	if resp.Properties.IPAddress != nil && *resp.Properties.IPAddress != "" {
   180  		d.Set("ip_address", resp.Properties.IPAddress)
   181  	}
   182  
   183  	flattenAndSetTags(d, resp.Tags)
   184  
   185  	return nil
   186  }
   187  
   188  func resourceArmPublicIpDelete(d *schema.ResourceData, meta interface{}) error {
   189  	publicIPClient := meta.(*ArmClient).publicIPClient
   190  
   191  	id, err := parseAzureResourceID(d.Id())
   192  	if err != nil {
   193  		return err
   194  	}
   195  	resGroup := id.ResourceGroup
   196  	name := id.Path["publicIPAddresses"]
   197  
   198  	_, err = publicIPClient.Delete(resGroup, name)
   199  
   200  	return err
   201  }
   202  
   203  func publicIPStateRefreshFunc(client *ArmClient, resourceGroupName string, publicIpName string) resource.StateRefreshFunc {
   204  	return func() (interface{}, string, error) {
   205  		res, err := client.publicIPClient.Get(resourceGroupName, publicIpName, "")
   206  		if err != nil {
   207  			return nil, "", fmt.Errorf("Error issuing read request in publicIPStateRefreshFunc to Azure ARM for public ip '%s' (RG: '%s'): %s", publicIpName, resourceGroupName, err)
   208  		}
   209  
   210  		return res, *res.Properties.ProvisioningState, nil
   211  	}
   212  }
   213  
   214  func validatePublicIpAllocation(v interface{}, k string) (ws []string, errors []error) {
   215  	value := strings.ToLower(v.(string))
   216  	allocations := map[string]bool{
   217  		"static":  true,
   218  		"dynamic": true,
   219  	}
   220  
   221  	if !allocations[value] {
   222  		errors = append(errors, fmt.Errorf("Public IP Allocation can only be Static of Dynamic"))
   223  	}
   224  	return
   225  }
   226  
   227  func validatePublicIpDomainNameLabel(v interface{}, k string) (ws []string, errors []error) {
   228  	value := v.(string)
   229  	if !regexp.MustCompile(`^[a-z0-9-]+$`).MatchString(value) {
   230  		errors = append(errors, fmt.Errorf(
   231  			"only alphanumeric characters and hyphens allowed in %q: %q",
   232  			k, value))
   233  	}
   234  
   235  	if len(value) > 61 {
   236  		errors = append(errors, fmt.Errorf(
   237  			"%q cannot be longer than 61 characters: %q", k, value))
   238  	}
   239  
   240  	if len(value) == 0 {
   241  		errors = append(errors, fmt.Errorf(
   242  			"%q cannot be an empty string: %q", k, value))
   243  	}
   244  	if regexp.MustCompile(`-$`).MatchString(value) {
   245  		errors = append(errors, fmt.Errorf(
   246  			"%q cannot end with a hyphen: %q", k, value))
   247  	}
   248  
   249  	return
   250  
   251  }