From 00de4ed1118915c0f67f8122c21e1b02f9f5fd2e Mon Sep 17 00:00:00 2001 From: Peter McAtominey Date: Mon, 8 Aug 2016 00:45:56 +0100 Subject: [PATCH] provider/azurerm: vnet gateway vip --- builtin/providers/azurerm/provider.go | 1 + .../resource_arm_virtual_network_gateway.go | 610 ++++++++++++++++++ ...source_arm_virtual_network_gateway_test.go | 277 ++++++++ 3 files changed, 888 insertions(+) create mode 100644 builtin/providers/azurerm/resource_arm_virtual_network_gateway.go create mode 100644 builtin/providers/azurerm/resource_arm_virtual_network_gateway_test.go diff --git a/builtin/providers/azurerm/provider.go b/builtin/providers/azurerm/provider.go index 62d060a39fe5..0fd6f4a63846 100644 --- a/builtin/providers/azurerm/provider.go +++ b/builtin/providers/azurerm/provider.go @@ -107,6 +107,7 @@ func Provider() terraform.ResourceProvider { "azurerm_virtual_machine": resourceArmVirtualMachine(), "azurerm_virtual_machine_scale_set": resourceArmVirtualMachineScaleSet(), "azurerm_virtual_network": resourceArmVirtualNetwork(), + "azurerm_virtual_network_gateway": resourceArmvirtualNetworkGateway(), "azurerm_virtual_network_peering": resourceArmVirtualNetworkPeering(), // These resources use the Riviera SDK diff --git a/builtin/providers/azurerm/resource_arm_virtual_network_gateway.go b/builtin/providers/azurerm/resource_arm_virtual_network_gateway.go new file mode 100644 index 000000000000..1d8014e8fdbf --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_virtual_network_gateway.go @@ -0,0 +1,610 @@ +package azurerm + +import ( + "bytes" + "fmt" + "log" + "net/http" + + "time" + + "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" +) + +func resourceArmvirtualNetworkGateway() *schema.Resource { + return &schema.Resource{ + Create: resourceArmvirtualNetworkGatewayCreate, + Read: resourceArmvirtualNetworkGatewayRead, + Update: resourceArmvirtualNetworkGatewayCreate, + Delete: resourceArmvirtualNetworkGatewayDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "location": locationSchema(), + + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.VirtualNetworkGatewayTypeExpressRoute), + string(network.VirtualNetworkGatewayTypeVpn), + }, false), + }, + + "vpn_type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.RouteBased), + string(network.PolicyBased), + }, false), + }, + + "enable_bgp": { + Type: schema.TypeBool, + Required: true, + }, + + "active_active": { + Type: schema.TypeBool, + Optional: true, + }, + + "sku": { + Type: schema.TypeSet, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.VirtualNetworkGatewaySkuNameBasic), + string(network.VirtualNetworkGatewaySkuNameStandard), + string(network.VirtualNetworkGatewaySkuNameHighPerformance), + }, false), + }, + "tier": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.VirtualNetworkGatewaySkuTierBasic), + string(network.VirtualNetworkGatewaySkuTierStandard), + string(network.VirtualNetworkGatewaySkuTierHighPerformance), + }, false), + }, + "capacity": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + Set: hashVirtualNetworkGatewaySku, + }, + + // used TypeList here so the private_ip_address can be referenced + "ip_configuration": { + Type: schema.TypeList, + Required: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "private_ip_address_allocation": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.Static), + string(network.Dynamic), + }, false), + }, + "subnet_id": { + Type: schema.TypeString, + Optional: true, + }, + "public_ip_address_id": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "vpn_client_configuration": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address_space": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "root_certificate": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "public_cert_data": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + Set: hashVirtualNetworkGatewayRootCert, + }, + "revoked_certificate": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "thumbprint": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + Set: hashVirtualNetworkGatewayRevokedCert, + }, + }, + }, + Set: hashVirtualNetworkGatewayVpnClientConfig, + }, + + "bgp_settings": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "asn": { + Type: schema.TypeInt, + Required: true, + }, + "peering_address": { + Type: schema.TypeString, + Required: true, + }, + "peer_weight": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + Set: hashVirtualNetworkGatewayBgpSettings, + }, + + "gateway_default_site_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "tags": tagsSchema(), + }, + } +} + +func resourceArmvirtualNetworkGatewayCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).vnetGatewayClient + + log.Printf("[INFO] preparing arguments for Azure ARM Virtual Network Gateway creation.") + + name := d.Get("name").(string) + location := d.Get("location").(string) + resGroup := d.Get("resource_group_name").(string) + tags := d.Get("tags").(map[string]interface{}) + + gateway := network.VirtualNetworkGateway{ + Name: &name, + Location: &location, + Tags: expandTags(tags), + VirtualNetworkGatewayPropertiesFormat: getArmvirtualNetworkGatewayProperties(d), + } + + _, err := client.CreateOrUpdate(resGroup, name, gateway, make(chan struct{})) + if err != nil { + return err + } + + read, err := client.Get(resGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Cannot read VirtualNetwork Gateway %s (resource group %s) ID", name, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmvirtualNetworkGatewayRead(d, meta) +} + +func resourceArmvirtualNetworkGatewayRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).vnetGatewayClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + name := id.Path["virtualNetworkGateways"] + + resp, err := client.Get(resGroup, name) + if err != nil { + if resp.StatusCode == http.StatusNotFound { + d.SetId("") + return nil + } + return fmt.Errorf("Error making Read request on VirtualNetwork Gateway %s: %s", name, err) + } + gw := *resp.VirtualNetworkGatewayPropertiesFormat + + d.Set("name", resp.Name) + d.Set("resource_group_name", resGroup) + d.Set("location", azureRMNormalizeLocation(*resp.Location)) + d.Set("type", string(gw.GatewayType)) + d.Set("enable_bgp", gw.EnableBgp) + d.Set("active_active", gw.ActiveActive) + d.Set("sku", schema.NewSet(hashVirtualNetworkGatewaySku, flattenArmVirtualNetworkGatewaySku(gw.Sku))) + + if string(gw.VpnType) != "" { + d.Set("vpn_type", string(gw.VpnType)) + } + + if gw.GatewayDefaultSite != nil { + d.Set("gateway_default_site_id", gw.GatewayDefaultSite.ID) + } + + d.Set("ip_configuration", flattenArmVirtualNetworkGatewayIPConfigurations(gw.IPConfigurations)) + + if gw.VpnClientConfiguration != nil { + vpnConfigFlat := flattenArmVirtualNetworkGatewayVpnClientConfig(gw.VpnClientConfiguration) + d.Set("vpn_client_configuration", schema.NewSet(hashVirtualNetworkGatewayVpnClientConfig, vpnConfigFlat)) + } + + if gw.BgpSettings != nil { + d.Set("bgp_settings", schema.NewSet(hashVirtualNetworkGatewayBgpSettings, flattenArmVirtualNetworkGatewayBgpSettings(gw.BgpSettings))) + } + + flattenAndSetTags(d, resp.Tags) + + return nil +} + +func resourceArmvirtualNetworkGatewayDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).vnetGatewayClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + name := id.Path["virtualNetworkGateways"] + + _, err = client.Delete(resGroup, name, make(chan struct{})) + if err != nil { + return err + } + + // Gateways aren't fully cleaned up when the API indicates the delete operation + // has finished, this workaround was suggested by Azure support to avoid conflicts + // when modifying/deleting the related subnet or network. + time.Sleep(time.Minute * 15) + + return nil +} + +func getArmvirtualNetworkGatewayProperties(d *schema.ResourceData) *network.VirtualNetworkGatewayPropertiesFormat { + gatewayType := network.VirtualNetworkGatewayType(d.Get("type").(string)) + vpnType := network.VpnType(d.Get("vpn_type").(string)) + enableBgp := d.Get("enable_bgp").(bool) + activeActive := d.Get("active_active").(bool) + + props := &network.VirtualNetworkGatewayPropertiesFormat{ + GatewayType: gatewayType, + VpnType: vpnType, + EnableBgp: &enableBgp, + ActiveActive: &activeActive, + Sku: expandArmVirtualNetworkGatewaySku(d), + IPConfigurations: expandArmVirtualNetworkGatewayIPConfigurations(d), + } + + if gatewayDefaultSiteID := d.Get("gateway_default_site_id").(string); gatewayDefaultSiteID != "" { + props.GatewayDefaultSite = &network.SubResource{ + ID: &gatewayDefaultSiteID, + } + } + + if _, ok := d.GetOk("vpn_client_configuration"); ok { + props.VpnClientConfiguration = expandArmVirtualNetworkGatewayVpnClientConfig(d) + } + + if _, ok := d.GetOk("bgp_settings"); ok { + props.BgpSettings = expandArmVirtualNetworkGatewayBgpSettings(d) + } + + return props +} + +func expandArmVirtualNetworkGatewayBgpSettings(d *schema.ResourceData) *network.BgpSettings { + bgpSets := d.Get("bgp_settings").(*schema.Set).List() + bgp := bgpSets[0].(map[string]interface{}) + + asn := int64(bgp["asn"].(int)) + peeringAddress := bgp["peering_address"].(string) + peerWeight := int32(bgp["peer_weight"].(int)) + + return &network.BgpSettings{ + Asn: &asn, + BgpPeeringAddress: &peeringAddress, + PeerWeight: &peerWeight, + } +} + +func expandArmVirtualNetworkGatewayIPConfigurations(d *schema.ResourceData) *[]network.VirtualNetworkGatewayIPConfiguration { + configs := d.Get("ip_configuration").([]interface{}) + ipConfigs := make([]network.VirtualNetworkGatewayIPConfiguration, 0, len(configs)) + + for _, c := range configs { + conf := c.(map[string]interface{}) + + name := conf["name"].(string) + privateIPAllocMethod := network.IPAllocationMethod(conf["private_ip_address_allocation"].(string)) + + props := &network.VirtualNetworkGatewayIPConfigurationPropertiesFormat{ + PrivateIPAllocationMethod: privateIPAllocMethod, + } + + if subnetID := conf["subnet_id"].(string); subnetID != "" { + props.Subnet = &network.SubResource{ + ID: &subnetID, + } + } + + if publicIP := conf["public_ip_address_id"].(string); publicIP != "" { + props.PublicIPAddress = &network.SubResource{ + ID: &publicIP, + } + } + + ipConfig := network.VirtualNetworkGatewayIPConfiguration{ + Name: &name, + VirtualNetworkGatewayIPConfigurationPropertiesFormat: props, + } + + ipConfigs = append(ipConfigs, ipConfig) + } + + return &ipConfigs +} + +func expandArmVirtualNetworkGatewayVpnClientConfig(d *schema.ResourceData) *network.VpnClientConfiguration { + configSets := d.Get("vpn_client_configuration").(*schema.Set).List() + conf := configSets[0].(map[string]interface{}) + + confAddresses := conf["address_space"].([]interface{}) + addresses := make([]string, 0, len(confAddresses)) + for _, addr := range confAddresses { + addresses = append(addresses, addr.(string)) + } + + var rootCerts []network.VpnClientRootCertificate + for _, rootCertSet := range conf["root_certificate"].(*schema.Set).List() { + rootCert := rootCertSet.(map[string]interface{}) + name := rootCert["name"].(string) + publicCertData := rootCert["public_cert_data"].(string) + r := network.VpnClientRootCertificate{ + Name: &name, + VpnClientRootCertificatePropertiesFormat: &network.VpnClientRootCertificatePropertiesFormat{ + PublicCertData: &publicCertData, + }, + } + rootCerts = append(rootCerts, r) + } + + var revokedCerts []network.VpnClientRevokedCertificate + for _, revokedCertSet := range conf["revoked_certificate"].(*schema.Set).List() { + revokedCert := revokedCertSet.(map[string]interface{}) + name := revokedCert["name"].(string) + thumbprint := revokedCert["thumbprint"].(string) + r := network.VpnClientRevokedCertificate{ + Name: &name, + VpnClientRevokedCertificatePropertiesFormat: &network.VpnClientRevokedCertificatePropertiesFormat{ + Thumbprint: &thumbprint, + }, + } + revokedCerts = append(revokedCerts, r) + } + + return &network.VpnClientConfiguration{ + VpnClientAddressPool: &network.AddressSpace{ + AddressPrefixes: &addresses, + }, + VpnClientRootCertificates: &rootCerts, + VpnClientRevokedCertificates: &revokedCerts, + } +} + +func expandArmVirtualNetworkGatewaySku(d *schema.ResourceData) *network.VirtualNetworkGatewaySku { + skuSets := d.Get("sku").(*schema.Set).List() + sku := skuSets[0].(map[string]interface{}) + + name := sku["name"].(string) + tier := sku["tier"].(string) + + return &network.VirtualNetworkGatewaySku{ + Name: network.VirtualNetworkGatewaySkuName(name), + Tier: network.VirtualNetworkGatewaySkuTier(tier), + } +} + +func flattenArmVirtualNetworkGatewayBgpSettings(settings *network.BgpSettings) []interface{} { + flat := make(map[string]interface{}) + + flat["asn"] = int(*settings.Asn) + flat["peering_address"] = *settings.BgpPeeringAddress + flat["peer_weight"] = int(*settings.PeerWeight) + + return []interface{}{flat} +} + +func flattenArmVirtualNetworkGatewayIPConfigurations(ipConfigs *[]network.VirtualNetworkGatewayIPConfiguration) []interface{} { + flat := make([]interface{}, 0, len(*ipConfigs)) + + for _, cfg := range *ipConfigs { + props := cfg.VirtualNetworkGatewayIPConfigurationPropertiesFormat + v := make(map[string]interface{}) + + v["name"] = *cfg.Name + v["private_ip_address_allocation"] = string(props.PrivateIPAllocationMethod) + v["subnet_id"] = *props.Subnet.ID + v["public_ip_address_id"] = *props.PublicIPAddress.ID + + flat = append(flat, v) + } + + return flat +} + +func flattenArmVirtualNetworkGatewayVpnClientConfig(cfg *network.VpnClientConfiguration) []interface{} { + flat := make(map[string]interface{}) + + addressSpace := make([]interface{}, 0, len(*cfg.VpnClientAddressPool.AddressPrefixes)) + for _, addr := range *cfg.VpnClientAddressPool.AddressPrefixes { + addressSpace = append(addressSpace, addr) + } + flat["address_space"] = addressSpace + + rootCerts := make([]interface{}, 0, len(*cfg.VpnClientRootCertificates)) + for _, cert := range *cfg.VpnClientRootCertificates { + v := map[string]interface{}{ + "name": cert.Name, + "public_cert_data": cert.VpnClientRootCertificatePropertiesFormat.PublicCertData, + } + rootCerts = append(rootCerts, v) + } + flat["root_certificate"] = schema.NewSet(hashVirtualNetworkGatewayRootCert, rootCerts) + + revokedCerts := make([]interface{}, 0, len(*cfg.VpnClientRevokedCertificates)) + for _, cert := range *cfg.VpnClientRevokedCertificates { + v := map[string]interface{}{ + "name": cert.Name, + "thumbprint": cert.VpnClientRevokedCertificatePropertiesFormat.Thumbprint, + } + revokedCerts = append(revokedCerts, v) + } + flat["revoked_certificate"] = schema.NewSet(hashVirtualNetworkGatewayRevokedCert, revokedCerts) + + return []interface{}{flat} +} + +func flattenArmVirtualNetworkGatewaySku(sku *network.VirtualNetworkGatewaySku) []interface{} { + flat := make(map[string]interface{}) + + flat["name"] = string(sku.Name) + flat["tier"] = string(sku.Tier) + flat["capacity"] = int(*sku.Capacity) + + return []interface{}{flat} +} + +func hashVirtualNetworkGatewayBgpSettings(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + + buf.WriteString(fmt.Sprintf("%d-", m["asn"].(int))) + buf.WriteString(fmt.Sprintf("%s-", m["peering_address"].(string))) + buf.WriteString(fmt.Sprintf("%d-", m["peer_weight"].(int))) + + return hashcode.String(buf.String()) +} + +func hashVirtualNetworkGatewayRootCert(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + + buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["public_cert_data"].(string))) + + return hashcode.String(buf.String()) +} + +func hashVirtualNetworkGatewayRevokedCert(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + + buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["thumbprint"].(string))) + + return hashcode.String(buf.String()) +} + +func hashVirtualNetworkGatewayVpnClientConfig(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + + addressList := m["address_space"].([]interface{}) + for _, a := range addressList { + buf.WriteString(fmt.Sprintf("%s-", a.(string))) + } + + rootCerts := m["root_certificate"].(*schema.Set) + for _, cert := range rootCerts.List() { + buf.WriteString(fmt.Sprintf("%d-", rootCerts.F(cert))) + } + + if m["revoked_certificate"] != nil { + revokedCerts := m["revoked_certificate"].(*schema.Set) + for _, cert := range revokedCerts.List() { + buf.WriteString(fmt.Sprintf("%d-", revokedCerts.F(cert))) + } + } + + return hashcode.String(buf.String()) +} + +func hashVirtualNetworkGatewaySku(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + + buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["tier"].(string))) + + return hashcode.String(buf.String()) +} diff --git a/builtin/providers/azurerm/resource_arm_virtual_network_gateway_test.go b/builtin/providers/azurerm/resource_arm_virtual_network_gateway_test.go new file mode 100644 index 000000000000..2c0f1e7bb19e --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_virtual_network_gateway_test.go @@ -0,0 +1,277 @@ +package azurerm + +import ( + "fmt" + "net/http" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAzureRMVirtualNetworkGateway_basic(t *testing.T) { + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureRMVirtualNetworkGateway_basic, ri, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMVirtualNetworkDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMVirtualNetworkGatewayExists("azurerm_virtual_network_gateway.test"), + ), + }, + }, + }) +} + +func TestAccAzureRMVirtualNetworkGateway_withTags(t *testing.T) { + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureRMVirtualNetworkGateway_withTags, ri, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMVirtualNetworkGateway_withTagsUpdated, ri, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMVirtualNetworkDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMVirtualNetworkGatewayExists("azurerm_virtual_network_gateway.test"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_gateway.test", "tags.%", "2"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_gateway.test", "tags.environment", "Production"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_gateway.test", "tags.cost_center", "MSFT"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMVirtualNetworkGatewayExists("azurerm_virtual_network_gateway.test"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_gateway.test", "tags.%", "1"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_gateway.test", "tags.environment", "staging"), + ), + }, + }, + }) +} + +func testCheckAzureRMVirtualNetworkGatewayExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + name := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for virtual network gateway: %s", name) + } + + conn := testAccProvider.Meta().(*ArmClient).vnetGatewayClient + + resp, err := conn.Get(resourceGroup, name) + if err != nil { + return fmt.Errorf("Bad: Get on vnetGatewayClient: %s", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: Virtual Network Gateway %q (resource group: %q) does not exist", name, resourceGroup) + } + + return nil + } +} + +func testCheckAzureRMVirtualNetworkGatewayDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).vnetGatewayClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_virtual_network_gateway" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.Get(resourceGroup, name) + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Virtual Network Gateway sitll exists:\n%#v", resp.VirtualNetworkGatewayPropertiesFormat) + } + } + + return nil +} + +var testAccAzureRMVirtualNetworkGateway_basic = ` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "GatewaySubnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.1.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "actestpublicip%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "Dynamic" +} + +resource "azurerm_virtual_network_gateway" "test" { + name = "acctestgw-%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + enable_bgp = false + vpn_type = "RouteBased" + type = "Vpn" + + sku { + name = "Basic" + tier = "Basic" + } + + ip_configuration { + name = "vnetGatewayConfig1" + public_ip_address_id = "${azurerm_public_ip.test.id}" + private_ip_address_allocation = "Dynamic" + subnet_id = "${azurerm_subnet.test.id}" + } +} +` + +var testAccAzureRMVirtualNetworkGateway_withTags = ` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "GatewaySubnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.1.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "actestpublicip%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "Dynamic" +} + +resource "azurerm_virtual_network_gateway" "test" { + name = "acctestgw-%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + enable_bgp = false + vpn_type = "RouteBased" + type = "Vpn" + + sku { + name = "Basic" + tier = "Basic" + } + + ip_configuration { + name = "vnetGatewayConfig1" + public_ip_address_id = "${azurerm_public_ip.test.id}" + private_ip_address_allocation = "Dynamic" + subnet_id = "${azurerm_subnet.test.id}" + } + + tags { + environment = "Production" + cost_center = "MSFT" + } +} +` + +var testAccAzureRMVirtualNetworkGateway_withTagsUpdated = ` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "GatewaySubnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.1.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "actestpublicip%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "Dynamic" +} + +resource "azurerm_virtual_network_gateway" "test" { + name = "acctestgw-%d" + location = "West US" + resource_group_name = "${azurerm_resource_group.test.name}" + enable_bgp = false + vpn_type = "RouteBased" + type = "Vpn" + + sku { + name = "Basic" + tier = "Basic" + } + + ip_configuration { + name = "vnetGatewayConfig1" + public_ip_address_id = "${azurerm_public_ip.test.id}" + private_ip_address_allocation = "Dynamic" + subnet_id = "${azurerm_subnet.test.id}" + } + + tags { + environment = "staging" + } +} +`