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