Skip to content

Commit

Permalink
r/bridge_domain: add static_remote_vtep_list argument
Browse files Browse the repository at this point in the history
inside vxlan block
Fix #672

and use same way as vlan to vxlan/vlan-id field names on struct
  • Loading branch information
jeremmfr committed Jun 18, 2024
1 parent 7a3ab40 commit 4185d3e
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 73 deletions.
1 change: 1 addition & 0 deletions .changes/issue-672-673.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<!-- markdownlint-disable-file MD013 MD041 -->
ENHANCEMENTS:

* **resource/junos_bridge_domain**: add `static_remote_vtep_list` argument inside `vxlan` block argument (Fix [#672](https://github.com/jeremmfr/terraform-provider-junos/issues/672))
* **resource/junos_routing_instance**: add `remote_vtep_list` and `remote_vtep_v6_list` arguments (Fix [#673](https://github.com/jeremmfr/terraform-provider-junos/issues/673))
* **resource/junos_switch_options**: add `remote_vtep_list` and `remote_vtep_v6_list` arguments
6 changes: 4 additions & 2 deletions docs/resources/bridge_domain.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ The following arguments are supported:
Declare vxlan options.
- **vni** (Required, Number)
VXLAN identifier (0..16777214).
- **vni_extend_evpn** (Optional, Boolean)
Extend VNI to EVPN.
- **decapsulate_accept_inner_vlan** (Optional, Boolean)
Accept VXLAN packets with inner VLAN.
- **encapsulate_inner_vlan** (Optional, Boolean)
Expand All @@ -65,10 +67,10 @@ The following arguments are supported:
CIDR for Multicast group registered for VXLAN segment.
- **ovsdb_managed** (Optional, Boolean)
Bridge-domain is managed remotely via VXLAN OVSDB Controller.
- **static_remote_vtep_list** (Optional, Set of String)
Configure bridge domain specific static remote VXLAN tunnel endpoints.
- **unreachable_vtep_aging_timer** (Optional, Number)
Unreachable VXLAN tunnel endpoint removal timer (300..1800 seconds).
- **vni_extend_evpn** (Optional, Boolean)
Extend VNI to EVPN.

## Attribute Reference

Expand Down
137 changes: 83 additions & 54 deletions internal/providerfwk/resource_bridge_domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,17 @@ func (rsc *bridgeDomain) Schema(
tfvalidator.BoolTrue(),
},
},
"static_remote_vtep_list": schema.SetAttribute{
ElementType: types.StringType,
Optional: true,
Description: "Configure bridge domain specific static remote VXLAN tunnel endpoints.",
Validators: []validator.Set{
setvalidator.SizeAtLeast(1),
setvalidator.ValueStringsAre(
tfvalidator.StringIPAddress().IPv4Only(),
),
},
},
"unreachable_vtep_aging_timer": schema.Int64Attribute{
Optional: true,
Description: "Unreachable VXLAN tunnel endpoint removal timer.",
Expand Down Expand Up @@ -289,40 +300,53 @@ type bridgeDomainData struct {
IsolatedVLAN types.Int64 `tfsdk:"isolated_vlan"`
RoutingInterface types.String `tfsdk:"routing_interface"`
ServiceID types.Int64 `tfsdk:"service_id"`
VLANID types.Int64 `tfsdk:"vlan_id"`
VLANIDList []types.String `tfsdk:"vlan_id_list"`
VXLAN *bridgeDomainBlockVXLAN `tfsdk:"vxlan"`
VlanID types.Int64 `tfsdk:"vlan_id"`
VlanIDList []types.String `tfsdk:"vlan_id_list"`
Vxlan *bridgeDomainBlockVxlan `tfsdk:"vxlan"`
}

type bridgeDomainConfig struct {
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
RoutingInstance types.String `tfsdk:"routing_instance"`
CommunityVlans types.Set `tfsdk:"community_vlans"`
Description types.String `tfsdk:"description"`
DomainID types.Int64 `tfsdk:"domain_id"`
DomainTypeBridge types.Bool `tfsdk:"domain_type_bridge"`
Interface types.Set `tfsdk:"interface"`
IsolatedVLAN types.Int64 `tfsdk:"isolated_vlan"`
RoutingInterface types.String `tfsdk:"routing_interface"`
ServiceID types.Int64 `tfsdk:"service_id"`
VLANID types.Int64 `tfsdk:"vlan_id"`
VLANIDList types.Set `tfsdk:"vlan_id_list"`
VXLAN *bridgeDomainBlockVXLAN `tfsdk:"vxlan"`
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
RoutingInstance types.String `tfsdk:"routing_instance"`
CommunityVlans types.Set `tfsdk:"community_vlans"`
Description types.String `tfsdk:"description"`
DomainID types.Int64 `tfsdk:"domain_id"`
DomainTypeBridge types.Bool `tfsdk:"domain_type_bridge"`
Interface types.Set `tfsdk:"interface"`
IsolatedVLAN types.Int64 `tfsdk:"isolated_vlan"`
RoutingInterface types.String `tfsdk:"routing_interface"`
ServiceID types.Int64 `tfsdk:"service_id"`
VlanID types.Int64 `tfsdk:"vlan_id"`
VlanIDList types.Set `tfsdk:"vlan_id_list"`
Vxlan *bridgeDomainBlockVxlanConfig `tfsdk:"vxlan"`
}

func (rscConfig *bridgeDomainConfig) isEmpty() bool {
return tfdata.CheckBlockIsEmpty(rscConfig, "ID", "Name", "RoutingInstance")
}

type bridgeDomainBlockVXLAN struct {
type bridgeDomainBlockVxlan struct {
Vni types.Int64 `tfsdk:"vni"`
VniExtendEvpn types.Bool `tfsdk:"vni_extend_evpn"`
DecapsulateAcceptInnerVlan types.Bool `tfsdk:"decapsulate_accept_inner_vlan"`
EncapsulateInnerVlan types.Bool `tfsdk:"encapsulate_inner_vlan"`
IngressNodeReplication types.Bool `tfsdk:"ingress_node_replication"`
MulticastGroup types.String `tfsdk:"multicast_group"`
OvsdbManaged types.Bool `tfsdk:"ovsdb_managed"`
StaticRemoteVtepList []types.String `tfsdk:"static_remote_vtep_list"`
UnreachableVtepAgingTimer types.Int64 `tfsdk:"unreachable_vtep_aging_timer"`
}

type bridgeDomainBlockVxlanConfig struct {
Vni types.Int64 `tfsdk:"vni"`
VniExtendEvpn types.Bool `tfsdk:"vni_extend_evpn"`
DecapsulateAcceptInnerVlan types.Bool `tfsdk:"decapsulate_accept_inner_vlan"`
EncapsulateInnerVlan types.Bool `tfsdk:"encapsulate_inner_vlan"`
IngressNodeReplication types.Bool `tfsdk:"ingress_node_replication"`
MulticastGroup types.String `tfsdk:"multicast_group"`
OvsdbManaged types.Bool `tfsdk:"ovsdb_managed"`
StaticRemoteVtepList types.Set `tfsdk:"static_remote_vtep_list"`
UnreachableVtepAgingTimer types.Int64 `tfsdk:"unreachable_vtep_aging_timer"`
}

Expand All @@ -343,16 +367,16 @@ func (rsc *bridgeDomain) ValidateConfig(
)
}

if !config.VLANID.IsNull() && !config.VLANID.IsUnknown() &&
!config.VLANIDList.IsNull() && !config.VLANIDList.IsUnknown() {
if !config.VlanID.IsNull() && !config.VlanID.IsUnknown() &&
!config.VlanIDList.IsNull() && !config.VlanIDList.IsUnknown() {
resp.Diagnostics.AddAttributeError(
path.Root("vlan_id"),
tfdiag.ConflictConfigErrSummary,
"vlan_id and vlan_id_list cannot be configured together",
)
}
if config.VXLAN != nil {
if config.VXLAN.Vni.IsNull() {
if config.Vxlan != nil {
if config.Vxlan.Vni.IsNull() {
resp.Diagnostics.AddAttributeError(
path.Root("vxlan").AtName("vni"),
tfdiag.MissingConfigErrSummary,
Expand Down Expand Up @@ -624,39 +648,42 @@ func (rscData *bridgeDomainData) set(
configSet = append(configSet, setPrefix+"service-id "+
utils.ConvI64toa(rscData.ServiceID.ValueInt64()))
}
if !rscData.VLANID.IsNull() {
if !rscData.VlanID.IsNull() {
configSet = append(configSet, setPrefix+"vlan-id "+
utils.ConvI64toa(rscData.VLANID.ValueInt64()))
utils.ConvI64toa(rscData.VlanID.ValueInt64()))
}
for _, v := range rscData.VLANIDList {
for _, v := range rscData.VlanIDList {
configSet = append(configSet, setPrefix+"vlan-id-list "+v.ValueString())
}
if rscData.VXLAN != nil {
if rscData.Vxlan != nil {
configSet = append(configSet, setPrefix+"vxlan vni "+
utils.ConvI64toa(rscData.VXLAN.Vni.ValueInt64()))
utils.ConvI64toa(rscData.Vxlan.Vni.ValueInt64()))

if rscData.VXLAN.VniExtendEvpn.ValueBool() {
if rscData.Vxlan.VniExtendEvpn.ValueBool() {
configSet = append(configSet, setPrefixProtocolsEvpn+"extended-vni-list "+
utils.ConvI64toa(rscData.VXLAN.Vni.ValueInt64()))
utils.ConvI64toa(rscData.Vxlan.Vni.ValueInt64()))
}
if rscData.VXLAN.DecapsulateAcceptInnerVlan.ValueBool() {
if rscData.Vxlan.DecapsulateAcceptInnerVlan.ValueBool() {
configSet = append(configSet, setPrefix+"vxlan decapsulate-accept-inner-vlan")
}
if rscData.VXLAN.EncapsulateInnerVlan.ValueBool() {
if rscData.Vxlan.EncapsulateInnerVlan.ValueBool() {
configSet = append(configSet, setPrefix+"vxlan encapsulate-inner-vlan")
}
if rscData.VXLAN.IngressNodeReplication.ValueBool() {
if rscData.Vxlan.IngressNodeReplication.ValueBool() {
configSet = append(configSet, setPrefix+"vxlan ingress-node-replication")
}
if v := rscData.VXLAN.MulticastGroup.ValueString(); v != "" {
if v := rscData.Vxlan.MulticastGroup.ValueString(); v != "" {
configSet = append(configSet, setPrefix+"vxlan multicast-group "+v)
}
if rscData.VXLAN.OvsdbManaged.ValueBool() {
if rscData.Vxlan.OvsdbManaged.ValueBool() {
configSet = append(configSet, setPrefix+"vxlan ovsdb-managed")
}
if !rscData.VXLAN.UnreachableVtepAgingTimer.IsNull() {
for _, v := range rscData.Vxlan.StaticRemoteVtepList {
configSet = append(configSet, setPrefix+"vxlan static-remote-vtep-list "+v.ValueString())
}
if !rscData.Vxlan.UnreachableVtepAgingTimer.IsNull() {
configSet = append(configSet, setPrefix+"vxlan unreachable-vtep-aging-timer "+
utils.ConvI64toa(rscData.VXLAN.UnreachableVtepAgingTimer.ValueInt64()))
utils.ConvI64toa(rscData.Vxlan.UnreachableVtepAgingTimer.ValueInt64()))
}
}

Expand Down Expand Up @@ -718,19 +745,19 @@ func (rscData *bridgeDomainData) read(
return err
}
case balt.CutPrefixInString(&itemTrim, "vlan-id "):
rscData.VLANID, err = tfdata.ConvAtoi64Value(itemTrim)
rscData.VlanID, err = tfdata.ConvAtoi64Value(itemTrim)
if err != nil {
return err
}
case balt.CutPrefixInString(&itemTrim, "vlan-id-list "):
rscData.VLANIDList = append(rscData.VLANIDList, types.StringValue(itemTrim))
rscData.VlanIDList = append(rscData.VlanIDList, types.StringValue(itemTrim))
case balt.CutPrefixInString(&itemTrim, "vxlan "):
if rscData.VXLAN == nil {
rscData.VXLAN = &bridgeDomainBlockVXLAN{}
if rscData.Vxlan == nil {
rscData.Vxlan = &bridgeDomainBlockVxlan{}
}
switch {
case balt.CutPrefixInString(&itemTrim, "vni "):
rscData.VXLAN.Vni, err = tfdata.ConvAtoi64Value(itemTrim)
rscData.Vxlan.Vni, err = tfdata.ConvAtoi64Value(itemTrim)
if err != nil {
return err
}
Expand All @@ -747,24 +774,26 @@ func (rscData *bridgeDomainData) read(
break
}
if itemEvpn == junos.SetLS+"extended-vni-list "+itemTrim {
rscData.VXLAN.VniExtendEvpn = types.BoolValue(true)
rscData.Vxlan.VniExtendEvpn = types.BoolValue(true)

break
}
}
}
case itemTrim == "decapsulate-accept-inner-vlan":
rscData.VXLAN.DecapsulateAcceptInnerVlan = types.BoolValue(true)
rscData.Vxlan.DecapsulateAcceptInnerVlan = types.BoolValue(true)
case itemTrim == "encapsulate-inner-vlan":
rscData.VXLAN.EncapsulateInnerVlan = types.BoolValue(true)
rscData.Vxlan.EncapsulateInnerVlan = types.BoolValue(true)
case itemTrim == "ingress-node-replication":
rscData.VXLAN.IngressNodeReplication = types.BoolValue(true)
rscData.Vxlan.IngressNodeReplication = types.BoolValue(true)
case balt.CutPrefixInString(&itemTrim, "multicast-group "):
rscData.VXLAN.MulticastGroup = types.StringValue(itemTrim)
rscData.Vxlan.MulticastGroup = types.StringValue(itemTrim)
case itemTrim == "ovsdb-managed":
rscData.VXLAN.OvsdbManaged = types.BoolValue(true)
rscData.Vxlan.OvsdbManaged = types.BoolValue(true)
case balt.CutPrefixInString(&itemTrim, "static-remote-vtep-list "):
rscData.Vxlan.StaticRemoteVtepList = append(rscData.Vxlan.StaticRemoteVtepList, types.StringValue(itemTrim))
case balt.CutPrefixInString(&itemTrim, "unreachable-vtep-aging-timer "):
rscData.VXLAN.UnreachableVtepAgingTimer, err = tfdata.ConvAtoi64Value(itemTrim)
rscData.Vxlan.UnreachableVtepAgingTimer, err = tfdata.ConvAtoi64Value(itemTrim)
if err != nil {
return err
}
Expand Down Expand Up @@ -801,10 +830,10 @@ func (rscData *bridgeDomainData) delOpts(
for _, v := range rscData.Interface {
configSet = append(configSet, delPrefix+"interface "+v.ValueString())
}
if rscData.VXLAN != nil {
if rscData.VXLAN.VniExtendEvpn.ValueBool() {
if rscData.Vxlan != nil {
if rscData.Vxlan.VniExtendEvpn.ValueBool() {
configSet = append(configSet, delPrefixProtocolsEvpn+
"extended-vni-list "+utils.ConvI64toa(rscData.VXLAN.Vni.ValueInt64()))
"extended-vni-list "+utils.ConvI64toa(rscData.Vxlan.Vni.ValueInt64()))
}
}

Expand All @@ -822,10 +851,10 @@ func (rscData *bridgeDomainData) del(
configSet := []string{
delPrefix + "bridge-domains \"" + rscData.Name.ValueString() + "\"",
}
if rscData.VXLAN != nil {
if rscData.VXLAN.VniExtendEvpn.ValueBool() {
if rscData.Vxlan != nil {
if rscData.Vxlan.VniExtendEvpn.ValueBool() {
configSet = append(configSet, delPrefix+
"protocols evpn extended-vni-list "+utils.ConvI64toa(rscData.VXLAN.Vni.ValueInt64()))
"protocols evpn extended-vni-list "+utils.ConvI64toa(rscData.Vxlan.Vni.ValueInt64()))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ resource "junos_routing_instance" "testacc_bridge_ri" {
route_distinguisher = "10:11"
vrf_target = "target:1:200"
vtep_source_interface = junos_interface_logical.testacc_bridge_ri.name
remote_vtep_list = ["192.0.2.136", "192.0.2.36"]
}
resource "junos_evpn" "testacc_bridge_ri" {
routing_instance = junos_routing_instance.testacc_bridge_ri.name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ resource "junos_routing_instance" "testacc_bridge_ri" {
route_distinguisher = "10:11"
vrf_target = "target:1:200"
vtep_source_interface = junos_interface_logical.testacc_bridge_ri.name
remote_vtep_list = ["192.0.2.136", "192.0.2.36"]
}
resource "junos_evpn" "testacc_bridge_ri" {
routing_instance = junos_routing_instance.testacc_bridge_ri.name
Expand All @@ -48,6 +49,7 @@ resource "junos_bridge_domain" "testacc_bridge_ri" {
service_id = 12
vlan_id = 13
vxlan {
vni = 15
vni = 15
static_remote_vtep_list = ["192.0.2.136", "192.0.2.36"]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ resource "junos_routing_instance" "testacc_bridge_ri" {
route_distinguisher = "10:11"
vrf_target = "target:1:200"
vtep_source_interface = junos_interface_logical.testacc_bridge_ri.name
remote_vtep_list = ["192.0.2.136", "192.0.2.36"]
}
resource "junos_evpn" "testacc_bridge_ri" {
routing_instance = junos_routing_instance.testacc_bridge_ri.name
Expand All @@ -47,6 +48,7 @@ resource "junos_bridge_domain" "testacc_bridge_ri" {
service_id = 12
vlan_id = 13
vxlan {
vni = 15
vni = 15
static_remote_vtep_list = ["192.0.2.36"]
}
}
30 changes: 15 additions & 15 deletions internal/providerfwk/upgradestate_bridge_domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ func upgradeBridgeDomainStateV0toV1(
IsolatedVLAN types.Int64 `tfsdk:"isolated_vlan"`
RoutingInterface types.String `tfsdk:"routing_interface"`
ServiceID types.Int64 `tfsdk:"service_id"`
VLANID types.Int64 `tfsdk:"vlan_id"`
VLANIDList []types.String `tfsdk:"vlan_id_list"`
VXLAN []struct {
VlanID types.Int64 `tfsdk:"vlan_id"`
VlanIDList []types.String `tfsdk:"vlan_id_list"`
Vxlan []struct {
Vni types.Int64 `tfsdk:"vni"`
VniExtendEvpn types.Bool `tfsdk:"vni_extend_evpn"`
DecapsulateAcceptInnerVlan types.Bool `tfsdk:"decapsulate_accept_inner_vlan"`
Expand Down Expand Up @@ -136,18 +136,18 @@ func upgradeBridgeDomainStateV0toV1(
dataV1.IsolatedVLAN = dataV0.IsolatedVLAN
dataV1.RoutingInterface = dataV0.RoutingInterface
dataV1.ServiceID = dataV0.ServiceID
dataV1.VLANID = dataV0.VLANID
dataV1.VLANIDList = dataV0.VLANIDList
if len(dataV0.VXLAN) > 0 {
dataV1.VXLAN = &bridgeDomainBlockVXLAN{
Vni: dataV0.VXLAN[0].Vni,
VniExtendEvpn: dataV0.VXLAN[0].VniExtendEvpn,
DecapsulateAcceptInnerVlan: dataV0.VXLAN[0].DecapsulateAcceptInnerVlan,
EncapsulateInnerVlan: dataV0.VXLAN[0].EncapsulateInnerVlan,
IngressNodeReplication: dataV0.VXLAN[0].IngressNodeReplication,
OvsdbManaged: dataV0.VXLAN[0].OvsdbManaged,
MulticastGroup: dataV0.VXLAN[0].MulticastGroup,
UnreachableVtepAgingTimer: dataV0.VXLAN[0].UnreachableVtepAgingTimer,
dataV1.VlanID = dataV0.VlanID
dataV1.VlanIDList = dataV0.VlanIDList
if len(dataV0.Vxlan) > 0 {
dataV1.Vxlan = &bridgeDomainBlockVxlan{
Vni: dataV0.Vxlan[0].Vni,
VniExtendEvpn: dataV0.Vxlan[0].VniExtendEvpn,
DecapsulateAcceptInnerVlan: dataV0.Vxlan[0].DecapsulateAcceptInnerVlan,
EncapsulateInnerVlan: dataV0.Vxlan[0].EncapsulateInnerVlan,
IngressNodeReplication: dataV0.Vxlan[0].IngressNodeReplication,
OvsdbManaged: dataV0.Vxlan[0].OvsdbManaged,
MulticastGroup: dataV0.Vxlan[0].MulticastGroup,
UnreachableVtepAgingTimer: dataV0.Vxlan[0].UnreachableVtepAgingTimer,
}
}

Expand Down

0 comments on commit 4185d3e

Please sign in to comment.