Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_express_route_circuit_peering - support for bandwidth_in_gbps, express_route_port_id #12289

Merged
merged 18 commits into from
Jun 24, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -330,17 +330,17 @@ resource "azurerm_express_route_circuit_peering" "test" {
express_route_circuit_name = azurerm_express_route_circuit.test.name
resource_group_name = azurerm_resource_group.test.name
peer_asn = 100
primary_peer_address_prefix = "192.168.3.0/30"
secondary_peer_address_prefix = "192.168.4.0/30"
primary_peer_address_prefix = "192.168.7.0/30"
secondary_peer_address_prefix = "192.168.8.0/30"
vlan_id = 300

microsoft_peering_config {
advertised_public_prefixes = ["123.2.0.0/24"]
advertised_public_prefixes = ["123.4.0.0/24"]
}

ipv6 {
primary_peer_address_prefix = "2002:db01::/126"
secondary_peer_address_prefix = "2003:db01::/126"
primary_peer_address_prefix = "2002:db03::/126"
secondary_peer_address_prefix = "2003:db03::/126"

microsoft_peering {
advertised_public_prefixes = ["2002:db01::/126"]
Expand Down Expand Up @@ -385,19 +385,19 @@ resource "azurerm_express_route_circuit_peering" "test" {
express_route_circuit_name = azurerm_express_route_circuit.test.name
resource_group_name = azurerm_resource_group.test.name
peer_asn = 100
primary_peer_address_prefix = "192.168.3.0/30"
secondary_peer_address_prefix = "192.168.4.0/30"
primary_peer_address_prefix = "192.168.9.0/30"
secondary_peer_address_prefix = "192.168.10.0/30"
vlan_id = 300

microsoft_peering_config {
advertised_public_prefixes = ["123.2.0.0/24"]
advertised_public_prefixes = ["123.5.0.0/24"]
}
ipv6 {
primary_peer_address_prefix = "2002:db01::/126"
secondary_peer_address_prefix = "2003:db01::/126"
primary_peer_address_prefix = "2002:db05::/126"
secondary_peer_address_prefix = "2003:db05::/126"

microsoft_peering {
advertised_public_prefixes = ["2002:db01::/126"]
advertised_public_prefixes = ["2002:db05::/126"]
customer_asn = 64511
routing_registry_name = "ARIN"
}
Expand Down Expand Up @@ -454,18 +454,18 @@ resource "azurerm_express_route_circuit_peering" "test" {
express_route_circuit_name = azurerm_express_route_circuit.test.name
resource_group_name = azurerm_resource_group.test.name
peer_asn = 100
primary_peer_address_prefix = "192.168.3.0/30"
secondary_peer_address_prefix = "192.168.4.0/30"
primary_peer_address_prefix = "192.168.11.0/30"
secondary_peer_address_prefix = "192.168.12.0/30"
vlan_id = 300
route_filter_id = azurerm_route_filter.test.id

microsoft_peering_config {
advertised_public_prefixes = ["123.2.0.0/24"]
advertised_public_prefixes = ["123.3.0.0/24"]
}

ipv6 {
primary_peer_address_prefix = "2002:db01::/126"
secondary_peer_address_prefix = "2003:db01::/126"
primary_peer_address_prefix = "2002:db02::/126"
secondary_peer_address_prefix = "2003:db02::/126"
route_filter_id = azurerm_route_filter.test.id

microsoft_peering {
Expand Down Expand Up @@ -513,12 +513,12 @@ resource "azurerm_express_route_circuit_peering" "test" {
express_route_circuit_name = azurerm_express_route_circuit.test.name
resource_group_name = azurerm_resource_group.test.name
peer_asn = 100
primary_peer_address_prefix = "192.168.1.0/30"
secondary_peer_address_prefix = "192.168.2.0/30"
primary_peer_address_prefix = "192.168.3.0/30"
secondary_peer_address_prefix = "192.168.4.0/30"
vlan_id = 300

microsoft_peering_config {
advertised_public_prefixes = ["123.1.0.0/24"]
advertised_public_prefixes = ["123.2.0.0/24"]
// https://tools.ietf.org/html/rfc5398
customer_asn = 64511
routing_registry_name = "ARIN"
Expand Down Expand Up @@ -618,8 +618,8 @@ resource "azurerm_express_route_circuit_peering" "test" {
express_route_circuit_name = azurerm_express_route_circuit.test.name
resource_group_name = azurerm_resource_group.test.name
peer_asn = 100
primary_peer_address_prefix = "192.168.1.0/30"
secondary_peer_address_prefix = "192.168.2.0/30"
primary_peer_address_prefix = "192.168.5.0/30"
secondary_peer_address_prefix = "192.168.6.0/30"
vlan_id = 300
route_filter_id = azurerm_route_filter.test.id

Expand Down
108 changes: 72 additions & 36 deletions azurerm/internal/services/network/express_route_circuit_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/suppress"
Expand Down Expand Up @@ -55,25 +57,6 @@ func resourceExpressRouteCircuit() *pluginsdk.Resource {

"location": azure.SchemaLocation(),

"service_provider_name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: suppress.CaseDifference,
},

"peering_location": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: suppress.CaseDifference,
},

"bandwidth_in_mbps": {
Type: pluginsdk.TypeInt,
Required: true,
},

"sku": {
Type: pluginsdk.TypeList,
Required: true,
Expand Down Expand Up @@ -111,6 +94,47 @@ func resourceExpressRouteCircuit() *pluginsdk.Resource {
Default: false,
},

"service_provider_name": {
Type: pluginsdk.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: suppress.CaseDifference,
RequiredWith: []string{"bandwidth_in_mbps", "peering_location"},
ConflictsWith: []string{"bandwidth_in_gbps", "express_route_port_id"},
},

"peering_location": {
Type: pluginsdk.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: suppress.CaseDifference,
RequiredWith: []string{"bandwidth_in_mbps", "service_provider_name"},
ConflictsWith: []string{"bandwidth_in_gbps", "express_route_port_id"},
},

"bandwidth_in_mbps": {
Type: pluginsdk.TypeInt,
Optional: true,
RequiredWith: []string{"peering_location", "service_provider_name"},
ConflictsWith: []string{"bandwidth_in_gbps", "express_route_port_id"},
},

"bandwidth_in_gbps": {
Type: pluginsdk.TypeFloat,
Optional: true,
RequiredWith: []string{"express_route_port_id"},
ConflictsWith: []string{"bandwidth_in_mbps", "peering_location", "service_provider_name"},
},

"express_route_port_id": {
Type: pluginsdk.TypeString,
Optional: true,
ForceNew: true,
RequiredWith: []string{"bandwidth_in_gbps"},
ConflictsWith: []string{"bandwidth_in_mbps", "peering_location", "service_provider_name"},
ValidateFunc: validate.ExpressRoutePortID,
},

"service_provider_provisioning_state": {
Type: pluginsdk.TypeString,
Computed: true,
Expand Down Expand Up @@ -154,12 +178,9 @@ func resourceExpressRouteCircuitCreateUpdate(d *pluginsdk.ResourceData, meta int
}

location := azure.NormalizeLocation(d.Get("location").(string))
serviceProviderName := d.Get("service_provider_name").(string)
peeringLocation := d.Get("peering_location").(string)
bandwidthInMbps := int32(d.Get("bandwidth_in_mbps").(int))
sku := expandExpressRouteCircuitSku(d)
allowRdfeOps := d.Get("allow_classic_operations").(bool)
t := d.Get("tags").(map[string]interface{})
allowRdfeOps := d.Get("allow_classic_operations").(bool)
expandedTags := tags.Expand(t)

// There is the potential for the express route circuit to become out of sync when the service provider updates
Expand Down Expand Up @@ -191,24 +212,29 @@ func resourceExpressRouteCircuitCreateUpdate(d *pluginsdk.ResourceData, meta int
erc.Sku = sku
erc.Tags = expandedTags

if erc.ExpressRouteCircuitPropertiesFormat != nil {
if !d.IsNewResource() {
erc.ExpressRouteCircuitPropertiesFormat.AllowClassicOperations = &allowRdfeOps
if erc.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties != nil {
erc.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties.ServiceProviderName = &serviceProviderName
erc.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties.PeeringLocation = &peeringLocation
erc.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties.BandwidthInMbps = &bandwidthInMbps
}
} else {
erc.ExpressRouteCircuitPropertiesFormat = &network.ExpressRouteCircuitPropertiesFormat{
AllowClassicOperations: &allowRdfeOps,
ServiceProviderProperties: &network.ExpressRouteCircuitServiceProviderProperties{
ServiceProviderName: &serviceProviderName,
PeeringLocation: &peeringLocation,
BandwidthInMbps: &bandwidthInMbps,
},
erc.ExpressRouteCircuitPropertiesFormat = &network.ExpressRouteCircuitPropertiesFormat{}

// ServiceProviderProperties and expressRoutePorts/bandwidthInGbps properties are mutually exclusive
if _, ok := d.GetOk("express_route_port_id"); ok {
erc.ExpressRouteCircuitPropertiesFormat.ExpressRoutePort = &network.SubResource{}
} else {
erc.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties = &network.ExpressRouteCircuitServiceProviderProperties{}
}
}

if erc.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties != nil {
erc.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties.ServiceProviderName = utils.String(d.Get("service_provider_name").(string))
erc.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties.PeeringLocation = utils.String(d.Get("peering_location").(string))
erc.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties.BandwidthInMbps = utils.Int32(int32(d.Get("bandwidth_in_mbps").(int)))

} else {
erc.ExpressRouteCircuitPropertiesFormat.ExpressRoutePort.ID = utils.String(d.Get("express_route_port_id").(string))
erc.ExpressRouteCircuitPropertiesFormat.BandwidthInGbps = utils.Float(d.Get("bandwidth_in_gbps").(float64))
}

future, err := client.CreateOrUpdate(ctx, resGroup, name, erc)
if err != nil {
return fmt.Errorf("Error Creating/Updating ExpressRouteCircuit %q (Resource Group %q): %+v", name, resGroup, err)
Expand Down Expand Up @@ -283,6 +309,16 @@ func resourceExpressRouteCircuitRead(d *pluginsdk.ResourceData, meta interface{}
}
}

if resp.ExpressRoutePort != nil {
d.Set("bandwidth_in_gbps", resp.BandwidthInGbps)

portID, err := parse.ExpressRoutePortID(*resp.ExpressRoutePort.ID)
xuzhang3 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}
d.Set("express_route_port_id", portID.ID())
}

if props := resp.ServiceProviderProperties; props != nil {
d.Set("service_provider_name", props.ServiceProviderName)
d.Set("peering_location", props.PeeringLocation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ func TestAccExpressRouteCircuit(t *testing.T) {
"requiresImport": testAccExpressRouteCircuit_requiresImport,
"data_basic": testAccDataSourceExpressRoute_basicMetered,
"bandwidthReduction": testAccExpressRouteCircuit_bandwidthReduction,
"port": testAccExpressRouteCircuit_withExpressRoutePort,
"updatePort": testAccExpressRouteCircuit_updateExpressRoutePort,
},
"PrivatePeering": {
"azurePrivatePeering": testAccExpressRouteCircuitPeering_azurePrivatePeering,
Expand Down Expand Up @@ -258,6 +260,43 @@ func testAccExpressRouteCircuit_bandwidthReduction(t *testing.T) {
})
}

func testAccExpressRouteCircuit_withExpressRoutePort(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_express_route_circuit", "test")
r := ExpressRouteCircuitResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.withExpressRoutePort(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func testAccExpressRouteCircuit_updateExpressRoutePort(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_express_route_circuit", "test")
r := ExpressRouteCircuitResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.withExpressRoutePort(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.updateExpressRoutePort(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func (t ExpressRouteCircuitResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := azure.ParseAzureResourceID(state.ID)
if err != nil {
Expand Down Expand Up @@ -505,3 +544,73 @@ resource "azurerm_express_route_circuit" "test" {
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, bandwidth)
}

func (ExpressRouteCircuitResource) withExpressRoutePort(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-expressroutecircuit-%d"
location = "%s"
}

resource "azurerm_express_route_port" "test" {
name = "acctest-ERP-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
peering_location = "Airtel-Chennai2-CLS"
bandwidth_in_gbps = 10
encapsulation = "Dot1Q"
}

resource "azurerm_express_route_circuit" "test" {
name = "acctest-ExpressRouteCircuit-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
express_route_port_id = azurerm_express_route_port.test.id
bandwidth_in_gbps = 5

sku {
tier = "Standard"
family = "MeteredData"
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger)
}

func (ExpressRouteCircuitResource) updateExpressRoutePort(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-expressroutecircuit-%d"
location = "%s"
}

resource "azurerm_express_route_port" "test" {
name = "acctest-ERP-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
peering_location = "Airtel-Chennai2-CLS"
bandwidth_in_gbps = 10
encapsulation = "Dot1Q"
}

resource "azurerm_express_route_circuit" "test" {
name = "acctest-ExpressRouteCircuit-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
express_route_port_id = azurerm_express_route_port.test.id
bandwidth_in_gbps = 10

sku {
tier = "Standard"
family = "MeteredData"
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger)
}
Loading