Skip to content

[ND 4.2+] Add modules for both Routing Policies Community Lists and Extended Community Lists (NDA-28) - #287

Open
gmicol wants to merge 19 commits into
CiscoDevNet:developfrom
gmicol:nd42_community_lists
Open

[ND 4.2+] Add modules for both Routing Policies Community Lists and Extended Community Lists (NDA-28)#287
gmicol wants to merge 19 commits into
CiscoDevNet:developfrom
gmicol:nd42_community_lists

Conversation

@gmicol

@gmicol gmicol commented May 20, 2026

Copy link
Copy Markdown
Collaborator

Related Issue(s)

Fixes #241
Fixes #242

Proposed Changes

  • Add nd_manage_community_list for ND 4.2+ Routing Policies Community Lists.
  • Add nd_manage_extended_community_list for ND 4.2+ Routing Policies Extended Community Lists.
  • Implement Manage API endpoints, models, enums, and orchestrators using the current Orchestrators framework and NDStateMachine.
  • Support merged, replaced, overridden, and deleted states.
  • Add module documentation, examples, return data, and check mode support.
  • Add unit coverage for endpoints, models, and orchestrators.
  • Add integration test targets for both modules.

Test Notes

  • Ran focused unit tests for the new endpoint, model, and orchestrator coverage: 30 passed.

Cisco Nexus Dashboard Version

Developed against Cisco Nexus Dashboard 4.2.1 / ND 4.2+.

Related ND API Resource Category

  • analyze
  • infa
  • manage
  • onemanage
  • other

Checklist

  • Latest commit is rebased from develop with merge conflicts resolved
  • New or updates to documentation has been made accordingly
  • Assigned the proper reviewers

@gmicol gmicol self-assigned this May 20, 2026
@gmicol gmicol added enhancement New feature or request jira-sync Sync this issue to Jira 2.0.0 Release 2.0.0 nda-project Move this issue to the NDA project labels May 20, 2026
@github-actions github-actions Bot changed the title [ND 4.2+] Add modules for both Routing Policies Community Lists and Extended Community Lists [ND 4.2+] Add modules for both Routing Policies Community Lists and Extended Community Lists (DCNE-827) May 20, 2026
@dcne-automation dcne-automation changed the title [ND 4.2+] Add modules for both Routing Policies Community Lists and Extended Community Lists (DCNE-827) [ND 4.2+] Add modules for both Routing Policies Community Lists and Extended Community Lists (NDA-28) May 20, 2026
@gmicol
gmicol force-pushed the nd42_community_lists branch from 6204e42 to a272206 Compare June 30, 2026 12:57
@gmicol gmicol added the ready for review Submitter is requesting a PR review label Jun 30, 2026
@gmicol
gmicol marked this pull request as ready for review June 30, 2026 12:59
@gmicol
gmicol force-pushed the nd42_community_lists branch from a272206 to 8fd0005 Compare June 30, 2026 13:07
Comment thread plugins/module_utils/models/manage_community_list/manage_community_list.py Outdated
Comment thread plugins/module_utils/orchestrators/manage_community_list.py Outdated
Comment thread plugins/modules/nd_manage_community_list.py Outdated
Comment thread plugins/modules/nd_manage_community_list.py Outdated
@sivakasi-cisco sivakasi-cisco added the nac01 NaC ND release 0.0.1 label Jul 14, 2026
samiib
samiib previously approved these changes Jul 24, 2026
Comment thread plugins/modules/nd_manage_community_list.py Outdated
gmicol added 18 commits July 29, 2026 11:26
Use PEP 585/604 annotations throughout the new module stacks and remove obsolete Python 2 boilerplate from production and unit-test files.
Normalize tenant-qualified names to bare Ansible config names while using computed API names for identifiers, payloads, update paths, and bulk deletes. Enforce the default and fully qualified API name length limits and cover same-name lists across tenants.
Use Pydantic validation context to enforce type-specific entry rules only for Ansible config. ND response parsing now tolerates controller-added cross-type fields while config validation remains strict.
Require type and entries during merged, replaced, and overridden validation using the state context supplied by NDStateMachine. Identifier-only models remain valid for deleted state and response parsing.
Normalize controller-added false flags and empty collections out of diff comparisons so identical merged configuration is stable. Explicitly clearing an active flag still produces an update.
Expose the OpenAPI clusterName query parameter as cluster_name and compose it with shared Lucene filter, pagination, and sort parameters. Add cluster_name to both module argument specs and cover item and collection URLs.
Pass explicit create, update, and delete operation types on custom bulk and item mutation requests. Results and verbose API history now classify writes correctly instead of recording them as queries.
Walk collection endpoints with bounded max and offset parameters, de-duplicate repeated rows, and stop safely when a controller ignores offset. Forward cluster_name to item, collection, and mutation endpoints through the shared endpoint configuration hook.
Use the NDStateMachine preflight hook for fabric mutation validation so check mode still fails early on unsafe writes. Collection reads and delete reconciliation no longer invoke mutation-only validation.
Treat only explicit failed, failure, and error tokens as per-item bulk failures, matching the current route-map denylist behavior. Accepted, empty, missing, and future informational status values no longer cause spurious module failures.
Set version_added to 2.0.0, remove the unsupported description example, and document cluster and tenant-qualified behavior. Define the standard state-machine return fields and representative samples for both modules.
Verify merged idempotency in both check and normal modes. Add opt-in coverage for same-name objects in two tenants, guarded by nd_test_tenant_name_a and nd_test_tenant_name_b, with tenant-aware cleanup.
Remove obsolete Python 2 future imports from the shared endpoint mixin file touched by the new community-list name mixins.
Add the class-level spacing required by pycodestyle. This resolves the sole failure reported by the containerized sanity run.
Require every standard community-list entry to select a community number or enable a well-known flag for config writes. Keep controller response parsing permissive, correct the module documentation, and add unit plus integration regression definitions.
Accept the comma-packed route-target grammar allowed by OpenAPI and normalize it to canonical list items for config and response data. Document the behavior and cover serialization, response parsing, invalid input, and idempotency.
@gmicol
gmicol force-pushed the nd42_community_lists branch from b7dd305 to 83c2c89 Compare July 30, 2026 13:52
@gmicol
gmicol requested a review from mikewiebe July 30, 2026 13:57
@samiib
samiib self-requested a review July 30, 2026 22:29

