Skip to content

dcnm_fabric: ND 4.x full-payload update sends empty-string nvPairs for feature-dependent parameters instead of template defaults #696

Description

@allenrobel

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Ansible Version and collection version

DCNM version

  • Applies to ND 4.1/4.2 (any controller where is_controller_version_4x is true)
  • Symptom observed on ND 4.3 EFT (out of support scope for this collection — see "scope" note below)

Affected module(s)

  • dcnm_fabric

Problem

Since the fix for #609, when the controller is ND 4.x, FabricUpdateCommon._fabric_needs_update_for_merged_state() (plugins/module_utils/fabric/update.py) builds the update payload by deep-copying the fabric's current nvPairs from the controller GET and overlaying the user's changes, because ND 4.x requires the full parameter set on PUT.

If the fabric was created with a minimal config, the controller stores "" for optional feature-dependent nvPairs (e.g. PTP_DOMAIN_ID, PTP_LB_ID, L3VNI_MCAST_GROUP, AUTO_SYMMETRIC_VRF_LITE, AUTO_SYMMETRIC_DEFAULT_VRF, DEFAULT_VRF_REDIS_BGP_RMAP). A later merged-state task that enables the parent features (FEATURE_PTP, ENABLE_TRM, VRF_LITE_AUTOCONFIG, AUTO_VRFLITE_IFC_DEFAULT_VRF) echoes those dependent parameters back to the controller as "".

This is internally inconsistent: VerifyPlaybookParams passes validation on the assumption that template defaults satisfy the dependency rules, but the payload the module then sends explicitly contradicts those defaults with empty strings. It works on ND 4.1/4.2 only because the legacy API silently populates template defaults for empty dependent fields server-side.

Example failure (ND 4.3 EFT, where the server validates strictly instead of populating defaults):

"DATA": "Invalid JSON response: Failed to update the fabric, due to invalid fields
[{PTP_DOMAIN_ID=, AUTO_SYMMETRIC_VRF_LITE=, PTP_LB_ID=, DEFAULT_VRF_REDIS_BGP_RMAP=,
enableMvpnVriId=, AUTO_SYMMETRIC_DEFAULT_VRF=, L3VNI_MCAST_GROUP=}], please provide valid fields
[{PTP_DOMAIN_ID=0, AUTO_SYMMETRIC_VRF_LITE=false, PTP_LB_ID=0,
DEFAULT_VRF_REDIS_BGP_RMAP=extcon-rmap-filter, enableMvpnVriId=true,
AUTO_SYMMETRIC_DEFAULT_VRF=false, L3VNI_MCAST_GROUP=239.1.1.0}] for fabric-settings",
"MESSAGE": "Bad Request", "METHOD": "PUT",
"REQUEST_PATH": ".../rest/control/fabrics/<fabric>/Easy_Fabric", "RETURN_CODE": 400

Every rejected field is a dependent of a feature the playbook enables, and every suggested value is the fabric template's defaultValue.

Expected Behavior

When building the ND 4.x full payload, the module should substitute the fabric template's default value for nvPairs whose controller-stored value is "", rather than echoing the empty string. The values sent would then match both what VerifyPlaybookParams assumed during validation and what the ND 4.1/4.2 server computes anyway (behavior-neutral on those releases).

Actual Behavior

Empty-string nvPairs are echoed verbatim in the PUT payload.

Steps to Reproduce

  1. state: merged — create a VXLAN_EVPN fabric with only FABRIC_NAME, FABRIC_TYPE, BGP_AS.
  2. state: merged — update the same fabric enabling FEATURE_PTP: true, ENABLE_TRM: true, VRF_LITE_AUTOCONFIG: Back2Back&ToExternal, AUTO_VRFLITE_IFC_DEFAULT_VRF: true without supplying their dependent parameters.
  3. Inspect the PUT payload (debug log): dependent parameters are sent as "" while their parent features are enabled.

Proposed fix

The merged-state path already fetches the fabric template from the controller (plugins/modules/dcnm_fabric.py, TemplateGet + VerifyPlaybookParams), and ParamInfo already extracts per-parameter defaults (plugins/module_utils/fabric/param_info.py, _get_default()). Wire the template/ParamInfo into FabricUpdateBulk and, in the ND 4.x full-payload branch, replace "" values with the template default.

Because the defaults come from the controller's own template, version-specific parameters (e.g. enableMvpnVriId) resolve correctly per-controller — no hardcoded key lists to maintain, unlike _remove_nd4x_problematic_keys.

Caution: substitution must not clobber the #622 workaround — STP_BRIDGE_PRIORITY must remain "" when STP_ROOT_OPTION is "unmanaged". This argues for gating substitution on the template's IsShow/dependency rules (the Ruleset machinery already exists) rather than blanket replacement of every empty value that has a default.

Scope note: this collection has no plans to support ND 4.3; the justification for this change is ND 4.1/4.2 correctness/consistency (payload should match what the module's own validation assumed). That it also avoids the strict-validation 400 on newer servers is a side effect.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions