From 8502431fc84346e3f3aa2e8fd557af88bf58b565 Mon Sep 17 00:00:00 2001 From: Shivani-gslab <145646625+Shivani-gslab@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:05:44 +0530 Subject: [PATCH 1/3] Feat(eos_cli_config_gen): Add support for LSP and CSNP timers under router_isis (#4619) --- .../documentation/devices/router-isis-2.md | 7 ++ .../documentation/devices/router-isis-new.md | 10 ++- .../documentation/devices/router-isis.md | 21 +++++- .../intended/configs/router-isis-2.cfg | 1 + .../intended/configs/router-isis-new.cfg | 1 + .../intended/configs/router-isis.cfg | 6 ++ .../inventory/host_vars/router-isis-2.yml | 4 ++ .../inventory/host_vars/router-isis-new.yml | 4 ++ .../inventory/host_vars/router-isis.yml | 12 ++++ .../documentation/devices/DC1-BL1A.md | 6 +- .../documentation/devices/DC1-BL1B.md | 6 +- .../documentation/devices/DC1-LEAF1A.md | 6 +- .../documentation/devices/DC1-LEAF2A.md | 6 +- .../documentation/devices/DC1-LEAF2B.md | 6 +- .../documentation/devices/DC1-SPINE1.md | 6 +- .../documentation/devices/DC1-SPINE2.md | 6 +- .../documentation/devices/DC1-SPINE3.md | 6 +- .../documentation/devices/DC1-SPINE4.md | 6 +- .../documentation/devices/DC1-SVC3A.md | 6 +- .../documentation/devices/DC1-SVC3B.md | 6 +- .../documentation/devices/SITE1-LER1.md | 7 +- .../documentation/devices/SITE1-LER2.md | 7 +- .../documentation/devices/SITE1-LSR1.md | 7 +- .../documentation/devices/SITE1-LSR2.md | 7 +- .../documentation/devices/SITE1-RR1.md | 7 +- .../documentation/devices/SITE2-LER1.md | 7 +- .../documentation/devices/SITE2-LSR1.md | 7 +- .../documentation/devices/SITE2-LSR2.md | 7 +- .../documentation/devices/SITE2-RR1.md | 7 +- .../documentation/devices/SITE3-LER1.md | 7 +- .../docs/tables/router-isis.md | 44 ++++++++++++ .../j2templates/documentation/router-isis.j2 | 37 +++++++++- .../j2templates/eos/router-isis.j2 | 25 +++++++ .../schema/eos_cli_config_gen.schema.yml | 70 +++++++++++++++++++ .../schema_fragments/router_isis.schema.yml | 67 ++++++++++++++++++ 35 files changed, 397 insertions(+), 48 deletions(-) diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis-2.md b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis-2.md index 49dd5658bc0..07132005a4a 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis-2.md +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis-2.md @@ -45,6 +45,12 @@ interface Management1 | -------- | ----- | | Instance | EVPN_UNDERLAY | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| LSP Generation Maximum Interval | 30 seconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | @@ -57,6 +63,7 @@ interface Management1 router isis EVPN_UNDERLAY set-overload-bit set-overload-bit on-startup 55 + timers lsp generation 30 authentication mode sha key-id 4 rx-disabled ! ``` diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis-new.md b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis-new.md index 7d277cfae7e..d0d681caa98 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis-new.md +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis-new.md @@ -194,7 +194,6 @@ interface Vlan4094 | Instance | EVPN_UNDERLAY | | Log Adjacency Changes | False | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 10000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | | SPF Interval | 250 seconds | @@ -205,6 +204,14 @@ interface Vlan4094 | Graceful-restart t2 Level-2 | 20 | | Graceful-restart Restart-hold-time | 10 | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 10000 milliseconds | +| LSP Generation Maximum Interval | 30 seconds | +| LSP Generation Initial Wait-time | 40 milliseconds | + #### ISIS Route Redistribution | Route Type | Route-Map | Include Leaked | @@ -282,6 +289,7 @@ router isis EVPN_UNDERLAY set-overload-bit advertise passive-only spf-interval 250 seconds 10 milliseconds 20 milliseconds + timers lsp generation 30 40 authentication mode shared-secret profile test1 algorithm md5 level-1 authentication mode sha key-id 2 level-2 graceful-restart diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis.md b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis.md index fda57c11f04..1586cb655dd 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis.md +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-isis.md @@ -281,11 +281,24 @@ interface Vlan4094 | Type | level-2 | | Router-ID | 192.168.255.3 | | Log Adjacency Changes | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | False | | SPF Interval | 250 seconds | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | +| CSN Packet Transmission Interval | 10 seconds | +| CSN Packet P2P Links Disabled | True | +| LSP Generation Maximum Interval | 30 seconds | +| LSP Generation Initial Wait-time | 40 milliseconds | +| LSP Generation Wait-time | 50 milliseconds | +| LSP Out-delay | 20 milliseconds | +| LSP Refresh Interval | 56 seconds | +| LSP Minimum Remaining Lifetime | 78 seconds | + #### ISIS Route Redistribution | Route Type | Route-Map | Include Leaked | @@ -352,6 +365,12 @@ router isis EVPN_UNDERLAY set-overload-bit on-startup wait-for-bgp advertise passive-only spf-interval 250 + timers csnp generation interval 10 seconds + timers csnp generation p2p disabled + timers lsp out-delay 20 + timers lsp refresh 56 + timers lsp generation 30 40 50 + timers lsp min-remaining-lifetime 78 authentication mode sha key-id 5 rx-disabled level-1 authentication mode shared-secret profile test2 algorithm md5 rx-disabled level-2 authentication key 0 password diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis-2.cfg b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis-2.cfg index b45e1df447e..08adebcbf19 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis-2.cfg +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis-2.cfg @@ -7,5 +7,6 @@ interface Management1 router isis EVPN_UNDERLAY set-overload-bit set-overload-bit on-startup 55 + timers lsp generation 30 authentication mode sha key-id 4 rx-disabled ! diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis-new.cfg b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis-new.cfg index f406824400d..c4edb58bcc6 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis-new.cfg +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis-new.cfg @@ -71,6 +71,7 @@ router isis EVPN_UNDERLAY set-overload-bit advertise passive-only spf-interval 250 seconds 10 milliseconds 20 milliseconds + timers lsp generation 30 40 authentication mode shared-secret profile test1 algorithm md5 level-1 authentication mode sha key-id 2 level-2 graceful-restart diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis.cfg b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis.cfg index b92ac671374..61067928546 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis.cfg +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-isis.cfg @@ -108,6 +108,12 @@ router isis EVPN_UNDERLAY set-overload-bit on-startup wait-for-bgp advertise passive-only spf-interval 250 + timers csnp generation interval 10 seconds + timers csnp generation p2p disabled + timers lsp out-delay 20 + timers lsp refresh 56 + timers lsp generation 30 40 50 + timers lsp min-remaining-lifetime 78 authentication mode sha key-id 5 rx-disabled level-1 authentication mode shared-secret profile test2 algorithm md5 rx-disabled level-2 authentication key 0 password diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis-2.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis-2.yml index d009055aef4..1c9b45328f6 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis-2.yml +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis-2.yml @@ -4,6 +4,10 @@ router_isis: enabled: true on_startup: delay: 55 + timers: + lsp: + generation: + interval: 30 authentication: both: key_type: 0 diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis-new.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis-new.yml index 5ab2e962757..a289f5205de 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis-new.yml +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis-new.yml @@ -17,6 +17,10 @@ router_isis: timers: local_convergence: protected_prefixes: true + lsp: + generation: + interval: 30 + initial_wait_time: 40 advertise: passive_only: true redistribute_routes: diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis.yml index 0bab20e51f7..22aecdb4b7f 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis.yml +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-isis.yml @@ -14,6 +14,18 @@ router_isis: local_convergence: protected_prefixes: true delay: 15000 + csnp: + generation: + interval: 10 + p2p_disabled: true + lsp: + out_delay: 20 + refresh_interval: 56 + generation: + interval: 30 + initial_wait_time: 40 + wait_time: 50 + min_remaining_lifetime: 78 advertise: passive_only: true redistribute_routes: diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-BL1A.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-BL1A.md index 6feb69861ec..5f39892b7e3 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-BL1A.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-BL1A.md @@ -690,9 +690,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP VLAN Aware Bundles diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-BL1B.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-BL1B.md index 2563c18cfeb..8b1b3e76354 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-BL1B.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-BL1B.md @@ -690,9 +690,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP VLAN Aware Bundles diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF1A.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF1A.md index 31113b01356..98e7a334a77 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF1A.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF1A.md @@ -566,9 +566,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP VLAN Aware Bundles diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF2A.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF2A.md index a3846007d25..df8564f6cdc 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF2A.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF2A.md @@ -920,9 +920,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP VLAN Aware Bundles diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF2B.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF2B.md index a6643c3d023..660f78de080 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF2B.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-LEAF2B.md @@ -920,9 +920,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP VLAN Aware Bundles diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE1.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE1.md index d54b21e2659..e7e5b9ce234 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE1.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE1.md @@ -420,9 +420,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP Device Configuration diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE2.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE2.md index ba041364330..5dbde9614ed 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE2.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE2.md @@ -420,9 +420,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP Device Configuration diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE3.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE3.md index 118ce0a9605..bf9eea2d6bf 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE3.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE3.md @@ -420,9 +420,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP Device Configuration diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE4.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE4.md index ccfeed22327..8a45a95352b 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE4.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SPINE4.md @@ -420,9 +420,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP Device Configuration diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SVC3A.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SVC3A.md index 9bda09b73b7..d168f4869bb 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SVC3A.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SVC3A.md @@ -1040,9 +1040,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP VLAN Aware Bundles diff --git a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SVC3B.md b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SVC3B.md index 1bd39e7e092..98b49bfff54 100644 --- a/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SVC3B.md +++ b/ansible_collections/arista/avd/molecule/eos_config_deploy_cvp/documentation/devices/DC1-SVC3B.md @@ -1013,9 +1013,9 @@ ASN Notation: asplain ##### EVPN Peer Groups -| Peer Group | Activate | Encapsulation | -| ---------- | -------- | ------------- | -| EVPN-OVERLAY-PEERS | True | default | +| Peer Group | Activate | Route-map In | Route-map Out | Encapsulation | +| ---------- | -------- | ------------ | ------------- | ------------- | +| EVPN-OVERLAY-PEERS | True | - | - | default | #### Router BGP VLAN Aware Bundles diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER1.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER1.md index 93707bdabd2..0eb9f15d5f2 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER1.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER1.md @@ -560,10 +560,15 @@ router ospf 19 vrf TENANT_B_INTRA | Router-ID | 100.70.0.5 | | Log Adjacency Changes | True | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER2.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER2.md index 8023886adb2..c6c71d4b749 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER2.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER2.md @@ -525,10 +525,15 @@ ip route vrf MGMT 0.0.0.0/0 192.168.200.5 | Router-ID | 100.70.0.6 | | Log Adjacency Changes | True | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LSR1.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LSR1.md index 00290755453..1657aa260a1 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LSR1.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LSR1.md @@ -333,10 +333,15 @@ ip route vrf MGMT 0.0.0.0/0 192.168.200.5 | Router-ID | 100.70.0.1 | | Log Adjacency Changes | True | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LSR2.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LSR2.md index 8807fca1dc2..1d6a909ec98 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LSR2.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LSR2.md @@ -309,10 +309,15 @@ ip route vrf MGMT 0.0.0.0/0 192.168.200.5 | Router-ID | 100.70.0.2 | | Log Adjacency Changes | True | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-RR1.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-RR1.md index ce63c726cf3..94352209b52 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-RR1.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-RR1.md @@ -288,10 +288,15 @@ ip route vrf MGMT 0.0.0.0/0 192.168.200.5 | Router-ID | 100.70.0.8 | | Log Adjacency Changes | True | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LER1.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LER1.md index fc7322f5ffc..f463525b357 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LER1.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LER1.md @@ -628,10 +628,15 @@ router ospf 99 vrf TENANT_B_WAN | Router-ID | 100.70.0.7 | | Log Adjacency Changes | True | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LSR1.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LSR1.md index 77cbcc0f53e..774da3217fa 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LSR1.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LSR1.md @@ -333,10 +333,15 @@ ip route vrf MGMT 0.0.0.0/0 192.168.200.5 | Router-ID | 100.70.0.3 | | Log Adjacency Changes | True | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LSR2.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LSR2.md index 14c5750d42b..0420c63bbf6 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LSR2.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LSR2.md @@ -396,10 +396,15 @@ ip route vrf MGMT 0.0.0.0/0 192.168.200.5 | Router-ID | 100.70.0.4 | | Log Adjacency Changes | True | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-RR1.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-RR1.md index e2823cd95ad..112ebf34ba2 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-RR1.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-RR1.md @@ -288,10 +288,15 @@ ip route vrf MGMT 0.0.0.0/0 192.168.200.5 | Router-ID | 100.70.0.9 | | Log Adjacency Changes | True | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE3-LER1.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE3-LER1.md index 3d59fc72e88..380f046bbfc 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE3-LER1.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE3-LER1.md @@ -252,10 +252,15 @@ ip route vrf MGMT 0.0.0.0/0 192.168.200.5 | Router-ID | 100.70.0.10 | | Log Adjacency Changes | True | | MPLS LDP Sync Default | True | -| Local Convergence Delay (ms) | 15000 | | Advertise Passive-only | True | | SR MPLS Enabled | True | +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +| Local Convergence Delay | 15000 milliseconds | + #### ISIS Interfaces Summary | Interface | ISIS Instance | ISIS Metric | Interface Mode | diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/router-isis.md b/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/router-isis.md index 02a7c7bba0f..ad6b2ea856e 100644 --- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/router-isis.md +++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/router-isis.md @@ -18,6 +18,18 @@ | [    local_convergence](## "router_isis.timers.local_convergence") | Dictionary | | | | | | [      protected_prefixes](## "router_isis.timers.local_convergence.protected_prefixes") | Boolean | | | | | | [      delay](## "router_isis.timers.local_convergence.delay") | Integer | | `10000` | | Delay in milliseconds. | + | [    lsp](## "router_isis.timers.lsp") | Dictionary | | | | Link State Packet timers. | + | [      generation](## "router_isis.timers.lsp.generation") | Dictionary | | | | | + | [        interval](## "router_isis.timers.lsp.generation.interval") | Integer | Required | | Min: 1
Max: 300 | Maximum interval (in seconds) between generating two LSPs. | + | [        initial_wait_time](## "router_isis.timers.lsp.generation.initial_wait_time") | Integer | | | Min: 1
Max: 300000 | Initial wait time (in milliseconds) before generating LSPs. | + | [        wait_time](## "router_isis.timers.lsp.generation.wait_time") | Integer | | | Min: 1
Max: 300000 | Wait time (in milliseconds) between generating the first and second LSPs. | + | [      out_delay](## "router_isis.timers.lsp.out_delay") | Integer | | | Min: 1
Max: 65000 | Transmit delay (in milliseconds) for link state packets. | + | [      refresh_interval](## "router_isis.timers.lsp.refresh_interval") | Integer | | | Min: 30
Max: 65535 | Interval (in seconds) between two LSP refreshes. | + | [      min_remaining_lifetime](## "router_isis.timers.lsp.min_remaining_lifetime") | Integer | | | Min: 60
Max: 65535 | Minimum remaining lifetime for LSPs (in seconds). | + | [    csnp](## "router_isis.timers.csnp") | Dictionary | | | | CSN Packet timers. | + | [      generation](## "router_isis.timers.csnp.generation") | Dictionary | | | | | + | [        interval](## "router_isis.timers.csnp.generation.interval") | Integer | | | Min: 1
Max: 300 | Transmit frequency (in seconds) for CSN packets. | + | [        p2p_disabled](## "router_isis.timers.csnp.generation.p2p_disabled") | Boolean | | | | Disable periodic CSN packets for P2P links. | | [  set_overload_bit](## "router_isis.set_overload_bit") | Dictionary | | | | | | [    enabled](## "router_isis.set_overload_bit.enabled") | Boolean | | | | | | [    on_startup](## "router_isis.set_overload_bit.on_startup") | Dictionary | | | | | @@ -147,6 +159,38 @@ # Delay in milliseconds. delay: + + # Link State Packet timers. + lsp: + generation: + + # Maximum interval (in seconds) between generating two LSPs. + interval: + + # Initial wait time (in milliseconds) before generating LSPs. + initial_wait_time: + + # Wait time (in milliseconds) between generating the first and second LSPs. + wait_time: + + # Transmit delay (in milliseconds) for link state packets. + out_delay: + + # Interval (in seconds) between two LSP refreshes. + refresh_interval: + + # Minimum remaining lifetime for LSPs (in seconds). + min_remaining_lifetime: + + # CSN Packet timers. + csnp: + generation: + + # Transmit frequency (in seconds) for CSN packets. + interval: + + # Disable periodic CSN packets for P2P links. + p2p_disabled: set_overload_bit: enabled: on_startup: diff --git a/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/router-isis.j2 b/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/router-isis.j2 index 9acdfb4691a..f423620878b 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/router-isis.j2 +++ b/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/router-isis.j2 @@ -30,9 +30,6 @@ {% if router_isis.mpls_ldp_sync_default is arista.avd.defined(true) %} | MPLS LDP Sync Default | {{ router_isis.mpls_ldp_sync_default }} | {% endif %} -{% if router_isis.timers.local_convergence.protected_prefixes is arista.avd.defined(true) %} -| Local Convergence Delay (ms) | {{ router_isis.timers.local_convergence.delay | arista.avd.default(10000) }} | -{% endif %} {% if router_isis.advertise.passive_only is arista.avd.defined(true) %} | Advertise Passive-only | {{ router_isis.advertise.passive_only }} | {% endif %} @@ -62,6 +59,40 @@ | Graceful-restart Restart-hold-time | {{ router_isis.graceful_restart.restart_hold_time }} | {% endif %} {% endif %} +{% if router_isis.timers is arista.avd.defined %} + +#### ISIS Route Timers + +| Settings | Value | +| -------- | ----- | +{% if router_isis.timers.local_convergence.protected_prefixes is arista.avd.defined(true) %} +| Local Convergence Delay | {{ router_isis.timers.local_convergence.delay | arista.avd.default(10000) }} milliseconds | +{% endif %} +{% if router_isis.timers.csnp.generation.interval is arista.avd.defined %} +| CSN Packet Transmission Interval | {{ router_isis.timers.csnp.generation.interval }} seconds | +{% endif %} +{% if router_isis.timers.csnp.generation.p2p_disabled is arista.avd.defined %} +| CSN Packet P2P Links Disabled | {{ router_isis.timers.csnp.generation.p2p_disabled }} | +{% endif %} +{% if router_isis.timers.lsp.generation.interval is arista.avd.defined %} +| LSP Generation Maximum Interval | {{ router_isis.timers.lsp.generation.interval }} seconds | +{% endif %} +{% if router_isis.timers.lsp.generation.initial_wait_time is arista.avd.defined %} +| LSP Generation Initial Wait-time | {{ router_isis.timers.lsp.generation.initial_wait_time }} milliseconds | +{% endif %} +{% if router_isis.timers.lsp.generation.wait_time is arista.avd.defined %} +| LSP Generation Wait-time | {{ router_isis.timers.lsp.generation.wait_time }} milliseconds | +{% endif %} +{% if router_isis.timers.lsp.out_delay is arista.avd.defined %} +| LSP Out-delay | {{ router_isis.timers.lsp.out_delay }} milliseconds | +{% endif %} +{% if router_isis.timers.lsp.refresh_interval is arista.avd.defined %} +| LSP Refresh Interval | {{ router_isis.timers.lsp.refresh_interval }} seconds | +{% endif %} +{% if router_isis.timers.lsp.min_remaining_lifetime is arista.avd.defined %} +| LSP Minimum Remaining Lifetime | {{ router_isis.timers.lsp.min_remaining_lifetime }} seconds | +{% endif %} +{% endif %} {% if router_isis.redistribute_routes is arista.avd.defined %} #### ISIS Route Redistribution diff --git a/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/router-isis.j2 b/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/router-isis.j2 index 36f3d6f7768..46b10c24c47 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/router-isis.j2 +++ b/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/router-isis.j2 @@ -91,6 +91,31 @@ router isis {{ router_isis.instance }} {% endif %} {{ spf_interval_cli }} {% endif %} +{% if router_isis.timers.csnp.generation.interval is arista.avd.defined %} + timers csnp generation interval {{ router_isis.timers.csnp.generation.interval }} seconds +{% endif %} +{% if router_isis.timers.csnp.generation.p2p_disabled is arista.avd.defined(true) %} + timers csnp generation p2p disabled +{% endif %} +{% if router_isis.timers.lsp.out_delay is arista.avd.defined %} + timers lsp out-delay {{ router_isis.timers.lsp.out_delay }} +{% endif %} +{% if router_isis.timers.lsp.refresh_interval is arista.avd.defined %} + timers lsp refresh {{ router_isis.timers.lsp.refresh_interval }} +{% endif %} +{% if router_isis.timers.lsp.generation.interval is arista.avd.defined %} +{% set timers_lsp_generation = "timers lsp generation " ~ router_isis.timers.lsp.generation.interval %} +{% if router_isis.timers.lsp.generation.initial_wait_time is arista.avd.defined %} +{% set timers_lsp_generation = timers_lsp_generation ~ " " ~ router_isis.timers.lsp.generation.initial_wait_time %} +{% if router_isis.timers.lsp.generation.wait_time is arista.avd.defined %} +{% set timers_lsp_generation = timers_lsp_generation ~ " " ~ router_isis.timers.lsp.generation.wait_time %} +{% endif %} +{% endif %} + {{ timers_lsp_generation }} +{% endif %} +{% if router_isis.timers.lsp.min_remaining_lifetime is arista.avd.defined %} + timers lsp min-remaining-lifetime {{ router_isis.timers.lsp.min_remaining_lifetime }} +{% endif %} {% if router_isis.authentication.both.mode is arista.avd.defined and (router_isis.authentication.both.mode in ["md5", "text"] or (router_isis.authentication.both.mode == "sha" and router_isis.authentication.both.sha.key_id is arista.avd.defined) diff --git a/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml b/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml index 888dbcde951..0f4a82a5e4d 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml +++ b/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml @@ -17884,6 +17884,76 @@ keys: - str default: 10000 description: Delay in milliseconds. + lsp: + description: Link State Packet timers. + type: dict + keys: + generation: + type: dict + keys: + interval: + type: int + convert_types: + - str + min: 1 + max: 300 + required: true + description: Maximum interval (in seconds) between generating + two LSPs. + initial_wait_time: + type: int + convert_types: + - str + min: 1 + max: 300000 + description: Initial wait time (in milliseconds) before generating + LSPs. + wait_time: + type: int + convert_types: + - str + min: 1 + max: 300000 + description: Wait time (in milliseconds) between generating the + first and second LSPs. + out_delay: + type: int + convert_types: + - str + min: 1 + max: 65000 + description: Transmit delay (in milliseconds) for link state packets. + refresh_interval: + type: int + convert_types: + - str + min: 30 + max: 65535 + description: Interval (in seconds) between two LSP refreshes. + min_remaining_lifetime: + type: int + convert_types: + - str + min: 60 + max: 65535 + description: Minimum remaining lifetime for LSPs (in seconds). + csnp: + type: dict + description: CSN Packet timers. + keys: + generation: + type: dict + keys: + interval: + type: int + convert_types: + - str + min: 1 + max: 300 + description: Transmit frequency (in seconds) for CSN packets. + p2p_disabled: + type: bool + description: Disable periodic CSN packets for P2P links. set_overload_bit: type: dict keys: diff --git a/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/router_isis.schema.yml b/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/router_isis.schema.yml index 2348a8dd713..b7837d870ca 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/router_isis.schema.yml +++ b/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/router_isis.schema.yml @@ -44,6 +44,73 @@ keys: - str default: 10000 description: Delay in milliseconds. + lsp: + description: Link State Packet timers. + type: dict + keys: + generation: + type: dict + keys: + interval: + type: int + convert_types: + - str + min: 1 + max: 300 + required: true + description: Maximum interval (in seconds) between generating two LSPs. + initial_wait_time: + type: int + convert_types: + - str + min: 1 + max: 300000 + description: Initial wait time (in milliseconds) before generating LSPs. + wait_time: + type: int + convert_types: + - str + min: 1 + max: 300000 + description: Wait time (in milliseconds) between generating the first and second LSPs. + out_delay: + type: int + convert_types: + - str + min: 1 + max: 65000 + description: Transmit delay (in milliseconds) for link state packets. + refresh_interval: + type: int + convert_types: + - str + min: 30 + max: 65535 + description: Interval (in seconds) between two LSP refreshes. + min_remaining_lifetime: + type: int + convert_types: + - str + min: 60 + max: 65535 + description: Minimum remaining lifetime for LSPs (in seconds). + csnp: + type: dict + description: CSN Packet timers. + keys: + generation: + type: dict + keys: + interval: + type: int + convert_types: + - str + min: 1 + max: 300 + description: Transmit frequency (in seconds) for CSN packets. + p2p_disabled: + type: bool + description: Disable periodic CSN packets for P2P links. set_overload_bit: type: dict keys: From f22b00261384404e0d814451df7619473e820310 Mon Sep 17 00:00:00 2001 From: laxmikantchintakindi <159624484+laxmikantchintakindi@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:22:16 +0530 Subject: [PATCH 2/3] Feat(eos_cli_config_gen): Add support for `mac timestamp header` command (#4635) --- .../documentation/devices/ethernet-interfaces.md | 3 +++ .../intended/configs/ethernet-interfaces.cfg | 3 +++ .../inventory/host_vars/ethernet-interfaces.yml | 3 +++ .../docs/tables/ethernet-interfaces.md | 6 ++++++ .../j2templates/eos/ethernet-interfaces.j2 | 3 +++ .../schema/eos_cli_config_gen.schema.yml | 13 +++++++++++++ .../schema_fragments/ethernet_interfaces.schema.yml | 7 +++++++ 7 files changed, 38 insertions(+) diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/ethernet-interfaces.md b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/ethernet-interfaces.md index 63671daa4fe..cdd060acbb7 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/ethernet-interfaces.md +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/ethernet-interfaces.md @@ -1041,6 +1041,7 @@ interface Ethernet63 interface Ethernet64 description DHCP server interface no switchport + mac timestamp replace-fcs ip address 192.168.42.42/24 dhcp server ipv4 dhcp server ipv6 @@ -1049,6 +1050,7 @@ interface Ethernet65 description Multiple VRIDs no shutdown no switchport + mac timestamp header ip address 192.0.2.2/25 ipv6 enable ipv6 address 2001:db8::2/64 @@ -1085,6 +1087,7 @@ interface Ethernet67 description Custom_Transceiver_Frequency no shutdown switchport + mac timestamp before-fcs transceiver frequency 190050.000 ! interface Ethernet67.1 diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/ethernet-interfaces.cfg b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/ethernet-interfaces.cfg index d0fbafa4ba4..4ee49a35864 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/ethernet-interfaces.cfg +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/ethernet-interfaces.cfg @@ -656,6 +656,7 @@ interface Ethernet63 interface Ethernet64 description DHCP server interface no switchport + mac timestamp replace-fcs ip address 192.168.42.42/24 dhcp server ipv4 dhcp server ipv6 @@ -664,6 +665,7 @@ interface Ethernet65 description Multiple VRIDs no shutdown no switchport + mac timestamp header ip address 192.0.2.2/25 ipv6 enable ipv6 address 2001:db8::2/64 @@ -700,6 +702,7 @@ interface Ethernet67 description Custom_Transceiver_Frequency no shutdown switchport + mac timestamp before-fcs transceiver frequency 190050.000 ! interface Ethernet67.1 diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/ethernet-interfaces.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/ethernet-interfaces.yml index 659bd5346da..22f0dd3e185 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/ethernet-interfaces.yml +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/ethernet-interfaces.yml @@ -1146,6 +1146,7 @@ ethernet_interfaces: ip_address: 192.168.42.42/24 dhcp_server_ipv4: true dhcp_server_ipv6: true + mac_timestamp: replace-fcs - name: Ethernet69 switchport: @@ -1163,6 +1164,7 @@ ethernet_interfaces: ipv6_enable: true ipv6_address: 2001:db8::2/64 ipv6_address_link_local: fe80::2/64 + mac_timestamp: header vrrp_ids: - id: 1 priority_level: 105 @@ -1236,6 +1238,7 @@ ethernet_interfaces: shutdown: false transceiver: frequency: 190050 + mac_timestamp: before-fcs - name: Ethernet67.1 description: Test_encapsulation_dot1q diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/ethernet-interfaces.md b/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/ethernet-interfaces.md index 5b5032eb4b3..56ce6b6b34c 100644 --- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/ethernet-interfaces.md +++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/ethernet-interfaces.md @@ -26,6 +26,7 @@ | [    l2_protocol](## "ethernet_interfaces.[].l2_protocol") | Dictionary | | | | | | [      encapsulation_dot1q_vlan](## "ethernet_interfaces.[].l2_protocol.encapsulation_dot1q_vlan") | Integer | | | | Vlan tag to configure on sub-interface. | | [      forwarding_profile](## "ethernet_interfaces.[].l2_protocol.forwarding_profile") | String | | | | L2 protocol forwarding profile. | + | [    mac_timestamp](## "ethernet_interfaces.[].mac_timestamp") | String | | | Valid Values:
- before-fcs
- replace-fcs
- header | header: Insert timestamp in ethernet header. Supported on platforms like 7500E/R and 7280E/R.
before-fcs: Insert timestamp before fcs field. Supported on platforms like 7150.
replace-fcs: Replace fcs field with timestamp. | | [    trunk_groups](## "ethernet_interfaces.[].trunk_groups") deprecated | List, items: String | | | | This key is deprecated. Support will be removed in AVD version 6.0.0. Use switchport.trunk.groups instead. | | [      - <str>](## "ethernet_interfaces.[].trunk_groups.[]") | String | | | | | | [    type](## "ethernet_interfaces.[].type") deprecated | String | | | Valid Values:
- routed
- switched
- l3dot1q
- l2dot1q
- port-channel-member | l3dot1q and l2dot1q are used for sub-interfaces. The parent interface should be defined as routed.
The `type = switched/routed` should not be combined with `switchport`.
This key is deprecated. Support will be removed in AVD version 6.0.0. See [here](https://avd.arista.com/stable/docs/release-notes/5.x.x.html#removal-of-type-key-dependency-for-rendering-ethernetport-channel-interfaces-configuration-and-documentation) for details. | @@ -550,6 +551,11 @@ # L2 protocol forwarding profile. forwarding_profile: + + # header: Insert timestamp in ethernet header. Supported on platforms like 7500E/R and 7280E/R. + # before-fcs: Insert timestamp before fcs field. Supported on platforms like 7150. + # replace-fcs: Replace fcs field with timestamp. + mac_timestamp: # This key is deprecated. # Support will be removed in AVD version 6.0.0. # Use switchport.trunk.groups instead. diff --git a/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/ethernet-interfaces.j2 b/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/ethernet-interfaces.j2 index 57986706be8..4da67bafade 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/ethernet-interfaces.j2 +++ b/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/ethernet-interfaces.j2 @@ -302,6 +302,9 @@ interface {{ ethernet_interface.name }} {% if ethernet_interface.l2_protocol.encapsulation_dot1q_vlan is arista.avd.defined %} l2-protocol encapsulation dot1q vlan {{ ethernet_interface.l2_protocol.encapsulation_dot1q_vlan }} {% endif %} +{% if ethernet_interface.mac_timestamp is arista.avd.defined %} + mac timestamp {{ ethernet_interface.mac_timestamp }} +{% endif %} {% if ethernet_interface.evpn_ethernet_segment is arista.avd.defined %} ! evpn ethernet-segment diff --git a/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml b/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml index 0f4a82a5e4d..be2ada40deb 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml +++ b/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml @@ -2140,6 +2140,19 @@ keys: forwarding_profile: type: str description: L2 protocol forwarding profile. + mac_timestamp: + type: str + valid_values: + - before-fcs + - replace-fcs + - header + description: 'header: Insert timestamp in ethernet header. Supported on + platforms like 7500E/R and 7280E/R. + + before-fcs: Insert timestamp before fcs field. Supported on platforms + like 7150. + + replace-fcs: Replace fcs field with timestamp.' trunk_groups: type: list items: diff --git a/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/ethernet_interfaces.schema.yml b/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/ethernet_interfaces.schema.yml index f51b016ce7a..9602a0314ef 100644 --- a/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/ethernet_interfaces.schema.yml +++ b/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/ethernet_interfaces.schema.yml @@ -116,6 +116,13 @@ keys: forwarding_profile: type: str description: L2 protocol forwarding profile. + mac_timestamp: + type: str + valid_values: ["before-fcs", "replace-fcs", "header"] + description: |- + header: Insert timestamp in ethernet header. Supported on platforms like 7500E/R and 7280E/R. + before-fcs: Insert timestamp before fcs field. Supported on platforms like 7150. + replace-fcs: Replace fcs field with timestamp. trunk_groups: type: list items: From 221cac03607cb2bc219fa692f5b9dca264af0afe Mon Sep 17 00:00:00 2001 From: Claus Holbech Date: Thu, 7 Nov 2024 10:19:04 +0100 Subject: [PATCH 3/3] Test: Include more molecule scenarios in pytest (#4662) --- .gitignore | 1 - .../arista/avd/molecule/README.md | 2 +- .../devices/host4_inline_jinja.md | 53 +++++ .../intended/configs/host4_inline_jinja.cfg | 7 + .../host_vars/host1/tacacs-servers.yml | 3 +- .../host4_inline_jinja/tacacs-servers.yml | 9 + .../eos_cli_config_gen/inventory/hosts.ini | 185 ----------------- .../eos_cli_config_gen/inventory/hosts.yml | 192 ++++++++++++++++++ .../molecule/eos_cli_config_gen/molecule.yml | 2 +- .../inventory/hosts.ini | 3 - .../inventory/hosts.yml | 9 + .../molecule.yml | 2 +- .../inventory/hosts.yml | 3 + .../inventory/hosts.yml | 8 + python-avd/.gitignore | 1 - python-avd/Makefile | 44 ---- python-avd/pyproject.toml | 19 ++ python-avd/scripts/export_test_vars.yml | 81 -------- python-avd/tests/models.py | 101 +++++++++ .../pyavd/cv/client/test_async_decorators.py | 8 +- .../pyavd/eos_cli_config_gen/conftest.py | 86 -------- .../test_get_device_config.py | 23 --- .../eos_cli_config_gen/test_get_device_doc.py | 22 -- .../test_validate_structured_config.py | 42 ---- .../tests/pyavd/eos_designs/__init__.py | 3 - .../tests/pyavd/eos_designs/conftest.py | 93 --------- .../pyavd/eos_designs/test_get_avd_facts.py | 18 -- .../test_get_device_structured_config.py | 19 -- .../pyavd/eos_designs/test_validate_inputs.py | 14 -- .../test_validate_structured_config.py | 42 ---- .../__init__.py | 0 .../pyavd/molecule_scenarios/conftest.py | 37 ++++ .../molecule_scenarios/test_get_avd_facts.py | 35 ++++ .../test_get_device_config.py | 31 ++- .../molecule_scenarios/test_get_device_doc.py | 49 +++++ .../test_get_device_structured_config.py | 36 ++++ .../test_validate_inputs.py | 29 +++ .../test_validate_structured_config.py | 100 +++++++++ python-avd/tox.ini | 21 +- 39 files changed, 726 insertions(+), 707 deletions(-) create mode 100644 ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/host4_inline_jinja.md create mode 100644 ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/host4_inline_jinja.cfg create mode 100644 ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host4_inline_jinja/tacacs-servers.yml delete mode 100644 ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.ini create mode 100644 ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.yml delete mode 100644 ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/inventory/hosts.ini create mode 100644 ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/inventory/hosts.yml delete mode 100644 python-avd/scripts/export_test_vars.yml create mode 100644 python-avd/tests/models.py delete mode 100644 python-avd/tests/pyavd/eos_cli_config_gen/conftest.py delete mode 100644 python-avd/tests/pyavd/eos_cli_config_gen/test_get_device_config.py delete mode 100644 python-avd/tests/pyavd/eos_cli_config_gen/test_get_device_doc.py delete mode 100644 python-avd/tests/pyavd/eos_cli_config_gen/test_validate_structured_config.py delete mode 100644 python-avd/tests/pyavd/eos_designs/__init__.py delete mode 100644 python-avd/tests/pyavd/eos_designs/conftest.py delete mode 100644 python-avd/tests/pyavd/eos_designs/test_get_avd_facts.py delete mode 100644 python-avd/tests/pyavd/eos_designs/test_get_device_structured_config.py delete mode 100644 python-avd/tests/pyavd/eos_designs/test_validate_inputs.py delete mode 100644 python-avd/tests/pyavd/eos_designs/test_validate_structured_config.py rename python-avd/tests/pyavd/{eos_cli_config_gen => molecule_scenarios}/__init__.py (100%) create mode 100644 python-avd/tests/pyavd/molecule_scenarios/conftest.py create mode 100644 python-avd/tests/pyavd/molecule_scenarios/test_get_avd_facts.py rename python-avd/tests/pyavd/{eos_designs => molecule_scenarios}/test_get_device_config.py (50%) create mode 100644 python-avd/tests/pyavd/molecule_scenarios/test_get_device_doc.py create mode 100644 python-avd/tests/pyavd/molecule_scenarios/test_get_device_structured_config.py create mode 100644 python-avd/tests/pyavd/molecule_scenarios/test_validate_inputs.py create mode 100644 python-avd/tests/pyavd/molecule_scenarios/test_validate_structured_config.py diff --git a/.gitignore b/.gitignore index bd5e8f6192b..3303d9a97e8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ __pycache__/ /python-avd/build/ /python-avd/dist/ /python-avd/vendor/ -/python-avd/tests/pyavd/artifacts/ /python-avd/pyavd.egg-info/ /python-avd/.tox/ /python-avd/.coverage diff --git a/ansible_collections/arista/avd/molecule/README.md b/ansible_collections/arista/avd/molecule/README.md index 28fcf066812..ad2353236a8 100644 --- a/ansible_collections/arista/avd/molecule/README.md +++ b/ansible_collections/arista/avd/molecule/README.md @@ -76,7 +76,7 @@ When you update a template in `eos_cli_config_gen`, you should report a test cas 1. Create or update a file related to updated section under `inventory/host_vars` -2. If the section is new, update the inventory file ([hosts.ini](eos_cli_config_gen/inventory/hosts.ini)) to add a new host. The host SHALL be the name of your section and also the `.yml` in your `host_vars` +2. If the section is new, update the inventory file ([hosts.yml](eos_cli_config_gen/inventory/hosts.yml)) to add a new host. The host SHALL be the name of your section and also the `.yml` in your `host_vars` 3. Run molecule scenario to generate artifacts: diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/host4_inline_jinja.md b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/host4_inline_jinja.md new file mode 100644 index 00000000000..73a1ac0d771 --- /dev/null +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/host4_inline_jinja.md @@ -0,0 +1,53 @@ +# host4_inline_jinja + +## Table of Contents + +- [Management](#management) + - [Management Interfaces](#management-interfaces) +- [Authentication](#authentication) + - [TACACS Servers](#tacacs-servers) + +## Management + +### Management Interfaces + +#### Management Interfaces Summary + +##### IPv4 + +| Management Interface | Description | Type | VRF | IP Address | Gateway | +| -------------------- | ----------- | ---- | --- | ---------- | ------- | +| Management1 | OOB_MANAGEMENT | oob | MGMT | 10.73.255.122/24 | 10.73.255.2 | + +##### IPv6 + +| Management Interface | Description | Type | VRF | IPv6 Address | IPv6 Gateway | +| -------------------- | ----------- | ---- | --- | ------------ | ------------ | +| Management1 | OOB_MANAGEMENT | oob | MGMT | - | - | + +#### Management Interfaces Device Configuration + +```eos +! +interface Management1 + description OOB_MANAGEMENT + vrf MGMT + ip address 10.73.255.122/24 +``` + +## Authentication + +### TACACS Servers + +#### TACACS Servers + +| VRF | TACACS Servers | Single-Connection | Timeout | +| --- | -------------- | ----------------- | ------- | +| default | 10.10.10.158 | False | - | + +#### TACACS Servers Device Configuration + +```eos +! +tacacs-server host 10.10.10.158 key 7 +``` diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/host4_inline_jinja.cfg b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/host4_inline_jinja.cfg new file mode 100644 index 00000000000..d789bbd82db --- /dev/null +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/host4_inline_jinja.cfg @@ -0,0 +1,7 @@ +! +tacacs-server host 10.10.10.158 key 7 071B245F5A +! +interface Management1 + description OOB_MANAGEMENT + vrf MGMT + ip address 10.73.255.122/24 diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host1/tacacs-servers.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host1/tacacs-servers.yml index 3aafd2695a9..cfbbee549f5 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host1/tacacs-servers.yml +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host1/tacacs-servers.yml @@ -14,8 +14,7 @@ tacacs_servers: single_connection: false - host: 10.10.10.158 vrf: default - # Testing of play_vars in eos_cli_config_gen - key: "{{ tacacs_key_set_as_play_var }}" + key: 071B245F5A key_type: 7 - host: 10.10.10.159 vrf: default diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host4_inline_jinja/tacacs-servers.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host4_inline_jinja/tacacs-servers.yml new file mode 100644 index 00000000000..502415c86dc --- /dev/null +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/host4_inline_jinja/tacacs-servers.yml @@ -0,0 +1,9 @@ +--- +## Tacacs+ Servers +tacacs_servers: + hosts: + - host: 10.10.10.158 + vrf: default + # Testing of play_vars in eos_cli_config_gen + key: "{{ tacacs_key_set_as_play_var }}" + key_type: 7 diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.ini b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.ini deleted file mode 100644 index 14d027d2504..00000000000 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.ini +++ /dev/null @@ -1,185 +0,0 @@ -[test_hosts] -; ls -l | gawk -F ' ' '{print $9}'| gawk -F '.' '{print $1}' -host1 -host2 -acl -address-locking -base -banners_without_eof -custom-templates -daemon_terminattr -dns-ntp -eos_cli_config_gen_configuration.enable -eos_cli_config_gen_documentation.enable -errdisable -ethernet-interfaces -event-handlers -event-monitor -flow-tracking -flow-tracking-2 -groups -hardware-counter -hardware -hide-passwords -hostname -igmp-snooping -interface-defaults -interface-profiles -ip-access-lists -ip-dhcp-relay -ip-dhcp-snooping -ip-community-lists -ip-extended-community-lists -ip-extended-community-lists-regexp -ip-igmp-snooping-enable -ip-nat -ip-security -ip-routing -ip-routing-fib -ip-radius-source-interface -ip-tacacs-source-interface -ip-client-source-interfaces -ip-virtual-router-mac-address -ipv6-access-lists -ipv6-dhcp-relay -ipv6-neighbors -ipv6-static-routes -l2-protocol-forwarding -lacp -link-tracking-groups -lldp -load-interval -logging-match-list -logging-minimal -logging -mcs-client -loopbacks-interfaces -mac-address-table -maintenance -management-accounts -management-api-http -management-cvx -management-api-models -management-gnmi -management-gnmi-new-flags -management-gnmi-grpc-tunnel -management-console -management-defaults -management-interfaces -management-security -management-ssh -management-ssh-custom-cipher -management-tech-support -mac-access-lists -mac-security-eth-po-entropy -match-lists -mlag-configuration -monitor-layer1 -monitor-connectivity -monitor-connectivity-2 -monitor-sessions -monitor-session-default-encapsulation-gre -monitor-telemetry-influx -monitor-telemetry-postcard-policy -mpls -mpls-2 -mpls-3 -none_configuration -ntp -object-tracking -patch-panel -peer-filters -platform -poe -policy-maps -policy-maps-pbr -port-channel-interfaces -prefix-lists -prompt -prompt-2 -ptp -qos -queue-monitor-length -queue-monitor-length-notifying -queue-monitor-streaming -redundancy -roles -route-maps -router-adaptive-virtual-topology -router-adaptive-virtual-topology-2 -router-bfd-1 -router-bfd-2 -router-bgp-additional-paths -router-bgp-base -router-bgp-evpn -router-bgp-evpn-vpn-import-pruning -router-bgp-evpn-mpls -router-bgp-ipv4-labeled-unicast -router-bgp-link-state -router-bgp-path-selection -router-bgp-rtc -router-bgp-v4-evpn -router-bgp-v4-v6-evpn -router-bgp-v4-v6-sr-te -router-bgp-vpn-ipv4-vpn-ipv6 -router-bgp-vpws -router-bgp-vrf-address-families -router-bgp-vrf-lite -router-general -router-isis -router-isis-new -router-isis-1 -router-isis-2 -router-l2-vpn -router-msdp -router-multicast -router-ospf -router-path-selection -router-pim-sparse-mode -router-service-insertion -router-igmp -router-internet-exit -service-routing-configuration-bgp -service-routing-protocols-model -service-routing-protocols-model-2 -router-general -router-traffic-engineering -router-segment-security -sflow -snmp -snmp-server-traps -spanning-tree -spanning-tree-bpdu -spanning-tree-rstp -spanning-tree-rapid-pvst -switchport-mode -switchport-port-security -stun -sync-e -tcam-profile -static-routes -system -tap-aggregation -terminal -terminattr-cloud -terminattr-extra-flags -terminattr-multi-cluster-certs -terminattr-multi-cluster -terminattr-onprem-certs -terminattr-onprem-token -terminattr-prem -terminattr-prem-no-ingestkey -terminattr-prem-disableaaa -traffic-policies -traffic-policies-2 -traffic-policies-3 -transceiver_qsfp_default_mode_4x10_false -tunnel-interfaces -unsupported-transceiver -vlan-interfaces -virtual-source-nat -vlan-internal-order -vlans -vmtracer-sessions -vxlan-interface -vxlan-interface-false diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.yml new file mode 100644 index 00000000000..18fc19240c4 --- /dev/null +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.yml @@ -0,0 +1,192 @@ +--- +test_hosts: + children: + IGNORE_IN_PYTEST: + hosts: + host4_inline_jinja: + custom-templates: # TODO: Remove inline jinja + tcam-profile: # TODO: Remove inline jinja + hosts: + host1: + host2: + host4_inline_jinja: + acl: + address-locking: + base: + banners_without_eof: + custom-templates: + daemon_terminattr: + dns-ntp: + eos_cli_config_gen_configuration.enable: + eos_cli_config_gen_documentation.enable: + errdisable: + ethernet-interfaces: + event-handlers: + event-monitor: + flow-tracking: + flow-tracking-2: + groups: + hardware-counter: + hardware: + hide-passwords: + hostname: + igmp-snooping: + interface-defaults: + interface-profiles: + ip-access-lists: + ip-dhcp-relay: + ip-dhcp-snooping: + ip-community-lists: + ip-extended-community-lists: + ip-extended-community-lists-regexp: + ip-igmp-snooping-enable: + ip-nat: + ip-security: + ip-routing: + ip-routing-fib: + ip-radius-source-interface: + ip-tacacs-source-interface: + ip-client-source-interfaces: + ip-virtual-router-mac-address: + ipv6-access-lists: + ipv6-dhcp-relay: + ipv6-neighbors: + ipv6-static-routes: + l2-protocol-forwarding: + lacp: + link-tracking-groups: + lldp: + load-interval: + logging-match-list: + logging-minimal: + logging: + mcs-client: + loopbacks-interfaces: + mac-address-table: + maintenance: + management-accounts: + management-api-http: + management-cvx: + management-api-models: + management-gnmi: + management-gnmi-new-flags: + management-gnmi-grpc-tunnel: + management-console: + management-defaults: + management-interfaces: + management-security: + management-ssh: + management-ssh-custom-cipher: + management-tech-support: + mac-access-lists: + mac-security-eth-po-entropy: + match-lists: + mlag-configuration: + monitor-layer1: + monitor-connectivity: + monitor-connectivity-2: + monitor-sessions: + monitor-session-default-encapsulation-gre: + monitor-telemetry-influx: + monitor-telemetry-postcard-policy: + mpls: + mpls-2: + mpls-3: + none_configuration: + ntp: + object-tracking: + patch-panel: + peer-filters: + platform: + poe: + policy-maps: + policy-maps-pbr: + port-channel-interfaces: + prefix-lists: + prompt: + prompt-2: + ptp: + qos: + queue-monitor-length: + queue-monitor-length-notifying: + queue-monitor-streaming: + redundancy: + roles: + route-maps: + router-adaptive-virtual-topology: + router-adaptive-virtual-topology-2: + router-bfd-1: + router-bfd-2: + router-bgp-additional-paths: + router-bgp-base: + router-bgp-evpn: + router-bgp-evpn-vpn-import-pruning: + router-bgp-evpn-mpls: + router-bgp-ipv4-labeled-unicast: + router-bgp-link-state: + router-bgp-path-selection: + router-bgp-rtc: + router-bgp-v4-evpn: + router-bgp-v4-v6-evpn: + router-bgp-v4-v6-sr-te: + router-bgp-vpn-ipv4-vpn-ipv6: + router-bgp-vpws: + router-bgp-vrf-address-families: + router-bgp-vrf-lite: + router-general: + router-isis: + router-isis-new: + router-isis-1: + router-isis-2: + router-l2-vpn: + router-msdp: + router-multicast: + router-ospf: + router-path-selection: + router-pim-sparse-mode: + router-service-insertion: + router-igmp: + router-internet-exit: + service-routing-configuration-bgp: + service-routing-protocols-model: + service-routing-protocols-model-2: + router-traffic-engineering: + router-segment-security: + sflow: + snmp: + snmp-server-traps: + spanning-tree: + spanning-tree-bpdu: + spanning-tree-rstp: + spanning-tree-rapid-pvst: + switchport-mode: + switchport-port-security: + stun: + sync-e: + tcam-profile: + static-routes: + system: + tap-aggregation: + terminal: + terminattr-cloud: + terminattr-extra-flags: + terminattr-multi-cluster-certs: + terminattr-multi-cluster: + terminattr-onprem-certs: + terminattr-onprem-token: + terminattr-prem: + terminattr-prem-no-ingestkey: + terminattr-prem-disableaaa: + traffic-policies: + traffic-policies-2: + traffic-policies-3: + transceiver_qsfp_default_mode_4x10_false: + tunnel-interfaces: + unsupported-transceiver: + vlan-interfaces: + virtual-source-nat: + vlan-internal-order: + vlans: + vmtracer-sessions: + vxlan-interface: + vxlan-interface-false: diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/molecule.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/molecule.yml index 64a2cc5a203..2a54eb2580c 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/molecule.yml +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/molecule.yml @@ -28,7 +28,7 @@ provisioner: inventory: links: - hosts: 'inventory/hosts.ini' + hosts: 'inventory/hosts.yml' host_vars: 'inventory/host_vars/' group_vars: 'inventory/group_vars/' verifier: diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/inventory/hosts.ini b/ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/inventory/hosts.ini deleted file mode 100644 index 232d6940908..00000000000 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/inventory/hosts.ini +++ /dev/null @@ -1,3 +0,0 @@ -[test_hosts] -host1 -host2 diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/inventory/hosts.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/inventory/hosts.yml new file mode 100644 index 00000000000..70f3887fd4f --- /dev/null +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/inventory/hosts.yml @@ -0,0 +1,9 @@ +--- +all: + groups: + IGNORE_IN_PYTEST: + hosts: # TODO: Remove inline jinja + host1: + hosts: + host1: + host2: diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/molecule.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/molecule.yml index c5456334a28..16804cbcd18 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/molecule.yml +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen_deprecated_vars/molecule.yml @@ -27,7 +27,7 @@ provisioner: gathering: explicit inventory: links: - hosts: 'inventory/hosts.ini' + hosts: 'inventory/hosts.yml' host_vars: 'inventory/host_vars/' group_vars: 'inventory/group_vars/' verifier: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/inventory/hosts.yml b/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/inventory/hosts.yml index 6f894ed98ac..f4b55fa1a2d 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/inventory/hosts.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/inventory/hosts.yml @@ -1,6 +1,9 @@ --- all: children: + IGNORE_IN_PYTEST: + hosts: + host1: # TODO: Remove inline jinja EOS_DESIGNS_DEPRECATED_VARS: hosts: host1: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/hosts.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/hosts.yml index ff75d0ed0f6..3e2d17e6fbc 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/hosts.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/hosts.yml @@ -1,6 +1,14 @@ --- all: children: + IGNORE_IN_PYTEST: + children: + CUSTOM_TEMPLATES_TESTS: + CUSTOM_PYTHON_MODULES_TESTS: + DC1_FABRIC: # TODO: Remove inline jinja + hosts: + RD-RT-ADMIN-SUBFIELD-L3LEAF6: # TODO: Remove inline jinja + connected_endpoints: # TODO: Remove inline jinja EOS_DESIGNS_UNIT_TESTS: children: CLEAN_UNIT_TESTS: # Single Devices testing one specific case and only using hostvars diff --git a/python-avd/.gitignore b/python-avd/.gitignore index 84c9a373c18..1effd93b916 100644 --- a/python-avd/.gitignore +++ b/python-avd/.gitignore @@ -3,7 +3,6 @@ __pycache__/ /build/ /dist/ -/tests/artifacts/ /pyavd.egg-info/ /pyavd/eos_cli_config_gen.templates.zip *.prof diff --git a/python-avd/Makefile b/python-avd/Makefile index 61c7a1c95ec..4dce12cdbb6 100644 --- a/python-avd/Makefile +++ b/python-avd/Makefile @@ -1,6 +1,5 @@ CURRENT_DIR = $(shell pwd) ANSIBLE_AVD_DIR ?= .. -TESTS_ARTIFACTS = $(CURRENT_DIR)/tests/pyavd/artifacts SCRIPTS_DIR = $(CURRENT_DIR)/scripts # export PYTHONPATH=$(CURRENT_DIR) # Uncomment to test from source @@ -12,9 +11,6 @@ help: ## Display help message .PHONY: dep dep: compile-templates compile-schemas ## compile Jinja templates & AVD schemas -.PHONY: test-dep -test-dep: copy-test-data ## Copy and Fix Ansible AVD test files - .PHONY: build build: ## Build pyavd package pip3 install build @@ -35,43 +31,3 @@ compile-schemas: .PHONY: compile-templates compile-templates: $(SCRIPTS_DIR)/compile_templates.py - -.PHONY: copy-test-data -copy-test-data: ## Copy inventory files from AVD collection Molecule scenario. - rm -rf $(TESTS_ARTIFACTS) - -## EOS_CLI_CONFIG_GEN - -## Workaround to get the lookup plugin to resolve this TCAM profile before exporting vars - mkdir -p $(SCRIPTS_DIR)/inventory - cp $(ANSIBLE_AVD_DIR)/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/TCAM_TRAFFIC_POLICY.conf $(SCRIPTS_DIR)/inventory/ - -## Excluding prompt because the unsafe marker is lost during the export of hostvars. -## Excluding custom-templates since there is no jinja support in pyavd - ANSIBLE_COLLECTIONS_PATH="..:/usr/share/ansible/collections" ansible-playbook \ - --limit 'all:!prompt:!custom-templates' \ - -i $(ANSIBLE_AVD_DIR)/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.ini \ - $(SCRIPTS_DIR)/export_test_vars.yml \ - -e testdir=eos_cli_config_gen \ - -f 10 - - rm -rf $(SCRIPTS_DIR)/inventory/ - -## Remove excluded tests - rm $(TESTS_ARTIFACTS)/eos_cli_config_gen/configs/prompt.cfg - rm $(TESTS_ARTIFACTS)/eos_cli_config_gen/configs/custom-templates.cfg - -## EOS_DESIGNS - - ANSIBLE_COLLECTIONS_PATH="..:/usr/share/ansible/collections" ansible-playbook \ - -i $(ANSIBLE_AVD_DIR)/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/hosts.yml $(SCRIPTS_DIR)/export_test_vars.yml \ - -e testdir=eos_designs_unit_tests \ - -f 10 - -## Remove tests with custom templates - rm $(TESTS_ARTIFACTS)/eos_designs_unit_tests/vars/CUSTOM-TEMPLATES*.json - rm $(TESTS_ARTIFACTS)/eos_designs_unit_tests/structured_configs/CUSTOM-TEMPLATES*.yml - rm $(TESTS_ARTIFACTS)/eos_designs_unit_tests/configs/CUSTOM-TEMPLATES*.cfg - rm $(TESTS_ARTIFACTS)/eos_designs_unit_tests/vars/CUSTOM-PYTHON_MODULES*.json - rm $(TESTS_ARTIFACTS)/eos_designs_unit_tests/structured_configs/CUSTOM-PYTHON_MODULES*.yml - rm $(TESTS_ARTIFACTS)/eos_designs_unit_tests/configs/CUSTOM-PYTHON_MODULES*.cfg diff --git a/python-avd/pyproject.toml b/python-avd/pyproject.toml index 79f95e185dd..0d5dbe3f6dc 100644 --- a/python-avd/pyproject.toml +++ b/python-avd/pyproject.toml @@ -31,6 +31,19 @@ dependencies = [ homepage = "https://avd.arista.com" repository = "https://github.com/aristanetworks/avd" +[dependency-groups] +pytest = [ + "ansible-core<2.18", + "pytest", + "pytest-asyncio", + "PyYAML>=6.0.0", + "pydantic>=2.3.0", + "referencing>=0.35.0", +] +coverage = [ + "coverage[toml]", +] + [project.optional-dependencies] ansible = [ "ansible-core>=2.15.0,<2.18.0", @@ -140,3 +153,9 @@ exclude_also = [ # Extend the `pyproject.toml` file in the parent directory... # Should not be needed, but the ruff vscode extension does not seem to respect the ruff behavior of ignoring files without tool.ruff extend = "../pyproject.toml" + +[tool.pytest.ini_options] +markers = [ + "molecule_scenarios: Create test case fixtures 'molecule_host' or 'molecule_scenario' for the given molecule scenarios.", +] +asyncio_default_fixture_loop_scope = "function" diff --git a/python-avd/scripts/export_test_vars.yml b/python-avd/scripts/export_test_vars.yml deleted file mode 100644 index b39d13ddfca..00000000000 --- a/python-avd/scripts/export_test_vars.yml +++ /dev/null @@ -1,81 +0,0 @@ ---- - -# Ansible Playbook to export vars from AVD molecule scenarios -# Must load inventory from file in source molecule scenario -# Must give destination path as extra-var like "-e testdir=eos_designs_unit_tests" - -- name: Copy files from molecule scenario - gather_facts: false - connection: local - hosts: all,!prompt ## Excluding prompt because the unsafe marker is lost during the export of hostvars. - vars: - scenario_dir: "{{ inventory_dir }}/.." - pyavd_test_artifacts_dir: "{{ playbook_dir }}/../tests/pyavd/artifacts" - tacacs_key_set_as_play_var: "071B245F5A" ## setting dummy value to avoid error for key set in molecule playbook - string_set_as_play_var: "test of var set under play vars" ## setting dummy value to avoid error for key set in molecule playbook - tasks: - - name: Clear directory - ansible.builtin.file: - path: "{{ pyavd_test_artifacts_dir }}/{{ testdir }}" - state: absent - run_once: true - delegate_to: localhost - - - name: Create directories - ansible.builtin.file: - path: "{{ pyavd_test_artifacts_dir }}/{{ testdir }}/{{ item }}" - state: directory - mode: "0o775" - run_once: true - loop: - - vars - - configs - - structured_configs - - documentation - delegate_to: localhost - - - name: Copy structured_configs - ansible.builtin.shell: - cmd: "cp {{ scenario_dir }}/intended/structured_configs/*.yml {{ pyavd_test_artifacts_dir }}/{{ testdir }}/structured_configs/" - run_once: true - delegate_to: localhost - when: lookup("ansible.builtin.fileglob", scenario_dir ~ "/intended/structured_configs/*.yml", skip=true) - - - name: Copy configs - ansible.builtin.shell: - cmd: "cp {{ scenario_dir }}/intended/configs/*.cfg {{ pyavd_test_artifacts_dir }}/{{ testdir }}/configs/" - run_once: true - delegate_to: localhost - when: lookup("ansible.builtin.fileglob", scenario_dir ~ "/intended/configs/*.cfg", skip=true) - - - name: Copy documentation - ansible.builtin.shell: - cmd: "cp {{ scenario_dir }}/documentation/devices/*.md {{ pyavd_test_artifacts_dir }}/{{ testdir }}/documentation/" - run_once: true - delegate_to: localhost - when: lookup("ansible.builtin.fileglob", scenario_dir ~ "/documentation/devices/*.md", skip=true) - - - name: Set fact with hostvars to force templating - ansible.builtin.set_fact: - templated_hostvars: "{{ hostvars[inventory_hostname] }}" - delegate_to: localhost - vars: - # Variables required to run Molecule test data outside Ansible without getting "undefined" errors. - playbook_dir: "playbook_dir" - switch: - mgmt_interface: Management99 - mgmt_vrf: MGMT - id: 6 - - - name: Export hostvars - ansible.builtin.copy: - content: "{{ templated_hostvars | to_json(sort_keys=false) }}" - dest: "{{ pyavd_test_artifacts_dir }}/{{ testdir }}/vars/{{ inventory_hostname }}.json" - delegate_to: localhost - vars: - # Variables required to run Molecule test data outside Ansible without getting "undefined" errors. - playbook_dir: "playbook_dir" - switch: - mgmt_interface: Management99 - mgmt_vrf: MGMT - id: 6 diff --git a/python-avd/tests/models.py b/python-avd/tests/models.py new file mode 100644 index 00000000000..696c8d063a2 --- /dev/null +++ b/python-avd/tests/models.py @@ -0,0 +1,101 @@ +# Copyright (c) 2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +import json +from copy import deepcopy +from functools import cached_property +from pathlib import Path +from typing import TYPE_CHECKING + +from ansible.inventory.manager import InventoryManager +from ansible.parsing.dataloader import DataLoader +from ansible.vars.manager import VariableManager +from yaml import CSafeLoader, load + +from pyavd import get_avd_facts + +if TYPE_CHECKING: + from ansible.inventory.host import Host as AnsibleHost + +REPO_ROOT = Path(__file__).parents[2] +MOLECULE_PATH = REPO_ROOT / "ansible_collections/arista/avd/molecule" + + +class MoleculeHost: + """Class representing one host defined in a Molecule scenario.""" + + name: str + ansible_host: AnsibleHost + scenario: MoleculeScenario + + def __init__(self, name: str, ansible_host: AnsibleHost, scenario: MoleculeScenario) -> None: + self.name = name + self.ansible_host = ansible_host + self.scenario = scenario + + @cached_property + def structured_config(self) -> dict: + """The intended structured config for the host, as read from the YAML file in the molecule scenario.""" + structured_config_path = self.scenario.path / "intended/structured_configs" / f"{self.name}.yml" + if not structured_config_path.exists(): + return {} + + return load(structured_config_path.read_text(), CSafeLoader) + + @cached_property + def config(self) -> str | None: + """The intended EOS config for the host, as read from the cfg file in the molecule scenario.""" + config_path = self.scenario.path / "intended/configs" / f"{self.name}.cfg" + if not config_path.exists(): + return None + + return config_path.read_text() + + @cached_property + def doc(self) -> str | None: + """The intended MarkDown documentation for the host, as read from the md file in the molecule scenario.""" + doc_path = self.scenario.path / "documentation/devices" / f"{self.name}.md" + if not doc_path.exists(): + return None + + return doc_path.read_text() + + @cached_property + def hostvars(self) -> dict: + """The input vars for the host, as read from the Ansible inventory in the molecule scenario.""" + return json.loads(json.dumps(self.scenario._vars.get_vars(host=self.ansible_host))) + + +class MoleculeScenario: + """Class representing one Molecule scenario.""" + + name: str + path: Path + hosts: list[MoleculeHost] + + def __init__(self, name: str) -> None: + """ + Class representing one Molecule scenario. + + Args: + name: Molecule scenario name + + The Ansible inventory of the Molecule scenario will be parsed and MoleculeHost instances will be inserted into the `hosts` property + for each host found in the inventory. + """ + self.name = name + self.path = MOLECULE_PATH / name + self._inventory = InventoryManager(loader=DataLoader(), sources=[(self.path / "inventory/hosts.yml").as_posix()]) + self._vars = VariableManager(loader=DataLoader(), inventory=self._inventory) + self.hosts = [] + for host in self._inventory.get_hosts(): + if "IGNORE_IN_PYTEST" in [group.name for group in host.groups]: + continue + self.hosts.append(MoleculeHost(name=host.name, ansible_host=host, scenario=self)) + + @cached_property + def avd_facts(self) -> dict: + """The AVD facts calculated from the full Ansible inventory in the molecule scenario.""" + return get_avd_facts({host.name: deepcopy(host.hostvars) for host in self.hosts}) diff --git a/python-avd/tests/pyavd/cv/client/test_async_decorators.py b/python-avd/tests/pyavd/cv/client/test_async_decorators.py index b0326bc82f3..f631c6f4a87 100644 --- a/python-avd/tests/pyavd/cv/client/test_async_decorators.py +++ b/python-avd/tests/pyavd/cv/client/test_async_decorators.py @@ -35,7 +35,7 @@ ] -class TestClass: +class CvClass: _cv_version: CvVersion def __init__(self, version: CvVersion) -> None: @@ -74,20 +74,20 @@ async def msgsize_limited_method(self, field: list, max_accepted_len: int) -> li @pytest.mark.parametrize(("version", "expected_exception"), INVALID_VERSION_TESTS) async def test_invalid_versions(version: str, expected_exception: Exception) -> None: with pytest.raises(type(expected_exception), match=expected_exception.args[0]): - await TestClass(CvVersion(version)).version_limited_method() + await CvClass(CvVersion(version)).version_limited_method() @pytest.mark.asyncio @pytest.mark.parametrize(("version", "expected_response"), VALID_VERSION_TESTS) async def test_valid_versions(version: str, expected_response: tuple[str, str]) -> None: - resp = await TestClass(CvVersion(version)).version_limited_method() + resp = await CvClass(CvVersion(version)).version_limited_method() assert resp == expected_response @pytest.mark.asyncio @pytest.mark.parametrize(("data", "max_len", "expected_response"), MSG_SIZE_HANDLER_TESTS) async def test_msg_size_handler(data: list, max_len: int, expected_response: list[int]) -> None: - resp = await TestClass(CvVersion(CVAAS_VERSION_STRING)).msgsize_limited_method(field=data, max_accepted_len=max_len) + resp = await CvClass(CvVersion(CVAAS_VERSION_STRING)).msgsize_limited_method(field=data, max_accepted_len=max_len) assert resp == expected_response diff --git a/python-avd/tests/pyavd/eos_cli_config_gen/conftest.py b/python-avd/tests/pyavd/eos_cli_config_gen/conftest.py deleted file mode 100644 index 79787a99201..00000000000 --- a/python-avd/tests/pyavd/eos_cli_config_gen/conftest.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from pathlib import Path - -import pytest - -from tests.utils import read_file, read_vars - -VARS_PATH = Path(Path(__file__).parent, "../artifacts/eos_cli_config_gen/vars") -CONFIGS_PATH = Path(Path(__file__).parent, "../artifacts/eos_cli_config_gen/configs") -DOCS_PATH = Path(Path(__file__).parent, "../artifacts/eos_cli_config_gen/documentation") - - -def get_hostnames() -> list: - assert Path(VARS_PATH).is_dir() - - return [Path(device_var_file).name.removesuffix(".yaml").removesuffix(".yml").removesuffix(".json") for device_var_file in Path(VARS_PATH).glob("*")] - - -@pytest.fixture(scope="module") -def all_inputs() -> dict[str, dict]: - """ - Return dict with all inputs. - - { - "hostname1": dict - "hostname2": dict - } - The inputs are read of test artifacts which are hostvars extracted from Ansible molecule scenarios. - """ - assert Path(VARS_PATH).is_dir() - - inputs = {} - for device_var_file in Path(VARS_PATH).glob("*"): - hostname = Path(device_var_file).name.removesuffix(".yaml").removesuffix(".yml").removesuffix(".json") - inputs[hostname] = read_vars(device_var_file) - - return inputs - - -@pytest.fixture(scope="module", params=get_hostnames()) -def hostname(request: pytest.FixtureRequest) -> dict: - return request.param - - -@pytest.fixture(scope="module") -def configs() -> dict: - """ - Return dict with all configs. - - { - "hostname1": str - "hostname2": str - } - The contents are extracted from Ansible molecule scenarios. - """ - assert Path(CONFIGS_PATH).is_dir() - - result = {} - for filename in Path(CONFIGS_PATH).glob("*"): - hostname = Path(filename).name.removesuffix(".cfg") - result[hostname] = read_file(filename) - - return result - - -@pytest.fixture(scope="module") -def device_docs() -> dict: - """ - Return dict with all docs. - - { - "hostname1": str - "hostname2": str - } - The contents are extracted from Ansible molecule scenarios. - """ - assert Path(DOCS_PATH).is_dir() - - result = {} - for filename in Path(DOCS_PATH).glob("*"): - hostname = Path(filename).name.removesuffix(".md") - result[hostname] = read_file(filename) - - return result diff --git a/python-avd/tests/pyavd/eos_cli_config_gen/test_get_device_config.py b/python-avd/tests/pyavd/eos_cli_config_gen/test_get_device_config.py deleted file mode 100644 index 3cdc9636034..00000000000 --- a/python-avd/tests/pyavd/eos_cli_config_gen/test_get_device_config.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from pyavd import get_device_config, validate_structured_config -from pyavd._utils import get - - -def test_get_device_config(hostname: str, all_inputs: dict, configs: dict) -> None: - """Test get_device_config.""" - structured_config: dict = all_inputs[hostname] - if not get(structured_config, "eos_cli_config_gen_configuration.enable", True): - return - - expected_config: str = configs[hostname] - - # run validation on structured_config to ensure it is converted - validate_structured_config(structured_config) - - device_config = get_device_config(structured_config) - - assert isinstance(device_config, str) - - assert device_config == expected_config diff --git a/python-avd/tests/pyavd/eos_cli_config_gen/test_get_device_doc.py b/python-avd/tests/pyavd/eos_cli_config_gen/test_get_device_doc.py deleted file mode 100644 index cec72efd4dd..00000000000 --- a/python-avd/tests/pyavd/eos_cli_config_gen/test_get_device_doc.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from pyavd import get_device_doc, validate_structured_config -from pyavd._utils import get - - -def test_get_device_doc(hostname: str, all_inputs: dict, device_docs: dict) -> None: - """Test get_device_config.""" - structured_config: dict = all_inputs[hostname] - if not get(structured_config, "eos_cli_config_gen_documentation.enable", True): - return - - # run validation on structured_config to ensure it is covered - validate_structured_config(structured_config) - - expected_doc: str = device_docs.get(hostname, "") - - device_doc = get_device_doc(structured_config, add_md_toc=True) - - assert isinstance(device_doc, str) - assert device_doc == expected_doc diff --git a/python-avd/tests/pyavd/eos_cli_config_gen/test_validate_structured_config.py b/python-avd/tests/pyavd/eos_cli_config_gen/test_validate_structured_config.py deleted file mode 100644 index 47499a0a351..00000000000 --- a/python-avd/tests/pyavd/eos_cli_config_gen/test_validate_structured_config.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from pyavd import validate_structured_config -from pyavd._errors import AvdValidationError -from pyavd.avd_schema_tools import AvdSchemaTools - -SCHEMA = AvdSchemaTools(schema_id="eos_cli_config_gen").avdschema._schema - - -def test_validate_structured_config_with_valid_data(hostname: str, all_inputs: dict) -> None: - """Test validate_structured_config.""" - structured_config = all_inputs[hostname] - validation_result = validate_structured_config(structured_config) - assert hostname - assert validation_result.validation_errors == [] - assert hostname - assert validation_result.failed is False - - -def test_validate_structured_config_with_invalid_data(hostname: str, all_inputs: dict) -> None: - """Test validate_structured_config.""" - structured_config: dict = all_inputs[hostname] - - updated = False - # Insert a bad key in a random dict (making sure the dict is covered by the schema) - for key, value in structured_config.items(): - if not isinstance(value, dict) or "structured_config" in key or key not in SCHEMA["keys"]: - continue - value.update({"invalid_key": "some_value"}) - updated = True - break - - # No dict found, so we insert our own instead - if not updated: - structured_config.update({"ethernet_interfaces": [{"name": "dummy", "invalid_key": "some_value"}]}) - - validation_result = validate_structured_config(structured_config) - assert validation_result.failed is True - assert len(validation_result.validation_errors) >= 1 - assert isinstance(validation_result.validation_errors[0], AvdValidationError) - assert "invalid_key" in str(validation_result.validation_errors[0]) diff --git a/python-avd/tests/pyavd/eos_designs/__init__.py b/python-avd/tests/pyavd/eos_designs/__init__.py deleted file mode 100644 index e772bee41fe..00000000000 --- a/python-avd/tests/pyavd/eos_designs/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. diff --git a/python-avd/tests/pyavd/eos_designs/conftest.py b/python-avd/tests/pyavd/eos_designs/conftest.py deleted file mode 100644 index 6afc0fe5b6c..00000000000 --- a/python-avd/tests/pyavd/eos_designs/conftest.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from pathlib import Path - -import pytest - -from pyavd import get_avd_facts -from tests.utils import read_file, read_vars - -VARS_PATH = Path(Path(__file__).parent, "../artifacts/eos_designs_unit_tests/vars") -STRUCTURED_CONFIGS_PATH = Path(Path(__file__).parent, "../artifacts/eos_designs_unit_tests/structured_configs") -CONFIGS_PATH = Path(Path(__file__).parent, "../artifacts/eos_designs_unit_tests/configs") - - -def get_hostnames() -> list: - assert Path(VARS_PATH).is_dir() - - return [Path(device_var_file).name.removesuffix(".yaml").removesuffix(".yml").removesuffix(".json") for device_var_file in Path(VARS_PATH).glob("*")] - - -@pytest.fixture(scope="module") -def all_inputs() -> dict[str, dict]: - """ - Return dict with all inputs. - - { - "hostname1": dict - "hostname2": dict - } - The inputs are read of test artifacts which are hostvars extracted from Ansible molecule scenarios. - """ - assert Path(VARS_PATH).is_dir() - - inputs = {} - for device_var_file in Path(VARS_PATH).glob("*"): - hostname = Path(device_var_file).name.removesuffix(".yaml").removesuffix(".yml").removesuffix(".json") - inputs[hostname] = read_vars(device_var_file) - - return inputs - - -@pytest.fixture(scope="module") -def avd_facts(all_inputs: dict) -> dict: - """Test get_avd_facts.""" - return get_avd_facts(all_inputs) - - -@pytest.fixture(scope="module", params=get_hostnames()) -def hostname(request: pytest.FixtureRequest) -> dict: - return request.param - - -@pytest.fixture(scope="module") -def structured_configs() -> dict: - """ - Return dict with all structured_configs. - - { - "hostname1": dict - "hostname2": dict - } - The contents are extracted from Ansible molecule scenarios. - """ - assert Path(STRUCTURED_CONFIGS_PATH).is_dir() - - result = {} - for filename in Path(STRUCTURED_CONFIGS_PATH).glob("*"): - hostname = Path(filename).name.removesuffix(".yaml").removesuffix(".yml").removesuffix(".json") - result[hostname] = read_vars(filename) - - return result - - -@pytest.fixture(scope="module") -def configs() -> dict: - """ - Return dict with all configs. - - { - "hostname1": str - "hostname2": str - } - The contents are extracted from Ansible molecule scenarios. - """ - assert Path(CONFIGS_PATH).is_dir() - - result = {} - for filename in Path(CONFIGS_PATH).glob("*"): - hostname = Path(filename).name.removesuffix(".cfg") - result[hostname] = read_file(filename) - - return result diff --git a/python-avd/tests/pyavd/eos_designs/test_get_avd_facts.py b/python-avd/tests/pyavd/eos_designs/test_get_avd_facts.py deleted file mode 100644 index faf545c9c20..00000000000 --- a/python-avd/tests/pyavd/eos_designs/test_get_avd_facts.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from pyavd import get_avd_facts - - -def test_get_avd_facts(all_inputs: dict) -> None: - """Test get_avd_facts.""" - avd_facts = get_avd_facts(all_inputs) - - assert isinstance(avd_facts, dict) - assert "avd_switch_facts" in avd_facts - assert isinstance(avd_facts["avd_switch_facts"], dict) - assert len(avd_facts["avd_switch_facts"]) == len(all_inputs) - assert "avd_overlay_peers" in avd_facts - assert isinstance(avd_facts["avd_overlay_peers"], dict) - assert "avd_topology_peers" in avd_facts - assert isinstance(avd_facts["avd_topology_peers"], dict) diff --git a/python-avd/tests/pyavd/eos_designs/test_get_device_structured_config.py b/python-avd/tests/pyavd/eos_designs/test_get_device_structured_config.py deleted file mode 100644 index 7d78598aaf4..00000000000 --- a/python-avd/tests/pyavd/eos_designs/test_get_device_structured_config.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from pyavd import get_device_structured_config, validate_inputs - - -def test_get_device_structured_config(hostname: str, all_inputs: dict, avd_facts: dict, structured_configs: dict) -> None: - """Test get_device_structured_config.""" - inputs = all_inputs[hostname] - - # run validation on inputs to ensure it is converted - validate_inputs(inputs) - - expected_structured_config = structured_configs[hostname] - structured_config = get_device_structured_config(hostname, inputs, avd_facts) - - assert isinstance(structured_config, dict) - assert hostname == structured_config["hostname"] - assert expected_structured_config == structured_config diff --git a/python-avd/tests/pyavd/eos_designs/test_validate_inputs.py b/python-avd/tests/pyavd/eos_designs/test_validate_inputs.py deleted file mode 100644 index 9d9578f2f12..00000000000 --- a/python-avd/tests/pyavd/eos_designs/test_validate_inputs.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from pyavd import validate_inputs - - -def test_validate_inputs_with_valid_inputs(hostname: str, all_inputs: dict) -> None: - """Test validate_inputs.""" - inputs = all_inputs[hostname] - validation_result = validate_inputs(inputs) - assert hostname - assert validation_result.validation_errors == [] - assert hostname - assert validation_result.failed is False diff --git a/python-avd/tests/pyavd/eos_designs/test_validate_structured_config.py b/python-avd/tests/pyavd/eos_designs/test_validate_structured_config.py deleted file mode 100644 index 790e8ab9925..00000000000 --- a/python-avd/tests/pyavd/eos_designs/test_validate_structured_config.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from pyavd import validate_structured_config -from pyavd._errors import AvdValidationError -from pyavd.avd_schema_tools import AvdSchemaTools - -SCHEMA = AvdSchemaTools(schema_id="eos_cli_config_gen").avdschema._schema - - -def test_validate_structured_config_with_valid_data(hostname: str, structured_configs: dict) -> None: - """Test validate_structured_config.""" - structured_config = structured_configs[hostname] - validation_result = validate_structured_config(structured_config) - assert hostname - assert validation_result.validation_errors == [] - assert hostname - assert validation_result.failed is False - - -def test_validate_structured_config_with_invalid_data(hostname: str, structured_configs: dict) -> None: - """Test validate_structured_config.""" - structured_config = structured_configs[hostname] - - updated = False - # Insert a bad key in a random dict (making sure the dict is covered by the schema) - for key, value in structured_config.items(): - if not isinstance(value, dict) or "structured_config" in key or key not in SCHEMA["keys"]: - continue - value.update({"invalid_key": "some_value"}) - updated = True - break - - # No dict found, so we insert our own instead - if not updated: - structured_config.update({"router_bgp": {"invalid_key": "some_value"}}) - - validation_result = validate_structured_config(structured_config) - assert validation_result.failed is True - assert len(validation_result.validation_errors) >= 1 - assert isinstance(validation_result.validation_errors[0], AvdValidationError) - assert "invalid_key" in str(validation_result.validation_errors[0]) diff --git a/python-avd/tests/pyavd/eos_cli_config_gen/__init__.py b/python-avd/tests/pyavd/molecule_scenarios/__init__.py similarity index 100% rename from python-avd/tests/pyavd/eos_cli_config_gen/__init__.py rename to python-avd/tests/pyavd/molecule_scenarios/__init__.py diff --git a/python-avd/tests/pyavd/molecule_scenarios/conftest.py b/python-avd/tests/pyavd/molecule_scenarios/conftest.py new file mode 100644 index 00000000000..895b055ae08 --- /dev/null +++ b/python-avd/tests/pyavd/molecule_scenarios/conftest.py @@ -0,0 +1,37 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from itertools import chain + +import pytest + +from tests.models import MoleculeHost, MoleculeScenario + +MOLECULE_SCENARIOS: dict[str, MoleculeScenario] = {} + + +def get_test_id(host: MoleculeHost) -> str: + return f"{host.scenario.name}__{host.name}" + + +def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: + """ + Generate MoleculeHost or MoleculeScenario instances for the scenarios given with pytest.mark.molecule_scenarios(, ). + + The generated objects are inserted with parametrize to generate a test case for each. + + Reads/updates MOLECULE_SCENARIOS for caching. + """ + molecule_scenario_names = chain.from_iterable(list(mark.args) for mark in metafunc.definition.iter_markers(name="molecule_scenarios")) + molecule_scenarios: list[MoleculeScenario] = [] + for molecule_scenario_name in molecule_scenario_names: + if molecule_scenario_name not in MOLECULE_SCENARIOS: + # Using this method since setdefault triggers init of the class which is expensive. + MOLECULE_SCENARIOS[molecule_scenario_name] = MoleculeScenario(molecule_scenario_name) + molecule_scenarios.append(MOLECULE_SCENARIOS[molecule_scenario_name]) + + if "molecule_host" in metafunc.fixturenames: + metafunc.parametrize("molecule_host", chain.from_iterable(scenario.hosts for scenario in molecule_scenarios), ids=get_test_id) + + elif "molecule_scenario" in metafunc.fixturenames: + metafunc.parametrize("molecule_scenario", molecule_scenarios, ids=lambda scenario: scenario.name) diff --git a/python-avd/tests/pyavd/molecule_scenarios/test_get_avd_facts.py b/python-avd/tests/pyavd/molecule_scenarios/test_get_avd_facts.py new file mode 100644 index 00000000000..55f041c3fd6 --- /dev/null +++ b/python-avd/tests/pyavd/molecule_scenarios/test_get_avd_facts.py @@ -0,0 +1,35 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from copy import deepcopy + +import pytest + +from pyavd import get_avd_facts +from tests.models import MoleculeScenario + + +@pytest.mark.molecule_scenarios( + "eos_designs_unit_tests", + "eos_designs_deprecated_vars", + "eos_designs_l2l2", + "eos_designs-mpls-isis-sr-ldp", + # TODO: "eos_designs-twodc-5stage-clos", # Remove inline jinja + "evpn_underlay_ebgp_overlay_ebgp", + "evpn_underlay_isis_overlay_ibgp", + "evpn_underlay_ospf_overlay_ebgp", + "evpn_underlay_rfc5549_overlay_ebgp", +) +def test_get_avd_facts(molecule_scenario: MoleculeScenario) -> None: + """Test get_avd_facts.""" + molecule_inputs = {host.name: deepcopy(host.hostvars) for host in molecule_scenario.hosts} + avd_facts = get_avd_facts(molecule_inputs) + + assert isinstance(avd_facts, dict) + assert "avd_switch_facts" in avd_facts + assert isinstance(avd_facts["avd_switch_facts"], dict) + assert len(avd_facts["avd_switch_facts"]) == len(molecule_inputs) + assert "avd_overlay_peers" in avd_facts + assert isinstance(avd_facts["avd_overlay_peers"], dict) + assert "avd_topology_peers" in avd_facts + assert isinstance(avd_facts["avd_topology_peers"], dict) diff --git a/python-avd/tests/pyavd/eos_designs/test_get_device_config.py b/python-avd/tests/pyavd/molecule_scenarios/test_get_device_config.py similarity index 50% rename from python-avd/tests/pyavd/eos_designs/test_get_device_config.py rename to python-avd/tests/pyavd/molecule_scenarios/test_get_device_config.py index 5bbc5f18d97..233117ed1c3 100644 --- a/python-avd/tests/pyavd/eos_designs/test_get_device_config.py +++ b/python-avd/tests/pyavd/molecule_scenarios/test_get_device_config.py @@ -1,19 +1,41 @@ # Copyright (c) 2023-2024 Arista Networks, Inc. # Use of this source code is governed by the Apache License 2.0 # that can be found in the LICENSE file. +from copy import deepcopy + +import pytest + from pyavd import get_device_config, validate_structured_config +from pyavd._utils import get +from tests.models import MoleculeHost -def test_get_device_config(hostname: str, all_inputs: dict, structured_configs: dict, configs: dict) -> None: +@pytest.mark.molecule_scenarios( + "eos_designs_unit_tests", + "eos_designs_deprecated_vars", + "eos_cli_config_gen", + "eos_cli_config_gen_deprecated_vars", + "eos_designs_l2l2", + "eos_designs-mpls-isis-sr-ldp", + "eos_designs-twodc-5stage-clos", + "evpn_underlay_ebgp_overlay_ebgp", + "evpn_underlay_isis_overlay_ibgp", + "evpn_underlay_ospf_overlay_ebgp", + "evpn_underlay_rfc5549_overlay_ebgp", +) +def test_get_device_config(molecule_host: MoleculeHost) -> None: """Test get_device_config.""" # Loading inputs first and then updating structured config on top. # This is how Ansible behaves, so we need this to generate the same configs. # The underlying cause is eos_cli_config_gen inputs being set in eos_designs molecule vars, # which are then _not_ included in the structured_config, hence lost unless we include the # inputs as well. - structured_config: dict = all_inputs[hostname] - structured_config.update(structured_configs[hostname]) - expected_config: str = configs[hostname] + structured_config: dict = deepcopy(molecule_host.hostvars) + structured_config.update(deepcopy(molecule_host.structured_config)) + expected_config = molecule_host.config + + if not get(structured_config, "eos_cli_config_gen_configuration.enable", default=True): + return # run validation on structured_config to ensure it is converted validate_structured_config(structured_config) @@ -21,5 +43,4 @@ def test_get_device_config(hostname: str, all_inputs: dict, structured_configs: device_config = get_device_config(structured_config) assert isinstance(device_config, str) - assert f"hostname {hostname}\n" in device_config assert device_config == expected_config diff --git a/python-avd/tests/pyavd/molecule_scenarios/test_get_device_doc.py b/python-avd/tests/pyavd/molecule_scenarios/test_get_device_doc.py new file mode 100644 index 00000000000..8abe7ecaa81 --- /dev/null +++ b/python-avd/tests/pyavd/molecule_scenarios/test_get_device_doc.py @@ -0,0 +1,49 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from copy import deepcopy + +import pytest + +from pyavd import get_device_doc, validate_structured_config +from pyavd._utils import get +from tests.models import MoleculeHost + + +@pytest.mark.molecule_scenarios( + "eos_cli_config_gen", + "eos_cli_config_gen_deprecated_vars", + "eos_designs_l2l2", + "eos_designs-mpls-isis-sr-ldp", + "eos_designs-twodc-5stage-clos", + "evpn_underlay_ebgp_overlay_ebgp", + "evpn_underlay_isis_overlay_ibgp", + "evpn_underlay_ospf_overlay_ebgp", + "evpn_underlay_rfc5549_overlay_ebgp", +) +def test_get_device_doc(molecule_host: MoleculeHost) -> None: + """Test get_device_config.""" + # Loading inputs first and then updating structured config on top. + # This is how Ansible behaves, so we need this to generate the same configs. + # The underlying cause is eos_cli_config_gen inputs being set in eos_designs molecule vars, + # which are then _not_ included in the structured_config, hence lost unless we include the + # inputs as well. + structured_config: dict = deepcopy(molecule_host.hostvars) + structured_config.update(deepcopy(molecule_host.structured_config)) + + if not get(structured_config, "eos_cli_config_gen_documentation.enable", default=True): + return + + # TODO: Deprecated, remove in 6.0.0 + if not get(structured_config, "generate_device_documentation", default=True): + return + + # run validation on structured_config to ensure it is covered + validate_structured_config(structured_config) + + expected_doc = molecule_host.doc + + device_doc = get_device_doc(structured_config, add_md_toc=True) + + assert isinstance(device_doc, str) + assert device_doc == expected_doc diff --git a/python-avd/tests/pyavd/molecule_scenarios/test_get_device_structured_config.py b/python-avd/tests/pyavd/molecule_scenarios/test_get_device_structured_config.py new file mode 100644 index 00000000000..b91f3777bbc --- /dev/null +++ b/python-avd/tests/pyavd/molecule_scenarios/test_get_device_structured_config.py @@ -0,0 +1,36 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from copy import deepcopy + +import pytest + +from pyavd import get_device_structured_config, validate_inputs +from tests.models import MoleculeHost + + +@pytest.mark.molecule_scenarios( + "eos_designs_unit_tests", + "eos_designs_deprecated_vars", + "eos_designs_l2l2", + "eos_designs-mpls-isis-sr-ldp", + # TODO: "eos_designs-twodc-5stage-clos", # Remove inline jinja + # TODO: "evpn_underlay_ebgp_overlay_ebgp", # Remove inline jinja + "evpn_underlay_isis_overlay_ibgp", + "evpn_underlay_ospf_overlay_ebgp", + "evpn_underlay_rfc5549_overlay_ebgp", +) +def test_get_device_structured_config(molecule_host: MoleculeHost) -> None: + """Test get_device_structured_config.""" + inputs = deepcopy(molecule_host.hostvars) + + # run validation on inputs to ensure it is converted + validate_inputs(inputs) + + expected_structured_config = molecule_host.structured_config + avd_facts = molecule_host.scenario.avd_facts + structured_config = get_device_structured_config(molecule_host.name, inputs, avd_facts) + + assert isinstance(structured_config, dict) + assert molecule_host.name == structured_config["hostname"] + assert expected_structured_config == structured_config diff --git a/python-avd/tests/pyavd/molecule_scenarios/test_validate_inputs.py b/python-avd/tests/pyavd/molecule_scenarios/test_validate_inputs.py new file mode 100644 index 00000000000..d725f8efee0 --- /dev/null +++ b/python-avd/tests/pyavd/molecule_scenarios/test_validate_inputs.py @@ -0,0 +1,29 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from copy import deepcopy + +import pytest + +from pyavd import validate_inputs +from tests.models import MoleculeHost + + +# eos_cli_config_gen inputs are validated by `validate_structured_config` in another file. +@pytest.mark.molecule_scenarios( + "eos_designs_unit_tests", + "eos_designs_deprecated_vars", + "eos_designs_l2l2", + "eos_designs-mpls-isis-sr-ldp", + "eos_designs-twodc-5stage-clos", + "evpn_underlay_ebgp_overlay_ebgp", + "evpn_underlay_isis_overlay_ibgp", + "evpn_underlay_ospf_overlay_ebgp", + "evpn_underlay_rfc5549_overlay_ebgp", +) +def test_validate_inputs_with_valid_inputs(molecule_host: MoleculeHost) -> None: + """Test validate_inputs.""" + inputs = deepcopy(molecule_host.hostvars) + validation_result = validate_inputs(inputs) + assert validation_result.validation_errors == [] + assert validation_result.failed is False diff --git a/python-avd/tests/pyavd/molecule_scenarios/test_validate_structured_config.py b/python-avd/tests/pyavd/molecule_scenarios/test_validate_structured_config.py new file mode 100644 index 00000000000..e47b07c50c6 --- /dev/null +++ b/python-avd/tests/pyavd/molecule_scenarios/test_validate_structured_config.py @@ -0,0 +1,100 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from copy import deepcopy + +import pytest + +from pyavd import validate_structured_config +from pyavd._errors import AvdValidationError +from pyavd.avd_schema_tools import AvdSchemaTools +from tests.models import MoleculeHost + +SCHEMA = AvdSchemaTools(schema_id="eos_cli_config_gen").avdschema._schema + + +@pytest.mark.molecule_scenarios( + "eos_designs_unit_tests", + "eos_designs_deprecated_vars", + "eos_designs_l2l2", + "eos_designs-mpls-isis-sr-ldp", + # TODO: "eos_designs-twodc-5stage-clos", # Remove inline jinja + "evpn_underlay_ebgp_overlay_ebgp", + "evpn_underlay_isis_overlay_ibgp", + "evpn_underlay_ospf_overlay_ebgp", + "evpn_underlay_rfc5549_overlay_ebgp", +) +def test_validate_structured_config_with_valid_data(molecule_host: MoleculeHost) -> None: + """Test validate_structured_config.""" + structured_config = deepcopy(molecule_host.structured_config) + validation_result = validate_structured_config(structured_config) + assert validation_result.validation_errors == [] + assert validation_result.failed is False + + +@pytest.mark.molecule_scenarios( + "eos_designs_unit_tests", + "eos_designs_deprecated_vars", +) +def test_validate_structured_config_with_invalid_data(molecule_host: MoleculeHost) -> None: + """Test validate_structured_config.""" + structured_config = deepcopy(molecule_host.structured_config) + + updated = False + # Insert a bad key in a random dict (making sure the dict is covered by the schema) + for key, value in structured_config.items(): + if not isinstance(value, dict) or "structured_config" in key or key not in SCHEMA["keys"]: + continue + value.update({"invalid_key": "some_value"}) + updated = True + break + + # No dict found, so we insert our own instead + if not updated: + structured_config.update({"router_bgp": {"invalid_key": "some_value"}}) + + validation_result = validate_structured_config(structured_config) + assert validation_result.failed is True + assert len(validation_result.validation_errors) >= 1 + assert isinstance(validation_result.validation_errors[0], AvdValidationError) + assert "invalid_key" in str(validation_result.validation_errors[0]) + + +@pytest.mark.molecule_scenarios( + "eos_cli_config_gen", + "eos_cli_config_gen_deprecated_vars", +) +def test_validate_cli_gen_inputs_with_valid_data(molecule_host: MoleculeHost) -> None: + """Test validate_structured_config.""" + inputs = deepcopy(molecule_host.hostvars) + validation_result = validate_structured_config(inputs) + assert validation_result.validation_errors == [] + assert validation_result.failed is False + + +@pytest.mark.molecule_scenarios( + "eos_cli_config_gen", + "eos_cli_config_gen_deprecated_vars", +) +def test_validate_cli_gen_inputs_with_invalid_data(molecule_host: MoleculeHost) -> None: + """Test validate_structured_config.""" + inputs = deepcopy(molecule_host.hostvars) + + updated = False + # Insert a bad key in a random dict (making sure the dict is covered by the schema) + for key, value in inputs.items(): + if not isinstance(value, dict) or key not in SCHEMA["keys"]: + continue + value.update({"invalid_key": "some_value"}) + updated = True + break + + # No dict found, so we insert our own instead + if not updated: + inputs.update({"router_bgp": {"invalid_key": "some_value"}}) + + validation_result = validate_structured_config(inputs) + assert validation_result.failed is True + assert len(validation_result.validation_errors) >= 1 + assert isinstance(validation_result.validation_errors[0], AvdValidationError) + assert "invalid_key" in str(validation_result.validation_errors[0]) diff --git a/python-avd/tox.ini b/python-avd/tox.ini index c42f1372adc..768f410200f 100644 --- a/python-avd/tox.ini +++ b/python-avd/tox.ini @@ -20,37 +20,26 @@ python = description = run the tests with our own runner package = wheel wheel_build_env = .pkg -allowlist_externals = - make -deps = - ansible-core<2.17 +dependency_groups = pytest - PyYAML>=6.0.0 - pydantic>=2.3.0 - referencing>=0.35.0 commands = - make test-dep # posargs allows to run only a specific test using # tox -e -- path/to/my/test::test pytest {posargs} [testenv:coverage] -deps = +dependency_groups = pytest - PyYAML>=6.0.0 - pydantic>=2.3.0 - coverage[toml] - referencing>=0.35.0 + coverage commands = coverage erase - make test-dep # posargs allows to run only a specific test using # tox -e -- path/to/my/test::test coverage run --rcfile=pyproject.toml -m pytest {posargs} [testenv:report] skip_install = true -deps = - coverage[toml] +dependency_groups = + coverage commands = coverage report --rcfile=pyproject.toml