Skip to content

Commit

Permalink
azurerm_virtual_network: support for bgp_community and `vnet_protec…
Browse files Browse the repository at this point in the history
…tion_enabled` (#8979)

Support for bgp_community and vnet_protection_enabled properties for vnet.
  • Loading branch information
magodo authored Nov 6, 2020
1 parent 194a523 commit 0771690
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,79 @@ func TestAccAzureRMVirtualNetwork_deleteSubnet(t *testing.T) {
})
}

func TestAccAzureRMVirtualNetwork_bgpCommunity(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_virtual_network", "test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acceptance.PreCheck(t) },
Providers: acceptance.SupportedProviders,
CheckDestroy: testCheckAzureRMVirtualNetworkDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMVirtualNetwork_basic(data),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualNetworkExists(data.ResourceName),
),
},
data.ImportStep(),
{
Config: testAccAzureRMVirtualNetwork_bgpCommunity(data),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualNetworkExists(data.ResourceName),
),
},
data.ImportStep(),
{
Config: testAccAzureRMVirtualNetwork_basic(data),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualNetworkExists(data.ResourceName),
),
},
data.ImportStep(),
},
})
}

func TestAccAzureRMVirtualNetwork_vmProtection(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_virtual_network", "test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acceptance.PreCheck(t) },
Providers: acceptance.SupportedProviders,
CheckDestroy: testCheckAzureRMVirtualNetworkDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMVirtualNetwork_basic(data),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualNetworkExists(data.ResourceName),
),
},
data.ImportStep(),
{
Config: testAccAzureRMVirtualNetwork_vmProtection(data, true),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualNetworkExists(data.ResourceName),
),
},
data.ImportStep(),
{
Config: testAccAzureRMVirtualNetwork_vmProtection(data, false),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualNetworkExists(data.ResourceName),
),
},
data.ImportStep(),
{
Config: testAccAzureRMVirtualNetwork_basic(data),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualNetworkExists(data.ResourceName),
),
},
data.ImportStep(),
},
})
}

func testCheckAzureRMVirtualNetworkExists(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client := acceptance.AzureProvider.Meta().(*clients.Client).Network.VnetClient
Expand Down Expand Up @@ -480,3 +553,57 @@ resource "azurerm_virtual_network" "test" {
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func testAccAzureRMVirtualNetwork_bgpCommunity(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_virtual_network" "test" {
name = "acctestvirtnet%d"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
subnet {
name = "subnet1"
address_prefix = "10.0.1.0/24"
}
bgp_community = "12076:20000"
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func testAccAzureRMVirtualNetwork_vmProtection(data acceptance.TestData, enabled bool) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_virtual_network" "test" {
name = "acctestvirtnet%d"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
subnet {
name = "subnet1"
address_prefix = "10.0.1.0/24"
}
vm_protection_enabled = %t
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, enabled)
}
37 changes: 37 additions & 0 deletions azurerm/internal/services/network/validate/virtual_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package validate

import (
"fmt"
"strconv"
"strings"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/parse"
)
Expand All @@ -21,3 +23,38 @@ func VirtualNetworkID(i interface{}, k string) (warnings []string, errors []erro

return warnings, errors
}

func VirtualNetworkBgpCommunity(i interface{}, k string) (warnings []string, errors []error) {
v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("expected type of %q to be string", k))
return
}

segments := strings.Split(v, ":")
if len(segments) != 2 {
errors = append(errors, fmt.Errorf(`invalid notation of bgp community: expected "x:y"`))
return
}

asn, err := strconv.Atoi(segments[0])
if err != nil {
errors = append(errors, fmt.Errorf(`converting asn %q: %v`, segments[0], err))
return
}
if !(asn > 0 && asn < 65535) {
errors = append(errors, fmt.Errorf(`asn %d exceeds range: [0, 65535]`, asn))
return
}

comm, err := strconv.Atoi(segments[1])
if err != nil {
errors = append(errors, fmt.Errorf(`converting community value %q: %v`, segments[1], err))
return
}
if !(comm > 0 && comm < 65535) {
errors = append(errors, fmt.Errorf(`community value %d exceeds range: [0, 65535]`, comm))
return
}
return warnings, errors
}
33 changes: 32 additions & 1 deletion azurerm/internal/services/network/virtual_network_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"net/http"
"time"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/validate"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
Expand Down Expand Up @@ -63,6 +65,12 @@ func resourceArmVirtualNetwork() *schema.Resource {
},
},

"bgp_community": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validate.VirtualNetworkBgpCommunity,
},

"ddos_protection_plan": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -92,6 +100,12 @@ func resourceArmVirtualNetwork() *schema.Resource {
},
},

"vm_protection_enabled": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},

"guid": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -260,6 +274,18 @@ func resourceArmVirtualNetworkRead(d *schema.ResourceData, meta interface{}) err
if err := d.Set("dns_servers", flattenVirtualNetworkDNSServers(props.DhcpOptions)); err != nil {
return fmt.Errorf("Error setting `dns_servers`: %+v", err)
}

bgpCommunity := ""
if p := props.BgpCommunities; p != nil {
if v := p.VirtualNetworkCommunity; v != nil {
bgpCommunity = *v
}
}
if err := d.Set("bgp_community", bgpCommunity); err != nil {
return fmt.Errorf("Error setting `bgp_community`: %+v", err)
}

d.Set("vm_protection_enabled", props.EnableVMProtection)
}

return tags.FlattenAndSet(d, resp.Tags)
Expand Down Expand Up @@ -345,7 +371,8 @@ func expandVirtualNetworkProperties(ctx context.Context, d *schema.ResourceData,
DhcpOptions: &network.DhcpOptions{
DNSServers: utils.ExpandStringSlice(d.Get("dns_servers").([]interface{})),
},
Subnets: &subnets,
EnableVMProtection: utils.Bool(d.Get("vm_protection_enabled").(bool)),
Subnets: &subnets,
}

if v, ok := d.GetOk("ddos_protection_plan"); ok {
Expand All @@ -369,6 +396,10 @@ func expandVirtualNetworkProperties(ctx context.Context, d *schema.ResourceData,
}
}

if v, ok := d.GetOk("bgp_community"); ok {
properties.BgpCommunities = &network.VirtualNetworkBgpCommunities{VirtualNetworkCommunity: utils.String(v.(string))}
}

return properties, nil
}

Expand Down
6 changes: 6 additions & 0 deletions website/docs/r/virtual_network.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ The following arguments are supported:

* `location` - (Required) The location/region where the virtual network is created. Changing this forces a new resource to be created.

* `bgp_community` - (Optional) The BGP community attribute in format `<as-number>:<community-value>`.

-> **NOTE** The `as-number` segment is the Microsoft ASN, which is always `12076` for now.

* `ddos_protection_plan` - (Optional) A `ddos_protection_plan` block as documented below.

* `dns_servers` - (Optional) List of IP addresses of DNS servers
Expand All @@ -89,6 +93,8 @@ The following arguments are supported:

-> **NOTE** Since `subnet` can be configured both inline and via the separate `azurerm_subnet` resource, we have to explicitly set it to empty slice (`[]`) to remove it.

* `vm_protection_enabled` - (Optional) Whether to enable VM protection for all the subnets in this Virtual Network. Defaults to `false`.

* `tags` - (Optional) A mapping of tags to assign to the resource.

---
Expand Down

0 comments on commit 0771690

Please sign in to comment.