diff --git a/playbooks/crescit_baseline_demo/00_apply_existing_baseline.yaml b/playbooks/crescit_baseline_demo/00_apply_existing_baseline.yaml new file mode 100644 index 000000000..84fadcd95 --- /dev/null +++ b/playbooks/crescit_baseline_demo/00_apply_existing_baseline.yaml @@ -0,0 +1,119 @@ +--- +# Apply focused baseline configuration used by Crescit demo scenarios. +# This keeps PR scope small while preserving high-value impact and auto-fix paths. +# Incident-informed framing: +# - Meta outage (2021-10-04): control-plane safety during live routing changes +# - Google Cloud incident 19009 (2019-06-02): staged rollout for large config updates +# - Fastly outage (2021-06-08): config gating before broad activation + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + deploy_changes: true + leaf1: 192.168.10.211 + leaf2: 192.168.10.212 + history_line: >- + History: 2023-06-14 Cisco Meraki backend config change triggered + one-time MS390/Catalyst reboot; baseline pins mgmt/data anchors first. + historical_config_anchors: + - incident: "Cisco Meraki MS390 config incident" + reference: "https://status.meraki.net/incidents/gc1gzznrmjl7" + - incident: "Cisco Duo edge misconfiguration outage" + reference: "https://status.duo.com/incidents/hw98mjf7fkth" + + tasks: + - name: Ensure baseline VRFs exist (foundation for scenarios 03/06/09/10) + cisco.dcnm.dcnm_vrf: + fabric: "{{ fabric_name }}" + state: merged + config: + - vrf_name: PROD_VRF_Core + vrf_id: 50010 + vlan_id: 2100 + rd: "65000:10" + vrf_template: Default_VRF_Universal + vrf_extension_template: Default_VRF_Extension_Universal + attach: + - ip_address: "{{ leaf1 }}" + - ip_address: "{{ leaf2 }}" + - vrf_name: PROD_VRF_Shared + vrf_id: 50020 + vlan_id: 2200 + rd: "65000:20" + vrf_template: Default_VRF_Universal + vrf_extension_template: Default_VRF_Extension_Universal + attach: + - ip_address: "{{ leaf1 }}" + - ip_address: "{{ leaf2 }}" + - vrf_name: PROD_VRF_WebTier + vrf_id: 50700 + vlan_id: 2700 + rd: "65000:700" + vrf_template: Default_VRF_Universal + vrf_extension_template: Default_VRF_Extension_Universal + attach: + - ip_address: "{{ leaf1 }}" + deploy: "{{ deploy_changes }}" + + - name: Ensure baseline networks exist (scenario anchors) + cisco.dcnm.dcnm_network: + fabric: "{{ fabric_name }}" + state: merged + config: + # Scenario 03 baseline: management network in secure reserved range + - net_name: MGMT_OOB_NET3901 + vrf_name: PROD_VRF_Core + net_id: 33901 + net_template: Default_Network_Universal + net_extension_template: Default_Network_Extension_Universal + vlan_id: 3901 + gw_ip_subnet: "10.39.1.1/24" + attach: + - ip_address: "{{ leaf1 }}" + ports: [] + # Scenario 06 baseline: existing web-tier network + - net_name: PROD_NET_WebServers + vrf_name: PROD_VRF_WebTier + net_id: 30700 + net_template: Default_Network_Universal + net_extension_template: Default_Network_Extension_Universal + vlan_id: 3070 + gw_ip_subnet: "10.107.10.1/24" + attach: + - ip_address: "{{ leaf1 }}" + ports: [] + # Scenario 09 baseline: legacy network exists before destructive remove test + - net_name: PROD_NET_Legacy_VLAN999 + vrf_name: PROD_VRF_Shared + net_id: 30999 + net_template: Default_Network_Universal + net_extension_template: Default_Network_Extension_Universal + vlan_id: 999 + gw_ip_subnet: "10.199.99.1/24" + attach: + - ip_address: "{{ leaf1 }}" + ports: [] + # Scenario 10 baseline: valid CIDR that PR640 intentionally corrupts + - net_name: PROD_NET_Invalid + vrf_name: PROD_VRF_Core + net_id: 30100 + net_template: Default_Network_Universal + net_extension_template: Default_Network_Extension_Universal + vlan_id: 3010 + gw_ip_subnet: "10.100.1.1/24" + attach: + - ip_address: "{{ leaf1 }}" + ports: [] + - ip_address: "{{ leaf2 }}" + ports: [] + + - name: Show baseline apply completion + ansible.builtin.debug: + msg: + - "{{ history_line }}" + - "Baseline applied for {{ fabric_name }}" + - "deploy_changes={{ deploy_changes }}" + - "Scenario anchors: 03(policy), 06(dependency-chain), 09(blast-radius), 10(auto-fix)" diff --git a/playbooks/crescit_baseline_demo/01_verify_baseline_state.yaml b/playbooks/crescit_baseline_demo/01_verify_baseline_state.yaml new file mode 100644 index 000000000..06257c4be --- /dev/null +++ b/playbooks/crescit_baseline_demo/01_verify_baseline_state.yaml @@ -0,0 +1,36 @@ +--- +# Query focused baseline state in NDFC after initial apply. +# This verification gate exists to reduce "live-change surprise" before PR640 deltas. + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + history_line: >- + History: Cisco Duo 2025-09-09 config change disrupted admin/API traffic; + verify baseline state before applying high-risk deltas. + + tasks: + - name: Query VRFs in fabric + cisco.dcnm.dcnm_vrf: + fabric: "{{ fabric_name }}" + state: query + register: vrf_query + + - name: Query networks in fabric + cisco.dcnm.dcnm_network: + fabric: "{{ fabric_name }}" + state: query + register: net_query + + - name: Show verification summary + ansible.builtin.debug: + msg: + - "{{ history_line }}" + - "Fabric: {{ fabric_name }}" + - "VRF objects found: {{ (vrf_query.response | default([])) | length }}" + - "Network objects found: {{ (net_query.response | default([])) | length }}" + - "Expected VRF markers: PROD_VRF_Core, PROD_VRF_Shared, PROD_VRF_WebTier" + - "Expected network markers: MGMT_OOB_NET3901, PROD_NET_WebServers, PROD_NET_Invalid, PROD_NET_Legacy_VLAN999" diff --git a/playbooks/crescit_baseline_demo/02_seed_shared_vrfs.yaml b/playbooks/crescit_baseline_demo/02_seed_shared_vrfs.yaml new file mode 100644 index 000000000..78b3ea3b3 --- /dev/null +++ b/playbooks/crescit_baseline_demo/02_seed_shared_vrfs.yaml @@ -0,0 +1,39 @@ +--- +# Seed brownfield-safe VRF baseline objects used by Crescit impact analysis. + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + deploy_changes: false + leaf1: 192.168.10.211 + leaf2: 192.168.10.212 + + tasks: + - name: Seed application and shared-service VRFs + cisco.dcnm.dcnm_vrf: + fabric: "{{ fabric_name }}" + state: merged + config: + - vrf_name: PROD_VRF_App + vrf_id: 50030 + vlan_id: 2300 + rd: "65000:30" + vrf_template: Default_VRF_Universal + vrf_extension_template: Default_VRF_Extension_Universal + attach: + - ip_address: "{{ leaf1 }}" + - ip_address: "{{ leaf2 }}" + + - vrf_name: PROD_VRF_Transit + vrf_id: 50040 + vlan_id: 2400 + rd: "65000:40" + vrf_template: Default_VRF_Universal + vrf_extension_template: Default_VRF_Extension_Universal + attach: + - ip_address: "{{ leaf1 }}" + - ip_address: "{{ leaf2 }}" + deploy: "{{ deploy_changes }}" diff --git a/playbooks/crescit_baseline_demo/03_seed_l3vni_networks.yaml b/playbooks/crescit_baseline_demo/03_seed_l3vni_networks.yaml new file mode 100644 index 000000000..de4470543 --- /dev/null +++ b/playbooks/crescit_baseline_demo/03_seed_l3vni_networks.yaml @@ -0,0 +1,58 @@ +--- +# Seed baseline L2/L3 network segments mapped to explicit VRFs. + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + deploy_changes: false + leaf1: 192.168.10.211 + leaf2: 192.168.10.212 + + tasks: + - name: Seed baseline networks for application tiers + cisco.dcnm.dcnm_network: + fabric: "{{ fabric_name }}" + state: merged + config: + - net_name: PROD_NET_AppFrontend + vrf_name: PROD_VRF_App + net_id: 30310 + net_template: Default_Network_Universal + net_extension_template: Default_Network_Extension_Universal + vlan_id: 3310 + gw_ip_subnet: "10.131.10.1/24" + attach: + - ip_address: "{{ leaf1 }}" + ports: [] + - ip_address: "{{ leaf2 }}" + ports: [] + + - net_name: PROD_NET_AppBackend + vrf_name: PROD_VRF_App + net_id: 30311 + net_template: Default_Network_Universal + net_extension_template: Default_Network_Extension_Universal + vlan_id: 3311 + gw_ip_subnet: "10.131.20.1/24" + attach: + - ip_address: "{{ leaf1 }}" + ports: [] + - ip_address: "{{ leaf2 }}" + ports: [] + + - net_name: PROD_NET_Transit + vrf_name: PROD_VRF_Transit + net_id: 30410 + net_template: Default_Network_Universal + net_extension_template: Default_Network_Extension_Universal + vlan_id: 3410 + gw_ip_subnet: "10.141.10.1/24" + attach: + - ip_address: "{{ leaf1 }}" + ports: [] + - ip_address: "{{ leaf2 }}" + ports: [] + deploy: "{{ deploy_changes }}" diff --git a/playbooks/crescit_baseline_demo/04_seed_secure_mgmt_vlan.yaml b/playbooks/crescit_baseline_demo/04_seed_secure_mgmt_vlan.yaml new file mode 100644 index 000000000..3a54f3e40 --- /dev/null +++ b/playbooks/crescit_baseline_demo/04_seed_secure_mgmt_vlan.yaml @@ -0,0 +1,29 @@ +--- +# Seed secure management VLANs in approved policy range for brownfield baseline. + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + deploy_changes: false + + tasks: + - name: Seed management and telemetry VLANs in secure range + cisco.dcnm.dcnm_vlan: + fabric: "{{ fabric_name }}" + state: merged + config: + - vlan_id: 3902 + vlan_name: MGMT_OOB_VLAN3902 + vlan_description: "Out-of-band management baseline" + + - vlan_id: 3903 + vlan_name: MGMT_TELEMETRY_VLAN3903 + vlan_description: "Streaming telemetry baseline" + + - vlan_id: 3904 + vlan_name: MGMT_BACKUP_VLAN3904 + vlan_description: "Backup and restore baseline" + deploy: "{{ deploy_changes }}" diff --git a/playbooks/crescit_baseline_demo/05_seed_interface_profiles.yaml b/playbooks/crescit_baseline_demo/05_seed_interface_profiles.yaml new file mode 100644 index 000000000..fe2fca927 --- /dev/null +++ b/playbooks/crescit_baseline_demo/05_seed_interface_profiles.yaml @@ -0,0 +1,44 @@ +--- +# Seed interface policy intent used as known-good baseline for comparison. + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + deploy_changes: false + leaf1: 192.168.10.211 + leaf2: 192.168.10.212 + + tasks: + - name: Seed routed uplink interface profile + cisco.dcnm.dcnm_interface: + fabric: "{{ fabric_name }}" + state: merged + config: + - name: Ethernet1/31 + type: int_routed + switch: + - "{{ leaf1 }}" + - "{{ leaf2 }}" + profile: + admin_state: true + mtu: 9216 + desc: "Baseline routed uplink for transit" + + - name: Seed SVI profile for app VRF handoff + cisco.dcnm.dcnm_interface: + fabric: "{{ fabric_name }}" + state: merged + config: + - name: Vlan2300 + type: svi + switch: + - "{{ leaf1 }}" + profile: + int_vrf: PROD_VRF_App + ipv4_addr: 10.130.0.1/24 + mtu: 9216 + desc: "Baseline gateway SVI for PROD_VRF_App" + deploy: "{{ deploy_changes }}" diff --git a/playbooks/crescit_baseline_demo/06_seed_uplink_link_templates.yaml b/playbooks/crescit_baseline_demo/06_seed_uplink_link_templates.yaml new file mode 100644 index 000000000..2bee136a3 --- /dev/null +++ b/playbooks/crescit_baseline_demo/06_seed_uplink_link_templates.yaml @@ -0,0 +1,25 @@ +--- +# Seed link templates so PR impact analysis can reason about underlay dependencies. + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + deploy_changes: false + + tasks: + - name: Seed underlay link intent across leaf-spine uplinks + cisco.dcnm.dcnm_links: + state: merged + config: + - source_fabric: "{{ fabric_name }}" + dest_fabric: "{{ fabric_name }}" + template_name: int_routed_host + profile: + ADMIN_STATE: "true" + MTU: "9216" + BFD_ECHO_DISABLE: "false" + ROUTING_TAG: "BASELINE_UNDERLAY" + deploy: "{{ deploy_changes }}" diff --git a/playbooks/crescit_baseline_demo/07_seed_vpc_domain_pair.yaml b/playbooks/crescit_baseline_demo/07_seed_vpc_domain_pair.yaml new file mode 100644 index 000000000..047e452d4 --- /dev/null +++ b/playbooks/crescit_baseline_demo/07_seed_vpc_domain_pair.yaml @@ -0,0 +1,35 @@ +--- +# Seed vPC peer baseline to model link/state dependencies for brownfield migrations. + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + deploy_changes: false + leaf1_ip: 192.168.10.211 + leaf2_ip: 192.168.10.212 + + tasks: + - name: Seed vPC pair baseline profile + cisco.dcnm.dcnm_vpc_pair: + src_fabric: "{{ fabric_name }}" + state: merged + deploy: "{{ deploy_changes }}" + config: + - peerOneId: "{{ leaf1_ip }}" + peerTwoId: "{{ leaf2_ip }}" + templateName: "vpc_pair" + profile: + ADMIN_STATE: true + ALLOWED_VLANS: "100-200,300,3902-3904" + DOMAIN_ID: 1000 + FABRIC_NAME: "{{ fabric_name }}" + KEEP_ALIVE_HOLD_TIMEOUT: 5 + KEEP_ALIVE_VRF: management + PC_MODE: active + PEER1_MEMBER_INTERFACES: e1/20 + PEER1_PCID: 101 + PEER2_MEMBER_INTERFACES: e1/20 + PEER2_PCID: 102 diff --git a/playbooks/crescit_baseline_demo/08_seed_service_extensions.yaml b/playbooks/crescit_baseline_demo/08_seed_service_extensions.yaml new file mode 100644 index 000000000..1a39c960e --- /dev/null +++ b/playbooks/crescit_baseline_demo/08_seed_service_extensions.yaml @@ -0,0 +1,29 @@ +--- +# Seed service extension networks to represent real brownfield dependency chains. + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + deploy_changes: false + leaf1: 192.168.10.211 + + tasks: + - name: Seed shared services extension network + cisco.dcnm.dcnm_network: + fabric: "{{ fabric_name }}" + state: merged + config: + - net_name: PROD_NET_SvcMesh + vrf_name: PROD_VRF_Shared + net_id: 30230 + net_template: Default_Network_Universal + net_extension_template: Default_Network_Extension_Universal + vlan_id: 3230 + gw_ip_subnet: "10.123.30.1/24" + attach: + - ip_address: "{{ leaf1 }}" + ports: [] + deploy: "{{ deploy_changes }}" diff --git a/playbooks/crescit_baseline_demo/09_verify_seeded_objects.yaml b/playbooks/crescit_baseline_demo/09_verify_seeded_objects.yaml new file mode 100644 index 000000000..3b205b54a --- /dev/null +++ b/playbooks/crescit_baseline_demo/09_verify_seeded_objects.yaml @@ -0,0 +1,42 @@ +--- +# Verify all seeded baseline objects before running PR impact analysis. + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + + tasks: + - name: Query seeded VRFs + cisco.dcnm.dcnm_vrf: + fabric: "{{ fabric_name }}" + state: query + register: vrf_query + + - name: Query seeded networks + cisco.dcnm.dcnm_network: + fabric: "{{ fabric_name }}" + state: query + register: network_query + + - name: Query seeded VLANs + cisco.dcnm.dcnm_vlan: + fabric: "{{ fabric_name }}" + state: query + register: vlan_query + + - name: Query seeded vPC pairs + cisco.dcnm.dcnm_vpc_pair: + src_fabric: "{{ fabric_name }}" + state: query + register: vpc_query + + - name: Show baseline verification snapshot + ansible.builtin.debug: + msg: + - "VRFs: {{ (vrf_query.response | default([])) | length }}" + - "Networks: {{ (network_query.response | default([])) | length }}" + - "VLANs: {{ (vlan_query.response | default([])) | length }}" + - "vPC pairs: {{ (vpc_query.response | default([])) | length }}" diff --git a/playbooks/crescit_baseline_demo/10_export_baseline_summary.yaml b/playbooks/crescit_baseline_demo/10_export_baseline_summary.yaml new file mode 100644 index 000000000..53c2a09ce --- /dev/null +++ b/playbooks/crescit_baseline_demo/10_export_baseline_summary.yaml @@ -0,0 +1,30 @@ +--- +# Export baseline summary markers used by demo narration and evidence cards. + +- hosts: ndfc + gather_facts: false + connection: ansible.netcommon.httpapi + + vars: + fabric_name: cisco_test_fabric1 + + tasks: + - name: Build baseline evidence summary + ansible.builtin.set_fact: + baseline_summary: + fabric: "{{ fabric_name }}" + markers: + - PROD_VRF_Core + - PROD_VRF_Shared + - PROD_VRF_App + - PROD_VRF_Transit + - MGMT_OOB_VLAN3902 + - PROD_NET_Legacy_VLAN999 + intent: + - "Brownfield-safe baseline before risky PR rollout" + - "Known-good dependency graph for VRF -> Network -> Interface" + - "Ready for Crescit impact and auto-fix demonstrations" + + - name: Display baseline evidence summary + ansible.builtin.debug: + var: baseline_summary diff --git a/playbooks/crescit_baseline_demo/inventory.yaml b/playbooks/crescit_baseline_demo/inventory.yaml new file mode 100644 index 000000000..920dca6fa --- /dev/null +++ b/playbooks/crescit_baseline_demo/inventory.yaml @@ -0,0 +1,19 @@ +--- +# Baseline demo inventory for Crescit +# Update ansible_host/credentials to match your environment. + +all: + vars: + ansible_python_interpreter: python + ansible_httpapi_validate_certs: false + ansible_httpapi_use_ssl: true + children: + ndfc: + vars: + ansible_connection: ansible.netcommon.httpapi + ansible_network_os: cisco.dcnm.dcnm + ansible_user: admin + ansible_password: "Admin1@#" + hosts: + ndfc1: + ansible_host: 10.78.210.227