diff --git a/azurerm/data_source_virtual_network_gateway.go b/azurerm/data_source_virtual_network_gateway.go index 0e0271e3c595..516a9fe3f015 100644 --- a/azurerm/data_source_virtual_network_gateway.go +++ b/azurerm/data_source_virtual_network_gateway.go @@ -57,6 +57,11 @@ func dataSourceArmVirtualNetworkGateway() *schema.Resource { Computed: true, }, + "generation": { + Type: schema.TypeString, + Computed: true, + }, + "ip_configuration": { Type: schema.TypeList, Computed: true, @@ -219,6 +224,7 @@ func dataSourceArmVirtualNetworkGatewayRead(d *schema.ResourceData, meta interfa d.Set("type", string(gw.GatewayType)) d.Set("enable_bgp", gw.EnableBgp) d.Set("active_active", gw.ActiveActive) + d.Set("generation", string(gw.VpnGatewayGeneration)) if string(gw.VpnType) != "" { d.Set("vpn_type", string(gw.VpnType)) diff --git a/azurerm/resource_arm_virtual_network_gateway.go b/azurerm/resource_arm_virtual_network_gateway.go index e015b430bd4e..833941be6d3c 100644 --- a/azurerm/resource_arm_virtual_network_gateway.go +++ b/azurerm/resource_arm_virtual_network_gateway.go @@ -97,11 +97,24 @@ func resourceArmVirtualNetworkGateway() *schema.Resource { // and validateArmVirtualNetworkGatewayExpressRouteSku. ValidateFunc: validation.Any( validateArmVirtualNetworkGatewayPolicyBasedVpnSku(), - validateArmVirtualNetworkGatewayRouteBasedVpnSku(), + validateArmVirtualNetworkGatewayRouteBasedVpnSkuGeneration1(), + validateArmVirtualNetworkGatewayRouteBasedVpnSkuGeneration2(), validateArmVirtualNetworkGatewayExpressRouteSku(), ), }, + "generation": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(network.VpnGatewayGenerationGeneration1), + string(network.VpnGatewayGenerationGeneration2), + string(network.VpnGatewayGenerationNone), + }, false), + }, + "ip_configuration": { Type: schema.TypeList, Required: true, @@ -364,6 +377,7 @@ func resourceArmVirtualNetworkGatewayRead(d *schema.ResourceData, meta interface d.Set("type", string(gw.GatewayType)) d.Set("enable_bgp", gw.EnableBgp) d.Set("active_active", gw.ActiveActive) + d.Set("generation", string(gw.VpnGatewayGeneration)) if string(gw.VpnType) != "" { d.Set("vpn_type", string(gw.VpnType)) @@ -420,14 +434,16 @@ func getArmVirtualNetworkGatewayProperties(d *schema.ResourceData) (*network.Vir vpnType := network.VpnType(d.Get("vpn_type").(string)) enableBgp := d.Get("enable_bgp").(bool) activeActive := d.Get("active_active").(bool) + generation := network.VpnGatewayGeneration(d.Get("generation").(string)) props := &network.VirtualNetworkGatewayPropertiesFormat{ - GatewayType: gatewayType, - VpnType: vpnType, - EnableBgp: &enableBgp, - ActiveActive: &activeActive, - Sku: expandArmVirtualNetworkGatewaySku(d), - IPConfigurations: expandArmVirtualNetworkGatewayIPConfigurations(d), + GatewayType: gatewayType, + VpnType: vpnType, + EnableBgp: &enableBgp, + ActiveActive: &activeActive, + VpnGatewayGeneration: generation, + Sku: expandArmVirtualNetworkGatewaySku(d), + IPConfigurations: expandArmVirtualNetworkGatewayIPConfigurations(d), } if gatewayDefaultSiteID := d.Get("default_local_network_gateway_id").(string); gatewayDefaultSiteID != "" { @@ -451,9 +467,16 @@ func getArmVirtualNetworkGatewayProperties(d *schema.ResourceData) (*network.Vir } } - // Sku validation for route-based VPN gateways - if props.GatewayType == network.VirtualNetworkGatewayTypeVpn && props.VpnType == network.RouteBased { - if ok, err := evaluateSchemaValidateFunc(string(props.Sku.Name), "sku", validateArmVirtualNetworkGatewayRouteBasedVpnSku()); !ok { + // Sku validation for route-based VPN gateways of first geneneration + if props.GatewayType == network.VirtualNetworkGatewayTypeVpn && props.VpnType == network.RouteBased && props.VpnGatewayGeneration == network.VpnGatewayGenerationGeneration1 { + if ok, err := evaluateSchemaValidateFunc(string(props.Sku.Name), "sku", validateArmVirtualNetworkGatewayRouteBasedVpnSkuGeneration1()); !ok { + return nil, err + } + } + + // Sku validation for route-based VPN gateways of second geneneration + if props.GatewayType == network.VirtualNetworkGatewayTypeVpn && props.VpnType == network.RouteBased && props.VpnGatewayGeneration == network.VpnGatewayGenerationGeneration2 { + if ok, err := evaluateSchemaValidateFunc(string(props.Sku.Name), "sku", validateArmVirtualNetworkGatewayRouteBasedVpnSkuGeneration2()); !ok { return nil, err } } @@ -764,7 +787,7 @@ func validateArmVirtualNetworkGatewayPolicyBasedVpnSku() schema.SchemaValidateFu }, true) } -func validateArmVirtualNetworkGatewayRouteBasedVpnSku() schema.SchemaValidateFunc { +func validateArmVirtualNetworkGatewayRouteBasedVpnSkuGeneration1() schema.SchemaValidateFunc { return validation.StringInSlice([]string{ string(network.VirtualNetworkGatewaySkuTierBasic), string(network.VirtualNetworkGatewaySkuTierStandard), @@ -778,6 +801,19 @@ func validateArmVirtualNetworkGatewayRouteBasedVpnSku() schema.SchemaValidateFun }, true) } +func validateArmVirtualNetworkGatewayRouteBasedVpnSkuGeneration2() schema.SchemaValidateFunc { + return validation.StringInSlice([]string{ + string(network.VirtualNetworkGatewaySkuNameVpnGw2), + string(network.VirtualNetworkGatewaySkuNameVpnGw3), + string(network.VirtualNetworkGatewaySkuNameVpnGw4), + string(network.VirtualNetworkGatewaySkuNameVpnGw5), + string(network.VirtualNetworkGatewaySkuNameVpnGw2AZ), + string(network.VirtualNetworkGatewaySkuNameVpnGw3AZ), + string(network.VirtualNetworkGatewaySkuNameVpnGw4AZ), + string(network.VirtualNetworkGatewaySkuNameVpnGw5AZ), + }, true) +} + func validateArmVirtualNetworkGatewayExpressRouteSku() schema.SchemaValidateFunc { return validation.StringInSlice([]string{ string(network.VirtualNetworkGatewaySkuTierStandard), diff --git a/azurerm/resource_arm_virtual_network_gateway_test.go b/azurerm/resource_arm_virtual_network_gateway_test.go index 1ce598de9a6b..94bdfc31420b 100644 --- a/azurerm/resource_arm_virtual_network_gateway_test.go +++ b/azurerm/resource_arm_virtual_network_gateway_test.go @@ -193,6 +193,27 @@ func TestAccAzureRMVirtualNetworkGateway_vpnGw3(t *testing.T) { }) } +func TestAccAzureRMVirtualNetworkGateway_generation(t *testing.T) { + resourceName := "azurerm_virtual_network_gateway.test" + ri := tf.AccRandTimeInt() + config := testAccAzureRMVirtualNetworkGateway_generation(ri, testLocation(), "Generation2") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMVirtualNetworkGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMVirtualNetworkGatewayExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "generation", "Generation2"), + ), + }, + }, + }) +} + func TestAccAzureRMVirtualNetworkGateway_vpnClientConfig(t *testing.T) { ri := tf.AccRandTimeInt() resourceName := "azurerm_virtual_network_gateway.test" @@ -808,3 +829,50 @@ resource "azurerm_virtual_network_gateway" "test" { } `, rInt, location, rInt, rInt, rInt) } + +func testAccAzureRMVirtualNetworkGateway_generation(rInt int, location string, generation string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvn-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.0.0.0/16"] +} + +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 = "acctestpip-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + allocation_method = "Dynamic" +} + +resource "azurerm_virtual_network_gateway" "test" { + name = "acctestvng-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + type = "Vpn" + vpn_type = "RouteBased" + sku = "VpnGw2" + generation = "%s" + + ip_configuration { + public_ip_address_id = "${azurerm_public_ip.test.id}" + private_ip_address_allocation = "Dynamic" + subnet_id = "${azurerm_subnet.test.id}" + } +} +`, rInt, location, rInt, rInt, rInt, generation) +} diff --git a/website/docs/d/virtual_network_gateway.html.markdown b/website/docs/d/virtual_network_gateway.html.markdown index a3258c33aa41..682e7954fe40 100644 --- a/website/docs/d/virtual_network_gateway.html.markdown +++ b/website/docs/d/virtual_network_gateway.html.markdown @@ -51,6 +51,8 @@ output "virtual_network_gateway_id" { * `sku` - Configuration of the size and capacity of the Virtual Network Gateway. +* `generation` - The Generation of the Virtual Network Gateway. + * `ip_configuration` - One or two `ip_configuration` blocks documented below. * `vpn_client_configuration` - A `vpn_client_configuration` block which is documented below. diff --git a/website/docs/r/virtual_network_gateway.html.markdown b/website/docs/r/virtual_network_gateway.html.markdown index bbe284055602..c7f1e9358507 100644 --- a/website/docs/r/virtual_network_gateway.html.markdown +++ b/website/docs/r/virtual_network_gateway.html.markdown @@ -136,13 +136,17 @@ The following arguments are supported: * `sku` - (Required) Configuration of the size and capacity of the virtual network gateway. Valid options are `Basic`, `Standard`, `HighPerformance`, `UltraPerformance`, - `ErGw1AZ`, `ErGw2AZ`, `ErGw3AZ`, `VpnGw1`, `VpnGw2`, `VpnGw3`, `VpnGw1AZ`, `VpnGw2AZ`, and `VpnGw3AZ` - and depend on the `type` and `vpn_type` arguments. + `ErGw1AZ`, `ErGw2AZ`, `ErGw3AZ`, `VpnGw1`, `VpnGw2`, `VpnGw3`, `VpnGw4`,`VpnGw5`, `VpnGw1AZ`, + `VpnGw2AZ`, `VpnGw3AZ`,`VpnGw4AZ` and `VpnGw5AZ` and depend on the `type`, `vpn_type` and + `generation` arguments. A `PolicyBased` gateway only supports the `Basic` sku. Further, the `UltraPerformance` - sku is only supported by an `ExpressRoute` gateway. + sku is only supported by an `ExpressRoute` gateway. ~> **NOTE:** To build a UltraPerformance ExpressRoute Virtual Network gateway, the associated Public IP needs to be sku "Basic" not "Standard" +* `generation` - (Optional) The Generation of the Virtual Network gateway. Possible values include `Generation1`, `Generation2` or `None`. + +-> **NOTE:** The available values depend on the `type` and `sku` arguments - where `Generation2` is only value for a `sku` larger than `VpnGw2` or `VpnGw2AZ`. * `ip_configuration` (Required) One or two `ip_configuration` blocks documented below. An active-standby gateway requires exactly one `ip_configuration` block whereas