github.com/andresvia/terraform@v0.6.15-0.20160412045437-d51c75946785/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 }