github.com/jdextraze/terraform@v0.6.17-0.20160511153921-e33847c8a8af/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 "tags": tagsSchema(), 149 }, 150 } 151 } 152 153 func resourceArmNetworkInterfaceCreate(d *schema.ResourceData, meta interface{}) error { 154 client := meta.(*ArmClient) 155 ifaceClient := client.ifaceClient 156 157 log.Printf("[INFO] preparing arguments for Azure ARM Network Interface creation.") 158 159 name := d.Get("name").(string) 160 location := d.Get("location").(string) 161 resGroup := d.Get("resource_group_name").(string) 162 tags := d.Get("tags").(map[string]interface{}) 163 164 properties := network.InterfacePropertiesFormat{} 165 166 if v, ok := d.GetOk("network_security_group_id"); ok { 167 nsgId := v.(string) 168 properties.NetworkSecurityGroup = &network.SecurityGroup{ 169 ID: &nsgId, 170 } 171 } 172 173 dns, hasDns := d.GetOk("dns_servers") 174 nameLabel, hasNameLabel := d.GetOk("internal_dns_name_label") 175 if hasDns || hasNameLabel { 176 ifaceDnsSettings := network.InterfaceDNSSettings{} 177 178 if hasDns { 179 var dnsServers []string 180 dns := dns.(*schema.Set).List() 181 for _, v := range dns { 182 str := v.(string) 183 dnsServers = append(dnsServers, str) 184 } 185 ifaceDnsSettings.DNSServers = &dnsServers 186 } 187 188 if hasNameLabel { 189 name_label := nameLabel.(string) 190 ifaceDnsSettings.InternalDNSNameLabel = &name_label 191 192 } 193 194 properties.DNSSettings = &ifaceDnsSettings 195 } 196 197 ipConfigs, sgErr := expandAzureRmNetworkInterfaceIpConfigurations(d) 198 if sgErr != nil { 199 return fmt.Errorf("Error Building list of Network Interface IP Configurations: %s", sgErr) 200 } 201 if len(ipConfigs) > 0 { 202 properties.IPConfigurations = &ipConfigs 203 } 204 205 iface := network.Interface{ 206 Name: &name, 207 Location: &location, 208 Properties: &properties, 209 Tags: expandTags(tags), 210 } 211 212 resp, err := ifaceClient.CreateOrUpdate(resGroup, name, iface) 213 if err != nil { 214 return err 215 } 216 217 d.SetId(*resp.ID) 218 219 log.Printf("[DEBUG] Waiting for Network Interface (%s) to become available", name) 220 stateConf := &resource.StateChangeConf{ 221 Pending: []string{"Accepted", "Updating"}, 222 Target: []string{"Succeeded"}, 223 Refresh: networkInterfaceStateRefreshFunc(client, resGroup, name), 224 Timeout: 10 * time.Minute, 225 } 226 if _, err := stateConf.WaitForState(); err != nil { 227 return fmt.Errorf("Error waiting for Network Interface (%s) to become available: %s", name, err) 228 } 229 230 return resourceArmNetworkInterfaceRead(d, meta) 231 } 232 233 func resourceArmNetworkInterfaceRead(d *schema.ResourceData, meta interface{}) error { 234 ifaceClient := meta.(*ArmClient).ifaceClient 235 236 id, err := parseAzureResourceID(d.Id()) 237 if err != nil { 238 return err 239 } 240 resGroup := id.ResourceGroup 241 name := id.Path["networkInterfaces"] 242 243 resp, err := ifaceClient.Get(resGroup, name, "") 244 if resp.StatusCode == http.StatusNotFound { 245 d.SetId("") 246 return nil 247 } 248 if err != nil { 249 return fmt.Errorf("Error making Read request on Azure Network Interface %s: %s", name, err) 250 } 251 252 iface := *resp.Properties 253 254 if iface.MacAddress != nil { 255 if *iface.MacAddress != "" { 256 d.Set("mac_address", iface.MacAddress) 257 } 258 } 259 260 if iface.IPConfigurations != nil && len(*iface.IPConfigurations) > 0 { 261 var privateIPAddress *string 262 ///TODO: Change this to a loop when https://github.com/Azure/azure-sdk-for-go/issues/259 is fixed 263 if (*iface.IPConfigurations)[0].Properties != nil { 264 privateIPAddress = (*iface.IPConfigurations)[0].Properties.PrivateIPAddress 265 } 266 267 if *privateIPAddress != "" { 268 d.Set("private_ip_address", *privateIPAddress) 269 } 270 } 271 272 if iface.VirtualMachine != nil { 273 if *iface.VirtualMachine.ID != "" { 274 d.Set("virtual_machine_id", *iface.VirtualMachine.ID) 275 } 276 } 277 278 if iface.DNSSettings != nil { 279 if iface.DNSSettings.AppliedDNSServers != nil && len(*iface.DNSSettings.AppliedDNSServers) > 0 { 280 dnsServers := make([]string, 0, len(*iface.DNSSettings.AppliedDNSServers)) 281 for _, dns := range *iface.DNSSettings.AppliedDNSServers { 282 dnsServers = append(dnsServers, dns) 283 } 284 285 if err := d.Set("applied_dns_servers", dnsServers); err != nil { 286 return err 287 } 288 } 289 290 if iface.DNSSettings.InternalFqdn != nil && *iface.DNSSettings.InternalFqdn != "" { 291 d.Set("internal_fqdn", iface.DNSSettings.InternalFqdn) 292 } 293 } 294 295 flattenAndSetTags(d, resp.Tags) 296 297 return nil 298 } 299 300 func resourceArmNetworkInterfaceDelete(d *schema.ResourceData, meta interface{}) error { 301 ifaceClient := meta.(*ArmClient).ifaceClient 302 303 id, err := parseAzureResourceID(d.Id()) 304 if err != nil { 305 return err 306 } 307 resGroup := id.ResourceGroup 308 name := id.Path["networkInterfaces"] 309 310 _, err = ifaceClient.Delete(resGroup, name) 311 312 return err 313 } 314 315 func networkInterfaceStateRefreshFunc(client *ArmClient, resourceGroupName string, ifaceName string) resource.StateRefreshFunc { 316 return func() (interface{}, string, error) { 317 res, err := client.ifaceClient.Get(resourceGroupName, ifaceName, "") 318 if err != nil { 319 return nil, "", fmt.Errorf("Error issuing read request in networkInterfaceStateRefreshFunc to Azure ARM for network interace '%s' (RG: '%s'): %s", ifaceName, resourceGroupName, err) 320 } 321 322 return res, *res.Properties.ProvisioningState, nil 323 } 324 } 325 326 func resourceArmNetworkInterfaceIpConfigurationHash(v interface{}) int { 327 var buf bytes.Buffer 328 m := v.(map[string]interface{}) 329 buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) 330 buf.WriteString(fmt.Sprintf("%s-", m["subnet_id"].(string))) 331 buf.WriteString(fmt.Sprintf("%s-", m["private_ip_address_allocation"].(string))) 332 333 return hashcode.String(buf.String()) 334 } 335 336 func validateNetworkInterfacePrivateIpAddressAllocation(v interface{}, k string) (ws []string, errors []error) { 337 value := strings.ToLower(v.(string)) 338 allocations := map[string]bool{ 339 "static": true, 340 "dynamic": true, 341 } 342 343 if !allocations[value] { 344 errors = append(errors, fmt.Errorf("Network Interface Allocations can only be Static or Dynamic")) 345 } 346 return 347 } 348 349 func expandAzureRmNetworkInterfaceIpConfigurations(d *schema.ResourceData) ([]network.InterfaceIPConfiguration, error) { 350 configs := d.Get("ip_configuration").(*schema.Set).List() 351 ipConfigs := make([]network.InterfaceIPConfiguration, 0, len(configs)) 352 353 for _, configRaw := range configs { 354 data := configRaw.(map[string]interface{}) 355 356 subnet_id := data["subnet_id"].(string) 357 private_ip_allocation_method := data["private_ip_address_allocation"].(string) 358 359 properties := network.InterfaceIPConfigurationPropertiesFormat{ 360 Subnet: &network.Subnet{ 361 ID: &subnet_id, 362 }, 363 PrivateIPAllocationMethod: &private_ip_allocation_method, 364 } 365 366 if v := data["private_ip_address"].(string); v != "" { 367 properties.PrivateIPAddress = &v 368 } 369 370 if v := data["public_ip_address_id"].(string); v != "" { 371 properties.PublicIPAddress = &network.PublicIPAddress{ 372 ID: &v, 373 } 374 } 375 376 if v, ok := data["load_balancer_backend_address_pools_ids"]; ok { 377 var ids []network.BackendAddressPool 378 pools := v.(*schema.Set).List() 379 for _, p := range pools { 380 pool_id := p.(string) 381 id := network.BackendAddressPool{ 382 ID: &pool_id, 383 } 384 385 ids = append(ids, id) 386 } 387 388 properties.LoadBalancerBackendAddressPools = &ids 389 } 390 391 if v, ok := data["load_balancer_inbound_nat_rules_ids"]; ok { 392 var natRules []network.InboundNatRule 393 rules := v.(*schema.Set).List() 394 for _, r := range rules { 395 rule_id := r.(string) 396 rule := network.InboundNatRule{ 397 ID: &rule_id, 398 } 399 400 natRules = append(natRules, rule) 401 } 402 403 properties.LoadBalancerInboundNatRules = &natRules 404 } 405 406 name := data["name"].(string) 407 ipConfig := network.InterfaceIPConfiguration{ 408 Name: &name, 409 Properties: &properties, 410 } 411 412 ipConfigs = append(ipConfigs, ipConfig) 413 } 414 415 return ipConfigs, nil 416 }