github.com/shvar/terraform@v0.6.9-0.20151215234924-3365cd2231df/builtin/providers/azurerm/resource_arm_virtual_network.go (about)

     1  package azurerm
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"net/http"
     7  	"time"
     8  
     9  	"github.com/Azure/azure-sdk-for-go/arm/network"
    10  	"github.com/hashicorp/terraform/helper/hashcode"
    11  	"github.com/hashicorp/terraform/helper/resource"
    12  	"github.com/hashicorp/terraform/helper/schema"
    13  )
    14  
    15  func resourceArmVirtualNetwork() *schema.Resource {
    16  	return &schema.Resource{
    17  		Create: resourceArmVirtualNetworkCreate,
    18  		Read:   resourceArmVirtualNetworkRead,
    19  		Update: resourceArmVirtualNetworkCreate,
    20  		Delete: resourceArmVirtualNetworkDelete,
    21  
    22  		Schema: map[string]*schema.Schema{
    23  			"name": &schema.Schema{
    24  				Type:     schema.TypeString,
    25  				Required: true,
    26  				ForceNew: true,
    27  			},
    28  
    29  			"address_space": &schema.Schema{
    30  				Type:     schema.TypeList,
    31  				Required: true,
    32  				Elem:     &schema.Schema{Type: schema.TypeString},
    33  			},
    34  
    35  			"dns_servers": &schema.Schema{
    36  				Type:     schema.TypeList,
    37  				Optional: true,
    38  				Elem: &schema.Schema{
    39  					Type: schema.TypeString,
    40  				},
    41  			},
    42  
    43  			"subnet": &schema.Schema{
    44  				Type:     schema.TypeSet,
    45  				Required: true,
    46  				Elem: &schema.Resource{
    47  					Schema: map[string]*schema.Schema{
    48  						"name": &schema.Schema{
    49  							Type:     schema.TypeString,
    50  							Required: true,
    51  						},
    52  						"address_prefix": &schema.Schema{
    53  							Type:     schema.TypeString,
    54  							Required: true,
    55  						},
    56  						"security_group": &schema.Schema{
    57  							Type:     schema.TypeString,
    58  							Optional: true,
    59  						},
    60  					},
    61  				},
    62  				Set: resourceAzureSubnetHash,
    63  			},
    64  
    65  			"location": &schema.Schema{
    66  				Type:      schema.TypeString,
    67  				Required:  true,
    68  				ForceNew:  true,
    69  				StateFunc: azureRMNormalizeLocation,
    70  			},
    71  
    72  			"resource_group_name": &schema.Schema{
    73  				Type:     schema.TypeString,
    74  				Required: true,
    75  				ForceNew: true,
    76  			},
    77  		},
    78  	}
    79  }
    80  
    81  func resourceArmVirtualNetworkCreate(d *schema.ResourceData, meta interface{}) error {
    82  	client := meta.(*ArmClient)
    83  	vnetClient := client.vnetClient
    84  
    85  	log.Printf("[INFO] preparing arguments for Azure ARM virtual network creation.")
    86  
    87  	name := d.Get("name").(string)
    88  	location := d.Get("location").(string)
    89  	resGroup := d.Get("resource_group_name").(string)
    90  
    91  	vnet := network.VirtualNetwork{
    92  		Name:       &name,
    93  		Location:   &location,
    94  		Properties: getVirtualNetworkProperties(d),
    95  	}
    96  
    97  	resp, err := vnetClient.CreateOrUpdate(resGroup, name, vnet)
    98  	if err != nil {
    99  		return err
   100  	}
   101  
   102  	d.SetId(*resp.ID)
   103  
   104  	log.Printf("[DEBUG] Waiting for Virtual Network (%s) to become available", name)
   105  	stateConf := &resource.StateChangeConf{
   106  		Pending: []string{"Accepted", "Updating"},
   107  		Target:  "Succeeded",
   108  		Refresh: virtualNetworkStateRefreshFunc(client, resGroup, name),
   109  		Timeout: 10 * time.Minute,
   110  	}
   111  	if _, err := stateConf.WaitForState(); err != nil {
   112  		return fmt.Errorf("Error waiting for Virtual Network (%s) to become available: %s", name, err)
   113  	}
   114  
   115  	return resourceArmVirtualNetworkRead(d, meta)
   116  }
   117  
   118  func resourceArmVirtualNetworkRead(d *schema.ResourceData, meta interface{}) error {
   119  	vnetClient := meta.(*ArmClient).vnetClient
   120  
   121  	id, err := parseAzureResourceID(d.Id())
   122  	if err != nil {
   123  		return err
   124  	}
   125  	resGroup := id.ResourceGroup
   126  	name := id.Path["virtualNetworks"]
   127  
   128  	resp, err := vnetClient.Get(resGroup, name)
   129  	if resp.StatusCode == http.StatusNotFound {
   130  		d.SetId("")
   131  		return nil
   132  	}
   133  	if err != nil {
   134  		return fmt.Errorf("Error making Read request on Azure virtual network %s: %s", name, err)
   135  	}
   136  	vnet := *resp.Properties
   137  
   138  	// update appropriate values
   139  	d.Set("address_space", vnet.AddressSpace.AddressPrefixes)
   140  
   141  	subnets := &schema.Set{
   142  		F: resourceAzureSubnetHash,
   143  	}
   144  
   145  	for _, subnet := range *vnet.Subnets {
   146  		s := map[string]interface{}{}
   147  
   148  		s["name"] = *subnet.Name
   149  		s["address_prefix"] = *subnet.Properties.AddressPrefix
   150  		if subnet.Properties.NetworkSecurityGroup != nil {
   151  			s["security_group"] = *subnet.Properties.NetworkSecurityGroup.ID
   152  		}
   153  
   154  		subnets.Add(s)
   155  	}
   156  	d.Set("subnet", subnets)
   157  
   158  	dnses := []string{}
   159  	for _, dns := range *vnet.DhcpOptions.DNSServers {
   160  		dnses = append(dnses, dns)
   161  	}
   162  	d.Set("dns_servers", dnses)
   163  
   164  	return nil
   165  }
   166  
   167  func resourceArmVirtualNetworkDelete(d *schema.ResourceData, meta interface{}) error {
   168  	vnetClient := meta.(*ArmClient).vnetClient
   169  
   170  	id, err := parseAzureResourceID(d.Id())
   171  	if err != nil {
   172  		return err
   173  	}
   174  	resGroup := id.ResourceGroup
   175  	name := id.Path["virtualNetworks"]
   176  
   177  	_, err = vnetClient.Delete(resGroup, name)
   178  
   179  	return err
   180  }
   181  
   182  func getVirtualNetworkProperties(d *schema.ResourceData) *network.VirtualNetworkPropertiesFormat {
   183  	// first; get address space prefixes:
   184  	prefixes := []string{}
   185  	for _, prefix := range d.Get("address_space").([]interface{}) {
   186  		prefixes = append(prefixes, prefix.(string))
   187  	}
   188  
   189  	// then; the dns servers:
   190  	dnses := []string{}
   191  	for _, dns := range d.Get("dns_servers").([]interface{}) {
   192  		dnses = append(dnses, dns.(string))
   193  	}
   194  
   195  	// then; the subnets:
   196  	subnets := []network.Subnet{}
   197  	if subs := d.Get("subnet").(*schema.Set); subs.Len() > 0 {
   198  		for _, subnet := range subs.List() {
   199  			subnet := subnet.(map[string]interface{})
   200  
   201  			name := subnet["name"].(string)
   202  			prefix := subnet["address_prefix"].(string)
   203  			secGroup := subnet["security_group"].(string)
   204  
   205  			var subnetObj network.Subnet
   206  			subnetObj.Name = &name
   207  			subnetObj.Properties = &network.SubnetPropertiesFormat{}
   208  			subnetObj.Properties.AddressPrefix = &prefix
   209  
   210  			if secGroup != "" {
   211  				subnetObj.Properties.NetworkSecurityGroup = &network.SubResource{
   212  					ID: &secGroup,
   213  				}
   214  			}
   215  
   216  			subnets = append(subnets, subnetObj)
   217  		}
   218  	}
   219  
   220  	// finally; return the struct:
   221  	return &network.VirtualNetworkPropertiesFormat{
   222  		AddressSpace: &network.AddressSpace{
   223  			AddressPrefixes: &prefixes,
   224  		},
   225  		DhcpOptions: &network.DhcpOptions{
   226  			DNSServers: &dnses,
   227  		},
   228  		Subnets: &subnets,
   229  	}
   230  }
   231  
   232  func resourceAzureSubnetHash(v interface{}) int {
   233  	m := v.(map[string]interface{})
   234  	subnet := m["name"].(string) + m["address_prefix"].(string)
   235  	if securityGroup, present := m["security_group"]; present {
   236  		subnet = subnet + securityGroup.(string)
   237  	}
   238  	return hashcode.String(subnet)
   239  }
   240  
   241  func virtualNetworkStateRefreshFunc(client *ArmClient, resourceGroupName string, networkName string) resource.StateRefreshFunc {
   242  	return func() (interface{}, string, error) {
   243  		res, err := client.vnetClient.Get(resourceGroupName, networkName)
   244  		if err != nil {
   245  			return nil, "", fmt.Errorf("Error issuing read request in virtualNetworkStateRefreshFunc to Azure ARM for virtual network '%s' (RG: '%s'): %s", networkName, resourceGroupName, err)
   246  		}
   247  
   248  		return res, *res.Properties.ProvisioningState, nil
   249  	}
   250  }