github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/builtin/providers/azurerm/resource_arm_network_interface_card.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/network" 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 resourceArmNetworkInterface() *schema.Resource { 18 return &schema.Resource{ 19 Create: resourceArmNetworkInterfaceCreate, 20 Read: resourceArmNetworkInterfaceRead, 21 Update: resourceArmNetworkInterfaceCreate, 22 Delete: resourceArmNetworkInterfaceDelete, 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 "network_security_group_id": &schema.Schema{ 45 Type: schema.TypeString, 46 Optional: true, 47 Computed: true, 48 }, 49 50 "mac_address": &schema.Schema{ 51 Type: schema.TypeString, 52 Optional: true, 53 Computed: true, 54 }, 55 56 "virtual_machine_id": &schema.Schema{ 57 Type: schema.TypeString, 58 Optional: true, 59 Computed: true, 60 }, 61 62 "ip_configuration": &schema.Schema{ 63 Type: schema.TypeSet, 64 Required: true, 65 Elem: &schema.Resource{ 66 Schema: map[string]*schema.Schema{ 67 "name": &schema.Schema{ 68 Type: schema.TypeString, 69 Required: true, 70 }, 71 72 "subnet_id": &schema.Schema{ 73 Type: schema.TypeString, 74 Required: true, 75 }, 76 77 "private_ip_address": &schema.Schema{ 78 Type: schema.TypeString, 79 Optional: true, 80 Computed: true, 81 }, 82 83 "private_ip_address_allocation": &schema.Schema{ 84 Type: schema.TypeString, 85 Required: true, 86 ValidateFunc: validateNetworkInterfacePrivateIpAddressAllocation, 87 }, 88 89 "public_ip_address_id": &schema.Schema{ 90 Type: schema.TypeString, 91 Optional: true, 92 Computed: true, 93 }, 94 95 "load_balancer_backend_address_pools_ids": &schema.Schema{ 96 Type: schema.TypeSet, 97 Optional: true, 98 Computed: true, 99 Elem: &schema.Schema{Type: schema.TypeString}, 100 Set: schema.HashString, 101 }, 102 103 "load_balancer_inbound_nat_rules_ids": &schema.Schema{ 104 Type: schema.TypeSet, 105 Optional: true, 106 Computed: true, 107 Elem: &schema.Schema{Type: schema.TypeString}, 108 Set: schema.HashString, 109 }, 110 }, 111 }, 112 Set: resourceArmNetworkInterfaceIpConfigurationHash, 113 }, 114 115 "dns_servers": &schema.Schema{ 116 Type: schema.TypeSet, 117 Optional: true, 118 Computed: true, 119 Elem: &schema.Schema{Type: schema.TypeString}, 120 Set: schema.HashString, 121 }, 122 123 "internal_dns_name_label": &schema.Schema{ 124 Type: schema.TypeString, 125 Optional: true, 126 Computed: true, 127 }, 128 129 "applied_dns_servers": &schema.Schema{ 130 Type: schema.TypeSet, 131 Optional: true, 132 Computed: true, 133 Elem: &schema.Schema{Type: schema.TypeString}, 134 Set: schema.HashString, 135 }, 136 137 "internal_fqdn": &schema.Schema{ 138 Type: schema.TypeString, 139 Optional: true, 140 Computed: true, 141 }, 142 143 "tags": tagsSchema(), 144 }, 145 } 146 } 147 148 func resourceArmNetworkInterfaceCreate(d *schema.ResourceData, meta interface{}) error { 149 client := meta.(*ArmClient) 150 ifaceClient := client.ifaceClient 151 152 log.Printf("[INFO] preparing arguments for Azure ARM Network Interface creation.") 153 154 name := d.Get("name").(string) 155 location := d.Get("location").(string) 156 resGroup := d.Get("resource_group_name").(string) 157 tags := d.Get("tags").(map[string]interface{}) 158 159 properties := network.InterfacePropertiesFormat{} 160 161 if v, ok := d.GetOk("network_security_group_id"); ok { 162 nsgId := v.(string) 163 properties.NetworkSecurityGroup = &network.SecurityGroup{ 164 ID: &nsgId, 165 } 166 } 167 168 dns, hasDns := d.GetOk("dns_servers") 169 nameLabel, hasNameLabel := d.GetOk("internal_dns_name_label") 170 if hasDns || hasNameLabel { 171 ifaceDnsSettings := network.InterfaceDNSSettings{} 172 173 if hasDns { 174 var dnsServers []string 175 dns := dns.(*schema.Set).List() 176 for _, v := range dns { 177 str := v.(string) 178 dnsServers = append(dnsServers, str) 179 } 180 ifaceDnsSettings.DNSServers = &dnsServers 181 } 182 183 if hasNameLabel { 184 name_label := nameLabel.(string) 185 ifaceDnsSettings.InternalDNSNameLabel = &name_label 186 187 } 188 189 properties.DNSSettings = &ifaceDnsSettings 190 } 191 192 ipConfigs, sgErr := expandAzureRmNetworkInterfaceIpConfigurations(d) 193 if sgErr != nil { 194 return fmt.Errorf("Error Building list of Network Interface IP Configurations: %s", sgErr) 195 } 196 if len(ipConfigs) > 0 { 197 properties.IPConfigurations = &ipConfigs 198 } 199 200 iface := network.Interface{ 201 Name: &name, 202 Location: &location, 203 Properties: &properties, 204 Tags: expandTags(tags), 205 } 206 207 resp, err := ifaceClient.CreateOrUpdate(resGroup, name, iface) 208 if err != nil { 209 return err 210 } 211 212 d.SetId(*resp.ID) 213 214 log.Printf("[DEBUG] Waiting for Network Interface (%s) to become available", name) 215 stateConf := &resource.StateChangeConf{ 216 Pending: []string{"Accepted", "Updating"}, 217 Target: "Succeeded", 218 Refresh: networkInterfaceStateRefreshFunc(client, resGroup, name), 219 Timeout: 10 * time.Minute, 220 } 221 if _, err := stateConf.WaitForState(); err != nil { 222 return fmt.Errorf("Error waiting for Network Interface (%s) to become available: %s", name, err) 223 } 224 225 return resourceArmNetworkInterfaceRead(d, meta) 226 } 227 228 func resourceArmNetworkInterfaceRead(d *schema.ResourceData, meta interface{}) error { 229 ifaceClient := meta.(*ArmClient).ifaceClient 230 231 id, err := parseAzureResourceID(d.Id()) 232 if err != nil { 233 return err 234 } 235 resGroup := id.ResourceGroup 236 name := id.Path["networkInterfaces"] 237 238 resp, err := ifaceClient.Get(resGroup, name, "") 239 if resp.StatusCode == http.StatusNotFound { 240 d.SetId("") 241 return nil 242 } 243 if err != nil { 244 return fmt.Errorf("Error making Read request on Azure Netowkr Interface %s: %s", name, err) 245 } 246 247 iface := *resp.Properties 248 249 if iface.MacAddress != nil { 250 if *iface.MacAddress != "" { 251 d.Set("mac_address", iface.MacAddress) 252 } 253 } 254 255 if iface.VirtualMachine != nil { 256 if *iface.VirtualMachine.ID != "" { 257 d.Set("virtual_machine_id", *iface.VirtualMachine.ID) 258 } 259 } 260 261 if iface.DNSSettings != nil { 262 if iface.DNSSettings.AppliedDNSServers != nil && len(*iface.DNSSettings.AppliedDNSServers) > 0 { 263 dnsServers := make([]string, 0, len(*iface.DNSSettings.AppliedDNSServers)) 264 for _, dns := range *iface.DNSSettings.AppliedDNSServers { 265 dnsServers = append(dnsServers, dns) 266 } 267 268 if err := d.Set("applied_dns_servers", dnsServers); err != nil { 269 return err 270 } 271 } 272 273 if iface.DNSSettings.InternalFqdn != nil && *iface.DNSSettings.InternalFqdn != "" { 274 d.Set("internal_fqdn", iface.DNSSettings.InternalFqdn) 275 } 276 } 277 278 flattenAndSetTags(d, resp.Tags) 279 280 return nil 281 } 282 283 func resourceArmNetworkInterfaceDelete(d *schema.ResourceData, meta interface{}) error { 284 ifaceClient := meta.(*ArmClient).ifaceClient 285 286 id, err := parseAzureResourceID(d.Id()) 287 if err != nil { 288 return err 289 } 290 resGroup := id.ResourceGroup 291 name := id.Path["networkInterfaces"] 292 293 _, err = ifaceClient.Delete(resGroup, name) 294 295 return err 296 } 297 298 func networkInterfaceStateRefreshFunc(client *ArmClient, resourceGroupName string, ifaceName string) resource.StateRefreshFunc { 299 return func() (interface{}, string, error) { 300 res, err := client.ifaceClient.Get(resourceGroupName, ifaceName, "") 301 if err != nil { 302 return nil, "", fmt.Errorf("Error issuing read request in networkInterfaceStateRefreshFunc to Azure ARM for network interace '%s' (RG: '%s'): %s", ifaceName, resourceGroupName, err) 303 } 304 305 return res, *res.Properties.ProvisioningState, nil 306 } 307 } 308 309 func resourceArmNetworkInterfaceIpConfigurationHash(v interface{}) int { 310 var buf bytes.Buffer 311 m := v.(map[string]interface{}) 312 buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) 313 buf.WriteString(fmt.Sprintf("%s-", m["subnet_id"].(string))) 314 buf.WriteString(fmt.Sprintf("%s-", m["private_ip_address_allocation"].(string))) 315 316 return hashcode.String(buf.String()) 317 } 318 319 func validateNetworkInterfacePrivateIpAddressAllocation(v interface{}, k string) (ws []string, errors []error) { 320 value := strings.ToLower(v.(string)) 321 allocations := map[string]bool{ 322 "static": true, 323 "dynamic": true, 324 } 325 326 if !allocations[value] { 327 errors = append(errors, fmt.Errorf("Network Interface Allocations can only be Static or Dynamic")) 328 } 329 return 330 } 331 332 func expandAzureRmNetworkInterfaceIpConfigurations(d *schema.ResourceData) ([]network.InterfaceIPConfiguration, error) { 333 configs := d.Get("ip_configuration").(*schema.Set).List() 334 ipConfigs := make([]network.InterfaceIPConfiguration, 0, len(configs)) 335 336 for _, configRaw := range configs { 337 data := configRaw.(map[string]interface{}) 338 339 subnet_id := data["subnet_id"].(string) 340 private_ip_allocation_method := data["private_ip_address_allocation"].(string) 341 342 properties := network.InterfaceIPConfigurationPropertiesFormat{ 343 Subnet: &network.Subnet{ 344 ID: &subnet_id, 345 }, 346 PrivateIPAllocationMethod: &private_ip_allocation_method, 347 } 348 349 if v := data["private_ip_address"].(string); v != "" { 350 properties.PrivateIPAddress = &v 351 } 352 353 if v := data["public_ip_address_id"].(string); v != "" { 354 properties.PublicIPAddress = &network.PublicIPAddress{ 355 ID: &v, 356 } 357 } 358 359 if v, ok := data["load_balancer_backend_address_pools_ids"]; ok { 360 var ids []network.BackendAddressPool 361 pools := v.(*schema.Set).List() 362 for _, p := range pools { 363 pool_id := p.(string) 364 id := network.BackendAddressPool{ 365 ID: &pool_id, 366 } 367 368 ids = append(ids, id) 369 } 370 371 properties.LoadBalancerBackendAddressPools = &ids 372 } 373 374 if v, ok := data["load_balancer_inbound_nat_rules_ids"]; ok { 375 var natRules []network.InboundNatRule 376 rules := v.(*schema.Set).List() 377 for _, r := range rules { 378 rule_id := r.(string) 379 rule := network.InboundNatRule{ 380 ID: &rule_id, 381 } 382 383 natRules = append(natRules, rule) 384 } 385 386 properties.LoadBalancerInboundNatRules = &natRules 387 } 388 389 name := data["name"].(string) 390 ipConfig := network.InterfaceIPConfiguration{ 391 Name: &name, 392 Properties: &properties, 393 } 394 395 ipConfigs = append(ipConfigs, ipConfig) 396 } 397 398 return ipConfigs, nil 399 }