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