Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 124 additions & 2 deletions generator/defs/vrf-bulk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -400,9 +400,132 @@ resource:
description: If set to `true`, does a deployment of all attachments in this `vrf`. This parameter cannot be set to `true` if `deploy_all_attachments` in the resource is set or `deploy_this_attachment` in the `attach-list` is set
ndfc_type: bool
example: false
- model_name: msd_child_fabric_attributes
tf_name: msd_child_fabric_attributes
type: MapNested
description: Multi Site Domain child fabric specific vrf attributes
payload_hide: true
computed: true
optional: true
attributes:
- model_name: fabric_name
tf_name: fabric_name
type: String
description: The name of the fabric
example: CML
computed: true
- model_name: advertiseHostRouteFlag
tf_name: advertise_host_routes
type: Bool
optional: true
computed: true
default_value: false
description: "MSD Child fabric: Flag to Control Advertisement of /32 and /128 Routes to Edge Routers"
example: true
- model_name: advertiseDefaultRouteFlag
tf_name: advertise_default_route
type: Bool
optional: true
computed: true
default_value: true
description: "Child fabric: Flag to Control Advertisement of Default Route Internally"
example: false
- model_name: configureStaticDefaultRouteFlag
tf_name: configure_static_default_route
type: Bool
optional: true
computed: true
default_value: true
description: "Child fabric: Flag to Control Static Default Route Configuration"
example: false
- model_name: bgpPassword
tf_name: bgp_password
type: String
string_patterns: ['^[a-fA-F0-9]+$']
default_value: ""
description: VRF Lite BGP neighbor password (Hex String)
example: 1234567890ABCDEF
- model_name: bgpPasswordKeyType
tf_name: bgp_password_type
type: String
enum_values: ["3", "7"]
default_value: ""
description: "VRF Lite BGP Key Encryption Type: 3 - 3DES, 7 - Cisco"
example: 7
- model_name: ENABLE_NETFLOW
tf_name: netflow
type: Bool
optional: true
computed: true
default_value: false
description: For netflow on VRF-LITE Sub-interface. Supported only if netflow is enabled on fabric. For NX-OS only
example: false
- model_name: NETFLOW_MONITOR
tf_name: netflow_monitor
type: String
default_value: ""
description: Netflow monitor. For NX-OS only
example: MON1
- model_name: trmEnabled
tf_name: trm
type: Bool
optional: true
computed: true
default_value: false
description: Enable Tenant Routed Multicast
- model_name: trmBGWMSiteEnabled
tf_name: trm_bgw_msite
type: Bool
optional: true
computed: true
default_value: false
description: Enable TRM on Border Gateway Multisite
example: true
- model_name: isRPAbsent
tf_name: no_rp
type: Bool
optional: true
computed: true
default_value: false
description: There is no RP as only SSM is used
example: false
- model_name: rpAddress
tf_name: rp_address
type: String
default_value: ""
description: IPv4 address
- model_name: loopbackNumber
tf_name: rp_loopback_id
type: Int64
handle_empty: true
min_int: 0
max_int: 1023
description: RP loopback ID
- model_name: L3VniMcastGroup
tf_name: underlay_multicast_address
type: String
default_value: ""
description: IPv4 Multicast Address. Applicable only when TRM is enabled.
- model_name: multicastGroup
tf_name: overlay_multicast_groups
type: String
default_value: ""
description: Overlay multicast groups
example: 234.0.0.0/8
- model_name: routeTargetImportMvpn
tf_name: route_target_import_mvpn
type: String
default_value: ""
description: For MVPN Routes Import, One or a Comma Separated List
exclude_test: true
- model_name: routeTargetExportMvpn
tf_name: route_target_export_mvpn
type: String
default_value: ""
description: For MVPN Routes Export, One or a Comma Separated List
exclude_test: true
- model_name: lanAttachList
augment_from: vrf_attachments.attachments.lanAttachList

datasource:
name: vrf_bulk
doc_category: Fabric
Expand Down Expand Up @@ -650,4 +773,3 @@ datasource:
exclude_test: true
computed: true
optional: false

