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