terraform/builtin/providers/azure/resource_azure_local_networ...

254 lines
8.2 KiB
Go

package azure
import (
"fmt"
"log"
"github.com/Azure/azure-sdk-for-go/management"
"github.com/Azure/azure-sdk-for-go/management/virtualnetwork"
"github.com/hashicorp/terraform/helper/schema"
)
// resourceAzureLocalNetworkConnetion returns the schema.Resource associated to an
// Azure hosted service.
func resourceAzureLocalNetworkConnection() *schema.Resource {
return &schema.Resource{
Create: resourceAzureLocalNetworkConnectionCreate,
Read: resourceAzureLocalNetworkConnectionRead,
Update: resourceAzureLocalNetworkConnectionUpdate,
Exists: resourceAzureLocalNetworkConnectionExists,
Delete: resourceAzureLocalNetworkConnectionDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: parameterDescriptions["name"],
},
"vpn_gateway_address": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: parameterDescriptions["vpn_gateway_address"],
},
"address_space_prefixes": &schema.Schema{
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: parameterDescriptions["address_space_prefixes"],
},
},
}
}
// sourceAzureLocalNetworkConnectionCreate issues all the necessary API calls
// to create a virtual network on Azure.
func resourceAzureLocalNetworkConnectionCreate(d *schema.ResourceData, meta interface{}) error {
azureClient := meta.(*Client)
mgmtClient := azureClient.mgmtClient
vnetClient := azureClient.vnetClient
log.Println("[INFO] Fetching current network configuration from Azure.")
azureClient.vnetMutex.Lock()
defer azureClient.vnetMutex.Unlock()
netConf, err := vnetClient.GetVirtualNetworkConfiguration()
if err != nil {
if management.IsResourceNotFoundError(err) {
// if no network config exists yet; create a new one now:
netConf = virtualnetwork.NetworkConfiguration{}
} else {
return fmt.Errorf("Failed to get the current network configuration from Azure: %s", err)
}
}
// get provided configuration:
name := d.Get("name").(string)
vpnGateway := d.Get("vpn_gateway_address").(string)
var prefixes []string
for _, prefix := range d.Get("address_space_prefixes").([]interface{}) {
prefixes = append(prefixes, prefix.(string))
}
// add configuration to network config:
netConf.Configuration.LocalNetworkSites = append(netConf.Configuration.LocalNetworkSites,
virtualnetwork.LocalNetworkSite{
Name: name,
VPNGatewayAddress: vpnGateway,
AddressSpace: virtualnetwork.AddressSpace{
AddressPrefix: prefixes,
},
})
// send the configuration back to Azure:
log.Println("[INFO] Sending updated network configuration back to Azure.")
reqID, err := vnetClient.SetVirtualNetworkConfiguration(netConf)
if err != nil {
return fmt.Errorf("Failed setting updated network configuration: %s", err)
}
err = mgmtClient.WaitForOperation(reqID, nil)
if err != nil {
return fmt.Errorf("Failed updating the network configuration: %s", err)
}
d.SetId(name)
return nil
}
// resourceAzureLocalNetworkConnectionRead does all the necessary API calls to
// read the state of our local natwork from Azure.
func resourceAzureLocalNetworkConnectionRead(d *schema.ResourceData, meta interface{}) error {
azureClient := meta.(*Client)
vnetClient := azureClient.vnetClient
log.Println("[INFO] Fetching current network configuration from Azure.")
netConf, err := vnetClient.GetVirtualNetworkConfiguration()
if err != nil {
return fmt.Errorf("Failed to get the current network configuration from Azure: %s", err)
}
var found bool
name := d.Get("name").(string)
// browsing for our network config:
for _, lnet := range netConf.Configuration.LocalNetworkSites {
if lnet.Name == name {
found = true
d.Set("vpn_gateway_address", lnet.VPNGatewayAddress)
d.Set("address_space_prefixes", lnet.AddressSpace.AddressPrefix)
break
}
}
// remove the resource from the state of it has been deleted in the meantime:
if !found {
log.Println(fmt.Printf("[INFO] Azure local network '%s' has been deleted remotely. Removimg from Terraform.", name))
d.SetId("")
}
return nil
}
// resourceAzureLocalNetworkConnectionUpdate does all the necessary API calls
// update the settings of our Local Network on Azure.
func resourceAzureLocalNetworkConnectionUpdate(d *schema.ResourceData, meta interface{}) error {
azureClient := meta.(*Client)
mgmtClient := azureClient.mgmtClient
vnetClient := azureClient.vnetClient
log.Println("[INFO] Fetching current network configuration from Azure.")
azureClient.vnetMutex.Lock()
defer azureClient.vnetMutex.Unlock()
netConf, err := vnetClient.GetVirtualNetworkConfiguration()
if err != nil {
return fmt.Errorf("Failed to get the current network configuration from Azure: %s", err)
}
name := d.Get("name").(string)
cvpn := d.HasChange("vpn_gateway_address")
cprefixes := d.HasChange("address_space_prefixes")
var found bool
for i, lnet := range netConf.Configuration.LocalNetworkSites {
if lnet.Name == name {
found = true
if cvpn {
netConf.Configuration.LocalNetworkSites[i].VPNGatewayAddress = d.Get("vpn_gateway_address").(string)
}
if cprefixes {
var prefixes []string
for _, prefix := range d.Get("address_space_prefixes").([]interface{}) {
prefixes = append(prefixes, prefix.(string))
}
netConf.Configuration.LocalNetworkSites[i].AddressSpace.AddressPrefix = prefixes
}
break
}
}
// remove the resource from the state of it has been deleted in the meantime:
if !found {
log.Println(fmt.Printf("[INFO] Azure local network '%s' has been deleted remotely. Removimg from Terraform.", name))
d.SetId("")
} else if cvpn || cprefixes {
// else, send the configuration back to Azure:
log.Println("[INFO] Sending updated network configuration back to Azure.")
reqID, err := vnetClient.SetVirtualNetworkConfiguration(netConf)
if err != nil {
return fmt.Errorf("Failed setting updated network configuration: %s", err)
}
err = mgmtClient.WaitForOperation(reqID, nil)
if err != nil {
return fmt.Errorf("Failed updating the network configuration: %s", err)
}
}
return nil
}
// resourceAzureLocalNetworkConnectionExists does all the necessary API calls
// to check if the local network already exists on Azure.
func resourceAzureLocalNetworkConnectionExists(d *schema.ResourceData, meta interface{}) (bool, error) {
vnetClient := meta.(*Client).vnetClient
log.Println("[INFO] Fetching current network configuration from Azure.")
netConf, err := vnetClient.GetVirtualNetworkConfiguration()
if err != nil {
return false, fmt.Errorf("Failed to get the current network configuration from Azure: %s", err)
}
name := d.Get("name")
for _, lnet := range netConf.Configuration.LocalNetworkSites {
if lnet.Name == name {
return true, nil
}
}
return false, nil
}
// resourceAzureLocalNetworkConnectionDelete does all the necessary API calls
// to delete a local network off Azure.
func resourceAzureLocalNetworkConnectionDelete(d *schema.ResourceData, meta interface{}) error {
azureClient := meta.(*Client)
mgmtClient := azureClient.mgmtClient
vnetClient := azureClient.vnetClient
log.Println("[INFO] Fetching current network configuration from Azure.")
azureClient.vnetMutex.Lock()
defer azureClient.vnetMutex.Unlock()
netConf, err := vnetClient.GetVirtualNetworkConfiguration()
if err != nil {
return fmt.Errorf("Failed to get the current network configuration from Azure: %s", err)
}
name := d.Get("name").(string)
// search for our local network and remove it if found:
for i, lnet := range netConf.Configuration.LocalNetworkSites {
if lnet.Name == name {
netConf.Configuration.LocalNetworkSites = append(
netConf.Configuration.LocalNetworkSites[:i],
netConf.Configuration.LocalNetworkSites[i+1:]...,
)
break
}
}
// send the configuration back to Azure:
log.Println("[INFO] Sending updated network configuration back to Azure.")
reqID, err := vnetClient.SetVirtualNetworkConfiguration(netConf)
if err != nil {
return fmt.Errorf("Failed setting updated network configuration: %s", err)
}
err = mgmtClient.WaitForOperation(reqID, nil)
if err != nil {
return fmt.Errorf("Failed updating the network configuration: %s", err)
}
d.SetId("")
return nil
}