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