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  }