7 changes: 7 additions & 0 deletions internal/provider/fabric_vxlan_msd_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,16 @@ func (r *fabricVxlanMsdResource) Create(ctx context.Context, req resource.Create
return
}
r.client.AddChildFabricsToMsd(ctx, &resp.Diagnostics, &data)
if resp.Diagnostics.HasError() {
// Cleanup - delete the fabric created
r.client.RscDeleteFabric(ctx, &resp.Diagnostics, data.FabricName.ValueString())
return
}
// Get and set back the child fabrics to make sure they are correctly added in NDFC
data.ChildFabrics = r.GetChildFabrics(ctx, &resp.Diagnostics, data.FabricName.ValueString())
if resp.Diagnostics.HasError() {
// Cleanup - delete the fabric created
r.client.RscDeleteFabric(ctx, &resp.Diagnostics, data.FabricName.ValueString())
return
}
// Save updated data into Terraform state
Expand Down
4 changes: 2 additions & 2 deletions internal/provider/fabrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ func TestAccFabricVxlanMsdResource(t *testing.T) {
PreCheck: func() { testAccPreCheck(t, "fabric_vxlan_msd") },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{ // Create fabric
{ // Create MSD fabric with child_fabric1 and child_fabric2 (resource.tf)
Config: func() string {
*stepCount++
tt := fmt.Sprintf("%s%d", t.Name(), *stepCount)
return helper.GenerateFabricConfig(tt, cfg, helper.Base_file)
}(),
//Check: resource.ComposeTestCheckFunc(FabricVxlanMsdModelHelperStateCheck("ndfc_fabric_vxlan_msd.test_resource_fabric_vxlan_msd_1", FabricRsc, path.Empty())...),
}, { // modify fields like ANYCAST_GW_MAC, BGW_ROUTING_TAG and DELAY_RESTORE with different values and deploy true
}, { // Modify attributes and replace child_fabric2 with child_fabric3 (resource_modified.tf)
Config: func() string {
*stepCount++
tt := fmt.Sprintf("%s%d", t.Name(), *stepCount)
Expand Down
71 changes: 60 additions & 11 deletions internal/provider/ndfc/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import (
"time"

"github.com/netascode/go-nd"

"github.com/tidwall/gjson"
)

type NDFCAPI interface {
Expand Down Expand Up @@ -87,7 +85,7 @@ func (c NDFCAPICommon) Get() ([]byte, error) {
return res, nil
}

func (c NDFCAPICommon) Post(payload []byte) (gjson.Result, error) {
func (c NDFCAPICommon) Post(payload []byte) (nd.Res, error) {

url := c.NDFCAPI.PostUrl()
if strings.Contains(url, "deploy") {
Expand All @@ -112,29 +110,48 @@ func (c NDFCAPICommon) Post(payload []byte) (gjson.Result, error) {
res, err = c.client.Post(c.NDFCAPI.PostUrl(), string(payload))
}
if err != nil {
// Ensure response body is populated for error reporting
if res.Str == "" && res.String() != "" {
res.Str = res.String()
}
if res.Str == "" && res.Raw != "" {
res.Str = res.Raw
}
log.Printf("[ERR] Failed to make POST request: %s |%v|", err, res)
return res, err
}
log.Printf("[DEBUG] POST request was ok")
return res, nil
}

func (c NDFCAPICommon) Put(payload []byte) (gjson.Result, error) {
func (c NDFCAPICommon) Put(payload []byte) (nd.Res, error) {
// Acquire deploy r lock
fnRscAcquireLock(c.NDFCAPI.RscName())
defer fnRscReleaseLock(c.NDFCAPI.RscName())

log.Printf("Put URL: %s\n", c.NDFCAPI.PutUrl())
lock := c.NDFCAPI.GetLock()
lock.Lock()
defer lock.Unlock()
res, err := c.client.Put(c.NDFCAPI.PutUrl(), string(payload))
log.Printf("Put URL acquired lock: %s\n", c.NDFCAPI.PutUrl())
var res nd.Res
var err error
res, err = c.client.Put(c.NDFCAPI.PutUrl(), string(payload))
if err != nil {
// Ensure response body is populated for error reporting
if res.Str == "" && res.String() != "" {
res.Str = res.String()
}
if res.Str == "" && res.Raw != "" {
res.Str = res.Raw
}
log.Printf("[ERR] Failed to make PUT request: %s |%v|", err, res)
return res, err
}
log.Printf("[DEBUG] PUT request was ok")
return res, nil
}

func (c NDFCAPICommon) Delete() (gjson.Result, error) {
func (c NDFCAPICommon) Delete() (nd.Res, error) {
fnRscAcquireLock(c.NDFCAPI.RscName())
defer fnRscReleaseLock(c.NDFCAPI.RscName())

Expand All @@ -159,29 +176,50 @@ func (c NDFCAPICommon) Delete() (gjson.Result, error) {
res, err = c.client.Delete(c.NDFCAPI.DeleteUrl(), "")
}
if err != nil {
// Ensure response body is populated for error reporting
if res.Str == "" && res.String() != "" {
res.Str = res.String()
}
if res.Str == "" && res.Raw != "" {
res.Str = res.Raw
}
log.Printf("[ERR] Failed to make DELETE request: %s |%v|", err, res)
return res, err
}
log.Printf("[DEBUG] DELETE request was ok")
return res, nil
}

func (c NDFCAPICommon) DeleteWithPayload(payload []byte) (gjson.Result, error) {
func (c NDFCAPICommon) DeleteWithPayload(payload []byte) (nd.Res, error) {
fnRscAcquireLock(c.NDFCAPI.RscName())
defer fnRscReleaseLock(c.NDFCAPI.RscName())

c.NDFCAPI.GetLock().Lock()
defer c.NDFCAPI.GetLock().Unlock()
res, err := c.client.Delete(c.NDFCAPI.DeleteUrl(), string(payload))
log.Printf("DeleteWithPayload URL: %s\n", c.NDFCAPI.DeleteUrl())
var res nd.Res
var err error
res, err = c.client.Delete(c.NDFCAPI.DeleteUrl(), string(payload))
if err != nil {
// Ensure response body is populated for error reporting
if res.Str == "" && res.String() != "" {
res.Str = res.String()
}
if res.Str == "" && res.Raw != "" {
res.Str = res.Raw
}
log.Printf("[ERR] Failed to make DELETE request with payload: %s |%v|", err, res)
return res, err
}
log.Printf("[DEBUG] DELETE request with payload was ok")
return res, nil
}

func (c *NDFCAPICommon) SetDeployLocked() {
c.LockedForDeploy = true
}

func (c NDFCAPICommon) DeployPost(payload []byte) (gjson.Result, error) {
func (c NDFCAPICommon) DeployPost(payload []byte) (nd.Res, error) {
// Global write lock must be acquired before deploy lock
// Check
if fnGlobalDeployTryLock(c.NDFCAPI.RscName()) {
Expand All @@ -195,10 +233,21 @@ func (c NDFCAPICommon) DeployPost(payload []byte) (gjson.Result, error) {
lock.Lock()
defer lock.Unlock()
log.Printf("Deploy Post URL acquired lock: %s\n", c.NDFCAPI.PostUrl())
res, err := c.client.Post(c.NDFCAPI.PostUrl(), string(payload))
var res nd.Res
var err error
res, err = c.client.Post(c.NDFCAPI.PostUrl(), string(payload))
if err != nil {
// Ensure response body is populated for error reporting
if res.Str == "" && res.String() != "" {
res.Str = res.String()
}
if res.Str == "" && res.Raw != "" {
res.Str = res.Raw
}
log.Printf("[ERR] Failed to make DEPLOY POST request: %s |%v|", err, res)
return res, err
}
log.Printf("[DEBUG] DEPLOY POST request was ok")
return res, nil
}

Expand Down
16 changes: 16 additions & 0 deletions internal/provider/ndfc/fabric_msd.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,19 @@ func (m *NDFC) GetMsdChildFabricAssociations(ctx context.Context, dg *diag.Diagn
}
return childFabrics
}

// IsFabricMsd checks if a fabric is an MSD parent fabric
func (m *NDFC) IsFabricMsd(ctx context.Context, dg *diag.Diagnostics, fabricName string) bool {
fType := m.GetFabricTemplateType(ctx, dg, fabricName)
if dg.HasError() {
return false
}

if fType != ResourceVxlanMsdType {
tflog.Debug(ctx, fmt.Sprintf("Fabric %s is not MSD parent fabric (type: %s)", fabricName, fType))
return false
}

tflog.Debug(ctx, fmt.Sprintf("Fabric %s is MSD parent fabric", fabricName))
return true
}
11 changes: 6 additions & 5 deletions internal/provider/ndfc/ndfc_global_deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,10 @@ func (c *NDFC) checkDeployStatus(ctx context.Context, diags *diag.Diagnostics, f

// Get configuration preview to refresh switch status.
// This is bug in NDFC sometimes the status is not updated
_, err := c.getConfigurationPreview(fabricName)
if err != nil {
payload, err := c.getConfigurationPreview(fabricName)
if err != nil || payload == nil{
diags.AddError("Deploy failed", "Configuration preview failed")
tflog.Debug(ctx, fmt.Sprintf("checkDeployStatus: Configuration preview failed with error: %v", err))
return nil
}

Expand Down Expand Up @@ -223,10 +224,10 @@ func (c *NDFC) getConfigurationPreview(fabricName string) ([]byte, error) {

// Config Preview refreshes the config status of switches in the fabric
payload, err := previewApi.Get()
if len(payload) == 0 || string(payload) == "[]" || err != nil {
return nil, fmt.Errorf("configuration preview failed")
if (len(payload) == 0 || string(payload) == "[]") && err == nil {
return nil, nil
}
return payload, nil
return payload, err
}

// GetDeploymentHistoryWithFilters provides more detailed filtering options for deployment history
Expand Down
1 change: 1 addition & 0 deletions internal/provider/ndfc/net_deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func (c NDFC) RscDeployNetworkAttachments(ctx context.Context, dg *diag.Diagnost
// Get configuration preview to refresh the deploy status
// This is bug in NDFC sometimes the status is not updated
_, err := c.getConfigurationPreview(d.FabricName)
// payload is empty for MSD fabric hence only error is checked.
if err != nil {
dg.AddError("Deploy failed", "Configuration preview failed")
return
Expand Down
Loading