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