@allenrobel allenrobel left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review (follow-up)

Re-reviewed the commits pushed since my last review. All ten review-response fixes check out as claimed — nice work, especially the tenant-scoped api_name identity and the diff-normalization/idempotency mechanics, which I traced end to end. Three additive findings below as inline comments.

🤖 Generated with Claude Code

data["name"] = self.api_name
return data

def to_diff_dict(self, **kwargs) -> dict[str, Any]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This to_diff_dict() override (and its twin in manage_extended_community_list.py line 298) works around an ND wire-shape discrepancy: ND echoes false well-known-flag defaults (and empty collections, in the extended model) for fields the user never set. Per the team's workaround-marker convention, each such site needs its own TODO(4.2.1) <slug> marker so the workaround can be audited and removed later — same pattern as the route-map model's next-hop boolean stripping in manage_route_map.py. Until we've found a way to share the bug-tracker data that backs the slugs, please use TBD as the slug (as the route-map PR did), e.g.:

# TODO(4.2.1) TBD
# ND echoes false/empty defaults for unset standard-entry fields on GET; strip them so diffs stay idempotent.

One marker here and one on the extended twin.

if getattr(entry, field) is not None:
raise ValueError(f"entries[{i}].{field} must not be set for " "type='expanded'. Use community_number_regex instead.")
else:
# standard

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up to "Reject flagless standard community entries": that commit added an at-least-one-selector rule to CommunityListModel (a standard entry must set at least one community number or well-known flag), but the standard branch here never got the equivalent. All five selector collections default to None, so a standard entry with only sequence_number + action passes local validation and is sent to ND — the same failure mode Mike lab-verified for community lists. The module docs also still say entries "may set any combination of" the collections, with no at-least-one requirement.

Suggest mirroring the community-list fix: for config input, require at least one of the five collections to be non-empty, update the DOCUMENTATION/notes, and add the matching unit coverage. (Caveat: I have not lab-verified that ND rejects the extended variant the way it rejects flagless standard community entries — worth a quick check while you're in there.)


model_config = ConfigDict(extra="forbid")

cluster_name: str | None = Field(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cluster_name is hand-declared here (and in manage_extended_community_lists.py line 47) with a definition identical to the existing ClusterNameMixin in endpoints/mixins.py, whose stated purpose is adding common fields to endpoint models without duplication. The other endpoint-params classes in the collection compose the mixin for this exact field, and model_config = ConfigDict(extra="forbid") layers fine on top of it elsewhere. Suggest class CommunityListsEndpointParams(ClusterNameMixin, EndpointQueryParams) (and the twin) and dropping the local field.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2.0.0 Release 2.0.0 enhancement New feature or request jira-sync Sync this issue to Jira nac01 NaC ND release 0.0.1 nda-project Move this issue to the NDA project ready for review Submitter is requesting a PR review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ND 4.2+] Add Extended Community Lists Module [ND 4.2+] Add Community Lists Module

6 participants