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  }