diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ab7dc1dcb71..3891bc25698 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -214,7 +214,7 @@ repos: language: python files: python-avd/pyavd/[a-z_]+/schema pass_filenames: false - additional_dependencies: ['deepmerge>=1.1.0', 'PyYAML>=6.0.0', 'pydantic>=2.3.0', 'jsonschema>=4.10.3', 'referencing>=0.35.0'] + additional_dependencies: ['deepmerge>=1.1.0', 'PyYAML>=6.0.0', 'pydantic>=2.3.0', 'jsonschema>=4.10.3', 'referencing>=0.35.0', 'isort'] - id: templates name: Precompile eos_cli_config_gen Jinja2 diff --git a/pyproject.toml b/pyproject.toml index eb07b591e09..dcbe3fec228 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,13 @@ [tool.black] line-length = 160 -force-exclude = '''python-avd/pyavd/_cv/api/.*''' +force-exclude = ''' +/( +python-avd/pyavd/_cv/api/\.\* +| python-avd/pyavd/_eos_designs/_schema/eos_designs\.py +| python-avd/pyavd/_eos_cli_config_gen/_schema/eos_cli_config_gen\.py +)/ +''' [tool.isort] diff --git a/python-avd/pyavd/_schema/eos_cli_config_gen.py b/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.py similarity index 92% rename from python-avd/pyavd/_schema/eos_cli_config_gen.py rename to python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.py index 07166505ca9..a62ab55bb16 100644 --- a/python-avd/pyavd/_schema/eos_cli_config_gen.py +++ b/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.py @@ -2,25 +2,26 @@ # Use of this source code is governed by the Apache License 2.0 # that can be found in the LICENSE file. -from typing import Literal - +from pyavd._schema.models import AvdBase, AvdDictBaseModel +from pyavd._schema.types import Format, MaxLen, MinLen, Pattern, ValidValues from typing_extensions import Annotated -from .models import AvdDictBaseModel -from .types import ConvertTypes, Format, MaxLen, MinLen, Pattern - -class EosCliConfigGen(object): +class EosCliConfigGen(AvdBase): class AaaAccounting(AvdDictBaseModel): class Exec(AvdDictBaseModel): class Console(AvdDictBaseModel): - type: Literal["none", "start-stop", "stop-only"] | None = None + type: Annotated[str, ValidValues["none", "start-stop", "stop-only"]] | None = None group: str | None = None """Group Name.""" logging: bool | None = None def __init__( - self, type: Literal["none", "start-stop", "stop-only"] | None = None, group: str | None = None, logging: bool | None = None, **kwargs + self, + type: Annotated[str, ValidValues["none", "start-stop", "stop-only"]] | None = None, + group: str | None = None, + logging: bool | None = None, + **kwargs, ): """ Args: @@ -36,13 +37,17 @@ def __init__( return super().__init__(**kwargs) class Default(AvdDictBaseModel): - type: Literal["none", "start-stop", "stop-only"] | None = None + type: Annotated[str, ValidValues["none", "start-stop", "stop-only"]] | None = None group: str | None = None """Group Name.""" logging: bool | None = None def __init__( - self, type: Literal["none", "start-stop", "stop-only"] | None = None, group: str | None = None, logging: bool | None = None, **kwargs + self, + type: Annotated[str, ValidValues["none", "start-stop", "stop-only"]] | None = None, + group: str | None = None, + logging: bool | None = None, + **kwargs, ): """ Args: @@ -74,11 +79,11 @@ def __init__(self, console: Console | None = None, default: Default | None = Non class System(AvdDictBaseModel): class Default(AvdDictBaseModel): - type: Literal["none", "start-stop", "stop-only"] | None = None + type: Annotated[str, ValidValues["none", "start-stop", "stop-only"]] | None = None group: str | None = None """Group Name.""" - def __init__(self, type: Literal["none", "start-stop", "stop-only"] | None = None, group: str | None = None, **kwargs): + def __init__(self, type: Annotated[str, ValidValues["none", "start-stop", "stop-only"]] | None = None, group: str | None = None, **kwargs): """ Args: ----- @@ -104,11 +109,11 @@ def __init__(self, default: Default | None = None, **kwargs): class Dot1x(AvdDictBaseModel): class Default(AvdDictBaseModel): - type: Literal["start-stop", "stop-only"] | None = None + type: Annotated[str, ValidValues["start-stop", "stop-only"]] | None = None group: str | None = None """Group Name.""" - def __init__(self, type: Literal["start-stop", "stop-only"] | None = None, group: str | None = None, **kwargs): + def __init__(self, type: Annotated[str, ValidValues["start-stop", "stop-only"]] | None = None, group: str | None = None, **kwargs): """ Args: ----- @@ -134,17 +139,17 @@ def __init__(self, default: Default | None = None, **kwargs): class Commands(AvdDictBaseModel): class ConsoleItem(AvdDictBaseModel): - commands: Annotated[str, ConvertTypes[int]] | None = None + commands: str | None = None """Privilege level 'all' or 0-15.""" - type: Literal["none", "start-stop", "stop-only"] | None = None + type: Annotated[str, ValidValues["none", "start-stop", "stop-only"]] | None = None group: str | None = None """Group Name.""" logging: bool | None = None def __init__( self, - commands: Annotated[str, ConvertTypes[int]] | None = None, - type: Literal["none", "start-stop", "stop-only"] | None = None, + commands: str | None = None, + type: Annotated[str, ValidValues["none", "start-stop", "stop-only"]] | None = None, group: str | None = None, logging: bool | None = None, **kwargs, @@ -165,17 +170,17 @@ def __init__( return super().__init__(**kwargs) class DefaultItem(AvdDictBaseModel): - commands: Annotated[str, ConvertTypes[int]] | None = None + commands: str | None = None """Privilege level 'all' or 0-15.""" - type: Literal["none", "start-stop", "stop-only"] | None = None + type: Annotated[str, ValidValues["none", "start-stop", "stop-only"]] | None = None group: str | None = None """Group Name.""" logging: bool | None = None def __init__( self, - commands: Annotated[str, ConvertTypes[int]] | None = None, - type: Literal["none", "start-stop", "stop-only"] | None = None, + commands: str | None = None, + type: Annotated[str, ValidValues["none", "start-stop", "stop-only"]] | None = None, group: str | None = None, logging: bool | None = None, **kwargs, @@ -464,7 +469,7 @@ def __init__(self, dot1x_additional_groups: list[str] | None = None, **kwargs): class Commands(AvdDictBaseModel): class PrivilegeItem(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int]] | None = None + level: str | None = None """Privilege level(s) 0-15.""" default: str | None = None """ @@ -476,7 +481,7 @@ class PrivilegeItem(AvdDictBaseModel): group MYGROUP local" """ - def __init__(self, level: Annotated[str, ConvertTypes[int]] | None = None, default: str | None = None, **kwargs): + def __init__(self, level: str | None = None, default: str | None = None, **kwargs): """ Args: ----- @@ -589,10 +594,10 @@ class AaaServerGroupsItem(AvdDictBaseModel): class ServersItem(AvdDictBaseModel): server: str | None = None """Hostname or IP address.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF name.""" - def __init__(self, server: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, server: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -606,11 +611,15 @@ def __init__(self, server: str | None = None, vrf: Annotated[str, ConvertTypes[i name: str | None = None """Group name.""" - type: Literal["tacacs+", "radius", "ldap"] | None = None + type: Annotated[str, ValidValues["tacacs+", "radius", "ldap"]] | None = None servers: list[ServersItem] | None = None def __init__( - self, name: str | None = None, type: Literal["tacacs+", "radius", "ldap"] | None = None, servers: list[ServersItem] | None = None, **kwargs + self, + name: str | None = None, + type: Annotated[str, ValidValues["tacacs+", "radius", "ldap"]] | None = None, + servers: list[ServersItem] | None = None, + **kwargs, ): """ Args: @@ -649,10 +658,10 @@ def __init__(self, sequence: int = None, action: str = None, **kwargs): self.action = action return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """Access-list Name.""" counters_per_entry: bool | None = None - permit_response_traffic: Literal["nat"] | None = None + permit_response_traffic: Annotated[str, ValidValues["nat"]] | None = None """ Permit response traffic automatically based on NAT translations. Minimum EOS version requirement 4.32.2F. @@ -661,9 +670,9 @@ def __init__(self, sequence: int = None, action: str = None, **kwargs): def __init__( self, - name: Annotated[str, ConvertTypes[int]] = None, + name: str = None, counters_per_entry: bool | None = None, - permit_response_traffic: Literal["nat"] | None = None, + permit_response_traffic: Annotated[str, ValidValues["nat"]] | None = None, sequence_numbers: list[SequenceNumbersItem] = None, **kwargs, ): @@ -768,10 +777,10 @@ class AgentsItem(AvdDictBaseModel): class EnvironmentVariablesItem(AvdDictBaseModel): name: str = None """Environment variable name.""" - value: Annotated[str, ConvertTypes[int, bool]] = None + value: str = None """Environment variable value.""" - def __init__(self, name: str = None, value: Annotated[str, ConvertTypes[int, bool]] = None, **kwargs): + def __init__(self, name: str = None, value: str = None, **kwargs): """ Args: ----- @@ -804,7 +813,10 @@ class CategoriesItem(AvdDictBaseModel): class ApplicationsItem(AvdDictBaseModel): name: str | None = None """Application name.""" - service: Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] | None = None + service: ( + Annotated[str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"]] + | None + ) = None """ Service Name. Specific service to target for this application. @@ -817,7 +829,10 @@ def __init__( self, name: str | None = None, service: ( - Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] | None + Annotated[ + str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] + ] + | None ) = None, **kwargs, ): @@ -858,9 +873,9 @@ class FieldSets(AvdDictBaseModel): class L4PortsItem(AvdDictBaseModel): name: str = None """L4 port field-set name.""" - port_values: list[Annotated[str, ConvertTypes[int]]] | None = None + port_values: list[str] | None = None - def __init__(self, name: str = None, port_values: list[Annotated[str, ConvertTypes[int]]] | None = None, **kwargs): + def __init__(self, name: str = None, port_values: list[str] | None = None, **kwargs): """ Args: ----- @@ -914,7 +929,7 @@ class Ipv4ApplicationsItem(AvdDictBaseModel): """Source prefix set name.""" dest_prefix_set_name: str | None = None """Destination prefix set name.""" - protocols: list[str] | None = None + protocols: list[Annotated[str, ValidValues["ahp", "esp", "icmp", "igmp", "ospf", "pim", "rsvp", "tcp", "udp", "vrrp"]]] | None = None """ List of protocols to consider for this application. To use port field-sets (source, destination or both), the list @@ -927,7 +942,7 @@ class Ipv4ApplicationsItem(AvdDictBaseModel): and for `tcp_dest_port_set_name` and `udp_dest_port_set_name` if set in order to generate valid configuration in EOS. """ - protocol_ranges: list[Annotated[str, ConvertTypes[int]]] | None = None + protocol_ranges: list[str] | None = None """ Accept protocol value(s) or range(s). Protocol values can be between 1 and 255. @@ -966,8 +981,8 @@ def __init__( name: str = None, src_prefix_set_name: str | None = None, dest_prefix_set_name: str | None = None, - protocols: list[str] | None = None, - protocol_ranges: list[Annotated[str, ConvertTypes[int]]] | None = None, + protocols: list[Annotated[str, ValidValues["ahp", "esp", "icmp", "igmp", "ospf", "pim", "rsvp", "tcp", "udp", "vrrp"]]] | None = None, + protocol_ranges: list[str] | None = None, udp_src_port_set_name: str | None = None, tcp_src_port_set_name: str | None = None, udp_dest_port_set_name: str | None = None, @@ -1030,7 +1045,7 @@ def __init__( class L4ApplicationsItem(AvdDictBaseModel): name: str = None """Application name.""" - protocols: list[str] | None = None + protocols: list[Annotated[str, ValidValues["ahp", "esp", "icmp", "igmp", "ospf", "pim", "rsvp", "tcp", "udp", "vrrp"]]] | None = None """ List of protocols to consider for this application. To use port field-sets (source, destination or both), the list @@ -1043,7 +1058,7 @@ class L4ApplicationsItem(AvdDictBaseModel): and for `tcp_dest_port_set_name` and `udp_dest_port_set_name` if set in order to generate valid configuration in EOS. """ - protocol_ranges: list[Annotated[str, ConvertTypes[int]]] | None = None + protocol_ranges: list[str] | None = None """ Accept protocol value(s) or range(s). Protocol values can be between 1 and 255. @@ -1080,8 +1095,8 @@ class L4ApplicationsItem(AvdDictBaseModel): def __init__( self, name: str = None, - protocols: list[str] | None = None, - protocol_ranges: list[Annotated[str, ConvertTypes[int]]] | None = None, + protocols: list[Annotated[str, ValidValues["ahp", "esp", "icmp", "igmp", "ospf", "pim", "rsvp", "tcp", "udp", "vrrp"]]] | None = None, + protocol_ranges: list[str] | None = None, udp_src_port_set_name: str | None = None, tcp_src_port_set_name: str | None = None, udp_dest_port_set_name: str | None = None, @@ -1158,7 +1173,10 @@ class ApplicationProfilesItem(AvdDictBaseModel): class ApplicationsItem(AvdDictBaseModel): name: str | None = None """Application Name.""" - service: Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] | None = None + service: ( + Annotated[str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"]] + | None + ) = None """ Service Name. Specific service to target for this application. @@ -1171,7 +1189,10 @@ def __init__( self, name: str | None = None, service: ( - Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] | None + Annotated[ + str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] + ] + | None ) = None, **kwargs, ): @@ -1194,7 +1215,10 @@ def __init__( class CategoriesItem(AvdDictBaseModel): name: str | None = None """Name of a category.""" - service: Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] | None = None + service: ( + Annotated[str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"]] + | None + ) = None """ Service Name. Specific service to target for this application. @@ -1207,7 +1231,10 @@ def __init__( self, name: str | None = None, service: ( - Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] | None + Annotated[ + str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] + ] + | None ) = None, **kwargs, ): @@ -1231,7 +1258,7 @@ def __init__( """Application Profile name.""" applications: list[ApplicationsItem] | None = None """List of applications part of the application profile.""" - application_transports: list[str] | None = None + application_transports: list[Annotated[str, ValidValues["http", "https", "udp", "tcp", "ip", "ip6", "ssl", "rtp", "sctp", "quic"]]] | None = None """List of transport protocols.""" categories: list[CategoriesItem] | None = None """Categories under this application profile.""" @@ -1240,7 +1267,9 @@ def __init__( self, name: str | None = None, applications: list[ApplicationsItem] | None = None, - application_transports: list[str] | None = None, + application_transports: ( + list[Annotated[str, ValidValues["http", "https", "udp", "tcp", "ip", "ip6", "ssl", "rtp", "sctp", "quic"]]] | None + ) = None, categories: list[CategoriesItem] | None = None, **kwargs, ): @@ -1325,16 +1354,16 @@ def __init__(self, timeout_default: int | None = None, **kwargs): class StaticEntriesItem(AvdDictBaseModel): ipv4_address: str = None """ARP entry IPv4 address.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """ARP entry VRF.""" - mac_address: Annotated[str, Pattern["^[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}$"]] = None + mac_address: Annotated[str, Pattern[r"^[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}$"]] = None """ARP entry MAC address.""" def __init__( self, ipv4_address: str = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, - mac_address: Annotated[str, Pattern["^[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}$"]] = None, + vrf: str | None = None, + mac_address: Annotated[str, Pattern[r"^[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}$"]] = None, **kwargs, ): """ @@ -1372,16 +1401,16 @@ def __init__(self, persistent: Persistent | None = None, aging: Aging | None = N class AsPath(AvdDictBaseModel): class AccessListsItem(AvdDictBaseModel): class EntriesItem(AvdDictBaseModel): - type: Literal["permit", "deny"] | None = None + type: Annotated[str, ValidValues["permit", "deny"]] | None = None match: str | None = None """Regex To Match.""" - origin: Literal["any", "egp", "igp", "incomplete"] | None = "any" + origin: Annotated[str, ValidValues["any", "egp", "igp", "incomplete"]] | None = "any" def __init__( self, - type: Literal["permit", "deny"] | None = None, + type: Annotated[str, ValidValues["permit", "deny"]] | None = None, match: str | None = None, - origin: Literal["any", "egp", "igp", "incomplete"] | None = "any", + origin: Annotated[str, ValidValues["any", "egp", "igp", "incomplete"]] | None = "any", **kwargs, ): """ @@ -1413,10 +1442,10 @@ def __init__(self, name: str | None = None, entries: list[EntriesItem] | None = self.entries = entries return super().__init__(**kwargs) - regex_mode: Literal["asn", "string"] | None = None + regex_mode: Annotated[str, ValidValues["asn", "string"]] | None = None access_lists: list[AccessListsItem] | None = None - def __init__(self, regex_mode: Literal["asn", "string"] | None = None, access_lists: list[AccessListsItem] | None = None, **kwargs): + def __init__(self, regex_mode: Annotated[str, ValidValues["asn", "string"]] | None = None, access_lists: list[AccessListsItem] | None = None, **kwargs): """ Args: ----- @@ -1449,17 +1478,12 @@ def __init__(self, login: str | None = None, motd: str | None = None, **kwargs): class BgpGroupsItem(AvdDictBaseModel): name: str = None """Group Name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None neighbors: list[str] | None = None bgp_maintenance_profiles: list[str] | None = None def __init__( - self, - name: str = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, - neighbors: list[str] | None = None, - bgp_maintenance_profiles: list[str] | None = None, - **kwargs, + self, name: str = None, vrf: str | None = None, neighbors: list[str] | None = None, bgp_maintenance_profiles: list[str] | None = None, **kwargs ): """ Args: @@ -1478,11 +1502,11 @@ def __init__( class Boot(AvdDictBaseModel): class Secret(AvdDictBaseModel): - hash_algorithm: Literal["md5", "sha512"] | None = "sha512" + hash_algorithm: Annotated[str, ValidValues["md5", "sha512"]] | None = "sha512" key: str | None = None """Hashed Password.""" - def __init__(self, hash_algorithm: Literal["md5", "sha512"] | None = "sha512", key: str | None = None, **kwargs): + def __init__(self, hash_algorithm: Annotated[str, ValidValues["md5", "sha512"]] | None = "sha512", key: str | None = None, **kwargs): """ Args: ----- @@ -1509,10 +1533,10 @@ def __init__(self, secret: Secret | None = None, **kwargs): class ClassMaps(AvdDictBaseModel): class PbrItem(AvdDictBaseModel): class Ip(AvdDictBaseModel): - access_group: Annotated[str, ConvertTypes[int]] | None = None + access_group: str | None = None """Standard Access-List Name.""" - def __init__(self, access_group: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, access_group: str | None = None, **kwargs): """ Args: ----- @@ -1540,10 +1564,10 @@ def __init__(self, name: str = None, ip: Ip | None = None, **kwargs): class QosItem(AvdDictBaseModel): class Ip(AvdDictBaseModel): - access_group: Annotated[str, ConvertTypes[int]] | None = None + access_group: str | None = None """IPv4 Access-List Name.""" - def __init__(self, access_group: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, access_group: str | None = None, **kwargs): """ Args: ----- @@ -1554,10 +1578,10 @@ def __init__(self, access_group: Annotated[str, ConvertTypes[int]] | None = None return super().__init__(**kwargs) class Ipv6(AvdDictBaseModel): - access_group: Annotated[str, ConvertTypes[int]] | None = None + access_group: str | None = None """IPv6 Access-List Name.""" - def __init__(self, access_group: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, access_group: str | None = None, **kwargs): """ Args: ----- @@ -1569,22 +1593,14 @@ def __init__(self, access_group: Annotated[str, ConvertTypes[int]] | None = None name: str = None """Class-Map Name.""" - vlan: Annotated[str, ConvertTypes[int]] | None = None + vlan: str | None = None """VLAN value(s) or range(s) of VLAN values.""" - cos: Annotated[str, ConvertTypes[int]] | None = None + cos: str | None = None """CoS value(s) or range(s) of CoS values.""" ip: Ip | None = None ipv6: Ipv6 | None = None - def __init__( - self, - name: str = None, - vlan: Annotated[str, ConvertTypes[int]] | None = None, - cos: Annotated[str, ConvertTypes[int]] | None = None, - ip: Ip | None = None, - ipv6: Ipv6 | None = None, - **kwargs, - ): + def __init__(self, name: str = None, vlan: str | None = None, cos: str | None = None, ip: Ip | None = None, ipv6: Ipv6 | None = None, **kwargs): """ Args: ----- @@ -1659,11 +1675,9 @@ class Mcs(AvdDictBaseModel): class Redis(AvdDictBaseModel): password: str | None = None """Hashed password using the password_type.""" - password_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = "7" + password_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = "7" - def __init__( - self, password: str | None = None, password_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = "7", **kwargs - ): + def __init__(self, password: str | None = None, password_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = "7", **kwargs): """ Args: ----- @@ -1692,9 +1706,11 @@ def __init__(self, redis: Redis | None = None, shutdown: bool | None = None, **k class Vxlan(AvdDictBaseModel): shutdown: bool | None = None - vtep_mac_learning: Literal["control-plane", "data-plane"] | None = None + vtep_mac_learning: Annotated[str, ValidValues["control-plane", "data-plane"]] | None = None - def __init__(self, shutdown: bool | None = None, vtep_mac_learning: Literal["control-plane", "data-plane"] | None = None, **kwargs): + def __init__( + self, shutdown: bool | None = None, vtep_mac_learning: Annotated[str, ValidValues["control-plane", "data-plane"]] | None = None, **kwargs + ): """ Args: ----- @@ -1743,7 +1759,7 @@ def __init__(self, shutdown: bool | None = None, peer_hosts: list[str] | None = class DaemonTerminattr(AvdDictBaseModel): class ClustersItem(AvdDictBaseModel): class Cvauth(AvdDictBaseModel): - method: Literal["token", "token-secure", "key", "certs"] | None = None + method: Annotated[str, ValidValues["token", "token-secure", "key", "certs"]] | None = None key: str | None = None token_file: str | None = None """ @@ -1768,7 +1784,7 @@ class Cvauth(AvdDictBaseModel): def __init__( self, - method: Literal["token", "token-secure", "key", "certs"] | None = None, + method: Annotated[str, ValidValues["token", "token-secure", "key", "certs"]] | None = None, key: str | None = None, token_file: str | None = None, cert_file: str | None = None, @@ -1830,7 +1846,7 @@ def __init__( The interface name is case sensitive and has to match the interface name in the running-config, e.g.:Vlan100. """ - cvvrf: Annotated[str, ConvertTypes[int]] | None = None + cvvrf: str | None = None """The VRF to use to connect to CloudVision.""" def __init__( @@ -1842,7 +1858,7 @@ def __init__( cvproxy: str | None = None, cvsourceip: str | None = None, cvsourceintf: str | None = None, - cvvrf: Annotated[str, ConvertTypes[int]] | None = None, + cvvrf: str | None = None, **kwargs, ): """ @@ -1879,7 +1895,7 @@ def __init__( return super().__init__(**kwargs) class Cvauth(AvdDictBaseModel): - method: Literal["token", "token-secure", "key", "certs"] | None = None + method: Annotated[str, ValidValues["token", "token-secure", "key", "certs"]] | None = None key: str | None = None token_file: str | None = None """ @@ -1904,7 +1920,7 @@ class Cvauth(AvdDictBaseModel): def __init__( self, - method: Literal["token", "token-secure", "key", "certs"] | None = None, + method: Annotated[str, ValidValues["token", "token-secure", "key", "certs"]] | None = None, key: str | None = None, token_file: str | None = None, cert_file: str | None = None, @@ -1967,7 +1983,7 @@ def __init__( The interface name is case sensitive and has to match the interface name in the running-config, e.g.:Vlan100. """ - cvvrf: Annotated[str, ConvertTypes[int]] | None = None + cvvrf: str | None = None """The VRF to use to connect to CloudVision.""" cvgnmi: bool | None = None """Stream states from EOS gNMI servers (Openconfig) to CloudVision. Available as of TerminAttr v1.13.1.""" @@ -2031,7 +2047,7 @@ def __init__( cvproxy: str | None = None, cvsourceip: str | None = None, cvsourceintf: str | None = None, - cvvrf: Annotated[str, ConvertTypes[int]] | None = None, + cvvrf: str | None = None, cvgnmi: bool | None = None, disable_aaa: bool | None = None, grpcaddr: str | None = None, @@ -2251,10 +2267,10 @@ def __init__( self.array_ipv4_address = array_ipv4_address return super().__init__(**kwargs) - vendor_id: Annotated[str, ConvertTypes[int]] = None + vendor_id: str = None sub_options: list[SubOptionsItem] | None = None - def __init__(self, vendor_id: Annotated[str, ConvertTypes[int]] = None, sub_options: list[SubOptionsItem] | None = None, **kwargs): + def __init__(self, vendor_id: str = None, sub_options: list[SubOptionsItem] | None = None, **kwargs): """ Args: ----- @@ -2303,7 +2319,7 @@ def __init__(self, days: int = None, hours: int = None, minutes: int = None, **k return super().__init__(**kwargs) subnet: str = None - name: Annotated[str, ConvertTypes[int]] | None = None + name: str | None = None default_gateway: str | None = None dns_servers: list[str] | None = None ranges: list[RangesItem] | None = None @@ -2312,7 +2328,7 @@ def __init__(self, days: int = None, hours: int = None, minutes: int = None, **k def __init__( self, subnet: str = None, - name: Annotated[str, ConvertTypes[int]] | None = None, + name: str | None = None, default_gateway: str | None = None, dns_servers: list[str] | None = None, ranges: list[RangesItem] | None = None, @@ -2339,7 +2355,7 @@ def __init__( return super().__init__(**kwargs) disabled: bool | None = None - vrf: Annotated[str, ConvertTypes[int]] = None + vrf: str = None """VRF in which to configure the DHCP server, use `default` to indicate default VRF.""" dns_domain_name_ipv4: str | None = None dns_domain_name_ipv6: str | None = None @@ -2354,7 +2370,7 @@ def __init__( def __init__( self, disabled: bool | None = None, - vrf: Annotated[str, ConvertTypes[int]] = None, + vrf: str = None, dns_domain_name_ipv4: str | None = None, dns_domain_name_ipv6: str | None = None, dns_servers_ipv4: list[str] | None = None, @@ -2435,10 +2451,13 @@ class CachedResultsTimeout(AvdDictBaseModel): duration in hours <1-864000000> duration in seconds """ - time_duration_unit: Literal["days", "hours", "minutes", "seconds"] = None + time_duration_unit: Annotated[str, ValidValues["days", "hours", "minutes", "seconds"]] = None def __init__( - self, time_duration: int | None = None, time_duration_unit: Literal["days", "hours", "minutes", "seconds"] = None, **kwargs + self, + time_duration: int | None = None, + time_duration_unit: Annotated[str, ValidValues["days", "hours", "minutes", "seconds"]] = None, + **kwargs, ): """ Args: @@ -2508,10 +2527,13 @@ class CachedResultsTimeout(AvdDictBaseModel): duration in hours <1-864000000> duration in seconds """ - time_duration_unit: Literal["days", "hours", "minutes", "seconds"] = None + time_duration_unit: Annotated[str, ValidValues["days", "hours", "minutes", "seconds"]] = None def __init__( - self, time_duration: int | None = None, time_duration_unit: Literal["days", "hours", "minutes", "seconds"] = None, **kwargs + self, + time_duration: int | None = None, + time_duration_unit: Annotated[str, ValidValues["days", "hours", "minutes", "seconds"]] = None, + **kwargs, ): """ Args: @@ -2568,7 +2590,7 @@ def __init__( self.traffic_allow = traffic_allow return super().__init__(**kwargs) - eap_response: Literal["success", "disabled"] | None = None + eap_response: Annotated[str, ValidValues["success", "disabled"]] | None = None """EAP response to send.""" action: Action | None = None """Set action for supplicant when AAA times out.""" @@ -2578,7 +2600,7 @@ def __init__( def __init__( self, - eap_response: Literal["success", "disabled"] | None = None, + eap_response: Annotated[str, ValidValues["success", "disabled"]] | None = None, action: Action | None = None, phone_action: PhoneAction | None = None, recovery_action_reauthenticate: bool | None = None, @@ -2662,7 +2684,7 @@ def __init__( class Supplicant(AvdDictBaseModel): class ProfilesItem(AvdDictBaseModel): name: str = None - eap_method: Literal["fast", "tls"] | None = None + eap_method: Annotated[str, ValidValues["fast", "tls"]] | None = None """ Extensible Authentication Protocol method: - EAP Flexible Authentication via Secure Tunneling. @@ -2671,7 +2693,7 @@ class ProfilesItem(AvdDictBaseModel): """ identity: str | None = None """User identity.""" - passphrase_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = "7" + passphrase_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = "7" passphrase: str | None = None """Extensible Authentication Protocol password.""" ssl_profile: str | None = None @@ -2679,9 +2701,9 @@ class ProfilesItem(AvdDictBaseModel): def __init__( self, name: str = None, - eap_method: Literal["fast", "tls"] | None = None, + eap_method: Annotated[str, ValidValues["fast", "tls"]] | None = None, identity: str | None = None, - passphrase_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = "7", + passphrase_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = "7", passphrase: str | None = None, ssl_profile: str | None = None, **kwargs, @@ -2806,10 +2828,12 @@ class TcpMssCeiling(AvdDictBaseModel): """Segment Size for IPv4.""" ipv6: int | None = None """Segment Size for IPv6.""" - direction: Literal["ingress", "egress"] | None = None + direction: Annotated[str, ValidValues["ingress", "egress"]] | None = None """Optional direction ('ingress', 'egress') for tcp mss ceiling.""" - def __init__(self, ipv4: int | None = None, ipv6: int | None = None, direction: Literal["ingress", "egress"] | None = None, **kwargs): + def __init__( + self, ipv4: int | None = None, ipv6: int | None = None, direction: Annotated[str, ValidValues["ingress", "egress"]] | None = None, **kwargs + ): """ Args: ----- @@ -2823,7 +2847,7 @@ def __init__(self, ipv4: int | None = None, ipv6: int | None = None, direction: self.direction = direction return super().__init__(**kwargs) - name: Literal["Dps1"] = None + name: Annotated[str, ValidValues["Dps1"]] = None """"Dps1" is currently the only supported interface.""" description: str | None = None shutdown: bool | None = None @@ -2838,7 +2862,7 @@ def __init__(self, ipv4: int | None = None, ipv6: int | None = None, direction: def __init__( self, - name: Literal["Dps1"] = None, + name: Annotated[str, ValidValues["Dps1"]] = None, description: str | None = None, shutdown: bool | None = None, mtu: int | None = None, @@ -2911,7 +2935,7 @@ def __init__(self, name: str | None = None, match_map: str | None = None, prefix return super().__init__(**kwargs) class EnablePassword(AvdDictBaseModel): - hash_algorithm: Literal["md5", "sha512"] | None = None + hash_algorithm: Annotated[str, ValidValues["md5", "sha512"]] | None = None key: str | None = None """ Must be the hash of the password using the specified algorithm. @@ -2919,7 +2943,7 @@ class EnablePassword(AvdDictBaseModel): generate the hash on an EOS device. """ - def __init__(self, hash_algorithm: Literal["md5", "sha512"] | None = None, key: str | None = None, **kwargs): + def __init__(self, hash_algorithm: Annotated[str, ValidValues["md5", "sha512"]] | None = None, key: str | None = None, **kwargs): """ Args: ----- @@ -2974,9 +2998,31 @@ def __init__(self, hide_passwords: bool | None = True, **kwargs): class Errdisable(AvdDictBaseModel): class Detect(AvdDictBaseModel): - causes: list[str] | None = None + causes: ( + list[ + Annotated[ + str, + ValidValues["acl", "arp-inspection", "dot1x", "link-change", "tapagg", "xcvr-misconfigured", "xcvr-overheat", "xcvr-power-unsupported"], + ] + ] + | None + ) = None - def __init__(self, causes: list[str] | None = None, **kwargs): + def __init__( + self, + causes: ( + list[ + Annotated[ + str, + ValidValues[ + "acl", "arp-inspection", "dot1x", "link-change", "tapagg", "xcvr-misconfigured", "xcvr-overheat", "xcvr-power-unsupported" + ], + ] + ] + | None + ) = None, + **kwargs, + ): """ Args: ----- @@ -2987,11 +3033,68 @@ def __init__(self, causes: list[str] | None = None, **kwargs): return super().__init__(**kwargs) class Recovery(AvdDictBaseModel): - causes: list[str] | None = None + causes: ( + list[ + Annotated[ + str, + ValidValues[ + "arp-inspection", + "bpduguard", + "dot1x", + "hitless-reload-down", + "lacp-rate-limit", + "link-flap", + "no-internal-vlan", + "portchannelguard", + "portsec", + "speed-misconfigured", + "tap-port-init", + "tapagg", + "uplink-failure-detection", + "xcvr-misconfigured", + "xcvr-overheat", + "xcvr-power-unsupported", + "xcvr-unsupported", + ], + ] + ] + | None + ) = None interval: int | None = 300 """Interval in seconds.""" - def __init__(self, causes: list[str] | None = None, interval: int | None = 300, **kwargs): + def __init__( + self, + causes: ( + list[ + Annotated[ + str, + ValidValues[ + "arp-inspection", + "bpduguard", + "dot1x", + "hitless-reload-down", + "lacp-rate-limit", + "link-flap", + "no-internal-vlan", + "portchannelguard", + "portsec", + "speed-misconfigured", + "tap-port-init", + "tapagg", + "uplink-failure-detection", + "xcvr-misconfigured", + "xcvr-overheat", + "xcvr-power-unsupported", + "xcvr-unsupported", + ], + ] + ] + | None + ) = None, + interval: int | None = 300, + **kwargs, + ): """ Args: ----- @@ -3020,10 +3123,15 @@ def __init__(self, detect: Detect | None = None, recovery: Recovery | None = Non class EthernetInterfacesItem(AvdDictBaseModel): class Phone(AvdDictBaseModel): - trunk: Literal["tagged", "tagged phone", "untagged", "untagged phone"] | None = None + trunk: Annotated[str, ValidValues["tagged", "tagged phone", "untagged", "untagged phone"]] | None = None vlan: int | None = None - def __init__(self, trunk: Literal["tagged", "tagged phone", "untagged", "untagged phone"] | None = None, vlan: int | None = None, **kwargs): + def __init__( + self, + trunk: Annotated[str, ValidValues["tagged", "tagged phone", "untagged", "untagged phone"]] | None = None, + vlan: int | None = None, + **kwargs, + ): """ Args: ----- @@ -3072,9 +3180,9 @@ def __init__(self, ipv4: bool | None = None, ipv6: bool | None = None, **kwargs) return super().__init__(**kwargs) class Flowcontrol(AvdDictBaseModel): - received: Literal["desired", "on", "off"] | None = None + received: Annotated[str, ValidValues["desired", "on", "off"]] | None = None - def __init__(self, received: Literal["desired", "on", "off"] | None = None, **kwargs): + def __init__(self, received: Annotated[str, ValidValues["desired", "on", "off"]] | None = None, **kwargs): """ Args: ----- @@ -3124,9 +3232,9 @@ def __init__(self, enabled: bool | None = True, fire_code: bool | None = None, r class LinkTrackingGroupsItem(AvdDictBaseModel): name: str = None """Group name.""" - direction: Literal["upstream", "downstream"] | None = None + direction: Annotated[str, ValidValues["upstream", "downstream"]] | None = None - def __init__(self, name: str = None, direction: Literal["upstream", "downstream"] | None = None, **kwargs): + def __init__(self, name: str = None, direction: Annotated[str, ValidValues["upstream", "downstream"]] | None = None, **kwargs): """ Args: ----- @@ -3140,7 +3248,7 @@ def __init__(self, name: str = None, direction: Literal["upstream", "downstream" class EvpnEthernetSegment(AvdDictBaseModel): class DesignatedForwarderElection(AvdDictBaseModel): - algorithm: Literal["modulus", "preference"] | None = None + algorithm: Annotated[str, ValidValues["modulus", "preference"]] | None = None preference_value: int | None = None """Preference_value is only used when "algorithm" is "preference".""" dont_preempt: bool | None = None @@ -3151,7 +3259,7 @@ class DesignatedForwarderElection(AvdDictBaseModel): def __init__( self, - algorithm: Literal["modulus", "preference"] | None = None, + algorithm: Annotated[str, ValidValues["modulus", "preference"]] | None = None, preference_value: int | None = None, dont_preempt: bool | None = None, hold_time: int | None = None, @@ -3196,7 +3304,7 @@ def __init__(self, shared_index: int | None = None, tunnel_flood_filter_time: in identifier: str | None = None """EVPN Ethernet Segment Identifier (Type 1 format).""" - redundancy: Literal["all-active", "single-active"] | None = None + redundancy: Annotated[str, ValidValues["all-active", "single-active"]] | None = None designated_forwarder_election: DesignatedForwarderElection | None = None mpls: Mpls | None = None route_target: str | None = None @@ -3205,7 +3313,7 @@ def __init__(self, shared_index: int | None = None, tunnel_flood_filter_time: in def __init__( self, identifier: str | None = None, - redundancy: Literal["all-active", "single-active"] | None = None, + redundancy: Annotated[str, ValidValues["all-active", "single-active"]] | None = None, designated_forwarder_election: DesignatedForwarderElection | None = None, mpls: Mpls | None = None, route_target: str | None = None, @@ -3325,10 +3433,10 @@ class IpHelpersItem(AvdDictBaseModel): ip_helper: str = None source_interface: str | None = None """Source interface name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF name.""" - def __init__(self, ip_helper: str = None, source_interface: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, ip_helper: str = None, source_interface: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -3370,7 +3478,7 @@ class StaticItem(AvdDictBaseModel): access_list: str | None = None """'access_list' and 'group' are mutual exclusive.""" comment: str | None = None - direction: Literal["egress", "ingress"] | None = None + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None """ Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware platform. EOS might @@ -3383,7 +3491,7 @@ class StaticItem(AvdDictBaseModel): original_port: int | None = None """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" priority: int | None = None - protocol: Literal["udp", "tcp"] | None = None + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None translated_ip: str = None """IPv4 address.""" translated_port: int | None = None @@ -3393,12 +3501,12 @@ def __init__( self, access_list: str | None = None, comment: str | None = None, - direction: Literal["egress", "ingress"] | None = None, + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None, group: int | None = None, original_ip: str | None = None, original_port: int | None = None, priority: int | None = None, - protocol: Literal["udp", "tcp"] | None = None, + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None, translated_ip: str = None, translated_port: int | None = None, **kwargs, @@ -3452,7 +3560,7 @@ class Source(AvdDictBaseModel): class DynamicItem(AvdDictBaseModel): access_list: str = None comment: str | None = None - nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] = None + nat_type: Annotated[str, ValidValues["overload", "pool", "pool-address-only", "pool-full-cone"]] = None pool_name: str | None = None """ required if 'nat_type' is pool, pool-address-only or pool-full-cone. @@ -3464,7 +3572,7 @@ def __init__( self, access_list: str = None, comment: str | None = None, - nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] = None, + nat_type: Annotated[str, ValidValues["overload", "pool", "pool-address-only", "pool-full-cone"]] = None, pool_name: str | None = None, priority: int | None = None, **kwargs, @@ -3492,7 +3600,7 @@ class StaticItem(AvdDictBaseModel): access_list: str | None = None """'access_list' and 'group' are mutual exclusive.""" comment: str | None = None - direction: Literal["egress", "ingress"] | None = None + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None """ Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware platform. EOS might @@ -3505,7 +3613,7 @@ class StaticItem(AvdDictBaseModel): original_port: int | None = None """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" priority: int | None = None - protocol: Literal["udp", "tcp"] | None = None + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None translated_ip: str = None """IPv4 address.""" translated_port: int | None = None @@ -3515,12 +3623,12 @@ def __init__( self, access_list: str | None = None, comment: str | None = None, - direction: Literal["egress", "ingress"] | None = None, + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None, group: int | None = None, original_ip: str | None = None, original_port: int | None = None, priority: int | None = None, - protocol: Literal["udp", "tcp"] | None = None, + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None, translated_ip: str = None, translated_port: int | None = None, **kwargs, @@ -3591,17 +3699,17 @@ def __init__(self, service_profile: str | None = None, destination: Destination class Ipv6NdPrefixesItem(AvdDictBaseModel): ipv6_prefix: str = None - valid_lifetime: Annotated[str, ConvertTypes[int]] | None = None + valid_lifetime: str | None = None """Infinite or lifetime in seconds.""" - preferred_lifetime: Annotated[str, ConvertTypes[int]] | None = None + preferred_lifetime: str | None = None """Infinite or lifetime in seconds.""" no_autoconfig_flag: bool | None = None def __init__( self, ipv6_prefix: str = None, - valid_lifetime: Annotated[str, ConvertTypes[int]] | None = None, - preferred_lifetime: Annotated[str, ConvertTypes[int]] | None = None, + valid_lifetime: str | None = None, + preferred_lifetime: str | None = None, no_autoconfig_flag: bool | None = None, **kwargs, ): @@ -3623,7 +3731,7 @@ def __init__( class Ipv6DhcpRelayDestinationsItem(AvdDictBaseModel): address: str = None """DHCP server's IPv6 address.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None local_interface: str | None = None """Local interface to communicate with DHCP server - mutually exclusive to source_address.""" source_address: str | None = None @@ -3634,7 +3742,7 @@ class Ipv6DhcpRelayDestinationsItem(AvdDictBaseModel): def __init__( self, address: str = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, local_interface: str | None = None, source_address: str | None = None, link_address: str | None = None, @@ -3738,12 +3846,16 @@ def __init__(self, ipv4: Ipv4 | None = None, ipv6: Ipv6 | None = None, **kwargs) class OspfMessageDigestKeysItem(AvdDictBaseModel): id: int = None - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = None + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = None key: str | None = None """Encrypted password - only type 7 supported.""" def __init__( - self, id: int = None, hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = None, key: str | None = None, **kwargs + self, + id: int = None, + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = None, + key: str | None = None, + **kwargs, ): """ Args: @@ -3761,12 +3873,12 @@ def __init__( class Pim(AvdDictBaseModel): class Ipv4(AvdDictBaseModel): class Hello(AvdDictBaseModel): - count: Annotated[str, ConvertTypes[int, float]] | None = None + count: str | None = None """Number of missed hellos after which the neighbor expires. Range <1.5-65535>.""" interval: int | None = None """PIM hello interval in seconds.""" - def __init__(self, count: Annotated[str, ConvertTypes[int, float]] | None = None, interval: int | None = None, **kwargs): + def __init__(self, count: str | None = None, interval: int | None = None, **kwargs): """ Args: ----- @@ -3844,13 +3956,13 @@ def __init__(self, profile: str | None = None, **kwargs): class TcpMssCeiling(AvdDictBaseModel): ipv4_segment_size: int | None = None ipv6_segment_size: int | None = None - direction: Literal["egress", "ingress"] | None = None + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None def __init__( self, ipv4_segment_size: int | None = None, ipv6_segment_size: int | None = None, - direction: Literal["egress", "ingress"] | None = None, + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None, **kwargs, ): """ @@ -3868,9 +3980,9 @@ def __init__( class ChannelGroup(AvdDictBaseModel): id: int | None = None - mode: Literal["on", "active", "passive"] | None = None + mode: Annotated[str, ValidValues["on", "active", "passive"]] | None = None - def __init__(self, id: int | None = None, mode: Literal["on", "active", "passive"] | None = None, **kwargs): + def __init__(self, id: int | None = None, mode: Annotated[str, ValidValues["on", "active", "passive"]] | None = None, **kwargs): """ Args: ----- @@ -3884,10 +3996,10 @@ def __init__(self, id: int | None = None, mode: Literal["on", "active", "passive class Poe(AvdDictBaseModel): class Reboot(AvdDictBaseModel): - action: Literal["maintain", "power-off"] | None = None + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None """PoE action for interface.""" - def __init__(self, action: Literal["maintain", "power-off"] | None = None, **kwargs): + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, **kwargs): """ Args: ----- @@ -3898,12 +4010,12 @@ def __init__(self, action: Literal["maintain", "power-off"] | None = None, **kwa return super().__init__(**kwargs) class LinkDown(AvdDictBaseModel): - action: Literal["maintain", "power-off"] | None = None + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None """PoE action for interface.""" power_off_delay: int | None = None """Number of seconds to delay shutting the power off after a link down event occurs. Default value is 5 seconds in EOS.""" - def __init__(self, action: Literal["maintain", "power-off"] | None = None, power_off_delay: int | None = None, **kwargs): + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, power_off_delay: int | None = None, **kwargs): """ Args: ----- @@ -3916,10 +4028,10 @@ def __init__(self, action: Literal["maintain", "power-off"] | None = None, power return super().__init__(**kwargs) class Shutdown(AvdDictBaseModel): - action: Literal["maintain", "power-off"] | None = None + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None """PoE action for interface.""" - def __init__(self, action: Literal["maintain", "power-off"] | None = None, **kwargs): + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, **kwargs): """ Args: ----- @@ -3931,13 +4043,11 @@ def __init__(self, action: Literal["maintain", "power-off"] | None = None, **kwa class Limit(AvdDictBaseModel): field_class: int | None = None - watts: Annotated[str, ConvertTypes[int, float]] | None = None + watts: str | None = None fixed: bool | None = None """Set to ignore hardware classification.""" - def __init__( - self, field_class: int | None = None, watts: Annotated[str, ConvertTypes[int, float]] | None = None, fixed: bool | None = None, **kwargs - ): + def __init__(self, field_class: int | None = None, watts: str | None = None, fixed: bool | None = None, **kwargs): """ Args: ----- @@ -3953,7 +4063,7 @@ def __init__( disabled: bool | None = False """Disable PoE on a POE capable port. PoE is enabled on all ports that support it by default in EOS.""" - priority: Literal["critical", "high", "medium", "low"] | None = None + priority: Annotated[str, ValidValues["critical", "high", "medium", "low"]] | None = None """Prioritize a port's power in the event that one of the switch's power supplies loses power.""" reboot: Reboot | None = None """Set the PoE power behavior for a PoE port when the system is rebooted.""" @@ -3977,7 +4087,7 @@ def __init__( def __init__( self, disabled: bool | None = False, - priority: Literal["critical", "high", "medium", "low"] | None = None, + priority: Annotated[str, ValidValues["critical", "high", "medium", "low"]] | None = None, reboot: Reboot | None = None, link_down: LinkDown | None = None, shutdown: Shutdown | None = None, @@ -4046,23 +4156,23 @@ def __init__(self, interval: int | None = None, **kwargs): enable: bool | None = None announce: Announce | None = None delay_req: int | None = None - delay_mechanism: Literal["e2e", "p2p"] | None = None + delay_mechanism: Annotated[str, ValidValues["e2e", "p2p"]] | None = None sync_message: SyncMessage | None = None - role: Literal["master", "dynamic"] | None = None - vlan: Annotated[str, ConvertTypes[int]] | None = None + role: Annotated[str, ValidValues["master", "dynamic"]] | None = None + vlan: str | None = None """VLAN can be 'all' or list of vlans as string.""" - transport: Literal["ipv4", "ipv6", "layer2"] | None = None + transport: Annotated[str, ValidValues["ipv4", "ipv6", "layer2"]] | None = None def __init__( self, enable: bool | None = None, announce: Announce | None = None, delay_req: int | None = None, - delay_mechanism: Literal["e2e", "p2p"] | None = None, + delay_mechanism: Annotated[str, ValidValues["e2e", "p2p"]] | None = None, sync_message: SyncMessage | None = None, - role: Literal["master", "dynamic"] | None = None, - vlan: Annotated[str, ConvertTypes[int]] | None = None, - transport: Literal["ipv4", "ipv6", "layer2"] | None = None, + role: Annotated[str, ValidValues["master", "dynamic"]] | None = None, + vlan: str | None = None, + transport: Annotated[str, ValidValues["ipv4", "ipv6", "layer2"]] | None = None, **kwargs, ): """ @@ -4090,12 +4200,12 @@ def __init__( class StormControl(AvdDictBaseModel): class All(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional field and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -4108,12 +4218,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class Broadcast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional field and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -4126,12 +4236,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class Multicast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional field and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -4144,12 +4254,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class UnknownUnicast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional field and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -4253,17 +4363,17 @@ def __init__(self, transmit: bool | None = None, receive: bool | None = None, zt return super().__init__(**kwargs) class VlanTranslationsItem(AvdDictBaseModel): - field_from: Annotated[str, ConvertTypes[int]] | None = None + field_from: str | None = None """List of vlans as string (only one vlan if direction is "both").""" to: int | None = None """VLAN ID.""" - direction: Literal["in", "out", "both"] | None = "both" + direction: Annotated[str, ValidValues["in", "out", "both"]] | None = "both" def __init__( self, - field_from: Annotated[str, ConvertTypes[int]] | None = None, + field_from: str | None = None, to: int | None = None, - direction: Literal["in", "out", "both"] | None = "both", + direction: Annotated[str, ValidValues["in", "out", "both"]] | None = "both", **kwargs, ): """ @@ -4281,9 +4391,9 @@ def __init__( class Dot1x(AvdDictBaseModel): class Pae(AvdDictBaseModel): - mode: Literal["authenticator"] | None = None + mode: Annotated[str, ValidValues["authenticator"]] | None = None - def __init__(self, mode: Literal["authenticator"] | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["authenticator"]] | None = None, **kwargs): """ Args: ----- @@ -4294,10 +4404,10 @@ def __init__(self, mode: Literal["authenticator"] | None = None, **kwargs): return super().__init__(**kwargs) class AuthenticationFailure(AvdDictBaseModel): - action: Literal["allow", "drop"] | None = None + action: Annotated[str, ValidValues["allow", "drop"]] | None = None allow_vlan: int | None = None - def __init__(self, action: Literal["allow", "drop"] | None = None, allow_vlan: int | None = None, **kwargs): + def __init__(self, action: Annotated[str, ValidValues["allow", "drop"]] | None = None, allow_vlan: int | None = None, **kwargs): """ Args: ----- @@ -4310,10 +4420,12 @@ def __init__(self, action: Literal["allow", "drop"] | None = None, allow_vlan: i return super().__init__(**kwargs) class HostMode(AvdDictBaseModel): - mode: Literal["multi-host", "single-host"] | None = None + mode: Annotated[str, ValidValues["multi-host", "single-host"]] | None = None multi_host_authenticated: bool | None = None - def __init__(self, mode: Literal["multi-host", "single-host"] | None = None, multi_host_authenticated: bool | None = None, **kwargs): + def __init__( + self, mode: Annotated[str, ValidValues["multi-host", "single-host"]] | None = None, multi_host_authenticated: bool | None = None, **kwargs + ): """ Args: ----- @@ -4347,7 +4459,7 @@ def __init__(self, enabled: bool | None = None, always: bool | None = None, host class Timeout(AvdDictBaseModel): idle_host: int | None = None quiet_period: int | None = None - reauth_period: Annotated[str, ConvertTypes[int]] | None = None + reauth_period: str | None = None """Value can be 60-4294967295 or 'server'.""" reauth_timeout_ignore: bool | None = None tx_period: int | None = None @@ -4356,7 +4468,7 @@ def __init__( self, idle_host: int | None = None, quiet_period: int | None = None, - reauth_period: Annotated[str, ConvertTypes[int]] | None = None, + reauth_period: str | None = None, reauth_timeout_ignore: bool | None = None, tx_period: int | None = None, **kwargs, @@ -4426,7 +4538,7 @@ def __init__(self, disabled: bool | None = None, authentication_failure_fallback self.authentication_failure_fallback_mba = authentication_failure_fallback_mba return super().__init__(**kwargs) - port_control: Literal["auto", "force-authorized", "force-unauthorized"] | None = None + port_control: Annotated[str, ValidValues["auto", "force-authorized", "force-unauthorized"]] | None = None port_control_force_authorized_phone: bool | None = None reauthentication: bool | None = None pae: Pae | None = None @@ -4440,7 +4552,7 @@ def __init__(self, disabled: bool | None = None, authentication_failure_fallback def __init__( self, - port_control: Literal["auto", "force-authorized", "force-unauthorized"] | None = None, + port_control: Annotated[str, ValidValues["auto", "force-authorized", "force-unauthorized"]] | None = None, port_control_force_authorized_phone: bool | None = None, reauthentication: bool | None = None, pae: Pae | None = None, @@ -4512,13 +4624,15 @@ def __init__(self, rate: str | None = None, **kwargs): return super().__init__(**kwargs) class Qos(AvdDictBaseModel): - trust: Literal["dscp", "cos", "disabled"] | None = None + trust: Annotated[str, ValidValues["dscp", "cos", "disabled"]] | None = None dscp: int | None = None """DSCP value.""" cos: int | None = None """COS value.""" - def __init__(self, trust: Literal["dscp", "cos", "disabled"] | None = None, dscp: int | None = None, cos: int | None = None, **kwargs): + def __init__( + self, trust: Annotated[str, ValidValues["dscp", "cos", "disabled"]] | None = None, dscp: int | None = None, cos: int | None = None, **kwargs + ): """ Args: ----- @@ -4665,10 +4779,10 @@ def __init__(self, ip: bool | None = None, ldp: Ldp | None = None, **kwargs): return super().__init__(**kwargs) class LacpTimer(AvdDictBaseModel): - mode: Literal["fast", "normal"] | None = None + mode: Annotated[str, ValidValues["fast", "normal"]] | None = None multiplier: int | None = None - def __init__(self, mode: Literal["fast", "normal"] | None = None, multiplier: int | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["fast", "normal"]] | None = None, multiplier: int | None = None, **kwargs): """ Args: ----- @@ -4695,18 +4809,14 @@ def __init__(self, override: str | None = None, **kwargs): self.override = override return super().__init__(**kwargs) - frequency: Annotated[str, ConvertTypes[int, float]] | None = None + frequency: str | None = None """Transceiver Laser Frequency in GHz (min 190000, max 200000).""" - frequency_unit: Literal["ghz"] | None = None + frequency_unit: Annotated[str, ValidValues["ghz"]] | None = None """Unit of Transceiver Laser Frequency.""" media: Media | None = None def __init__( - self, - frequency: Annotated[str, ConvertTypes[int, float]] | None = None, - frequency_unit: Literal["ghz"] | None = None, - media: Media | None = None, - **kwargs, + self, frequency: str | None = None, frequency_unit: Annotated[str, ValidValues["ghz"]] | None = None, media: Media | None = None, **kwargs ): """ Args: @@ -4886,7 +4996,7 @@ class UcTxQueuesItem(AvdDictBaseModel): class RandomDetect(AvdDictBaseModel): class Ecn(AvdDictBaseModel): class Threshold(AvdDictBaseModel): - units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] = None + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "milliseconds"]] = None """Indicate the units to be used for the threshold values.""" min: int = None """Set the random-detect ECN minimum-threshold.""" @@ -4899,7 +5009,7 @@ class Threshold(AvdDictBaseModel): def __init__( self, - units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] = None, + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "milliseconds"]] = None, min: int = None, max: int = None, max_probability: int | None = None, @@ -4972,7 +5082,7 @@ class TxQueuesItem(AvdDictBaseModel): class RandomDetect(AvdDictBaseModel): class Ecn(AvdDictBaseModel): class Threshold(AvdDictBaseModel): - units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] = None + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "milliseconds"]] = None """Indicate the units to be used for the threshold values.""" min: int | None = None """Set the random-detect ECN minimum-threshold.""" @@ -4985,7 +5095,7 @@ class Threshold(AvdDictBaseModel): def __init__( self, - units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] = None, + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "milliseconds"]] = None, min: int | None = None, max: int = None, max_probability: int = None, @@ -5154,9 +5264,9 @@ def __init__(self, name: str = None, decrement: int | None = None, shutdown: boo class Ipv4(AvdDictBaseModel): address: str = None """Virtual IPv4 address.""" - version: Literal[2, 3] | None = None + version: int | None = None - def __init__(self, address: str = None, version: Literal[2, 3] | None = None, **kwargs): + def __init__(self, address: str = None, version: int | None = None, **kwargs): """ Args: ----- @@ -5249,12 +5359,12 @@ def __init__(self, disabled: bool | None = None, limit: int | None = None, **kwa return super().__init__(**kwargs) class Violation(AvdDictBaseModel): - mode: Literal["shutdown", "protect"] | None = None + mode: Annotated[str, ValidValues["shutdown", "protect"]] | None = None """Configure port security mode.""" protect_log: bool | None = None """Log new addresses seen after limit is reached in protect mode.""" - def __init__(self, mode: Literal["shutdown", "protect"] | None = None, protect_log: bool | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["shutdown", "protect"]] | None = None, protect_log: bool | None = None, **kwargs): """ Args: ----- @@ -5267,7 +5377,7 @@ def __init__(self, mode: Literal["shutdown", "protect"] | None = None, protect_l return super().__init__(**kwargs) class VlansItem(AvdDictBaseModel): - range: Annotated[str, ConvertTypes[int]] = None + range: str = None """ VLAN ID or range(s) of VLAN IDs, <1-4094>. Example: @@ -5277,7 +5387,7 @@ class VlansItem(AvdDictBaseModel): """ mac_address_maximum: int | None = None - def __init__(self, range: Annotated[str, ConvertTypes[int]] = None, mac_address_maximum: int | None = None, **kwargs): + def __init__(self, range: str = None, mac_address_maximum: int | None = None, **kwargs): """ Args: ----- @@ -5353,7 +5463,7 @@ def __init__(self, port_security: PortSecurity | None = None, **kwargs): """"l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI.""" l2_mru: int | None = None """"l2_mru" should only be defined for platforms supporting the "l2 mru" CLI.""" - vlans: Annotated[str, ConvertTypes[int]] | None = None + vlans: str | None = None """ List of switchport vlans as string. For a trunk port this would be a range like "1-200,300". @@ -5363,11 +5473,11 @@ def __init__(self, port_security: PortSecurity | None = None, **kwargs): native_vlan: int | None = None native_vlan_tag: bool | None = None """If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence.""" - mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None = None + mode: Annotated[str, ValidValues["access", "dot1q-tunnel", "trunk", "trunk phone"]] | None = None phone: Phone | None = None l2_protocol: L2Protocol | None = None trunk_groups: list[str] | None = None - type: Literal["routed", "switched", "l3dot1q", "l2dot1q", "port-channel-member"] | None = None + type: Annotated[str, ValidValues["routed", "switched", "l3dot1q", "l2dot1q", "port-channel-member"]] | None = None """ l3dot1q and l2dot1q are used for sub-interfaces. The parent interface should be defined as routed. Interface will not be @@ -5376,7 +5486,7 @@ def __init__(self, port_security: PortSecurity | None = None, **kwargs): snmp_trap_link_change: bool | None = None address_locking: AddressLocking | None = None flowcontrol: Flowcontrol | None = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF name.""" flow_tracker: FlowTracker | None = None error_correction_encoding: ErrorCorrectionEncoding | None = None @@ -5389,7 +5499,7 @@ def __init__(self, port_security: PortSecurity | None = None, **kwargs): ip_address: str | None = None """IPv4 address/mask or "dhcp".""" ip_address_secondaries: list[str] | None = None - ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None = None + ip_verify_unicast_source_reachable_via: Annotated[str, ValidValues["any", "rx"]] | None = None dhcp_client_accept_default_route: bool | None = None """Install default-route obtained via DHCP.""" dhcp_server_ipv4: bool | None = None @@ -5421,9 +5531,9 @@ def __init__(self, port_security: PortSecurity | None = None, **kwargs): multicast: Multicast | None = None """Boundaries can be either 1 ACL or a list of multicast IP address_range(s)/prefix but not combination of both.""" ospf_network_point_to_point: bool | None = None - ospf_area: Annotated[str, ConvertTypes[int]] | None = None + ospf_area: str | None = None ospf_cost: int | None = None - ospf_authentication: Literal["none", "simple", "message-digest"] | None = None + ospf_authentication: Annotated[str, ValidValues["none", "simple", "message-digest"]] | None = None ospf_authentication_key: str | None = None """Encrypted password - only type 7 supported.""" ospf_message_digest_keys: list[OspfMessageDigestKeysItem] | None = None @@ -5443,9 +5553,9 @@ def __init__(self, port_security: PortSecurity | None = None, **kwargs): isis_passive: bool | None = None isis_metric: int | None = None isis_network_point_to_point: bool | None = None - isis_circuit_type: Literal["level-1-2", "level-1", "level-2"] | None = None + isis_circuit_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = None isis_hello_padding: bool | None = None - isis_authentication_mode: Literal["text", "md5"] | None = None + isis_authentication_mode: Annotated[str, ValidValues["text", "md5"]] | None = None isis_authentication_key: str | None = None """Type-7 encrypted password.""" poe: Poe | None = None @@ -5456,7 +5566,7 @@ def __init__(self, port_security: PortSecurity | None = None, **kwargs): logging: Logging | None = None lldp: Lldp | None = None trunk_private_vlan_secondary: bool | None = None - pvlan_mapping: Annotated[str, ConvertTypes[int]] | None = None + pvlan_mapping: str | None = None """List of vlans as string.""" vlan_translations: list[VlanTranslationsItem] | None = None dot1x: Dot1x | None = None @@ -5464,10 +5574,10 @@ def __init__(self, port_security: PortSecurity | None = None, **kwargs): """QOS profile.""" shape: Shape | None = None qos: Qos | None = None - spanning_tree_bpdufilter: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None - spanning_tree_bpduguard: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None - spanning_tree_guard: Literal["loop", "root", "disabled"] | None = None - spanning_tree_portfast: Literal["edge", "network"] | None = None + spanning_tree_bpdufilter: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None + spanning_tree_bpduguard: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None + spanning_tree_guard: Annotated[str, ValidValues["loop", "root", "disabled"]] | None = None + spanning_tree_portfast: Annotated[str, ValidValues["edge", "network"]] | None = None vmtracer: bool | None = None priority_flow_control: PriorityFlowControl | None = None bfd: Bfd | None = None @@ -5509,18 +5619,18 @@ def __init__( mtu: int | None = None, l2_mtu: int | None = None, l2_mru: int | None = None, - vlans: Annotated[str, ConvertTypes[int]] | None = None, + vlans: str | None = None, native_vlan: int | None = None, native_vlan_tag: bool | None = None, - mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None = None, + mode: Annotated[str, ValidValues["access", "dot1q-tunnel", "trunk", "trunk phone"]] | None = None, phone: Phone | None = None, l2_protocol: L2Protocol | None = None, trunk_groups: list[str] | None = None, - type: Literal["routed", "switched", "l3dot1q", "l2dot1q", "port-channel-member"] | None = None, + type: Annotated[str, ValidValues["routed", "switched", "l3dot1q", "l2dot1q", "port-channel-member"]] | None = None, snmp_trap_link_change: bool | None = None, address_locking: AddressLocking | None = None, flowcontrol: Flowcontrol | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, flow_tracker: FlowTracker | None = None, error_correction_encoding: ErrorCorrectionEncoding | None = None, link_tracking_groups: list[LinkTrackingGroupsItem] | None = None, @@ -5530,7 +5640,7 @@ def __init__( vlan_id: int | None = None, ip_address: str | None = None, ip_address_secondaries: list[str] | None = None, - ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None = None, + ip_verify_unicast_source_reachable_via: Annotated[str, ValidValues["any", "rx"]] | None = None, dhcp_client_accept_default_route: bool | None = None, dhcp_server_ipv4: bool | None = None, dhcp_server_ipv6: bool | None = None, @@ -5551,9 +5661,9 @@ def __init__( mac_access_group_out: str | None = None, multicast: Multicast | None = None, ospf_network_point_to_point: bool | None = None, - ospf_area: Annotated[str, ConvertTypes[int]] | None = None, + ospf_area: str | None = None, ospf_cost: int | None = None, - ospf_authentication: Literal["none", "simple", "message-digest"] | None = None, + ospf_authentication: Annotated[str, ValidValues["none", "simple", "message-digest"]] | None = None, ospf_authentication_key: str | None = None, ospf_message_digest_keys: list[OspfMessageDigestKeysItem] | None = None, pim: Pim | None = None, @@ -5565,9 +5675,9 @@ def __init__( isis_passive: bool | None = None, isis_metric: int | None = None, isis_network_point_to_point: bool | None = None, - isis_circuit_type: Literal["level-1-2", "level-1", "level-2"] | None = None, + isis_circuit_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = None, isis_hello_padding: bool | None = None, - isis_authentication_mode: Literal["text", "md5"] | None = None, + isis_authentication_mode: Annotated[str, ValidValues["text", "md5"]] | None = None, isis_authentication_key: str | None = None, poe: Poe | None = None, ptp: Ptp | None = None, @@ -5576,16 +5686,16 @@ def __init__( logging: Logging | None = None, lldp: Lldp | None = None, trunk_private_vlan_secondary: bool | None = None, - pvlan_mapping: Annotated[str, ConvertTypes[int]] | None = None, + pvlan_mapping: str | None = None, vlan_translations: list[VlanTranslationsItem] | None = None, dot1x: Dot1x | None = None, service_profile: str | None = None, shape: Shape | None = None, qos: Qos | None = None, - spanning_tree_bpdufilter: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None, - spanning_tree_bpduguard: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None, - spanning_tree_guard: Literal["loop", "root", "disabled"] | None = None, - spanning_tree_portfast: Literal["edge", "network"] | None = None, + spanning_tree_bpdufilter: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None, + spanning_tree_bpduguard: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None, + spanning_tree_guard: Annotated[str, ValidValues["loop", "root", "disabled"]] | None = None, + spanning_tree_portfast: Annotated[str, ValidValues["edge", "network"]] | None = None, vmtracer: bool | None = None, priority_flow_control: PriorityFlowControl | None = None, bfd: Bfd | None = None, @@ -5954,15 +6064,15 @@ def __init__(self, interface: str = None, ip: bool | None = None, ipv6: bool | N return super().__init__(**kwargs) class TriggerOnMaintenance(AvdDictBaseModel): - operation: Literal["enter", "exit"] = None + operation: Annotated[str, ValidValues["enter", "exit"]] = None bgp_peer: str | None = None """ Ipv4/Ipv6 address or peer group name. Trigger condition occurs on maintenance operation of specified BGP peer. """ - action: Literal["after", "before", "all", "begin", "end"] = None + action: Annotated[str, ValidValues["after", "before", "all", "begin", "end"]] = None """Action for maintenance operation.""" - stage: Literal["bgp", "linkdown", "mlag", "ratemon"] | None = None + stage: Annotated[str, ValidValues["bgp", "linkdown", "mlag", "ratemon"]] | None = None """Action is triggered after/before specified stage.""" vrf: str | None = None """VRF name. VRF can be defined for "bgp_peer" only.""" @@ -5973,10 +6083,10 @@ class TriggerOnMaintenance(AvdDictBaseModel): def __init__( self, - operation: Literal["enter", "exit"] = None, + operation: Annotated[str, ValidValues["enter", "exit"]] = None, bgp_peer: str | None = None, - action: Literal["after", "before", "all", "begin", "end"] = None, - stage: Literal["bgp", "linkdown", "mlag", "ratemon"] | None = None, + action: Annotated[str, ValidValues["after", "before", "all", "begin", "end"]] = None, + stage: Annotated[str, ValidValues["bgp", "linkdown", "mlag", "ratemon"]] | None = None, vrf: str | None = None, interface: str | None = None, unit: str | None = None, @@ -6007,14 +6117,16 @@ def __init__( name: str = None """Event Handler Name.""" - action_type: Literal["bash", "increment", "log"] | None = None + action_type: Annotated[str, ValidValues["bash", "increment", "log"]] | None = None action: str | None = None """Command to execute.""" actions: Actions | None = None """Note: `bash_command` and `log` are mutually exclusive. `bash_command` takes precedence over `log`.""" delay: int | None = None """Event-handler delay in seconds.""" - trigger: Literal["on-boot", "on-counters", "on-intf", "on-logging", "on-maintenance", "on-startup-config", "vm-tracer vm"] | None = None + trigger: ( + Annotated[str, ValidValues["on-boot", "on-counters", "on-intf", "on-logging", "on-maintenance", "on-startup-config", "vm-tracer vm"]] | None + ) = None """Configure event trigger condition.""" trigger_on_counters: TriggerOnCounters | None = None trigger_on_logging: TriggerOnLogging | None = None @@ -6034,11 +6146,13 @@ def __init__( def __init__( self, name: str = None, - action_type: Literal["bash", "increment", "log"] | None = None, + action_type: Annotated[str, ValidValues["bash", "increment", "log"]] | None = None, action: str | None = None, actions: Actions | None = None, delay: int | None = None, - trigger: Literal["on-boot", "on-counters", "on-intf", "on-logging", "on-maintenance", "on-startup-config", "vm-tracer vm"] | None = None, + trigger: ( + Annotated[str, ValidValues["on-boot", "on-counters", "on-intf", "on-logging", "on-maintenance", "on-startup-config", "vm-tracer vm"]] | None + ) = None, trigger_on_counters: TriggerOnCounters | None = None, trigger_on_logging: TriggerOnLogging | None = None, trigger_on_intf: TriggerOnIntf | None = None, @@ -6560,7 +6674,7 @@ def __init__( self.table_size = table_size return super().__init__(**kwargs) - type: Literal["sampled"] = None + type: Annotated[str, ValidValues["sampled"]] = None """Flow Tracking Type - only 'sampled' supported for now.""" sample: int | None = None trackers: list[TrackersItem] | None = None @@ -6568,7 +6682,7 @@ def __init__( def __init__( self, - type: Literal["sampled"] = None, + type: Annotated[str, ValidValues["sampled"]] = None, sample: int | None = None, trackers: list[TrackersItem] | None = None, shutdown: bool | None = False, @@ -6591,9 +6705,9 @@ def __init__( class Hardware(AvdDictBaseModel): class AccessList(AvdDictBaseModel): - mechanism: Literal["algomatch", "none", "tcam"] | None = None + mechanism: Annotated[str, ValidValues["algomatch", "none", "tcam"]] | None = None - def __init__(self, mechanism: Literal["algomatch", "none", "tcam"] | None = None, **kwargs): + def __init__(self, mechanism: Annotated[str, ValidValues["algomatch", "none", "tcam"]] | None = None, **kwargs): """ Args: ----- @@ -6604,11 +6718,11 @@ def __init__(self, mechanism: Literal["algomatch", "none", "tcam"] | None = None return super().__init__(**kwargs) class SpeedGroupsItem(AvdDictBaseModel): - speed_group: Annotated[str, ConvertTypes[int]] = None + speed_group: str = None serdes: str | None = None """Serdes speed like "10g" or "25g".""" - def __init__(self, speed_group: Annotated[str, ConvertTypes[int]] = None, serdes: str | None = None, **kwargs): + def __init__(self, speed_group: str = None, serdes: str | None = None, **kwargs): """ Args: ----- @@ -6638,48 +6752,51 @@ def __init__(self, access_list: AccessList | None = None, speed_groups: list[Spe class HardwareCounters(AvdDictBaseModel): class FeaturesItem(AvdDictBaseModel): name: ( - Literal[ - "acl", - "decap-group", - "directflow", - "ecn", - "flow-spec", - "gre tunnel interface", - "ip", - "mpls interface", - "mpls lfib", - "mpls tunnel", - "multicast", - "nexthop", - "pbr", - "pdp", - "policing interface", - "qos", - "qos dual-rate-policer", - "route", - "routed-port", - "segment-security", - "subinterface", - "tapagg", - "traffic-class", - "traffic-policy", - "vlan", - "vlan-interface", - "vni decap", - "vni encap", - "vtep decap", - "vtep encap", + Annotated[ + str, + ValidValues[ + "acl", + "decap-group", + "directflow", + "ecn", + "flow-spec", + "gre tunnel interface", + "ip", + "mpls interface", + "mpls lfib", + "mpls tunnel", + "multicast", + "nexthop", + "pbr", + "pdp", + "policing interface", + "qos", + "qos dual-rate-policer", + "route", + "routed-port", + "segment-security", + "subinterface", + "tapagg", + "traffic-class", + "traffic-policy", + "vlan", + "vlan-interface", + "vni decap", + "vni encap", + "vtep decap", + "vtep encap", + ], ] | None ) = None - direction: Literal["in", "out", "cpu"] | None = None + direction: Annotated[str, ValidValues["in", "out", "cpu"]] | None = None """ Most features support only 'in' and 'out'. Some like traffic-policy support 'cpu'. Some features DO NOT have any direction. This validation IS NOT made by the schemas. """ - address_type: Literal["ipv4", "ipv6", "mac"] | None = None + address_type: Annotated[str, ValidValues["ipv4", "ipv6", "mac"]] | None = None """ Supported only for the following features: - acl: [ipv4, ipv6, mac] if direction is 'out' @@ -6690,7 +6807,7 @@ class FeaturesItem(AvdDictBaseModel): """ layer3: bool | None = None """Supported only for the 'ip' feature.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """ Supported only for the 'route' feature. This validation IS NOT made by the schemas. @@ -6706,44 +6823,47 @@ class FeaturesItem(AvdDictBaseModel): def __init__( self, name: ( - Literal[ - "acl", - "decap-group", - "directflow", - "ecn", - "flow-spec", - "gre tunnel interface", - "ip", - "mpls interface", - "mpls lfib", - "mpls tunnel", - "multicast", - "nexthop", - "pbr", - "pdp", - "policing interface", - "qos", - "qos dual-rate-policer", - "route", - "routed-port", - "segment-security", - "subinterface", - "tapagg", - "traffic-class", - "traffic-policy", - "vlan", - "vlan-interface", - "vni decap", - "vni encap", - "vtep decap", - "vtep encap", + Annotated[ + str, + ValidValues[ + "acl", + "decap-group", + "directflow", + "ecn", + "flow-spec", + "gre tunnel interface", + "ip", + "mpls interface", + "mpls lfib", + "mpls tunnel", + "multicast", + "nexthop", + "pbr", + "pdp", + "policing interface", + "qos", + "qos dual-rate-policer", + "route", + "routed-port", + "segment-security", + "subinterface", + "tapagg", + "traffic-class", + "traffic-policy", + "vlan", + "vlan-interface", + "vni decap", + "vni encap", + "vtep decap", + "vtep encap", + ], ] | None ) = None, - direction: Literal["in", "out", "cpu"] | None = None, - address_type: Literal["ipv4", "ipv6", "mac"] | None = None, + direction: Annotated[str, ValidValues["in", "out", "cpu"]] | None = None, + address_type: Annotated[str, ValidValues["ipv4", "ipv6", "mac"]] | None = None, layer3: bool | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, prefix: str | None = None, units_packets: bool | None = None, **kwargs, @@ -6973,7 +7093,7 @@ class EntriesItem(AvdDictBaseModel): Comment up to 100 characters. If remark is defined, other keys in the ACL entry will be ignored. """ - action: Literal["permit", "deny"] | None = None + action: Annotated[str, ValidValues["permit", "deny"]] | None = None """ ACL action. Required except for remarks. @@ -6989,16 +7109,16 @@ class EntriesItem(AvdDictBaseModel): "" without a mask means host. Required except for remarks. """ - source_ports_match: Literal["eq", "gt", "lt", "neq", "range"] | None = "eq" - source_ports: list[Annotated[str, ConvertTypes[int]]] | None = None + source_ports_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq", "range"]] | None = "eq" + source_ports: list[str] | None = None destination: str | None = None """ "any", "/" or "". "" without a mask means host. Required except for remarks. """ - destination_ports_match: Literal["eq", "gt", "lt", "neq", "range"] | None = "eq" - destination_ports: list[Annotated[str, ConvertTypes[int]]] | None = None + destination_ports_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq", "range"]] | None = "eq" + destination_ports: list[str] | None = None tcp_flags: list[str] | None = None fragments: bool | None = None """Match non-head fragment packets.""" @@ -7006,16 +7126,16 @@ class EntriesItem(AvdDictBaseModel): """Log matches against this rule.""" ttl: int | None = None """TTL value.""" - ttl_match: Literal["eq", "gt", "lt", "neq"] | None = "eq" - icmp_type: Annotated[str, ConvertTypes[int]] | None = None + ttl_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq"]] | None = "eq" + icmp_type: str | None = None """Message type name/number for ICMP packets.""" - icmp_code: Annotated[str, ConvertTypes[int]] | None = None + icmp_code: str | None = None """Message code for ICMP packets.""" nexthop_group: str | None = None """nexthop-group name.""" tracked: bool | None = None """Match packets in existing ICMP/UDP/TCP connections.""" - dscp: Annotated[str, ConvertTypes[int]] | None = None + dscp: str | None = None """DSCP value or name.""" vlan_number: int | None = None vlan_inner: bool | None = False @@ -7026,24 +7146,24 @@ def __init__( self, sequence: int | None = None, remark: str | None = None, - action: Literal["permit", "deny"] | None = None, + action: Annotated[str, ValidValues["permit", "deny"]] | None = None, protocol: str | None = None, source: str | None = None, - source_ports_match: Literal["eq", "gt", "lt", "neq", "range"] | None = "eq", - source_ports: list[Annotated[str, ConvertTypes[int]]] | None = None, + source_ports_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq", "range"]] | None = "eq", + source_ports: list[str] | None = None, destination: str | None = None, - destination_ports_match: Literal["eq", "gt", "lt", "neq", "range"] | None = "eq", - destination_ports: list[Annotated[str, ConvertTypes[int]]] | None = None, + destination_ports_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq", "range"]] | None = "eq", + destination_ports: list[str] | None = None, tcp_flags: list[str] | None = None, fragments: bool | None = None, log: bool | None = None, ttl: int | None = None, - ttl_match: Literal["eq", "gt", "lt", "neq"] | None = "eq", - icmp_type: Annotated[str, ConvertTypes[int]] | None = None, - icmp_code: Annotated[str, ConvertTypes[int]] | None = None, + ttl_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq"]] | None = "eq", + icmp_type: str | None = None, + icmp_code: str | None = None, nexthop_group: str | None = None, tracked: bool | None = None, - dscp: Annotated[str, ConvertTypes[int]] | None = None, + dscp: str | None = None, vlan_number: int | None = None, vlan_inner: bool | None = False, vlan_mask: str | None = None, @@ -7114,15 +7234,13 @@ def __init__( self.vlan_mask = vlan_mask return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """Access-list Name.""" counters_per_entry: bool | None = None entries: list[EntriesItem] | None = None """ACL Entries.""" - def __init__( - self, name: Annotated[str, ConvertTypes[int]] = None, counters_per_entry: bool | None = None, entries: list[EntriesItem] | None = None, **kwargs - ): + def __init__(self, name: str = None, counters_per_entry: bool | None = None, entries: list[EntriesItem] | None = None, **kwargs): """ Args: ----- @@ -7138,7 +7256,7 @@ def __init__( class IpCommunityListsItem(AvdDictBaseModel): class EntriesItem(AvdDictBaseModel): - action: Literal["permit", "deny"] = None + action: Annotated[str, ValidValues["permit", "deny"]] = None communities: list[str] | None = None """ If defined, a standard community-list will be configured. @@ -7158,7 +7276,9 @@ class EntriesItem(AvdDictBaseModel): If defined, a regex community-list will be configured. """ - def __init__(self, action: Literal["permit", "deny"] = None, communities: list[str] | None = None, regexp: str | None = None, **kwargs): + def __init__( + self, action: Annotated[str, ValidValues["permit", "deny"]] = None, communities: list[str] | None = None, regexp: str | None = None, **kwargs + ): """ Args: ----- @@ -7226,9 +7346,9 @@ class IpDhcpSnooping(AvdDictBaseModel): class InformationOption(AvdDictBaseModel): enabled: bool | None = None """Enable insertion of option-82 in DHCP request packets.""" - circuit_id_type: Annotated[str, ConvertTypes[int]] | None = None + circuit_id_type: str | None = None """"none" or <0 - 255>.""" - circuit_id_format: Literal["%h:%p", "%p:%v"] | None = None + circuit_id_format: Annotated[str, ValidValues["%h:%p", "%p:%v"]] | None = None """ Required if `circuit_id_type` is set. - "%h:%p" Hostname and interface name @@ -7238,8 +7358,8 @@ class InformationOption(AvdDictBaseModel): def __init__( self, enabled: bool | None = None, - circuit_id_type: Annotated[str, ConvertTypes[int]] | None = None, - circuit_id_format: Literal["%h:%p", "%p:%v"] | None = None, + circuit_id_type: str | None = None, + circuit_id_format: Annotated[str, ValidValues["%h:%p", "%p:%v"]] | None = None, **kwargs, ): """ @@ -7261,7 +7381,7 @@ def __init__( enabled: bool | None = None bridging: bool | None = None information_option: InformationOption | None = None - vlan: Annotated[str, ConvertTypes[int]] | None = None + vlan: str | None = None """ VLAN range as string. "< vlan_id >, < vlan_id >-< vlan_id >" @@ -7273,7 +7393,7 @@ def __init__( enabled: bool | None = None, bridging: bool | None = None, information_option: InformationOption | None = None, - vlan: Annotated[str, ConvertTypes[int]] | None = None, + vlan: str | None = None, **kwargs, ): """ @@ -7298,9 +7418,9 @@ class IpDomainLookup(AvdDictBaseModel): class SourceInterfacesItem(AvdDictBaseModel): name: str = None """Source Interface.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None - def __init__(self, name: str = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -7326,14 +7446,14 @@ def __init__(self, source_interfaces: list[SourceInterfacesItem] | None = None, class IpExtcommunityListsItem(AvdDictBaseModel): class EntriesItem(AvdDictBaseModel): - type: Literal["permit", "deny"] = None + type: Annotated[str, ValidValues["permit", "deny"]] = None extcommunities: str = None """ Communities as string. Example: "65000:65000" """ - def __init__(self, type: Literal["permit", "deny"] = None, extcommunities: str = None, **kwargs): + def __init__(self, type: Annotated[str, ValidValues["permit", "deny"]] = None, extcommunities: str = None, **kwargs): """ Args: ----- @@ -7365,11 +7485,11 @@ def __init__(self, name: str = None, entries: list[EntriesItem] = None, **kwargs class IpExtcommunityListsRegexpItem(AvdDictBaseModel): class EntriesItem(AvdDictBaseModel): - type: Literal["permit", "deny"] = None + type: Annotated[str, ValidValues["permit", "deny"]] = None regexp: str = None """Regular Expression.""" - def __init__(self, type: Literal["permit", "deny"] = None, regexp: str = None, **kwargs): + def __init__(self, type: Annotated[str, ValidValues["permit", "deny"]] = None, regexp: str = None, **kwargs): """ Args: ----- @@ -7419,9 +7539,9 @@ class IpHardware(AvdDictBaseModel): class Fib(AvdDictBaseModel): class Optimize(AvdDictBaseModel): class Prefixes(AvdDictBaseModel): - profile: Literal["internet", "urpf-internet"] | None = None + profile: Annotated[str, ValidValues["internet", "urpf-internet"]] | None = None - def __init__(self, profile: Literal["internet", "urpf-internet"] | None = None, **kwargs): + def __init__(self, profile: Annotated[str, ValidValues["internet", "urpf-internet"]] | None = None, **kwargs): """ Args: ----- @@ -7470,9 +7590,9 @@ def __init__(self, fib: Fib | None = None, **kwargs): class IpHttpClientSourceInterfacesItem(AvdDictBaseModel): name: str | None = None """Interface Name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -7677,12 +7797,12 @@ def __init__( class IpNameServersItem(AvdDictBaseModel): ip_address: str | None = None """IPv4 or IPv6 address for DNS server.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name.""" priority: int | None = None """Priority value (lower is first).""" - def __init__(self, ip_address: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, priority: int | None = None, **kwargs): + def __init__(self, ip_address: str | None = None, vrf: str | None = None, priority: int | None = None, **kwargs): """ Args: ----- @@ -7725,7 +7845,7 @@ class StaticItem(AvdDictBaseModel): access_list: str | None = None """'access_list' and 'group' are mutual exclusive.""" comment: str | None = None - direction: Literal["egress", "ingress"] | None = None + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None """ Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware platform. EOS might @@ -7738,7 +7858,7 @@ class StaticItem(AvdDictBaseModel): original_port: int | None = None """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" priority: int | None = None - protocol: Literal["udp", "tcp"] | None = None + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None translated_ip: str = None """IPv4 address.""" translated_port: int | None = None @@ -7748,12 +7868,12 @@ def __init__( self, access_list: str | None = None, comment: str | None = None, - direction: Literal["egress", "ingress"] | None = None, + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None, group: int | None = None, original_ip: str | None = None, original_port: int | None = None, priority: int | None = None, - protocol: Literal["udp", "tcp"] | None = None, + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None, translated_ip: str = None, translated_port: int | None = None, **kwargs, @@ -7807,7 +7927,7 @@ class Source(AvdDictBaseModel): class DynamicItem(AvdDictBaseModel): access_list: str = None comment: str | None = None - nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] = None + nat_type: Annotated[str, ValidValues["overload", "pool", "pool-address-only", "pool-full-cone"]] = None pool_name: str | None = None """ required if 'nat_type' is pool, pool-address-only or pool-full-cone. @@ -7819,7 +7939,7 @@ def __init__( self, access_list: str = None, comment: str | None = None, - nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] = None, + nat_type: Annotated[str, ValidValues["overload", "pool", "pool-address-only", "pool-full-cone"]] = None, pool_name: str | None = None, priority: int | None = None, **kwargs, @@ -7847,7 +7967,7 @@ class StaticItem(AvdDictBaseModel): access_list: str | None = None """'access_list' and 'group' are mutual exclusive.""" comment: str | None = None - direction: Literal["egress", "ingress"] | None = None + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None """ Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware platform. EOS might @@ -7860,7 +7980,7 @@ class StaticItem(AvdDictBaseModel): original_port: int | None = None """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" priority: int | None = None - protocol: Literal["udp", "tcp"] | None = None + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None translated_ip: str = None """IPv4 address.""" translated_port: int | None = None @@ -7870,12 +7990,12 @@ def __init__( self, access_list: str | None = None, comment: str | None = None, - direction: Literal["egress", "ingress"] | None = None, + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None, group: int | None = None, original_ip: str | None = None, original_port: int | None = None, priority: int | None = None, - protocol: Literal["udp", "tcp"] | None = None, + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None, translated_ip: str = None, translated_port: int | None = None, **kwargs, @@ -7926,19 +8046,12 @@ def __init__(self, dynamic: list[DynamicItem] | None = None, static: list[Static return super().__init__(**kwargs) name: str = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """Specify VRF for NAT profile.""" destination: Destination | None = None source: Source | None = None - def __init__( - self, - name: str = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, - destination: Destination | None = None, - source: Source | None = None, - **kwargs, - ): + def __init__(self, name: str = None, vrf: str | None = None, destination: Destination | None = None, source: Source | None = None, **kwargs): """ Args: ----- @@ -8002,7 +8115,7 @@ def __init__( return super().__init__(**kwargs) name: str = None - type: Literal["ip-port", "port-only"] | None = "ip-port" + type: Annotated[str, ValidValues["ip-port", "port-only"]] | None = "ip-port" prefix_length: int | None = None """It is only used and required when `type` is `ip-port`.""" ranges: list[RangesItem] | None = None @@ -8011,7 +8124,7 @@ def __init__( def __init__( self, name: str = None, - type: Literal["ip-port", "port-only"] | None = "ip-port", + type: Annotated[str, ValidValues["ip-port", "port-only"]] | None = "ip-port", prefix_length: int | None = None, ranges: list[RangesItem] | None = None, utilization_log_threshold: int | None = None, @@ -8166,11 +8279,11 @@ def __init__(self, limit: int | None = None, host_limit: int | None = None, ip_l return super().__init__(**kwargs) class TimeoutsItem(AvdDictBaseModel): - protocol: Literal["tcp", "udp"] = None + protocol: Annotated[str, ValidValues["tcp", "udp"]] = None timeout: int = None """In seconds.""" - def __init__(self, protocol: Literal["tcp", "udp"] = None, timeout: int = None, **kwargs): + def __init__(self, protocol: Annotated[str, ValidValues["tcp", "udp"]] = None, timeout: int = None, **kwargs): """ Args: ----- @@ -8250,10 +8363,10 @@ def __init__( class IpRadiusSourceInterfacesItem(AvdDictBaseModel): name: str | None = None """Interface Name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name.""" - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -8284,9 +8397,9 @@ class IkePoliciesItem(AvdDictBaseModel): """ ike_lifetime: int | None = None """IKE lifetime in hours.""" - encryption: Literal["3des", "aes128", "aes256"] | None = None + encryption: Annotated[str, ValidValues["3des", "aes128", "aes256"]] | None = None """IKE encryption algorithm.""" - dh_group: Literal[1, 2, 5, 14, 15, 16, 17, 20, 21, 24] | None = None + dh_group: int | None = None """Diffie-Hellman group for the key exchange.""" def __init__( @@ -8295,8 +8408,8 @@ def __init__( local_id: str | None = None, local_id_fqdn: str | None = None, ike_lifetime: int | None = None, - encryption: Literal["3des", "aes128", "aes256"] | None = None, - dh_group: Literal[1, 2, 5, 14, 15, 16, 17, 20, 21, 24] | None = None, + encryption: Annotated[str, ValidValues["3des", "aes128", "aes256"]] | None = None, + dh_group: int | None = None, **kwargs, ): """ @@ -8337,9 +8450,14 @@ class SaLifetime(AvdDictBaseModel): <1-6000> Byte limit in GB ( 1024 MB ) <1-6144000> Byte limit in MB ( 1024 KB ) """ - unit: Literal["gigabytes", "hours", "megabytes", "thousand-packets"] | None = "hours" + unit: Annotated[str, ValidValues["gigabytes", "hours", "megabytes", "thousand-packets"]] | None = "hours" - def __init__(self, value: int | None = None, unit: Literal["gigabytes", "hours", "megabytes", "thousand-packets"] | None = "hours", **kwargs): + def __init__( + self, + value: int | None = None, + unit: Annotated[str, ValidValues["gigabytes", "hours", "megabytes", "thousand-packets"]] | None = "hours", + **kwargs, + ): """ Args: ----- @@ -8359,13 +8477,15 @@ def __init__(self, value: int | None = None, unit: Literal["gigabytes", "hours", return super().__init__(**kwargs) class Esp(AvdDictBaseModel): - integrity: Literal["disabled", "sha1", "sha256", "null"] | None = None - encryption: Literal["disabled", "aes128", "aes128gcm128", "aes128gcm64", "aes256", "aes256gcm128", "null"] | None = None + integrity: Annotated[str, ValidValues["disabled", "sha1", "sha256", "null"]] | None = None + encryption: Annotated[str, ValidValues["disabled", "aes128", "aes128gcm128", "aes128gcm64", "aes256", "aes256gcm128", "null"]] | None = None def __init__( self, - integrity: Literal["disabled", "sha1", "sha256", "null"] | None = None, - encryption: Literal["disabled", "aes128", "aes128gcm128", "aes128gcm64", "aes256", "aes256gcm128", "null"] | None = None, + integrity: Annotated[str, ValidValues["disabled", "sha1", "sha256", "null"]] | None = None, + encryption: ( + Annotated[str, ValidValues["disabled", "aes128", "aes128gcm128", "aes128gcm64", "aes256", "aes256gcm128", "null"]] | None + ) = None, **kwargs, ): """ @@ -8383,16 +8503,9 @@ def __init__( """Name of the SA policy. The "null" value is deprecated and will be removed in AVD 5.0.0.""" sa_lifetime: SaLifetime | None = None esp: Esp | None = None - pfs_dh_group: Literal[1, 2, 5, 14, 15, 16, 17, 20, 21, 24] | None = None + pfs_dh_group: int | None = None - def __init__( - self, - name: str = None, - sa_lifetime: SaLifetime | None = None, - esp: Esp | None = None, - pfs_dh_group: Literal[1, 2, 5, 14, 15, 16, 17, 20, 21, 24] | None = None, - **kwargs, - ): + def __init__(self, name: str = None, sa_lifetime: SaLifetime | None = None, esp: Esp | None = None, pfs_dh_group: int | None = None, **kwargs): """ Args: ----- @@ -8414,7 +8527,7 @@ class Dpd(AvdDictBaseModel): """Interval (in seconds) between keep-alive messages.""" time: int = None """Time (in seconds) after which the action is applied.""" - action: Literal["clear", "hold", "restart"] = None + action: Annotated[str, ValidValues["clear", "hold", "restart"]] = None """ Action to apply. @@ -8424,7 +8537,7 @@ class Dpd(AvdDictBaseModel): connection immediately """ - def __init__(self, interval: int = None, time: int = None, action: Literal["clear", "hold", "restart"] = None, **kwargs): + def __init__(self, interval: int = None, time: int = None, action: Annotated[str, ValidValues["clear", "hold", "restart"]] = None, **kwargs): """ Args: ----- @@ -8450,13 +8563,13 @@ def __init__(self, interval: int = None, time: int = None, action: Literal["clea """Name of the IKE policy to use in this profile.""" sa_policy: str | None = None """Name of the Security Association to use in this profile.""" - connection: Literal["add", "start", "route"] | None = None + connection: Annotated[str, ValidValues["add", "start", "route"]] | None = None """IPsec connection (Initiator/Responder/Dynamic).""" shared_key: str | None = None """Encrypted password - only type 7 supported.""" dpd: Dpd | None = None """Dead Peer Detection.""" - mode: Literal["transport", "tunnel"] | None = None + mode: Annotated[str, ValidValues["transport", "tunnel"]] | None = None """Ipsec mode type.""" flow_parallelization_encapsulation_udp: bool | None = None """ @@ -8470,10 +8583,10 @@ def __init__( name: str = None, ike_policy: str | None = None, sa_policy: str | None = None, - connection: Literal["add", "start", "route"] | None = None, + connection: Annotated[str, ValidValues["add", "start", "route"]] | None = None, shared_key: str | None = None, dpd: Dpd | None = None, - mode: Literal["transport", "tunnel"] | None = None, + mode: Annotated[str, ValidValues["transport", "tunnel"]] | None = None, flow_parallelization_encapsulation_udp: bool | None = None, **kwargs, ): @@ -8561,9 +8674,9 @@ def __init__( class IpSshClientSourceInterfacesItem(AvdDictBaseModel): name: str | None = None """Interface Name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = "default" + vrf: str | None = "default" - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = "default", **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = "default", **kwargs): """ Args: ----- @@ -8578,9 +8691,9 @@ def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int class IpTacacsSourceInterfacesItem(AvdDictBaseModel): name: str | None = None """Interface name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -8652,18 +8765,12 @@ def __init__(self, sequence: int = None, action: str = None, **kwargs): self.action = action return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """IPv6 Access-list Name.""" counters_per_entry: bool | None = None sequence_numbers: list[SequenceNumbersItem] = None - def __init__( - self, - name: Annotated[str, ConvertTypes[int]] = None, - counters_per_entry: bool | None = None, - sequence_numbers: list[SequenceNumbersItem] = None, - **kwargs, - ): + def __init__(self, name: str = None, counters_per_entry: bool | None = None, sequence_numbers: list[SequenceNumbersItem] = None, **kwargs): """ Args: ----- @@ -8681,10 +8788,10 @@ class Ipv6DhcpRelay(AvdDictBaseModel): class Option(AvdDictBaseModel): link_layer_address: bool | None = None """Add Option 79 (Link Layer Address Option).""" - remote_id_format: Literal["%m:%i", "%m:%p"] | None = None + remote_id_format: Annotated[str, ValidValues["%m:%i", "%m:%p"]] | None = None """Add RemoteID option 37 in format MAC address and interface ID (`%m:%i`) or MAC address and interface name (`%m:%p`).""" - def __init__(self, link_layer_address: bool | None = None, remote_id_format: Literal["%m:%i", "%m:%p"] | None = None, **kwargs): + def __init__(self, link_layer_address: bool | None = None, remote_id_format: Annotated[str, ValidValues["%m:%i", "%m:%p"]] | None = None, **kwargs): """ Args: ----- @@ -8777,7 +8884,7 @@ class StaticEntriesItem(AvdDictBaseModel): vrf: str | None = None interface: str = None """Interface name.""" - mac_address: Annotated[str, Pattern["^([0-9a-f]{2}:){5}[0-9a-f]{2}$"]] = None + mac_address: Annotated[str, Pattern[r"^([0-9a-f]{2}:){5}[0-9a-f]{2}$"]] = None """MAC address of neighbor like 'aa:af:12:34:bc:bf'""" def __init__( @@ -8785,7 +8892,7 @@ def __init__( ipv6_address: str = None, vrf: str | None = None, interface: str = None, - mac_address: Annotated[str, Pattern["^([0-9a-f]{2}:){5}[0-9a-f]{2}$"]] = None, + mac_address: Annotated[str, Pattern[r"^([0-9a-f]{2}:){5}[0-9a-f]{2}$"]] = None, **kwargs, ): """ @@ -8908,18 +9015,12 @@ def __init__(self, sequence: int = None, action: str = None, **kwargs): self.action = action return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """Access-list Name.""" counters_per_entry: bool | None = None sequence_numbers: list[SequenceNumbersItem] = None - def __init__( - self, - name: Annotated[str, ConvertTypes[int]] = None, - counters_per_entry: bool | None = None, - sequence_numbers: list[SequenceNumbersItem] = None, - **kwargs, - ): + def __init__(self, name: str = None, counters_per_entry: bool | None = None, sequence_numbers: list[SequenceNumbersItem] = None, **kwargs): """ Args: ----- @@ -8934,7 +9035,7 @@ def __init__( return super().__init__(**kwargs) class Ipv6StaticRoutesItem(AvdDictBaseModel): - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None destination_address_prefix: str | None = None """IPv6 Network/Mask.""" interface: str | None = None @@ -8950,7 +9051,7 @@ class Ipv6StaticRoutesItem(AvdDictBaseModel): def __init__( self, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, destination_address_prefix: str | None = None, interface: str | None = None, gateway: str | None = None, @@ -8989,14 +9090,14 @@ def __init__( class L2Protocol(AvdDictBaseModel): class ForwardingProfilesItem(AvdDictBaseModel): class ProtocolsItem(AvdDictBaseModel): - name: Literal["bfd per-link rfc-7130", "e-lmi", "isis", "lacp", "lldp", "macsec", "pause", "stp"] = None + name: Annotated[str, ValidValues["bfd per-link rfc-7130", "e-lmi", "isis", "lacp", "lldp", "macsec", "pause", "stp"]] = None forward: bool | None = None tagged_forward: bool | None = None untagged_forward: bool | None = None def __init__( self, - name: Literal["bfd per-link rfc-7130", "e-lmi", "isis", "lacp", "lldp", "macsec", "pause", "stp"] = None, + name: Annotated[str, ValidValues["bfd per-link rfc-7130", "e-lmi", "isis", "lacp", "lldp", "macsec", "pause", "stp"]] = None, forward: bool | None = None, tagged_forward: bool | None = None, untagged_forward: bool | None = None, @@ -9132,24 +9233,9 @@ def __init__(self, name: str = None, links_minimum: int | None = None, recovery_ class Lldp(AvdDictBaseModel): class TlvsItem(AvdDictBaseModel): - name: Literal[ - "link-aggregation", - "management-address", - "max-frame-size", - "med", - "port-description", - "port-vlan", - "power-via-mdi", - "system-capabilities", - "system-description", - "system-name", - "vlan-name", - ] = None - transmit: bool | None = None - - def __init__( - self, - name: Literal[ + name: Annotated[ + str, + ValidValues[ "link-aggregation", "management-address", "max-frame-size", @@ -9161,6 +9247,27 @@ def __init__( "system-description", "system-name", "vlan-name", + ], + ] = None + transmit: bool | None = None + + def __init__( + self, + name: Annotated[ + str, + ValidValues[ + "link-aggregation", + "management-address", + "max-frame-size", + "med", + "port-description", + "port-vlan", + "power-via-mdi", + "system-capabilities", + "system-description", + "system-name", + "vlan-name", + ], ] = None, transmit: bool | None = None, **kwargs, @@ -9180,7 +9287,7 @@ def __init__( timer_reinitialization: str | None = None holdtime: int | None = None management_address: str | None = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None receive_packet_tagged_drop: str | None = None tlvs: list[TlvsItem] | None = None run: bool | None = None @@ -9191,7 +9298,7 @@ def __init__( timer_reinitialization: str | None = None, holdtime: int | None = None, management_address: str | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, receive_packet_tagged_drop: str | None = None, tlvs: list[TlvsItem] | None = None, run: bool | None = None, @@ -9256,7 +9363,7 @@ class LocalUsersItem(AvdDictBaseModel): """If set a password will not be configured for this user. "sha512_password" MUST not be defined for this user.""" ssh_key: str | None = None secondary_ssh_key: str | None = None - shell: Literal["/bin/bash", "/bin/sh", "/sbin/nologin"] | None = None + shell: Annotated[str, ValidValues["/bin/bash", "/bin/sh", "/sbin/nologin"]] | None = None """Specify shell for the user.""" def __init__( @@ -9269,7 +9376,7 @@ def __init__( no_password: bool | None = None, ssh_key: str | None = None, secondary_ssh_key: str | None = None, - shell: Literal["/bin/bash", "/bin/sh", "/sbin/nologin"] | None = None, + shell: Annotated[str, ValidValues["/bin/bash", "/bin/sh", "/sbin/nologin"]] | None = None, **kwargs, ): """ @@ -9305,14 +9412,22 @@ def __init__( class Logging(AvdDictBaseModel): class Buffered(AvdDictBaseModel): size: int | None = None - level: Literal["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"] | None = None + level: ( + Annotated[ + str, ValidValues["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"] + ] + | None + ) = None """Buffer logging severity level.""" def __init__( self, size: int | None = None, level: ( - Literal["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"] | None + Annotated[ + str, ValidValues["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"] + ] + | None ) = None, **kwargs, ): @@ -9329,14 +9444,24 @@ def __init__( class Synchronous(AvdDictBaseModel): level: ( - Literal["alerts", "all", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"] | None + Annotated[ + str, + ValidValues["alerts", "all", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"], + ] + | None ) = "critical" """Synchronous logging severity level.""" def __init__( self, level: ( - Literal["alerts", "all", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"] | None + Annotated[ + str, + ValidValues[ + "alerts", "all", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled" + ], + ] + | None ) = "critical", **kwargs, ): @@ -9351,11 +9476,16 @@ def __init__( class Format(AvdDictBaseModel): timestamp: ( - Literal["high-resolution", "traditional", "traditional timezone", "traditional year", "traditional timezone year", "traditional year timezone"] + Annotated[ + str, + ValidValues[ + "high-resolution", "traditional", "traditional timezone", "traditional year", "traditional timezone year", "traditional year timezone" + ], + ] | None ) = None """Timestamp format.""" - hostname: Literal["fqdn", "ipv4"] | None = None + hostname: Annotated[str, ValidValues["fqdn", "ipv4"]] | None = None """Hostname format in syslogs. For hostname _only_, remove the line. (default EOS CLI behaviour).""" sequence_numbers: bool | None = None """Add sequence numbers to log messages.""" @@ -9365,12 +9495,20 @@ class Format(AvdDictBaseModel): def __init__( self, timestamp: ( - Literal[ - "high-resolution", "traditional", "traditional timezone", "traditional year", "traditional timezone year", "traditional year timezone" + Annotated[ + str, + ValidValues[ + "high-resolution", + "traditional", + "traditional timezone", + "traditional year", + "traditional timezone year", + "traditional year timezone", + ], ] | None ) = None, - hostname: Literal["fqdn", "ipv4"] | None = None, + hostname: Annotated[str, ValidValues["fqdn", "ipv4"]] | None = None, sequence_numbers: bool | None = None, rfc5424: bool | None = None, **kwargs, @@ -9394,10 +9532,12 @@ class VrfsItem(AvdDictBaseModel): class HostsItem(AvdDictBaseModel): name: str = None """Syslog server name.""" - protocol: Literal["tcp", "udp"] | None = "udp" + protocol: Annotated[str, ValidValues["tcp", "udp"]] | None = "udp" ports: list[int] | None = None - def __init__(self, name: str = None, protocol: Literal["tcp", "udp"] | None = "udp", ports: list[int] | None = None, **kwargs): + def __init__( + self, name: str = None, protocol: Annotated[str, ValidValues["tcp", "udp"]] | None = "udp", ports: list[int] | None = None, **kwargs + ): """ Args: ----- @@ -9411,15 +9551,13 @@ def __init__(self, name: str = None, protocol: Literal["tcp", "udp"] | None = "u self.ports = ports return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF name.""" source_interface: str | None = None """Source interface name.""" hosts: list[HostsItem] | None = None - def __init__( - self, name: Annotated[str, ConvertTypes[int]] = None, source_interface: str | None = None, hosts: list[HostsItem] | None = None, **kwargs - ): + def __init__(self, name: str = None, source_interface: str | None = None, hosts: list[HostsItem] | None = None, **kwargs): """ Args: ----- @@ -9438,9 +9576,9 @@ class Match(AvdDictBaseModel): class MatchListsItem(AvdDictBaseModel): name: str = None """Match list.""" - action: Literal["discard"] | None = None + action: Annotated[str, ValidValues["discard"]] | None = None - def __init__(self, name: str = None, action: Literal["discard"] | None = None, **kwargs): + def __init__(self, name: str = None, action: Annotated[str, ValidValues["discard"]] | None = None, **kwargs): """ Args: ----- @@ -9523,7 +9661,8 @@ class LevelItem(AvdDictBaseModel): facility: str = None severity: ( Annotated[ - Literal[ + str, + ValidValues[ "alerts", "critical", "debugging", @@ -9541,7 +9680,6 @@ class LevelItem(AvdDictBaseModel): "6", "7", ], - ConvertTypes[int], ] | None ) = None @@ -9566,7 +9704,8 @@ def __init__( facility: str = None, severity: ( Annotated[ - Literal[ + str, + ValidValues[ "alerts", "critical", "debugging", @@ -9584,7 +9723,6 @@ def __init__( "6", "7", ], - ConvertTypes[int], ] | None ) = None, @@ -9614,70 +9752,30 @@ def __init__( self.severity = severity return super().__init__(**kwargs) - console: Literal["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"] | None = None + console: ( + Annotated[str, ValidValues["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"]] + | None + ) = None """Console logging severity level.""" - monitor: Literal["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"] | None = None + monitor: ( + Annotated[str, ValidValues["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"]] + | None + ) = None """Monitor logging severity level.""" buffered: Buffered | None = None - trap: Literal["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "system", "warnings", "disabled"] | None = ( - None - ) + trap: ( + Annotated[ + str, ValidValues["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "system", "warnings", "disabled"] + ] + | None + ) = None """Trap logging severity level.""" synchronous: Synchronous | None = None format: Format | None = None facility: ( - Literal[ - "auth", - "cron", - "daemon", - "kern", - "local0", - "local1", - "local2", - "local3", - "local4", - "local5", - "local6", - "local7", - "lpr", - "mail", - "news", - "sys9", - "sys10", - "sys11", - "sys12", - "sys13", - "sys14", - "syslog", - "user", - "uucp", - ] - | None - ) = None - source_interface: str | None = None - """Source Interface Name.""" - vrfs: list[VrfsItem] | None = None - policy: Policy | None = None - event: Event | None = None - level: list[LevelItem] | None = None - """Configure logging severity.""" - - def __init__( - self, - console: ( - Literal["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"] | None - ) = None, - monitor: ( - Literal["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"] | None - ) = None, - buffered: Buffered | None = None, - trap: ( - Literal["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "system", "warnings", "disabled"] | None - ) = None, - synchronous: Synchronous | None = None, - format: Format | None = None, - facility: ( - Literal[ + Annotated[ + str, + ValidValues[ "auth", "cron", "daemon", @@ -9702,6 +9800,71 @@ def __init__( "syslog", "user", "uucp", + ], + ] + | None + ) = None + source_interface: str | None = None + """Source Interface Name.""" + vrfs: list[VrfsItem] | None = None + policy: Policy | None = None + event: Event | None = None + level: list[LevelItem] | None = None + """Configure logging severity.""" + + def __init__( + self, + console: ( + Annotated[ + str, ValidValues["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"] + ] + | None + ) = None, + monitor: ( + Annotated[ + str, ValidValues["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"] + ] + | None + ) = None, + buffered: Buffered | None = None, + trap: ( + Annotated[ + str, + ValidValues["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "system", "warnings", "disabled"], + ] + | None + ) = None, + synchronous: Synchronous | None = None, + format: Format | None = None, + facility: ( + Annotated[ + str, + ValidValues[ + "auth", + "cron", + "daemon", + "kern", + "local0", + "local1", + "local2", + "local3", + "local4", + "local5", + "local6", + "local7", + "lpr", + "mail", + "news", + "sys9", + "sys10", + "sys11", + "sys12", + "sys13", + "sys14", + "syslog", + "user", + "uucp", + ], ] | None ) = None, @@ -9790,7 +9953,7 @@ def __init__(self, ipv4_index: int | None = None, ipv6_index: int | None = None, """Loopback interface name e.g. "Loopback0".""" description: str | None = None shutdown: bool | None = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF name.""" ip_address: str | None = None """IPv4_address/Mask.""" @@ -9799,7 +9962,7 @@ def __init__(self, ipv4_index: int | None = None, ipv6_index: int | None = None, ipv6_address: str | None = None """IPv6_address/Mask.""" ip_proxy_arp: bool | None = None - ospf_area: Annotated[str, ConvertTypes[int]] | None = None + ospf_area: str | None = None mpls: Mpls | None = None isis_enable: str | None = None """ISIS instance name.""" @@ -9817,13 +9980,13 @@ def __init__( name: str = None, description: str | None = None, shutdown: bool | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, ip_address: str | None = None, ip_address_secondaries: list[str] | None = None, ipv6_enable: bool | None = None, ipv6_address: str | None = None, ip_proxy_arp: bool | None = None, - ospf_area: Annotated[str, ConvertTypes[int]] | None = None, + ospf_area: str | None = None, mpls: Mpls | None = None, isis_enable: str | None = None, isis_bfd: bool | None = None, @@ -9894,14 +10057,12 @@ def __init__(self, sequence: int | None = None, action: str | None = None, **kwa self.action = action return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """MAC Access-list Name.""" counters_per_entry: bool | None = None entries: list[EntriesItem] | None = None - def __init__( - self, name: Annotated[str, ConvertTypes[int]] = None, counters_per_entry: bool | None = None, entries: list[EntriesItem] | None = None, **kwargs - ): + def __init__(self, name: str = None, counters_per_entry: bool | None = None, entries: list[EntriesItem] | None = None, **kwargs): """ Args: ----- @@ -10033,9 +10194,9 @@ def __init__(self, key_server_priority: int | None = None, session: Session | No class L2Protocols(AvdDictBaseModel): class EthernetFlowControl(AvdDictBaseModel): - mode: Literal["encrypt", "bypass"] = None + mode: Annotated[str, ValidValues["encrypt", "bypass"]] = None - def __init__(self, mode: Literal["encrypt", "bypass"] = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["encrypt", "bypass"]] = None, **kwargs): """ Args: ----- @@ -10046,9 +10207,9 @@ def __init__(self, mode: Literal["encrypt", "bypass"] = None, **kwargs): return super().__init__(**kwargs) class Lldp(AvdDictBaseModel): - mode: Literal["bypass", "bypass unauthorized"] = None + mode: Annotated[str, ValidValues["bypass", "bypass unauthorized"]] = None - def __init__(self, mode: Literal["bypass", "bypass unauthorized"] = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["bypass", "bypass unauthorized"]] = None, **kwargs): """ Args: ----- @@ -10074,12 +10235,12 @@ def __init__(self, ethernet_flow_control: EthernetFlowControl | None = None, lld return super().__init__(**kwargs) class TrafficUnprotected(AvdDictBaseModel): - action: Literal["allow", "drop"] = None + action: Annotated[str, ValidValues["allow", "drop"]] = None """Allow/drop the transmit/receive of unprotected traffic.""" allow_active_sak: bool | None = None """Allow transmit/receive of encrypted traffic using operational SAK and block otherwise.""" - def __init__(self, action: Literal["allow", "drop"] = None, allow_active_sak: bool | None = None, **kwargs): + def __init__(self, action: Annotated[str, ValidValues["allow", "drop"]] = None, allow_active_sak: bool | None = None, **kwargs): """ Args: ----- @@ -10093,7 +10254,7 @@ def __init__(self, action: Literal["allow", "drop"] = None, allow_active_sak: bo name: str = None """Profile-Name.""" - cipher: Literal["aes128-gcm", "aes128-gcm-xpn", "aes256-gcm", "aes256-gcm-xpn"] | None = None + cipher: Annotated[str, ValidValues["aes128-gcm", "aes128-gcm-xpn", "aes256-gcm", "aes256-gcm-xpn"]] | None = None connection_keys: list[ConnectionKeysItem] | None = None mka: Mka | None = None sci: bool | None = None @@ -10103,7 +10264,7 @@ def __init__(self, action: Literal["allow", "drop"] = None, allow_active_sak: bo def __init__( self, name: str = None, - cipher: Literal["aes128-gcm", "aes128-gcm-xpn", "aes256-gcm", "aes256-gcm-xpn"] | None = None, + cipher: Annotated[str, ValidValues["aes128-gcm", "aes128-gcm-xpn", "aes256-gcm", "aes256-gcm-xpn"]] | None = None, connection_keys: list[ConnectionKeysItem] | None = None, mka: Mka | None = None, sci: bool | None = None, @@ -10380,9 +10541,9 @@ class GrpcItem(AvdDictBaseModel): """Transport name.""" ssl_profile: str | None = None """SSL profile name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF name is optional.""" - notification_timestamp: Literal["send-time", "last-change-time"] | None = None + notification_timestamp: Annotated[str, ValidValues["send-time", "last-change-time"]] | None = None """ Per the gNMI specification, the default timestamp field of a notification message is set to be the time at which the @@ -10405,8 +10566,8 @@ def __init__( self, name: str | None = None, ssl_profile: str | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, - notification_timestamp: Literal["send-time", "last-change-time"] | None = None, + vrf: str | None = None, + notification_timestamp: Annotated[str, ValidValues["send-time", "last-change-time"]] | None = None, ip_access_group: str | None = None, port: int | None = None, **kwargs, @@ -10503,7 +10664,7 @@ def __init__(self, use_serial_number: bool | None = None, target_ids: list[str] """Tunnel SSL profile name.""" gnmi_ssl_profile: str | None = None """gNMI SSL profile name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF name.""" destination: Destination | None = None local_interface: LocalInterface | None = None @@ -10515,7 +10676,7 @@ def __init__( shutdown: bool | None = None, tunnel_ssl_profile: str | None = None, gnmi_ssl_profile: str | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, destination: Destination | None = None, local_interface: LocalInterface | None = None, target: Target | None = None, @@ -10560,12 +10721,12 @@ def __init__(self, grpc: list[GrpcItem] | None = None, grpc_tunnels: list[GrpcTu return super().__init__(**kwargs) class EnableVrfsItem(AvdDictBaseModel): - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF name.""" access_group: str | None = None """Standard IPv4 ACL name.""" - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, access_group: str | None = None, **kwargs): + def __init__(self, name: str = None, access_group: str | None = None, **kwargs): """ Args: ----- @@ -10616,14 +10777,14 @@ def __init__( class ManagementApiHttp(AvdDictBaseModel): class EnableVrfsItem(AvdDictBaseModel): - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF Name.""" access_group: str | None = None """Standard IPv4 ACL name.""" ipv6_access_group: str | None = None """Standard IPv6 ACL name.""" - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, access_group: str | None = None, ipv6_access_group: str | None = None, **kwargs): + def __init__(self, name: str = None, access_group: str | None = None, ipv6_access_group: str | None = None, **kwargs): """ Args: ----- @@ -10711,10 +10872,10 @@ def __init__(self, path: str | None = None, disabled: bool | None = False, **kwa self.disabled = disabled return super().__init__(**kwargs) - name: Literal["sysdb", "smash"] | None = None + name: Annotated[str, ValidValues["sysdb", "smash"]] | None = None paths: list[PathsItem] | None = None - def __init__(self, name: Literal["sysdb", "smash"] | None = None, paths: list[PathsItem] | None = None, **kwargs): + def __init__(self, name: Annotated[str, ValidValues["sysdb", "smash"]] | None = None, paths: list[PathsItem] | None = None, **kwargs): """ Args: ----- @@ -10756,16 +10917,11 @@ class ManagementCvx(AvdDictBaseModel): server_hosts: list[str] | None = None source_interface: str | None = None """Interface name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name.""" def __init__( - self, - shutdown: bool | None = None, - server_hosts: list[str] | None = None, - source_interface: str | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, - **kwargs, + self, shutdown: bool | None = None, server_hosts: list[str] | None = None, source_interface: str | None = None, vrf: str | None = None, **kwargs ): """ Args: @@ -10784,9 +10940,9 @@ def __init__( class ManagementDefaults(AvdDictBaseModel): class Secret(AvdDictBaseModel): - hash: Literal["md5", "sha512"] | None = None + hash: Annotated[str, ValidValues["md5", "sha512"]] | None = None - def __init__(self, hash: Literal["md5", "sha512"] | None = None, **kwargs): + def __init__(self, hash: Annotated[str, ValidValues["md5", "sha512"]] | None = None, **kwargs): """ Args: ----- @@ -10836,14 +10992,14 @@ def __init__(self, transmit: bool | None = None, receive: bool | None = None, zt speed: str | None = None """Speed should be set in the format `` or `forced ` or `auto `.""" mtu: int | None = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name.""" ip_address: str | None = None """IPv4_address/Mask.""" ipv6_enable: bool | None = None ipv6_address: str | None = None """IPv6_address/Mask.""" - type: Literal["oob", "inband"] | None = "oob" + type: Annotated[str, ValidValues["oob", "inband"]] | None = "oob" """For documentation purposes only.""" gateway: str | None = None """IPv4 address of default gateway in management VRF.""" @@ -10862,11 +11018,11 @@ def __init__( shutdown: bool | None = None, speed: str | None = None, mtu: int | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, ip_address: str | None = None, ipv6_enable: bool | None = None, ipv6_address: str | None = None, - type: Literal["oob", "inband"] | None = "oob", + type: Annotated[str, ValidValues["oob", "inband"]] | None = "oob", gateway: str | None = None, ipv6_gateway: str | None = None, mac_address: str | None = None, @@ -11159,7 +11315,7 @@ def __init__(self, file: str | None = None, key: str | None = None, **kwargs): return super().__init__(**kwargs) name: str | None = None - tls_versions: Annotated[str, ConvertTypes[float]] | None = None + tls_versions: str | None = None """ List of allowed TLS versions as string. Examples: @@ -11184,7 +11340,7 @@ def __init__(self, file: str | None = None, key: str | None = None, **kwargs): def __init__( self, name: str | None = None, - tls_versions: Annotated[str, ConvertTypes[float]] | None = None, + tls_versions: str | None = None, cipher_list: str | None = None, trust_certificate: TrustCertificate | None = None, chain_certificate: ChainCertificate | None = None, @@ -11320,7 +11476,7 @@ def __init__(self, infinite: bool | None = None, start_date_time: str | None = N name: str = None secret: str = None - secret_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = "7" + secret_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = "7" receive_lifetime: ReceiveLifetime = None transmit_lifetime: TransmitLifetime = None local_time: bool | None = None @@ -11330,7 +11486,7 @@ def __init__( self, name: str = None, secret: str = None, - secret_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = "7", + secret_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = "7", receive_lifetime: ReceiveLifetime = None, transmit_lifetime: TransmitLifetime = None, local_time: bool | None = None, @@ -11407,10 +11563,10 @@ class ManagementSsh(AvdDictBaseModel): class AccessGroupsItem(AvdDictBaseModel): name: str | None = None """Standard ACL Name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name.""" - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -11425,10 +11581,10 @@ def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int class Ipv6AccessGroupsItem(AvdDictBaseModel): name: str | None = None """Standard ACL Name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name.""" - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -11481,12 +11637,12 @@ def __init__(self, limit: int | None = None, per_host: int | None = None, **kwar return super().__init__(**kwargs) class VrfsItem(AvdDictBaseModel): - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF Name.""" enable: bool | None = None """Enable SSH in VRF.""" - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, enable: bool | None = None, **kwargs): + def __init__(self, name: str = None, enable: bool | None = None, **kwargs): """ Args: ----- @@ -11592,10 +11748,10 @@ class PolicyShowTechSupport(AvdDictBaseModel): class ExcludeCommandsItem(AvdDictBaseModel): command: str | None = None """Command to exclude from tech-support.""" - type: Literal["text", "json"] | None = "text" + type: Annotated[str, ValidValues["text", "json"]] | None = "text" """The supported values for type are platform dependent.""" - def __init__(self, command: str | None = None, type: Literal["text", "json"] | None = "text", **kwargs): + def __init__(self, command: str | None = None, type: Annotated[str, ValidValues["text", "json"]] | None = "text", **kwargs): """ Args: ----- @@ -12013,11 +12169,9 @@ class AvtsItem(AvdDictBaseModel): class Constraints(AvdDictBaseModel): jitter: int | None = None latency: int | None = None - lossrate: Annotated[str, ConvertTypes[float]] | None = None + lossrate: str | None = None - def __init__( - self, jitter: int | None = None, latency: int | None = None, lossrate: Annotated[str, ConvertTypes[float]] | None = None, **kwargs - ): + def __init__(self, jitter: int | None = None, latency: int | None = None, lossrate: str | None = None, **kwargs): """ Args: ----- @@ -12286,10 +12440,10 @@ class MlagConfiguration(AvdDictBaseModel): class PeerAddressHeartbeat(AvdDictBaseModel): peer_ip: str | None = None """IPv4 or IPv6 Address.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name.""" - def __init__(self, peer_ip: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, peer_ip: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -12317,9 +12471,9 @@ def __init__(self, peer_ip: str | None = None, vrf: Annotated[str, ConvertTypes[ """Delay in seconds.""" peer_link: str | None = None """Port-Channel interface name.""" - reload_delay_mlag: Annotated[str, ConvertTypes[int]] | None = None + reload_delay_mlag: str | None = None """Delay in seconds <0-86400> or 'infinity'.""" - reload_delay_non_mlag: Annotated[str, ConvertTypes[int]] | None = None + reload_delay_non_mlag: str | None = None """Delay in seconds <0-86400> or 'infinity'.""" def __init__( @@ -12333,8 +12487,8 @@ def __init__( dual_primary_recovery_delay_mlag: int | None = None, dual_primary_recovery_delay_non_mlag: int | None = None, peer_link: str | None = None, - reload_delay_mlag: Annotated[str, ConvertTypes[int]] | None = None, - reload_delay_non_mlag: Annotated[str, ConvertTypes[int]] | None = None, + reload_delay_mlag: str | None = None, + reload_delay_non_mlag: str | None = None, **kwargs, ): """ @@ -12516,7 +12670,7 @@ def __init__( self.url = url return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF Name.""" description: str | None = None interface_sets: list[InterfaceSetsItem] | None = None @@ -12535,7 +12689,7 @@ def __init__( def __init__( self, - name: Annotated[str, ConvertTypes[int]] = None, + name: str = None, description: str | None = None, interface_sets: list[InterfaceSetsItem] | None = None, local_interfaces: str | None = None, @@ -12672,12 +12826,14 @@ def __init__(self, enabled: bool = None, logging_mac_fault: bool | None = None, class MonitorSessionsItem(AvdDictBaseModel): class SourcesItem(AvdDictBaseModel): class AccessGroup(AvdDictBaseModel): - type: Literal["ip", "ipv6", "mac"] | None = None + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None name: str | None = None """ACL Name.""" priority: int | None = None - def __init__(self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | None = None, priority: int | None = None, **kwargs): + def __init__( + self, type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None, name: str | None = None, priority: int | None = None, **kwargs + ): """ Args: ----- @@ -12693,11 +12849,15 @@ def __init__(self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | name: str | None = None """Interface name, range or comma separated list.""" - direction: Literal["rx", "tx", "both"] | None = None + direction: Annotated[str, ValidValues["rx", "tx", "both"]] | None = None access_group: AccessGroup | None = None def __init__( - self, name: str | None = None, direction: Literal["rx", "tx", "both"] | None = None, access_group: AccessGroup | None = None, **kwargs + self, + name: str | None = None, + direction: Annotated[str, ValidValues["rx", "tx", "both"]] | None = None, + access_group: AccessGroup | None = None, + **kwargs, ): """ Args: @@ -12713,11 +12873,11 @@ def __init__( return super().__init__(**kwargs) class AccessGroup(AvdDictBaseModel): - type: Literal["ip", "ipv6", "mac"] | None = None + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None name: str | None = None """ACL Name.""" - def __init__(self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | None = None, **kwargs): + def __init__(self, type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None, name: str | None = None, **kwargs): """ Args: ----- @@ -12831,21 +12991,21 @@ class DestinationsItem(AvdDictBaseModel): database: str | None = None """Set name of the database.""" data_retention_policy: str | None = None - url: Annotated[str, Pattern["(http(s)?|udp|unix)://.+"]] | None = None + url: Annotated[str, Pattern[r"(http(s)?|udp|unix)://.+"]] | None = None """It only accepts http(s), udp and unix domain destination URL.""" username: str | None = None password: str | None = None - password_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = "7" + password_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = "7" def __init__( self, name: str = None, database: str | None = None, data_retention_policy: str | None = None, - url: Annotated[str, Pattern["(http(s)?|udp|unix)://.+"]] | None = None, + url: Annotated[str, Pattern[r"(http(s)?|udp|unix)://.+"]] | None = None, username: str | None = None, password: str | None = None, - password_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = "7", + password_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = "7", **kwargs, ): """ @@ -12873,11 +13033,11 @@ class SourceSocketsItem(AvdDictBaseModel): name: str = None """Label of the socket connection.""" connection_limit: int | None = None - url: Annotated[str, Pattern["(http(s)?|udp|unix)://.+"]] | None = None + url: Annotated[str, Pattern[r"(http(s)?|udp|unix)://.+"]] | None = None """It only accepts http(s), udp and unix domain socket URL.""" def __init__( - self, name: str = None, connection_limit: int | None = None, url: Annotated[str, Pattern["(http(s)?|udp|unix)://.+"]] | None = None, **kwargs + self, name: str = None, connection_limit: int | None = None, url: Annotated[str, Pattern[r"(http(s)?|udp|unix)://.+"]] | None = None, **kwargs ): """ Args: @@ -12952,10 +13112,10 @@ class Collection(AvdDictBaseModel): """Source IP address of GRE tunnel.""" destination: str | None = None """Destination IP address of GRE tunnel.""" - version: Literal[1, 2] | None = None + version: int | None = None """Postcard version.""" - def __init__(self, source: str | None = None, destination: str | None = None, version: Literal[1, 2] | None = None, **kwargs): + def __init__(self, source: str | None = None, destination: str | None = None, version: int | None = None, **kwargs): """ Args: ----- @@ -12988,12 +13148,12 @@ def __init__(self, value: int | None = None, mask: str | None = None, **kwargs): self.mask = mask return super().__init__(**kwargs) - rate: Literal[16384, 32768, 65536] | None = None + rate: int | None = None """Sampling rate. `rate` is preferred when both `rate` and `tcp_udp_checksum` are defined.""" tcp_udp_checksum: TcpUdpChecksum | None = None """TCP/UDP parameters.""" - def __init__(self, rate: Literal[16384, 32768, 65536] | None = None, tcp_udp_checksum: TcpUdpChecksum | None = None, **kwargs): + def __init__(self, rate: int | None = None, tcp_udp_checksum: TcpUdpChecksum | None = None, **kwargs): """ Args: ----- @@ -13059,8 +13219,8 @@ def __init__(self, name: str = None, ingress_sample_policy: str | None = None, * class SamplePoliciesItem(AvdDictBaseModel): class MatchRulesItem(AvdDictBaseModel): class ProtocolsItem(AvdDictBaseModel): - protocol: Literal["tcp", "udp"] = None - source_ports: list[Annotated[str, ConvertTypes[int]]] | None = None + protocol: Annotated[str, ValidValues["tcp", "udp"]] = None + source_ports: list[str] | None = None """ A list of port numbers or port range or port name. Combination of port numbers or range and port name is not supported on EOS. The port numbers should be in range of 0-65535. @@ -13068,7 +13228,7 @@ class ProtocolsItem(AvdDictBaseModel): [ "12", "14-20" ] [ "www" ] """ - destination_ports: list[Annotated[str, ConvertTypes[int]]] | None = None + destination_ports: list[str] | None = None """ A list of port numbers or port range or port name. Combination of port numbers or range and port name is not supported on EOS. The port numbers should be in range of 0-65535. @@ -13079,9 +13239,9 @@ class ProtocolsItem(AvdDictBaseModel): def __init__( self, - protocol: Literal["tcp", "udp"] = None, - source_ports: list[Annotated[str, ConvertTypes[int]]] | None = None, - destination_ports: list[Annotated[str, ConvertTypes[int]]] | None = None, + protocol: Annotated[str, ValidValues["tcp", "udp"]] = None, + source_ports: list[str] | None = None, + destination_ports: list[str] | None = None, **kwargs, ): """ @@ -13108,7 +13268,7 @@ def __init__( return super().__init__(**kwargs) name: str = None - type: Literal["ipv4", "ipv6"] = None + type: Annotated[str, ValidValues["ipv4", "ipv6"]] = None """IP address version.""" destination_prefix: str | None = None """ @@ -13125,7 +13285,7 @@ def __init__( def __init__( self, name: str = None, - type: Literal["ipv4", "ipv6"] = None, + type: Annotated[str, ValidValues["ipv4", "ipv6"]] = None, destination_prefix: str | None = None, source_prefix: str | None = None, protocols: list[ProtocolsItem] | None = None, @@ -13249,10 +13409,10 @@ def __init__(self, ip: bool | None = None, ldp: Ldp | None = None, **kwargs): class NameServer(AvdDictBaseModel): class Source(AvdDictBaseModel): - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name.""" - def __init__(self, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, vrf: str | None = None, **kwargs): """ Args: ----- @@ -13281,10 +13441,10 @@ class Ntp(AvdDictBaseModel): class LocalInterface(AvdDictBaseModel): name: str | None = None """Source interface.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF name.""" - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -13310,7 +13470,7 @@ class ServersItem(AvdDictBaseModel): """Value of minpoll between 3 - 17 (Logarithmic).""" preferred: bool | None = None version: int | None = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF name.""" def __init__( @@ -13324,7 +13484,7 @@ def __init__( minpoll: int | None = None, preferred: bool | None = None, version: int | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, **kwargs, ): """ @@ -13357,17 +13517,17 @@ def __init__( class AuthenticationKeysItem(AvdDictBaseModel): id: int = None """Key identifier.""" - hash_algorithm: Literal["md5", "sha1"] | None = None + hash_algorithm: Annotated[str, ValidValues["md5", "sha1"]] | None = None key: str | None = None """Obfuscated key.""" - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = None + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = None def __init__( self, id: int = None, - hash_algorithm: Literal["md5", "sha1"] | None = None, + hash_algorithm: Annotated[str, ValidValues["md5", "sha1"]] | None = None, key: str | None = None, - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = None, + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = None, **kwargs, ): """ @@ -13390,7 +13550,7 @@ def __init__( authenticate: bool | None = None authenticate_servers_only: bool | None = None authentication_keys: list[AuthenticationKeysItem] | None = None - trusted_keys: Annotated[str, ConvertTypes[int]] | None = None + trusted_keys: str | None = None """List of trusted-keys as string ex. 10-12,15.""" def __init__( @@ -13400,7 +13560,7 @@ def __init__( authenticate: bool | None = None, authenticate_servers_only: bool | None = None, authentication_keys: list[AuthenticationKeysItem] | None = None, - trusted_keys: Annotated[str, ConvertTypes[int]] | None = None, + trusted_keys: str | None = None, **kwargs, ): """ @@ -13498,8 +13658,8 @@ def __init__(self, interface: Interface | None = None, **kwargs): class PatchesItem(AvdDictBaseModel): class ConnectorsItem(AvdDictBaseModel): - id: Annotated[str, ConvertTypes[int]] = None - type: Literal["interface", "pseudowire"] = None + id: str = None + type: Annotated[str, ValidValues["interface", "pseudowire"]] = None endpoint: str = None """ String with relevant endpoint depending on type. @@ -13511,9 +13671,7 @@ class ConnectorsItem(AvdDictBaseModel): - "ldp LDP_PW_1" """ - def __init__( - self, id: Annotated[str, ConvertTypes[int]] = None, type: Literal["interface", "pseudowire"] = None, endpoint: str = None, **kwargs - ): + def __init__(self, id: str = None, type: Annotated[str, ValidValues["interface", "pseudowire"]] = None, endpoint: str = None, **kwargs): """ Args: ----- @@ -13614,14 +13772,14 @@ class Mmu(AvdDictBaseModel): class QueueProfilesItem(AvdDictBaseModel): class MulticastQueuesItem(AvdDictBaseModel): class Drop(AvdDictBaseModel): - precedence: Literal[1, 2] = None - threshold: Annotated[str, ConvertTypes[int]] = None + precedence: int = None + threshold: str = None """ Drop Threshold. This value may also be fractions. Example: 7/8 or 3/4 or 1/2 """ - def __init__(self, precedence: Literal[1, 2] = None, threshold: Annotated[str, ConvertTypes[int]] = None, **kwargs): + def __init__(self, precedence: int = None, threshold: str = None, **kwargs): """ Args: ----- @@ -13636,23 +13794,23 @@ def __init__(self, precedence: Literal[1, 2] = None, threshold: Annotated[str, C return super().__init__(**kwargs) id: int = None - unit: Literal["bytes", "cells"] | None = None + unit: Annotated[str, ValidValues["bytes", "cells"]] | None = None """Unit to be used for the reservation value. If not specified, default is bytes.""" reserved: int | None = None """ Amount of memory that should be reserved for this queue. """ - threshold: Annotated[str, ConvertTypes[int]] | None = None + threshold: str | None = None """Dynamic Shared Memory threshold.""" drop: Drop | None = None def __init__( self, id: int = None, - unit: Literal["bytes", "cells"] | None = None, + unit: Annotated[str, ValidValues["bytes", "cells"]] | None = None, reserved: int | None = None, - threshold: Annotated[str, ConvertTypes[int]] | None = None, + threshold: str | None = None, drop: Drop | None = None, **kwargs, ): @@ -13677,14 +13835,14 @@ def __init__( class UnicastQueuesItem(AvdDictBaseModel): class Drop(AvdDictBaseModel): - precedence: Literal[1, 2] = None - threshold: Annotated[str, ConvertTypes[int]] = None + precedence: int = None + threshold: str = None """ Drop Threshold. This value may also be fractions. Example: 7/8 or 3/4 or 1/2 """ - def __init__(self, precedence: Literal[1, 2] = None, threshold: Annotated[str, ConvertTypes[int]] = None, **kwargs): + def __init__(self, precedence: int = None, threshold: str = None, **kwargs): """ Args: ----- @@ -13699,23 +13857,23 @@ def __init__(self, precedence: Literal[1, 2] = None, threshold: Annotated[str, C return super().__init__(**kwargs) id: int = None - unit: Literal["bytes", "cells"] | None = None + unit: Annotated[str, ValidValues["bytes", "cells"]] | None = None """Unit to be used for the reservation value. If not specified, default is bytes.""" reserved: int | None = None """ Amount of memory that should be reserved for this queue. """ - threshold: Annotated[str, ConvertTypes[int]] | None = None + threshold: str | None = None """Dynamic Shared Memory threshold.""" drop: Drop | None = None def __init__( self, id: int = None, - unit: Literal["bytes", "cells"] | None = None, + unit: Annotated[str, ValidValues["bytes", "cells"]] | None = None, reserved: int | None = None, - threshold: Annotated[str, ConvertTypes[int]] | None = None, + threshold: str | None = None, drop: Drop | None = None, **kwargs, ): @@ -13778,11 +13936,11 @@ def __init__(self, active_profile: str | None = None, queue_profiles: list[Queue self.queue_profiles = queue_profiles return super().__init__(**kwargs) - forwarding_table_partition: Annotated[str, ConvertTypes[int]] | None = None + forwarding_table_partition: str | None = None mmu: Mmu | None = None """Memory Management Unit settings.""" - def __init__(self, forwarding_table_partition: Annotated[str, ConvertTypes[int]] | None = None, mmu: Mmu | None = None, **kwargs): + def __init__(self, forwarding_table_partition: str | None = None, mmu: Mmu | None = None, **kwargs): """ Args: ----- @@ -13828,9 +13986,9 @@ def __init__(self, hardware_only: bool | None = None, mode: str | None = None, * return super().__init__(**kwargs) class MulticastReplication(AvdDictBaseModel): - default: Literal["ingress", "egress"] | None = None + default: Annotated[str, ValidValues["ingress", "egress"]] | None = None - def __init__(self, default: Literal["ingress", "egress"] | None = None, **kwargs): + def __init__(self, default: Annotated[str, ValidValues["ingress", "egress"]] | None = None, **kwargs): """ Args: ----- @@ -13844,7 +14002,7 @@ def __init__(self, default: Literal["ingress", "egress"] | None = None, **kwargs lag: Lag | None = None forwarding_mode: str | None = None multicast_replication: MulticastReplication | None = None - mdb_profile: Literal["balanced", "balanced-xl", "l3", "l3-xl", "l3-xxl", "l3-xxxl"] | None = None + mdb_profile: Annotated[str, ValidValues["balanced", "balanced-xl", "l3", "l3-xl", "l3-xxl", "l3-xxxl"]] | None = None """Sand platforms MDB Profile configuration. Note: l3-xxxl does not support MLAG.""" def __init__( @@ -13853,7 +14011,7 @@ def __init__( lag: Lag | None = None, forwarding_mode: str | None = None, multicast_replication: MulticastReplication | None = None, - mdb_profile: Literal["balanced", "balanced-xl", "l3", "l3-xl", "l3-xxl", "l3-xxxl"] | None = None, + mdb_profile: Annotated[str, ValidValues["balanced", "balanced-xl", "l3", "l3-xl", "l3-xxl", "l3-xxxl"]] | None = None, **kwargs, ): """ @@ -13909,10 +14067,10 @@ def __init__(self, trident: Trident | None = None, sand: Sand | None = None, sfe class Poe(AvdDictBaseModel): class Reboot(AvdDictBaseModel): - action: Literal["power-off", "maintain"] | None = None + action: Annotated[str, ValidValues["power-off", "maintain"]] | None = None """PoE action for interface. By default in EOS, reboot action is set to power-off.""" - def __init__(self, action: Literal["power-off", "maintain"] | None = None, **kwargs): + def __init__(self, action: Annotated[str, ValidValues["power-off", "maintain"]] | None = None, **kwargs): """ Args: ----- @@ -13923,10 +14081,10 @@ def __init__(self, action: Literal["power-off", "maintain"] | None = None, **kwa return super().__init__(**kwargs) class InterfaceShutdown(AvdDictBaseModel): - action: Literal["power-off", "maintain"] | None = None + action: Annotated[str, ValidValues["power-off", "maintain"]] | None = None """PoE action for interface. By default in EOS, interface shutdown action is set to maintain.""" - def __init__(self, action: Literal["power-off", "maintain"] | None = None, **kwargs): + def __init__(self, action: Annotated[str, ValidValues["power-off", "maintain"]] | None = None, **kwargs): """ Args: ----- @@ -14035,17 +14193,12 @@ class QosItem(AvdDictBaseModel): class ClassesItem(AvdDictBaseModel): class Set(AvdDictBaseModel): cos: int | None = None - dscp: Annotated[str, ConvertTypes[int]] | None = None + dscp: str | None = None traffic_class: int | None = None drop_precedence: int | None = None def __init__( - self, - cos: int | None = None, - dscp: Annotated[str, ConvertTypes[int]] | None = None, - traffic_class: int | None = None, - drop_precedence: int | None = None, - **kwargs, + self, cos: int | None = None, dscp: str | None = None, traffic_class: int | None = None, drop_precedence: int | None = None, **kwargs ): """ Args: @@ -14064,14 +14217,12 @@ def __init__( class Police(AvdDictBaseModel): class Action(AvdDictBaseModel): - type: Literal["dscp", "drop-precedence"] | None = None + type: Annotated[str, ValidValues["dscp", "drop-precedence"]] | None = None """Set action for policed traffic.""" - dscp_value: Annotated[str, ConvertTypes[int]] | None = None + dscp_value: str | None = None """Set when action.type is set to "dscp".""" - def __init__( - self, type: Literal["dscp", "drop-precedence"] | None = None, dscp_value: Annotated[str, ConvertTypes[int]] | None = None, **kwargs - ): + def __init__(self, type: Annotated[str, ValidValues["dscp", "drop-precedence"]] | None = None, dscp_value: str | None = None, **kwargs): """ Args: ----- @@ -14088,32 +14239,32 @@ def __init__( Specify rate. Range in kbps <8-200000000>. """ - rate_unit: Literal["bps", "kbps", "mbps", "pps"] | None = "bps" + rate_unit: Annotated[str, ValidValues["bps", "kbps", "mbps", "pps"]] | None = "bps" rate_burst_size: int | None = None """Range in bytes <256-128000000>.""" - rate_burst_size_unit: Literal["bytes", "kbytes", "mbytes", "packets"] | None = "bytes" + rate_burst_size_unit: Annotated[str, ValidValues["bytes", "kbytes", "mbytes", "packets"]] | None = "bytes" action: Action | None = None higher_rate: int | None = None """ Specify higher rate. Range in kbps . """ - higher_rate_unit: Literal["bps", "kbps", "mbps", "pps"] | None = "bps" + higher_rate_unit: Annotated[str, ValidValues["bps", "kbps", "mbps", "pps"]] | None = "bps" higher_rate_burst_size: int | None = None """Range in bytes <256-128000000>.""" - higher_rate_burst_size_unit: Literal["bytes", "kbytes", "mbytes", "packets"] | None = "bytes" + higher_rate_burst_size_unit: Annotated[str, ValidValues["bytes", "kbytes", "mbytes", "packets"]] | None = "bytes" def __init__( self, rate: int | None = None, - rate_unit: Literal["bps", "kbps", "mbps", "pps"] | None = "bps", + rate_unit: Annotated[str, ValidValues["bps", "kbps", "mbps", "pps"]] | None = "bps", rate_burst_size: int | None = None, - rate_burst_size_unit: Literal["bytes", "kbytes", "mbytes", "packets"] | None = "bytes", + rate_burst_size_unit: Annotated[str, ValidValues["bytes", "kbytes", "mbytes", "packets"]] | None = "bytes", action: Action | None = None, higher_rate: int | None = None, - higher_rate_unit: Literal["bps", "kbps", "mbps", "pps"] | None = "bps", + higher_rate_unit: Annotated[str, ValidValues["bps", "kbps", "mbps", "pps"]] | None = "bps", higher_rate_burst_size: int | None = None, - higher_rate_burst_size_unit: Literal["bytes", "kbytes", "mbytes", "packets"] | None = "bytes", + higher_rate_burst_size_unit: Annotated[str, ValidValues["bytes", "kbytes", "mbytes", "packets"]] | None = "bytes", **kwargs, ): """ @@ -14187,11 +14338,16 @@ class ClassesItem(AvdDictBaseModel): """Maximum rate limit.""" bandwidth: int | None = None """Minimum bandwidth.""" - rate_unit: Literal["pps", "kbps"] | None = None + rate_unit: Annotated[str, ValidValues["pps", "kbps"]] | None = None """The `rate_unit` must be defined for `shape` and `bandwidth`.""" def __init__( - self, name: str = None, shape: int | None = None, bandwidth: int | None = None, rate_unit: Literal["pps", "kbps"] | None = None, **kwargs + self, + name: str = None, + shape: int | None = None, + bandwidth: int | None = None, + rate_unit: Annotated[str, ValidValues["pps", "kbps"]] | None = None, + **kwargs, ): """ Args: @@ -14368,9 +14524,9 @@ def __init__(self, client: Client | None = None, network: Network | None = None, class LinkTrackingGroupsItem(AvdDictBaseModel): name: str = None """Group name.""" - direction: Literal["upstream", "downstream"] | None = None + direction: Annotated[str, ValidValues["upstream", "downstream"]] | None = None - def __init__(self, name: str = None, direction: Literal["upstream", "downstream"] | None = None, **kwargs): + def __init__(self, name: str = None, direction: Annotated[str, ValidValues["upstream", "downstream"]] | None = None, **kwargs): """ Args: ----- @@ -14383,10 +14539,10 @@ def __init__(self, name: str = None, direction: Literal["upstream", "downstream" return super().__init__(**kwargs) class Phone(AvdDictBaseModel): - trunk: Literal["tagged", "untagged"] | None = None + trunk: Annotated[str, ValidValues["tagged", "untagged"]] | None = None vlan: int | None = None - def __init__(self, trunk: Literal["tagged", "untagged"] | None = None, vlan: int | None = None, **kwargs): + def __init__(self, trunk: Annotated[str, ValidValues["tagged", "untagged"]] | None = None, vlan: int | None = None, **kwargs): """ Args: ----- @@ -14417,13 +14573,15 @@ def __init__(self, encapsulation_dot1q_vlan: int | None = None, forwarding_profi return super().__init__(**kwargs) class Qos(AvdDictBaseModel): - trust: Literal["dscp", "cos", "disabled"] | None = None + trust: Annotated[str, ValidValues["dscp", "cos", "disabled"]] | None = None dscp: int | None = None """DSCP value.""" cos: int | None = None """COS value.""" - def __init__(self, trust: Literal["dscp", "cos", "disabled"] | None = None, dscp: int | None = None, cos: int | None = None, **kwargs): + def __init__( + self, trust: Annotated[str, ValidValues["dscp", "cos", "disabled"]] | None = None, dscp: int | None = None, cos: int | None = None, **kwargs + ): """ Args: ----- @@ -14575,17 +14733,17 @@ def __init__(self, ip: bool | None = None, ldp: Ldp | None = None, **kwargs): return super().__init__(**kwargs) class VlanTranslationsItem(AvdDictBaseModel): - field_from: Annotated[str, ConvertTypes[int]] | None = None + field_from: str | None = None """List of vlans as string (only one vlan if direction is "both").""" to: int | None = None """VLAN ID.""" - direction: Literal["in", "out", "both"] | None = "both" + direction: Annotated[str, ValidValues["in", "out", "both"]] | None = "both" def __init__( self, - field_from: Annotated[str, ConvertTypes[int]] | None = None, + field_from: str | None = None, to: int | None = None, - direction: Literal["in", "out", "both"] | None = "both", + direction: Annotated[str, ValidValues["in", "out", "both"]] | None = "both", **kwargs, ): """ @@ -14632,12 +14790,12 @@ def __init__(self, rate: str | None = None, **kwargs): class StormControl(AvdDictBaseModel): class All(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional field and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -14650,12 +14808,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class Broadcast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional field and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -14668,12 +14826,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class Multicast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional field and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -14686,12 +14844,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class UnknownUnicast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional field and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -14751,7 +14909,7 @@ def __init__(self, input: str | None = None, output: str | None = None, **kwargs class EvpnEthernetSegment(AvdDictBaseModel): class DesignatedForwarderElection(AvdDictBaseModel): - algorithm: Literal["modulus", "preference"] | None = None + algorithm: Annotated[str, ValidValues["modulus", "preference"]] | None = None preference_value: int | None = None """Preference_value is only used when "algorithm" is "preference".""" dont_preempt: bool | None = False @@ -14762,7 +14920,7 @@ class DesignatedForwarderElection(AvdDictBaseModel): def __init__( self, - algorithm: Literal["modulus", "preference"] | None = None, + algorithm: Annotated[str, ValidValues["modulus", "preference"]] | None = None, preference_value: int | None = None, dont_preempt: bool | None = False, hold_time: int | None = None, @@ -14807,7 +14965,7 @@ def __init__(self, shared_index: int | None = None, tunnel_flood_filter_time: in identifier: str | None = None """EVPN Ethernet Segment Identifier (Type 1 format).""" - redundancy: Literal["all-active", "single-active"] | None = None + redundancy: Annotated[str, ValidValues["all-active", "single-active"]] | None = None designated_forwarder_election: DesignatedForwarderElection | None = None mpls: Mpls | None = None route_target: str | None = None @@ -14816,7 +14974,7 @@ def __init__(self, shared_index: int | None = None, tunnel_flood_filter_time: in def __init__( self, identifier: str | None = None, - redundancy: Literal["all-active", "single-active"] | None = None, + redundancy: Annotated[str, ValidValues["all-active", "single-active"]] | None = None, designated_forwarder_election: DesignatedForwarderElection | None = None, mpls: Mpls | None = None, route_target: str | None = None, @@ -14872,12 +15030,12 @@ def __init__(self, interval: int | None = None, **kwargs): enable: bool | None = None announce: Announce | None = None delay_req: int | None = None - delay_mechanism: Literal["e2e", "p2p"] | None = None + delay_mechanism: Annotated[str, ValidValues["e2e", "p2p"]] | None = None sync_message: SyncMessage | None = None - role: Literal["master", "dynamic"] | None = None - vlan: Annotated[str, ConvertTypes[int]] | None = None + role: Annotated[str, ValidValues["master", "dynamic"]] | None = None + vlan: str | None = None """VLAN can be 'all' or list of vlans as string.""" - transport: Literal["ipv4", "ipv6", "layer2"] | None = None + transport: Annotated[str, ValidValues["ipv4", "ipv6", "layer2"]] | None = None mpass: bool | None = None """ When MPASS is enabled on an MLAG port-channel, MLAG peers coordinate to function as a single PTP logical device. @@ -14892,11 +15050,11 @@ def __init__( enable: bool | None = None, announce: Announce | None = None, delay_req: int | None = None, - delay_mechanism: Literal["e2e", "p2p"] | None = None, + delay_mechanism: Annotated[str, ValidValues["e2e", "p2p"]] | None = None, sync_message: SyncMessage | None = None, - role: Literal["master", "dynamic"] | None = None, - vlan: Annotated[str, ConvertTypes[int]] | None = None, - transport: Literal["ipv4", "ipv6", "layer2"] | None = None, + role: Annotated[str, ValidValues["master", "dynamic"]] | None = None, + vlan: str | None = None, + transport: Annotated[str, ValidValues["ipv4", "ipv6", "layer2"]] | None = None, mpass: bool | None = None, **kwargs, ): @@ -14958,7 +15116,7 @@ class StaticItem(AvdDictBaseModel): access_list: str | None = None """'access_list' and 'group' are mutual exclusive.""" comment: str | None = None - direction: Literal["egress", "ingress"] | None = None + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None """ Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware platform. EOS might @@ -14971,7 +15129,7 @@ class StaticItem(AvdDictBaseModel): original_port: int | None = None """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" priority: int | None = None - protocol: Literal["udp", "tcp"] | None = None + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None translated_ip: str = None """IPv4 address.""" translated_port: int | None = None @@ -14981,12 +15139,12 @@ def __init__( self, access_list: str | None = None, comment: str | None = None, - direction: Literal["egress", "ingress"] | None = None, + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None, group: int | None = None, original_ip: str | None = None, original_port: int | None = None, priority: int | None = None, - protocol: Literal["udp", "tcp"] | None = None, + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None, translated_ip: str = None, translated_port: int | None = None, **kwargs, @@ -15040,7 +15198,7 @@ class Source(AvdDictBaseModel): class DynamicItem(AvdDictBaseModel): access_list: str = None comment: str | None = None - nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] = None + nat_type: Annotated[str, ValidValues["overload", "pool", "pool-address-only", "pool-full-cone"]] = None pool_name: str | None = None """ required if 'nat_type' is pool, pool-address-only or pool-full-cone. @@ -15052,7 +15210,7 @@ def __init__( self, access_list: str = None, comment: str | None = None, - nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] = None, + nat_type: Annotated[str, ValidValues["overload", "pool", "pool-address-only", "pool-full-cone"]] = None, pool_name: str | None = None, priority: int | None = None, **kwargs, @@ -15080,7 +15238,7 @@ class StaticItem(AvdDictBaseModel): access_list: str | None = None """'access_list' and 'group' are mutual exclusive.""" comment: str | None = None - direction: Literal["egress", "ingress"] | None = None + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None """ Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware platform. EOS might @@ -15093,7 +15251,7 @@ class StaticItem(AvdDictBaseModel): original_port: int | None = None """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" priority: int | None = None - protocol: Literal["udp", "tcp"] | None = None + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None translated_ip: str = None """IPv4 address.""" translated_port: int | None = None @@ -15103,12 +15261,12 @@ def __init__( self, access_list: str | None = None, comment: str | None = None, - direction: Literal["egress", "ingress"] | None = None, + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None, group: int | None = None, original_ip: str | None = None, original_port: int | None = None, priority: int | None = None, - protocol: Literal["udp", "tcp"] | None = None, + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None, translated_ip: str = None, translated_port: int | None = None, **kwargs, @@ -15175,17 +15333,17 @@ def __init__(self, destination: Destination | None = None, source: Source | None class Ipv6NdPrefixesItem(AvdDictBaseModel): ipv6_prefix: str = None - valid_lifetime: Annotated[str, ConvertTypes[int]] | None = None + valid_lifetime: str | None = None """Infinite or lifetime in seconds.""" - preferred_lifetime: Annotated[str, ConvertTypes[int]] | None = None + preferred_lifetime: str | None = None """Infinite or lifetime in seconds.""" no_autoconfig_flag: bool | None = None def __init__( self, ipv6_prefix: str = None, - valid_lifetime: Annotated[str, ConvertTypes[int]] | None = None, - preferred_lifetime: Annotated[str, ConvertTypes[int]] | None = None, + valid_lifetime: str | None = None, + preferred_lifetime: str | None = None, no_autoconfig_flag: bool | None = None, **kwargs, ): @@ -15207,12 +15365,12 @@ def __init__( class Pim(AvdDictBaseModel): class Ipv4(AvdDictBaseModel): class Hello(AvdDictBaseModel): - count: Annotated[str, ConvertTypes[int, float]] | None = None + count: str | None = None """Number of missed hellos after which the neighbor expires. Range <1.5-65535>.""" interval: int | None = None """PIM hello interval in seconds.""" - def __init__(self, count: Annotated[str, ConvertTypes[int, float]] | None = None, interval: int | None = None, **kwargs): + def __init__(self, count: str | None = None, interval: int | None = None, **kwargs): """ Args: ----- @@ -15276,12 +15434,16 @@ def __init__(self, ipv4: Ipv4 | None = None, **kwargs): class OspfMessageDigestKeysItem(AvdDictBaseModel): id: int = None - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = None + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = None key: str | None = None """Encrypted password.""" def __init__( - self, id: int = None, hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = None, key: str | None = None, **kwargs + self, + id: int = None, + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = None, + key: str | None = None, + **kwargs, ): """ Args: @@ -15465,7 +15627,7 @@ def __init__(self, enable: bool | None = None, egress: Egress | None = None, **k """"l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI.""" l2_mru: int | None = None """"l2_mru" should only be defined for platforms supporting the "l2 mru" CLI.""" - vlans: Annotated[str, ConvertTypes[int]] | None = None + vlans: str | None = None """ List of switchport vlans as string. For a trunk port this would be a range like "1-200,300". @@ -15473,7 +15635,7 @@ def __init__(self, enable: bool | None = None, egress: Egress | None = None, **k would be a single vlan "123". """ snmp_trap_link_change: bool | None = None - type: Literal["routed", "switched", "l3dot1q", "l2dot1q"] | None = None + type: Annotated[str, ValidValues["routed", "switched", "l3dot1q", "l2dot1q"]] | None = None """ l3dot1q and l2dot1q are used for sub-interfaces. The parent interface should be defined as routed. Interface will not be @@ -15481,11 +15643,11 @@ def __init__(self, enable: bool | None = None, egress: Egress | None = None, **k """ encapsulation_dot1q_vlan: int | None = None """VLAN tag to configure on sub-interface.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF name.""" encapsulation_vlan: EncapsulationVlan | None = None vlan_id: int | None = None - mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None = None + mode: Annotated[str, ValidValues["access", "dot1q-tunnel", "trunk", "trunk phone"]] | None = None native_vlan: int | None = None """If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence.""" native_vlan_tag: bool | None = False @@ -15499,13 +15661,13 @@ def __init__(self, enable: bool | None = None, egress: Egress | None = None, **k trunk_groups: list[str] | None = None lacp_fallback_timeout: int | None = 90 """Timeout in seconds.""" - lacp_fallback_mode: Literal["individual", "static"] | None = None + lacp_fallback_mode: Annotated[str, ValidValues["individual", "static"]] | None = None qos: Qos | None = None bfd: Bfd | None = None service_policy: ServicePolicy | None = None mpls: Mpls | None = None trunk_private_vlan_secondary: bool | None = None - pvlan_mapping: Annotated[str, ConvertTypes[int]] | None = None + pvlan_mapping: str | None = None """List of vlans as string.""" vlan_translations: list[VlanTranslationsItem] | None = None shape: Shape | None = None @@ -15518,9 +15680,9 @@ def __init__(self, enable: bool | None = None, egress: Egress | None = None, **k isis_passive: bool | None = None isis_metric: int | None = None isis_network_point_to_point: bool | None = None - isis_circuit_type: Literal["level-1-2", "level-1", "level-2"] | None = None + isis_circuit_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = None isis_hello_padding: bool | None = None - isis_authentication_mode: Literal["text", "md5"] | None = None + isis_authentication_mode: Annotated[str, ValidValues["text", "md5"]] | None = None isis_authentication_key: str | None = None """Type-7 encrypted password.""" traffic_policy: TrafficPolicy | None = None @@ -15539,15 +15701,15 @@ def __init__(self, enable: bool | None = None, egress: Egress | None = None, **k """ lacp_id: str | None = None """LACP ID with format xxxx.xxxx.xxxx.""" - spanning_tree_bpdufilter: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None - spanning_tree_bpduguard: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None - spanning_tree_guard: Literal["loop", "root", "disabled"] | None = None - spanning_tree_portfast: Literal["edge", "network"] | None = None + spanning_tree_bpdufilter: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None + spanning_tree_bpduguard: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None + spanning_tree_guard: Annotated[str, ValidValues["loop", "root", "disabled"]] | None = None + spanning_tree_portfast: Annotated[str, ValidValues["edge", "network"]] | None = None vmtracer: bool | None = None ptp: Ptp | None = None ip_address: str | None = None """IPv4 address/mask.""" - ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None = None + ip_verify_unicast_source_reachable_via: Annotated[str, ValidValues["any", "rx"]] | None = None ip_nat: IpNat | None = None ipv6_enable: bool | None = None ipv6_address: str | None = None @@ -15573,9 +15735,9 @@ def __init__(self, enable: bool | None = None, egress: Egress | None = None, **k service_profile: str | None = None """QOS profile.""" ospf_network_point_to_point: bool | None = None - ospf_area: Annotated[str, ConvertTypes[int]] | None = None + ospf_area: str | None = None ospf_cost: int | None = None - ospf_authentication: Literal["none", "simple", "message-digest"] | None = None + ospf_authentication: Annotated[str, ValidValues["none", "simple", "message-digest"]] | None = None ospf_authentication_key: str | None = None """Encrypted password.""" ospf_message_digest_keys: list[OspfMessageDigestKeysItem] | None = None @@ -15602,14 +15764,14 @@ def __init__( shutdown: bool | None = None, l2_mtu: int | None = None, l2_mru: int | None = None, - vlans: Annotated[str, ConvertTypes[int]] | None = None, + vlans: str | None = None, snmp_trap_link_change: bool | None = None, - type: Literal["routed", "switched", "l3dot1q", "l2dot1q"] | None = None, + type: Annotated[str, ValidValues["routed", "switched", "l3dot1q", "l2dot1q"]] | None = None, encapsulation_dot1q_vlan: int | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, encapsulation_vlan: EncapsulationVlan | None = None, vlan_id: int | None = None, - mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None = None, + mode: Annotated[str, ValidValues["access", "dot1q-tunnel", "trunk", "trunk phone"]] | None = None, native_vlan: int | None = None, native_vlan_tag: bool | None = False, link_tracking_groups: list[LinkTrackingGroupsItem] | None = None, @@ -15619,13 +15781,13 @@ def __init__( mlag: int | None = None, trunk_groups: list[str] | None = None, lacp_fallback_timeout: int | None = 90, - lacp_fallback_mode: Literal["individual", "static"] | None = None, + lacp_fallback_mode: Annotated[str, ValidValues["individual", "static"]] | None = None, qos: Qos | None = None, bfd: Bfd | None = None, service_policy: ServicePolicy | None = None, mpls: Mpls | None = None, trunk_private_vlan_secondary: bool | None = None, - pvlan_mapping: Annotated[str, ConvertTypes[int]] | None = None, + pvlan_mapping: str | None = None, vlan_translations: list[VlanTranslationsItem] | None = None, shape: Shape | None = None, storm_control: StormControl | None = None, @@ -15635,23 +15797,23 @@ def __init__( isis_passive: bool | None = None, isis_metric: int | None = None, isis_network_point_to_point: bool | None = None, - isis_circuit_type: Literal["level-1-2", "level-1", "level-2"] | None = None, + isis_circuit_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = None, isis_hello_padding: bool | None = None, - isis_authentication_mode: Literal["text", "md5"] | None = None, + isis_authentication_mode: Annotated[str, ValidValues["text", "md5"]] | None = None, isis_authentication_key: str | None = None, traffic_policy: TrafficPolicy | None = None, evpn_ethernet_segment: EvpnEthernetSegment | None = None, esi: str | None = None, rt: str | None = None, lacp_id: str | None = None, - spanning_tree_bpdufilter: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None, - spanning_tree_bpduguard: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None, - spanning_tree_guard: Literal["loop", "root", "disabled"] | None = None, - spanning_tree_portfast: Literal["edge", "network"] | None = None, + spanning_tree_bpdufilter: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None, + spanning_tree_bpduguard: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None, + spanning_tree_guard: Annotated[str, ValidValues["loop", "root", "disabled"]] | None = None, + spanning_tree_portfast: Annotated[str, ValidValues["edge", "network"]] | None = None, vmtracer: bool | None = None, ptp: Ptp | None = None, ip_address: str | None = None, - ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None = None, + ip_verify_unicast_source_reachable_via: Annotated[str, ValidValues["any", "rx"]] | None = None, ip_nat: IpNat | None = None, ipv6_enable: bool | None = None, ipv6_address: str | None = None, @@ -15668,9 +15830,9 @@ def __init__( pim: Pim | None = None, service_profile: str | None = None, ospf_network_point_to_point: bool | None = None, - ospf_area: Annotated[str, ConvertTypes[int]] | None = None, + ospf_area: str | None = None, ospf_cost: int | None = None, - ospf_authentication: Literal["none", "simple", "message-digest"] | None = None, + ospf_authentication: Annotated[str, ValidValues["none", "simple", "message-digest"]] | None = None, ospf_authentication_key: str | None = None, ospf_message_digest_keys: list[OspfMessageDigestKeysItem] | None = None, flow_tracker: FlowTracker | None = None, @@ -15918,9 +16080,9 @@ def __init__(self, name: str = None, sequence_numbers: list[SequenceNumbersItem] class PriorityFlowControl(AvdDictBaseModel): class Watchdog(AvdDictBaseModel): - action: Literal["drop", "no-drop"] | None = None + action: Annotated[str, ValidValues["drop", "no-drop"]] | None = None """Action on stuck queue.""" - timeout: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None + timeout: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None """ Timeout in seconds after which port should be errdisabled or should start dropping on congested priorities. @@ -15928,14 +16090,14 @@ class Watchdog(AvdDictBaseModel): be decimal with up to 2 decimal point. Example: 0.01 or 60 """ - polling_interval: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,3})?$"]] | None = None + polling_interval: Annotated[str, Pattern[r"^\d+(\.\d{1,3})?$"]] | None = None """ Time interval in seconds at which the watchdog should poll the queues. This should be decimal with up to 3 decimal point. Example: 0.005 or 60 """ - recovery_time: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None + recovery_time: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None """ Recovery-time in seconds after which stuck queue should recover and start forwarding again. @@ -15948,10 +16110,10 @@ class Watchdog(AvdDictBaseModel): def __init__( self, - action: Literal["drop", "no-drop"] | None = None, - timeout: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None, - polling_interval: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,3})?$"]] | None = None, - recovery_time: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None, + action: Annotated[str, ValidValues["drop", "no-drop"]] | None = None, + timeout: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None, + polling_interval: Annotated[str, Pattern[r"^\d+(\.\d{1,3})?$"]] | None = None, + recovery_time: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None, override_action_drop: bool | None = None, **kwargs, ): @@ -16181,7 +16343,7 @@ def __init__(self, enabled: bool | None = True, threshold: Threshold | None = No self.missing_message = missing_message return super().__init__(**kwargs) - mode: Literal["boundary", "disabled", "e2etransparent", "gptp", "ordinarymaster", "p2ptransparent"] | None = None + mode: Annotated[str, ValidValues["boundary", "disabled", "e2etransparent", "gptp", "ordinarymaster", "p2ptransparent"]] | None = None mode_one_step: bool | None = None forward_unicast: bool | None = None clock_identity: str | None = None @@ -16196,7 +16358,7 @@ def __init__(self, enabled: bool | None = True, threshold: Threshold | None = No def __init__( self, - mode: Literal["boundary", "disabled", "e2etransparent", "gptp", "ordinarymaster", "p2ptransparent"] | None = None, + mode: Annotated[str, ValidValues["boundary", "disabled", "e2etransparent", "gptp", "ordinarymaster", "p2ptransparent"]] | None = None, mode_one_step: bool | None = None, forward_unicast: bool | None = None, clock_identity: str | None = None, @@ -16409,7 +16571,7 @@ def __init__(self, rate: str | None = None, **kwargs): class RandomDetect(AvdDictBaseModel): class Ecn(AvdDictBaseModel): class Threshold(AvdDictBaseModel): - units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] = None + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "milliseconds"]] = None """ Units to be used for the threshold values. This should be one of segments, byte, kbytes, mbytes. @@ -16425,7 +16587,7 @@ class Threshold(AvdDictBaseModel): def __init__( self, - units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] = None, + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "milliseconds"]] = None, min: int = None, max: int = None, max_probability: int | None = None, @@ -16469,7 +16631,7 @@ def __init__(self, count: bool | None = None, threshold: Threshold | None = None class Drop(AvdDictBaseModel): class Threshold(AvdDictBaseModel): - units: Literal["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"] = None + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"]] = None """Units to be used for the threshold values.""" drop_precedence: int | None = None """Specify Drop Precedence value.""" @@ -16484,7 +16646,7 @@ class Threshold(AvdDictBaseModel): def __init__( self, - units: Literal["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"] = None, + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"]] = None, drop_precedence: int | None = None, min: int = None, max: int = None, @@ -16544,7 +16706,7 @@ def __init__(self, ecn: Ecn | None = None, drop: Drop | None = None, **kwargs): """TX-Queue ID.""" bandwidth_percent: int | None = None bandwidth_guaranteed_percent: int | None = None - priority: Literal["priority strict", "no priority"] | None = None + priority: Annotated[str, ValidValues["priority strict", "no priority"]] | None = None shape: Shape | None = None comment: str | None = None """Text comment added to queue.""" @@ -16555,7 +16717,7 @@ def __init__( id: int = None, bandwidth_percent: int | None = None, bandwidth_guaranteed_percent: int | None = None, - priority: Literal["priority strict", "no priority"] | None = None, + priority: Annotated[str, ValidValues["priority strict", "no priority"]] | None = None, shape: Shape | None = None, comment: str | None = None, random_detect: RandomDetect | None = None, @@ -16605,7 +16767,7 @@ def __init__(self, rate: str | None = None, **kwargs): class RandomDetect(AvdDictBaseModel): class Ecn(AvdDictBaseModel): class Threshold(AvdDictBaseModel): - units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] = None + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "milliseconds"]] = None """Unit to be used for the threshold values.""" min: int = None """Random-detect ECN minimum-threshold.""" @@ -16618,7 +16780,7 @@ class Threshold(AvdDictBaseModel): def __init__( self, - units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] = None, + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "milliseconds"]] = None, min: int = None, max: int = None, max_probability: int | None = None, @@ -16660,7 +16822,7 @@ def __init__(self, count: bool | None = None, threshold: Threshold | None = None class Drop(AvdDictBaseModel): class Threshold(AvdDictBaseModel): - units: Literal["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"] = None + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"]] = None """Units to be used for the threshold values.""" drop_precedence: int | None = None """Specify Drop Precedence value.""" @@ -16675,7 +16837,7 @@ class Threshold(AvdDictBaseModel): def __init__( self, - units: Literal["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"] = None, + units: Annotated[str, ValidValues["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"]] = None, drop_precedence: int | None = None, min: int = None, max: int = None, @@ -16735,7 +16897,7 @@ def __init__(self, ecn: Ecn | None = None, drop: Drop | None = None, **kwargs): """UC TX queue ID.""" bandwidth_percent: int | None = None bandwidth_guaranteed_percent: int | None = None - priority: Literal["priority strict", "no priority"] | None = None + priority: Annotated[str, ValidValues["priority strict", "no priority"]] | None = None shape: Shape | None = None comment: str | None = None """Text comment added to queue.""" @@ -16746,7 +16908,7 @@ def __init__( id: int = None, bandwidth_percent: int | None = None, bandwidth_guaranteed_percent: int | None = None, - priority: Literal["priority strict", "no priority"] | None = None, + priority: Annotated[str, ValidValues["priority strict", "no priority"]] | None = None, shape: Shape | None = None, comment: str | None = None, random_detect: RandomDetect | None = None, @@ -16797,7 +16959,7 @@ def __init__(self, rate: str | None = None, **kwargs): """MC TX queue ID.""" bandwidth_percent: int | None = None bandwidth_guaranteed_percent: int | None = None - priority: Literal["priority strict", "no priority"] | None = None + priority: Annotated[str, ValidValues["priority strict", "no priority"]] | None = None shape: Shape | None = None comment: str | None = None """Text comment added to queue.""" @@ -16807,7 +16969,7 @@ def __init__( id: int = None, bandwidth_percent: int | None = None, bandwidth_guaranteed_percent: int | None = None, - priority: Literal["priority strict", "no priority"] | None = None, + priority: Annotated[str, ValidValues["priority strict", "no priority"]] | None = None, shape: Shape | None = None, comment: str | None = None, **kwargs, @@ -16834,7 +16996,7 @@ def __init__( class PriorityFlowControl(AvdDictBaseModel): class Watchdog(AvdDictBaseModel): class Timer(AvdDictBaseModel): - timeout: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] = None + timeout: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] = None """ Timeout in seconds after which port should be errdisabled or should start dropping on congested priorities. @@ -16842,7 +17004,7 @@ class Timer(AvdDictBaseModel): be decimal with up to 2 decimal point. Example: 0.01 or 60 """ - polling_interval: Annotated[str, ConvertTypes[int, float], Pattern["^auto|\d+(\.\d{1,3})?$"]] = None + polling_interval: Annotated[str, Pattern[r"^auto|\d+(\.\d{1,3})?$"]] = None """ Time interval in seconds at which the watchdog should poll the queues. This should be decimal with up to 3 decimal point @@ -16850,7 +17012,7 @@ class Timer(AvdDictBaseModel): to 'auto' based on recovery_time and timeout values. Example: 0.005 or 60 """ - recovery_time: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] = None + recovery_time: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] = None """ Recovery-time in seconds after which stuck queue should recover and start forwarding again. @@ -16867,9 +17029,9 @@ class Timer(AvdDictBaseModel): def __init__( self, - timeout: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] = None, - polling_interval: Annotated[str, ConvertTypes[int, float], Pattern["^auto|\d+(\.\d{1,3})?$"]] = None, - recovery_time: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] = None, + timeout: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] = None, + polling_interval: Annotated[str, Pattern[r"^auto|\d+(\.\d{1,3})?$"]] = None, + recovery_time: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] = None, forced: bool | None = None, **kwargs, ): @@ -16908,7 +17070,7 @@ def __init__( enabled: bool = None """Enable the watchdog on stuck transmit queues.""" - action: Literal["drop", "notify-only"] | None = None + action: Annotated[str, ValidValues["drop", "notify-only"]] | None = None """ Override the default error-disable action to either drop traffic on the stuck queue or notify-only @@ -16918,7 +17080,9 @@ def __init__( timer: Timer | None = None """Timer thresholds whilst monitoring queues.""" - def __init__(self, enabled: bool = None, action: Literal["drop", "notify-only"] | None = None, timer: Timer | None = None, **kwargs): + def __init__( + self, enabled: bool = None, action: Annotated[str, ValidValues["drop", "notify-only"]] | None = None, timer: Timer | None = None, **kwargs + ): """ Args: ----- @@ -16977,7 +17141,7 @@ def __init__(self, enabled: bool | None = None, watchdog: Watchdog | None = None name: str = None """Profile-Name.""" - trust: Literal["cos", "dscp", "disabled"] | None = None + trust: Annotated[str, ValidValues["cos", "dscp", "disabled"]] | None = None cos: int | None = None dscp: int | None = None shape: Shape | None = None @@ -16991,7 +17155,7 @@ def __init__(self, enabled: bool | None = None, watchdog: Watchdog | None = None def __init__( self, name: str = None, - trust: Literal["cos", "dscp", "disabled"] | None = None, + trust: Annotated[str, ValidValues["cos", "dscp", "disabled"]] | None = None, cos: int | None = None, dscp: int | None = None, shape: Shape | None = None, @@ -17128,7 +17292,7 @@ class QueueMonitorStreaming(AvdDictBaseModel): ipv6_access_group: str | None = None """Name of IPv6 ACL.""" max_connections: int | None = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None def __init__( self, @@ -17136,7 +17300,7 @@ def __init__( ip_access_group: str | None = None, ipv6_access_group: str | None = None, max_connections: int | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, **kwargs, ): """ @@ -17195,20 +17359,14 @@ def __init__(self, port: int | None = None, tls_ssl_profile: str | None = None, class HostsItem(AvdDictBaseModel): host: str = None """Host IP address or name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None timeout: int | None = None retransmit: int | None = None key: str | None = None """Encrypted key.""" def __init__( - self, - host: str = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, - timeout: int | None = None, - retransmit: int | None = None, - key: str | None = None, - **kwargs, + self, host: str = None, vrf: str | None = None, timeout: int | None = None, retransmit: int | None = None, key: str | None = None, **kwargs ): """ Args: @@ -17254,11 +17412,11 @@ def __init__( class RadiusServersItem(AvdDictBaseModel): host: str | None = None """Host IP address or name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None key: str | None = None """Encrypted key.""" - def __init__(self, host: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, key: str | None = None, **kwargs): + def __init__(self, host: str | None = None, vrf: str | None = None, key: str | None = None, **kwargs): """ Args: ----- @@ -17290,7 +17448,7 @@ class RolesItem(AvdDictBaseModel): class SequenceNumbersItem(AvdDictBaseModel): sequence: int | None = None """Sequence number.""" - action: Literal["permit", "deny"] | None = None + action: Annotated[str, ValidValues["permit", "deny"]] | None = None mode: str | None = None """"config", "config-all", "exec" or mode key as string.""" command: str | None = None @@ -17299,7 +17457,7 @@ class SequenceNumbersItem(AvdDictBaseModel): def __init__( self, sequence: int | None = None, - action: Literal["permit", "deny"] | None = None, + action: Annotated[str, ValidValues["permit", "deny"]] | None = None, mode: str | None = None, command: str | None = None, **kwargs, @@ -17355,7 +17513,7 @@ def __init__(self, enabled: bool | None = None, sequence_number: int | None = No sequence: int = None """Sequence ID.""" - type: Literal["permit", "deny"] = None + type: Annotated[str, ValidValues["permit", "deny"]] = None description: str | None = None match: list[str] | None = None """List of "match" statements.""" @@ -17368,7 +17526,7 @@ def __init__(self, enabled: bool | None = None, sequence_number: int | None = No def __init__( self, sequence: int = None, - type: Literal["permit", "deny"] = None, + type: Annotated[str, ValidValues["permit", "deny"]] = None, description: str | None = None, match: list[str] | None = None, set: list[str] | None = None, @@ -17415,10 +17573,10 @@ def __init__(self, name: str = None, sequence_numbers: list[SequenceNumbersItem] class RouterAdaptiveVirtualTopology(AvdDictBaseModel): class Region(AvdDictBaseModel): - name: Annotated[str, Pattern["^[A-Za-z0-9_.:{}\[\]-]+$"]] = None + name: Annotated[str, Pattern[r"^[A-Za-z0-9_.:{}\[\]-]+$"]] = None id: int = None - def __init__(self, name: Annotated[str, Pattern["^[A-Za-z0-9_.:{}\[\]-]+$"]] = None, id: int = None, **kwargs): + def __init__(self, name: Annotated[str, Pattern[r"^[A-Za-z0-9_.:{}\[\]-]+$"]] = None, id: int = None, **kwargs): """ Args: ----- @@ -17431,10 +17589,10 @@ def __init__(self, name: Annotated[str, Pattern["^[A-Za-z0-9_.:{}\[\]-]+$"]] = N return super().__init__(**kwargs) class Zone(AvdDictBaseModel): - name: Annotated[str, Pattern["^[A-Za-z0-9_.:{}\[\]-]+$"]] = None + name: Annotated[str, Pattern[r"^[A-Za-z0-9_.:{}\[\]-]+$"]] = None id: int = None - def __init__(self, name: Annotated[str, Pattern["^[A-Za-z0-9_.:{}\[\]-]+$"]] = None, id: int = None, **kwargs): + def __init__(self, name: Annotated[str, Pattern[r"^[A-Za-z0-9_.:{}\[\]-]+$"]] = None, id: int = None, **kwargs): """ Args: ----- @@ -17447,10 +17605,10 @@ def __init__(self, name: Annotated[str, Pattern["^[A-Za-z0-9_.:{}\[\]-]+$"]] = N return super().__init__(**kwargs) class Site(AvdDictBaseModel): - name: Annotated[str, Pattern["^[A-Za-z0-9_.:{}\[\]-]+$"]] = None + name: Annotated[str, Pattern[r"^[A-Za-z0-9_.:{}\[\]-]+$"]] = None id: int = None - def __init__(self, name: Annotated[str, Pattern["^[A-Za-z0-9_.:{}\[\]-]+$"]] = None, id: int = None, **kwargs): + def __init__(self, name: Annotated[str, Pattern[r"^[A-Za-z0-9_.:{}\[\]-]+$"]] = None, id: int = None, **kwargs): """ Args: ----- @@ -17574,7 +17732,7 @@ def __init__(self, name: str = None, policy: str | None = None, profiles: list[P self.profiles = profiles return super().__init__(**kwargs) - topology_role: Literal["edge", "pathfinder", "transit region", "transit zone"] | None = None + topology_role: Annotated[str, ValidValues["edge", "pathfinder", "transit region", "transit zone"]] | None = None """Role name.""" region: Region | None = None """Region name and ID.""" @@ -17594,7 +17752,7 @@ def __init__(self, name: str = None, policy: str | None = None, profiles: list[P def __init__( self, - topology_role: Literal["edge", "pathfinder", "transit region", "transit zone"] | None = None, + topology_role: Annotated[str, ValidValues["edge", "pathfinder", "transit region", "transit zone"]] | None = None, region: Region | None = None, zone: Zone | None = None, site: Site | None = None, @@ -18008,7 +18166,7 @@ class ListenRangesItem(AvdDictBaseModel): If both are defined, `peer_filter` takes precedence """ - remote_as: Annotated[str, ConvertTypes[int]] | None = None + remote_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -18021,7 +18179,7 @@ def __init__( peer_id_include_router_id: bool | None = None, peer_group: str | None = None, peer_filter: str | None = None, - remote_as: Annotated[str, ConvertTypes[int]] | None = None, + remote_as: str | None = None, **kwargs, ): """ @@ -18145,7 +18303,7 @@ def __init__(self, enabled: bool | None = None, always: bool | None = None, rout class MissingPolicy(AvdDictBaseModel): class DirectionIn(AvdDictBaseModel): - action: Literal["deny", "permit", "deny-in-out"] = None + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None """Missing policy action.""" include_community_list: bool | None = None """Include community-list references in missing policy decision.""" @@ -18156,7 +18314,7 @@ class DirectionIn(AvdDictBaseModel): def __init__( self, - action: Literal["deny", "permit", "deny-in-out"] = None, + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None, include_community_list: bool | None = None, include_prefix_list: bool | None = None, include_sub_route_map: bool | None = None, @@ -18178,7 +18336,7 @@ def __init__( return super().__init__(**kwargs) class DirectionOut(AvdDictBaseModel): - action: Literal["deny", "permit", "deny-in-out"] = None + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None """Missing policy action.""" include_community_list: bool | None = None """Include community-list references in missing policy decision.""" @@ -18189,7 +18347,7 @@ class DirectionOut(AvdDictBaseModel): def __init__( self, - action: Literal["deny", "permit", "deny-in-out"] = None, + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None, include_community_list: bool | None = None, include_prefix_list: bool | None = None, include_sub_route_map: bool | None = None, @@ -18280,10 +18438,12 @@ def __init__(self, enabled: bool | None = None, all: bool | None = None, **kwarg class SharedSecret(AvdDictBaseModel): profile: str = None """Name of profile defined under `management_security`.""" - hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] = None + hash_algorithm: Annotated[str, ValidValues["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"]] = None """Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above.""" - def __init__(self, profile: str = None, hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] = None, **kwargs): + def __init__( + self, profile: str = None, hash_algorithm: Annotated[str, ValidValues["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"]] = None, **kwargs + ): """ Args: ----- @@ -18299,13 +18459,13 @@ def __init__(self, profile: str = None, hash_algorithm: Literal["aes-128-cmac-96 """Peer-group name.""" type: str | None = None """Key only used for documentation or validation purposes.""" - remote_as: Annotated[str, ConvertTypes[int]] | None = None + remote_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float number. """ - local_as: Annotated[str, ConvertTypes[int]] | None = None + local_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -18343,7 +18503,7 @@ def __init__(self, profile: str = None, hash_algorithm: Literal["aes-128-cmac-96 """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" maximum_routes: int | None = None """Maximum number of routes (0 means unlimited).""" - maximum_routes_warning_limit: Annotated[str, ConvertTypes[int]] | None = None + maximum_routes_warning_limit: str | None = None """ Maximum number of routes after which a warning is issued (0 means never warn) or Percentage of maximum number of routes @@ -18378,8 +18538,8 @@ def __init__( self, name: str = None, type: str | None = None, - remote_as: Annotated[str, ConvertTypes[int]] | None = None, - local_as: Annotated[str, ConvertTypes[int]] | None = None, + remote_as: str | None = None, + local_as: str | None = None, description: str | None = None, shutdown: bool | None = None, as_path: AsPath | None = None, @@ -18398,7 +18558,7 @@ def __init__( default_originate: DefaultOriginate | None = None, send_community: str | None = None, maximum_routes: int | None = None, - maximum_routes_warning_limit: Annotated[str, ConvertTypes[int]] | None = None, + maximum_routes_warning_limit: str | None = None, maximum_routes_warning_only: bool | None = None, missing_policy: MissingPolicy | None = None, link_bandwidth: LinkBandwidth | None = None, @@ -18571,7 +18731,7 @@ def __init__(self, enabled: bool | None = None, always: bool | None = None, rout class MissingPolicy(AvdDictBaseModel): class DirectionIn(AvdDictBaseModel): - action: Literal["deny", "permit", "deny-in-out"] = None + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None """Missing policy action.""" include_community_list: bool | None = None """Include community-list references in missing policy decision.""" @@ -18582,7 +18742,7 @@ class DirectionIn(AvdDictBaseModel): def __init__( self, - action: Literal["deny", "permit", "deny-in-out"] = None, + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None, include_community_list: bool | None = None, include_prefix_list: bool | None = None, include_sub_route_map: bool | None = None, @@ -18604,7 +18764,7 @@ def __init__( return super().__init__(**kwargs) class DirectionOut(AvdDictBaseModel): - action: Literal["deny", "permit", "deny-in-out"] = None + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None """Missing policy action.""" include_community_list: bool | None = None """Include community-list references in missing policy decision.""" @@ -18615,7 +18775,7 @@ class DirectionOut(AvdDictBaseModel): def __init__( self, - action: Literal["deny", "permit", "deny-in-out"] = None, + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None, include_community_list: bool | None = None, include_prefix_list: bool | None = None, include_sub_route_map: bool | None = None, @@ -18741,10 +18901,12 @@ def __init__(self, enabled: bool | None = None, replace_as: bool | None = None, class SharedSecret(AvdDictBaseModel): profile: str = None """Name of profile defined under `management_security`.""" - hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] = None + hash_algorithm: Annotated[str, ValidValues["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"]] = None """Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above.""" - def __init__(self, profile: str = None, hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] = None, **kwargs): + def __init__( + self, profile: str = None, hash_algorithm: Annotated[str, ValidValues["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"]] = None, **kwargs + ): """ Args: ----- @@ -18758,13 +18920,13 @@ def __init__(self, profile: str = None, hash_algorithm: Literal["aes-128-cmac-96 ip_address: str = None peer_group: str | None = None - remote_as: Annotated[str, ConvertTypes[int]] | None = None + remote_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float number. """ - local_as: Annotated[str, ConvertTypes[int]] | None = None + local_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -18797,7 +18959,7 @@ def __init__(self, profile: str = None, hash_algorithm: Literal["aes-128-cmac-96 """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" maximum_routes: int | None = None """Maximum number of routes (0 means unlimited).""" - maximum_routes_warning_limit: Annotated[str, ConvertTypes[int]] | None = None + maximum_routes_warning_limit: str | None = None """ Maximum number of routes after which a warning is issued (0 means never warn) or Percentage of maximum number of routes @@ -18824,8 +18986,8 @@ def __init__( self, ip_address: str = None, peer_group: str | None = None, - remote_as: Annotated[str, ConvertTypes[int]] | None = None, - local_as: Annotated[str, ConvertTypes[int]] | None = None, + remote_as: str | None = None, + local_as: str | None = None, as_path: AsPath | None = None, peer: str | None = None, description: str | None = None, @@ -18843,7 +19005,7 @@ def __init__( default_originate: DefaultOriginate | None = None, send_community: str | None = None, maximum_routes: int | None = None, - maximum_routes_warning_limit: Annotated[str, ConvertTypes[int]] | None = None, + maximum_routes_warning_limit: str | None = None, maximum_routes_warning_only: bool | None = None, missing_policy: MissingPolicy | None = None, allowas_in: AllowasIn | None = None, @@ -18945,7 +19107,7 @@ def __init__( class NeighborInterfacesItem(AvdDictBaseModel): name: str = None """Interface name.""" - remote_as: Annotated[str, ConvertTypes[int]] | None = None + remote_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -18961,7 +19123,7 @@ class NeighborInterfacesItem(AvdDictBaseModel): def __init__( self, name: str = None, - remote_as: Annotated[str, ConvertTypes[int]] | None = None, + remote_as: str | None = None, peer: str | None = None, peer_group: str | None = "Peer-group name", description: str | None = None, @@ -19031,7 +19193,9 @@ def __init__( return super().__init__(**kwargs) class RedistributeRoutesItem(AvdDictBaseModel): - source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] = None + source_protocol: Annotated[str, ValidValues["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"]] = ( + None + ) route_map: str | None = None rcf: str | None = None """ @@ -19043,7 +19207,7 @@ class RedistributeRoutesItem(AvdDictBaseModel): `dynamic`. """ include_leaked: bool | None = None - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None """ Routes learned by the OSPF protocol. The `ospf_route_type` is valid for source_protocols 'ospf' and 'ospfv3'. @@ -19051,11 +19215,13 @@ class RedistributeRoutesItem(AvdDictBaseModel): def __init__( self, - source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] = None, + source_protocol: Annotated[ + str, ValidValues["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + ] = None, route_map: str | None = None, rcf: str | None = None, include_leaked: bool | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None, + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None, **kwargs, ): """ @@ -19085,11 +19251,11 @@ def __init__( class VlanAwareBundlesItem(AvdDictBaseModel): class RdEvpnDomain(AvdDictBaseModel): - domain: Literal["remote", "all"] | None = None + domain: Annotated[str, ValidValues["remote", "all"]] | None = None rd: str | None = None """Route distinguisher.""" - def __init__(self, domain: Literal["remote", "all"] | None = None, rd: str | None = None, **kwargs): + def __init__(self, domain: Annotated[str, ValidValues["remote", "all"]] | None = None, rd: str | None = None, **kwargs): """ Args: ----- @@ -19103,10 +19269,10 @@ def __init__(self, domain: Literal["remote", "all"] | None = None, rd: str | Non class RouteTargets(AvdDictBaseModel): class ImportEvpnDomainsItem(AvdDictBaseModel): - domain: Literal["remote", "all"] | None = None + domain: Annotated[str, ValidValues["remote", "all"]] | None = None route_target: str | None = None - def __init__(self, domain: Literal["remote", "all"] | None = None, route_target: str | None = None, **kwargs): + def __init__(self, domain: Annotated[str, ValidValues["remote", "all"]] | None = None, route_target: str | None = None, **kwargs): """ Args: ----- @@ -19119,10 +19285,10 @@ def __init__(self, domain: Literal["remote", "all"] | None = None, route_target: return super().__init__(**kwargs) class ExportEvpnDomainsItem(AvdDictBaseModel): - domain: Literal["remote", "all"] | None = None + domain: Annotated[str, ValidValues["remote", "all"]] | None = None route_target: str | None = None - def __init__(self, domain: Literal["remote", "all"] | None = None, route_target: str | None = None, **kwargs): + def __init__(self, domain: Annotated[str, ValidValues["remote", "all"]] | None = None, route_target: str | None = None, **kwargs): """ Args: ----- @@ -19135,10 +19301,10 @@ def __init__(self, domain: Literal["remote", "all"] | None = None, route_target: return super().__init__(**kwargs) class ImportExportEvpnDomainsItem(AvdDictBaseModel): - domain: Literal["remote", "all"] | None = None + domain: Annotated[str, ValidValues["remote", "all"]] | None = None route_target: str | None = None - def __init__(self, domain: Literal["remote", "all"] | None = None, route_target: str | None = None, **kwargs): + def __init__(self, domain: Annotated[str, ValidValues["remote", "all"]] | None = None, route_target: str | None = None, **kwargs): """ Args: ----- @@ -19198,7 +19364,7 @@ def __init__( route_targets: RouteTargets | None = None redistribute_routes: list[str] | None = None no_redistribute_routes: list[str] | None = None - vlan: Annotated[str, ConvertTypes[int]] | None = None + vlan: str | None = None """VLAN range as string. Example "100-200,300".""" eos_cli: str | None = None """Multiline EOS CLI rendered directly on the Router BGP, VLAN-aware-bundle definition in the final EOS configuration.""" @@ -19213,7 +19379,7 @@ def __init__( route_targets: RouteTargets | None = None, redistribute_routes: list[str] | None = None, no_redistribute_routes: list[str] | None = None, - vlan: Annotated[str, ConvertTypes[int]] | None = None, + vlan: str | None = None, eos_cli: str | None = None, **kwargs, ): @@ -19246,11 +19412,11 @@ def __init__( class VlansItem(AvdDictBaseModel): class RdEvpnDomain(AvdDictBaseModel): - domain: Literal["remote", "all"] | None = None + domain: Annotated[str, ValidValues["remote", "all"]] | None = None rd: str | None = None """Route distinguisher.""" - def __init__(self, domain: Literal["remote", "all"] | None = None, rd: str | None = None, **kwargs): + def __init__(self, domain: Annotated[str, ValidValues["remote", "all"]] | None = None, rd: str | None = None, **kwargs): """ Args: ----- @@ -19264,10 +19430,10 @@ def __init__(self, domain: Literal["remote", "all"] | None = None, rd: str | Non class RouteTargets(AvdDictBaseModel): class ImportEvpnDomainsItem(AvdDictBaseModel): - domain: Literal["remote", "all"] | None = None + domain: Annotated[str, ValidValues["remote", "all"]] | None = None route_target: str | None = None - def __init__(self, domain: Literal["remote", "all"] | None = None, route_target: str | None = None, **kwargs): + def __init__(self, domain: Annotated[str, ValidValues["remote", "all"]] | None = None, route_target: str | None = None, **kwargs): """ Args: ----- @@ -19280,10 +19446,10 @@ def __init__(self, domain: Literal["remote", "all"] | None = None, route_target: return super().__init__(**kwargs) class ExportEvpnDomainsItem(AvdDictBaseModel): - domain: Literal["remote", "all"] | None = None + domain: Annotated[str, ValidValues["remote", "all"]] | None = None route_target: str | None = None - def __init__(self, domain: Literal["remote", "all"] | None = None, route_target: str | None = None, **kwargs): + def __init__(self, domain: Annotated[str, ValidValues["remote", "all"]] | None = None, route_target: str | None = None, **kwargs): """ Args: ----- @@ -19296,10 +19462,10 @@ def __init__(self, domain: Literal["remote", "all"] | None = None, route_target: return super().__init__(**kwargs) class ImportExportEvpnDomainsItem(AvdDictBaseModel): - domain: Literal["remote", "all"] | None = None + domain: Annotated[str, ValidValues["remote", "all"]] | None = None route_target: str | None = None - def __init__(self, domain: Literal["remote", "all"] | None = None, route_target: str | None = None, **kwargs): + def __init__(self, domain: Annotated[str, ValidValues["remote", "all"]] | None = None, route_target: str | None = None, **kwargs): """ Args: ----- @@ -19491,14 +19657,14 @@ def __init__(self, enable: bool | None = None, inter_domain: bool | None = None, self.inter_domain = inter_domain return super().__init__(**kwargs) - encapsulation: Literal["vxlan", "mpls"] | None = None + encapsulation: Annotated[str, ValidValues["vxlan", "mpls"]] | None = None next_hop_self_source_interface: str | None = None """Source interface name.""" next_hop_self_received_evpn_routes: NextHopSelfReceivedEvpnRoutes | None = None def __init__( self, - encapsulation: Literal["vxlan", "mpls"] | None = None, + encapsulation: Annotated[str, ValidValues["vxlan", "mpls"]] | None = None, next_hop_self_source_interface: str | None = None, next_hop_self_received_evpn_routes: NextHopSelfReceivedEvpnRoutes | None = None, **kwargs, @@ -19517,12 +19683,17 @@ def __init__( return super().__init__(**kwargs) class NextHopMplsResolutionRibsItem(AvdDictBaseModel): - rib_type: Literal["system-connected", "tunnel-rib-colored", "tunnel-rib"] = None + rib_type: Annotated[str, ValidValues["system-connected", "tunnel-rib-colored", "tunnel-rib"]] = None """Type of RIB. For 'tunnel-rib', use 'rib_name' to specify the name of the Tunnel-RIB to use.""" rib_name: str | None = None """The name of the tunnel-rib to use when using 'tunnel-rib' type.""" - def __init__(self, rib_type: Literal["system-connected", "tunnel-rib-colored", "tunnel-rib"] = None, rib_name: str | None = None, **kwargs): + def __init__( + self, + rib_type: Annotated[str, ValidValues["system-connected", "tunnel-rib-colored", "tunnel-rib"]] = None, + rib_name: str | None = None, + **kwargs, + ): """ Args: ----- @@ -19700,7 +19871,7 @@ def __init__(self, receive: bool | None = None, send: Send | None = None, **kwar """ default_route: DefaultRoute | None = None domain_remote: bool | None = None - encapsulation: Literal["vxlan", "mpls"] | None = None + encapsulation: Annotated[str, ValidValues["vxlan", "mpls"]] | None = None additional_paths: AdditionalPaths | None = None def __init__( @@ -19713,7 +19884,7 @@ def __init__( rcf_out: str | None = None, default_route: DefaultRoute | None = None, domain_remote: bool | None = None, - encapsulation: Literal["vxlan", "mpls"] | None = None, + encapsulation: Annotated[str, ValidValues["vxlan", "mpls"]] | None = None, additional_paths: AdditionalPaths | None = None, **kwargs, ): @@ -19789,14 +19960,14 @@ def __init__(self, resolution_disabled: bool | None = None, **kwargs): return super().__init__(**kwargs) class Route(AvdDictBaseModel): - import_match_failure_action: Literal["discard"] | None = None + import_match_failure_action: Annotated[str, ValidValues["discard"]] | None = None import_ethernet_segment_ip_mass_withdraw: bool | None = None import_overlay_index_gateway: bool | None = None export_ethernet_segment_ip_mass_withdraw: bool | None = None def __init__( self, - import_match_failure_action: Literal["discard"] | None = None, + import_match_failure_action: Annotated[str, ValidValues["discard"]] | None = None, import_ethernet_segment_ip_mass_withdraw: bool | None = None, import_overlay_index_gateway: bool | None = None, export_ethernet_segment_ip_mass_withdraw: bool | None = None, @@ -20232,7 +20403,9 @@ def __init__( return super().__init__(**kwargs) class RedistributeRoutesItem(AvdDictBaseModel): - source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] = None + source_protocol: Annotated[ + str, ValidValues["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + ] = None route_map: str | None = None include_leaked: bool | None = None """Only applicable if `source_protocol` is one of `connected`, `static`, `isis`, `ospf`, `ospfv3`.""" @@ -20245,7 +20418,7 @@ class RedistributeRoutesItem(AvdDictBaseModel): Only applicable if `source_protocol` is one of `connected`, `static`, `isis`, `user`, `dynamic`. """ - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None """ Routes learned by the OSPF protocol. The `ospf_route_type` is valid for source_protocols 'ospf' and 'ospfv3'. @@ -20253,11 +20426,13 @@ class RedistributeRoutesItem(AvdDictBaseModel): def __init__( self, - source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] = None, + source_protocol: Annotated[ + str, ValidValues["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + ] = None, route_map: str | None = None, include_leaked: bool | None = None, rcf: str | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None, + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None, **kwargs, ): """ @@ -20382,7 +20557,7 @@ class RedistributeRoutesItem(AvdDictBaseModel): `route_map` takes precedence. Only applicable if `source_protocol` is `isis`. """ - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None """ Routes learned by the OSPF protocol. The `ospf_route_type` is valid for source_protocols 'ospf' and 'ospfv3'. @@ -20394,7 +20569,7 @@ def __init__( route_map: str | None = None, include_leaked: bool | None = None, rcf: str | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None, + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None, **kwargs, ): """ @@ -20680,7 +20855,7 @@ class RedistributeRoutesItem(AvdDictBaseModel): `route_map` takes precedence. Only used if `source_protocol` is one of `connected`, `static`, `isis`, `user`, `dynamic`. """ - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None """ Routes learned by the OSPF protocol. The `ospf_route_type` is valid for source_protocols 'ospfv3'. @@ -20692,7 +20867,7 @@ def __init__( route_map: str | None = None, include_leaked: bool | None = None, rcf: str | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None, + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None, **kwargs, ): """ @@ -20754,13 +20929,13 @@ def __init__( class AddressFamilyIpv6Multicast(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -20863,7 +21038,7 @@ def __init__(self, prefix: str = None, route_map: str | None = None, **kwargs): return super().__init__(**kwargs) class RedistributeRoutesItem(AvdDictBaseModel): - source_protocol: Literal["connected", "isis", "ospf", "ospfv3", "static"] = None + source_protocol: Annotated[str, ValidValues["connected", "isis", "ospf", "ospfv3", "static"]] = None include_leaked: bool | None = None """Only applicable if `source_protocol` is `isis`.""" route_map: str | None = None @@ -20875,7 +21050,7 @@ class RedistributeRoutesItem(AvdDictBaseModel): `route_map` takes precedence. Only applicable if `source_protocol` is `isis`. """ - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None """ Routes learned by the OSPF protocol. The `ospf_route_type` is valid for source_protocols 'ospf' and 'ospfv3'. @@ -20883,11 +21058,11 @@ class RedistributeRoutesItem(AvdDictBaseModel): def __init__( self, - source_protocol: Literal["connected", "isis", "ospf", "ospfv3", "static"] = None, + source_protocol: Annotated[str, ValidValues["connected", "isis", "ospf", "ospfv3", "static"]] = None, include_leaked: bool | None = None, route_map: str | None = None, rcf: str | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None, + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None, **kwargs, ): """ @@ -21016,13 +21191,13 @@ def __init__(self, neighbors: list[NeighborsItem] | None = None, peer_groups: li class AddressFamilyLinkState(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -21050,13 +21225,13 @@ def __init__(self, missing_policy: MissingPolicy | None = None, **kwargs): class PeerGroupsItem(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -21091,13 +21266,13 @@ def __init__(self, name: str = None, activate: bool | None = None, missing_polic class NeighborsItem(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -21192,13 +21367,13 @@ def __init__( class AddressFamilyFlowSpecIpv4(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -21278,13 +21453,13 @@ def __init__(self, bgp: Bgp | None = None, neighbors: list[NeighborsItem] | None class AddressFamilyFlowSpecIpv6(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -21694,9 +21869,9 @@ def __init__( return super().__init__(**kwargs) class Route(AvdDictBaseModel): - import_match_failure_action: Literal["discard"] | None = None + import_match_failure_action: Annotated[str, ValidValues["discard"]] | None = None - def __init__(self, import_match_failure_action: Literal["discard"] | None = None, **kwargs): + def __init__(self, import_match_failure_action: Annotated[str, ValidValues["discard"]] | None = None, **kwargs): """ Args: ----- @@ -21914,9 +22089,9 @@ def __init__( return super().__init__(**kwargs) class Route(AvdDictBaseModel): - import_match_failure_action: Literal["discard"] | None = None + import_match_failure_action: Annotated[str, ValidValues["discard"]] | None = None - def __init__(self, import_match_failure_action: Literal["discard"] | None = None, **kwargs): + def __init__(self, import_match_failure_action: Annotated[str, ValidValues["discard"]] | None = None, **kwargs): """ Args: ----- @@ -22094,7 +22269,7 @@ def __init__(self, ipv4: Ipv4 | None = None, **kwargs): return super().__init__(**kwargs) class DefaultRouteExportsItem(AvdDictBaseModel): - address_family: Literal["evpn", "vpn-ipv4", "vpn-ipv6"] = None + address_family: Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]] = None always: bool | None = None route_map: str | None = None rcf: str | None = None @@ -22105,7 +22280,7 @@ class DefaultRouteExportsItem(AvdDictBaseModel): def __init__( self, - address_family: Literal["evpn", "vpn-ipv4", "vpn-ipv6"] = None, + address_family: Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]] = None, always: bool | None = None, route_map: str | None = None, rcf: str | None = None, @@ -22311,7 +22486,7 @@ class ListenRangesItem(AvdDictBaseModel): If both are defined, peer_filter takes precedence. """ - remote_as: Annotated[str, ConvertTypes[int]] | None = None + remote_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -22324,7 +22499,7 @@ def __init__( peer_id_include_router_id: bool | None = None, peer_group: str | None = None, peer_filter: str | None = None, - remote_as: Annotated[str, ConvertTypes[int]] | None = None, + remote_as: str | None = None, **kwargs, ): """ @@ -22481,7 +22656,7 @@ def __init__(self, enabled: bool | None = None, always: bool | None = None, rout ip_address: str = None peer_group: str | None = None """Peer-group name.""" - remote_as: Annotated[str, ConvertTypes[int]] | None = None + remote_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -22493,7 +22668,7 @@ def __init__(self, enabled: bool | None = None, always: bool | None = None, rout """Remove private AS numbers in outbound AS path.""" remove_private_as_ingress: RemovePrivateAsIngress | None = None weight: int | None = None - local_as: Annotated[str, ConvertTypes[int]] | None = None + local_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -22517,7 +22692,7 @@ def __init__(self, enabled: bool | None = None, always: bool | None = None, rout send_community: str | None = None """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" maximum_routes: int | None = None - maximum_routes_warning_limit: Annotated[str, ConvertTypes[int]] | None = None + maximum_routes_warning_limit: str | None = None """ Maximum number of routes after which a warning is issued (0 means never warn) or Percentage of maximum number of routes @@ -22540,13 +22715,13 @@ def __init__( self, ip_address: str = None, peer_group: str | None = None, - remote_as: Annotated[str, ConvertTypes[int]] | None = None, + remote_as: str | None = None, password: str | None = None, passive: bool | None = None, remove_private_as: RemovePrivateAs | None = None, remove_private_as_ingress: RemovePrivateAsIngress | None = None, weight: int | None = None, - local_as: Annotated[str, ConvertTypes[int]] | None = None, + local_as: str | None = None, as_path: AsPath | None = None, description: str | None = None, route_reflector_client: bool | None = None, @@ -22559,7 +22734,7 @@ def __init__( rib_in_pre_policy_retain: RibInPrePolicyRetain | None = None, send_community: str | None = None, maximum_routes: int | None = None, - maximum_routes_warning_limit: Annotated[str, ConvertTypes[int]] | None = None, + maximum_routes_warning_limit: str | None = None, maximum_routes_warning_only: bool | None = None, allowas_in: AllowasIn | None = None, default_originate: DefaultOriginate | None = None, @@ -22649,7 +22824,7 @@ def __init__( class NeighborInterfacesItem(AvdDictBaseModel): name: str = None """Interface name.""" - remote_as: Annotated[str, ConvertTypes[int]] | None = None + remote_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -22664,7 +22839,7 @@ class NeighborInterfacesItem(AvdDictBaseModel): def __init__( self, name: str = None, - remote_as: Annotated[str, ConvertTypes[int]] | None = None, + remote_as: str | None = None, peer_group: str | None = None, peer_filter: str | None = None, description: str | None = None, @@ -22703,7 +22878,7 @@ class RedistributeRoutesItem(AvdDictBaseModel): Only applicable if `source_protocol` is one of `connected`, `dynamic`, `isis`, `static` and `user`. """ - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None """ Routes learned by the OSPF protocol. The `ospf_route_type` is valid for source_protocols 'ospf' and 'ospfv3'. @@ -22715,7 +22890,7 @@ def __init__( route_map: str | None = None, include_leaked: bool | None = None, rcf: str | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None, + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None, **kwargs, ): """ @@ -22784,13 +22959,13 @@ def __init__( class AddressFamilyIpv4(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -23005,7 +23180,9 @@ def __init__(self, prefix: str = None, route_map: str | None = None, **kwargs): return super().__init__(**kwargs) class RedistributeRoutesItem(AvdDictBaseModel): - source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] = None + source_protocol: Annotated[ + str, ValidValues["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + ] = None route_map: str | None = None include_leaked: bool | None = None rcf: str | None = None @@ -23017,7 +23194,7 @@ class RedistributeRoutesItem(AvdDictBaseModel): Only applicable if `source_protocol` is one of `connected`, `dynamic`, `isis`, `static` and `user`. """ - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None """ Routes learned by the OSPF protocol. The `ospf_route_type` is valid for source_protocols 'ospf' and 'ospfv3'. @@ -23025,11 +23202,15 @@ class RedistributeRoutesItem(AvdDictBaseModel): def __init__( self, - source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] = None, + source_protocol: Annotated[ + str, ValidValues["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + ] = None, route_map: str | None = None, include_leaked: bool | None = None, rcf: str | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None, + ospf_route_type: ( + Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None + ) = None, **kwargs, ): """ @@ -23088,13 +23269,13 @@ def __init__( class AddressFamilyIpv6(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -23276,7 +23457,9 @@ def __init__(self, prefix: str = None, route_map: str | None = None, **kwargs): return super().__init__(**kwargs) class RedistributeRoutesItem(AvdDictBaseModel): - source_protocol: Literal["attached-host", "bgp", "connected", "dhcp", "dynamic", "isis", "ospfv3", "static", "user"] = None + source_protocol: Annotated[str, ValidValues["attached-host", "bgp", "connected", "dhcp", "dynamic", "isis", "ospfv3", "static", "user"]] = ( + None + ) route_map: str | None = None include_leaked: bool | None = None rcf: str | None = None @@ -23288,7 +23471,7 @@ class RedistributeRoutesItem(AvdDictBaseModel): Only applicable if `source_protocol` is one of `connected`, `dynamic`, `isis`, `static` and `user`. """ - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None """ Routes learned by the OSPF protocol. The `ospf_route_type` is valid for source_protocols 'ospfv3'. @@ -23296,11 +23479,15 @@ class RedistributeRoutesItem(AvdDictBaseModel): def __init__( self, - source_protocol: Literal["attached-host", "bgp", "connected", "dhcp", "dynamic", "isis", "ospfv3", "static", "user"] = None, + source_protocol: Annotated[ + str, ValidValues["attached-host", "bgp", "connected", "dhcp", "dynamic", "isis", "ospfv3", "static", "user"] + ] = None, route_map: str | None = None, include_leaked: bool | None = None, rcf: str | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None, + ospf_route_type: ( + Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None + ) = None, **kwargs, ): """ @@ -23359,13 +23546,13 @@ def __init__( class AddressFamilyIpv4Multicast(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -23451,7 +23638,7 @@ def __init__(self, prefix: str = None, route_map: str | None = None, **kwargs): return super().__init__(**kwargs) class RedistributeRoutesItem(AvdDictBaseModel): - source_protocol: Literal["attached-host", "connected", "isis", "ospf", "ospfv3", "static"] = None + source_protocol: Annotated[str, ValidValues["attached-host", "connected", "isis", "ospf", "ospfv3", "static"]] = None route_map: str | None = None include_leaked: bool | None = None """Only applicable if `source_protocol` is `isis`.""" @@ -23463,7 +23650,7 @@ class RedistributeRoutesItem(AvdDictBaseModel): `route_map` takes precedence. Only applicable if `source_protocol` is `isis`. """ - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None """ Routes learned by the OSPF protocol. The `ospf_route_type` is valid for source_protocols 'ospf' and 'ospfv3'. @@ -23471,11 +23658,13 @@ class RedistributeRoutesItem(AvdDictBaseModel): def __init__( self, - source_protocol: Literal["attached-host", "connected", "isis", "ospf", "ospfv3", "static"] = None, + source_protocol: Annotated[str, ValidValues["attached-host", "connected", "isis", "ospf", "ospfv3", "static"]] = None, route_map: str | None = None, include_leaked: bool | None = None, rcf: str | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None, + ospf_route_type: ( + Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None + ) = None, **kwargs, ): """ @@ -23533,13 +23722,13 @@ def __init__( class AddressFamilyIpv6Multicast(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -23625,7 +23814,7 @@ def __init__(self, prefix: str = None, route_map: str | None = None, **kwargs): return super().__init__(**kwargs) class RedistributeRoutesItem(AvdDictBaseModel): - source_protocol: Literal["connected", "isis", "ospf", "ospfv3", "static"] = None + source_protocol: Annotated[str, ValidValues["connected", "isis", "ospf", "ospfv3", "static"]] = None route_map: str | None = None include_leaked: bool | None = None """Only applicable if `source_protocol` is `isis`.""" @@ -23637,7 +23826,7 @@ class RedistributeRoutesItem(AvdDictBaseModel): `route_map` takes precedence. Only applicable if `source_protocol` is `isis`. """ - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None = None """ Routes learned by the OSPF protocol. The `ospf_route_type` is valid for source_protocols 'ospf' and 'ospfv3'. @@ -23645,11 +23834,13 @@ class RedistributeRoutesItem(AvdDictBaseModel): def __init__( self, - source_protocol: Literal["connected", "isis", "ospf", "ospfv3", "static"] = None, + source_protocol: Annotated[str, ValidValues["connected", "isis", "ospf", "ospfv3", "static"]] = None, route_map: str | None = None, include_leaked: bool | None = None, rcf: str | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None = None, + ospf_route_type: ( + Annotated[str, ValidValues["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"]] | None + ) = None, **kwargs, ): """ @@ -23707,13 +23898,13 @@ def __init__( class AddressFamilyFlowSpecIpv4(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -23773,13 +23964,13 @@ def __init__(self, bgp: Bgp | None = None, neighbors: list[NeighborsItem] | None class AddressFamilyFlowSpecIpv6(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -23839,13 +24030,13 @@ def __init__(self, bgp: Bgp | None = None, neighbors: list[NeighborsItem] | None class AddressFamiliesItem(AvdDictBaseModel): class Bgp(AvdDictBaseModel): class MissingPolicy(AvdDictBaseModel): - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None def __init__( self, - direction_in_action: Literal["deny", "deny-in-out", "permit"] | None = None, - direction_out_action: Literal["deny", "deny-in-out", "permit"] | None = None, + direction_in_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, + direction_out_action: Annotated[str, ValidValues["deny", "deny-in-out", "permit"]] | None = None, **kwargs, ): """ @@ -23982,7 +24173,7 @@ def __init__( self.networks = networks return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF name.""" bgp: Bgp | None = None rd: str | None = None @@ -24017,7 +24208,7 @@ def __init__( def __init__( self, - name: Annotated[str, ConvertTypes[int]] = None, + name: str = None, bgp: Bgp | None = None, rd: str | None = None, evpn_multicast: bool | None = None, @@ -24116,13 +24307,13 @@ def __init__(self, name: str = None, recovery_delay: int | None = None, **kwargs self.recovery_delay = recovery_delay return super().__init__(**kwargs) - field_as: Annotated[str, ConvertTypes[int]] | None = None + field_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float number. """ - as_notation: Literal["asdot", "asplain"] | None = None + as_notation: Annotated[str, ValidValues["asdot", "asplain"]] | None = None """ BGP AS can be deplayed in the asplain <1-4294967295> or asdot notation "<1-65535>.<0-65535>". This flag indicates which mode is preferred - asplain is the default. @@ -24170,8 +24361,8 @@ def __init__(self, name: str = None, recovery_delay: int | None = None, **kwargs def __init__( self, - field_as: Annotated[str, ConvertTypes[int]] | None = None, - as_notation: Literal["asdot", "asplain"] | None = None, + field_as: str | None = None, + as_notation: Annotated[str, ValidValues["asdot", "asplain"]] | None = None, router_id: str | None = None, distance: Distance | None = None, graceful_restart: GracefulRestart | None = None, @@ -24316,11 +24507,11 @@ def __init__(self, ipv4: str | None = None, ipv6: str | None = None, **kwargs): class VrfsItem(AvdDictBaseModel): class LeakRoutesItem(AvdDictBaseModel): - source_vrf: Annotated[str, ConvertTypes[int]] | None = None + source_vrf: str | None = None subscribe_policy: str | None = None """Route-Map Policy.""" - def __init__(self, source_vrf: Annotated[str, ConvertTypes[int]] | None = None, subscribe_policy: str | None = None, **kwargs): + def __init__(self, source_vrf: str | None = None, subscribe_policy: str | None = None, **kwargs): """ Args: ----- @@ -24359,14 +24550,12 @@ def __init__(self, dynamic_prefix_lists: list[DynamicPrefixListsItem] | None = N self.dynamic_prefix_lists = dynamic_prefix_lists return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """Destination-VRF.""" leak_routes: list[LeakRoutesItem] | None = None routes: Routes | None = None - def __init__( - self, name: Annotated[str, ConvertTypes[int]] = None, leak_routes: list[LeakRoutesItem] | None = None, routes: Routes | None = None, **kwargs - ): + def __init__(self, name: str = None, leak_routes: list[LeakRoutesItem] | None = None, routes: Routes | None = None, **kwargs): """ Args: ----- @@ -24472,7 +24661,7 @@ class RouterIgmp(AvdDictBaseModel): class VrfsItem(AvdDictBaseModel): name: str = None """VRF name.""" - host_proxy_match_mroute: Literal["all", "iif"] | None = None + host_proxy_match_mroute: Annotated[str, ValidValues["all", "iif"]] | None = None """ Specify conditions for sending IGMP joins for host-proxy. 'iif' will enable igmp host-proxy to work in iif aware. @@ -24480,7 +24669,7 @@ class VrfsItem(AvdDictBaseModel): will enable igmp host-proxy to work in iif unaware mode (EOS default). """ - def __init__(self, name: str = None, host_proxy_match_mroute: Literal["all", "iif"] | None = None, **kwargs): + def __init__(self, name: str = None, host_proxy_match_mroute: Annotated[str, ValidValues["all", "iif"]] | None = None, **kwargs): """ Args: ----- @@ -24496,7 +24685,7 @@ def __init__(self, name: str = None, host_proxy_match_mroute: Literal["all", "ii self.host_proxy_match_mroute = host_proxy_match_mroute return super().__init__(**kwargs) - host_proxy_match_mroute: Literal["all", "iif"] | None = None + host_proxy_match_mroute: Annotated[str, ValidValues["all", "iif"]] | None = None """ Specify conditions for sending IGMP joins for host-proxy. 'iif' will enable igmp host-proxy to work in iif aware. @@ -24511,7 +24700,11 @@ def __init__(self, name: str = None, host_proxy_match_mroute: Literal["all", "ii """ def __init__( - self, host_proxy_match_mroute: Literal["all", "iif"] | None = None, ssm_aware: bool | None = None, vrfs: list[VrfsItem] | None = None, **kwargs + self, + host_proxy_match_mroute: Annotated[str, ValidValues["all", "iif"]] | None = None, + ssm_aware: bool | None = None, + vrfs: list[VrfsItem] | None = None, + **kwargs, ): """ Args: @@ -24724,8 +24917,8 @@ class Both(AvdDictBaseModel): class KeyIdsItem(AvdDictBaseModel): id: int = None """Configure authentication key-id.""" - algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] = None + algorithm: Annotated[str, ValidValues["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None + key_type: Annotated[str, ValidValues["0", "7", "8a"]] = None """Configure authentication key type.""" key: str = None """Password string.""" @@ -24735,8 +24928,8 @@ class KeyIdsItem(AvdDictBaseModel): def __init__( self, id: int = None, - algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None, - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] = None, + algorithm: Annotated[str, ValidValues["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None, + key_type: Annotated[str, ValidValues["0", "7", "8a"]] = None, key: str = None, rfc_5310: bool | None = None, **kwargs, @@ -24773,9 +24966,14 @@ def __init__(self, key_id: int = None, **kwargs): class SharedSecret(AvdDictBaseModel): profile: str = None - algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None + algorithm: Annotated[str, ValidValues["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None - def __init__(self, profile: str = None, algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None, **kwargs): + def __init__( + self, + profile: str = None, + algorithm: Annotated[str, ValidValues["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None, + **kwargs, + ): """ Args: ----- @@ -24787,12 +24985,12 @@ def __init__(self, profile: str = None, algorithm: Literal["md5", "sha-1", "sha- self.algorithm = algorithm return super().__init__(**kwargs) - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = None + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = None """Configure authentication key type. Default key_id is 0.""" key: str | None = None """Password string.""" key_ids: list[KeyIdsItem] | None = None - mode: Literal["md5", "sha", "text", "shared_secret"] | None = None + mode: Annotated[str, ValidValues["md5", "sha", "text", "shared_secret"]] | None = None """Authentication mode.""" sha: Sha | None = None """Required settings for authentication mode 'sha'.""" @@ -24802,10 +25000,10 @@ def __init__(self, profile: str = None, algorithm: Literal["md5", "sha-1", "sha- def __init__( self, - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = None, + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = None, key: str | None = None, key_ids: list[KeyIdsItem] | None = None, - mode: Literal["md5", "sha", "text", "shared_secret"] | None = None, + mode: Annotated[str, ValidValues["md5", "sha", "text", "shared_secret"]] | None = None, sha: Sha | None = None, shared_secret: SharedSecret | None = None, rx_disabled: bool | None = None, @@ -24836,8 +25034,8 @@ class Level1(AvdDictBaseModel): class KeyIdsItem(AvdDictBaseModel): id: int = None """Configure authentication key-id.""" - algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] = None + algorithm: Annotated[str, ValidValues["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None + key_type: Annotated[str, ValidValues["0", "7", "8a"]] = None """Configure authentication key type.""" key: str = None """Password string.""" @@ -24847,8 +25045,8 @@ class KeyIdsItem(AvdDictBaseModel): def __init__( self, id: int = None, - algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None, - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] = None, + algorithm: Annotated[str, ValidValues["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None, + key_type: Annotated[str, ValidValues["0", "7", "8a"]] = None, key: str = None, rfc_5310: bool | None = None, **kwargs, @@ -24885,9 +25083,14 @@ def __init__(self, key_id: int = None, **kwargs): class SharedSecret(AvdDictBaseModel): profile: str = None - algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None + algorithm: Annotated[str, ValidValues["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None - def __init__(self, profile: str = None, algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None, **kwargs): + def __init__( + self, + profile: str = None, + algorithm: Annotated[str, ValidValues["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None, + **kwargs, + ): """ Args: ----- @@ -24899,12 +25102,12 @@ def __init__(self, profile: str = None, algorithm: Literal["md5", "sha-1", "sha- self.algorithm = algorithm return super().__init__(**kwargs) - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = None + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = None """Configure authentication key type. Default key_id is 0.""" key: str | None = None """Password string.""" key_ids: list[KeyIdsItem] | None = None - mode: Literal["md5", "sha", "text", "shared_secret"] | None = None + mode: Annotated[str, ValidValues["md5", "sha", "text", "shared_secret"]] | None = None """Authentication mode.""" sha: Sha | None = None """Required settings for authentication mode 'sha'.""" @@ -24914,10 +25117,10 @@ def __init__(self, profile: str = None, algorithm: Literal["md5", "sha-1", "sha- def __init__( self, - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = None, + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = None, key: str | None = None, key_ids: list[KeyIdsItem] | None = None, - mode: Literal["md5", "sha", "text", "shared_secret"] | None = None, + mode: Annotated[str, ValidValues["md5", "sha", "text", "shared_secret"]] | None = None, sha: Sha | None = None, shared_secret: SharedSecret | None = None, rx_disabled: bool | None = None, @@ -24948,8 +25151,8 @@ class Level2(AvdDictBaseModel): class KeyIdsItem(AvdDictBaseModel): id: int = None """Configure authentication key-id.""" - algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] = None + algorithm: Annotated[str, ValidValues["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None + key_type: Annotated[str, ValidValues["0", "7", "8a"]] = None """Configure authentication key type.""" key: str = None """Password string.""" @@ -24959,8 +25162,8 @@ class KeyIdsItem(AvdDictBaseModel): def __init__( self, id: int = None, - algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None, - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] = None, + algorithm: Annotated[str, ValidValues["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None, + key_type: Annotated[str, ValidValues["0", "7", "8a"]] = None, key: str = None, rfc_5310: bool | None = None, **kwargs, @@ -24997,9 +25200,14 @@ def __init__(self, key_id: int = None, **kwargs): class SharedSecret(AvdDictBaseModel): profile: str = None - algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None + algorithm: Annotated[str, ValidValues["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None - def __init__(self, profile: str = None, algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] = None, **kwargs): + def __init__( + self, + profile: str = None, + algorithm: Annotated[str, ValidValues["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"]] = None, + **kwargs, + ): """ Args: ----- @@ -25011,12 +25219,12 @@ def __init__(self, profile: str = None, algorithm: Literal["md5", "sha-1", "sha- self.algorithm = algorithm return super().__init__(**kwargs) - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = None + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = None """Configure authentication key type. Default key_id is 0.""" key: str | None = None """Password string.""" key_ids: list[KeyIdsItem] | None = None - mode: Literal["md5", "sha", "text", "shared_secret"] | None = None + mode: Annotated[str, ValidValues["md5", "sha", "text", "shared_secret"]] | None = None """Authentication mode.""" sha: Sha | None = None """Required settings for authentication mode 'sha'.""" @@ -25026,10 +25234,10 @@ def __init__(self, profile: str = None, algorithm: Literal["md5", "sha-1", "sha- def __init__( self, - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = None, + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = None, key: str | None = None, key_ids: list[KeyIdsItem] | None = None, - mode: Literal["md5", "sha", "text", "shared_secret"] | None = None, + mode: Annotated[str, ValidValues["md5", "sha", "text", "shared_secret"]] | None = None, sha: Sha | None = None, shared_secret: SharedSecret | None = None, rx_disabled: bool | None = None, @@ -25091,19 +25299,19 @@ def __init__(self, passive_only: bool | None = None, **kwargs): return super().__init__(**kwargs) class RedistributeRoutesItem(AvdDictBaseModel): - source_protocol: Literal["bgp", "connected", "isis", "ospf", "ospfv3", "static"] = None + source_protocol: Annotated[str, ValidValues["bgp", "connected", "isis", "ospf", "ospfv3", "static"]] = None route_map: str | None = None """Route-map name.""" include_leaked: bool | None = None - ospf_route_type: Literal["external", "internal", "nssa-external"] | None = None + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external"]] | None = None """ospf_route_type is required with source_protocols 'ospf' and 'ospfv3'.""" def __init__( self, - source_protocol: Literal["bgp", "connected", "isis", "ospf", "ospfv3", "static"] = None, + source_protocol: Annotated[str, ValidValues["bgp", "connected", "isis", "ospf", "ospfv3", "static"]] = None, route_map: str | None = None, include_leaked: bool | None = None, - ospf_route_type: Literal["external", "internal", "nssa-external"] | None = None, + ospf_route_type: Annotated[str, ValidValues["external", "internal", "nssa-external"]] | None = None, **kwargs, ): """ @@ -25139,15 +25347,15 @@ def __init__(self, enable: bool | None = None, strict: bool | None = None, **kwa self.strict = strict return super().__init__(**kwargs) - mode: Literal["link-protection", "node-protection"] | None = None - level: Literal["level-1", "level-2"] | None = None + mode: Annotated[str, ValidValues["link-protection", "node-protection"]] | None = None + level: Annotated[str, ValidValues["level-1", "level-2"]] | None = None srlg: Srlg | None = None """Shared Risk Link Group.""" def __init__( self, - mode: Literal["link-protection", "node-protection"] | None = None, - level: Literal["level-1", "level-2"] | None = None, + mode: Annotated[str, ValidValues["link-protection", "node-protection"]] | None = None, + level: Annotated[str, ValidValues["level-1", "level-2"]] | None = None, srlg: Srlg | None = None, **kwargs, ): @@ -25232,16 +25440,16 @@ def __init__(self, enable: bool | None = None, strict: bool | None = None, **kwa self.strict = strict return super().__init__(**kwargs) - mode: Literal["link-protection", "node-protection"] | None = None - level: Literal["level-1", "level-2"] | None = None + mode: Annotated[str, ValidValues["link-protection", "node-protection"]] | None = None + level: Annotated[str, ValidValues["level-1", "level-2"]] | None = None """Optional, default is to protect all levels.""" srlg: Srlg | None = None """Shared Risk Link Group.""" def __init__( self, - mode: Literal["link-protection", "node-protection"] | None = None, - level: Literal["level-1", "level-2"] | None = None, + mode: Annotated[str, ValidValues["link-protection", "node-protection"]] | None = None, + level: Annotated[str, ValidValues["level-1", "level-2"]] | None = None, srlg: Srlg | None = None, **kwargs, ): @@ -25330,7 +25538,7 @@ class SpfInterval(AvdDictBaseModel): Range in milliseconds: <1-300000> """ - interval_unit: Literal["seconds", "milliseconds"] | None = None + interval_unit: Annotated[str, ValidValues["seconds", "milliseconds"]] | None = None """If interval unit is not defined EOS takes `seconds` by default.""" wait_interval: int | None = None """Initial wait interval for SPF in milliseconds.""" @@ -25340,7 +25548,7 @@ class SpfInterval(AvdDictBaseModel): def __init__( self, interval: int | None = None, - interval_unit: Literal["seconds", "milliseconds"] | None = None, + interval_unit: Annotated[str, ValidValues["seconds", "milliseconds"]] | None = None, wait_interval: int | None = None, hold_interval: int | None = None, **kwargs, @@ -25408,14 +25616,14 @@ def __init__(self, enabled: bool | None = None, restart_hold_time: int | None = """CLNS Address like "49.0001.0001.0000.0001.00".""" router_id: str | None = None """IPv4 Address.""" - is_type: Literal["level-1", "level-1-2", "level-2"] | None = None + is_type: Annotated[str, ValidValues["level-1", "level-1-2", "level-2"]] | None = None log_adjacency_changes: bool | None = None mpls_ldp_sync_default: bool | None = None timers: Timers | None = None set_overload_bit: SetOverloadBit | None = None authentication: Authentication | None = None advertise: Advertise | None = None - address_family: list[str] | None = None + address_family: list[Annotated[str, ValidValues["ipv4", "ipv6", "ipv4 unicast", "ipv6 unicast"]]] | None = None isis_af_defaults: list[str] | None = None redistribute_routes: list[RedistributeRoutesItem] | None = None address_family_ipv4: AddressFamilyIpv4 | None = None @@ -25431,14 +25639,14 @@ def __init__( instance: str = None, net: str | None = None, router_id: str | None = None, - is_type: Literal["level-1", "level-1-2", "level-2"] | None = None, + is_type: Annotated[str, ValidValues["level-1", "level-1-2", "level-2"]] | None = None, log_adjacency_changes: bool | None = None, mpls_ldp_sync_default: bool | None = None, timers: Timers | None = None, set_overload_bit: SetOverloadBit | None = None, authentication: Authentication | None = None, advertise: Advertise | None = None, - address_family: list[str] | None = None, + address_family: list[Annotated[str, ValidValues["ipv4", "ipv6", "ipv4 unicast", "ipv6 unicast"]]] | None = None, isis_af_defaults: list[str] | None = None, redistribute_routes: list[RedistributeRoutesItem] | None = None, address_family_ipv4: AddressFamilyIpv4 | None = None, @@ -25837,7 +26045,7 @@ def __init__( self.sa_filter = sa_filter return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF name.""" originator_id_local_interface: str | None = None """Interface to use for originator ID.""" @@ -25850,7 +26058,7 @@ def __init__( def __init__( self, - name: Annotated[str, ConvertTypes[int]] = None, + name: str = None, originator_id_local_interface: str | None = None, rejected_limit: int | None = None, forward_register_packets: bool | None = None, @@ -25990,8 +26198,8 @@ def __init__(self, routes: list[RoutesItem] | None = None, **kwargs): """MFIB entry activity polling interval.""" counters: Counters | None = None routing: bool | None = None - multipath: Literal["none", "deterministic", "deterministic color", "deterministic router-id"] | None = None - software_forwarding: Literal["kernel", "sfe"] | None = None + multipath: Annotated[str, ValidValues["none", "deterministic", "deterministic color", "deterministic router-id"]] | None = None + software_forwarding: Annotated[str, ValidValues["kernel", "sfe"]] | None = None rpf: Rpf | None = None def __init__( @@ -25999,8 +26207,8 @@ def __init__( activity_polling_interval: int | None = None, counters: Counters | None = None, routing: bool | None = None, - multipath: Literal["none", "deterministic", "deterministic color", "deterministic router-id"] | None = None, - software_forwarding: Literal["kernel", "sfe"] | None = None, + multipath: Annotated[str, ValidValues["none", "deterministic", "deterministic color", "deterministic router-id"]] | None = None, + software_forwarding: Annotated[str, ValidValues["kernel", "sfe"]] | None = None, rpf: Rpf | None = None, **kwargs, ): @@ -26051,10 +26259,10 @@ def __init__(self, routing: bool | None = None, **kwargs): self.routing = routing return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None ipv4: Ipv4 | None = None - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, ipv4: Ipv4 | None = None, **kwargs): + def __init__(self, name: str = None, ipv4: Ipv4 | None = None, **kwargs): """ Args: ----- @@ -26215,10 +26423,10 @@ class DefaultInformationOriginate(AvdDictBaseModel): always: bool | None = None metric: int | None = None """Metric for default route.""" - metric_type: Literal[1, 2] | None = None + metric_type: int | None = None """OSPF metric type for default route.""" - def __init__(self, always: bool | None = None, metric: int | None = None, metric_type: Literal[1, 2] | None = None, **kwargs): + def __init__(self, always: bool | None = None, metric: int | None = None, metric_type: int | None = None, **kwargs): """ Args: ----- @@ -26346,10 +26554,10 @@ def __init__(self, networks: list[str] | None = None, prefix_list: str | None = class DefaultInformationOriginate(AvdDictBaseModel): metric: int | None = None """Metric for default route.""" - metric_type: Literal[1, 2] | None = None + metric_type: int | None = None """OSPF metric type for default route.""" - def __init__(self, metric: int | None = None, metric_type: Literal[1, 2] | None = None, **kwargs): + def __init__(self, metric: int | None = None, metric_type: int | None = None, **kwargs): """ Args: ----- @@ -26361,18 +26569,18 @@ def __init__(self, metric: int | None = None, metric_type: Literal[1, 2] | None self.metric_type = metric_type return super().__init__(**kwargs) - id: Annotated[str, ConvertTypes[int]] = None + id: str = None filter: Filter | None = None - type: Literal["normal", "stub", "nssa"] | None = "normal" + type: Annotated[str, ValidValues["normal", "stub", "nssa"]] | None = "normal" no_summary: bool | None = None nssa_only: bool | None = None default_information_originate: DefaultInformationOriginate | None = None def __init__( self, - id: Annotated[str, ConvertTypes[int]] = None, + id: str = None, filter: Filter | None = None, - type: Literal["normal", "stub", "nssa"] | None = "normal", + type: Annotated[str, ValidValues["normal", "stub", "nssa"]] | None = "normal", no_summary: bool | None = None, nssa_only: bool | None = None, default_information_originate: DefaultInformationOriginate | None = None, @@ -26427,7 +26635,7 @@ def __init__(self, override_metric: int | None = None, **kwargs): external_lsa: ExternalLsa | None = None include_stub: bool | None = None - on_startup: Annotated[str, ConvertTypes[int]] | None = None + on_startup: str | None = None """ "wait-for-bgp" or Integer 5-86400. Example: "wait-for-bgp" Or "222" @@ -26438,7 +26646,7 @@ def __init__( self, external_lsa: ExternalLsa | None = None, include_stub: bool | None = None, - on_startup: Annotated[str, ConvertTypes[int]] | None = None, + on_startup: str | None = None, summary_lsa: SummaryLsa | None = None, **kwargs, ): @@ -26473,7 +26681,7 @@ def __init__(self, router_lsa: RouterLsa | None = None, **kwargs): id: int = None """OSPF Process ID.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name for OSPF Process.""" passive_interface_default: bool | None = None router_id: str | None = None @@ -26502,7 +26710,7 @@ def __init__(self, router_lsa: RouterLsa | None = None, **kwargs): def __init__( self, id: int = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, passive_interface_default: bool | None = None, router_id: str | None = None, distance: Distance | None = None, @@ -26605,7 +26813,7 @@ def __init__(self, server_profiles: list[str] = None, **kwargs): self.server_profiles = server_profiles return super().__init__(**kwargs) - name: Annotated[str, Pattern["^Ethernet\d+(/\d+)*(\.\d+)?$"]] = None + name: Annotated[str, Pattern[r"^Ethernet\d+(/\d+)*(\.\d+)?$"]] = None """Local interface name.""" public_address: str | None = None """Public IP assigned by NAT.""" @@ -26613,7 +26821,7 @@ def __init__(self, server_profiles: list[str] = None, **kwargs): def __init__( self, - name: Annotated[str, Pattern["^Ethernet\d+(/\d+)*(\.\d+)?$"]] = None, + name: Annotated[str, Pattern[r"^Ethernet\d+(/\d+)*(\.\d+)?$"]] = None, public_address: str | None = None, stun: Stun | None = None, **kwargs, @@ -26737,7 +26945,7 @@ def __init__(self, auto: bool | None = False, interval: int | None = None, failu """Path group ID.""" ipsec_profile: str | None = None """IPSec profile for the path group.""" - flow_assignment: Literal["lan"] | None = None + flow_assignment: Annotated[str, ValidValues["lan"]] | None = None """Flow assignment `lan` can not be configured in a path group with dynamic peers.""" local_interfaces: list[LocalInterfacesItem] | None = None local_ips: list[LocalIpsItem] | None = None @@ -26751,7 +26959,7 @@ def __init__( name: str = None, id: int | None = None, ipsec_profile: str | None = None, - flow_assignment: Literal["lan"] | None = None, + flow_assignment: Annotated[str, ValidValues["lan"]] | None = None, local_interfaces: list[LocalInterfacesItem] | None = None, local_ips: list[LocalIpsItem] | None = None, dynamic_peers: DynamicPeers | None = None, @@ -26816,7 +27024,7 @@ def __init__(self, name: str = None, priority: int | None = None, **kwargs): """Jitter requirement for this load balance policy in milliseconds.""" latency: int | None = None """One way delay requirement for this load balance policy in milliseconds.""" - loss_rate: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None + loss_rate: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None """ Loss Rate requirement in percentage for this load balance policy. Value between 0.00 and 100.00. @@ -26830,7 +27038,7 @@ def __init__( lowest_hop_count: bool | None = None, jitter: int | None = None, latency: int | None = None, - loss_rate: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None, + loss_rate: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None, path_groups: list[PathGroupsItem] | None = None, **kwargs, ): @@ -26929,7 +27137,7 @@ def __init__(self, name: str = None, path_selection_policy: str | None = None, * return super().__init__(**kwargs) class TcpMssCeiling(AvdDictBaseModel): - ipv4_segment_size: Annotated[str, ConvertTypes[int]] | None = None + ipv4_segment_size: str | None = None """ Segment Size for IPv4. Can be an integer in the range 64-65515 or "auto". @@ -26938,13 +27146,13 @@ class TcpMssCeiling(AvdDictBaseModel): and multi-hop path MTU towards a remote VTEP (minus 40bytes to account for IP + TCP header). """ - direction: Literal["ingress"] | None = "ingress" + direction: Annotated[str, ValidValues["ingress"]] | None = "ingress" """ Enforce on packets through DPS tunnel for a specific direction. Only 'ingress' direction is supported. """ - def __init__(self, ipv4_segment_size: Annotated[str, ConvertTypes[int]] | None = None, direction: Literal["ingress"] | None = "ingress", **kwargs): + def __init__(self, ipv4_segment_size: str | None = None, direction: Annotated[str, ValidValues["ingress"]] | None = "ingress", **kwargs): """ Args: ----- @@ -26964,7 +27172,7 @@ def __init__(self, ipv4_segment_size: Annotated[str, ConvertTypes[int]] | None = self.direction = direction return super().__init__(**kwargs) - peer_dynamic_source: Literal["stun"] | None = None + peer_dynamic_source: Annotated[str, ValidValues["stun"]] | None = None """Source of dynamic peer discovery.""" path_groups: list[PathGroupsItem] | None = None load_balance_policies: list[LoadBalancePoliciesItem] | None = None @@ -26974,7 +27182,7 @@ def __init__(self, ipv4_segment_size: Annotated[str, ConvertTypes[int]] | None = def __init__( self, - peer_dynamic_source: Literal["stun"] | None = None, + peer_dynamic_source: Annotated[str, ValidValues["stun"]] | None = None, path_groups: list[PathGroupsItem] | None = None, load_balance_policies: list[LoadBalancePoliciesItem] | None = None, policies: list[PoliciesItem] | None = None, @@ -27161,11 +27369,11 @@ def __init__(self, bfd: bool | None = None, rp_addresses: list[RpAddressesItem] self.rp_addresses = rp_addresses return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF Name.""" ipv4: Ipv4 | None = None - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, ipv4: Ipv4 | None = None, **kwargs): + def __init__(self, name: str = None, ipv4: Ipv4 | None = None, **kwargs): """ Args: ----- @@ -27199,7 +27407,7 @@ class SequenceNumbersItem(AvdDictBaseModel): """Sequence ID.""" application: str = None """The name of the application.""" - action: Literal["forward", "drop", "redirect"] = None + action: Annotated[str, ValidValues["forward", "drop", "redirect"]] = None """ The action to take - note that platform support for the redirect action is limited. The "redirect" action also requires the 'next_hop' to be configured. @@ -27215,7 +27423,7 @@ def __init__( self, sequence: int = None, application: str = None, - action: Literal["forward", "drop", "redirect"] = None, + action: Annotated[str, ValidValues["forward", "drop", "redirect"]] = None, log: bool | None = None, stateless: bool | None = True, next_hop: str | None = None, @@ -27262,7 +27470,7 @@ class VrfsItem(AvdDictBaseModel): class SegmentsItem(AvdDictBaseModel): class Definition(AvdDictBaseModel): class MatchListsItem(AvdDictBaseModel): - address_family: Literal["ipv4", "ipv6"] = None + address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] = None """Indicate which address-family the match list belongs to e.g. ipv4 or ipv6.""" covered_prefix_list: str | None = None """ @@ -27276,7 +27484,11 @@ class MatchListsItem(AvdDictBaseModel): """ def __init__( - self, address_family: Literal["ipv4", "ipv6"] = None, covered_prefix_list: str | None = None, prefix: str | None = None, **kwargs + self, + address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] = None, + covered_prefix_list: str | None = None, + prefix: str | None = None, + **kwargs, ): """ Args: @@ -27528,7 +27740,7 @@ class PolicyEndpointsItem(AvdDictBaseModel): class ColorsItem(AvdDictBaseModel): class PathGroupItem(AvdDictBaseModel): class SegmentListItem(AvdDictBaseModel): - label_stack: Annotated[str, ConvertTypes[int]] | None = None + label_stack: str | None = None """ Label Stack as string. Example: "100 2000 30" @@ -27536,13 +27748,7 @@ class SegmentListItem(AvdDictBaseModel): weight: int | None = None index: int | None = None - def __init__( - self, - label_stack: Annotated[str, ConvertTypes[int]] | None = None, - weight: int | None = None, - index: int | None = None, - **kwargs, - ): + def __init__(self, label_stack: str | None = None, weight: int | None = None, index: int | None = None, **kwargs): """ Args: ----- @@ -27559,13 +27765,13 @@ def __init__( return super().__init__(**kwargs) preference: int | None = None - explicit_null: Literal["ipv4", "ipv6", "ipv4 ipv6", "none"] | None = None + explicit_null: Annotated[str, ValidValues["ipv4", "ipv6", "ipv4 ipv6", "none"]] | None = None segment_list: list[SegmentListItem] | None = None def __init__( self, preference: int | None = None, - explicit_null: Literal["ipv4", "ipv6", "ipv4 ipv6", "none"] | None = None, + explicit_null: Annotated[str, ValidValues["ipv4", "ipv6", "ipv4 ipv6", "none"]] | None = None, segment_list: list[SegmentListItem] | None = None, **kwargs, ): @@ -27586,7 +27792,7 @@ def __init__( binding_sid: int | None = None description: str | None = None name: str | None = None - sbfd_remote_discriminator: Annotated[str, ConvertTypes[int]] | None = None + sbfd_remote_discriminator: str | None = None """IPv4 address or 32 bit integer.""" path_group: list[PathGroupItem] | None = None @@ -27596,7 +27802,7 @@ def __init__( binding_sid: int | None = None, description: str | None = None, name: str | None = None, - sbfd_remote_discriminator: Annotated[str, ConvertTypes[int]] | None = None, + sbfd_remote_discriminator: str | None = None, path_group: list[PathGroupItem] | None = None, **kwargs, ): @@ -27717,7 +27923,7 @@ def __init__(self, destination: str = None, port: int | None = None, **kwargs): self.port = port return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None destinations: list[DestinationsItem] | None = None source: str | None = None """ @@ -27730,7 +27936,7 @@ def __init__(self, destination: str = None, port: int | None = None, **kwargs): def __init__( self, - name: Annotated[str, ConvertTypes[int]] = None, + name: str = None, destinations: list[DestinationsItem] | None = None, source: str | None = None, source_interface: str | None = None, @@ -27954,13 +28160,13 @@ def __init__( class SnmpServer(AvdDictBaseModel): class EngineIds(AvdDictBaseModel): class RemotesItem(AvdDictBaseModel): - id: Annotated[str, ConvertTypes[int]] | None = None + id: str | None = None """Remote engine ID in hexadecimal.""" address: str | None = None """Hostname or IP of remote engine.""" udp_port: int | None = None - def __init__(self, id: Annotated[str, ConvertTypes[int]] | None = None, address: str | None = None, udp_port: int | None = None, **kwargs): + def __init__(self, id: str | None = None, address: str | None = None, udp_port: int | None = None, **kwargs): """ Args: ----- @@ -27974,11 +28180,11 @@ def __init__(self, id: Annotated[str, ConvertTypes[int]] | None = None, address: self.udp_port = udp_port return super().__init__(**kwargs) - local: Annotated[str, ConvertTypes[int]] | None = None + local: str | None = None """Engine ID in hexadecimal.""" remotes: list[RemotesItem] | None = None - def __init__(self, local: Annotated[str, ConvertTypes[int]] | None = None, remotes: list[RemotesItem] | None = None, **kwargs): + def __init__(self, local: str | None = None, remotes: list[RemotesItem] | None = None, **kwargs): """ Args: ----- @@ -28021,7 +28227,7 @@ def __init__(self, name: str | None = None, **kwargs): name: str = None """Community name.""" - access: Literal["ro", "rw"] | None = None + access: Annotated[str, ValidValues["ro", "rw"]] | None = None access_list_ipv4: AccessListIpv4 | None = None access_list_ipv6: AccessListIpv6 | None = None view: str | None = None @@ -28029,7 +28235,7 @@ def __init__(self, name: str | None = None, **kwargs): def __init__( self, name: str = None, - access: Literal["ro", "rw"] | None = None, + access: Annotated[str, ValidValues["ro", "rw"]] | None = None, access_list_ipv4: AccessListIpv4 | None = None, access_list_ipv6: AccessListIpv6 | None = None, view: str | None = None, @@ -28055,9 +28261,9 @@ def __init__( class Ipv4AclsItem(AvdDictBaseModel): name: str | None = None """IPv4 access list name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -28072,9 +28278,9 @@ def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int class Ipv6AclsItem(AvdDictBaseModel): name: str | None = None """IPv6 access list name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -28089,9 +28295,9 @@ def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int class LocalInterfacesItem(AvdDictBaseModel): name: str = None """Interface name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None - def __init__(self, name: str = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -28136,8 +28342,8 @@ def __init__( class GroupsItem(AvdDictBaseModel): name: str | None = None """Group name.""" - version: Literal["v1", "v2c", "v3"] | None = None - authentication: Literal["auth", "noauth", "priv"] | None = None + version: Annotated[str, ValidValues["v1", "v2c", "v3"]] | None = None + authentication: Annotated[str, ValidValues["auth", "noauth", "priv"]] | None = None read: str | None = None """Read view.""" write: str | None = None @@ -28148,8 +28354,8 @@ class GroupsItem(AvdDictBaseModel): def __init__( self, name: str | None = None, - version: Literal["v1", "v2c", "v3"] | None = None, - authentication: Literal["auth", "noauth", "priv"] | None = None, + version: Annotated[str, ValidValues["v1", "v2c", "v3"]] | None = None, + authentication: Annotated[str, ValidValues["auth", "noauth", "priv"]] | None = None, read: str | None = None, write: str | None = None, notify: str | None = None, @@ -28186,8 +28392,8 @@ class UsersItem(AvdDictBaseModel): """ udp_port: int | None = None """udp_port will not be used if no remote_address is configured.""" - version: Literal["v1", "v2c", "v3"] | None = None - localized: Annotated[str, ConvertTypes[int]] | None = None + version: Annotated[str, ValidValues["v1", "v2c", "v3"]] | None = None + localized: str | None = None """Engine ID in hexadecimal for localizing auth and/or priv.""" auth: str | None = None """Hash algorithm.""" @@ -28204,8 +28410,8 @@ def __init__( group: str | None = None, remote_address: str | None = None, udp_port: int | None = None, - version: Literal["v1", "v2c", "v3"] | None = None, - localized: Annotated[str, ConvertTypes[int]] | None = None, + version: Annotated[str, ValidValues["v1", "v2c", "v3"]] | None = None, + localized: str | None = None, auth: str | None = None, auth_passphrase: str | None = None, priv: str | None = None, @@ -28244,9 +28450,11 @@ def __init__( class HostsItem(AvdDictBaseModel): class UsersItem(AvdDictBaseModel): username: str | None = None - authentication_level: Literal["auth", "noauth", "priv"] | None = None + authentication_level: Annotated[str, ValidValues["auth", "noauth", "priv"]] | None = None - def __init__(self, username: str | None = None, authentication_level: Literal["auth", "noauth", "priv"] | None = None, **kwargs): + def __init__( + self, username: str | None = None, authentication_level: Annotated[str, ValidValues["auth", "noauth", "priv"]] | None = None, **kwargs + ): """ Args: ----- @@ -28260,8 +28468,8 @@ def __init__(self, username: str | None = None, authentication_level: Literal["a host: str | None = None """Host IP address or name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None - version: Annotated[Literal["1", "2c", "3"], ConvertTypes[int]] | None = None + vrf: str | None = None + version: Annotated[str, ValidValues["1", "2c", "3"]] | None = None community: str | None = None """Community name.""" users: list[UsersItem] | None = None @@ -28269,8 +28477,8 @@ def __init__(self, username: str | None = None, authentication_level: Literal["a def __init__( self, host: str | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, - version: Annotated[Literal["1", "2c", "3"], ConvertTypes[int]] | None = None, + vrf: str | None = None, + version: Annotated[str, ValidValues["1", "2c", "3"]] | None = None, community: str | None = None, users: list[UsersItem] | None = None, **kwargs, @@ -28336,11 +28544,11 @@ def __init__(self, enable: bool | None = False, snmp_traps: list[SnmpTrapsItem] return super().__init__(**kwargs) class VrfsItem(AvdDictBaseModel): - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF name.""" enable: bool | None = None - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, enable: bool | None = None, **kwargs): + def __init__(self, name: str = None, enable: bool | None = None, **kwargs): """ Args: ----- @@ -28457,13 +28665,13 @@ class Configuration(AvdDictBaseModel): class InstancesItem(AvdDictBaseModel): id: int = None """Instance ID.""" - vlans: Annotated[str, ConvertTypes[int]] | None = None + vlans: str | None = None """ "< vlan_id >, < vlan_id >-< vlan_id >" Example: 15,16,17,18 """ - def __init__(self, id: int = None, vlans: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, id: int = None, vlans: str | None = None, **kwargs): """ Args: ----- @@ -28512,11 +28720,11 @@ def __init__(self, pvst_border: bool | None = None, configuration: Configuration return super().__init__(**kwargs) class MstInstancesItem(AvdDictBaseModel): - id: Annotated[str, ConvertTypes[int]] = None + id: str = None """Instance ID.""" priority: int | None = None - def __init__(self, id: Annotated[str, ConvertTypes[int]] = None, priority: int | None = None, **kwargs): + def __init__(self, id: str = None, priority: int | None = None, **kwargs): """ Args: ----- @@ -28529,14 +28737,14 @@ def __init__(self, id: Annotated[str, ConvertTypes[int]] = None, priority: int | return super().__init__(**kwargs) class RapidPvstInstancesItem(AvdDictBaseModel): - id: Annotated[str, ConvertTypes[int]] = None + id: str = None """ "< vlan_id >, < vlan_id >-< vlan_id >" Example: 105,202,505-506 """ priority: int | None = None - def __init__(self, id: Annotated[str, ConvertTypes[int]] = None, priority: int | None = None, **kwargs): + def __init__(self, id: str = None, priority: int | None = None, **kwargs): """ Args: ----- @@ -28552,12 +28760,12 @@ def __init__(self, id: Annotated[str, ConvertTypes[int]] = None, priority: int | root_super: bool | None = None edge_port: EdgePort | None = None - mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None = None + mode: Annotated[str, ValidValues["mstp", "rstp", "rapid-pvst", "none"]] | None = None bpduguard_rate_limit: BpduguardRateLimit | None = None rstp_priority: int | None = None mst: Mst | None = None mst_instances: list[MstInstancesItem] | None = None - no_spanning_tree_vlan: Annotated[str, ConvertTypes[int]] | None = None + no_spanning_tree_vlan: str | None = None """ "< vlan_id >, < vlan_id >-< vlan_id >" Example: 105,202,505-506 @@ -28568,12 +28776,12 @@ def __init__( self, root_super: bool | None = None, edge_port: EdgePort | None = None, - mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None = None, + mode: Annotated[str, ValidValues["mstp", "rstp", "rapid-pvst", "none"]] | None = None, bpduguard_rate_limit: BpduguardRateLimit | None = None, rstp_priority: int | None = None, mst: Mst | None = None, mst_instances: list[MstInstancesItem] | None = None, - no_spanning_tree_vlan: Annotated[str, ConvertTypes[int]] | None = None, + no_spanning_tree_vlan: str | None = None, rapid_pvst_instances: list[RapidPvstInstancesItem] | None = None, **kwargs, ): @@ -28628,18 +28836,12 @@ def __init__(self, sequence: int = None, action: str = None, **kwargs): self.action = action return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """Access-list Name.""" counters_per_entry: bool | None = None sequence_numbers: list[SequenceNumbersItem] = None - def __init__( - self, - name: Annotated[str, ConvertTypes[int]] = None, - counters_per_entry: bool | None = None, - sequence_numbers: list[SequenceNumbersItem] = None, - **kwargs, - ): + def __init__(self, name: str = None, counters_per_entry: bool | None = None, sequence_numbers: list[SequenceNumbersItem] = None, **kwargs): """ Args: ----- @@ -28654,7 +28856,7 @@ def __init__( return super().__init__(**kwargs) class StaticRoutesItem(AvdDictBaseModel): - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name.""" destination_address_prefix: str | None = None """IPv4_network/Mask.""" @@ -28671,7 +28873,7 @@ class StaticRoutesItem(AvdDictBaseModel): def __init__( self, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, destination_address_prefix: str | None = None, interface: str | None = None, gateway: str | None = None, @@ -28830,11 +29032,13 @@ def __init__(self, client: Client | None = None, server: Server | None = None, * class SwitchportDefault(AvdDictBaseModel): class Phone(AvdDictBaseModel): cos: int | None = None - trunk: Literal["tagged", "untagged"] | None = None + trunk: Annotated[str, ValidValues["tagged", "untagged"]] | None = None vlan: int | None = None """VLAN ID.""" - def __init__(self, cos: int | None = None, trunk: Literal["tagged", "untagged"] | None = None, vlan: int | None = None, **kwargs): + def __init__( + self, cos: int | None = None, trunk: Annotated[str, ValidValues["tagged", "untagged"]] | None = None, vlan: int | None = None, **kwargs + ): """ Args: ----- @@ -28848,10 +29052,10 @@ def __init__(self, cos: int | None = None, trunk: Literal["tagged", "untagged"] self.vlan = vlan return super().__init__(**kwargs) - mode: Literal["routed", "access"] | None = None + mode: Annotated[str, ValidValues["routed", "access"]] | None = None phone: Phone | None = None - def __init__(self, mode: Literal["routed", "access"] | None = None, phone: Phone | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["routed", "access"]] | None = None, phone: Phone | None = None, **kwargs): """ Args: ----- @@ -28922,9 +29126,9 @@ def __init__(self, ipv4: int | None = None, ipv6: int | None = None, **kwargs): class Ipv4AccessGroupsItem(AvdDictBaseModel): acl_name: str = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None - def __init__(self, acl_name: str = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, acl_name: str = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -28938,9 +29142,9 @@ def __init__(self, acl_name: str = None, vrf: Annotated[str, ConvertTypes[int]] class Ipv6AccessGroupsItem(AvdDictBaseModel): acl_name: str = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None - def __init__(self, acl_name: str = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, acl_name: str = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -28977,13 +29181,13 @@ def __init__( return super().__init__(**kwargs) class L1(AvdDictBaseModel): - unsupported_speed_action: Literal["error", "warn"] | None = None - unsupported_error_correction_action: Literal["error", "warn"] | None = None + unsupported_speed_action: Annotated[str, ValidValues["error", "warn"]] | None = None + unsupported_error_correction_action: Annotated[str, ValidValues["error", "warn"]] | None = None def __init__( self, - unsupported_speed_action: Literal["error", "warn"] | None = None, - unsupported_error_correction_action: Literal["error", "warn"] | None = None, + unsupported_speed_action: Annotated[str, ValidValues["error", "warn"]] | None = None, + unsupported_error_correction_action: Annotated[str, ValidValues["error", "warn"]] | None = None, **kwargs, ): """ @@ -29016,10 +29220,10 @@ class TacacsServers(AvdDictBaseModel): class HostsItem(AvdDictBaseModel): host: str | None = None """Host IP address or name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None key: str | None = None """Encrypted key.""" - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = "7" + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = "7" single_connection: bool | None = None timeout: int | None = None """Timeout in seconds.""" @@ -29027,9 +29231,9 @@ class HostsItem(AvdDictBaseModel): def __init__( self, host: str | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, key: str | None = None, - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = "7", + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = "7", single_connection: bool | None = None, timeout: int | None = None, **kwargs, @@ -29111,11 +29315,11 @@ def __init__(self, exclusive: Exclusive | None = None, **kwargs): class Mac(AvdDictBaseModel): class Timestamp(AvdDictBaseModel): class Header(AvdDictBaseModel): - format: Literal["48-bit", "64-bit"] | None = None + format: Annotated[str, ValidValues["48-bit", "64-bit"]] | None = None eth_type: int | None = None """EtherType.""" - def __init__(self, format: Literal["48-bit", "64-bit"] | None = None, eth_type: int | None = None, **kwargs): + def __init__(self, format: Annotated[str, ValidValues["48-bit", "64-bit"]] | None = None, eth_type: int | None = None, **kwargs): """ Args: ----- @@ -29149,13 +29353,13 @@ def __init__(self, replace_source_mac: bool | None = None, header: Header | None """ fcs_append: bool | None = None """mac.fcs_append and mac.fcs_error are mutually exclusive. If both are defined, mac.fcs_append takes precedence.""" - fcs_error: Literal["correct", "discard", "pass-through"] | None = None + fcs_error: Annotated[str, ValidValues["correct", "discard", "pass-through"]] | None = None def __init__( self, timestamp: Timestamp | None = None, fcs_append: bool | None = None, - fcs_error: Literal["correct", "discard", "pass-through"] | None = None, + fcs_error: Annotated[str, ValidValues["correct", "discard", "pass-through"]] | None = None, **kwargs, ): """ @@ -29439,7 +29643,7 @@ class ProtocolsItem(AvdDictBaseModel): """L4 port range field set.""" dst_field: str | None = None """L4 port range field set.""" - flags: list[str] | None = None + flags: list[Annotated[str, ValidValues["established", "initial"]]] | None = None icmp_type: list[str] | None = None def __init__( @@ -29449,7 +29653,7 @@ def __init__( dst_port: str | None = None, src_field: str | None = None, dst_field: str | None = None, - flags: list[str] | None = None, + flags: list[Annotated[str, ValidValues["established", "initial"]]] | None = None, icmp_type: list[str] | None = None, **kwargs, ): @@ -29512,7 +29716,7 @@ def __init__( name: str = None """Traffic Policy Item.""" - type: Literal["ipv4", "ipv6"] | None = None + type: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = None source: Source | None = None destination: Destination | None = None ttl: str | None = None @@ -29528,7 +29732,7 @@ def __init__( def __init__( self, name: str = None, - type: Literal["ipv4", "ipv6"] | None = None, + type: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = None, source: Source | None = None, destination: Destination | None = None, ttl: str | None = None, @@ -29693,10 +29897,12 @@ class TcpMssCeiling(AvdDictBaseModel): """Segment Size for IPv4.""" ipv6: int | None = None """Segment Size for IPv6.""" - direction: Literal["ingress", "egress"] | None = None + direction: Annotated[str, ValidValues["ingress", "egress"]] | None = None """Optional direction ('ingress', 'egress') for tcp mss ceiling.""" - def __init__(self, ipv4: int | None = None, ipv6: int | None = None, direction: Literal["ingress", "egress"] | None = None, **kwargs): + def __init__( + self, ipv4: int | None = None, ipv6: int | None = None, direction: Annotated[str, ValidValues["ingress", "egress"]] | None = None, **kwargs + ): """ Args: ----- @@ -29715,7 +29921,7 @@ def __init__(self, ipv4: int | None = None, ipv6: int | None = None, direction: description: str | None = None shutdown: bool | None = None mtu: int | None = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF Name.""" ip_address: Annotated[str, Format["ipv4_cidr"]] | None = None """IPv4_address/Mask.""" @@ -29731,7 +29937,7 @@ def __init__(self, ipv4: int | None = None, ipv6: int | None = None, direction: ipv6_access_group_out: str | None = None """IPv6 ACL Name for egress.""" tcp_mss_ceiling: TcpMssCeiling | None = None - tunnel_mode: Literal["gre", "ipsec"] | None = None + tunnel_mode: Annotated[str, ValidValues["gre", "ipsec"]] | None = None """ Tunnel encapsulation method. `gre`: Generic route encapsulation protocol, @@ -29759,7 +29965,7 @@ def __init__( description: str | None = None, shutdown: bool | None = None, mtu: int | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, ip_address: Annotated[str, Format["ipv4_cidr"]] | None = None, ipv6_enable: bool | None = None, ipv6_address: Annotated[str, Format["ipv6_cidr"]] | None = None, @@ -29768,7 +29974,7 @@ def __init__( ipv6_access_group_in: str | None = None, ipv6_access_group_out: str | None = None, tcp_mss_ceiling: TcpMssCeiling | None = None, - tunnel_mode: Literal["gre", "ipsec"] | None = None, + tunnel_mode: Annotated[str, ValidValues["gre", "ipsec"]] | None = None, source_interface: str | None = None, destination: str | None = None, path_mtu_discovery: bool | None = None, @@ -29830,12 +30036,12 @@ def __init__( return super().__init__(**kwargs) class VirtualSourceNatVrfsItem(AvdDictBaseModel): - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF Name.""" ip_address: str | None = None """IPv4 Address.""" - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, ip_address: str | None = None, **kwargs): + def __init__(self, name: str = None, ip_address: str | None = None, **kwargs): """ Args: ----- @@ -29976,10 +30182,10 @@ class IpHelpersItem(AvdDictBaseModel): """IP address or hostname of DHCP server.""" source_interface: str | None = None """Interface used as source for forwarded DHCP packets.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF where DHCP server can be reached.""" - def __init__(self, ip_helper: str = None, source_interface: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, ip_helper: str = None, source_interface: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -30021,7 +30227,7 @@ class StaticItem(AvdDictBaseModel): access_list: str | None = None """'access_list' and 'group' are mutual exclusive.""" comment: str | None = None - direction: Literal["egress", "ingress"] | None = None + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None """ Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware platform. EOS might @@ -30034,7 +30240,7 @@ class StaticItem(AvdDictBaseModel): original_port: int | None = None """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" priority: int | None = None - protocol: Literal["udp", "tcp"] | None = None + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None translated_ip: str = None """IPv4 address.""" translated_port: int | None = None @@ -30044,12 +30250,12 @@ def __init__( self, access_list: str | None = None, comment: str | None = None, - direction: Literal["egress", "ingress"] | None = None, + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None, group: int | None = None, original_ip: str | None = None, original_port: int | None = None, priority: int | None = None, - protocol: Literal["udp", "tcp"] | None = None, + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None, translated_ip: str = None, translated_port: int | None = None, **kwargs, @@ -30103,7 +30309,7 @@ class Source(AvdDictBaseModel): class DynamicItem(AvdDictBaseModel): access_list: str = None comment: str | None = None - nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] = None + nat_type: Annotated[str, ValidValues["overload", "pool", "pool-address-only", "pool-full-cone"]] = None pool_name: str | None = None """ required if 'nat_type' is pool, pool-address-only or pool-full-cone. @@ -30115,7 +30321,7 @@ def __init__( self, access_list: str = None, comment: str | None = None, - nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] = None, + nat_type: Annotated[str, ValidValues["overload", "pool", "pool-address-only", "pool-full-cone"]] = None, pool_name: str | None = None, priority: int | None = None, **kwargs, @@ -30143,7 +30349,7 @@ class StaticItem(AvdDictBaseModel): access_list: str | None = None """'access_list' and 'group' are mutual exclusive.""" comment: str | None = None - direction: Literal["egress", "ingress"] | None = None + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None """ Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware platform. EOS might @@ -30156,7 +30362,7 @@ class StaticItem(AvdDictBaseModel): original_port: int | None = None """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" priority: int | None = None - protocol: Literal["udp", "tcp"] | None = None + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None translated_ip: str = None """IPv4 address.""" translated_port: int | None = None @@ -30166,12 +30372,12 @@ def __init__( self, access_list: str | None = None, comment: str | None = None, - direction: Literal["egress", "ingress"] | None = None, + direction: Annotated[str, ValidValues["egress", "ingress"]] | None = None, group: int | None = None, original_ip: str | None = None, original_port: int | None = None, priority: int | None = None, - protocol: Literal["udp", "tcp"] | None = None, + protocol: Annotated[str, ValidValues["udp", "tcp"]] | None = None, translated_ip: str = None, translated_port: int | None = None, **kwargs, @@ -30261,17 +30467,17 @@ def __init__(self, dynamic_capacity: int | None = None, expire: int | None = Non class Ipv6NdPrefixesItem(AvdDictBaseModel): ipv6_prefix: str = None """IPv6_address/Mask.""" - valid_lifetime: Annotated[str, ConvertTypes[int]] | None = None + valid_lifetime: str | None = None """In seconds <0-4294967295> or infinite.""" - preferred_lifetime: Annotated[str, ConvertTypes[int]] | None = None + preferred_lifetime: str | None = None """In seconds <0-4294967295> or infinite.""" no_autoconfig_flag: bool | None = None def __init__( self, ipv6_prefix: str = None, - valid_lifetime: Annotated[str, ConvertTypes[int]] | None = None, - preferred_lifetime: Annotated[str, ConvertTypes[int]] | None = None, + valid_lifetime: str | None = None, + preferred_lifetime: str | None = None, no_autoconfig_flag: bool | None = None, **kwargs, ): @@ -30293,7 +30499,7 @@ def __init__( class Ipv6DhcpRelayDestinationsItem(AvdDictBaseModel): address: str = None """DHCP server's IPv6 address.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None local_interface: str | None = None """Local interface to communicate with DHCP server - mutually exclusive to source_address.""" source_address: str | None = None @@ -30304,7 +30510,7 @@ class Ipv6DhcpRelayDestinationsItem(AvdDictBaseModel): def __init__( self, address: str = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, local_interface: str | None = None, source_address: str | None = None, link_address: str | None = None, @@ -30330,11 +30536,11 @@ def __init__( class Multicast(AvdDictBaseModel): class Ipv4(AvdDictBaseModel): class BoundariesItem(AvdDictBaseModel): - boundary: Annotated[str, ConvertTypes[int]] = None + boundary: str = None """IPv4 access-list name or IPv4 multicast group prefix with mask.""" out: bool | None = None - def __init__(self, boundary: Annotated[str, ConvertTypes[int]] = None, out: bool | None = None, **kwargs): + def __init__(self, boundary: str = None, out: bool | None = None, **kwargs): """ Args: ----- @@ -30389,10 +30595,10 @@ def __init__( class Ipv6(AvdDictBaseModel): class BoundariesItem(AvdDictBaseModel): - boundary: Annotated[str, ConvertTypes[int]] = None + boundary: str = None """IPv6 access-list name or IPv6 multicast group prefix with mask.""" - def __init__(self, boundary: Annotated[str, ConvertTypes[int]] = None, **kwargs): + def __init__(self, boundary: str = None, **kwargs): """ Args: ----- @@ -30460,12 +30666,16 @@ def __init__(self, ipv4: Ipv4 | None = None, ipv6: Ipv6 | None = None, **kwargs) class OspfMessageDigestKeysItem(AvdDictBaseModel): id: int = None - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = None + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = None key: str | None = None """Encrypted password.""" def __init__( - self, id: int = None, hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = None, key: str | None = None, **kwargs + self, + id: int = None, + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = None, + key: str | None = None, + **kwargs, ): """ Args: @@ -30483,12 +30693,12 @@ def __init__( class Pim(AvdDictBaseModel): class Ipv4(AvdDictBaseModel): class Hello(AvdDictBaseModel): - count: Annotated[str, ConvertTypes[int, float]] | None = None + count: str | None = None """Number of missed hellos after which the neighbor expires. Range <1.5-65535>.""" interval: int | None = None """PIM hello interval in seconds.""" - def __init__(self, count: Annotated[str, ConvertTypes[int, float]] | None = None, interval: int | None = None, **kwargs): + def __init__(self, count: str | None = None, interval: int | None = None, **kwargs): """ Args: ----- @@ -30654,9 +30864,9 @@ def __init__(self, name: str = None, decrement: int | None = None, shutdown: boo class Ipv4(AvdDictBaseModel): address: str = None """Virtual IPv4 address.""" - version: Literal[2, 3] | None = None + version: int | None = None - def __init__(self, address: str = None, version: Literal[2, 3] | None = None, **kwargs): + def __init__(self, address: str = None, version: int | None = None, **kwargs): """ Args: ----- @@ -30862,7 +31072,7 @@ def __init__(self, pbr: Pbr | None = None, **kwargs): description: str | None = None logging: Logging | None = None shutdown: bool | None = None - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """VRF name.""" arp_aging_timeout: int | None = None """In seconds.""" @@ -30878,7 +31088,7 @@ def __init__(self, pbr: Pbr | None = None, **kwargs): ip_address_virtual: str | None = None """IPv4_address/Mask.""" ip_address_virtual_secondaries: list[str] | None = None - ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None = None + ip_verify_unicast_source_reachable_via: Annotated[str, ValidValues["any", "rx"]] | None = None ip_igmp: bool | None = None ip_igmp_version: int | None = None ip_igmp_host_proxy: IpIgmpHostProxy | None = None @@ -30917,19 +31127,19 @@ def __init__(self, pbr: Pbr | None = None, **kwargs): ipv6_dhcp_relay_destinations: list[Ipv6DhcpRelayDestinationsItem] | None = None ipv6_dhcp_relay_all_subnets: bool | None = None """Allow forwarding requests with additional IPv6 addresses in the gateway address "giaddr" field.""" - access_group_in: Annotated[str, ConvertTypes[int]] | None = None + access_group_in: str | None = None """IPv4 access-list name.""" - access_group_out: Annotated[str, ConvertTypes[int]] | None = None + access_group_out: str | None = None """IPv4 access-list name.""" - ipv6_access_group_in: Annotated[str, ConvertTypes[int]] | None = None + ipv6_access_group_in: str | None = None """IPv6 access-list name.""" - ipv6_access_group_out: Annotated[str, ConvertTypes[int]] | None = None + ipv6_access_group_out: str | None = None """IPv6 access-list name.""" multicast: Multicast | None = None ospf_network_point_to_point: bool | None = None - ospf_area: Annotated[str, ConvertTypes[int]] | None = None + ospf_area: str | None = None ospf_cost: int | None = None - ospf_authentication: Literal["none", "simple", "message-digest"] | None = None + ospf_authentication: Annotated[str, ValidValues["none", "simple", "message-digest"]] | None = None ospf_authentication_key: str | None = None """Encrypted password used for simple authentication.""" ospf_message_digest_keys: list[OspfMessageDigestKeysItem] | None = None @@ -30969,7 +31179,7 @@ def __init__( description: str | None = None, logging: Logging | None = None, shutdown: bool | None = None, - vrf: Annotated[str, ConvertTypes[int]] | None = None, + vrf: str | None = None, arp_aging_timeout: int | None = None, arp_cache_dynamic_capacity: int | None = None, arp_gratuitous_accept: bool | None = None, @@ -30981,7 +31191,7 @@ def __init__( ip_virtual_router_addresses: list[str] | None = None, ip_address_virtual: str | None = None, ip_address_virtual_secondaries: list[str] | None = None, - ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None = None, + ip_verify_unicast_source_reachable_via: Annotated[str, ValidValues["any", "rx"]] | None = None, ip_igmp: bool | None = None, ip_igmp_version: int | None = None, ip_igmp_host_proxy: IpIgmpHostProxy | None = None, @@ -31002,15 +31212,15 @@ def __init__( ipv6_nd_prefixes: list[Ipv6NdPrefixesItem] | None = None, ipv6_dhcp_relay_destinations: list[Ipv6DhcpRelayDestinationsItem] | None = None, ipv6_dhcp_relay_all_subnets: bool | None = None, - access_group_in: Annotated[str, ConvertTypes[int]] | None = None, - access_group_out: Annotated[str, ConvertTypes[int]] | None = None, - ipv6_access_group_in: Annotated[str, ConvertTypes[int]] | None = None, - ipv6_access_group_out: Annotated[str, ConvertTypes[int]] | None = None, + access_group_in: str | None = None, + access_group_out: str | None = None, + ipv6_access_group_in: str | None = None, + ipv6_access_group_out: str | None = None, multicast: Multicast | None = None, ospf_network_point_to_point: bool | None = None, - ospf_area: Annotated[str, ConvertTypes[int]] | None = None, + ospf_area: str | None = None, ospf_cost: int | None = None, - ospf_authentication: Literal["none", "simple", "message-digest"] | None = None, + ospf_authentication: Annotated[str, ValidValues["none", "simple", "message-digest"]] | None = None, ospf_authentication_key: str | None = None, ospf_message_digest_keys: list[OspfMessageDigestKeysItem] | None = None, pim: Pim | None = None, @@ -31199,10 +31409,10 @@ def __init__(self, beginning: int = None, ending: int = None, **kwargs): self.ending = ending return super().__init__(**kwargs) - allocation: Literal["ascending", "descending"] = None + allocation: Annotated[str, ValidValues["ascending", "descending"]] = None range: Range = None - def __init__(self, allocation: Literal["ascending", "descending"] = None, range: Range = None, **kwargs): + def __init__(self, allocation: Annotated[str, ValidValues["ascending", "descending"]] = None, range: Range = None, **kwargs): """ Args: ----- @@ -31216,11 +31426,11 @@ def __init__(self, allocation: Literal["ascending", "descending"] = None, range: class VlansItem(AvdDictBaseModel): class PrivateVlan(AvdDictBaseModel): - type: Literal["community", "isolated"] | None = None + type: Annotated[str, ValidValues["community", "isolated"]] | None = None primary_vlan: int | None = None """Primary VLAN ID.""" - def __init__(self, type: Literal["community", "isolated"] | None = None, primary_vlan: int | None = None, **kwargs): + def __init__(self, type: Annotated[str, ValidValues["community", "isolated"]] | None = None, primary_vlan: int | None = None, **kwargs): """ Args: ----- @@ -31236,7 +31446,7 @@ def __init__(self, type: Literal["community", "isolated"] | None = None, primary """VLAN ID.""" name: str | None = None """VLAN Name.""" - state: Literal["active", "suspend"] | None = None + state: Annotated[str, ValidValues["active", "suspend"]] | None = None trunk_groups: list[str] | None = None private_vlan: PrivateVlan | None = None tenant: str | None = None @@ -31246,7 +31456,7 @@ def __init__( self, id: int = None, name: str | None = None, - state: Literal["active", "suspend"] | None = None, + state: Annotated[str, ValidValues["active", "suspend"]] | None = None, trunk_groups: list[str] | None = None, private_vlan: PrivateVlan | None = None, tenant: str | None = None, @@ -31311,7 +31521,7 @@ def __init__( return super().__init__(**kwargs) class VrfsItem(AvdDictBaseModel): - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF Name.""" description: str | None = None ip_routing: bool | None = None @@ -31322,7 +31532,7 @@ class VrfsItem(AvdDictBaseModel): def __init__( self, - name: Annotated[str, ConvertTypes[int]] = None, + name: str = None, description: str | None = None, ip_routing: bool | None = None, ipv6_routing: bool | None = None, @@ -31455,13 +31665,13 @@ def __init__( return super().__init__(**kwargs) class VrfsItem(AvdDictBaseModel): - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF Name.""" vni: int | None = None multicast_group: str | None = None """IP Multicast Group Address.""" - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, vni: int | None = None, multicast_group: str | None = None, **kwargs): + def __init__(self, name: str = None, vni: int | None = None, multicast_group: str | None = None, **kwargs): """ Args: ----- @@ -31610,7 +31820,7 @@ def __init__(self, field_Vxlan1: Vxlan1 | None = None, **kwargs): """Application traffic recognition configuration.""" arp: Arp | None = None as_path: AsPath | None = None - avd_data_conversion_mode: Literal["disabled", "error", "warning", "info", "debug", "quiet"] | None = "debug" + avd_data_conversion_mode: Annotated[str, ValidValues["disabled", "error", "warning", "info", "debug", "quiet"]] | None = "debug" """ Conversion Mode for AVD input data conversion. Input data conversion will perform type conversion of input variables as @@ -31628,7 +31838,7 @@ def __init__(self, field_Vxlan1: Vxlan1 | None = None, **kwargs): messages viewable with -v. "quiet" will not produce any messages. """ - avd_data_validation_mode: Literal["disabled", "error", "warning", "info", "debug"] | None = "warning" + avd_data_validation_mode: Annotated[str, ValidValues["disabled", "error", "warning", "info", "debug"]] | None = "warning" """ Validation Mode for AVD input data validation. Input data validation will validate the input variables according to the @@ -31864,7 +32074,7 @@ def __init__(self, field_Vxlan1: Vxlan1 | None = None, **kwargs): """Configure network services inserted to data forwarding.""" router_traffic_engineering: RouterTrafficEngineering | None = None service_routing_configuration_bgp: ServiceRoutingConfigurationBgp | None = None - service_routing_protocols_model: Literal["multi-agent", "ribd"] | None = None + service_routing_protocols_model: Annotated[str, ValidValues["multi-agent", "ribd"]] | None = None service_unsupported_transceiver: ServiceUnsupportedTransceiver | None = None sflow: Sflow | None = None snmp_server: SnmpServer | None = None @@ -31912,8 +32122,8 @@ def __init__( application_traffic_recognition: ApplicationTrafficRecognition | None = None, arp: Arp | None = None, as_path: AsPath | None = None, - avd_data_conversion_mode: Literal["disabled", "error", "warning", "info", "debug", "quiet"] | None = "debug", - avd_data_validation_mode: Literal["disabled", "error", "warning", "info", "debug"] | None = "warning", + avd_data_conversion_mode: Annotated[str, ValidValues["disabled", "error", "warning", "info", "debug", "quiet"]] | None = "debug", + avd_data_validation_mode: Annotated[str, ValidValues["disabled", "error", "warning", "info", "debug"]] | None = "warning", banners: Banners | None = None, bgp_groups: list[BgpGroupsItem] | None = None, boot: Boot | None = None, @@ -32055,7 +32265,7 @@ def __init__( router_service_insertion: RouterServiceInsertion | None = None, router_traffic_engineering: RouterTrafficEngineering | None = None, service_routing_configuration_bgp: ServiceRoutingConfigurationBgp | None = None, - service_routing_protocols_model: Literal["multi-agent", "ribd"] | None = None, + service_routing_protocols_model: Annotated[str, ValidValues["multi-agent", "ribd"]] | None = None, service_unsupported_transceiver: ServiceUnsupportedTransceiver | None = None, sflow: Sflow | None = None, snmp_server: SnmpServer | None = None, diff --git a/python-avd/pyavd/_eos_designs/schema/eos_designs.jsonschema.json b/python-avd/pyavd/_eos_designs/schema/eos_designs.jsonschema.json index 51d1c306dc1..08379b244b8 100644 --- a/python-avd/pyavd/_eos_designs/schema/eos_designs.jsonschema.json +++ b/python-avd/pyavd/_eos_designs/schema/eos_designs.jsonschema.json @@ -6697,7 +6697,7 @@ "algorithm": { "type": "string", "default": "first_id", - "description": "This variable defines the Multi-chassis Link Aggregation (MLAG) algorithm used.\nEach MLAG link will have a /31* subnet with each subnet allocated from the relevant MLAG pool via a calculated offset.\nThe offset is calculated using one of the following algorithms:\n - first_id: `(mlag_primary_id - 1) * 2` where `mlag_primary_id` is the ID of the first node defined under the node_group.\n This allocation method will skip every other /31* subnet making it less space efficient than `odd_id`.\n - odd_id: `(odd_id - 1) / 2`. Requires the node_group to have a node with an odd ID and a node with an even ID.\n - same_subnet: the offset will always be zero.\n This allocation method will cause every MLAG link to be addressed with the same /31* subnet.\n\\* - The prefix length is configurable with a default of /31.", + "description": "This variable defines the Multi-chassis Link Aggregation (MLAG) algorithm used.\nEach MLAG link will have a /31\u00b9 subnet with each subnet allocated from the relevant MLAG pool via a calculated offset.\nThe offset is calculated using one of the following algorithms:\n - first_id: `(mlag_primary_id - 1) * 2` where `mlag_primary_id` is the ID of the first node defined under the node_group.\n This allocation method will skip every other /31\u00b9 subnet making it less space efficient than `odd_id`.\n - odd_id: `(odd_id - 1) / 2`. Requires the node_group to have a node with an odd ID and a node with an even ID.\n - same_subnet: the offset will always be zero.\n This allocation method will cause every MLAG link to be addressed with the same /31\u00b9 subnet.\n\u00b9 The prefix length is configurable with a default of /31.", "enum": [ "first_id", "odd_id", diff --git a/python-avd/pyavd/_schema/eos_designs.py b/python-avd/pyavd/_eos_designs/schema/eos_designs.py similarity index 88% rename from python-avd/pyavd/_schema/eos_designs.py rename to python-avd/pyavd/_eos_designs/schema/eos_designs.py index 6a99cd02d26..7add11b83b2 100644 --- a/python-avd/pyavd/_schema/eos_designs.py +++ b/python-avd/pyavd/_eos_designs/schema/eos_designs.py @@ -2,18 +2,524 @@ # Use of this source code is governed by the Apache License 2.0 # that can be found in the LICENSE file. -from typing import Any, Literal +from typing import Any +from pyavd._eos_cli_config_gen.schema.eos_cli_config_gen import EosCliConfigGen +from pyavd._schema.models import AvdDictBaseModel, AvdEosDesignsRootDictBase +from pyavd._schema.types import Format, MaxLen, MinLen, Pattern, ToLower, ValidValues from typing_extensions import Annotated -from .eos_cli_config_gen import EosCliConfigGen -from .models import AvdDictBaseModel, AvdEosDesignsRootDictBase -from .types import ConvertTypes, Format, MaxLen, MinLen, Pattern, ToLower - class EosDesigns(AvdEosDesignsRootDictBase): - class ApplicationClassification(EosCliConfigGen.ApplicationTrafficRecognition): - pass + class ApplicationClassification(AvdDictBaseModel): + class CategoriesItem(AvdDictBaseModel): + class ApplicationsItem(AvdDictBaseModel): + name: str | None = None + """Application name.""" + service: ( + Annotated[str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"]] + | None + ) = None + """ + Service Name. + Specific service to target for this application. + If no service is specified, all supported services of the + application are matched. + Not all valid values are valid for all applications, check on EOS CLI. + """ + + def __init__( + self, + name: str | None = None, + service: ( + Annotated[ + str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] + ] + | None + ) = None, + **kwargs, + ): + """ + Args: + ----- + name: Application name. + service: + Service Name. + Specific service to target for this application. + If no service is specified, all supported services of the + application are matched. + Not all valid values are valid for all applications, check on EOS CLI. + + """ + self.name = name + self.service = service + return super().__init__(**kwargs) + + name: str = None + """Category name.""" + applications: list[ApplicationsItem] | None = None + """List of applications.""" + + def __init__(self, name: str = None, applications: list[ApplicationsItem] | None = None, **kwargs): + """ + Args: + ----- + name: Category name. + applications: List of applications. + + """ + self.name = name + self.applications = applications + return super().__init__(**kwargs) + + class FieldSets(AvdDictBaseModel): + class L4PortsItem(AvdDictBaseModel): + name: str = None + """L4 port field-set name.""" + port_values: list[str] | None = None + + def __init__(self, name: str = None, port_values: list[str] | None = None, **kwargs): + """ + Args: + ----- + name: L4 port field-set name. + port_values: port_values + + """ + self.name = name + self.port_values = port_values + return super().__init__(**kwargs) + + class Ipv4PrefixesItem(AvdDictBaseModel): + name: str = None + """IPv4 prefix field-set name.""" + prefix_values: list[str] | None = None + + def __init__(self, name: str = None, prefix_values: list[str] | None = None, **kwargs): + """ + Args: + ----- + name: IPv4 prefix field-set name. + prefix_values: prefix_values + + """ + self.name = name + self.prefix_values = prefix_values + return super().__init__(**kwargs) + + l4_ports: list[L4PortsItem] | None = None + """L4 port field-set.""" + ipv4_prefixes: list[Ipv4PrefixesItem] | None = None + """IPv4 prefix field set.""" + + def __init__(self, l4_ports: list[L4PortsItem] | None = None, ipv4_prefixes: list[Ipv4PrefixesItem] | None = None, **kwargs): + """ + Args: + ----- + l4_ports: L4 port field-set. + ipv4_prefixes: IPv4 prefix field set. + + """ + self.l4_ports = l4_ports + self.ipv4_prefixes = ipv4_prefixes + return super().__init__(**kwargs) + + class Applications(AvdDictBaseModel): + class Ipv4ApplicationsItem(AvdDictBaseModel): + name: str = None + """Application name.""" + src_prefix_set_name: str | None = None + """Source prefix set name.""" + dest_prefix_set_name: str | None = None + """Destination prefix set name.""" + protocols: list[Annotated[str, ValidValues["ahp", "esp", "icmp", "igmp", "ospf", "pim", "rsvp", "tcp", "udp", "vrrp"]]] | None = None + """ + List of protocols to consider for this application. + To use port field-sets (source, destination or both), the list + must + contain only one or two protocols, either `tcp` or `udp`. + When using both protocols, one line is rendered for each in + the configuration, + hence the field-sets must have the same value for `tcp_src_port_set_name` and + `udp_src_port_set_name` + and for `tcp_dest_port_set_name` and `udp_dest_port_set_name` + if set in order to generate valid configuration in EOS. + """ + protocol_ranges: list[str] | None = None + """ + Accept protocol value(s) or range(s). + Protocol values can be between 1 and 255. + """ + udp_src_port_set_name: str | None = None + """ + Name of field set for UDP source ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must be + the same as `tcp_src_port_set_name`. + """ + tcp_src_port_set_name: str | None = None + """ + Name of field set for TCP source ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must be + the same as `udp_src_port_set_name`. + """ + udp_dest_port_set_name: str | None = None + """ + Name of field set for UDP destination ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must + be the same as `tcp_dest_port_set_name`. + """ + tcp_dest_port_set_name: str | None = None + """ + Name of field set for TCP destination ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must + be the same as `udp_dest_port_set_name`. + """ + + def __init__( + self, + name: str = None, + src_prefix_set_name: str | None = None, + dest_prefix_set_name: str | None = None, + protocols: list[Annotated[str, ValidValues["ahp", "esp", "icmp", "igmp", "ospf", "pim", "rsvp", "tcp", "udp", "vrrp"]]] | None = None, + protocol_ranges: list[str] | None = None, + udp_src_port_set_name: str | None = None, + tcp_src_port_set_name: str | None = None, + udp_dest_port_set_name: str | None = None, + tcp_dest_port_set_name: str | None = None, + **kwargs, + ): + """ + Args: + ----- + name: Application name. + src_prefix_set_name: Source prefix set name. + dest_prefix_set_name: Destination prefix set name. + protocols: + List of protocols to consider for this application. + To use port field-sets (source, destination or both), the list + must + contain only one or two protocols, either `tcp` or `udp`. + When using both protocols, one line is rendered for each in + the configuration, + hence the field-sets must have the same value for `tcp_src_port_set_name` and + `udp_src_port_set_name` + and for `tcp_dest_port_set_name` and `udp_dest_port_set_name` + if set in order to generate valid configuration in EOS. + protocol_ranges: + Accept protocol value(s) or range(s). + Protocol values can be between 1 and 255. + udp_src_port_set_name: + Name of field set for UDP source ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must be + the same as `tcp_src_port_set_name`. + tcp_src_port_set_name: + Name of field set for TCP source ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must be + the same as `udp_src_port_set_name`. + udp_dest_port_set_name: + Name of field set for UDP destination ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must + be the same as `tcp_dest_port_set_name`. + tcp_dest_port_set_name: + Name of field set for TCP destination ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must + be the same as `udp_dest_port_set_name`. + + """ + self.name = name + self.src_prefix_set_name = src_prefix_set_name + self.dest_prefix_set_name = dest_prefix_set_name + self.protocols = protocols + self.protocol_ranges = protocol_ranges + self.udp_src_port_set_name = udp_src_port_set_name + self.tcp_src_port_set_name = tcp_src_port_set_name + self.udp_dest_port_set_name = udp_dest_port_set_name + self.tcp_dest_port_set_name = tcp_dest_port_set_name + return super().__init__(**kwargs) + + class L4ApplicationsItem(AvdDictBaseModel): + name: str = None + """Application name.""" + protocols: list[Annotated[str, ValidValues["ahp", "esp", "icmp", "igmp", "ospf", "pim", "rsvp", "tcp", "udp", "vrrp"]]] | None = None + """ + List of protocols to consider for this application. + To use port field-sets (source, destination or both), the list + must + contain only one or two protocols, either `tcp` or `udp`. + When using both protocols, one line is rendered for each in + the configuration, + hence the field-sets must have the same value for `tcp_src_port_set_name` and + `udp_src_port_set_name` + and for `tcp_dest_port_set_name` and `udp_dest_port_set_name` + if set in order to generate valid configuration in EOS. + """ + protocol_ranges: list[str] | None = None + """ + Accept protocol value(s) or range(s). + Protocol values can be between 1 and 255. + """ + udp_src_port_set_name: str | None = None + """ + Name of field set for UDP source ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must be + the same as `tcp_src_port_set_name`. + """ + tcp_src_port_set_name: str | None = None + """ + Name of field set for TCP source ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must be + the same as `udp_src_port_set_name`. + """ + udp_dest_port_set_name: str | None = None + """ + Name of field set for UDP destination ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must + be the same as `tcp_dest_port_set_name`. + """ + tcp_dest_port_set_name: str | None = None + """ + Name of field set for TCP destination ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must + be the same as `udp_dest_port_set_name`. + """ + + def __init__( + self, + name: str = None, + protocols: list[Annotated[str, ValidValues["ahp", "esp", "icmp", "igmp", "ospf", "pim", "rsvp", "tcp", "udp", "vrrp"]]] | None = None, + protocol_ranges: list[str] | None = None, + udp_src_port_set_name: str | None = None, + tcp_src_port_set_name: str | None = None, + udp_dest_port_set_name: str | None = None, + tcp_dest_port_set_name: str | None = None, + **kwargs, + ): + """ + Args: + ----- + name: Application name. + protocols: + List of protocols to consider for this application. + To use port field-sets (source, destination or both), the list + must + contain only one or two protocols, either `tcp` or `udp`. + When using both protocols, one line is rendered for each in + the configuration, + hence the field-sets must have the same value for `tcp_src_port_set_name` and + `udp_src_port_set_name` + and for `tcp_dest_port_set_name` and `udp_dest_port_set_name` + if set in order to generate valid configuration in EOS. + protocol_ranges: + Accept protocol value(s) or range(s). + Protocol values can be between 1 and 255. + udp_src_port_set_name: + Name of field set for UDP source ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must be + the same as `tcp_src_port_set_name`. + tcp_src_port_set_name: + Name of field set for TCP source ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must be + the same as `udp_src_port_set_name`. + udp_dest_port_set_name: + Name of field set for UDP destination ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must + be the same as `tcp_dest_port_set_name`. + tcp_dest_port_set_name: + Name of field set for TCP destination ports. + When the `protocols` list contain both `tcp` and `udp`, this key value + must + be the same as `udp_dest_port_set_name`. + + """ + self.name = name + self.protocols = protocols + self.protocol_ranges = protocol_ranges + self.udp_src_port_set_name = udp_src_port_set_name + self.tcp_src_port_set_name = tcp_src_port_set_name + self.udp_dest_port_set_name = udp_dest_port_set_name + self.tcp_dest_port_set_name = tcp_dest_port_set_name + return super().__init__(**kwargs) + + ipv4_applications: list[Ipv4ApplicationsItem] | None = None + """List of user defined IPv4 applications. The name should be unique over all defined applications (ipv4 and l4).""" + l4_applications: list[L4ApplicationsItem] | None = None + """List of user defined L4 applications. The name should be unique over all defined applications (ipv4 and l4).""" + + def __init__(self, ipv4_applications: list[Ipv4ApplicationsItem] | None = None, l4_applications: list[L4ApplicationsItem] | None = None, **kwargs): + """ + Args: + ----- + ipv4_applications: List of user defined IPv4 applications. The name should be unique over all defined applications (ipv4 and l4). + l4_applications: List of user defined L4 applications. The name should be unique over all defined applications (ipv4 and l4). + + """ + self.ipv4_applications = ipv4_applications + self.l4_applications = l4_applications + return super().__init__(**kwargs) + + class ApplicationProfilesItem(AvdDictBaseModel): + class ApplicationsItem(AvdDictBaseModel): + name: str | None = None + """Application Name.""" + service: ( + Annotated[str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"]] + | None + ) = None + """ + Service Name. + Specific service to target for this application. + If no service is specified, all supported services of the + application are matched. + Not all valid values are valid for all applications, check on EOS CLI. + """ + + def __init__( + self, + name: str | None = None, + service: ( + Annotated[ + str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] + ] + | None + ) = None, + **kwargs, + ): + """ + Args: + ----- + name: Application Name. + service: + Service Name. + Specific service to target for this application. + If no service is specified, all supported services of the + application are matched. + Not all valid values are valid for all applications, check on EOS CLI. + + """ + self.name = name + self.service = service + return super().__init__(**kwargs) + + class CategoriesItem(AvdDictBaseModel): + name: str | None = None + """Name of a category.""" + service: ( + Annotated[str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"]] + | None + ) = None + """ + Service Name. + Specific service to target for this application. + If no service is specified, all supported services of the + application are matched. + Not all valid values are valid for all applications, check on EOS CLI. + """ + + def __init__( + self, + name: str | None = None, + service: ( + Annotated[ + str, ValidValues["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] + ] + | None + ) = None, + **kwargs, + ): + """ + Args: + ----- + name: Name of a category. + service: + Service Name. + Specific service to target for this application. + If no service is specified, all supported services of the + application are matched. + Not all valid values are valid for all applications, check on EOS CLI. + + """ + self.name = name + self.service = service + return super().__init__(**kwargs) + + name: str | None = None + """Application Profile name.""" + applications: list[ApplicationsItem] | None = None + """List of applications part of the application profile.""" + application_transports: list[Annotated[str, ValidValues["http", "https", "udp", "tcp", "ip", "ip6", "ssl", "rtp", "sctp", "quic"]]] | None = None + """List of transport protocols.""" + categories: list[CategoriesItem] | None = None + """Categories under this application profile.""" + + def __init__( + self, + name: str | None = None, + applications: list[ApplicationsItem] | None = None, + application_transports: ( + list[Annotated[str, ValidValues["http", "https", "udp", "tcp", "ip", "ip6", "ssl", "rtp", "sctp", "quic"]]] | None + ) = None, + categories: list[CategoriesItem] | None = None, + **kwargs, + ): + """ + Args: + ----- + name: Application Profile name. + applications: List of applications part of the application profile. + application_transports: List of transport protocols. + categories: Categories under this application profile. + + """ + self.name = name + self.applications = applications + self.application_transports = application_transports + self.categories = categories + return super().__init__(**kwargs) + + categories: list[CategoriesItem] | None = None + """List of categories.""" + field_sets: FieldSets | None = None + applications: Applications | None = None + application_profiles: list[ApplicationProfilesItem] | None = None + """Group of applications.""" + + def __init__( + self, + categories: list[CategoriesItem] | None = None, + field_sets: FieldSets | None = None, + applications: Applications | None = None, + application_profiles: list[ApplicationProfilesItem] | None = None, + **kwargs, + ): + """ + Args: + ----- + categories: List of categories. + field_sets: field_sets + applications: applications + application_profiles: Group of applications. + + """ + self.categories = categories + self.field_sets = field_sets + self.applications = applications + self.application_profiles = application_profiles + return super().__init__(**kwargs) class BfdMultihop(AvdDictBaseModel): interval: int = None @@ -34,8 +540,24 @@ def __init__(self, interval: int = None, min_rx: int = None, multiplier: int = N self.multiplier = multiplier return super().__init__(**kwargs) - class BgpDistance(EosCliConfigGen.RouterBgp.Distance): - pass + class BgpDistance(AvdDictBaseModel): + external_routes: int = None + internal_routes: int = None + local_routes: int = None + + def __init__(self, external_routes: int = None, internal_routes: int = None, local_routes: int = None, **kwargs): + """ + Args: + ----- + external_routes: external_routes + internal_routes: internal_routes + local_routes: local_routes + + """ + self.external_routes = external_routes + self.internal_routes = internal_routes + self.local_routes = local_routes + return super().__init__(**kwargs) class BgpGracefulRestart(AvdDictBaseModel): enabled: bool = False @@ -302,17 +824,19 @@ def __init__( return super().__init__(**kwargs) class WanOverlayPeers(AvdDictBaseModel): - class BfdTimers(EosCliConfigGen.RouterBgp.PeerGroupsItem.BfdTimers): - interval: int | None = 1000 - min_rx: int | None = 1000 - multiplier: int | None = 10 + class BfdTimers(AvdDictBaseModel): + interval: int = 1000 + """Interval in milliseconds.""" + min_rx: int = 1000 + """Rate in milliseconds.""" + multiplier: int = 10 - def __init__(self, interval: int | None = 1000, min_rx: int | None = 1000, multiplier: int | None = 10, **kwargs): + def __init__(self, interval: int = 1000, min_rx: int = 1000, multiplier: int = 10, **kwargs): """ Args: ----- - interval: interval - min_rx: min_rx + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. multiplier: multiplier """ @@ -386,17 +910,19 @@ def __init__( return super().__init__(**kwargs) class WanRrOverlayPeers(AvdDictBaseModel): - class BfdTimers(EosCliConfigGen.RouterBgp.PeerGroupsItem.BfdTimers): - interval: int | None = 1000 - min_rx: int | None = 1000 - multiplier: int | None = 10 + class BfdTimers(AvdDictBaseModel): + interval: int = 1000 + """Interval in milliseconds.""" + min_rx: int = 1000 + """Rate in milliseconds.""" + multiplier: int = 10 - def __init__(self, interval: int | None = 1000, min_rx: int | None = 1000, multiplier: int | None = 10, **kwargs): + def __init__(self, interval: int = 1000, min_rx: int = 1000, multiplier: int = 10, **kwargs): """ Args: ----- - interval: interval - min_rx: min_rx + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. multiplier: multiplier """ @@ -643,7 +1169,7 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """Nodes where this link should be configured.""" interfaces: list[str] | None = None """Interfaces where this link should be configured and Required unless using port-channels.""" - field_as: list[Annotated[str, ConvertTypes[int]]] | None = None + field_as: list[str] | None = None """ AS numbers for BGP. Required with bgp peering. @@ -654,8 +1180,8 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """Add this interface to underlay routing protocol.""" isis_hello_padding: bool | None = False isis_metric: int | None = None - isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None = None - isis_authentication_mode: Literal["md5", "text"] | None = None + isis_circuit_type: Annotated[str, ValidValues["level-1", "level-2", "level-1-2"]] | None = None + isis_authentication_mode: Annotated[str, ValidValues["md5", "text"]] | None = None isis_authentication_key: str | None = None """Type-7 encrypted password.""" mpls_ip: bool | None = None @@ -682,7 +1208,7 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """Port-channel parameters.""" raw_eos_cli: str | None = None """EOS CLI rendered directly on the point-to-point interface in the final EOS configuration.""" - routing_protocol: Literal["ebgp"] | None = None + routing_protocol: Annotated[str, ValidValues["ebgp"]] | None = None """ Enables deviation of the routing protocol used on this link from the fabric underlay default. - ebgp: Enforce plain IPv4 @@ -706,13 +1232,13 @@ def __init__( ipv6_enable: bool | None = False, nodes: list[str] | None = None, interfaces: list[str] | None = None, - field_as: list[Annotated[str, ConvertTypes[int]]] | None = None, + field_as: list[str] | None = None, descriptions: list[str] | None = None, include_in_underlay_protocol: bool | None = True, isis_hello_padding: bool | None = False, isis_metric: int | None = None, - isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None = None, - isis_authentication_mode: Literal["md5", "text"] | None = None, + isis_circuit_type: Annotated[str, ValidValues["level-1", "level-2", "level-1-2"]] | None = None, + isis_authentication_mode: Annotated[str, ValidValues["md5", "text"]] | None = None, isis_authentication_key: str | None = None, mpls_ip: bool | None = None, mpls_ldp: bool | None = None, @@ -726,7 +1252,7 @@ def __init__( macsec_profile: str | None = None, port_channel: PortChannel | None = None, raw_eos_cli: str | None = None, - routing_protocol: Literal["ebgp"] | None = None, + routing_protocol: Annotated[str, ValidValues["ebgp"]] | None = None, structured_config: dict | None = None, **kwargs, ): @@ -904,7 +1430,7 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """ interfaces: list[str] | None = None """Interfaces where this link should be configured and Required unless using port-channels.""" - field_as: list[Annotated[str, ConvertTypes[int]]] | None = None + field_as: list[str] | None = None """ AS numbers for BGP. Required with bgp peering. @@ -915,8 +1441,8 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """Add this interface to underlay routing protocol.""" isis_hello_padding: bool | None = False isis_metric: int | None = None - isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None = None - isis_authentication_mode: Literal["md5", "text"] | None = None + isis_circuit_type: Annotated[str, ValidValues["level-1", "level-2", "level-1-2"]] | None = None + isis_authentication_mode: Annotated[str, ValidValues["md5", "text"]] | None = None isis_authentication_key: str | None = None """Type-7 encrypted password.""" mpls_ip: bool | None = None @@ -943,7 +1469,7 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """Port-channel parameters.""" raw_eos_cli: str | None = None """EOS CLI rendered directly on the point-to-point interface in the final EOS configuration.""" - routing_protocol: Literal["ebgp"] | None = None + routing_protocol: Annotated[str, ValidValues["ebgp"]] | None = None """ Enables deviation of the routing protocol used on this link from the fabric underlay default. - ebgp: Enforce plain IPv4 @@ -967,13 +1493,13 @@ def __init__( ip: list[str] | None = None, ipv6_enable: bool | None = False, interfaces: list[str] | None = None, - field_as: list[Annotated[str, ConvertTypes[int]]] | None = None, + field_as: list[str] | None = None, descriptions: list[str] | None = None, include_in_underlay_protocol: bool | None = True, isis_hello_padding: bool | None = False, isis_metric: int | None = None, - isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None = None, - isis_authentication_mode: Literal["md5", "text"] | None = None, + isis_circuit_type: Annotated[str, ValidValues["level-1", "level-2", "level-1-2"]] | None = None, + isis_authentication_mode: Annotated[str, ValidValues["md5", "text"]] | None = None, isis_authentication_key: str | None = None, mpls_ip: bool | None = None, mpls_ldp: bool | None = None, @@ -987,7 +1513,7 @@ def __init__( macsec_profile: str | None = None, port_channel: PortChannel | None = None, raw_eos_cli: str | None = None, - routing_protocol: Literal["ebgp"] | None = None, + routing_protocol: Annotated[str, ValidValues["ebgp"]] | None = None, structured_config: dict | None = None, **kwargs, ): @@ -1203,7 +1729,7 @@ def __init__( name: str = None """Internet-exit policy name.""" - type: Literal["direct", "zscaler"] = None + type: Annotated[str, ValidValues["direct", "zscaler"]] = None """ Internet-exit policy type. direct: Exit directly over wan interfaces @@ -1218,7 +1744,7 @@ def __init__( def __init__( self, name: str = None, - type: Literal["direct", "zscaler"] = None, + type: Annotated[str, ValidValues["direct", "zscaler"]] = None, fallback_to_system_default: bool | None = True, zscaler: Zscaler | None = None, **kwargs, @@ -1242,12 +1768,12 @@ def __init__( self.zscaler = zscaler return super().__init__(**kwargs) - class CvPathfinderRegionsItem(EosCliConfigGen.RouterAdaptiveVirtualTopology.Region): - class SitesItem(EosCliConfigGen.RouterAdaptiveVirtualTopology.Site): - name: Annotated[str, MinLen[1], MaxLen[128]] = None + class CvPathfinderRegionsItem(AvdDictBaseModel): + class SitesItem(AvdDictBaseModel): + name: Annotated[str, MinLen[1], MaxLen[128], Pattern[r"^[A-Za-z0-9_.:{}\[\]-]+$"]] = None """The site name.""" description: str | None = None - id: int | None = None + id: int = None """ The site ID must be unique within a zone. Given that all the sites are placed in a zone named after the region, the site @@ -1260,9 +1786,9 @@ class SitesItem(EosCliConfigGen.RouterAdaptiveVirtualTopology.Site): def __init__( self, - name: Annotated[str, MinLen[1], MaxLen[128]] = None, + name: Annotated[str, MinLen[1], MaxLen[128], Pattern[r"^[A-Za-z0-9_.:{}\[\]-]+$"]] = None, description: str | None = None, - id: int | None = None, + id: int = None, location: str | None = None, site_contact: str | None = None, site_after_hours_contact: str | None = None, @@ -1290,18 +1816,18 @@ def __init__( self.site_after_hours_contact = site_after_hours_contact return super().__init__(**kwargs) - name: Annotated[str, MinLen[1], MaxLen[128]] = None + name: Annotated[str, MinLen[1], MaxLen[128], Pattern[r"^[A-Za-z0-9_.:{}\[\]-]+$"]] = None description: str | None = None - id: int | None = None + id: int = None """The region ID must be unique for the whole WAN deployment.""" sites: list[SitesItem] | None = None """All sites are placed in a default zone "-ZONE" with ID 1.""" def __init__( self, - name: Annotated[str, MinLen[1], MaxLen[128]] = None, + name: Annotated[str, MinLen[1], MaxLen[128], Pattern[r"^[A-Za-z0-9_.:{}\[\]-]+$"]] = None, description: str | None = None, - id: int | None = None, + id: int = None, sites: list[SitesItem] | None = None, **kwargs, ): @@ -1420,10 +1946,10 @@ def __init__(self, node_type: str = None, match_hostnames: list[str] = None, **k return super().__init__(**kwargs) class Design(AvdDictBaseModel): - type: Literal["l3ls-evpn", "mpls", "l2ls"] | None = "l3ls-evpn" + type: Annotated[str, ValidValues["l3ls-evpn", "mpls", "l2ls"]] | None = "l3ls-evpn" """By setting the design.type variable, the default node-types and templates described in these documents will be used.""" - def __init__(self, type: Literal["l3ls-evpn", "mpls", "l2ls"] | None = "l3ls-evpn", **kwargs): + def __init__(self, type: Annotated[str, ValidValues["l3ls-evpn", "mpls", "l2ls"]] | None = "l3ls-evpn", **kwargs): """ Args: ----- @@ -1593,15 +2119,15 @@ def __init__(self, interface: str = None, ip: bool | None = None, ipv6: bool | N return super().__init__(**kwargs) class TriggerOnMaintenance(AvdDictBaseModel): - operation: Literal["enter", "exit"] = None + operation: Annotated[str, ValidValues["enter", "exit"]] = None bgp_peer: str | None = None """ Ipv4/Ipv6 address or peer group name. Trigger condition occurs on maintenance operation of specified BGP peer. """ - action: Literal["after", "before", "all", "begin", "end"] = None + action: Annotated[str, ValidValues["after", "before", "all", "begin", "end"]] = None """Action for maintenance operation.""" - stage: Literal["bgp", "linkdown", "mlag", "ratemon"] | None = None + stage: Annotated[str, ValidValues["bgp", "linkdown", "mlag", "ratemon"]] | None = None """Action is triggered after/before specified stage.""" vrf: str | None = None """VRF name. VRF can be defined for "bgp_peer" only.""" @@ -1612,10 +2138,10 @@ class TriggerOnMaintenance(AvdDictBaseModel): def __init__( self, - operation: Literal["enter", "exit"] = None, + operation: Annotated[str, ValidValues["enter", "exit"]] = None, bgp_peer: str | None = None, - action: Literal["after", "before", "all", "begin", "end"] = None, - stage: Literal["bgp", "linkdown", "mlag", "ratemon"] | None = None, + action: Annotated[str, ValidValues["after", "before", "all", "begin", "end"]] = None, + stage: Annotated[str, ValidValues["bgp", "linkdown", "mlag", "ratemon"]] | None = None, vrf: str | None = None, interface: str | None = None, unit: str | None = None, @@ -1646,14 +2172,16 @@ def __init__( name: str = None """Event Handler Name.""" - action_type: Literal["bash", "increment", "log"] | None = None + action_type: Annotated[str, ValidValues["bash", "increment", "log"]] | None = None action: str | None = None """Command to execute.""" actions: Actions | None = None """Note: `bash_command` and `log` are mutually exclusive. `bash_command` takes precedence over `log`.""" delay: int | None = None """Event-handler delay in seconds.""" - trigger: Literal["on-boot", "on-counters", "on-intf", "on-logging", "on-maintenance", "on-startup-config", "vm-tracer vm"] | None = None + trigger: ( + Annotated[str, ValidValues["on-boot", "on-counters", "on-intf", "on-logging", "on-maintenance", "on-startup-config", "vm-tracer vm"]] | None + ) = None """Configure event trigger condition.""" trigger_on_counters: TriggerOnCounters | None = None trigger_on_logging: TriggerOnLogging | None = None @@ -1673,11 +2201,13 @@ def __init__( def __init__( self, name: str = None, - action_type: Literal["bash", "increment", "log"] | None = None, + action_type: Annotated[str, ValidValues["bash", "increment", "log"]] | None = None, action: str | None = None, actions: Actions | None = None, delay: int | None = None, - trigger: Literal["on-boot", "on-counters", "on-intf", "on-logging", "on-maintenance", "on-startup-config", "vm-tracer vm"] | None = None, + trigger: ( + Annotated[str, ValidValues["on-boot", "on-counters", "on-intf", "on-logging", "on-maintenance", "on-startup-config", "vm-tracer vm"]] | None + ) = None, trigger_on_counters: TriggerOnCounters | None = None, trigger_on_logging: TriggerOnLogging | None = None, trigger_on_intf: TriggerOnIntf | None = None, @@ -1761,7 +2291,7 @@ def __init__(self, raw_eos_cli: str | None = None, **kwargs): self.raw_eos_cli = raw_eos_cli return super().__init__(**kwargs) - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """ Specify an EVPN vlan-aware-bundle name. EVPN vlan-aware-bundles group L2 VLANs and define common settings. @@ -1772,7 +2302,7 @@ def __init__(self, raw_eos_cli: str | None = None, **kwargs): bundle. See "overlay_rd_type" and "overlay_rt_type" for details. """ - rt_override: Annotated[str, ConvertTypes[int]] | None = None + rt_override: str | None = None """ By default the MAC VRF bundle RT will be derived from mac_vrf_id_base + bundle_id. The rt_override allows us to override @@ -1784,7 +2314,7 @@ def __init__(self, raw_eos_cli: str | None = None, **kwargs): details). - A full RT string with colon separator which will override the full RT. """ - rd_override: Annotated[str, ConvertTypes[int]] | None = None + rd_override: str | None = None """ By default the MAC VRF bundle RD will be derived from mac_vrf_id_base + bundle_id. The rt_override allows us to override @@ -1807,10 +2337,10 @@ def __init__(self, raw_eos_cli: str | None = None, **kwargs): def __init__( self, - name: Annotated[str, ConvertTypes[int]] = None, + name: str = None, id: int = None, - rt_override: Annotated[str, ConvertTypes[int]] | None = None, - rd_override: Annotated[str, ConvertTypes[int]] | None = None, + rt_override: str | None = None, + rd_override: str | None = None, evpn_l2_multi_domain: bool | None = None, bgp: Bgp | None = None, **kwargs, @@ -2074,23 +2604,23 @@ def __init__( class FabricIpAddressing(AvdDictBaseModel): class Mlag(AvdDictBaseModel): - algorithm: Literal["first_id", "odd_id", "same_subnet"] | None = "first_id" + algorithm: Annotated[str, ValidValues["first_id", "odd_id", "same_subnet"]] | None = "first_id" """ This variable defines the Multi-chassis Link Aggregation (MLAG) algorithm used. - Each MLAG link will have a /31* subnet + Each MLAG link will have a /31¹ subnet with each subnet allocated from the relevant MLAG pool via a calculated offset. The offset is calculated using one of the following algorithms: - first_id: `(mlag_primary_id - 1) * 2` where `mlag_primary_id` is the ID of the first node defined under the node_group. - This allocation method will skip every other /31* subnet making it less space + This allocation method will skip every other /31¹ subnet making it less space efficient than `odd_id`. - odd_id: `(odd_id - 1) / 2`. Requires the node_group to have a node with an odd ID and a node with an even ID. - same_subnet: the offset will always be zero. This allocation method will cause every MLAG - link to be addressed with the same /31* subnet. - \* - The prefix length is configurable with a default of /31. + link to be addressed with the same /31¹ subnet. + ¹ The prefix length is configurable with a default of /31. """ ipv4_prefix_length: int | None = 31 """IPv4 prefix length used for MLAG peer-vlan and L3 point-to-point SVIs over the MLAG peer-link.""" @@ -2099,7 +2629,7 @@ class Mlag(AvdDictBaseModel): def __init__( self, - algorithm: Literal["first_id", "odd_id", "same_subnet"] | None = "first_id", + algorithm: Annotated[str, ValidValues["first_id", "odd_id", "same_subnet"]] | None = "first_id", ipv4_prefix_length: int | None = 31, ipv6_prefix_length: int | None = 64, **kwargs, @@ -2109,20 +2639,20 @@ def __init__( ----- algorithm: This variable defines the Multi-chassis Link Aggregation (MLAG) algorithm used. - Each MLAG link will have a /31* subnet + Each MLAG link will have a /31¹ subnet with each subnet allocated from the relevant MLAG pool via a calculated offset. The offset is calculated using one of the following algorithms: - first_id: `(mlag_primary_id - 1) * 2` where `mlag_primary_id` is the ID of the first node defined under the node_group. - This allocation method will skip every other /31* subnet making it less space + This allocation method will skip every other /31¹ subnet making it less space efficient than `odd_id`. - odd_id: `(odd_id - 1) / 2`. Requires the node_group to have a node with an odd ID and a node with an even ID. - same_subnet: the offset will always be zero. This allocation method will cause every MLAG - link to be addressed with the same /31* subnet. - \* - The prefix length is configurable with a default of /31. + link to be addressed with the same /31¹ subnet. + ¹ The prefix length is configurable with a default of /31. ipv4_prefix_length: IPv4 prefix length used for MLAG peer-vlan and L3 point-to-point SVIs over the MLAG peer-link. ipv6_prefix_length: IPv6 prefix length used for MLAG peer-vlan and L3 point-to-point SVIs over the MLAG peer-link. @@ -2572,8 +3102,264 @@ def __init__( self.device_tags = device_tags return super().__init__(**kwargs) - class HardwareCounters(EosCliConfigGen.HardwareCounters): - pass + class HardwareCounters(AvdDictBaseModel): + class FeaturesItem(AvdDictBaseModel): + name: ( + Annotated[ + str, + ValidValues[ + "acl", + "decap-group", + "directflow", + "ecn", + "flow-spec", + "gre tunnel interface", + "ip", + "mpls interface", + "mpls lfib", + "mpls tunnel", + "multicast", + "nexthop", + "pbr", + "pdp", + "policing interface", + "qos", + "qos dual-rate-policer", + "route", + "routed-port", + "segment-security", + "subinterface", + "tapagg", + "traffic-class", + "traffic-policy", + "vlan", + "vlan-interface", + "vni decap", + "vni encap", + "vtep decap", + "vtep encap", + ], + ] + | None + ) = None + direction: Annotated[str, ValidValues["in", "out", "cpu"]] | None = None + """ + Most features support only 'in' and 'out'. Some like traffic-policy support 'cpu'. + Some features DO NOT have any + direction. + This validation IS NOT made by the schemas. + """ + address_type: Annotated[str, ValidValues["ipv4", "ipv6", "mac"]] | None = None + """ + Supported only for the following features: + - acl: [ipv4, ipv6, mac] if direction is 'out' + - multicast: [ipv4, ipv6] + - + route: [ipv4, ipv6] + This validation IS NOT made by the schemas. + """ + layer3: bool | None = None + """Supported only for the 'ip' feature.""" + vrf: str | None = None + """ + Supported only for the 'route' feature. + This validation IS NOT made by the schemas. + """ + prefix: str | None = None + """ + Supported only for the 'route' feature. + Mandatory for the 'route' feature. + This validation IS NOT made by the schemas. + """ + units_packets: bool | None = None + + def __init__( + self, + name: ( + Annotated[ + str, + ValidValues[ + "acl", + "decap-group", + "directflow", + "ecn", + "flow-spec", + "gre tunnel interface", + "ip", + "mpls interface", + "mpls lfib", + "mpls tunnel", + "multicast", + "nexthop", + "pbr", + "pdp", + "policing interface", + "qos", + "qos dual-rate-policer", + "route", + "routed-port", + "segment-security", + "subinterface", + "tapagg", + "traffic-class", + "traffic-policy", + "vlan", + "vlan-interface", + "vni decap", + "vni encap", + "vtep decap", + "vtep encap", + ], + ] + | None + ) = None, + direction: Annotated[str, ValidValues["in", "out", "cpu"]] | None = None, + address_type: Annotated[str, ValidValues["ipv4", "ipv6", "mac"]] | None = None, + layer3: bool | None = None, + vrf: str | None = None, + prefix: str | None = None, + units_packets: bool | None = None, + **kwargs, + ): + """ + Args: + ----- + name: name + direction: + Most features support only 'in' and 'out'. Some like traffic-policy support 'cpu'. + Some features DO NOT have any + direction. + This validation IS NOT made by the schemas. + address_type: + Supported only for the following features: + - acl: [ipv4, ipv6, mac] if direction is 'out' + - multicast: [ipv4, ipv6] + - + route: [ipv4, ipv6] + This validation IS NOT made by the schemas. + layer3: Supported only for the 'ip' feature. + vrf: + Supported only for the 'route' feature. + This validation IS NOT made by the schemas. + prefix: + Supported only for the 'route' feature. + Mandatory for the 'route' feature. + This validation IS NOT made by the schemas. + units_packets: units_packets + + """ + self.name = name + self.direction = direction + self.address_type = address_type + self.layer3 = layer3 + self.vrf = vrf + self.prefix = prefix + self.units_packets = units_packets + return super().__init__(**kwargs) + + features: list[FeaturesItem] | None = None + """ + This data model allows to configure the list of hardware counters feature + available on Arista platforms. + + The `name` key + accepts a list of valid_values which MUST be updated to support + new feature as they are released in EOS. + + The available + values of the different keys like 'direction' or 'address_type' + are feature and hardware dependent and this model DOES + NOT validate that the + combinations are valid. It is the responsibility of the user of this data model + to make sure that + the rendered CLI is accepted by the targeted device. + + Examples: + + * Use: + ```yaml + hardware_counters: + features: + - name: ip + direction: out + layer3: true + units_packets: true + ``` + to render: + ```eos + hardware counter feature ip out layer3 units packets + ``` + * Use: + ```yaml + hardware_counters: + features: + - name: route + address_type: ipv4 + vrf: test + prefix: 192.168.0.0/24 + ``` + + to render: + ```eos + hardware counter feature route ipv4 vrf test + 192.168.0.0/24 + ``` + """ + + def __init__(self, features: list[FeaturesItem] | None = None, **kwargs): + """ + Args: + ----- + features: + This data model allows to configure the list of hardware counters feature + available on Arista platforms. + + The `name` key + accepts a list of valid_values which MUST be updated to support + new feature as they are released in EOS. + + The available + values of the different keys like 'direction' or 'address_type' + are feature and hardware dependent and this model DOES + NOT validate that the + combinations are valid. It is the responsibility of the user of this data model + to make sure that + the rendered CLI is accepted by the targeted device. + + Examples: + + * Use: + ```yaml + hardware_counters: + features: + - name: ip + direction: out + layer3: true + units_packets: true + ``` + to render: + ```eos + hardware counter feature ip out layer3 units packets + ``` + * Use: + ```yaml + hardware_counters: + features: + - name: route + address_type: ipv4 + vrf: test + prefix: 192.168.0.0/24 + ``` + + to render: + ```eos + hardware counter feature route ipv4 vrf test + 192.168.0.0/24 + ``` + + """ + self.features = features + return super().__init__(**kwargs) class InternalVlanOrder(AvdDictBaseModel): class Range(AvdDictBaseModel): @@ -2594,10 +3380,10 @@ def __init__(self, beginning: int = None, ending: int = None, **kwargs): self.ending = ending return super().__init__(**kwargs) - allocation: Literal["ascending", "descending"] = None + allocation: Annotated[str, ValidValues["ascending", "descending"]] = None range: Range | None = None - def __init__(self, allocation: Literal["ascending", "descending"] = None, range: Range | None = None, **kwargs): + def __init__(self, allocation: Annotated[str, ValidValues["ascending", "descending"]] = None, range: Range | None = None, **kwargs): """ Args: ----- @@ -2609,7 +3395,7 @@ def __init__(self, allocation: Literal["ascending", "descending"] = None, range: self.range = range return super().__init__(**kwargs) - class Ipv4AclsItem(EosCliConfigGen.IpAccessListsItem): + class Ipv4AclsItem(AvdDictBaseModel): class EntriesItem(AvdDictBaseModel): source: str | None = None """ @@ -2629,8 +3415,77 @@ class EntriesItem(AvdDictBaseModel): means host. Required except for remarks. """ + sequence: int | None = None + """ACL entry sequence number.""" + remark: str | None = None + """ + Comment up to 100 characters. + If remark is defined, other keys in the ACL entry will be ignored. + """ + action: Annotated[str, ValidValues["permit", "deny"]] | None = None + """ + ACL action. + Required except for remarks. + """ + protocol: str | None = None + """ + "ip", "tcp", "udp", "icmp" or other protocol name or number. + Required except for remarks. + """ + source_ports_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq", "range"]] | None = "eq" + source_ports: list[str] | None = None + destination_ports_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq", "range"]] | None = "eq" + destination_ports: list[str] | None = None + tcp_flags: list[str] | None = None + fragments: bool | None = None + """Match non-head fragment packets.""" + log: bool | None = None + """Log matches against this rule.""" + ttl: int | None = None + """TTL value.""" + ttl_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq"]] | None = "eq" + icmp_type: str | None = None + """Message type name/number for ICMP packets.""" + icmp_code: str | None = None + """Message code for ICMP packets.""" + nexthop_group: str | None = None + """nexthop-group name.""" + tracked: bool | None = None + """Match packets in existing ICMP/UDP/TCP connections.""" + dscp: str | None = None + """DSCP value or name.""" + vlan_number: int | None = None + vlan_inner: bool | None = False + vlan_mask: str | None = None + """0x000-0xFFF VLAN mask.""" - def __init__(self, source: str | None = None, destination: str | None = None, **kwargs): + def __init__( + self, + source: str | None = None, + destination: str | None = None, + sequence: int | None = None, + remark: str | None = None, + action: Annotated[str, ValidValues["permit", "deny"]] | None = None, + protocol: str | None = None, + source_ports_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq", "range"]] | None = "eq", + source_ports: list[str] | None = None, + destination_ports_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq", "range"]] | None = "eq", + destination_ports: list[str] | None = None, + tcp_flags: list[str] | None = None, + fragments: bool | None = None, + log: bool | None = None, + ttl: int | None = None, + ttl_match: Annotated[str, ValidValues["eq", "gt", "lt", "neq"]] | None = "eq", + icmp_type: str | None = None, + icmp_code: str | None = None, + nexthop_group: str | None = None, + tracked: bool | None = None, + dscp: str | None = None, + vlan_number: int | None = None, + vlan_inner: bool | None = False, + vlan_mask: str | None = None, + **kwargs, + ): """ Args: ----- @@ -2648,10 +3503,58 @@ def __init__(self, source: str | None = None, destination: str | None = None, ** "" without a mask means host. Required except for remarks. + sequence: ACL entry sequence number. + remark: + Comment up to 100 characters. + If remark is defined, other keys in the ACL entry will be ignored. + action: + ACL action. + Required except for remarks. + protocol: + "ip", "tcp", "udp", "icmp" or other protocol name or number. + Required except for remarks. + source_ports_match: source_ports_match + source_ports: source_ports + destination_ports_match: destination_ports_match + destination_ports: destination_ports + tcp_flags: tcp_flags + fragments: Match non-head fragment packets. + log: Log matches against this rule. + ttl: TTL value. + ttl_match: ttl_match + icmp_type: Message type name/number for ICMP packets. + icmp_code: Message code for ICMP packets. + nexthop_group: nexthop-group name. + tracked: Match packets in existing ICMP/UDP/TCP connections. + dscp: DSCP value or name. + vlan_number: vlan_number + vlan_inner: vlan_inner + vlan_mask: 0x000-0xFFF VLAN mask. """ self.source = source self.destination = destination + self.sequence = sequence + self.remark = remark + self.action = action + self.protocol = protocol + self.source_ports_match = source_ports_match + self.source_ports = source_ports + self.destination_ports_match = destination_ports_match + self.destination_ports = destination_ports + self.tcp_flags = tcp_flags + self.fragments = fragments + self.log = log + self.ttl = ttl + self.ttl_match = ttl_match + self.icmp_type = icmp_type + self.icmp_code = icmp_code + self.nexthop_group = nexthop_group + self.tracked = tracked + self.dscp = dscp + self.vlan_number = vlan_number + self.vlan_inner = vlan_inner + self.vlan_mask = vlan_mask return super().__init__(**kwargs) name: str = None @@ -2660,29 +3563,37 @@ def __init__(self, source: str | None = None, destination: str | None = None, ** When using substitution for any fields, the interface name will be appended to the ACL name. """ entries: list[EntriesItem] = None + """ACL Entries.""" + counters_per_entry: bool | None = None - def __init__(self, name: str = None, entries: list[EntriesItem] = None, **kwargs): + def __init__(self, name: str = None, entries: list[EntriesItem] = None, counters_per_entry: bool | None = None, **kwargs): """ Args: ----- name: Access-list name. When using substitution for any fields, the interface name will be appended to the ACL name. - entries: entries + entries: ACL Entries. + counters_per_entry: counters_per_entry """ self.name = name self.entries = entries + self.counters_per_entry = counters_per_entry return super().__init__(**kwargs) class IsisTiLfa(AvdDictBaseModel): enabled: bool | None = False - protection: Literal["link", "node"] | None = None + protection: Annotated[str, ValidValues["link", "node"]] | None = None local_convergence_delay: int | None = 10000 """Local convergence delay in milliseconds.""" def __init__( - self, enabled: bool | None = False, protection: Literal["link", "node"] | None = None, local_convergence_delay: int | None = 10000, **kwargs + self, + enabled: bool | None = False, + protection: Annotated[str, ValidValues["link", "node"]] | None = None, + local_convergence_delay: int | None = 10000, + **kwargs, ): """ Args: @@ -2813,7 +3724,7 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """Nodes where this link should be configured.""" interfaces: list[str] | None = None """Interfaces where this link should be configured and Required unless using port-channels.""" - field_as: list[Annotated[str, ConvertTypes[int]]] | None = None + field_as: list[str] | None = None """ AS numbers for BGP. Required with bgp peering. @@ -2824,8 +3735,8 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """Add this interface to underlay routing protocol.""" isis_hello_padding: bool | None = False isis_metric: int | None = None - isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None = None - isis_authentication_mode: Literal["md5", "text"] | None = None + isis_circuit_type: Annotated[str, ValidValues["level-1", "level-2", "level-1-2"]] | None = None + isis_authentication_mode: Annotated[str, ValidValues["md5", "text"]] | None = None isis_authentication_key: str | None = None """Type-7 encrypted password.""" mpls_ip: bool | None = None @@ -2852,7 +3763,7 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """Port-channel parameters.""" raw_eos_cli: str | None = None """EOS CLI rendered directly on the point-to-point interface in the final EOS configuration.""" - routing_protocol: Literal["ebgp"] | None = None + routing_protocol: Annotated[str, ValidValues["ebgp"]] | None = None """ Enables deviation of the routing protocol used on this link from the fabric underlay default. - ebgp: Enforce plain IPv4 @@ -2876,13 +3787,13 @@ def __init__( ipv6_enable: bool | None = False, nodes: list[str] | None = None, interfaces: list[str] | None = None, - field_as: list[Annotated[str, ConvertTypes[int]]] | None = None, + field_as: list[str] | None = None, descriptions: list[str] | None = None, include_in_underlay_protocol: bool | None = True, isis_hello_padding: bool | None = False, isis_metric: int | None = None, - isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None = None, - isis_authentication_mode: Literal["md5", "text"] | None = None, + isis_circuit_type: Annotated[str, ValidValues["level-1", "level-2", "level-1-2"]] | None = None, + isis_authentication_mode: Annotated[str, ValidValues["md5", "text"]] | None = None, isis_authentication_key: str | None = None, mpls_ip: bool | None = None, mpls_ldp: bool | None = None, @@ -2896,7 +3807,7 @@ def __init__( macsec_profile: str | None = None, port_channel: PortChannel | None = None, raw_eos_cli: str | None = None, - routing_protocol: Literal["ebgp"] | None = None, + routing_protocol: Annotated[str, ValidValues["ebgp"]] | None = None, structured_config: dict | None = None, **kwargs, ): @@ -3074,7 +3985,7 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """ interfaces: list[str] | None = None """Interfaces where this link should be configured and Required unless using port-channels.""" - field_as: list[Annotated[str, ConvertTypes[int]]] | None = None + field_as: list[str] | None = None """ AS numbers for BGP. Required with bgp peering. @@ -3085,8 +3996,8 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """Add this interface to underlay routing protocol.""" isis_hello_padding: bool | None = False isis_metric: int | None = None - isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None = None - isis_authentication_mode: Literal["md5", "text"] | None = None + isis_circuit_type: Annotated[str, ValidValues["level-1", "level-2", "level-1-2"]] | None = None + isis_authentication_mode: Annotated[str, ValidValues["md5", "text"]] | None = None isis_authentication_key: str | None = None """Type-7 encrypted password.""" mpls_ip: bool | None = None @@ -3113,7 +4024,7 @@ def __init__(self, mode: str | None = "active", nodes_child_interfaces: list[Nod """Port-channel parameters.""" raw_eos_cli: str | None = None """EOS CLI rendered directly on the point-to-point interface in the final EOS configuration.""" - routing_protocol: Literal["ebgp"] | None = None + routing_protocol: Annotated[str, ValidValues["ebgp"]] | None = None """ Enables deviation of the routing protocol used on this link from the fabric underlay default. - ebgp: Enforce plain IPv4 @@ -3137,13 +4048,13 @@ def __init__( ip: list[str] | None = None, ipv6_enable: bool | None = False, interfaces: list[str] | None = None, - field_as: list[Annotated[str, ConvertTypes[int]]] | None = None, + field_as: list[str] | None = None, descriptions: list[str] | None = None, include_in_underlay_protocol: bool | None = True, isis_hello_padding: bool | None = False, isis_metric: int | None = None, - isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None = None, - isis_authentication_mode: Literal["md5", "text"] | None = None, + isis_circuit_type: Annotated[str, ValidValues["level-1", "level-2", "level-1-2"]] | None = None, + isis_authentication_mode: Annotated[str, ValidValues["md5", "text"]] | None = None, isis_authentication_key: str | None = None, mpls_ip: bool | None = None, mpls_ldp: bool | None = None, @@ -3157,7 +4068,7 @@ def __init__( macsec_profile: str | None = None, port_channel: PortChannel | None = None, raw_eos_cli: str | None = None, - routing_protocol: Literal["ebgp"] | None = None, + routing_protocol: Annotated[str, ValidValues["ebgp"]] | None = None, structured_config: dict | None = None, **kwargs, ): @@ -3342,7 +4253,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): profile: str = None """L3 interface profile name. Any variable supported under `l3_interfaces` can be inherited from a profile.""" - name: Annotated[str, Pattern["Ethernet[\d/]+(.[\d]+)?"]] | None = None + name: Annotated[str, Pattern[r"Ethernet[\d/]+(.[\d]+)?"]] | None = None """ Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. For a subinterface, the parent @@ -3396,7 +4307,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true and `ip` is an IP address. """ - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_in: str | None = None """ Name of the IPv4 access-list to be assigned in the ingress direction. The access-list must be defined under `ipv4_acls` @@ -3404,7 +4315,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Required for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under `wan_carriers`. """ - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_out: str | None = None """ Name of the IPv4 Access-list to be assigned in the egress direction. The access-list must be defined under `ipv4_acls` @@ -3422,7 +4333,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Unless the carrier is marked as 'trusted' under `wan_carriers`, `ipv4_acl_in` is also required on all WAN interfaces. """ - wan_circuit_id: Annotated[str, ConvertTypes[int]] | None = None + wan_circuit_id: str | None = None """ The WAN circuit ID for this interface. This is not rendered in the configuration but used for WAN designs. @@ -3441,7 +4352,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): def __init__( self, profile: str = None, - name: Annotated[str, Pattern["Ethernet[\d/]+(.[\d]+)?"]] | None = None, + name: Annotated[str, Pattern[r"Ethernet[\d/]+(.[\d]+)?"]] | None = None, description: str | None = None, ip_address: str | None = None, dhcp_ip: str | None = None, @@ -3453,12 +4364,12 @@ def __init__( peer: str | None = None, peer_interface: str | None = None, peer_ip: str | None = None, - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None, - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None, + ipv4_acl_in: str | None = None, + ipv4_acl_out: str | None = None, static_routes: list[StaticRoutesItem] | None = None, qos_profile: str | None = None, wan_carrier: str | None = None, - wan_circuit_id: Annotated[str, ConvertTypes[int]] | None = None, + wan_circuit_id: str | None = None, connected_to_pathfinder: bool | None = True, cv_pathfinder_internet_exit: CvPathfinderInternetExit | None = None, raw_eos_cli: str | None = None, @@ -3583,7 +4494,7 @@ class LocalUsersItem(AvdDictBaseModel): """If set a password will not be configured for this user. "sha512_password" MUST not be defined for this user.""" ssh_key: str | None = None secondary_ssh_key: str | None = None - shell: Literal["/bin/bash", "/bin/sh", "/sbin/nologin"] | None = None + shell: Annotated[str, ValidValues["/bin/bash", "/bin/sh", "/sbin/nologin"]] | None = None """Specify shell for the user.""" def __init__( @@ -3596,7 +4507,7 @@ def __init__( no_password: bool | None = None, ssh_key: str | None = None, secondary_ssh_key: str | None = None, - shell: Literal["/bin/bash", "/bin/sh", "/sbin/nologin"] | None = None, + shell: Annotated[str, ValidValues["/bin/bash", "/bin/sh", "/sbin/nologin"]] | None = None, **kwargs, ): """ @@ -3682,9 +4593,9 @@ def __init__(self, base_vlan: int | None = 3000, **kwargs): class NetworkPortsItem(AvdDictBaseModel): class Flowcontrol(AvdDictBaseModel): - received: Literal["received", "send", "on"] | None = None + received: Annotated[str, ValidValues["received", "send", "on"]] | None = None - def __init__(self, received: Literal["received", "send", "on"] | None = None, **kwargs): + def __init__(self, received: Annotated[str, ValidValues["received", "send", "on"]] | None = None, **kwargs): """ Args: ----- @@ -3696,14 +4607,14 @@ def __init__(self, received: Literal["received", "send", "on"] | None = None, ** class Ptp(AvdDictBaseModel): enabled: bool | None = False - endpoint_role: Literal["bmca", "default", "follower"] | None = "follower" - profile: Literal["aes67", "aes67-r16-2016", "smpte2059-2"] | None = "aes67-r16-2016" + endpoint_role: Annotated[str, ValidValues["bmca", "default", "follower"]] | None = "follower" + profile: Annotated[str, ValidValues["aes67", "aes67-r16-2016", "smpte2059-2"]] | None = "aes67-r16-2016" def __init__( self, enabled: bool | None = False, - endpoint_role: Literal["bmca", "default", "follower"] | None = "follower", - profile: Literal["aes67", "aes67-r16-2016", "smpte2059-2"] | None = "aes67-r16-2016", + endpoint_role: Annotated[str, ValidValues["bmca", "default", "follower"]] | None = "follower", + profile: Annotated[str, ValidValues["aes67", "aes67-r16-2016", "smpte2059-2"]] | None = "aes67-r16-2016", **kwargs, ): """ @@ -3764,9 +4675,9 @@ def __init__(self, enabled: bool | None = None, name: str | None = None, **kwarg class Dot1x(AvdDictBaseModel): class Pae(AvdDictBaseModel): - mode: Literal["authenticator"] | None = None + mode: Annotated[str, ValidValues["authenticator"]] | None = None - def __init__(self, mode: Literal["authenticator"] | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["authenticator"]] | None = None, **kwargs): """ Args: ----- @@ -3777,10 +4688,10 @@ def __init__(self, mode: Literal["authenticator"] | None = None, **kwargs): return super().__init__(**kwargs) class AuthenticationFailure(AvdDictBaseModel): - action: Literal["allow", "drop"] | None = None + action: Annotated[str, ValidValues["allow", "drop"]] | None = None allow_vlan: int | None = None - def __init__(self, action: Literal["allow", "drop"] | None = None, allow_vlan: int | None = None, **kwargs): + def __init__(self, action: Annotated[str, ValidValues["allow", "drop"]] | None = None, allow_vlan: int | None = None, **kwargs): """ Args: ----- @@ -3793,10 +4704,12 @@ def __init__(self, action: Literal["allow", "drop"] | None = None, allow_vlan: i return super().__init__(**kwargs) class HostMode(AvdDictBaseModel): - mode: Literal["multi-host", "single-host"] | None = None + mode: Annotated[str, ValidValues["multi-host", "single-host"]] | None = None multi_host_authenticated: bool | None = None - def __init__(self, mode: Literal["multi-host", "single-host"] | None = None, multi_host_authenticated: bool | None = None, **kwargs): + def __init__( + self, mode: Annotated[str, ValidValues["multi-host", "single-host"]] | None = None, multi_host_authenticated: bool | None = None, **kwargs + ): """ Args: ----- @@ -3830,7 +4743,7 @@ def __init__(self, enabled: bool | None = None, always: bool | None = None, host class Timeout(AvdDictBaseModel): idle_host: int | None = None quiet_period: int | None = None - reauth_period: Annotated[str, ConvertTypes[int]] | None = None + reauth_period: str | None = None """Range 60-4294967295 or "server".""" reauth_timeout_ignore: bool | None = None tx_period: int | None = None @@ -3839,7 +4752,7 @@ def __init__( self, idle_host: int | None = None, quiet_period: int | None = None, - reauth_period: Annotated[str, ConvertTypes[int]] | None = None, + reauth_period: str | None = None, reauth_timeout_ignore: bool | None = None, tx_period: int | None = None, **kwargs, @@ -3877,7 +4790,7 @@ def __init__(self, access_vlan_membership_egress: bool | None = None, native_vla self.native_vlan_membership_egress = native_vlan_membership_egress return super().__init__(**kwargs) - port_control: Literal["auto", "force-authorized", "force-unauthorized"] | None = None + port_control: Annotated[str, ValidValues["auto", "force-authorized", "force-unauthorized"]] | None = None port_control_force_authorized_phone: bool | None = None reauthentication: bool | None = None pae: Pae | None = None @@ -3890,7 +4803,7 @@ def __init__(self, access_vlan_membership_egress: bool | None = None, native_vla def __init__( self, - port_control: Literal["auto", "force-authorized", "force-unauthorized"] | None = None, + port_control: Annotated[str, ValidValues["auto", "force-authorized", "force-unauthorized"]] | None = None, port_control_force_authorized_phone: bool | None = None, reauthentication: bool | None = None, pae: Pae | None = None, @@ -3929,35 +4842,161 @@ def __init__( self.unauthorized = unauthorized return super().__init__(**kwargs) - class Poe(EosCliConfigGen.EthernetInterfacesItem.Poe): - pass - - class StormControl(AvdDictBaseModel): - class All(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None - """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" - """Optional variable and is hardware dependent.""" + class Poe(AvdDictBaseModel): + class Reboot(AvdDictBaseModel): + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None + """PoE action for interface.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, **kwargs): """ Args: ----- - level: Configure maximum storm-control level. - unit: Optional variable and is hardware dependent. + action: PoE action for interface. """ - self.level = level - self.unit = unit + self.action = action + return super().__init__(**kwargs) + + class LinkDown(AvdDictBaseModel): + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None + """PoE action for interface.""" + power_off_delay: int | None = None + """Number of seconds to delay shutting the power off after a link down event occurs. Default value is 5 seconds in EOS.""" + + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, power_off_delay: int | None = None, **kwargs): + """ + Args: + ----- + action: PoE action for interface. + power_off_delay: Number of seconds to delay shutting the power off after a link down event occurs. Default value is 5 seconds in EOS. + + """ + self.action = action + self.power_off_delay = power_off_delay + return super().__init__(**kwargs) + + class Shutdown(AvdDictBaseModel): + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None + """PoE action for interface.""" + + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, **kwargs): + """ + Args: + ----- + action: PoE action for interface. + + """ + self.action = action + return super().__init__(**kwargs) + + class Limit(AvdDictBaseModel): + field_class: int | None = None + watts: str | None = None + fixed: bool | None = None + """Set to ignore hardware classification.""" + + def __init__(self, field_class: int | None = None, watts: str | None = None, fixed: bool | None = None, **kwargs): + """ + Args: + ----- + field_class: field_class + watts: watts + fixed: Set to ignore hardware classification. + + """ + self.field_class = field_class + self.watts = watts + self.fixed = fixed + return super().__init__(**kwargs) + + disabled: bool | None = False + """Disable PoE on a POE capable port. PoE is enabled on all ports that support it by default in EOS.""" + priority: Annotated[str, ValidValues["critical", "high", "medium", "low"]] | None = None + """Prioritize a port's power in the event that one of the switch's power supplies loses power.""" + reboot: Reboot | None = None + """Set the PoE power behavior for a PoE port when the system is rebooted.""" + link_down: LinkDown | None = None + """Set the PoE power behavior for a PoE port when the port goes down.""" + shutdown: Shutdown | None = None + """Set the PoE power behavior for a PoE port when the port is admin down.""" + limit: Limit | None = None + """ + Override the hardware-negotiated power limit using either wattage or a power class. Note that if using a power class, + AVD will automatically convert the class value to the wattage value corresponding to that power class. + """ + negotiation_lldp: bool | None = None + """Disable to prevent port from negotiating power with powered devices over LLDP. Enabled by default in EOS.""" + legacy_detect: bool | None = None + """ + Allow a subset of legacy devices to work with the PoE switch. Disabled by default in EOS because it can cause false + positive detections. + """ + + def __init__( + self, + disabled: bool | None = False, + priority: Annotated[str, ValidValues["critical", "high", "medium", "low"]] | None = None, + reboot: Reboot | None = None, + link_down: LinkDown | None = None, + shutdown: Shutdown | None = None, + limit: Limit | None = None, + negotiation_lldp: bool | None = None, + legacy_detect: bool | None = None, + **kwargs, + ): + """ + Args: + ----- + disabled: Disable PoE on a POE capable port. PoE is enabled on all ports that support it by default in EOS. + priority: Prioritize a port's power in the event that one of the switch's power supplies loses power. + reboot: Set the PoE power behavior for a PoE port when the system is rebooted. + link_down: Set the PoE power behavior for a PoE port when the port goes down. + shutdown: Set the PoE power behavior for a PoE port when the port is admin down. + limit: + Override the hardware-negotiated power limit using either wattage or a power class. Note that if using a power class, + AVD will automatically convert the class value to the wattage value corresponding to that power class. + negotiation_lldp: Disable to prevent port from negotiating power with powered devices over LLDP. Enabled by default in EOS. + legacy_detect: + Allow a subset of legacy devices to work with the PoE switch. Disabled by default in EOS because it can cause false + positive detections. + + """ + self.disabled = disabled + self.priority = priority + self.reboot = reboot + self.link_down = link_down + self.shutdown = shutdown + self.limit = limit + self.negotiation_lldp = negotiation_lldp + self.legacy_detect = legacy_detect + return super().__init__(**kwargs) + + class StormControl(AvdDictBaseModel): + class All(AvdDictBaseModel): + level: str | None = None + """Configure maximum storm-control level.""" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" + """Optional variable and is hardware dependent.""" + + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): + """ + Args: + ----- + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + + """ + self.level = level + self.unit = unit return super().__init__(**kwargs) class Broadcast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -3970,12 +5009,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class Multicast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -3988,12 +5027,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class UnknownUnicast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -4036,12 +5075,18 @@ def __init__( class MonitorSessionsItem(AvdDictBaseModel): class SourceSettings(AvdDictBaseModel): class AccessGroup(AvdDictBaseModel): - type: Literal["ip", "ipv6", "mac"] | None = None + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None name: str | None = None """ACL name.""" priority: int | None = None - def __init__(self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | None = None, priority: int | None = None, **kwargs): + def __init__( + self, + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None, + name: str | None = None, + priority: int | None = None, + **kwargs, + ): """ Args: ----- @@ -4055,10 +5100,10 @@ def __init__(self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | self.priority = priority return super().__init__(**kwargs) - direction: Literal["rx", "tx", "both"] | None = None + direction: Annotated[str, ValidValues["rx", "tx", "both"]] | None = None access_group: AccessGroup | None = None - def __init__(self, direction: Literal["rx", "tx", "both"] | None = None, access_group: AccessGroup | None = None, **kwargs): + def __init__(self, direction: Annotated[str, ValidValues["rx", "tx", "both"]] | None = None, access_group: AccessGroup | None = None, **kwargs): """ Args: ----- @@ -4072,11 +5117,11 @@ def __init__(self, direction: Literal["rx", "tx", "both"] | None = None, access_ class SessionSettings(AvdDictBaseModel): class AccessGroup(AvdDictBaseModel): - type: Literal["ip", "ipv6", "mac"] | None = None + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None name: str | None = None """ACL name.""" - def __init__(self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | None = None, **kwargs): + def __init__(self, type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None, name: str | None = None, **kwargs): """ Args: ----- @@ -4172,7 +5217,7 @@ def __init__( name: str = None """Session name.""" - role: Literal["source", "destination"] | None = None + role: Annotated[str, ValidValues["source", "destination"]] | None = None source_settings: SourceSettings | None = None session_settings: SessionSettings | None = None """ @@ -4184,7 +5229,7 @@ def __init__( def __init__( self, name: str = None, - role: Literal["source", "destination"] | None = None, + role: Annotated[str, ValidValues["source", "destination"]] | None = None, source_settings: SourceSettings | None = None, session_settings: SessionSettings | None = None, **kwargs, @@ -4216,13 +5261,13 @@ class EthernetSegment(AvdDictBaseModel): Please see the notes under "EVPN A/A ESI dual and single-attached endpoint scenarios" before setting `short_esi: auto`. """ - redundancy: Literal["all-active", "single-active"] | None = None + redundancy: Annotated[str, ValidValues["all-active", "single-active"]] | None = None """ If omitted, Port-Channels use the EOS default of all-active. If omitted, Ethernet interfaces are configured as single- active. """ - designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None = None + designated_forwarder_algorithm: Annotated[str, ValidValues["auto", "modulus", "preference"]] | None = None """ Configure DF algorithm and preferences. - auto: Use preference-based algorithm and assign preference based on position @@ -4244,8 +5289,8 @@ class EthernetSegment(AvdDictBaseModel): def __init__( self, short_esi: str = None, - redundancy: Literal["all-active", "single-active"] | None = None, - designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None = None, + redundancy: Annotated[str, ValidValues["all-active", "single-active"]] | None = None, + designated_forwarder_algorithm: Annotated[str, ValidValues["auto", "modulus", "preference"]] | None = None, designated_forwarder_preferences: list[int] | None = None, dont_preempt: bool | None = None, **kwargs, @@ -4302,7 +5347,7 @@ def __init__(self, profile: str | None = None, **kwargs): self.profile = profile return super().__init__(**kwargs) - mode: Literal["static", "individual"] | None = None + mode: Annotated[str, ValidValues["static", "individual"]] | None = None """ Either static or individual mode is supported. If the mode is set to "individual" the "individual.profile" setting must @@ -4314,7 +5359,11 @@ def __init__(self, profile: str | None = None, **kwargs): """Timeout in seconds. EOS default is 90 seconds.""" def __init__( - self, mode: Literal["static", "individual"] | None = None, individual: Individual | None = None, timeout: int | None = None, **kwargs + self, + mode: Annotated[str, ValidValues["static", "individual"]] | None = None, + individual: Individual | None = None, + timeout: int | None = None, + **kwargs, ): """ Args: @@ -4333,12 +5382,12 @@ def __init__( return super().__init__(**kwargs) class LacpTimer(AvdDictBaseModel): - mode: Literal["normal", "fast"] | None = None + mode: Annotated[str, ValidValues["normal", "fast"]] | None = None """LACP mode for interface members.""" multiplier: int | None = None """Number of LACP BPDUs lost before deeming the peer down. EOS default is 3.""" - def __init__(self, mode: Literal["normal", "fast"] | None = None, multiplier: int | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["normal", "fast"]] | None = None, multiplier: int | None = None, **kwargs): """ Args: ----- @@ -4414,7 +5463,7 @@ def __init__( class StructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): pass - mode: Literal["active", "passive", "on"] | None = None + mode: Annotated[str, ValidValues["active", "passive", "on"]] | None = None """Port-Channel Mode.""" channel_id: int | None = None """ @@ -4463,7 +5512,7 @@ class StructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): def __init__( self, - mode: Literal["active", "passive", "on"] | None = None, + mode: Annotated[str, ValidValues["active", "passive", "on"]] | None = None, channel_id: int | None = None, description: str | None = None, enabled: bool | None = True, @@ -4560,7 +5609,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): """Port-profile name to inherit configuration.""" enabled: bool | None = True """Administrative state, setting to false will set the port to 'shutdown' in the intended configuration.""" - mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None = None + mode: Annotated[str, ValidValues["access", "dot1q-tunnel", "trunk", "trunk phone"]] | None = None """Interface mode.""" mtu: int | None = None l2_mtu: int | None = None @@ -4579,7 +5628,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Phone VLAN for a mode `trunk phone` port. Requires `mode: trunk phone` to be set. """ - phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None = None + phone_trunk_mode: Annotated[str, ValidValues["tagged", "untagged", "tagged phone", "untagged phone"]] | None = None """ Specify if the phone traffic is tagged or untagged. If both data and phone traffic are untagged, MAC-Based VLAN @@ -4591,14 +5640,14 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Trunk Groups are used for limiting VLANs on trunk ports to VLANs with the same Trunk Group. """ - vlans: Annotated[str, ConvertTypes[int]] | None = None + vlans: str | None = None """ Interface VLANs - if not set, the EOS default is that all VLANs are allowed for trunk ports, and VLAN 1 will be used for access ports. """ - spanning_tree_portfast: Literal["edge", "network"] | None = None - spanning_tree_bpdufilter: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None - spanning_tree_bpduguard: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None + spanning_tree_portfast: Annotated[str, ValidValues["edge", "network"]] | None = None + spanning_tree_bpdufilter: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None + spanning_tree_bpduguard: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None flowcontrol: Flowcontrol | None = None qos_profile: str | None = None """QOS profile name.""" @@ -4647,19 +5696,19 @@ def __init__( speed: str | None = None, profile: str | None = None, enabled: bool | None = True, - mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None = None, + mode: Annotated[str, ValidValues["access", "dot1q-tunnel", "trunk", "trunk phone"]] | None = None, mtu: int | None = None, l2_mtu: int | None = None, l2_mru: int | None = None, native_vlan: int | None = None, native_vlan_tag: bool | None = False, phone_vlan: int | None = None, - phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None = None, + phone_trunk_mode: Annotated[str, ValidValues["tagged", "untagged", "tagged phone", "untagged phone"]] | None = None, trunk_groups: list[str] | None = None, - vlans: Annotated[str, ConvertTypes[int]] | None = None, - spanning_tree_portfast: Literal["edge", "network"] | None = None, - spanning_tree_bpdufilter: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None, - spanning_tree_bpduguard: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None, + vlans: str | None = None, + spanning_tree_portfast: Annotated[str, ValidValues["edge", "network"]] | None = None, + spanning_tree_bpdufilter: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None, + spanning_tree_bpduguard: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None, flowcontrol: Flowcontrol | None = None, qos_profile: str | None = None, ptp: Ptp | None = None, @@ -4982,32 +6031,32 @@ def __init__( """Type value matching this node_type_key.""" connected_endpoints: bool | None = False """Are endpoints connected to this node type.""" - default_evpn_role: Literal["none", "client", "server"] | None = "none" + default_evpn_role: Annotated[str, ValidValues["none", "client", "server"]] | None = "none" """Default evpn_role. Can be overridden in topology vars.""" default_ptp_priority1: int | None = 127 """Default PTP priority 1""" default_underlay_routing_protocol: ( - Annotated[Literal["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"], ToLower] | None + Annotated[str, ToLower, ValidValues["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"]] | None ) = "ebgp" """ Set the default underlay routing_protocol. Can be overridden by setting "underlay_routing_protocol" host/group_vars. """ - default_overlay_routing_protocol: Annotated[Literal["ebgp", "ibgp", "her", "cvx", "none"], ToLower] | None = "ebgp" + default_overlay_routing_protocol: Annotated[str, ToLower, ValidValues["ebgp", "ibgp", "her", "cvx", "none"]] | None = "ebgp" """ Set the default overlay routing_protocol. Can be overridden by setting "overlay_routing_protocol" host/group_vars. """ - default_mpls_overlay_role: Literal["client", "server", "none"] | None = None + default_mpls_overlay_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None """ Set the default mpls overlay role. Acting role in overlay control plane. """ - default_overlay_address_families: list[Annotated[str, ToLower]] | None = None + default_overlay_address_families: list[Annotated[str, ToLower, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None """Set the default overlay address families.""" - default_evpn_encapsulation: Annotated[Literal["mpls", "vxlan"], ToLower] | None = None + default_evpn_encapsulation: Annotated[str, ToLower, ValidValues["mpls", "vxlan"]] | None = None """Set the default evpn encapsulation.""" - default_wan_role: Literal["client", "server"] | None = None + default_wan_role: Annotated[str, ValidValues["client", "server"]] | None = None """ Set the default WAN role. @@ -5019,7 +6068,7 @@ def __init__( Only supported if `overlay_routing_protocol` is set to `ibgp`. """ - default_flow_tracker_type: Literal["sampled", "hardware"] | None = "sampled" + default_flow_tracker_type: Annotated[str, ValidValues["sampled", "hardware"]] | None = "sampled" """Set the default flow tracker type.""" mlag_support: bool | None = False """Can this node type support mlag.""" @@ -5027,7 +6076,7 @@ def __init__( """Will network services be deployed on this node type.""" underlay_router: bool | None = True """Is this node type a L3 device.""" - uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None = "p2p" + uplink_type: Annotated[str, ValidValues["p2p", "port-channel", "p2p-vrfs", "lan"]] | None = "p2p" """ `uplink_type` must be `p2p`, `p2p-vrfs` or `lan` if `vtep` or `underlay_router` is true. @@ -5062,7 +6111,7 @@ def __init__( If description templates use Jinja2, they have to strip whitespaces using {%- -%} on any code blocks. """ - cv_tags_topology_type: Literal["leaf", "spine", "core", "edge"] | None = None + cv_tags_topology_type: Annotated[str, ValidValues["leaf", "spine", "core", "edge"]] | None = None """ PREVIEW: This key is currently not supported Type that CloudVision should use when generating the Topology. @@ -5073,26 +6122,26 @@ def __init__( key: str = None, type: str | None = None, connected_endpoints: bool | None = False, - default_evpn_role: Literal["none", "client", "server"] | None = "none", + default_evpn_role: Annotated[str, ValidValues["none", "client", "server"]] | None = "none", default_ptp_priority1: int | None = 127, default_underlay_routing_protocol: ( - Annotated[Literal["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"], ToLower] | None + Annotated[str, ToLower, ValidValues["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"]] | None ) = "ebgp", - default_overlay_routing_protocol: Annotated[Literal["ebgp", "ibgp", "her", "cvx", "none"], ToLower] | None = "ebgp", - default_mpls_overlay_role: Literal["client", "server", "none"] | None = None, - default_overlay_address_families: list[Annotated[str, ToLower]] | None = None, - default_evpn_encapsulation: Annotated[Literal["mpls", "vxlan"], ToLower] | None = None, - default_wan_role: Literal["client", "server"] | None = None, - default_flow_tracker_type: Literal["sampled", "hardware"] | None = "sampled", + default_overlay_routing_protocol: Annotated[str, ToLower, ValidValues["ebgp", "ibgp", "her", "cvx", "none"]] | None = "ebgp", + default_mpls_overlay_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None, + default_overlay_address_families: list[Annotated[str, ToLower, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None, + default_evpn_encapsulation: Annotated[str, ToLower, ValidValues["mpls", "vxlan"]] | None = None, + default_wan_role: Annotated[str, ValidValues["client", "server"]] | None = None, + default_flow_tracker_type: Annotated[str, ValidValues["sampled", "hardware"]] | None = "sampled", mlag_support: bool | None = False, network_services: NetworkServices | None = None, underlay_router: bool | None = True, - uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None = "p2p", + uplink_type: Annotated[str, ValidValues["p2p", "port-channel", "p2p-vrfs", "lan"]] | None = "p2p", vtep: bool | None = False, mpls_lsr: bool | None = False, ip_addressing: IpAddressing | None = None, interface_descriptions: InterfaceDescriptions | None = None, - cv_tags_topology_type: Literal["leaf", "spine", "core", "edge"] | None = None, + cv_tags_topology_type: Annotated[str, ValidValues["leaf", "spine", "core", "edge"]] | None = None, **kwargs, ): """ @@ -5232,17 +6281,17 @@ def __init__( class AuthenticationKeysItem(AvdDictBaseModel): id: int = None """Key identifier.""" - hash_algorithm: Literal["md5", "sha1"] | None = None + hash_algorithm: Annotated[str, ValidValues["md5", "sha1"]] | None = None key: str | None = None """Obfuscated key.""" - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = None + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = None def __init__( self, id: int = None, - hash_algorithm: Literal["md5", "sha1"] | None = None, + hash_algorithm: Annotated[str, ValidValues["md5", "sha1"]] | None = None, key: str | None = None, - key_type: Annotated[Literal["0", "7", "8a"], ConvertTypes[int]] | None = None, + key_type: Annotated[str, ValidValues["0", "7", "8a"]] | None = None, **kwargs, ): """ @@ -5282,7 +6331,7 @@ def __init__( authenticate: bool | None = None authenticate_servers_only: bool | None = None authentication_keys: list[AuthenticationKeysItem] | None = None - trusted_keys: Annotated[str, ConvertTypes[int]] | None = None + trusted_keys: str | None = None """List of trusted-keys as string ex. 10-12,15.""" def __init__( @@ -5292,7 +6341,7 @@ def __init__( authenticate: bool | None = None, authenticate_servers_only: bool | None = None, authentication_keys: list[AuthenticationKeysItem] | None = None, - trusted_keys: Annotated[str, ConvertTypes[int]] | None = None, + trusted_keys: str | None = None, **kwargs, ): """ @@ -5329,7 +6378,7 @@ def __init__( return super().__init__(**kwargs) class OverlayRdType(AvdDictBaseModel): - admin_subfield: Annotated[str, ConvertTypes[int]] | None = "overlay_loopback_ip" + admin_subfield: str | None = "overlay_loopback_ip" """ The method for deriving RD Administrator subfield (first part of RD): - 'overlay_loopback_ip' means the IP address of @@ -5343,13 +6392,13 @@ class OverlayRdType(AvdDictBaseModel): <0-65535>. - Integer between <0-4294967295>. """ - admin_subfield_offset: Annotated[str, ConvertTypes[int]] | None = None + admin_subfield_offset: str | None = None """ Offset can only be used if admin_subfield is an integer between <0-4294967295> or 'switch_id'. Total value of admin_subfield + admin_subfield_offset must be <= 4294967295. """ - vrf_admin_subfield: Annotated[str, ConvertTypes[int]] | None = None + vrf_admin_subfield: str | None = None """ The method for deriving RD Administrator subfield (first part of RD) for VRF services: - 'overlay_loopback_ip' means the @@ -5366,13 +6415,13 @@ class OverlayRdType(AvdDictBaseModel): 'vrf_admin_subfield' takes precedence for VRF RDs if set. Otherwise the 'admin_subfield' value will be used. """ - vrf_admin_subfield_offset: Annotated[str, ConvertTypes[int]] | None = None + vrf_admin_subfield_offset: str | None = None """ Offset can only be used if 'vrf_admin_subfield' is an integer between <0-4294967295> or 'switch_id'. Total value of 'vrf_admin_subfield' + 'vrf_admin_subfield_offset' must be <= 4294967295. """ - vlan_assigned_number_subfield: Literal["mac_vrf_id", "mac_vrf_vni", "vlan_id"] | None = "mac_vrf_id" + vlan_assigned_number_subfield: Annotated[str, ValidValues["mac_vrf_id", "mac_vrf_vni", "vlan_id"]] | None = "mac_vrf_id" """ The method for deriving RD Assigned Number subfield for VLAN services (second part of RD): - 'mac_vrf_id' means @@ -5387,11 +6436,11 @@ class OverlayRdType(AvdDictBaseModel): def __init__( self, - admin_subfield: Annotated[str, ConvertTypes[int]] | None = "overlay_loopback_ip", - admin_subfield_offset: Annotated[str, ConvertTypes[int]] | None = None, - vrf_admin_subfield: Annotated[str, ConvertTypes[int]] | None = None, - vrf_admin_subfield_offset: Annotated[str, ConvertTypes[int]] | None = None, - vlan_assigned_number_subfield: Literal["mac_vrf_id", "mac_vrf_vni", "vlan_id"] | None = "mac_vrf_id", + admin_subfield: str | None = "overlay_loopback_ip", + admin_subfield_offset: str | None = None, + vrf_admin_subfield: str | None = None, + vrf_admin_subfield_offset: str | None = None, + vlan_assigned_number_subfield: Annotated[str, ValidValues["mac_vrf_id", "mac_vrf_vni", "vlan_id"]] | None = "mac_vrf_id", **kwargs, ): """ @@ -5452,7 +6501,7 @@ def __init__( return super().__init__(**kwargs) class OverlayRtType(AvdDictBaseModel): - admin_subfield: Annotated[str, ConvertTypes[int]] | None = "vrf_id" + admin_subfield: str | None = "vrf_id" """ The method for deriving RT Administrator subfield (first part of RT): - 'vrf_id' means `(mac_vrf_id_base or @@ -5471,7 +6520,7 @@ class OverlayRtType(AvdDictBaseModel): The 'vrf_id', 'vrf_vni' and 'id' methods can be overridden per bundle defined under `evpn_vlan_bundles` using 'rt_override'. """ - vrf_admin_subfield: Annotated[str, ConvertTypes[int]] | None = "vrf_id" + vrf_admin_subfield: str | None = "vrf_id" """ The method for deriving RT Administrator subfield (first part of RT) for VRF services: - 'id' means `(vrf_id or @@ -5486,7 +6535,7 @@ class OverlayRtType(AvdDictBaseModel): 'vrf_admin_subfield' takes precedence for VRF RDs if set. Otherwise the 'admin_subfield' value will be used. """ - vlan_assigned_number_subfield: Literal["mac_vrf_id", "mac_vrf_vni", "vlan_id"] | None = "mac_vrf_id" + vlan_assigned_number_subfield: Annotated[str, ValidValues["mac_vrf_id", "mac_vrf_vni", "vlan_id"]] | None = "mac_vrf_id" """ The method for deriving RT Assigned Number subfield for VLAN services (second part of RT): - 'mac_vrf_id' means @@ -5501,9 +6550,9 @@ class OverlayRtType(AvdDictBaseModel): def __init__( self, - admin_subfield: Annotated[str, ConvertTypes[int]] | None = "vrf_id", - vrf_admin_subfield: Annotated[str, ConvertTypes[int]] | None = "vrf_id", - vlan_assigned_number_subfield: Literal["mac_vrf_id", "mac_vrf_vni", "vlan_id"] | None = "mac_vrf_id", + admin_subfield: str | None = "vrf_id", + vrf_admin_subfield: str | None = "vrf_id", + vlan_assigned_number_subfield: Annotated[str, ValidValues["mac_vrf_id", "mac_vrf_vni", "vlan_id"]] | None = "mac_vrf_id", **kwargs, ): """ @@ -5680,7 +6729,7 @@ def __init__( class StructuredConfig(EosCliConfigGen): pass - platforms: list[Annotated[str, ConvertTypes[int]]] | None = None + platforms: list[str] | None = None trident_forwarding_table_partition: str | None = None """Only applied when evpn_multicast is true.""" reload_delay: ReloadDelay | None = None @@ -5703,7 +6752,7 @@ class StructuredConfig(EosCliConfigGen): def __init__( self, - platforms: list[Annotated[str, ConvertTypes[int]]] | None = None, + platforms: list[str] | None = None, trident_forwarding_table_partition: str | None = None, reload_delay: ReloadDelay | None = None, tcam_profile: str | None = None, @@ -5751,9 +6800,9 @@ def __init__( class PlatformSpeedGroupsItem(AvdDictBaseModel): class SpeedsItem(AvdDictBaseModel): speed: str = None - speed_groups: list[Annotated[str, ConvertTypes[int]]] | None = None + speed_groups: list[str] | None = None - def __init__(self, speed: str = None, speed_groups: list[Annotated[str, ConvertTypes[int]]] | None = None, **kwargs): + def __init__(self, speed: str = None, speed_groups: list[str] | None = None, **kwargs): """ Args: ----- @@ -5765,10 +6814,10 @@ def __init__(self, speed: str = None, speed_groups: list[Annotated[str, ConvertT self.speed_groups = speed_groups return super().__init__(**kwargs) - platform: Annotated[str, ConvertTypes[int]] = None + platform: str = None speeds: list[SpeedsItem] | None = None - def __init__(self, platform: Annotated[str, ConvertTypes[int]] = None, speeds: list[SpeedsItem] | None = None, **kwargs): + def __init__(self, platform: str = None, speeds: list[SpeedsItem] | None = None, **kwargs): """ Args: ----- @@ -5782,9 +6831,9 @@ def __init__(self, platform: Annotated[str, ConvertTypes[int]] = None, speeds: l class PortProfilesItem(AvdDictBaseModel): class Flowcontrol(AvdDictBaseModel): - received: Literal["received", "send", "on"] | None = None + received: Annotated[str, ValidValues["received", "send", "on"]] | None = None - def __init__(self, received: Literal["received", "send", "on"] | None = None, **kwargs): + def __init__(self, received: Annotated[str, ValidValues["received", "send", "on"]] | None = None, **kwargs): """ Args: ----- @@ -5796,14 +6845,14 @@ def __init__(self, received: Literal["received", "send", "on"] | None = None, ** class Ptp(AvdDictBaseModel): enabled: bool | None = False - endpoint_role: Literal["bmca", "default", "follower"] | None = "follower" - profile: Literal["aes67", "aes67-r16-2016", "smpte2059-2"] | None = "aes67-r16-2016" + endpoint_role: Annotated[str, ValidValues["bmca", "default", "follower"]] | None = "follower" + profile: Annotated[str, ValidValues["aes67", "aes67-r16-2016", "smpte2059-2"]] | None = "aes67-r16-2016" def __init__( self, enabled: bool | None = False, - endpoint_role: Literal["bmca", "default", "follower"] | None = "follower", - profile: Literal["aes67", "aes67-r16-2016", "smpte2059-2"] | None = "aes67-r16-2016", + endpoint_role: Annotated[str, ValidValues["bmca", "default", "follower"]] | None = "follower", + profile: Annotated[str, ValidValues["aes67", "aes67-r16-2016", "smpte2059-2"]] | None = "aes67-r16-2016", **kwargs, ): """ @@ -5864,9 +6913,9 @@ def __init__(self, enabled: bool | None = None, name: str | None = None, **kwarg class Dot1x(AvdDictBaseModel): class Pae(AvdDictBaseModel): - mode: Literal["authenticator"] | None = None + mode: Annotated[str, ValidValues["authenticator"]] | None = None - def __init__(self, mode: Literal["authenticator"] | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["authenticator"]] | None = None, **kwargs): """ Args: ----- @@ -5877,10 +6926,10 @@ def __init__(self, mode: Literal["authenticator"] | None = None, **kwargs): return super().__init__(**kwargs) class AuthenticationFailure(AvdDictBaseModel): - action: Literal["allow", "drop"] | None = None + action: Annotated[str, ValidValues["allow", "drop"]] | None = None allow_vlan: int | None = None - def __init__(self, action: Literal["allow", "drop"] | None = None, allow_vlan: int | None = None, **kwargs): + def __init__(self, action: Annotated[str, ValidValues["allow", "drop"]] | None = None, allow_vlan: int | None = None, **kwargs): """ Args: ----- @@ -5893,10 +6942,12 @@ def __init__(self, action: Literal["allow", "drop"] | None = None, allow_vlan: i return super().__init__(**kwargs) class HostMode(AvdDictBaseModel): - mode: Literal["multi-host", "single-host"] | None = None + mode: Annotated[str, ValidValues["multi-host", "single-host"]] | None = None multi_host_authenticated: bool | None = None - def __init__(self, mode: Literal["multi-host", "single-host"] | None = None, multi_host_authenticated: bool | None = None, **kwargs): + def __init__( + self, mode: Annotated[str, ValidValues["multi-host", "single-host"]] | None = None, multi_host_authenticated: bool | None = None, **kwargs + ): """ Args: ----- @@ -5930,7 +6981,7 @@ def __init__(self, enabled: bool | None = None, always: bool | None = None, host class Timeout(AvdDictBaseModel): idle_host: int | None = None quiet_period: int | None = None - reauth_period: Annotated[str, ConvertTypes[int]] | None = None + reauth_period: str | None = None """Range 60-4294967295 or "server".""" reauth_timeout_ignore: bool | None = None tx_period: int | None = None @@ -5939,7 +6990,7 @@ def __init__( self, idle_host: int | None = None, quiet_period: int | None = None, - reauth_period: Annotated[str, ConvertTypes[int]] | None = None, + reauth_period: str | None = None, reauth_timeout_ignore: bool | None = None, tx_period: int | None = None, **kwargs, @@ -5977,7 +7028,7 @@ def __init__(self, access_vlan_membership_egress: bool | None = None, native_vla self.native_vlan_membership_egress = native_vlan_membership_egress return super().__init__(**kwargs) - port_control: Literal["auto", "force-authorized", "force-unauthorized"] | None = None + port_control: Annotated[str, ValidValues["auto", "force-authorized", "force-unauthorized"]] | None = None port_control_force_authorized_phone: bool | None = None reauthentication: bool | None = None pae: Pae | None = None @@ -5990,7 +7041,7 @@ def __init__(self, access_vlan_membership_egress: bool | None = None, native_vla def __init__( self, - port_control: Literal["auto", "force-authorized", "force-unauthorized"] | None = None, + port_control: Annotated[str, ValidValues["auto", "force-authorized", "force-unauthorized"]] | None = None, port_control_force_authorized_phone: bool | None = None, reauthentication: bool | None = None, pae: Pae | None = None, @@ -6029,17 +7080,143 @@ def __init__( self.unauthorized = unauthorized return super().__init__(**kwargs) - class Poe(EosCliConfigGen.EthernetInterfacesItem.Poe): - pass + class Poe(AvdDictBaseModel): + class Reboot(AvdDictBaseModel): + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None + """PoE action for interface.""" + + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, **kwargs): + """ + Args: + ----- + action: PoE action for interface. + + """ + self.action = action + return super().__init__(**kwargs) + + class LinkDown(AvdDictBaseModel): + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None + """PoE action for interface.""" + power_off_delay: int | None = None + """Number of seconds to delay shutting the power off after a link down event occurs. Default value is 5 seconds in EOS.""" + + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, power_off_delay: int | None = None, **kwargs): + """ + Args: + ----- + action: PoE action for interface. + power_off_delay: Number of seconds to delay shutting the power off after a link down event occurs. Default value is 5 seconds in EOS. + + """ + self.action = action + self.power_off_delay = power_off_delay + return super().__init__(**kwargs) + + class Shutdown(AvdDictBaseModel): + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None + """PoE action for interface.""" + + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, **kwargs): + """ + Args: + ----- + action: PoE action for interface. + + """ + self.action = action + return super().__init__(**kwargs) + + class Limit(AvdDictBaseModel): + field_class: int | None = None + watts: str | None = None + fixed: bool | None = None + """Set to ignore hardware classification.""" + + def __init__(self, field_class: int | None = None, watts: str | None = None, fixed: bool | None = None, **kwargs): + """ + Args: + ----- + field_class: field_class + watts: watts + fixed: Set to ignore hardware classification. + + """ + self.field_class = field_class + self.watts = watts + self.fixed = fixed + return super().__init__(**kwargs) + + disabled: bool | None = False + """Disable PoE on a POE capable port. PoE is enabled on all ports that support it by default in EOS.""" + priority: Annotated[str, ValidValues["critical", "high", "medium", "low"]] | None = None + """Prioritize a port's power in the event that one of the switch's power supplies loses power.""" + reboot: Reboot | None = None + """Set the PoE power behavior for a PoE port when the system is rebooted.""" + link_down: LinkDown | None = None + """Set the PoE power behavior for a PoE port when the port goes down.""" + shutdown: Shutdown | None = None + """Set the PoE power behavior for a PoE port when the port is admin down.""" + limit: Limit | None = None + """ + Override the hardware-negotiated power limit using either wattage or a power class. Note that if using a power class, + AVD will automatically convert the class value to the wattage value corresponding to that power class. + """ + negotiation_lldp: bool | None = None + """Disable to prevent port from negotiating power with powered devices over LLDP. Enabled by default in EOS.""" + legacy_detect: bool | None = None + """ + Allow a subset of legacy devices to work with the PoE switch. Disabled by default in EOS because it can cause false + positive detections. + """ + + def __init__( + self, + disabled: bool | None = False, + priority: Annotated[str, ValidValues["critical", "high", "medium", "low"]] | None = None, + reboot: Reboot | None = None, + link_down: LinkDown | None = None, + shutdown: Shutdown | None = None, + limit: Limit | None = None, + negotiation_lldp: bool | None = None, + legacy_detect: bool | None = None, + **kwargs, + ): + """ + Args: + ----- + disabled: Disable PoE on a POE capable port. PoE is enabled on all ports that support it by default in EOS. + priority: Prioritize a port's power in the event that one of the switch's power supplies loses power. + reboot: Set the PoE power behavior for a PoE port when the system is rebooted. + link_down: Set the PoE power behavior for a PoE port when the port goes down. + shutdown: Set the PoE power behavior for a PoE port when the port is admin down. + limit: + Override the hardware-negotiated power limit using either wattage or a power class. Note that if using a power class, + AVD will automatically convert the class value to the wattage value corresponding to that power class. + negotiation_lldp: Disable to prevent port from negotiating power with powered devices over LLDP. Enabled by default in EOS. + legacy_detect: + Allow a subset of legacy devices to work with the PoE switch. Disabled by default in EOS because it can cause false + positive detections. + + """ + self.disabled = disabled + self.priority = priority + self.reboot = reboot + self.link_down = link_down + self.shutdown = shutdown + self.limit = limit + self.negotiation_lldp = negotiation_lldp + self.legacy_detect = legacy_detect + return super().__init__(**kwargs) class StormControl(AvdDictBaseModel): class All(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -6052,12 +7229,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class Broadcast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -6070,12 +7247,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class Multicast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -6088,12 +7265,12 @@ def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None return super().__init__(**kwargs) class UnknownUnicast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__(self, level: Annotated[str, ConvertTypes[int, float]] | None = None, unit: Literal["percent", "pps"] | None = "percent", **kwargs): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -6136,12 +7313,18 @@ def __init__( class MonitorSessionsItem(AvdDictBaseModel): class SourceSettings(AvdDictBaseModel): class AccessGroup(AvdDictBaseModel): - type: Literal["ip", "ipv6", "mac"] | None = None + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None name: str | None = None """ACL name.""" priority: int | None = None - def __init__(self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | None = None, priority: int | None = None, **kwargs): + def __init__( + self, + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None, + name: str | None = None, + priority: int | None = None, + **kwargs, + ): """ Args: ----- @@ -6155,10 +7338,10 @@ def __init__(self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | self.priority = priority return super().__init__(**kwargs) - direction: Literal["rx", "tx", "both"] | None = None + direction: Annotated[str, ValidValues["rx", "tx", "both"]] | None = None access_group: AccessGroup | None = None - def __init__(self, direction: Literal["rx", "tx", "both"] | None = None, access_group: AccessGroup | None = None, **kwargs): + def __init__(self, direction: Annotated[str, ValidValues["rx", "tx", "both"]] | None = None, access_group: AccessGroup | None = None, **kwargs): """ Args: ----- @@ -6172,11 +7355,11 @@ def __init__(self, direction: Literal["rx", "tx", "both"] | None = None, access_ class SessionSettings(AvdDictBaseModel): class AccessGroup(AvdDictBaseModel): - type: Literal["ip", "ipv6", "mac"] | None = None + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None name: str | None = None """ACL name.""" - def __init__(self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | None = None, **kwargs): + def __init__(self, type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None, name: str | None = None, **kwargs): """ Args: ----- @@ -6272,7 +7455,7 @@ def __init__( name: str = None """Session name.""" - role: Literal["source", "destination"] | None = None + role: Annotated[str, ValidValues["source", "destination"]] | None = None source_settings: SourceSettings | None = None session_settings: SessionSettings | None = None """ @@ -6284,7 +7467,7 @@ def __init__( def __init__( self, name: str = None, - role: Literal["source", "destination"] | None = None, + role: Annotated[str, ValidValues["source", "destination"]] | None = None, source_settings: SourceSettings | None = None, session_settings: SessionSettings | None = None, **kwargs, @@ -6316,13 +7499,13 @@ class EthernetSegment(AvdDictBaseModel): Please see the notes under "EVPN A/A ESI dual and single-attached endpoint scenarios" before setting `short_esi: auto`. """ - redundancy: Literal["all-active", "single-active"] | None = None + redundancy: Annotated[str, ValidValues["all-active", "single-active"]] | None = None """ If omitted, Port-Channels use the EOS default of all-active. If omitted, Ethernet interfaces are configured as single- active. """ - designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None = None + designated_forwarder_algorithm: Annotated[str, ValidValues["auto", "modulus", "preference"]] | None = None """ Configure DF algorithm and preferences. - auto: Use preference-based algorithm and assign preference based on position @@ -6344,8 +7527,8 @@ class EthernetSegment(AvdDictBaseModel): def __init__( self, short_esi: str = None, - redundancy: Literal["all-active", "single-active"] | None = None, - designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None = None, + redundancy: Annotated[str, ValidValues["all-active", "single-active"]] | None = None, + designated_forwarder_algorithm: Annotated[str, ValidValues["auto", "modulus", "preference"]] | None = None, designated_forwarder_preferences: list[int] | None = None, dont_preempt: bool | None = None, **kwargs, @@ -6402,7 +7585,7 @@ def __init__(self, profile: str | None = None, **kwargs): self.profile = profile return super().__init__(**kwargs) - mode: Literal["static", "individual"] | None = None + mode: Annotated[str, ValidValues["static", "individual"]] | None = None """ Either static or individual mode is supported. If the mode is set to "individual" the "individual.profile" setting must @@ -6414,7 +7597,11 @@ def __init__(self, profile: str | None = None, **kwargs): """Timeout in seconds. EOS default is 90 seconds.""" def __init__( - self, mode: Literal["static", "individual"] | None = None, individual: Individual | None = None, timeout: int | None = None, **kwargs + self, + mode: Annotated[str, ValidValues["static", "individual"]] | None = None, + individual: Individual | None = None, + timeout: int | None = None, + **kwargs, ): """ Args: @@ -6433,12 +7620,12 @@ def __init__( return super().__init__(**kwargs) class LacpTimer(AvdDictBaseModel): - mode: Literal["normal", "fast"] | None = None + mode: Annotated[str, ValidValues["normal", "fast"]] | None = None """LACP mode for interface members.""" multiplier: int | None = None """Number of LACP BPDUs lost before deeming the peer down. EOS default is 3.""" - def __init__(self, mode: Literal["normal", "fast"] | None = None, multiplier: int | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["normal", "fast"]] | None = None, multiplier: int | None = None, **kwargs): """ Args: ----- @@ -6514,7 +7701,7 @@ def __init__( class StructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): pass - mode: Literal["active", "passive", "on"] | None = None + mode: Annotated[str, ValidValues["active", "passive", "on"]] | None = None """Port-Channel Mode.""" channel_id: int | None = None """ @@ -6563,7 +7750,7 @@ class StructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): def __init__( self, - mode: Literal["active", "passive", "on"] | None = None, + mode: Annotated[str, ValidValues["active", "passive", "on"]] | None = None, channel_id: int | None = None, description: str | None = None, enabled: bool | None = True, @@ -6649,7 +7836,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): """ enabled: bool | None = True """Administrative state, setting to false will set the port to 'shutdown' in the intended configuration.""" - mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None = None + mode: Annotated[str, ValidValues["access", "dot1q-tunnel", "trunk", "trunk phone"]] | None = None """Interface mode.""" mtu: int | None = None l2_mtu: int | None = None @@ -6668,7 +7855,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Phone VLAN for a mode `trunk phone` port. Requires `mode: trunk phone` to be set. """ - phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None = None + phone_trunk_mode: Annotated[str, ValidValues["tagged", "untagged", "tagged phone", "untagged phone"]] | None = None """ Specify if the phone traffic is tagged or untagged. If both data and phone traffic are untagged, MAC-Based VLAN @@ -6680,14 +7867,14 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Trunk Groups are used for limiting VLANs on trunk ports to VLANs with the same Trunk Group. """ - vlans: Annotated[str, ConvertTypes[int]] | None = None + vlans: str | None = None """ Interface VLANs - if not set, the EOS default is that all VLANs are allowed for trunk ports, and VLAN 1 will be used for access ports. """ - spanning_tree_portfast: Literal["edge", "network"] | None = None - spanning_tree_bpdufilter: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None - spanning_tree_bpduguard: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None + spanning_tree_portfast: Annotated[str, ValidValues["edge", "network"]] | None = None + spanning_tree_bpdufilter: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None + spanning_tree_bpduguard: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None flowcontrol: Flowcontrol | None = None qos_profile: str | None = None """QOS profile name.""" @@ -6735,19 +7922,19 @@ def __init__( speed: str | None = None, description: str | None = None, enabled: bool | None = True, - mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None = None, + mode: Annotated[str, ValidValues["access", "dot1q-tunnel", "trunk", "trunk phone"]] | None = None, mtu: int | None = None, l2_mtu: int | None = None, l2_mru: int | None = None, native_vlan: int | None = None, native_vlan_tag: bool | None = False, phone_vlan: int | None = None, - phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None = None, + phone_trunk_mode: Annotated[str, ValidValues["tagged", "untagged", "tagged phone", "untagged phone"]] | None = None, trunk_groups: list[str] | None = None, - vlans: Annotated[str, ConvertTypes[int]] | None = None, - spanning_tree_portfast: Literal["edge", "network"] | None = None, - spanning_tree_bpdufilter: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None, - spanning_tree_bpduguard: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None, + vlans: str | None = None, + spanning_tree_portfast: Annotated[str, ValidValues["edge", "network"]] | None = None, + spanning_tree_bpdufilter: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None, + spanning_tree_bpduguard: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None, flowcontrol: Flowcontrol | None = None, qos_profile: str | None = None, ptp: Ptp | None = None, @@ -6869,14 +8056,14 @@ def __init__( class Ptp(AvdDictBaseModel): enabled: bool | None = None - profile: Literal["aes67", "smpte2059-2", "aes67-r16-2016"] | None = "aes67-r16-2016" + profile: Annotated[str, ValidValues["aes67", "smpte2059-2", "aes67-r16-2016"]] | None = "aes67-r16-2016" domain: int | None = None auto_clock_identity: bool | None = True def __init__( self, enabled: bool | None = None, - profile: Literal["aes67", "smpte2059-2", "aes67-r16-2016"] | None = "aes67-r16-2016", + profile: Annotated[str, ValidValues["aes67", "smpte2059-2", "aes67-r16-2016"]] | None = "aes67-r16-2016", domain: int | None = None, auto_clock_identity: bool | None = True, **kwargs, @@ -6933,7 +8120,7 @@ def __init__(self, interval: int | None = None, **kwargs): delay_req: int | None = None sync_message: SyncMessage | None = None """PTP sync message interval.""" - transport: Literal["ipv4"] | None = None + transport: Annotated[str, ValidValues["ipv4"]] | None = None def __init__( self, @@ -6941,7 +8128,7 @@ def __init__( announce: Announce | None = None, delay_req: int | None = None, sync_message: SyncMessage | None = None, - transport: Literal["ipv4"] | None = None, + transport: Annotated[str, ValidValues["ipv4"]] | None = None, **kwargs, ): """ @@ -6961,15 +8148,82 @@ def __init__( self.transport = transport return super().__init__(**kwargs) - class QueueMonitorLength(EosCliConfigGen.QueueMonitorLength): - enabled: bool | None = None + class QueueMonitorLength(AvdDictBaseModel): + class DefaultThresholds(AvdDictBaseModel): + high: int = None + """Default high threshold for Ethernet Interfaces.""" + low: int | None = None + """ + Default low threshold for Ethernet Interfaces. + Low threshold support is platform dependent. + """ + + def __init__(self, high: int = None, low: int | None = None, **kwargs): + """ + Args: + ----- + high: Default high threshold for Ethernet Interfaces. + low: + Default low threshold for Ethernet Interfaces. + Low threshold support is platform dependent. + + """ + self.high = high + self.low = low + return super().__init__(**kwargs) + + class Cpu(AvdDictBaseModel): + class Thresholds(AvdDictBaseModel): + high: int = None + low: int | None = None + + def __init__(self, high: int = None, low: int | None = None, **kwargs): + """ + Args: + ----- + high: high + low: low + + """ + self.high = high + self.low = low + return super().__init__(**kwargs) + + thresholds: Thresholds | None = None + + def __init__(self, thresholds: Thresholds | None = None, **kwargs): + """ + Args: + ----- + thresholds: thresholds + + """ + self.thresholds = thresholds + return super().__init__(**kwargs) + + enabled: bool = None notifying: bool | None = None """ If True, `eos_designs` will configure `queue-monitor length notifying` according to the `platform_settings.[].feature_support.queue_monitor_length_notify` setting. """ + default_thresholds: DefaultThresholds | None = None + log: int | None = None + """Logging interval in seconds.""" + cpu: Cpu | None = None + tx_latency: bool | None = None + """Enable tx-latency mode.""" - def __init__(self, enabled: bool | None = None, notifying: bool | None = None, **kwargs): + def __init__( + self, + enabled: bool = None, + notifying: bool | None = None, + default_thresholds: DefaultThresholds | None = None, + log: int | None = None, + cpu: Cpu | None = None, + tx_latency: bool | None = None, + **kwargs, + ): """ Args: ----- @@ -6977,16 +8231,24 @@ def __init__(self, enabled: bool | None = None, notifying: bool | None = None, * notifying: If True, `eos_designs` will configure `queue-monitor length notifying` according to the `platform_settings.[].feature_support.queue_monitor_length_notify` setting. + default_thresholds: default_thresholds + log: Logging interval in seconds. + cpu: cpu + tx_latency: Enable tx-latency mode. """ self.enabled = enabled self.notifying = notifying + self.default_thresholds = default_thresholds + self.log = log + self.cpu = cpu + self.tx_latency = tx_latency return super().__init__(**kwargs) class Redundancy(AvdDictBaseModel): - protocol: Literal["sso", "rpr"] | None = None + protocol: Annotated[str, ValidValues["sso", "rpr"]] | None = None - def __init__(self, protocol: Literal["sso", "rpr"] | None = None, **kwargs): + def __init__(self, protocol: Annotated[str, ValidValues["sso", "rpr"]] | None = None, **kwargs): """ Args: ----- @@ -7023,7 +8285,7 @@ class DestinationsItem(AvdDictBaseModel): """sFlow destination name or IP address.""" port: int | None = None """UDP Port number. The default port number for sFlow is 6343.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None """ If not set, the VRF is automatically picked up from the global setting `default_mgmt_method`. The value of `vrf` will be @@ -7040,7 +8302,7 @@ class DestinationsItem(AvdDictBaseModel): Remember to set the `sflow_settings.vrfs[].source_interface` if needed. """ - def __init__(self, destination: str = None, port: int | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, destination: str = None, port: int | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -7068,7 +8330,7 @@ def __init__(self, destination: str = None, port: int | None = None, vrf: Annota return super().__init__(**kwargs) class VrfsItem(AvdDictBaseModel): - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF name.""" source_interface: str | None = None """ @@ -7077,7 +8339,7 @@ class VrfsItem(AvdDictBaseModel): `inband_mgmt_vrf`, this setting will take precedence. """ - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, source_interface: str | None = None, **kwargs): + def __init__(self, name: str = None, source_interface: str | None = None, **kwargs): """ Args: ----- @@ -7112,11 +8374,11 @@ def __init__(self, sample: Sample | None = None, destinations: list[Destinations class SnmpSettings(AvdDictBaseModel): class VrfsItem(AvdDictBaseModel): - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF name.""" enable: bool | None = None - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, enable: bool | None = None, **kwargs): + def __init__(self, name: str = None, enable: bool | None = None, **kwargs): """ Args: ----- @@ -7133,11 +8395,11 @@ class UsersItem(AvdDictBaseModel): """Username.""" group: str | None = None """Group name.""" - version: Literal["v1", "v2c", "v3"] | None = None - auth: Literal["md5", "sha", "sha256", "sha384", "sha512"] | None = None + version: Annotated[str, ValidValues["v1", "v2c", "v3"]] | None = None + auth: Annotated[str, ValidValues["md5", "sha", "sha256", "sha384", "sha512"]] | None = None auth_passphrase: str | None = None """Cleartext passphrase so the recommendation is to use vault. Requires 'auth' to be set.""" - priv: Literal["des", "aes", "aes192", "aes256"] | None = None + priv: Annotated[str, ValidValues["des", "aes", "aes192", "aes256"]] | None = None priv_passphrase: str | None = None """Cleartext passphrase so the recommendation is to use vault. Requires 'priv' to be set.""" @@ -7145,10 +8407,10 @@ def __init__( self, name: str | None = None, group: str | None = None, - version: Literal["v1", "v2c", "v3"] | None = None, - auth: Literal["md5", "sha", "sha256", "sha384", "sha512"] | None = None, + version: Annotated[str, ValidValues["v1", "v2c", "v3"]] | None = None, + auth: Annotated[str, ValidValues["md5", "sha", "sha256", "sha384", "sha512"]] | None = None, auth_passphrase: str | None = None, - priv: Literal["des", "aes", "aes192", "aes256"] | None = None, + priv: Annotated[str, ValidValues["des", "aes", "aes192", "aes256"]] | None = None, priv_passphrase: str | None = None, **kwargs, ): @@ -7176,9 +8438,11 @@ def __init__( class HostsItem(AvdDictBaseModel): class UsersItem(AvdDictBaseModel): username: str | None = None - authentication_level: Literal["auth", "noauth", "priv"] | None = None + authentication_level: Annotated[str, ValidValues["auth", "noauth", "priv"]] | None = None - def __init__(self, username: str | None = None, authentication_level: Literal["auth", "noauth", "priv"] | None = None, **kwargs): + def __init__( + self, username: str | None = None, authentication_level: Annotated[str, ValidValues["auth", "noauth", "priv"]] | None = None, **kwargs + ): """ Args: ----- @@ -7192,7 +8456,7 @@ def __init__(self, username: str | None = None, authentication_level: Literal["a host: str | None = None """Host IP address or name.""" - vrf: Annotated[str, ConvertTypes[int, int]] | None = None + vrf: str | None = None """ VRF Name. Can be used in combination with "use_mgmt_interface_vrf" and "use_inband_mgmt_vrf" to configure the SNMP host @@ -7210,7 +8474,7 @@ def __init__(self, username: str | None = None, authentication_level: Literal["a device, so if the host is only configured with this VRF, the host will not be configured at all. Can be used in combination with "vrf" and "use_mgmt_interface_vrf" to configure the SNMP host under multiple VRFs. """ - version: Annotated[Literal["1", "2c", "3"], ConvertTypes[int]] | None = None + version: Annotated[str, ValidValues["1", "2c", "3"]] | None = None community: str | None = None """Community name.""" users: list[UsersItem] | None = None @@ -7218,10 +8482,10 @@ def __init__(self, username: str | None = None, authentication_level: Literal["a def __init__( self, host: str | None = None, - vrf: Annotated[str, ConvertTypes[int, int]] | None = None, + vrf: str | None = None, use_mgmt_interface_vrf: bool | None = None, use_inband_mgmt_vrf: bool | None = None, - version: Annotated[Literal["1", "2c", "3"], ConvertTypes[int]] | None = None, + version: Annotated[str, ValidValues["1", "2c", "3"]] | None = None, community: str | None = None, users: list[UsersItem] | None = None, **kwargs, @@ -7287,7 +8551,7 @@ def __init__(self, name: str | None = None, **kwargs): name: str = None """Community name.""" - access: Literal["ro", "rw"] | None = None + access: Annotated[str, ValidValues["ro", "rw"]] | None = None access_list_ipv4: AccessListIpv4 | None = None access_list_ipv6: AccessListIpv6 | None = None view: str | None = None @@ -7295,7 +8559,7 @@ def __init__(self, name: str | None = None, **kwargs): def __init__( self, name: str = None, - access: Literal["ro", "rw"] | None = None, + access: Annotated[str, ValidValues["ro", "rw"]] | None = None, access_list_ipv4: AccessListIpv4 | None = None, access_list_ipv6: AccessListIpv6 | None = None, view: str | None = None, @@ -7321,9 +8585,9 @@ def __init__( class Ipv4AclsItem(AvdDictBaseModel): name: str | None = None """IPv4 access list name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -7338,9 +8602,9 @@ def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int class Ipv6AclsItem(AvdDictBaseModel): name: str | None = None """IPv6 access list name.""" - vrf: Annotated[str, ConvertTypes[int]] | None = None + vrf: str | None = None - def __init__(self, name: str | None = None, vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, name: str | None = None, vrf: str | None = None, **kwargs): """ Args: ----- @@ -7385,8 +8649,8 @@ def __init__( class GroupsItem(AvdDictBaseModel): name: str | None = None """Group name.""" - version: Literal["v1", "v2c", "v3"] | None = None - authentication: Literal["auth", "noauth", "priv"] | None = None + version: Annotated[str, ValidValues["v1", "v2c", "v3"]] | None = None + authentication: Annotated[str, ValidValues["auth", "noauth", "priv"]] | None = None read: str | None = None """Read view.""" write: str | None = None @@ -7397,8 +8661,8 @@ class GroupsItem(AvdDictBaseModel): def __init__( self, name: str | None = None, - version: Literal["v1", "v2c", "v3"] | None = None, - authentication: Literal["auth", "noauth", "priv"] | None = None, + version: Annotated[str, ValidValues["v1", "v2c", "v3"]] | None = None, + authentication: Annotated[str, ValidValues["auth", "noauth", "priv"]] | None = None, read: str | None = None, write: str | None = None, notify: str | None = None, @@ -7423,8 +8687,48 @@ def __init__( self.notify = notify return super().__init__(**kwargs) - class Traps(EosCliConfigGen.SnmpServer.Traps): - pass + class Traps(AvdDictBaseModel): + class SnmpTrapsItem(AvdDictBaseModel): + name: str | None = None + """ + Enable or disable specific snmp-traps and their sub_traps. + Examples: + - "bgp" + - "bgp established" + """ + enabled: bool | None = True + + def __init__(self, name: str | None = None, enabled: bool | None = True, **kwargs): + """ + Args: + ----- + name: + Enable or disable specific snmp-traps and their sub_traps. + Examples: + - "bgp" + - "bgp established" + enabled: enabled + + """ + self.name = name + self.enabled = enabled + return super().__init__(**kwargs) + + enable: bool | None = False + """Enable or disable all snmp-traps.""" + snmp_traps: list[SnmpTrapsItem] | None = None + + def __init__(self, enable: bool | None = False, snmp_traps: list[SnmpTrapsItem] | None = None, **kwargs): + """ + Args: + ----- + enable: Enable or disable all snmp-traps. + snmp_traps: snmp_traps + + """ + self.enable = enable + self.snmp_traps = snmp_traps + return super().__init__(**kwargs) contact: str | None = None """SNMP contact.""" @@ -7452,7 +8756,7 @@ class Traps(EosCliConfigGen.SnmpServer.Traps): """ compute_local_engineid: bool | None = False """Generate a local engineId for SNMP using the 'compute_local_engineid_source' method.""" - compute_local_engineid_source: Literal["hostname_and_ip", "system_mac"] | None = "hostname_and_ip" + compute_local_engineid_source: Annotated[str, ValidValues["hostname_and_ip", "system_mac"]] | None = "hostname_and_ip" """ `compute_local_engineid_source` supports: - `hostname_and_ip` generate a local engineId for SNMP by hashing via SHA1 @@ -7494,7 +8798,7 @@ def __init__( enable_mgmt_interface_vrf: bool | None = None, enable_inband_mgmt_vrf: bool | None = None, compute_local_engineid: bool | None = False, - compute_local_engineid_source: Literal["hostname_and_ip", "system_mac"] | None = "hostname_and_ip", + compute_local_engineid_source: Annotated[str, ValidValues["hostname_and_ip", "system_mac"]] | None = "hostname_and_ip", compute_v3_user_localized_key: bool | None = False, users: list[UsersItem] | None = None, hosts: list[HostsItem] | None = None, @@ -7833,12 +9137,10 @@ class IpHelpersItem(AvdDictBaseModel): """IPv4 DHCP server IP.""" source_interface: str | None = None """Interface name to originate DHCP relay packets to DHCP server.""" - source_vrf: Annotated[str, ConvertTypes[int]] | None = None + source_vrf: str | None = None """VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI.""" - def __init__( - self, ip_helper: str = None, source_interface: str | None = None, source_vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs - ): + def __init__(self, ip_helper: str = None, source_interface: str | None = None, source_vrf: str | None = None, **kwargs): """ Args: ----- @@ -7886,10 +9188,10 @@ class IgmpSnoopingQuerier(AvdDictBaseModel): IPv4_address If not set, IP address of "Loopback0" will be used. """ - version: Literal[1, 2, 3] | None = None + version: int | None = None """IGMP Version (By default EOS uses IGMP version 2 for IGMP querier).""" - def __init__(self, enabled: bool | None = None, source_address: str | None = None, version: Literal[1, 2, 3] | None = None, **kwargs): + def __init__(self, enabled: bool | None = None, source_address: str | None = None, version: int | None = None, **kwargs): """ Args: ----- @@ -7908,14 +9210,14 @@ def __init__(self, enabled: bool | None = None, source_address: str | None = Non class Ospf(AvdDictBaseModel): class MessageDigestKeysItem(AvdDictBaseModel): id: int | None = None - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = "sha512" + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = "sha512" key: str | None = None """Type 7 encrypted key.""" def __init__( self, id: int | None = None, - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = "sha512", + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = "sha512", key: str | None = None, **kwargs, ): @@ -7934,11 +9236,11 @@ def __init__( enabled: bool | None = None point_to_point: bool | None = True - area: Annotated[str, ConvertTypes[int]] | None = "0" + area: str | None = "0" """OSPF area ID.""" cost: int | None = None """OSPF link cost.""" - authentication: Literal["simple", "message-digest"] | None = None + authentication: Annotated[str, ValidValues["simple", "message-digest"]] | None = None simple_auth_key: str | None = None """Password used with simple authentication.""" message_digest_keys: list[MessageDigestKeysItem] | None = None @@ -7947,9 +9249,9 @@ def __init__( self, enabled: bool | None = None, point_to_point: bool | None = True, - area: Annotated[str, ConvertTypes[int]] | None = "0", + area: str | None = "0", cost: int | None = None, - authentication: Literal["simple", "message-digest"] | None = None, + authentication: Annotated[str, ValidValues["simple", "message-digest"]] | None = None, simple_auth_key: str | None = None, message_digest_keys: list[MessageDigestKeysItem] | None = None, **kwargs, @@ -8058,13 +9360,13 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): ipv6_virtual_router_addresses will take precedence _if_ there is an ipv6_address configured for the node. """ - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_in: str | None = None """ Name of the IPv4 access-list to be assigned in the ingress direction. The access-list must be defined under `ipv4_acls` and supports substitution of the field "interface_ip". """ - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_out: str | None = None """ Name of the IPv4 Access-list to be assigned in the egress direction. The access-list must be defined under `ipv4_acls` @@ -8078,7 +9380,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): The vni_override allows us to override this value and statically define it (optional). """ - rt_override: Annotated[str, ConvertTypes[int]] | None = None + rt_override: str | None = None """ By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. The rt_override allows us to override this @@ -8091,7 +9393,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): details). - A full RT string with colon separator which will override the full RT. """ - rd_override: Annotated[str, ConvertTypes[int]] | None = None + rd_override: str | None = None """ By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. The rt_override allows us to override this @@ -8156,12 +9458,12 @@ def __init__( ip_address_virtual_secondaries: list[str] | None = None, ip_virtual_router_addresses: list[str] | None = None, ipv6_virtual_router_addresses: list[str] | None = None, - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None, - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None, + ipv4_acl_in: str | None = None, + ipv4_acl_out: str | None = None, ip_helpers: list[IpHelpersItem] | None = None, vni_override: int | None = None, - rt_override: Annotated[str, ConvertTypes[int]] | None = None, - rd_override: Annotated[str, ConvertTypes[int]] | None = None, + rt_override: str | None = None, + rd_override: str | None = None, trunk_groups: list[str] | None = None, evpn_l2_multicast: EvpnL2Multicast | None = None, evpn_l3_multicast: EvpnL3Multicast | None = None, @@ -8312,12 +9614,10 @@ class IpHelpersItem(AvdDictBaseModel): """IPv4 DHCP server IP.""" source_interface: str | None = None """Interface name to originate DHCP relay packets to DHCP server.""" - source_vrf: Annotated[str, ConvertTypes[int]] | None = None + source_vrf: str | None = None """VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI.""" - def __init__( - self, ip_helper: str = None, source_interface: str | None = None, source_vrf: Annotated[str, ConvertTypes[int]] | None = None, **kwargs - ): + def __init__(self, ip_helper: str = None, source_interface: str | None = None, source_vrf: str | None = None, **kwargs): """ Args: ----- @@ -8365,10 +9665,10 @@ class IgmpSnoopingQuerier(AvdDictBaseModel): IPv4_address If not set, IP address of "Loopback0" will be used. """ - version: Literal[1, 2, 3] | None = None + version: int | None = None """IGMP Version (By default EOS uses IGMP version 2 for IGMP querier).""" - def __init__(self, enabled: bool | None = None, source_address: str | None = None, version: Literal[1, 2, 3] | None = None, **kwargs): + def __init__(self, enabled: bool | None = None, source_address: str | None = None, version: int | None = None, **kwargs): """ Args: ----- @@ -8387,14 +9687,14 @@ def __init__(self, enabled: bool | None = None, source_address: str | None = Non class Ospf(AvdDictBaseModel): class MessageDigestKeysItem(AvdDictBaseModel): id: int | None = None - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = "sha512" + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = "sha512" key: str | None = None """Type 7 encrypted key.""" def __init__( self, id: int | None = None, - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = "sha512", + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = "sha512", key: str | None = None, **kwargs, ): @@ -8413,11 +9713,11 @@ def __init__( enabled: bool | None = None point_to_point: bool | None = True - area: Annotated[str, ConvertTypes[int]] | None = "0" + area: str | None = "0" """OSPF area ID.""" cost: int | None = None """OSPF link cost.""" - authentication: Literal["simple", "message-digest"] | None = None + authentication: Annotated[str, ValidValues["simple", "message-digest"]] | None = None simple_auth_key: str | None = None """Password used with simple authentication.""" message_digest_keys: list[MessageDigestKeysItem] | None = None @@ -8426,9 +9726,9 @@ def __init__( self, enabled: bool | None = None, point_to_point: bool | None = True, - area: Annotated[str, ConvertTypes[int]] | None = "0", + area: str | None = "0", cost: int | None = None, - authentication: Literal["simple", "message-digest"] | None = None, + authentication: Annotated[str, ValidValues["simple", "message-digest"]] | None = None, simple_auth_key: str | None = None, message_digest_keys: list[MessageDigestKeysItem] | None = None, **kwargs, @@ -8549,13 +9849,13 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): ipv6_virtual_router_addresses will take precedence _if_ there is an ipv6_address configured for the node. """ - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_in: str | None = None """ Name of the IPv4 access-list to be assigned in the ingress direction. The access-list must be defined under `ipv4_acls` and supports substitution of the field "interface_ip". """ - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_out: str | None = None """ Name of the IPv4 Access-list to be assigned in the egress direction. The access-list must be defined under `ipv4_acls` @@ -8569,7 +9869,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): The vni_override allows us to override this value and statically define it (optional). """ - rt_override: Annotated[str, ConvertTypes[int]] | None = None + rt_override: str | None = None """ By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. The rt_override allows us to override this @@ -8582,7 +9882,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): details). - A full RT string with colon separator which will override the full RT. """ - rd_override: Annotated[str, ConvertTypes[int]] | None = None + rd_override: str | None = None """ By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. The rt_override allows us to override this @@ -8649,12 +9949,12 @@ def __init__( ip_address_virtual_secondaries: list[str] | None = None, ip_virtual_router_addresses: list[str] | None = None, ipv6_virtual_router_addresses: list[str] | None = None, - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None, - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None, + ipv4_acl_in: str | None = None, + ipv4_acl_out: str | None = None, ip_helpers: list[IpHelpersItem] | None = None, vni_override: int | None = None, - rt_override: Annotated[str, ConvertTypes[int]] | None = None, - rd_override: Annotated[str, ConvertTypes[int]] | None = None, + rt_override: str | None = None, + rd_override: str | None = None, trunk_groups: list[str] | None = None, evpn_l2_multicast: EvpnL2Multicast | None = None, evpn_l3_multicast: EvpnL3Multicast | None = None, @@ -8872,9 +10172,9 @@ def __init__(self, mlag: Mlag | None = None, mlag_l3: MlagL3 | None = None, upli return super().__init__(**kwargs) class UnderlayMulticastAnycastRp(AvdDictBaseModel): - mode: Literal["pim", "msdp"] | None = "pim" + mode: Annotated[str, ValidValues["pim", "msdp"]] | None = "pim" - def __init__(self, mode: Literal["pim", "msdp"] | None = "pim", **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["pim", "msdp"]] | None = "pim", **kwargs): """ Args: ----- @@ -8917,16 +10217,11 @@ def __init__(self, name: str = None, loopback_number: int = None, description: s configured matching these groups. Otherwise the groups are configured directly on the RP command. """ - access_list_name: Annotated[str, ConvertTypes[int]] | None = None + access_list_name: str | None = None """Name of standard Access-List.""" def __init__( - self, - rp: str = None, - nodes: list[NodesItem] | None = None, - groups: list[str] | None = None, - access_list_name: Annotated[str, ConvertTypes[int]] | None = None, - **kwargs, + self, rp: str = None, nodes: list[NodesItem] | None = None, groups: list[str] | None = None, access_list_name: str | None = None, **kwargs ): """ Args: @@ -9145,7 +10440,7 @@ def __init__(self, remote: str | None = None, local: str | None = None, **kwargs return super().__init__(**kwargs) class DpsKeepalive(AvdDictBaseModel): - interval: Annotated[str, ConvertTypes[int]] | None = None + interval: str | None = None """ Interval in milliseconds. Valid values are 50-60000 | "auto". @@ -9156,7 +10451,7 @@ class DpsKeepalive(AvdDictBaseModel): failure_threshold: int | None = 5 """Failure threshold in number of lost keep-alive messages.""" - def __init__(self, interval: Annotated[str, ConvertTypes[int]] | None = None, failure_threshold: int | None = 5, **kwargs): + def __init__(self, interval: str | None = None, failure_threshold: int | None = 5, **kwargs): """ Args: ----- @@ -9186,7 +10481,7 @@ def __init__(self, interval: Annotated[str, ConvertTypes[int]] | None = None, fa """Configuration of IPSec at the path-group level.""" import_path_groups: list[ImportPathGroupsItem] | None = None """List of path-groups to import in this path-group.""" - default_preference: Annotated[str, ConvertTypes[int]] | None = "preferred" + default_preference: str | None = "preferred" """ Preference value used when a preference is not given for a path-group in the `wan_virtual_topologies.policies` input or when @@ -9211,7 +10506,7 @@ def __init__( description: str | None = None, ipsec: Ipsec | None = None, import_path_groups: list[ImportPathGroupsItem] | None = None, - default_preference: Annotated[str, ConvertTypes[int]] | None = "preferred", + default_preference: str | None = "preferred", excluded_from_default_policy: bool | None = False, dps_keepalive: DpsKeepalive | None = None, **kwargs, @@ -9310,7 +10605,7 @@ def __init__(self, hostname: str = None, vtep_ip: str | None = None, path_groups class WanVirtualTopologies(AvdDictBaseModel): class VrfsItem(AvdDictBaseModel): - name: Annotated[str, ConvertTypes[int]] = None + name: str = None """VRF name.""" policy: str | None = "DEFAULT-POLICY" """ @@ -9335,7 +10630,7 @@ class VrfsItem(AvdDictBaseModel): In addition either `vrf_id` or `vrf_vni` must be set to enforce consistent route-targets across domains. """ - def __init__(self, name: Annotated[str, ConvertTypes[int]] = None, policy: str | None = "DEFAULT-POLICY", wan_vni: int = None, **kwargs): + def __init__(self, name: str = None, policy: str | None = "DEFAULT-POLICY", wan_vni: int = None, **kwargs): """ Args: ----- @@ -9371,7 +10666,7 @@ class Constraints(AvdDictBaseModel): """Jitter requirement for this load balance policy in milliseconds.""" latency: int | None = None """One way delay requirement for this load balance policy in milliseconds.""" - loss_rate: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None + loss_rate: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None """ Loss Rate requirement in percentage for this load balance policy. Value between 0.00 and 100.00. @@ -9381,7 +10676,7 @@ def __init__( self, jitter: int | None = None, latency: int | None = None, - loss_rate: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None, + loss_rate: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None, **kwargs, ): """ @@ -9402,7 +10697,7 @@ def __init__( class PathGroupsItem(AvdDictBaseModel): names: list[str] = None """List of path-group names.""" - preference: Annotated[str, ConvertTypes[int]] | None = None + preference: str | None = None """ Valid values are 1-65535 | "preferred" | "alternate". @@ -9413,7 +10708,7 @@ class PathGroupsItem(AvdDictBaseModel): If not set, each path-group in `names` will be attributed its `default_preference`. """ - def __init__(self, names: list[str] = None, preference: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, names: list[str] = None, preference: str | None = None, **kwargs): """ Args: ----- @@ -9537,7 +10832,7 @@ class Constraints(AvdDictBaseModel): """Jitter requirement for this load balance policy in milliseconds.""" latency: int | None = None """One way delay requirement for this load balance policy in milliseconds.""" - loss_rate: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None + loss_rate: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None """ Loss Rate requirement in percentage for this load balance policy. Value between 0.00 and 100.00. @@ -9547,7 +10842,7 @@ def __init__( self, jitter: int | None = None, latency: int | None = None, - loss_rate: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None, + loss_rate: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None, **kwargs, ): """ @@ -9568,7 +10863,7 @@ def __init__( class PathGroupsItem(AvdDictBaseModel): names: list[str] = None """List of path-group names.""" - preference: Annotated[str, ConvertTypes[int]] | None = None + preference: str | None = None """ Valid values are 1-65535 | "preferred" | "alternate". @@ -9579,7 +10874,7 @@ class PathGroupsItem(AvdDictBaseModel): If not set, each path-group in `names` will be attributed its `default_preference`. """ - def __init__(self, names: list[str] = None, preference: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, names: list[str] = None, preference: str | None = None, **kwargs): """ Args: ----- @@ -9708,7 +11003,7 @@ class Constraints(AvdDictBaseModel): """Jitter requirement for this load balance policy in milliseconds.""" latency: int | None = None """One way delay requirement for this load balance policy in milliseconds.""" - loss_rate: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None + loss_rate: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None """ Loss Rate requirement in percentage for this load balance policy. Value between 0.00 and 100.00. @@ -9718,7 +11013,7 @@ def __init__( self, jitter: int | None = None, latency: int | None = None, - loss_rate: Annotated[str, ConvertTypes[int, float], Pattern["^\d+(\.\d{1,2})?$"]] | None = None, + loss_rate: Annotated[str, Pattern[r"^\d+(\.\d{1,2})?$"]] | None = None, **kwargs, ): """ @@ -9739,7 +11034,7 @@ def __init__( class PathGroupsItem(AvdDictBaseModel): names: list[str] = None """List of path-group names.""" - preference: Annotated[str, ConvertTypes[int]] | None = None + preference: str | None = None """ Valid values are 1-65535 | "preferred" | "alternate". @@ -9750,7 +11045,7 @@ class PathGroupsItem(AvdDictBaseModel): If not set, each path-group in `names` will be attributed its `default_preference`. """ - def __init__(self, names: list[str] = None, preference: Annotated[str, ConvertTypes[int]] | None = None, **kwargs): + def __init__(self, names: list[str] = None, preference: str | None = None, **kwargs): """ Args: ----- @@ -10001,8 +11296,8 @@ class Primary(AvdDictBaseModel): datacenter: str = None city: str = None country: str = None - latitude: Annotated[str, ConvertTypes[int, float]] = None - longitude: Annotated[str, ConvertTypes[int, float]] = None + latitude: str = None + longitude: str = None def __init__( self, @@ -10010,8 +11305,8 @@ def __init__( datacenter: str = None, city: str = None, country: str = None, - latitude: Annotated[str, ConvertTypes[int, float]] = None, - longitude: Annotated[str, ConvertTypes[int, float]] = None, + latitude: str = None, + longitude: str = None, **kwargs, ): """ @@ -10038,8 +11333,8 @@ class Secondary(AvdDictBaseModel): datacenter: str = None city: str = None country: str = None - latitude: Annotated[str, ConvertTypes[int, float]] = None - longitude: Annotated[str, ConvertTypes[int, float]] = None + latitude: str = None + longitude: str = None def __init__( self, @@ -10047,8 +11342,8 @@ def __init__( datacenter: str = None, city: str = None, country: str = None, - latitude: Annotated[str, ConvertTypes[int, float]] = None, - longitude: Annotated[str, ConvertTypes[int, float]] = None, + latitude: str = None, + longitude: str = None, **kwargs, ): """ @@ -10075,8 +11370,8 @@ class Tertiary(AvdDictBaseModel): datacenter: str = None city: str = None country: str = None - latitude: Annotated[str, ConvertTypes[int, float]] = None - longitude: Annotated[str, ConvertTypes[int, float]] = None + latitude: str = None + longitude: str = None def __init__( self, @@ -10084,8 +11379,8 @@ def __init__( datacenter: str = None, city: str = None, country: str = None, - latitude: Annotated[str, ConvertTypes[int, float]] = None, - longitude: Annotated[str, ConvertTypes[int, float]] = None, + latitude: str = None, + longitude: str = None, **kwargs, ): """ @@ -10189,9 +11484,9 @@ class DynamicConnectedEndpointsKeys(object): class ConnectedEndpointsKeysKeyItem(AvdDictBaseModel): class AdaptersItem(AvdDictBaseModel): class Flowcontrol(AvdDictBaseModel): - received: Literal["received", "send", "on"] | None = None + received: Annotated[str, ValidValues["received", "send", "on"]] | None = None - def __init__(self, received: Literal["received", "send", "on"] | None = None, **kwargs): + def __init__(self, received: Annotated[str, ValidValues["received", "send", "on"]] | None = None, **kwargs): """ Args: ----- @@ -10203,14 +11498,14 @@ def __init__(self, received: Literal["received", "send", "on"] | None = None, ** class Ptp(AvdDictBaseModel): enabled: bool | None = False - endpoint_role: Literal["bmca", "default", "follower"] | None = "follower" - profile: Literal["aes67", "aes67-r16-2016", "smpte2059-2"] | None = "aes67-r16-2016" + endpoint_role: Annotated[str, ValidValues["bmca", "default", "follower"]] | None = "follower" + profile: Annotated[str, ValidValues["aes67", "aes67-r16-2016", "smpte2059-2"]] | None = "aes67-r16-2016" def __init__( self, enabled: bool | None = False, - endpoint_role: Literal["bmca", "default", "follower"] | None = "follower", - profile: Literal["aes67", "aes67-r16-2016", "smpte2059-2"] | None = "aes67-r16-2016", + endpoint_role: Annotated[str, ValidValues["bmca", "default", "follower"]] | None = "follower", + profile: Annotated[str, ValidValues["aes67", "aes67-r16-2016", "smpte2059-2"]] | None = "aes67-r16-2016", **kwargs, ): """ @@ -10271,9 +11566,9 @@ def __init__(self, enabled: bool | None = None, name: str | None = None, **kwarg class Dot1x(AvdDictBaseModel): class Pae(AvdDictBaseModel): - mode: Literal["authenticator"] | None = None + mode: Annotated[str, ValidValues["authenticator"]] | None = None - def __init__(self, mode: Literal["authenticator"] | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["authenticator"]] | None = None, **kwargs): """ Args: ----- @@ -10284,10 +11579,10 @@ def __init__(self, mode: Literal["authenticator"] | None = None, **kwargs): return super().__init__(**kwargs) class AuthenticationFailure(AvdDictBaseModel): - action: Literal["allow", "drop"] | None = None + action: Annotated[str, ValidValues["allow", "drop"]] | None = None allow_vlan: int | None = None - def __init__(self, action: Literal["allow", "drop"] | None = None, allow_vlan: int | None = None, **kwargs): + def __init__(self, action: Annotated[str, ValidValues["allow", "drop"]] | None = None, allow_vlan: int | None = None, **kwargs): """ Args: ----- @@ -10300,11 +11595,14 @@ def __init__(self, action: Literal["allow", "drop"] | None = None, allow_vlan: i return super().__init__(**kwargs) class HostMode(AvdDictBaseModel): - mode: Literal["multi-host", "single-host"] | None = None + mode: Annotated[str, ValidValues["multi-host", "single-host"]] | None = None multi_host_authenticated: bool | None = None def __init__( - self, mode: Literal["multi-host", "single-host"] | None = None, multi_host_authenticated: bool | None = None, **kwargs + self, + mode: Annotated[str, ValidValues["multi-host", "single-host"]] | None = None, + multi_host_authenticated: bool | None = None, + **kwargs, ): """ Args: @@ -10339,7 +11637,7 @@ def __init__(self, enabled: bool | None = None, always: bool | None = None, host class Timeout(AvdDictBaseModel): idle_host: int | None = None quiet_period: int | None = None - reauth_period: Annotated[str, ConvertTypes[int]] | None = None + reauth_period: str | None = None """Range 60-4294967295 or "server".""" reauth_timeout_ignore: bool | None = None tx_period: int | None = None @@ -10348,7 +11646,7 @@ def __init__( self, idle_host: int | None = None, quiet_period: int | None = None, - reauth_period: Annotated[str, ConvertTypes[int]] | None = None, + reauth_period: str | None = None, reauth_timeout_ignore: bool | None = None, tx_period: int | None = None, **kwargs, @@ -10386,7 +11684,7 @@ def __init__(self, access_vlan_membership_egress: bool | None = None, native_vla self.native_vlan_membership_egress = native_vlan_membership_egress return super().__init__(**kwargs) - port_control: Literal["auto", "force-authorized", "force-unauthorized"] | None = None + port_control: Annotated[str, ValidValues["auto", "force-authorized", "force-unauthorized"]] | None = None port_control_force_authorized_phone: bool | None = None reauthentication: bool | None = None pae: Pae | None = None @@ -10399,7 +11697,7 @@ def __init__(self, access_vlan_membership_egress: bool | None = None, native_vla def __init__( self, - port_control: Literal["auto", "force-authorized", "force-unauthorized"] | None = None, + port_control: Annotated[str, ValidValues["auto", "force-authorized", "force-unauthorized"]] | None = None, port_control_force_authorized_phone: bool | None = None, reauthentication: bool | None = None, pae: Pae | None = None, @@ -10438,22 +11736,145 @@ def __init__( self.unauthorized = unauthorized return super().__init__(**kwargs) - class Poe(EosCliConfigGen.EthernetInterfacesItem.Poe): - pass + class Poe(AvdDictBaseModel): + class Reboot(AvdDictBaseModel): + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None + """PoE action for interface.""" + + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, **kwargs): + """ + Args: + ----- + action: PoE action for interface. + + """ + self.action = action + return super().__init__(**kwargs) + + class LinkDown(AvdDictBaseModel): + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None + """PoE action for interface.""" + power_off_delay: int | None = None + """Number of seconds to delay shutting the power off after a link down event occurs. Default value is 5 seconds in EOS.""" + + def __init__( + self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, power_off_delay: int | None = None, **kwargs + ): + """ + Args: + ----- + action: PoE action for interface. + power_off_delay: Number of seconds to delay shutting the power off after a link down event occurs. Default value is 5 seconds in EOS. + + """ + self.action = action + self.power_off_delay = power_off_delay + return super().__init__(**kwargs) + + class Shutdown(AvdDictBaseModel): + action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None + """PoE action for interface.""" + + def __init__(self, action: Annotated[str, ValidValues["maintain", "power-off"]] | None = None, **kwargs): + """ + Args: + ----- + action: PoE action for interface. + + """ + self.action = action + return super().__init__(**kwargs) + + class Limit(AvdDictBaseModel): + field_class: int | None = None + watts: str | None = None + fixed: bool | None = None + """Set to ignore hardware classification.""" + + def __init__(self, field_class: int | None = None, watts: str | None = None, fixed: bool | None = None, **kwargs): + """ + Args: + ----- + field_class: field_class + watts: watts + fixed: Set to ignore hardware classification. + + """ + self.field_class = field_class + self.watts = watts + self.fixed = fixed + return super().__init__(**kwargs) + + disabled: bool | None = False + """Disable PoE on a POE capable port. PoE is enabled on all ports that support it by default in EOS.""" + priority: Annotated[str, ValidValues["critical", "high", "medium", "low"]] | None = None + """Prioritize a port's power in the event that one of the switch's power supplies loses power.""" + reboot: Reboot | None = None + """Set the PoE power behavior for a PoE port when the system is rebooted.""" + link_down: LinkDown | None = None + """Set the PoE power behavior for a PoE port when the port goes down.""" + shutdown: Shutdown | None = None + """Set the PoE power behavior for a PoE port when the port is admin down.""" + limit: Limit | None = None + """ + Override the hardware-negotiated power limit using either wattage or a power class. Note that if using a power class, + AVD will automatically convert the class value to the wattage value corresponding to that power class. + """ + negotiation_lldp: bool | None = None + """Disable to prevent port from negotiating power with powered devices over LLDP. Enabled by default in EOS.""" + legacy_detect: bool | None = None + """ + Allow a subset of legacy devices to work with the PoE switch. Disabled by default in EOS because it can cause false + positive detections. + """ + + def __init__( + self, + disabled: bool | None = False, + priority: Annotated[str, ValidValues["critical", "high", "medium", "low"]] | None = None, + reboot: Reboot | None = None, + link_down: LinkDown | None = None, + shutdown: Shutdown | None = None, + limit: Limit | None = None, + negotiation_lldp: bool | None = None, + legacy_detect: bool | None = None, + **kwargs, + ): + """ + Args: + ----- + disabled: Disable PoE on a POE capable port. PoE is enabled on all ports that support it by default in EOS. + priority: Prioritize a port's power in the event that one of the switch's power supplies loses power. + reboot: Set the PoE power behavior for a PoE port when the system is rebooted. + link_down: Set the PoE power behavior for a PoE port when the port goes down. + shutdown: Set the PoE power behavior for a PoE port when the port is admin down. + limit: + Override the hardware-negotiated power limit using either wattage or a power class. Note that if using a power class, + AVD will automatically convert the class value to the wattage value corresponding to that power class. + negotiation_lldp: Disable to prevent port from negotiating power with powered devices over LLDP. Enabled by default in EOS. + legacy_detect: + Allow a subset of legacy devices to work with the PoE switch. Disabled by default in EOS because it can cause false + positive detections. + + """ + self.disabled = disabled + self.priority = priority + self.reboot = reboot + self.link_down = link_down + self.shutdown = shutdown + self.limit = limit + self.negotiation_lldp = negotiation_lldp + self.legacy_detect = legacy_detect + return super().__init__(**kwargs) class StormControl(AvdDictBaseModel): class All(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__( - self, - level: Annotated[str, ConvertTypes[int, float]] | None = None, - unit: Literal["percent", "pps"] | None = "percent", - **kwargs, - ): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -10466,17 +11887,12 @@ def __init__( return super().__init__(**kwargs) class Broadcast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__( - self, - level: Annotated[str, ConvertTypes[int, float]] | None = None, - unit: Literal["percent", "pps"] | None = "percent", - **kwargs, - ): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -10489,17 +11905,12 @@ def __init__( return super().__init__(**kwargs) class Multicast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__( - self, - level: Annotated[str, ConvertTypes[int, float]] | None = None, - unit: Literal["percent", "pps"] | None = "percent", - **kwargs, - ): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -10512,17 +11923,12 @@ def __init__( return super().__init__(**kwargs) class UnknownUnicast(AvdDictBaseModel): - level: Annotated[str, ConvertTypes[int, float]] | None = None + level: str | None = None """Configure maximum storm-control level.""" - unit: Literal["percent", "pps"] | None = "percent" + unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent" """Optional variable and is hardware dependent.""" - def __init__( - self, - level: Annotated[str, ConvertTypes[int, float]] | None = None, - unit: Literal["percent", "pps"] | None = "percent", - **kwargs, - ): + def __init__(self, level: str | None = None, unit: Annotated[str, ValidValues["percent", "pps"]] | None = "percent", **kwargs): """ Args: ----- @@ -10565,13 +11971,17 @@ def __init__( class MonitorSessionsItem(AvdDictBaseModel): class SourceSettings(AvdDictBaseModel): class AccessGroup(AvdDictBaseModel): - type: Literal["ip", "ipv6", "mac"] | None = None + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None name: str | None = None """ACL name.""" priority: int | None = None def __init__( - self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | None = None, priority: int | None = None, **kwargs + self, + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None, + name: str | None = None, + priority: int | None = None, + **kwargs, ): """ Args: @@ -10586,10 +11996,15 @@ def __init__( self.priority = priority return super().__init__(**kwargs) - direction: Literal["rx", "tx", "both"] | None = None + direction: Annotated[str, ValidValues["rx", "tx", "both"]] | None = None access_group: AccessGroup | None = None - def __init__(self, direction: Literal["rx", "tx", "both"] | None = None, access_group: AccessGroup | None = None, **kwargs): + def __init__( + self, + direction: Annotated[str, ValidValues["rx", "tx", "both"]] | None = None, + access_group: AccessGroup | None = None, + **kwargs, + ): """ Args: ----- @@ -10603,11 +12018,11 @@ def __init__(self, direction: Literal["rx", "tx", "both"] | None = None, access_ class SessionSettings(AvdDictBaseModel): class AccessGroup(AvdDictBaseModel): - type: Literal["ip", "ipv6", "mac"] | None = None + type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None name: str | None = None """ACL name.""" - def __init__(self, type: Literal["ip", "ipv6", "mac"] | None = None, name: str | None = None, **kwargs): + def __init__(self, type: Annotated[str, ValidValues["ip", "ipv6", "mac"]] | None = None, name: str | None = None, **kwargs): """ Args: ----- @@ -10703,7 +12118,7 @@ def __init__( name: str = None """Session name.""" - role: Literal["source", "destination"] | None = None + role: Annotated[str, ValidValues["source", "destination"]] | None = None source_settings: SourceSettings | None = None session_settings: SessionSettings | None = None """ @@ -10715,7 +12130,7 @@ def __init__( def __init__( self, name: str = None, - role: Literal["source", "destination"] | None = None, + role: Annotated[str, ValidValues["source", "destination"]] | None = None, source_settings: SourceSettings | None = None, session_settings: SessionSettings | None = None, **kwargs, @@ -10747,13 +12162,13 @@ class EthernetSegment(AvdDictBaseModel): Please see the notes under "EVPN A/A ESI dual and single-attached endpoint scenarios" before setting `short_esi: auto`. """ - redundancy: Literal["all-active", "single-active"] | None = None + redundancy: Annotated[str, ValidValues["all-active", "single-active"]] | None = None """ If omitted, Port-Channels use the EOS default of all-active. If omitted, Ethernet interfaces are configured as single- active. """ - designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None = None + designated_forwarder_algorithm: Annotated[str, ValidValues["auto", "modulus", "preference"]] | None = None """ Configure DF algorithm and preferences. - auto: Use preference-based algorithm and assign preference based on position @@ -10775,8 +12190,8 @@ class EthernetSegment(AvdDictBaseModel): def __init__( self, short_esi: str = None, - redundancy: Literal["all-active", "single-active"] | None = None, - designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None = None, + redundancy: Annotated[str, ValidValues["all-active", "single-active"]] | None = None, + designated_forwarder_algorithm: Annotated[str, ValidValues["auto", "modulus", "preference"]] | None = None, designated_forwarder_preferences: list[int] | None = None, dont_preempt: bool | None = None, **kwargs, @@ -10833,7 +12248,7 @@ def __init__(self, profile: str | None = None, **kwargs): self.profile = profile return super().__init__(**kwargs) - mode: Literal["static", "individual"] | None = None + mode: Annotated[str, ValidValues["static", "individual"]] | None = None """ Either static or individual mode is supported. If the mode is set to "individual" the "individual.profile" setting must @@ -10846,7 +12261,7 @@ def __init__(self, profile: str | None = None, **kwargs): def __init__( self, - mode: Literal["static", "individual"] | None = None, + mode: Annotated[str, ValidValues["static", "individual"]] | None = None, individual: Individual | None = None, timeout: int | None = None, **kwargs, @@ -10868,12 +12283,12 @@ def __init__( return super().__init__(**kwargs) class LacpTimer(AvdDictBaseModel): - mode: Literal["normal", "fast"] | None = None + mode: Annotated[str, ValidValues["normal", "fast"]] | None = None """LACP mode for interface members.""" multiplier: int | None = None """Number of LACP BPDUs lost before deeming the peer down. EOS default is 3.""" - def __init__(self, mode: Literal["normal", "fast"] | None = None, multiplier: int | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["normal", "fast"]] | None = None, multiplier: int | None = None, **kwargs): """ Args: ----- @@ -10949,7 +12364,7 @@ def __init__( class StructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): pass - mode: Literal["active", "passive", "on"] | None = None + mode: Annotated[str, ValidValues["active", "passive", "on"]] | None = None """Port-Channel Mode.""" channel_id: int | None = None """ @@ -10998,7 +12413,7 @@ class StructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): def __init__( self, - mode: Literal["active", "passive", "on"] | None = None, + mode: Annotated[str, ValidValues["active", "passive", "on"]] | None = None, channel_id: int | None = None, description: str | None = None, enabled: bool | None = True, @@ -11098,7 +12513,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): """Port-profile name to inherit configuration.""" enabled: bool | None = True """Administrative state, setting to false will set the port to 'shutdown' in the intended configuration.""" - mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None = None + mode: Annotated[str, ValidValues["access", "dot1q-tunnel", "trunk", "trunk phone"]] | None = None """Interface mode.""" mtu: int | None = None l2_mtu: int | None = None @@ -11117,7 +12532,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Phone VLAN for a mode `trunk phone` port. Requires `mode: trunk phone` to be set. """ - phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None = None + phone_trunk_mode: Annotated[str, ValidValues["tagged", "untagged", "tagged phone", "untagged phone"]] | None = None """ Specify if the phone traffic is tagged or untagged. If both data and phone traffic are untagged, MAC-Based VLAN @@ -11129,14 +12544,14 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Trunk Groups are used for limiting VLANs on trunk ports to VLANs with the same Trunk Group. """ - vlans: Annotated[str, ConvertTypes[int]] | None = None + vlans: str | None = None """ Interface VLANs - if not set, the EOS default is that all VLANs are allowed for trunk ports, and VLAN 1 will be used for access ports. """ - spanning_tree_portfast: Literal["edge", "network"] | None = None - spanning_tree_bpdufilter: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None - spanning_tree_bpduguard: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None + spanning_tree_portfast: Annotated[str, ValidValues["edge", "network"]] | None = None + spanning_tree_bpdufilter: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None + spanning_tree_bpduguard: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None flowcontrol: Flowcontrol | None = None qos_profile: str | None = None """QOS profile name.""" @@ -11187,19 +12602,19 @@ def __init__( description: str | None = None, profile: str | None = None, enabled: bool | None = True, - mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None = None, + mode: Annotated[str, ValidValues["access", "dot1q-tunnel", "trunk", "trunk phone"]] | None = None, mtu: int | None = None, l2_mtu: int | None = None, l2_mru: int | None = None, native_vlan: int | None = None, native_vlan_tag: bool | None = False, phone_vlan: int | None = None, - phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None = None, + phone_trunk_mode: Annotated[str, ValidValues["tagged", "untagged", "tagged phone", "untagged phone"]] | None = None, trunk_groups: list[str] | None = None, - vlans: Annotated[str, ConvertTypes[int]] | None = None, - spanning_tree_portfast: Literal["edge", "network"] | None = None, - spanning_tree_bpdufilter: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None, - spanning_tree_bpduguard: Annotated[Literal["enabled", "disabled", "True", "False", "true", "false"], ConvertTypes[bool]] | None = None, + vlans: str | None = None, + spanning_tree_portfast: Annotated[str, ValidValues["edge", "network"]] | None = None, + spanning_tree_bpdufilter: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None, + spanning_tree_bpduguard: Annotated[str, ValidValues["enabled", "disabled", "True", "False", "true", "false"]] | None = None, flowcontrol: Flowcontrol | None = None, qos_profile: str | None = None, ptp: Ptp | None = None, @@ -11371,13 +12786,58 @@ def __init__(self, key: str, value: list[ConnectedEndpointsKeysKeyItem] | None = class DynamicNetworkServicesKeys(object): class NetworkServicesKeysNameItem(AvdDictBaseModel): - class BgpPeerGroupsItem(EosCliConfigGen.RouterBgp.PeerGroupsItem): + class BgpPeerGroupsItem(AvdDictBaseModel): class AddressFamilyIpv4(AvdDictBaseModel): - class DefaultOriginate(EosCliConfigGen.RouterBgp.AddressFamilyIpv4.PeerGroupsItem.DefaultOriginate): - pass + class DefaultOriginate(AvdDictBaseModel): + always: bool | None = None + route_map: str | None = None + """Route-map name.""" - class NextHop(EosCliConfigGen.RouterBgp.AddressFamilyIpv4.PeerGroupsItem.NextHop): - pass + def __init__(self, always: bool | None = None, route_map: str | None = None, **kwargs): + """ + Args: + ----- + always: always + route_map: Route-map name. + + """ + self.always = always + self.route_map = route_map + return super().__init__(**kwargs) + + class NextHop(AvdDictBaseModel): + class AddressFamilyIpv6(AvdDictBaseModel): + enabled: bool = None + originate: bool | None = None + + def __init__(self, enabled: bool = None, originate: bool | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + originate: originate + + """ + self.enabled = enabled + self.originate = originate + return super().__init__(**kwargs) + + address_family_ipv6: AddressFamilyIpv6 | None = None + address_family_ipv6_originate: bool | None = None + + def __init__( + self, address_family_ipv6: AddressFamilyIpv6 | None = None, address_family_ipv6_originate: bool | None = None, **kwargs + ): + """ + Args: + ----- + address_family_ipv6: address_family_ipv6 + address_family_ipv6_originate: address_family_ipv6_originate + + """ + self.address_family_ipv6 = address_family_ipv6 + self.address_family_ipv6_originate = address_family_ipv6_originate + return super().__init__(**kwargs) activate: bool | None = None route_map_in: str | None = None @@ -11460,6 +12920,257 @@ def __init__( self.prefix_list_out = prefix_list_out return super().__init__(**kwargs) + class AsPath(AvdDictBaseModel): + remote_as_replace_out: bool | None = None + """Replace AS number with local AS number.""" + prepend_own_disabled: bool | None = None + """Disable prepending own AS number to AS path.""" + + def __init__(self, remote_as_replace_out: bool | None = None, prepend_own_disabled: bool | None = None, **kwargs): + """ + Args: + ----- + remote_as_replace_out: Replace AS number with local AS number. + prepend_own_disabled: Disable prepending own AS number to AS path. + + """ + self.remote_as_replace_out = remote_as_replace_out + self.prepend_own_disabled = prepend_own_disabled + return super().__init__(**kwargs) + + class RemovePrivateAs(AvdDictBaseModel): + enabled: bool | None = None + all: bool | None = None + replace_as: bool | None = None + + def __init__(self, enabled: bool | None = None, all: bool | None = None, replace_as: bool | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + all: all + replace_as: replace_as + + """ + self.enabled = enabled + self.all = all + self.replace_as = replace_as + return super().__init__(**kwargs) + + class RemovePrivateAsIngress(AvdDictBaseModel): + enabled: bool | None = None + replace_as: bool | None = None + + def __init__(self, enabled: bool | None = None, replace_as: bool | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + replace_as: replace_as + + """ + self.enabled = enabled + self.replace_as = replace_as + return super().__init__(**kwargs) + + class BfdTimers(AvdDictBaseModel): + interval: int = None + """Interval in milliseconds.""" + min_rx: int = None + """Rate in milliseconds.""" + multiplier: int = None + + def __init__(self, interval: int = None, min_rx: int = None, multiplier: int = None, **kwargs): + """ + Args: + ----- + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + + """ + self.interval = interval + self.min_rx = min_rx + self.multiplier = multiplier + return super().__init__(**kwargs) + + class DefaultOriginate(AvdDictBaseModel): + enabled: bool | None = None + always: bool | None = None + route_map: str | None = None + """Route-map name.""" + + def __init__(self, enabled: bool | None = None, always: bool | None = None, route_map: str | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + always: always + route_map: Route-map name. + + """ + self.enabled = enabled + self.always = always + self.route_map = route_map + return super().__init__(**kwargs) + + class MissingPolicy(AvdDictBaseModel): + class DirectionIn(AvdDictBaseModel): + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None + """Missing policy action.""" + include_community_list: bool | None = None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None = None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None = None + """Include sub-route-map references in missing policy decision.""" + + def __init__( + self, + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None, + include_community_list: bool | None = None, + include_prefix_list: bool | None = None, + include_sub_route_map: bool | None = None, + **kwargs, + ): + """ + Args: + ----- + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + + """ + self.action = action + self.include_community_list = include_community_list + self.include_prefix_list = include_prefix_list + self.include_sub_route_map = include_sub_route_map + return super().__init__(**kwargs) + + class DirectionOut(AvdDictBaseModel): + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None + """Missing policy action.""" + include_community_list: bool | None = None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None = None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None = None + """Include sub-route-map references in missing policy decision.""" + + def __init__( + self, + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None, + include_community_list: bool | None = None, + include_prefix_list: bool | None = None, + include_sub_route_map: bool | None = None, + **kwargs, + ): + """ + Args: + ----- + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + + """ + self.action = action + self.include_community_list = include_community_list + self.include_prefix_list = include_prefix_list + self.include_sub_route_map = include_sub_route_map + return super().__init__(**kwargs) + + direction_in: DirectionIn | None = None + """Missing policy inbound direction.""" + direction_out: DirectionOut | None = None + """Missing policy outbound direction.""" + + def __init__(self, direction_in: DirectionIn | None = None, direction_out: DirectionOut | None = None, **kwargs): + """ + Args: + ----- + direction_in: Missing policy inbound direction. + direction_out: Missing policy outbound direction. + + """ + self.direction_in = direction_in + self.direction_out = direction_out + return super().__init__(**kwargs) + + class LinkBandwidth(AvdDictBaseModel): + enabled: bool | None = None + default: str | None = None + """nn.nn(K|M|G) link speed in bits/second.""" + + def __init__(self, enabled: bool | None = None, default: str | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + default: nn.nn(K|M|G) link speed in bits/second. + + """ + self.enabled = enabled + self.default = default + return super().__init__(**kwargs) + + class AllowasIn(AvdDictBaseModel): + enabled: bool | None = None + times: int | None = None + """Number of local ASNs allowed in a BGP update.""" + + def __init__(self, enabled: bool | None = None, times: int | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + times: Number of local ASNs allowed in a BGP update. + + """ + self.enabled = enabled + self.times = times + return super().__init__(**kwargs) + + class RibInPrePolicyRetain(AvdDictBaseModel): + enabled: bool | None = None + all: bool | None = None + + def __init__(self, enabled: bool | None = None, all: bool | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + all: all + + """ + self.enabled = enabled + self.all = all + return super().__init__(**kwargs) + + class SharedSecret(AvdDictBaseModel): + profile: str = None + """Name of profile defined under `management_security`.""" + hash_algorithm: Annotated[str, ValidValues["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"]] = None + """Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above.""" + + def __init__( + self, + profile: str = None, + hash_algorithm: Annotated[str, ValidValues["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"]] = None, + **kwargs, + ): + """ + Args: + ----- + profile: Name of profile defined under `management_security`. + hash_algorithm: Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above. + + """ + self.profile = profile + self.hash_algorithm = hash_algorithm + return super().__init__(**kwargs) + name: str = None """BGP peer group name.""" nodes: list[str] | None = None @@ -11470,6 +13181,82 @@ def __init__( """ address_family_ipv4: AddressFamilyIpv4 | None = None address_family_ipv6: AddressFamilyIpv6 | None = None + type: str | None = None + """Key only used for documentation or validation purposes.""" + remote_as: str | None = None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value + must be put in quotes, to prevent it from being interpreted as a float number. + """ + local_as: str | None = None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value + must be put in quotes, to prevent it from being interpreted as a float number. + """ + description: str | None = None + shutdown: bool | None = None + as_path: AsPath | None = None + """BGP AS-PATH options.""" + remove_private_as: RemovePrivateAs | None = None + """Remove private AS numbers in outbound AS path.""" + remove_private_as_ingress: RemovePrivateAsIngress | None = None + peer_filter: str | None = None + """ + Peer-filter name. + note: `bgp_listen_range_prefix` and `peer_filter` should not be mixed with + the new `listen_ranges` key + above to avoid conflicts. + """ + next_hop_unchanged: bool | None = None + update_source: str | None = None + """IP address or interface name.""" + route_reflector_client: bool | None = None + bfd: bool | None = None + """Enable BFD.""" + bfd_timers: BfdTimers | None = None + """Override default BFD timers. BFD must be enabled with `bfd: true`.""" + ebgp_multihop: int | None = None + """Time-to-live in range of hops.""" + next_hop_self: bool | None = None + password: str | None = None + passive: bool | None = None + default_originate: DefaultOriginate | None = None + send_community: str | None = None + """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" + maximum_routes: int | None = None + """Maximum number of routes (0 means unlimited).""" + maximum_routes_warning_limit: str | None = None + """ + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of maximum number of routes + at which to warn ("<1-100> percent"). + """ + maximum_routes_warning_only: bool | None = None + missing_policy: MissingPolicy | None = None + """Missing policy configuration for all address-families.""" + link_bandwidth: LinkBandwidth | None = None + allowas_in: AllowasIn | None = None + weight: int | None = None + timers: str | None = None + """BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>".""" + rib_in_pre_policy_retain: RibInPrePolicyRetain | None = None + route_map_in: str | None = None + """Inbound route-map name.""" + route_map_out: str | None = None + """Outbound route-map name.""" + bgp_listen_range_prefix: str | None = None + """ + IP prefix range. + note: `bgp_listen_range_prefix` and `peer_filter` should not be mixed with + the new `listen_ranges` key + above to avoid conflicts. + """ + session_tracker: str | None = None + shared_secret: SharedSecret | None = None + ttl_maximum_hops: int | None = None + """Maximum number of hops.""" def __init__( self, @@ -11477,6 +13264,41 @@ def __init__( nodes: list[str] | None = None, address_family_ipv4: AddressFamilyIpv4 | None = None, address_family_ipv6: AddressFamilyIpv6 | None = None, + type: str | None = None, + remote_as: str | None = None, + local_as: str | None = None, + description: str | None = None, + shutdown: bool | None = None, + as_path: AsPath | None = None, + remove_private_as: RemovePrivateAs | None = None, + remove_private_as_ingress: RemovePrivateAsIngress | None = None, + peer_filter: str | None = None, + next_hop_unchanged: bool | None = None, + update_source: str | None = None, + route_reflector_client: bool | None = None, + bfd: bool | None = None, + bfd_timers: BfdTimers | None = None, + ebgp_multihop: int | None = None, + next_hop_self: bool | None = None, + password: str | None = None, + passive: bool | None = None, + default_originate: DefaultOriginate | None = None, + send_community: str | None = None, + maximum_routes: int | None = None, + maximum_routes_warning_limit: str | None = None, + maximum_routes_warning_only: bool | None = None, + missing_policy: MissingPolicy | None = None, + link_bandwidth: LinkBandwidth | None = None, + allowas_in: AllowasIn | None = None, + weight: int | None = None, + timers: str | None = None, + rib_in_pre_policy_retain: RibInPrePolicyRetain | None = None, + route_map_in: str | None = None, + route_map_out: str | None = None, + bgp_listen_range_prefix: str | None = None, + session_tracker: str | None = None, + shared_secret: SharedSecret | None = None, + ttl_maximum_hops: int | None = None, **kwargs, ): """ @@ -11489,12 +13311,99 @@ def __init__( is created on devices which have a bgp_peer mapped to the corresponding peer_group. address_family_ipv4: address_family_ipv4 address_family_ipv6: address_family_ipv6 + type: Key only used for documentation or validation purposes. + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value + must be put in quotes, to prevent it from being interpreted as a float number. + local_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value + must be put in quotes, to prevent it from being interpreted as a float number. + description: description + shutdown: shutdown + as_path: BGP AS-PATH options. + remove_private_as: Remove private AS numbers in outbound AS path. + remove_private_as_ingress: remove_private_as_ingress + peer_filter: + Peer-filter name. + note: `bgp_listen_range_prefix` and `peer_filter` should not be mixed with + the new `listen_ranges` key + above to avoid conflicts. + next_hop_unchanged: next_hop_unchanged + update_source: IP address or interface name. + route_reflector_client: route_reflector_client + bfd: Enable BFD. + bfd_timers: Override default BFD timers. BFD must be enabled with `bfd: true`. + ebgp_multihop: Time-to-live in range of hops. + next_hop_self: next_hop_self + password: password + passive: passive + default_originate: default_originate + send_community: 'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'. + maximum_routes: Maximum number of routes (0 means unlimited). + maximum_routes_warning_limit: + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of maximum number of routes + at which to warn ("<1-100> percent"). + maximum_routes_warning_only: maximum_routes_warning_only + missing_policy: Missing policy configuration for all address-families. + link_bandwidth: link_bandwidth + allowas_in: allowas_in + weight: weight + timers: BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>". + rib_in_pre_policy_retain: rib_in_pre_policy_retain + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + bgp_listen_range_prefix: + IP prefix range. + note: `bgp_listen_range_prefix` and `peer_filter` should not be mixed with + the new `listen_ranges` key + above to avoid conflicts. + session_tracker: session_tracker + shared_secret: shared_secret + ttl_maximum_hops: Maximum number of hops. """ self.name = name self.nodes = nodes self.address_family_ipv4 = address_family_ipv4 self.address_family_ipv6 = address_family_ipv6 + self.type = type + self.remote_as = remote_as + self.local_as = local_as + self.description = description + self.shutdown = shutdown + self.as_path = as_path + self.remove_private_as = remove_private_as + self.remove_private_as_ingress = remove_private_as_ingress + self.peer_filter = peer_filter + self.next_hop_unchanged = next_hop_unchanged + self.update_source = update_source + self.route_reflector_client = route_reflector_client + self.bfd = bfd + self.bfd_timers = bfd_timers + self.ebgp_multihop = ebgp_multihop + self.next_hop_self = next_hop_self + self.password = password + self.passive = passive + self.default_originate = default_originate + self.send_community = send_community + self.maximum_routes = maximum_routes + self.maximum_routes_warning_limit = maximum_routes_warning_limit + self.maximum_routes_warning_only = maximum_routes_warning_only + self.missing_policy = missing_policy + self.link_bandwidth = link_bandwidth + self.allowas_in = allowas_in + self.weight = weight + self.timers = timers + self.rib_in_pre_policy_retain = rib_in_pre_policy_retain + self.route_map_in = route_map_in + self.route_map_out = route_map_out + self.bgp_listen_range_prefix = bgp_listen_range_prefix + self.session_tracker = session_tracker + self.shared_secret = shared_secret + self.ttl_maximum_hops = ttl_maximum_hops return super().__init__(**kwargs) class EvpnL2Multicast(AvdDictBaseModel): @@ -11588,7 +13497,7 @@ class PimRpAddressesItem(AvdDictBaseModel): Configuration Will be applied to all nodes if not set. """ groups: list[str] | None = None - access_list_name: Annotated[str, ConvertTypes[int]] | None = None + access_list_name: str | None = None """ List of groups to associate with the RP address set in 'rp'. If access_list_name is set, a standard access-list will be @@ -11601,7 +13510,7 @@ def __init__( rps: list[str] | None = None, nodes: list[str] | None = None, groups: list[str] | None = None, - access_list_name: Annotated[str, ConvertTypes[int]] | None = None, + access_list_name: str | None = None, **kwargs, ): """ @@ -11630,14 +13539,10 @@ class IgmpSnoopingQuerier(AvdDictBaseModel): """Will be enabled automatically if "evpn_l2_multicast" is enabled.""" source_address: Annotated[str, Format["ipv4"]] | None = None """Default IP address of Loopback0.""" - version: Literal[1, 2, 3] | None = 2 + version: int | None = 2 def __init__( - self, - enabled: bool | None = None, - source_address: Annotated[str, Format["ipv4"]] | None = None, - version: Literal[1, 2, 3] | None = 2, - **kwargs, + self, enabled: bool | None = None, source_address: Annotated[str, Format["ipv4"]] | None = None, version: int | None = 2, **kwargs ): """ Args: @@ -11658,16 +13563,10 @@ class IpHelpersItem(AvdDictBaseModel): """IPv4 DHCP server IP.""" source_interface: str | None = None """Interface name.""" - source_vrf: Annotated[str, ConvertTypes[int]] | None = None + source_vrf: str | None = None """VRF to originate DHCP relay packets to DHCP server. If not set, uses current VRF.""" - def __init__( - self, - ip_helper: str = None, - source_interface: str | None = None, - source_vrf: Annotated[str, ConvertTypes[int]] | None = None, - **kwargs, - ): + def __init__(self, ip_helper: str = None, source_interface: str | None = None, source_vrf: str | None = None, **kwargs): """ Args: ----- @@ -11880,7 +13779,7 @@ class PimRpAddressesItem(AvdDictBaseModel): Configuration Will be applied to all nodes if not set. """ groups: list[str] | None = None - access_list_name: Annotated[str, ConvertTypes[int]] | None = None + access_list_name: str | None = None """ List of groups to associate with the RP addresses set in 'rps'. If access_list_name is set, a standard access-list will @@ -11893,7 +13792,7 @@ def __init__( rps: list[str] | None = None, nodes: list[str] | None = None, groups: list[str] | None = None, - access_list_name: Annotated[str, ConvertTypes[int]] | None = None, + access_list_name: str | None = None, **kwargs, ): """ @@ -11924,16 +13823,10 @@ class IpHelpersItem(AvdDictBaseModel): """IPv4 DHCP server IP.""" source_interface: str | None = None """Interface name to originate DHCP relay packets to DHCP server.""" - source_vrf: Annotated[str, ConvertTypes[int]] | None = None + source_vrf: str | None = None """VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI.""" - def __init__( - self, - ip_helper: str = None, - source_interface: str | None = None, - source_vrf: Annotated[str, ConvertTypes[int]] | None = None, - **kwargs, - ): + def __init__(self, ip_helper: str = None, source_interface: str | None = None, source_vrf: str | None = None, **kwargs): """ Args: ----- @@ -11981,12 +13874,10 @@ class IgmpSnoopingQuerier(AvdDictBaseModel): IPv4_address If not set, IP address of "Loopback0" will be used. """ - version: Literal[1, 2, 3] | None = None + version: int | None = None """IGMP Version (By default EOS uses IGMP version 2 for IGMP querier).""" - def __init__( - self, enabled: bool | None = None, source_address: str | None = None, version: Literal[1, 2, 3] | None = None, **kwargs - ): + def __init__(self, enabled: bool | None = None, source_address: str | None = None, version: int | None = None, **kwargs): """ Args: ----- @@ -12005,14 +13896,14 @@ def __init__( class Ospf(AvdDictBaseModel): class MessageDigestKeysItem(AvdDictBaseModel): id: int | None = None - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = "sha512" + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = "sha512" key: str | None = None """Type 7 encrypted key.""" def __init__( self, id: int | None = None, - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = "sha512", + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = "sha512", key: str | None = None, **kwargs, ): @@ -12031,11 +13922,11 @@ def __init__( enabled: bool | None = None point_to_point: bool | None = True - area: Annotated[str, ConvertTypes[int]] | None = "0" + area: str | None = "0" """OSPF area ID.""" cost: int | None = None """OSPF link cost.""" - authentication: Literal["simple", "message-digest"] | None = None + authentication: Annotated[str, ValidValues["simple", "message-digest"]] | None = None simple_auth_key: str | None = None """Password used with simple authentication.""" message_digest_keys: list[MessageDigestKeysItem] | None = None @@ -12044,9 +13935,9 @@ def __init__( self, enabled: bool | None = None, point_to_point: bool | None = True, - area: Annotated[str, ConvertTypes[int]] | None = "0", + area: str | None = "0", cost: int | None = None, - authentication: Literal["simple", "message-digest"] | None = None, + authentication: Annotated[str, ValidValues["simple", "message-digest"]] | None = None, simple_auth_key: str | None = None, message_digest_keys: list[MessageDigestKeysItem] | None = None, **kwargs, @@ -12105,7 +13996,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): node: str = None """l3_leaf inventory hostname.""" - tags: list[Annotated[str, ConvertTypes[int]]] | None = ["all"] + tags: list[str] | None = ["all"] """ Tags leveraged for networks services filtering. Tags are matched against "filter.tags" defined under node type settings. @@ -12161,13 +14052,13 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): ipv6_virtual_router_addresses will take precedence _if_ there is an ipv6_address configured for the node. """ - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_in: str | None = None """ Name of the IPv4 access-list to be assigned in the ingress direction. The access-list must be defined under `ipv4_acls` and supports substitution of the field "interface_ip". """ - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_out: str | None = None """ Name of the IPv4 Access-list to be assigned in the egress direction. The access-list must be defined under `ipv4_acls` @@ -12181,7 +14072,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): The vni_override allows us to override this value and statically define it (optional). """ - rt_override: Annotated[str, ConvertTypes[int]] | None = None + rt_override: str | None = None """ By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. The rt_override allows us to override this @@ -12194,7 +14085,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): details). - A full RT string with colon separator which will override the full RT. """ - rd_override: Annotated[str, ConvertTypes[int]] | None = None + rd_override: str | None = None """ By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. The rt_override allows us to override this @@ -12247,7 +14138,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): def __init__( self, node: str = None, - tags: list[Annotated[str, ConvertTypes[int]]] | None = ["all"], + tags: list[str] | None = ["all"], name: str | None = None, enabled: bool | None = None, description: str | None = None, @@ -12260,12 +14151,12 @@ def __init__( ip_address_virtual_secondaries: list[str] | None = None, ip_virtual_router_addresses: list[str] | None = None, ipv6_virtual_router_addresses: list[str] | None = None, - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None, - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None, + ipv4_acl_in: str | None = None, + ipv4_acl_out: str | None = None, ip_helpers: list[IpHelpersItem] | None = None, vni_override: int | None = None, - rt_override: Annotated[str, ConvertTypes[int]] | None = None, - rd_override: Annotated[str, ConvertTypes[int]] | None = None, + rt_override: str | None = None, + rd_override: str | None = None, trunk_groups: list[str] | None = None, evpn_l2_multicast: EvpnL2Multicast | None = None, evpn_l3_multicast: EvpnL3Multicast | None = None, @@ -12421,16 +14312,10 @@ class IpHelpersItem(AvdDictBaseModel): """IPv4 DHCP server IP.""" source_interface: str | None = None """Interface name to originate DHCP relay packets to DHCP server.""" - source_vrf: Annotated[str, ConvertTypes[int]] | None = None + source_vrf: str | None = None """VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI.""" - def __init__( - self, - ip_helper: str = None, - source_interface: str | None = None, - source_vrf: Annotated[str, ConvertTypes[int]] | None = None, - **kwargs, - ): + def __init__(self, ip_helper: str = None, source_interface: str | None = None, source_vrf: str | None = None, **kwargs): """ Args: ----- @@ -12478,12 +14363,10 @@ class IgmpSnoopingQuerier(AvdDictBaseModel): IPv4_address If not set, IP address of "Loopback0" will be used. """ - version: Literal[1, 2, 3] | None = None + version: int | None = None """IGMP Version (By default EOS uses IGMP version 2 for IGMP querier).""" - def __init__( - self, enabled: bool | None = None, source_address: str | None = None, version: Literal[1, 2, 3] | None = None, **kwargs - ): + def __init__(self, enabled: bool | None = None, source_address: str | None = None, version: int | None = None, **kwargs): """ Args: ----- @@ -12502,14 +14385,14 @@ def __init__( class Ospf(AvdDictBaseModel): class MessageDigestKeysItem(AvdDictBaseModel): id: int | None = None - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = "sha512" + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = "sha512" key: str | None = None """Type 7 encrypted key.""" def __init__( self, id: int | None = None, - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = "sha512", + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = "sha512", key: str | None = None, **kwargs, ): @@ -12528,11 +14411,11 @@ def __init__( enabled: bool | None = None point_to_point: bool | None = True - area: Annotated[str, ConvertTypes[int]] | None = "0" + area: str | None = "0" """OSPF area ID.""" cost: int | None = None """OSPF link cost.""" - authentication: Literal["simple", "message-digest"] | None = None + authentication: Annotated[str, ValidValues["simple", "message-digest"]] | None = None simple_auth_key: str | None = None """Password used with simple authentication.""" message_digest_keys: list[MessageDigestKeysItem] | None = None @@ -12541,9 +14424,9 @@ def __init__( self, enabled: bool | None = None, point_to_point: bool | None = True, - area: Annotated[str, ConvertTypes[int]] | None = "0", + area: str | None = "0", cost: int | None = None, - authentication: Literal["simple", "message-digest"] | None = None, + authentication: Annotated[str, ValidValues["simple", "message-digest"]] | None = None, simple_auth_key: str | None = None, message_digest_keys: list[MessageDigestKeysItem] | None = None, **kwargs, @@ -12610,7 +14493,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): SVI can refer to one svi_profile which again can refer to another svi_profile to inherit settings in up to two levels (svi -> svi_profile -> svi_parent_profile). """ - tags: list[Annotated[str, ConvertTypes[int]]] | None = ["all"] + tags: list[str] | None = ["all"] """ Tags leveraged for networks services filtering. Tags are matched against "filter.tags" defined under node type settings. @@ -12677,13 +14560,13 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): ipv6_virtual_router_addresses will take precedence _if_ there is an ipv6_address configured for the node. """ - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_in: str | None = None """ Name of the IPv4 access-list to be assigned in the ingress direction. The access-list must be defined under `ipv4_acls` and supports substitution of the field "interface_ip". """ - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_out: str | None = None """ Name of the IPv4 Access-list to be assigned in the egress direction. The access-list must be defined under `ipv4_acls` @@ -12697,7 +14580,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): The vni_override allows us to override this value and statically define it (optional). """ - rt_override: Annotated[str, ConvertTypes[int]] | None = None + rt_override: str | None = None """ By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. The rt_override allows us to override this @@ -12710,7 +14593,7 @@ class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): details). - A full RT string with colon separator which will override the full RT. """ - rd_override: Annotated[str, ConvertTypes[int]] | None = None + rd_override: str | None = None """ By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. The rt_override allows us to override this @@ -12765,7 +14648,7 @@ def __init__( id: int = None, name: str = None, profile: str | None = None, - tags: list[Annotated[str, ConvertTypes[int]]] | None = ["all"], + tags: list[str] | None = ["all"], evpn_vlan_bundle: str | None = None, nodes: list[NodesItem] | None = None, enabled: bool | None = None, @@ -12779,12 +14662,12 @@ def __init__( ip_address_virtual_secondaries: list[str] | None = None, ip_virtual_router_addresses: list[str] | None = None, ipv6_virtual_router_addresses: list[str] | None = None, - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None, - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None, + ipv4_acl_in: str | None = None, + ipv4_acl_out: str | None = None, ip_helpers: list[IpHelpersItem] | None = None, vni_override: int | None = None, - rt_override: Annotated[str, ConvertTypes[int]] | None = None, - rd_override: Annotated[str, ConvertTypes[int]] | None = None, + rt_override: str | None = None, + rd_override: str | None = None, trunk_groups: list[str] | None = None, evpn_l2_multicast: EvpnL2Multicast | None = None, evpn_l3_multicast: EvpnL3Multicast | None = None, @@ -12955,14 +14838,14 @@ class L3InterfacesItem(AvdDictBaseModel): class Ospf(AvdDictBaseModel): class MessageDigestKeysItem(AvdDictBaseModel): id: int | None = None - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = "sha512" + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = "sha512" key: str | None = None """Key password.""" def __init__( self, id: int | None = None, - hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None = "sha512", + hash_algorithm: Annotated[str, ValidValues["md5", "sha1", "sha256", "sha384", "sha512"]] | None = "sha512", key: str | None = None, **kwargs, ): @@ -12981,11 +14864,11 @@ def __init__( enabled: bool | None = None point_to_point: bool | None = False - area: Annotated[str, ConvertTypes[int]] | None = "0" + area: str | None = "0" """OSPF area ID.""" cost: int | None = None """OSPF link cost.""" - authentication: Literal["simple", "message-digest"] | None = None + authentication: Annotated[str, ValidValues["simple", "message-digest"]] | None = None simple_auth_key: str | None = None """Password used with simple authentication.""" message_digest_keys: list[MessageDigestKeysItem] | None = None @@ -12994,9 +14877,9 @@ def __init__( self, enabled: bool | None = None, point_to_point: bool | None = False, - area: Annotated[str, ConvertTypes[int]] | None = "0", + area: str | None = "0", cost: int | None = None, - authentication: Literal["simple", "message-digest"] | None = None, + authentication: Annotated[str, ValidValues["simple", "message-digest"]] | None = None, simple_auth_key: str | None = None, message_digest_keys: list[MessageDigestKeysItem] | None = None, **kwargs, @@ -13140,10 +15023,10 @@ def __init__( class LoopbacksItem(AvdDictBaseModel): class Ospf(AvdDictBaseModel): enabled: bool | None = False - area: Annotated[str, ConvertTypes[int]] | None = "0" + area: str | None = "0" """OSPF area ID.""" - def __init__(self, enabled: bool | None = False, area: Annotated[str, ConvertTypes[int]] | None = "0", **kwargs): + def __init__(self, enabled: bool | None = False, area: str | None = "0", **kwargs): """ Args: ----- @@ -13320,7 +15203,7 @@ def __init__(self, always: bool | None = None, **kwargs): """IPv4_address or IPv6_address.""" peer_group: str | None = None """Peer group name.""" - remote_as: Annotated[str, ConvertTypes[int]] | None = None + remote_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -13373,7 +15256,7 @@ def __init__(self, always: bool | None = None, **kwargs): The prefix-list will be associated under the IPv4 or IPv6 address family based on the IP address. """ - local_as: Annotated[str, ConvertTypes[int]] | None = None + local_as: str | None = None """ Local BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the @@ -13387,7 +15270,7 @@ def __init__( self, ip_address: str = None, peer_group: str | None = None, - remote_as: Annotated[str, ConvertTypes[int]] | None = None, + remote_as: str | None = None, description: str | None = None, password: str | None = None, send_community: str | None = None, @@ -13405,7 +15288,7 @@ def __init__( route_map_in: str | None = None, prefix_list_in: str | None = None, prefix_list_out: str | None = None, - local_as: Annotated[str, ConvertTypes[int]] | None = None, + local_as: str | None = None, weight: int | None = None, bfd: bool | None = None, shutdown: bool | None = None, @@ -13507,13 +15390,58 @@ def __init__(self, raw_eos_cli: str | None = None, structured_config: Structured self.structured_config = structured_config return super().__init__(**kwargs) - class BgpPeerGroupsItem(EosCliConfigGen.RouterBgp.PeerGroupsItem): - class AddressFamilyIpv4(AvdDictBaseModel): - class DefaultOriginate(EosCliConfigGen.RouterBgp.AddressFamilyIpv4.PeerGroupsItem.DefaultOriginate): - pass + class BgpPeerGroupsItem(AvdDictBaseModel): + class AddressFamilyIpv4(AvdDictBaseModel): + class DefaultOriginate(AvdDictBaseModel): + always: bool | None = None + route_map: str | None = None + """Route-map name.""" + + def __init__(self, always: bool | None = None, route_map: str | None = None, **kwargs): + """ + Args: + ----- + always: always + route_map: Route-map name. + + """ + self.always = always + self.route_map = route_map + return super().__init__(**kwargs) + + class NextHop(AvdDictBaseModel): + class AddressFamilyIpv6(AvdDictBaseModel): + enabled: bool = None + originate: bool | None = None + + def __init__(self, enabled: bool = None, originate: bool | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + originate: originate + + """ + self.enabled = enabled + self.originate = originate + return super().__init__(**kwargs) + + address_family_ipv6: AddressFamilyIpv6 | None = None + address_family_ipv6_originate: bool | None = None + + def __init__( + self, address_family_ipv6: AddressFamilyIpv6 | None = None, address_family_ipv6_originate: bool | None = None, **kwargs + ): + """ + Args: + ----- + address_family_ipv6: address_family_ipv6 + address_family_ipv6_originate: address_family_ipv6_originate - class NextHop(EosCliConfigGen.RouterBgp.AddressFamilyIpv4.PeerGroupsItem.NextHop): - pass + """ + self.address_family_ipv6 = address_family_ipv6 + self.address_family_ipv6_originate = address_family_ipv6_originate + return super().__init__(**kwargs) activate: bool | None = None route_map_in: str | None = None @@ -13596,6 +15524,257 @@ def __init__( self.prefix_list_out = prefix_list_out return super().__init__(**kwargs) + class AsPath(AvdDictBaseModel): + remote_as_replace_out: bool | None = None + """Replace AS number with local AS number.""" + prepend_own_disabled: bool | None = None + """Disable prepending own AS number to AS path.""" + + def __init__(self, remote_as_replace_out: bool | None = None, prepend_own_disabled: bool | None = None, **kwargs): + """ + Args: + ----- + remote_as_replace_out: Replace AS number with local AS number. + prepend_own_disabled: Disable prepending own AS number to AS path. + + """ + self.remote_as_replace_out = remote_as_replace_out + self.prepend_own_disabled = prepend_own_disabled + return super().__init__(**kwargs) + + class RemovePrivateAs(AvdDictBaseModel): + enabled: bool | None = None + all: bool | None = None + replace_as: bool | None = None + + def __init__(self, enabled: bool | None = None, all: bool | None = None, replace_as: bool | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + all: all + replace_as: replace_as + + """ + self.enabled = enabled + self.all = all + self.replace_as = replace_as + return super().__init__(**kwargs) + + class RemovePrivateAsIngress(AvdDictBaseModel): + enabled: bool | None = None + replace_as: bool | None = None + + def __init__(self, enabled: bool | None = None, replace_as: bool | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + replace_as: replace_as + + """ + self.enabled = enabled + self.replace_as = replace_as + return super().__init__(**kwargs) + + class BfdTimers(AvdDictBaseModel): + interval: int = None + """Interval in milliseconds.""" + min_rx: int = None + """Rate in milliseconds.""" + multiplier: int = None + + def __init__(self, interval: int = None, min_rx: int = None, multiplier: int = None, **kwargs): + """ + Args: + ----- + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + + """ + self.interval = interval + self.min_rx = min_rx + self.multiplier = multiplier + return super().__init__(**kwargs) + + class DefaultOriginate(AvdDictBaseModel): + enabled: bool | None = None + always: bool | None = None + route_map: str | None = None + """Route-map name.""" + + def __init__(self, enabled: bool | None = None, always: bool | None = None, route_map: str | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + always: always + route_map: Route-map name. + + """ + self.enabled = enabled + self.always = always + self.route_map = route_map + return super().__init__(**kwargs) + + class MissingPolicy(AvdDictBaseModel): + class DirectionIn(AvdDictBaseModel): + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None + """Missing policy action.""" + include_community_list: bool | None = None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None = None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None = None + """Include sub-route-map references in missing policy decision.""" + + def __init__( + self, + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None, + include_community_list: bool | None = None, + include_prefix_list: bool | None = None, + include_sub_route_map: bool | None = None, + **kwargs, + ): + """ + Args: + ----- + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + + """ + self.action = action + self.include_community_list = include_community_list + self.include_prefix_list = include_prefix_list + self.include_sub_route_map = include_sub_route_map + return super().__init__(**kwargs) + + class DirectionOut(AvdDictBaseModel): + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None + """Missing policy action.""" + include_community_list: bool | None = None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None = None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None = None + """Include sub-route-map references in missing policy decision.""" + + def __init__( + self, + action: Annotated[str, ValidValues["deny", "permit", "deny-in-out"]] = None, + include_community_list: bool | None = None, + include_prefix_list: bool | None = None, + include_sub_route_map: bool | None = None, + **kwargs, + ): + """ + Args: + ----- + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + + """ + self.action = action + self.include_community_list = include_community_list + self.include_prefix_list = include_prefix_list + self.include_sub_route_map = include_sub_route_map + return super().__init__(**kwargs) + + direction_in: DirectionIn | None = None + """Missing policy inbound direction.""" + direction_out: DirectionOut | None = None + """Missing policy outbound direction.""" + + def __init__(self, direction_in: DirectionIn | None = None, direction_out: DirectionOut | None = None, **kwargs): + """ + Args: + ----- + direction_in: Missing policy inbound direction. + direction_out: Missing policy outbound direction. + + """ + self.direction_in = direction_in + self.direction_out = direction_out + return super().__init__(**kwargs) + + class LinkBandwidth(AvdDictBaseModel): + enabled: bool | None = None + default: str | None = None + """nn.nn(K|M|G) link speed in bits/second.""" + + def __init__(self, enabled: bool | None = None, default: str | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + default: nn.nn(K|M|G) link speed in bits/second. + + """ + self.enabled = enabled + self.default = default + return super().__init__(**kwargs) + + class AllowasIn(AvdDictBaseModel): + enabled: bool | None = None + times: int | None = None + """Number of local ASNs allowed in a BGP update.""" + + def __init__(self, enabled: bool | None = None, times: int | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + times: Number of local ASNs allowed in a BGP update. + + """ + self.enabled = enabled + self.times = times + return super().__init__(**kwargs) + + class RibInPrePolicyRetain(AvdDictBaseModel): + enabled: bool | None = None + all: bool | None = None + + def __init__(self, enabled: bool | None = None, all: bool | None = None, **kwargs): + """ + Args: + ----- + enabled: enabled + all: all + + """ + self.enabled = enabled + self.all = all + return super().__init__(**kwargs) + + class SharedSecret(AvdDictBaseModel): + profile: str = None + """Name of profile defined under `management_security`.""" + hash_algorithm: Annotated[str, ValidValues["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"]] = None + """Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above.""" + + def __init__( + self, + profile: str = None, + hash_algorithm: Annotated[str, ValidValues["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"]] = None, + **kwargs, + ): + """ + Args: + ----- + profile: Name of profile defined under `management_security`. + hash_algorithm: Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above. + + """ + self.profile = profile + self.hash_algorithm = hash_algorithm + return super().__init__(**kwargs) + name: str | None = None """BGP peer group name.""" nodes: list[str] | None = None @@ -13606,6 +15785,82 @@ def __init__( """ address_family_ipv4: AddressFamilyIpv4 | None = None address_family_ipv6: AddressFamilyIpv6 | None = None + type: str | None = None + """Key only used for documentation or validation purposes.""" + remote_as: str | None = None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value + must be put in quotes, to prevent it from being interpreted as a float number. + """ + local_as: str | None = None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value + must be put in quotes, to prevent it from being interpreted as a float number. + """ + description: str | None = None + shutdown: bool | None = None + as_path: AsPath | None = None + """BGP AS-PATH options.""" + remove_private_as: RemovePrivateAs | None = None + """Remove private AS numbers in outbound AS path.""" + remove_private_as_ingress: RemovePrivateAsIngress | None = None + peer_filter: str | None = None + """ + Peer-filter name. + note: `bgp_listen_range_prefix` and `peer_filter` should not be mixed with + the new `listen_ranges` key + above to avoid conflicts. + """ + next_hop_unchanged: bool | None = None + update_source: str | None = None + """IP address or interface name.""" + route_reflector_client: bool | None = None + bfd: bool | None = None + """Enable BFD.""" + bfd_timers: BfdTimers | None = None + """Override default BFD timers. BFD must be enabled with `bfd: true`.""" + ebgp_multihop: int | None = None + """Time-to-live in range of hops.""" + next_hop_self: bool | None = None + password: str | None = None + passive: bool | None = None + default_originate: DefaultOriginate | None = None + send_community: str | None = None + """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" + maximum_routes: int | None = None + """Maximum number of routes (0 means unlimited).""" + maximum_routes_warning_limit: str | None = None + """ + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of maximum number of routes + at which to warn ("<1-100> percent"). + """ + maximum_routes_warning_only: bool | None = None + missing_policy: MissingPolicy | None = None + """Missing policy configuration for all address-families.""" + link_bandwidth: LinkBandwidth | None = None + allowas_in: AllowasIn | None = None + weight: int | None = None + timers: str | None = None + """BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>".""" + rib_in_pre_policy_retain: RibInPrePolicyRetain | None = None + route_map_in: str | None = None + """Inbound route-map name.""" + route_map_out: str | None = None + """Outbound route-map name.""" + bgp_listen_range_prefix: str | None = None + """ + IP prefix range. + note: `bgp_listen_range_prefix` and `peer_filter` should not be mixed with + the new `listen_ranges` key + above to avoid conflicts. + """ + session_tracker: str | None = None + shared_secret: SharedSecret | None = None + ttl_maximum_hops: int | None = None + """Maximum number of hops.""" def __init__( self, @@ -13613,6 +15868,41 @@ def __init__( nodes: list[str] | None = None, address_family_ipv4: AddressFamilyIpv4 | None = None, address_family_ipv6: AddressFamilyIpv6 | None = None, + type: str | None = None, + remote_as: str | None = None, + local_as: str | None = None, + description: str | None = None, + shutdown: bool | None = None, + as_path: AsPath | None = None, + remove_private_as: RemovePrivateAs | None = None, + remove_private_as_ingress: RemovePrivateAsIngress | None = None, + peer_filter: str | None = None, + next_hop_unchanged: bool | None = None, + update_source: str | None = None, + route_reflector_client: bool | None = None, + bfd: bool | None = None, + bfd_timers: BfdTimers | None = None, + ebgp_multihop: int | None = None, + next_hop_self: bool | None = None, + password: str | None = None, + passive: bool | None = None, + default_originate: DefaultOriginate | None = None, + send_community: str | None = None, + maximum_routes: int | None = None, + maximum_routes_warning_limit: str | None = None, + maximum_routes_warning_only: bool | None = None, + missing_policy: MissingPolicy | None = None, + link_bandwidth: LinkBandwidth | None = None, + allowas_in: AllowasIn | None = None, + weight: int | None = None, + timers: str | None = None, + rib_in_pre_policy_retain: RibInPrePolicyRetain | None = None, + route_map_in: str | None = None, + route_map_out: str | None = None, + bgp_listen_range_prefix: str | None = None, + session_tracker: str | None = None, + shared_secret: SharedSecret | None = None, + ttl_maximum_hops: int | None = None, **kwargs, ): """ @@ -13625,16 +15915,103 @@ def __init__( is created on devices which have a bgp_peer mapped to the corresponding peer_group. address_family_ipv4: address_family_ipv4 address_family_ipv6: address_family_ipv6 + type: Key only used for documentation or validation purposes. + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value + must be put in quotes, to prevent it from being interpreted as a float number. + local_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value + must be put in quotes, to prevent it from being interpreted as a float number. + description: description + shutdown: shutdown + as_path: BGP AS-PATH options. + remove_private_as: Remove private AS numbers in outbound AS path. + remove_private_as_ingress: remove_private_as_ingress + peer_filter: + Peer-filter name. + note: `bgp_listen_range_prefix` and `peer_filter` should not be mixed with + the new `listen_ranges` key + above to avoid conflicts. + next_hop_unchanged: next_hop_unchanged + update_source: IP address or interface name. + route_reflector_client: route_reflector_client + bfd: Enable BFD. + bfd_timers: Override default BFD timers. BFD must be enabled with `bfd: true`. + ebgp_multihop: Time-to-live in range of hops. + next_hop_self: next_hop_self + password: password + passive: passive + default_originate: default_originate + send_community: 'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'. + maximum_routes: Maximum number of routes (0 means unlimited). + maximum_routes_warning_limit: + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of maximum number of routes + at which to warn ("<1-100> percent"). + maximum_routes_warning_only: maximum_routes_warning_only + missing_policy: Missing policy configuration for all address-families. + link_bandwidth: link_bandwidth + allowas_in: allowas_in + weight: weight + timers: BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>". + rib_in_pre_policy_retain: rib_in_pre_policy_retain + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + bgp_listen_range_prefix: + IP prefix range. + note: `bgp_listen_range_prefix` and `peer_filter` should not be mixed with + the new `listen_ranges` key + above to avoid conflicts. + session_tracker: session_tracker + shared_secret: shared_secret + ttl_maximum_hops: Maximum number of hops. """ self.name = name self.nodes = nodes self.address_family_ipv4 = address_family_ipv4 self.address_family_ipv6 = address_family_ipv6 + self.type = type + self.remote_as = remote_as + self.local_as = local_as + self.description = description + self.shutdown = shutdown + self.as_path = as_path + self.remove_private_as = remove_private_as + self.remove_private_as_ingress = remove_private_as_ingress + self.peer_filter = peer_filter + self.next_hop_unchanged = next_hop_unchanged + self.update_source = update_source + self.route_reflector_client = route_reflector_client + self.bfd = bfd + self.bfd_timers = bfd_timers + self.ebgp_multihop = ebgp_multihop + self.next_hop_self = next_hop_self + self.password = password + self.passive = passive + self.default_originate = default_originate + self.send_community = send_community + self.maximum_routes = maximum_routes + self.maximum_routes_warning_limit = maximum_routes_warning_limit + self.maximum_routes_warning_only = maximum_routes_warning_only + self.missing_policy = missing_policy + self.link_bandwidth = link_bandwidth + self.allowas_in = allowas_in + self.weight = weight + self.timers = timers + self.rib_in_pre_policy_retain = rib_in_pre_policy_retain + self.route_map_in = route_map_in + self.route_map_out = route_map_out + self.bgp_listen_range_prefix = bgp_listen_range_prefix + self.session_tracker = session_tracker + self.shared_secret = shared_secret + self.ttl_maximum_hops = ttl_maximum_hops return super().__init__(**kwargs) class AdditionalRouteTargetsItem(AvdDictBaseModel): - type: Literal["import", "export"] | None = None + type: Annotated[str, ValidValues["import", "export"]] | None = None address_family: str | None = None route_target: str | None = None nodes: list[str] | None = None @@ -13642,7 +16019,7 @@ class AdditionalRouteTargetsItem(AvdDictBaseModel): def __init__( self, - type: Literal["import", "export"] | None = None, + type: Annotated[str, ValidValues["import", "export"]] | None = None, address_family: str | None = None, route_target: str | None = None, nodes: list[str] | None = None, @@ -13666,8 +16043,8 @@ def __init__( class StructuredConfig(EosCliConfigGen): pass - name: Annotated[str, ConvertTypes[int]] = None - address_families: list[str] | None = None + name: str = None + address_families: list[Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None description: str | None = None """VRF description.""" vrf_vni: int | None = None @@ -13690,7 +16067,7 @@ class StructuredConfig(EosCliConfigGen): "vrf_id" is preferred over "vrf_vni" for MLAG iBGP peering vlan, see "mlag_ibgp_peering_vrfs.base_vlan" for details. """ - rd_override: Annotated[str, ConvertTypes[int]] | None = None + rd_override: str | None = None """ By default, the VRF RD will be derived from the pattern defined in `overlay_rd_type`. The rd_override allows us to @@ -13702,7 +16079,7 @@ class StructuredConfig(EosCliConfigGen): - A full RD string with colon separator which will override the full RD. """ - rt_override: Annotated[str, ConvertTypes[int]] | None = None + rt_override: str | None = None """ By default, the VRF RT will be derived from the pattern defined in `overlay_rt_type`. The rt_override allows us to @@ -13837,13 +16214,13 @@ class StructuredConfig(EosCliConfigGen): def __init__( self, - name: Annotated[str, ConvertTypes[int]] = None, - address_families: list[str] | None = None, + name: str = None, + address_families: list[Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None, description: str | None = None, vrf_vni: int | None = None, vrf_id: int | None = None, - rd_override: Annotated[str, ConvertTypes[int]] | None = None, - rt_override: Annotated[str, ConvertTypes[int]] | None = None, + rd_override: str | None = None, + rt_override: str | None = None, mlag_ibgp_peering_ipv4_pool: str | None = None, ip_helpers: list[IpHelpersItem] | None = None, enable_mlag_ibgp_peering_vrfs: bool | None = None, @@ -14052,9 +16429,9 @@ class IgmpSnoopingQuerier(AvdDictBaseModel): IPv4_address If not set, IP address of "Loopback0" will be used. """ - version: Literal[1, 2, 3] | None = 2 + version: int | None = 2 - def __init__(self, enabled: bool | None = None, source_address: str | None = None, version: Literal[1, 2, 3] | None = 2, **kwargs): + def __init__(self, enabled: bool | None = None, source_address: str | None = None, version: int | None = 2, **kwargs): """ Args: ----- @@ -14111,7 +16488,7 @@ def __init__(self, structured_config: StructuredConfig | None = None, raw_eos_cl The vni_override, allows to override this value and statically define it. """ - rt_override: Annotated[str, ConvertTypes[int]] | None = None + rt_override: str | None = None """ By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. The rt_override allows us to override this @@ -14124,7 +16501,7 @@ def __init__(self, structured_config: StructuredConfig | None = None, raw_eos_cl details). - A full RT string with colon separator which will override the full RT. """ - rd_override: Annotated[str, ConvertTypes[int]] | None = None + rd_override: str | None = None """ By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. The rt_override allows us to override this @@ -14185,8 +16562,8 @@ def __init__( self, id: int = None, vni_override: int | None = None, - rt_override: Annotated[str, ConvertTypes[int]] | None = None, - rd_override: Annotated[str, ConvertTypes[int]] | None = None, + rt_override: str | None = None, + rd_override: str | None = None, name: str = None, tags: list[str] | None = None, vxlan: bool | None = True, @@ -14294,10 +16671,10 @@ def __init__(self, number: int = None, **kwargs): class EndpointsItem(AvdDictBaseModel): class PortChannel(AvdDictBaseModel): - mode: Literal["active", "on"] | None = None + mode: Annotated[str, ValidValues["active", "on"]] | None = None short_esi: str | None = None - def __init__(self, mode: Literal["active", "on"] | None = None, short_esi: str | None = None, **kwargs): + def __init__(self, mode: Annotated[str, ValidValues["active", "on"]] | None = None, short_esi: str | None = None, **kwargs): """ Args: ----- @@ -14344,7 +16721,7 @@ def __init__( name: str = None """Pseudowire name.""" - type: Literal["vpws-pseudowire"] | None = "vpws-pseudowire" + type: Annotated[str, ValidValues["vpws-pseudowire"]] | None = "vpws-pseudowire" subinterfaces: list[SubinterfacesItem] | None = None """Subinterfaces will create subinterfaces and additional pseudowires/patch panel config for each endpoint.""" endpoints: list[EndpointsItem] | None = None @@ -14355,7 +16732,7 @@ def __init__( def __init__( self, name: str = None, - type: Literal["vpws-pseudowire"] | None = "vpws-pseudowire", + type: Annotated[str, ValidValues["vpws-pseudowire"]] | None = "vpws-pseudowire", subinterfaces: list[SubinterfacesItem] | None = None, endpoints: list[EndpointsItem] | None = None, lldp_disable: bool | None = None, @@ -14823,13 +17200,13 @@ class Filter(AvdDictBaseModel): """ tags: list[str] | None = ["all"] """Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default).""" - allow_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"] + allow_vrfs: list[str] | None = ["all"] """ Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs (default). This list also limits VRFs included by `always_include_vrfs_in_tenants`. """ - deny_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"] + deny_vrfs: list[str] | None = ["all"] """ Prevent configuration of Network Services defined under these VRFs. This list prevents the given VRFs to be included by @@ -14853,8 +17230,8 @@ def __init__( self, tenants: list[str] | None = ["all"], tags: list[str] | None = ["all"], - allow_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"], - deny_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"], + allow_vrfs: list[str] | None = ["all"], + deny_vrfs: list[str] | None = ["all"], always_include_vrfs_in_tenants: list[str] | None = None, only_vlans_in_use: bool | None = False, **kwargs, @@ -14900,7 +17277,7 @@ class RemotePeersItem(AvdDictBaseModel): """Hostname of remote EVPN GW server.""" ip_address: Annotated[str, Format["ipv4"]] | None = None """Peering IP of remote Route Server.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None + bgp_as: str | None = None """ Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in @@ -14908,11 +17285,7 @@ class RemotePeersItem(AvdDictBaseModel): """ def __init__( - self, - hostname: str | None = None, - ip_address: Annotated[str, Format["ipv4"]] | None = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None, - **kwargs, + self, hostname: str | None = None, ip_address: Annotated[str, Format["ipv4"]] | None = None, bgp_as: str | None = None, **kwargs ): """ Args: @@ -14999,20 +17372,14 @@ class RemotePeersItem(AvdDictBaseModel): """Hostname of remote IPVPN Peer.""" ip_address: Annotated[str, Format["ipv4"]] = None """Peering IP of remote IPVPN Peer.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] = None + bgp_as: str = None """ Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float number. """ - def __init__( - self, - hostname: str = None, - ip_address: Annotated[str, Format["ipv4"]] = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] = None, - **kwargs, - ): + def __init__(self, hostname: str = None, ip_address: Annotated[str, Format["ipv4"]] = None, bgp_as: str = None, **kwargs): """ Args: ----- @@ -15038,7 +17405,7 @@ def __init__( """Enable D-path for use with BGP bestpath selection algorithm.""" maximum_routes: int | None = 0 """Maximum routes to accept from IPVPN remote peers.""" - local_as: Annotated[str, ConvertTypes[int]] | None = "none" + local_as: str | None = "none" """ Local BGP AS applied to peering with IPVPN remote peers. BGP AS <1-4294967295> or AS number in asdot notation @@ -15057,7 +17424,7 @@ def __init__( ipvpn_domain_id: str | None = "65535:2", enable_d_path: bool | None = True, maximum_routes: int | None = 0, - local_as: Annotated[str, ConvertTypes[int]] | None = "none", + local_as: str | None = "none", address_families: list[str] | None = ["vpn-ipv4"], remote_peers: list[RemotePeersItem] | None = None, **kwargs, @@ -15234,7 +17601,7 @@ def __init__( return super().__init__(**kwargs) enabled: bool | None = False - profile: Literal["aes67", "smpte2059-2", "aes67-r16-2016"] | None = "aes67-r16-2016" + profile: Annotated[str, ValidValues["aes67", "smpte2059-2", "aes67-r16-2016"]] | None = "aes67-r16-2016" mlag: bool | None = False """ Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be configured on the MLAG @@ -15267,7 +17634,7 @@ def __init__( the recommended behaviour. This can be set manually if required, for example, to a value of "10.1.2.3". """ - mode: Literal["boundary"] | None = "boundary" + mode: Annotated[str, ValidValues["boundary"]] | None = "boundary" mode_one_step: bool | None = False ttl: int | None = None forward_unicast: bool | None = False @@ -15278,7 +17645,7 @@ def __init__( def __init__( self, enabled: bool | None = False, - profile: Literal["aes67", "smpte2059-2", "aes67-r16-2016"] | None = "aes67-r16-2016", + profile: Annotated[str, ValidValues["aes67", "smpte2059-2", "aes67-r16-2016"]] | None = "aes67-r16-2016", mlag: bool | None = False, domain: int | None = 127, priority1: int | None = None, @@ -15287,7 +17654,7 @@ def __init__( clock_identity_prefix: str | None = None, clock_identity: str | None = None, source_ip: str | None = None, - mode: Literal["boundary"] | None = "boundary", + mode: Annotated[str, ValidValues["boundary"]] | None = "boundary", mode_one_step: bool | None = False, ttl: int | None = None, forward_unicast: bool | None = False, @@ -15369,7 +17736,7 @@ def __init__(self, enabled: bool | None = None, name: str | None = None, **kwarg """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" ipsec: bool | None = True """Enable / Disable IPsec over HA path-group when HA is enabled.""" - ha_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + ha_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """ Local WAN HA interfaces Overwrite the default behavior which is to pick all the `uplink_interfaces`. @@ -15398,7 +17765,7 @@ def __init__( self, enabled: bool | None = True, ipsec: bool | None = True, - ha_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, + ha_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, ha_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, max_ha_interfaces: int | None = None, flow_tracking: FlowTracking | None = None, @@ -15512,7 +17879,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): profile: str | None = None """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" - name: Annotated[str, Pattern["Ethernet[\d/]+(.[\d]+)?"]] = None + name: Annotated[str, Pattern[r"Ethernet[\d/]+(.[\d]+)?"]] = None """ Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. For a subinterface, the parent @@ -15566,7 +17933,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true and `ip` is an IP address. """ - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_in: str | None = None """ Name of the IPv4 access-list to be assigned in the ingress direction. The access-list must be defined under `ipv4_acls` @@ -15574,7 +17941,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Required for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under `wan_carriers`. """ - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_out: str | None = None """ Name of the IPv4 Access-list to be assigned in the egress direction. The access-list must be defined under `ipv4_acls` @@ -15592,7 +17959,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Unless the carrier is marked as 'trusted' under `wan_carriers`, `ipv4_acl_in` is also required on all WAN interfaces. """ - wan_circuit_id: Annotated[str, ConvertTypes[int]] | None = None + wan_circuit_id: str | None = None """ The WAN circuit ID for this interface. This is not rendered in the configuration but used for WAN designs. @@ -15611,7 +17978,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): def __init__( self, profile: str | None = None, - name: Annotated[str, Pattern["Ethernet[\d/]+(.[\d]+)?"]] = None, + name: Annotated[str, Pattern[r"Ethernet[\d/]+(.[\d]+)?"]] = None, description: str | None = None, ip_address: str | None = None, dhcp_ip: str | None = None, @@ -15623,12 +17990,12 @@ def __init__( peer: str | None = None, peer_interface: str | None = None, peer_ip: str | None = None, - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None, - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None, + ipv4_acl_in: str | None = None, + ipv4_acl_out: str | None = None, static_routes: list[StaticRoutesItem] | None = None, qos_profile: str | None = None, wan_carrier: str | None = None, - wan_circuit_id: Annotated[str, ConvertTypes[int]] | None = None, + wan_circuit_id: str | None = None, connected_to_pathfinder: bool | None = True, cv_pathfinder_internet_exit: CvPathfinderInternetExit | None = None, raw_eos_cli: str | None = None, @@ -15733,7 +18100,7 @@ def __init__( id: int | None = None """Unique identifier used for IP addressing and other algorithms.""" - platform: Annotated[str, ConvertTypes[int]] | None = None + platform: str | None = None """Arista platform family.""" mac_address: str | None = None """Leverage to document management interface mac address.""" @@ -15791,7 +18158,7 @@ def __init__( """EOS CLI rendered directly on the root level of the final EOS configuration.""" structured_config: StructuredConfig | None = None """Custom structured config for eos_cli_config_gen.""" - uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None = "p2p" + uplink_type: Annotated[str, ValidValues["p2p", "port-channel", "p2p-vrfs", "lan"]] | None = "p2p" """ Override the default `uplink_type` set at the `node_type_key` level. `uplink_type` must be "p2p" if `vtep` or @@ -15799,7 +18166,7 @@ def __init__( """ uplink_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None """IPv4 subnet to use to connect to uplink switches.""" - uplink_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + uplink_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """ Local uplink interfaces. Each list item supports range syntax that can be expanded into a list of interfaces. @@ -15807,7 +18174,7 @@ def __init__( uplink_interfaces is not defined, platform-specific defaults (defined under default_interfaces) will be used instead. Please note that default_interfaces are not defined by default, you should define these yourself. """ - uplink_switch_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + uplink_switch_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """Interfaces located on uplink switches.""" uplink_switches: list[str] | None = None uplink_interface_speed: str | None = None @@ -15938,11 +18305,11 @@ def __init__( automatically using a hash of configuration elements. < 0000:0000:0000 | auto >. """ - isis_system_id_prefix: Annotated[str, Pattern["[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None + isis_system_id_prefix: Annotated[str, Pattern[r"[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None """(4.4 hexadecimal).""" isis_maximum_paths: int | None = None """Number of path to configure in ECMP for ISIS.""" - is_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2" + is_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2" node_sid_base: int | None = 0 """Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID.""" loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None @@ -15973,9 +18340,9 @@ def __init__( Overrides VTEP setting inherited from node_type_keys. """ - vtep_loopback: Annotated[str, Pattern["Loopback[\d/]+"]] | None = None + vtep_loopback: Annotated[str, Pattern[r"Loopback[\d/]+"]] | None = None """Set VXLAN source interface.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None + bgp_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -15984,7 +18351,7 @@ def __init__( """ bgp_defaults: list[str] | None = None """List of EOS commands to apply to BGP daemon.""" - evpn_role: Literal["client", "server", "none"] | None = None + evpn_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None """ Acting role in EVPN control plane. Default is set in node_type definition from node_type_keys. @@ -16061,7 +18428,7 @@ def __init__( mlag_peer_vlan: int | None = 4094 """MLAG Peer Link (control link) SVI interface id.""" mlag_peer_link_allowed_vlans: str | None = None - mlag_peer_address_family: Literal["ipv4", "ipv6"] | None = "ipv4" + mlag_peer_address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = "ipv4" """ IP address family used to establish MLAG Peer Link (control link). `ipv6` requires EOS version 4.31.1F or higher. @@ -16088,7 +18455,7 @@ def __init__( """ mlag_domain_id: str | None = None """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" - spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None = None + spanning_tree_mode: Annotated[str, ValidValues["mstp", "rstp", "rapid-pvst", "none"]] | None = None spanning_tree_priority: int | None = 32768 """ Spanning-tree priority configured for the selected mode. @@ -16222,7 +18589,7 @@ def __init__( automatically affect any parent/child devices configuration, so it must be set on each applicable node/node-group/node- type as needed. """ - inband_mgmt_vrf: Annotated[str, ConvertTypes[int]] | None = "default" + inband_mgmt_vrf: str | None = "default" """ VRF configured on the Inband Management Interface. The VRF is created if not already created by other means. @@ -16280,19 +18647,19 @@ def __init__( When using 'inband_mgmt_ip' the VLAN and SVI will only be created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be created using network services data models. """ - mpls_overlay_role: Literal["client", "server", "none"] | None = None + mpls_overlay_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None """ Set the default mpls overlay role. Acting role in overlay control plane. """ - overlay_address_families: list[str] | None = None + overlay_address_families: list[Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None """Set the default overlay address families.""" mpls_route_reflectors: list[str] | None = None """List of inventory hostname acting as MPLS route-reflectors.""" - bgp_cluster_id: Annotated[str, ConvertTypes[int]] | None = None + bgp_cluster_id: str | None = None """Set BGP cluster id.""" ptp: Ptp | None = None - wan_role: Literal["client", "server"] | None = None + wan_role: Annotated[str, ValidValues["client", "server"]] | None = None """ Override the default WAN role. @@ -16304,7 +18671,7 @@ def __init__( Only supported if `overlay_routing_protocol` is set to `ibgp`. """ - cv_pathfinder_transit_mode: Literal["region", "zone"] | None = None + cv_pathfinder_transit_mode: Annotated[str, ValidValues["region", "zone"]] | None = None """ Configure the transit mode for a WAN client for CV Pathfinder designs only when the `wan_mode` root key is set to @@ -16339,7 +18706,7 @@ def __init__( Maximum 2 devices supported by group for HA. """ - dps_mss_ipv4: Annotated[str, ConvertTypes[int]] | None = "auto" + dps_mss_ipv4: str | None = "auto" """IPv4 MSS value configured under "router path-selection" on WAN Devices.""" l3_interfaces: list[L3InterfacesItem] | None = None """ @@ -16352,7 +18719,7 @@ def __init__( This setting is useful on virtual Route Reflectors and Pathfinders where more CPU cores should be allocated for control plane. """ - flow_tracker_type: Literal["sampled", "hardware"] | None = None + flow_tracker_type: Annotated[str, ValidValues["sampled", "hardware"]] | None = None """ Set the flow tracker type. Override the `default_flow_tracker_type`` set at the `node_type_key` level. @@ -16362,7 +18729,7 @@ def __init__( def __init__( self, id: int | None = None, - platform: Annotated[str, ConvertTypes[int]] | None = None, + platform: str | None = None, mac_address: str | None = None, system_mac_address: str | None = None, serial_number: str | None = None, @@ -16377,10 +18744,10 @@ def __init__( always_configure_ip_routing: bool | None = False, raw_eos_cli: str | None = None, structured_config: StructuredConfig | None = None, - uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None = "p2p", + uplink_type: Annotated[str, ValidValues["p2p", "port-channel", "p2p-vrfs", "lan"]] | None = "p2p", uplink_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, - uplink_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, - uplink_switch_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, + uplink_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, + uplink_switch_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, uplink_switches: list[str] | None = None, uplink_interface_speed: str | None = None, uplink_switch_interface_speed: str | None = None, @@ -16398,9 +18765,9 @@ def __init__( mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | None = None, mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | None = None, short_esi: str | None = None, - isis_system_id_prefix: Annotated[str, Pattern["[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None, + isis_system_id_prefix: Annotated[str, Pattern[r"[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None, isis_maximum_paths: int | None = None, - is_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2", + is_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2", node_sid_base: int | None = 0, loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, vtep_loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, @@ -16408,10 +18775,10 @@ def __init__( loopback_ipv6_pool: Annotated[str, Format["ipv6_cidr"]] | None = None, loopback_ipv6_offset: int | None = 0, vtep: bool | None = None, - vtep_loopback: Annotated[str, Pattern["Loopback[\d/]+"]] | None = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None, + vtep_loopback: Annotated[str, Pattern[r"Loopback[\d/]+"]] | None = None, + bgp_as: str | None = None, bgp_defaults: list[str] | None = None, - evpn_role: Literal["client", "server", "none"] | None = None, + evpn_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None, evpn_route_servers: list[str] | None = None, evpn_services_l2_only: bool | None = False, filter: Filter | None = None, @@ -16427,12 +18794,12 @@ def __init__( mlag_peer_l3_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, mlag_peer_vlan: int | None = 4094, mlag_peer_link_allowed_vlans: str | None = None, - mlag_peer_address_family: Literal["ipv4", "ipv6"] | None = "ipv4", + mlag_peer_address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = "ipv4", mlag_peer_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, mlag_peer_ipv6_pool: Annotated[str, Format["ipv6_cidr"]] | None = None, mlag_port_channel_id: int | None = None, mlag_domain_id: str | None = None, - spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None = None, + spanning_tree_mode: Annotated[str, ValidValues["mstp", "rstp", "rapid-pvst", "none"]] | None = None, spanning_tree_priority: int | None = 32768, spanning_tree_root_super: bool | None = False, virtual_router_mac_address: Annotated[str, Format["mac"]] | None = None, @@ -16446,26 +18813,26 @@ def __init__( inband_mgmt_ipv6_gateway: Annotated[str, Format["ipv6"]] | None = None, inband_mgmt_description: str | None = "Inband Management", inband_mgmt_vlan_name: str | None = "Inband Management", - inband_mgmt_vrf: Annotated[str, ConvertTypes[int]] | None = "default", + inband_mgmt_vrf: str | None = "default", inband_mgmt_mtu: int | None = 1500, inband_ztp: bool | None = False, inband_ztp_lacp_fallback_delay: int | None = 30, inband_management_subnet: Annotated[str, Format["ipv4_cidr"]] | None = None, inband_management_vlan: int | None = 4092, - mpls_overlay_role: Literal["client", "server", "none"] | None = None, - overlay_address_families: list[str] | None = None, + mpls_overlay_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None, + overlay_address_families: list[Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None, mpls_route_reflectors: list[str] | None = None, - bgp_cluster_id: Annotated[str, ConvertTypes[int]] | None = None, + bgp_cluster_id: str | None = None, ptp: Ptp | None = None, - wan_role: Literal["client", "server"] | None = None, - cv_pathfinder_transit_mode: Literal["region", "zone"] | None = None, + wan_role: Annotated[str, ValidValues["client", "server"]] | None = None, + cv_pathfinder_transit_mode: Annotated[str, ValidValues["region", "zone"]] | None = None, cv_pathfinder_region: str | None = None, cv_pathfinder_site: str | None = None, wan_ha: WanHa | None = None, - dps_mss_ipv4: Annotated[str, ConvertTypes[int]] | None = "auto", + dps_mss_ipv4: str | None = "auto", l3_interfaces: list[L3InterfacesItem] | None = None, data_plane_cpu_allocation_max: int | None = None, - flow_tracker_type: Literal["sampled", "hardware"] | None = None, + flow_tracker_type: Annotated[str, ValidValues["sampled", "hardware"]] | None = None, **kwargs, ): """ @@ -17193,13 +19560,13 @@ class Filter(AvdDictBaseModel): """ tags: list[str] | None = ["all"] """Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default).""" - allow_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"] + allow_vrfs: list[str] | None = ["all"] """ Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs (default). This list also limits VRFs included by `always_include_vrfs_in_tenants`. """ - deny_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"] + deny_vrfs: list[str] | None = ["all"] """ Prevent configuration of Network Services defined under these VRFs. This list prevents the given VRFs to be included by @@ -17223,8 +19590,8 @@ def __init__( self, tenants: list[str] | None = ["all"], tags: list[str] | None = ["all"], - allow_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"], - deny_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"], + allow_vrfs: list[str] | None = ["all"], + deny_vrfs: list[str] | None = ["all"], always_include_vrfs_in_tenants: list[str] | None = None, only_vlans_in_use: bool | None = False, **kwargs, @@ -17270,7 +19637,7 @@ class RemotePeersItem(AvdDictBaseModel): """Hostname of remote EVPN GW server.""" ip_address: Annotated[str, Format["ipv4"]] | None = None """Peering IP of remote Route Server.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None + bgp_as: str | None = None """ Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in @@ -17281,7 +19648,7 @@ def __init__( self, hostname: str | None = None, ip_address: Annotated[str, Format["ipv4"]] | None = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None, + bgp_as: str | None = None, **kwargs, ): """ @@ -17369,20 +19736,14 @@ class RemotePeersItem(AvdDictBaseModel): """Hostname of remote IPVPN Peer.""" ip_address: Annotated[str, Format["ipv4"]] = None """Peering IP of remote IPVPN Peer.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] = None + bgp_as: str = None """ Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float number. """ - def __init__( - self, - hostname: str = None, - ip_address: Annotated[str, Format["ipv4"]] = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] = None, - **kwargs, - ): + def __init__(self, hostname: str = None, ip_address: Annotated[str, Format["ipv4"]] = None, bgp_as: str = None, **kwargs): """ Args: ----- @@ -17408,7 +19769,7 @@ def __init__( """Enable D-path for use with BGP bestpath selection algorithm.""" maximum_routes: int | None = 0 """Maximum routes to accept from IPVPN remote peers.""" - local_as: Annotated[str, ConvertTypes[int]] | None = "none" + local_as: str | None = "none" """ Local BGP AS applied to peering with IPVPN remote peers. BGP AS <1-4294967295> or AS number in asdot notation @@ -17427,7 +19788,7 @@ def __init__( ipvpn_domain_id: str | None = "65535:2", enable_d_path: bool | None = True, maximum_routes: int | None = 0, - local_as: Annotated[str, ConvertTypes[int]] | None = "none", + local_as: str | None = "none", address_families: list[str] | None = ["vpn-ipv4"], remote_peers: list[RemotePeersItem] | None = None, **kwargs, @@ -17608,7 +19969,7 @@ def __init__( return super().__init__(**kwargs) enabled: bool | None = False - profile: Literal["aes67", "smpte2059-2", "aes67-r16-2016"] | None = "aes67-r16-2016" + profile: Annotated[str, ValidValues["aes67", "smpte2059-2", "aes67-r16-2016"]] | None = "aes67-r16-2016" mlag: bool | None = False """ Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be configured on the MLAG @@ -17641,7 +20002,7 @@ def __init__( the recommended behaviour. This can be set manually if required, for example, to a value of "10.1.2.3". """ - mode: Literal["boundary"] | None = "boundary" + mode: Annotated[str, ValidValues["boundary"]] | None = "boundary" mode_one_step: bool | None = False ttl: int | None = None forward_unicast: bool | None = False @@ -17652,7 +20013,7 @@ def __init__( def __init__( self, enabled: bool | None = False, - profile: Literal["aes67", "smpte2059-2", "aes67-r16-2016"] | None = "aes67-r16-2016", + profile: Annotated[str, ValidValues["aes67", "smpte2059-2", "aes67-r16-2016"]] | None = "aes67-r16-2016", mlag: bool | None = False, domain: int | None = 127, priority1: int | None = None, @@ -17661,7 +20022,7 @@ def __init__( clock_identity_prefix: str | None = None, clock_identity: str | None = None, source_ip: str | None = None, - mode: Literal["boundary"] | None = "boundary", + mode: Annotated[str, ValidValues["boundary"]] | None = "boundary", mode_one_step: bool | None = False, ttl: int | None = None, forward_unicast: bool | None = False, @@ -17743,7 +20104,7 @@ def __init__(self, enabled: bool | None = None, name: str | None = None, **kwarg """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" ipsec: bool | None = True """Enable / Disable IPsec over HA path-group when HA is enabled.""" - ha_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + ha_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """ Local WAN HA interfaces Overwrite the default behavior which is to pick all the `uplink_interfaces`. @@ -17772,7 +20133,7 @@ def __init__( self, enabled: bool | None = True, ipsec: bool | None = True, - ha_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, + ha_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, ha_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, max_ha_interfaces: int | None = None, flow_tracking: FlowTracking | None = None, @@ -17886,7 +20247,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): profile: str | None = None """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" - name: Annotated[str, Pattern["Ethernet[\d/]+(.[\d]+)?"]] = None + name: Annotated[str, Pattern[r"Ethernet[\d/]+(.[\d]+)?"]] = None """ Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. For a subinterface, the parent @@ -17940,7 +20301,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true and `ip` is an IP address. """ - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_in: str | None = None """ Name of the IPv4 access-list to be assigned in the ingress direction. The access-list must be defined under `ipv4_acls` @@ -17948,7 +20309,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Required for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under `wan_carriers`. """ - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_out: str | None = None """ Name of the IPv4 Access-list to be assigned in the egress direction. The access-list must be defined under `ipv4_acls` @@ -17966,7 +20327,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Unless the carrier is marked as 'trusted' under `wan_carriers`, `ipv4_acl_in` is also required on all WAN interfaces. """ - wan_circuit_id: Annotated[str, ConvertTypes[int]] | None = None + wan_circuit_id: str | None = None """ The WAN circuit ID for this interface. This is not rendered in the configuration but used for WAN designs. @@ -17985,7 +20346,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): def __init__( self, profile: str | None = None, - name: Annotated[str, Pattern["Ethernet[\d/]+(.[\d]+)?"]] = None, + name: Annotated[str, Pattern[r"Ethernet[\d/]+(.[\d]+)?"]] = None, description: str | None = None, ip_address: str | None = None, dhcp_ip: str | None = None, @@ -17997,12 +20358,12 @@ def __init__( peer: str | None = None, peer_interface: str | None = None, peer_ip: str | None = None, - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None, - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None, + ipv4_acl_in: str | None = None, + ipv4_acl_out: str | None = None, static_routes: list[StaticRoutesItem] | None = None, qos_profile: str | None = None, wan_carrier: str | None = None, - wan_circuit_id: Annotated[str, ConvertTypes[int]] | None = None, + wan_circuit_id: str | None = None, connected_to_pathfinder: bool | None = True, cv_pathfinder_internet_exit: CvPathfinderInternetExit | None = None, raw_eos_cli: str | None = None, @@ -18114,7 +20475,7 @@ def __init__( """ id: int | None = None """Unique identifier used for IP addressing and other algorithms.""" - platform: Annotated[str, ConvertTypes[int]] | None = None + platform: str | None = None """Arista platform family.""" mac_address: str | None = None """Leverage to document management interface mac address.""" @@ -18172,7 +20533,7 @@ def __init__( """EOS CLI rendered directly on the root level of the final EOS configuration.""" structured_config: StructuredConfig | None = None """Custom structured config for eos_cli_config_gen.""" - uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None = "p2p" + uplink_type: Annotated[str, ValidValues["p2p", "port-channel", "p2p-vrfs", "lan"]] | None = "p2p" """ Override the default `uplink_type` set at the `node_type_key` level. `uplink_type` must be "p2p" if `vtep` or @@ -18180,7 +20541,7 @@ def __init__( """ uplink_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None """IPv4 subnet to use to connect to uplink switches.""" - uplink_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + uplink_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """ Local uplink interfaces. Each list item supports range syntax that can be expanded into a list of interfaces. @@ -18188,7 +20549,7 @@ def __init__( uplink_interfaces is not defined, platform-specific defaults (defined under default_interfaces) will be used instead. Please note that default_interfaces are not defined by default, you should define these yourself. """ - uplink_switch_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + uplink_switch_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """Interfaces located on uplink switches.""" uplink_switches: list[str] | None = None uplink_interface_speed: str | None = None @@ -18319,11 +20680,11 @@ def __init__( automatically using a hash of configuration elements. < 0000:0000:0000 | auto >. """ - isis_system_id_prefix: Annotated[str, Pattern["[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None + isis_system_id_prefix: Annotated[str, Pattern[r"[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None """(4.4 hexadecimal).""" isis_maximum_paths: int | None = None """Number of path to configure in ECMP for ISIS.""" - is_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2" + is_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2" node_sid_base: int | None = 0 """Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID.""" loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None @@ -18354,9 +20715,9 @@ def __init__( Overrides VTEP setting inherited from node_type_keys. """ - vtep_loopback: Annotated[str, Pattern["Loopback[\d/]+"]] | None = None + vtep_loopback: Annotated[str, Pattern[r"Loopback[\d/]+"]] | None = None """Set VXLAN source interface.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None + bgp_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -18365,7 +20726,7 @@ def __init__( """ bgp_defaults: list[str] | None = None """List of EOS commands to apply to BGP daemon.""" - evpn_role: Literal["client", "server", "none"] | None = None + evpn_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None """ Acting role in EVPN control plane. Default is set in node_type definition from node_type_keys. @@ -18442,7 +20803,7 @@ def __init__( mlag_peer_vlan: int | None = 4094 """MLAG Peer Link (control link) SVI interface id.""" mlag_peer_link_allowed_vlans: str | None = None - mlag_peer_address_family: Literal["ipv4", "ipv6"] | None = "ipv4" + mlag_peer_address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = "ipv4" """ IP address family used to establish MLAG Peer Link (control link). `ipv6` requires EOS version 4.31.1F or higher. @@ -18469,7 +20830,7 @@ def __init__( """ mlag_domain_id: str | None = None """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" - spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None = None + spanning_tree_mode: Annotated[str, ValidValues["mstp", "rstp", "rapid-pvst", "none"]] | None = None spanning_tree_priority: int | None = 32768 """ Spanning-tree priority configured for the selected mode. @@ -18603,7 +20964,7 @@ def __init__( automatically affect any parent/child devices configuration, so it must be set on each applicable node/node-group/node- type as needed. """ - inband_mgmt_vrf: Annotated[str, ConvertTypes[int]] | None = "default" + inband_mgmt_vrf: str | None = "default" """ VRF configured on the Inband Management Interface. The VRF is created if not already created by other means. @@ -18661,19 +21022,19 @@ def __init__( When using 'inband_mgmt_ip' the VLAN and SVI will only be created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be created using network services data models. """ - mpls_overlay_role: Literal["client", "server", "none"] | None = None + mpls_overlay_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None """ Set the default mpls overlay role. Acting role in overlay control plane. """ - overlay_address_families: list[str] | None = None + overlay_address_families: list[Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None """Set the default overlay address families.""" mpls_route_reflectors: list[str] | None = None """List of inventory hostname acting as MPLS route-reflectors.""" - bgp_cluster_id: Annotated[str, ConvertTypes[int]] | None = None + bgp_cluster_id: str | None = None """Set BGP cluster id.""" ptp: Ptp | None = None - wan_role: Literal["client", "server"] | None = None + wan_role: Annotated[str, ValidValues["client", "server"]] | None = None """ Override the default WAN role. @@ -18685,7 +21046,7 @@ def __init__( Only supported if `overlay_routing_protocol` is set to `ibgp`. """ - cv_pathfinder_transit_mode: Literal["region", "zone"] | None = None + cv_pathfinder_transit_mode: Annotated[str, ValidValues["region", "zone"]] | None = None """ Configure the transit mode for a WAN client for CV Pathfinder designs only when the `wan_mode` root key is set to @@ -18720,7 +21081,7 @@ def __init__( Maximum 2 devices supported by group for HA. """ - dps_mss_ipv4: Annotated[str, ConvertTypes[int]] | None = "auto" + dps_mss_ipv4: str | None = "auto" """IPv4 MSS value configured under "router path-selection" on WAN Devices.""" l3_interfaces: list[L3InterfacesItem] | None = None """ @@ -18733,7 +21094,7 @@ def __init__( This setting is useful on virtual Route Reflectors and Pathfinders where more CPU cores should be allocated for control plane. """ - flow_tracker_type: Literal["sampled", "hardware"] | None = None + flow_tracker_type: Annotated[str, ValidValues["sampled", "hardware"]] | None = None """ Set the flow tracker type. Override the `default_flow_tracker_type`` set at the `node_type_key` level. @@ -18745,7 +21106,7 @@ def __init__( name: str = None, downlink_pools: list[DownlinkPoolsItem] | None = None, id: int | None = None, - platform: Annotated[str, ConvertTypes[int]] | None = None, + platform: str | None = None, mac_address: str | None = None, system_mac_address: str | None = None, serial_number: str | None = None, @@ -18760,10 +21121,10 @@ def __init__( always_configure_ip_routing: bool | None = False, raw_eos_cli: str | None = None, structured_config: StructuredConfig | None = None, - uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None = "p2p", + uplink_type: Annotated[str, ValidValues["p2p", "port-channel", "p2p-vrfs", "lan"]] | None = "p2p", uplink_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, - uplink_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, - uplink_switch_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, + uplink_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, + uplink_switch_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, uplink_switches: list[str] | None = None, uplink_interface_speed: str | None = None, uplink_switch_interface_speed: str | None = None, @@ -18781,9 +21142,9 @@ def __init__( mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | None = None, mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | None = None, short_esi: str | None = None, - isis_system_id_prefix: Annotated[str, Pattern["[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None, + isis_system_id_prefix: Annotated[str, Pattern[r"[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None, isis_maximum_paths: int | None = None, - is_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2", + is_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2", node_sid_base: int | None = 0, loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, vtep_loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, @@ -18791,10 +21152,10 @@ def __init__( loopback_ipv6_pool: Annotated[str, Format["ipv6_cidr"]] | None = None, loopback_ipv6_offset: int | None = 0, vtep: bool | None = None, - vtep_loopback: Annotated[str, Pattern["Loopback[\d/]+"]] | None = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None, + vtep_loopback: Annotated[str, Pattern[r"Loopback[\d/]+"]] | None = None, + bgp_as: str | None = None, bgp_defaults: list[str] | None = None, - evpn_role: Literal["client", "server", "none"] | None = None, + evpn_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None, evpn_route_servers: list[str] | None = None, evpn_services_l2_only: bool | None = False, filter: Filter | None = None, @@ -18810,12 +21171,12 @@ def __init__( mlag_peer_l3_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, mlag_peer_vlan: int | None = 4094, mlag_peer_link_allowed_vlans: str | None = None, - mlag_peer_address_family: Literal["ipv4", "ipv6"] | None = "ipv4", + mlag_peer_address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = "ipv4", mlag_peer_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, mlag_peer_ipv6_pool: Annotated[str, Format["ipv6_cidr"]] | None = None, mlag_port_channel_id: int | None = None, mlag_domain_id: str | None = None, - spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None = None, + spanning_tree_mode: Annotated[str, ValidValues["mstp", "rstp", "rapid-pvst", "none"]] | None = None, spanning_tree_priority: int | None = 32768, spanning_tree_root_super: bool | None = False, virtual_router_mac_address: Annotated[str, Format["mac"]] | None = None, @@ -18829,26 +21190,26 @@ def __init__( inband_mgmt_ipv6_gateway: Annotated[str, Format["ipv6"]] | None = None, inband_mgmt_description: str | None = "Inband Management", inband_mgmt_vlan_name: str | None = "Inband Management", - inband_mgmt_vrf: Annotated[str, ConvertTypes[int]] | None = "default", + inband_mgmt_vrf: str | None = "default", inband_mgmt_mtu: int | None = 1500, inband_ztp: bool | None = False, inband_ztp_lacp_fallback_delay: int | None = 30, inband_management_subnet: Annotated[str, Format["ipv4_cidr"]] | None = None, inband_management_vlan: int | None = 4092, - mpls_overlay_role: Literal["client", "server", "none"] | None = None, - overlay_address_families: list[str] | None = None, + mpls_overlay_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None, + overlay_address_families: list[Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None, mpls_route_reflectors: list[str] | None = None, - bgp_cluster_id: Annotated[str, ConvertTypes[int]] | None = None, + bgp_cluster_id: str | None = None, ptp: Ptp | None = None, - wan_role: Literal["client", "server"] | None = None, - cv_pathfinder_transit_mode: Literal["region", "zone"] | None = None, + wan_role: Annotated[str, ValidValues["client", "server"]] | None = None, + cv_pathfinder_transit_mode: Annotated[str, ValidValues["region", "zone"]] | None = None, cv_pathfinder_region: str | None = None, cv_pathfinder_site: str | None = None, wan_ha: WanHa | None = None, - dps_mss_ipv4: Annotated[str, ConvertTypes[int]] | None = "auto", + dps_mss_ipv4: str | None = "auto", l3_interfaces: list[L3InterfacesItem] | None = None, data_plane_cpu_allocation_max: int | None = None, - flow_tracker_type: Literal["sampled", "hardware"] | None = None, + flow_tracker_type: Annotated[str, ValidValues["sampled", "hardware"]] | None = None, **kwargs, ): """ @@ -19555,13 +21916,13 @@ class Filter(AvdDictBaseModel): """ tags: list[str] | None = ["all"] """Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default).""" - allow_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"] + allow_vrfs: list[str] | None = ["all"] """ Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs (default). This list also limits VRFs included by `always_include_vrfs_in_tenants`. """ - deny_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"] + deny_vrfs: list[str] | None = ["all"] """ Prevent configuration of Network Services defined under these VRFs. This list prevents the given VRFs to be included by @@ -19585,8 +21946,8 @@ def __init__( self, tenants: list[str] | None = ["all"], tags: list[str] | None = ["all"], - allow_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"], - deny_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"], + allow_vrfs: list[str] | None = ["all"], + deny_vrfs: list[str] | None = ["all"], always_include_vrfs_in_tenants: list[str] | None = None, only_vlans_in_use: bool | None = False, **kwargs, @@ -19632,7 +21993,7 @@ class RemotePeersItem(AvdDictBaseModel): """Hostname of remote EVPN GW server.""" ip_address: Annotated[str, Format["ipv4"]] | None = None """Peering IP of remote Route Server.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None + bgp_as: str | None = None """ Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in @@ -19640,11 +22001,7 @@ class RemotePeersItem(AvdDictBaseModel): """ def __init__( - self, - hostname: str | None = None, - ip_address: Annotated[str, Format["ipv4"]] | None = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None, - **kwargs, + self, hostname: str | None = None, ip_address: Annotated[str, Format["ipv4"]] | None = None, bgp_as: str | None = None, **kwargs ): """ Args: @@ -19731,20 +22088,14 @@ class RemotePeersItem(AvdDictBaseModel): """Hostname of remote IPVPN Peer.""" ip_address: Annotated[str, Format["ipv4"]] = None """Peering IP of remote IPVPN Peer.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] = None + bgp_as: str = None """ Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float number. """ - def __init__( - self, - hostname: str = None, - ip_address: Annotated[str, Format["ipv4"]] = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] = None, - **kwargs, - ): + def __init__(self, hostname: str = None, ip_address: Annotated[str, Format["ipv4"]] = None, bgp_as: str = None, **kwargs): """ Args: ----- @@ -19770,7 +22121,7 @@ def __init__( """Enable D-path for use with BGP bestpath selection algorithm.""" maximum_routes: int | None = 0 """Maximum routes to accept from IPVPN remote peers.""" - local_as: Annotated[str, ConvertTypes[int]] | None = "none" + local_as: str | None = "none" """ Local BGP AS applied to peering with IPVPN remote peers. BGP AS <1-4294967295> or AS number in asdot notation @@ -19789,7 +22140,7 @@ def __init__( ipvpn_domain_id: str | None = "65535:2", enable_d_path: bool | None = True, maximum_routes: int | None = 0, - local_as: Annotated[str, ConvertTypes[int]] | None = "none", + local_as: str | None = "none", address_families: list[str] | None = ["vpn-ipv4"], remote_peers: list[RemotePeersItem] | None = None, **kwargs, @@ -19966,7 +22317,7 @@ def __init__( return super().__init__(**kwargs) enabled: bool | None = False - profile: Literal["aes67", "smpte2059-2", "aes67-r16-2016"] | None = "aes67-r16-2016" + profile: Annotated[str, ValidValues["aes67", "smpte2059-2", "aes67-r16-2016"]] | None = "aes67-r16-2016" mlag: bool | None = False """ Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be configured on the MLAG @@ -19999,7 +22350,7 @@ def __init__( the recommended behaviour. This can be set manually if required, for example, to a value of "10.1.2.3". """ - mode: Literal["boundary"] | None = "boundary" + mode: Annotated[str, ValidValues["boundary"]] | None = "boundary" mode_one_step: bool | None = False ttl: int | None = None forward_unicast: bool | None = False @@ -20010,7 +22361,7 @@ def __init__( def __init__( self, enabled: bool | None = False, - profile: Literal["aes67", "smpte2059-2", "aes67-r16-2016"] | None = "aes67-r16-2016", + profile: Annotated[str, ValidValues["aes67", "smpte2059-2", "aes67-r16-2016"]] | None = "aes67-r16-2016", mlag: bool | None = False, domain: int | None = 127, priority1: int | None = None, @@ -20019,7 +22370,7 @@ def __init__( clock_identity_prefix: str | None = None, clock_identity: str | None = None, source_ip: str | None = None, - mode: Literal["boundary"] | None = "boundary", + mode: Annotated[str, ValidValues["boundary"]] | None = "boundary", mode_one_step: bool | None = False, ttl: int | None = None, forward_unicast: bool | None = False, @@ -20101,7 +22452,7 @@ def __init__(self, enabled: bool | None = None, name: str | None = None, **kwarg """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" ipsec: bool | None = True """Enable / Disable IPsec over HA path-group when HA is enabled.""" - ha_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + ha_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """ Local WAN HA interfaces Overwrite the default behavior which is to pick all the `uplink_interfaces`. @@ -20130,7 +22481,7 @@ def __init__( self, enabled: bool | None = True, ipsec: bool | None = True, - ha_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, + ha_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, ha_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, max_ha_interfaces: int | None = None, flow_tracking: FlowTracking | None = None, @@ -20244,7 +22595,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): profile: str | None = None """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" - name: Annotated[str, Pattern["Ethernet[\d/]+(.[\d]+)?"]] = None + name: Annotated[str, Pattern[r"Ethernet[\d/]+(.[\d]+)?"]] = None """ Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. For a subinterface, the parent @@ -20298,7 +22649,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true and `ip` is an IP address. """ - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_in: str | None = None """ Name of the IPv4 access-list to be assigned in the ingress direction. The access-list must be defined under `ipv4_acls` @@ -20306,7 +22657,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Required for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under `wan_carriers`. """ - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_out: str | None = None """ Name of the IPv4 Access-list to be assigned in the egress direction. The access-list must be defined under `ipv4_acls` @@ -20324,7 +22675,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Unless the carrier is marked as 'trusted' under `wan_carriers`, `ipv4_acl_in` is also required on all WAN interfaces. """ - wan_circuit_id: Annotated[str, ConvertTypes[int]] | None = None + wan_circuit_id: str | None = None """ The WAN circuit ID for this interface. This is not rendered in the configuration but used for WAN designs. @@ -20343,7 +22694,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): def __init__( self, profile: str | None = None, - name: Annotated[str, Pattern["Ethernet[\d/]+(.[\d]+)?"]] = None, + name: Annotated[str, Pattern[r"Ethernet[\d/]+(.[\d]+)?"]] = None, description: str | None = None, ip_address: str | None = None, dhcp_ip: str | None = None, @@ -20355,12 +22706,12 @@ def __init__( peer: str | None = None, peer_interface: str | None = None, peer_ip: str | None = None, - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None, - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None, + ipv4_acl_in: str | None = None, + ipv4_acl_out: str | None = None, static_routes: list[StaticRoutesItem] | None = None, qos_profile: str | None = None, wan_carrier: str | None = None, - wan_circuit_id: Annotated[str, ConvertTypes[int]] | None = None, + wan_circuit_id: str | None = None, connected_to_pathfinder: bool | None = True, cv_pathfinder_internet_exit: CvPathfinderInternetExit | None = None, raw_eos_cli: str | None = None, @@ -20473,7 +22824,7 @@ def __init__( """Define variables per node.""" id: int | None = None """Unique identifier used for IP addressing and other algorithms.""" - platform: Annotated[str, ConvertTypes[int]] | None = None + platform: str | None = None """Arista platform family.""" mac_address: str | None = None """Leverage to document management interface mac address.""" @@ -20531,7 +22882,7 @@ def __init__( """EOS CLI rendered directly on the root level of the final EOS configuration.""" structured_config: StructuredConfig | None = None """Custom structured config for eos_cli_config_gen.""" - uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None = "p2p" + uplink_type: Annotated[str, ValidValues["p2p", "port-channel", "p2p-vrfs", "lan"]] | None = "p2p" """ Override the default `uplink_type` set at the `node_type_key` level. `uplink_type` must be "p2p" if `vtep` or @@ -20539,7 +22890,7 @@ def __init__( """ uplink_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None """IPv4 subnet to use to connect to uplink switches.""" - uplink_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + uplink_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """ Local uplink interfaces. Each list item supports range syntax that can be expanded into a list of interfaces. @@ -20547,7 +22898,7 @@ def __init__( uplink_interfaces is not defined, platform-specific defaults (defined under default_interfaces) will be used instead. Please note that default_interfaces are not defined by default, you should define these yourself. """ - uplink_switch_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + uplink_switch_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """Interfaces located on uplink switches.""" uplink_switches: list[str] | None = None uplink_interface_speed: str | None = None @@ -20678,11 +23029,11 @@ def __init__( automatically using a hash of configuration elements. < 0000:0000:0000 | auto >. """ - isis_system_id_prefix: Annotated[str, Pattern["[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None + isis_system_id_prefix: Annotated[str, Pattern[r"[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None """(4.4 hexadecimal).""" isis_maximum_paths: int | None = None """Number of path to configure in ECMP for ISIS.""" - is_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2" + is_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2" node_sid_base: int | None = 0 """Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID.""" loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None @@ -20713,9 +23064,9 @@ def __init__( Overrides VTEP setting inherited from node_type_keys. """ - vtep_loopback: Annotated[str, Pattern["Loopback[\d/]+"]] | None = None + vtep_loopback: Annotated[str, Pattern[r"Loopback[\d/]+"]] | None = None """Set VXLAN source interface.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None + bgp_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -20724,7 +23075,7 @@ def __init__( """ bgp_defaults: list[str] | None = None """List of EOS commands to apply to BGP daemon.""" - evpn_role: Literal["client", "server", "none"] | None = None + evpn_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None """ Acting role in EVPN control plane. Default is set in node_type definition from node_type_keys. @@ -20801,7 +23152,7 @@ def __init__( mlag_peer_vlan: int | None = 4094 """MLAG Peer Link (control link) SVI interface id.""" mlag_peer_link_allowed_vlans: str | None = None - mlag_peer_address_family: Literal["ipv4", "ipv6"] | None = "ipv4" + mlag_peer_address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = "ipv4" """ IP address family used to establish MLAG Peer Link (control link). `ipv6` requires EOS version 4.31.1F or higher. @@ -20828,7 +23179,7 @@ def __init__( """ mlag_domain_id: str | None = None """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" - spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None = None + spanning_tree_mode: Annotated[str, ValidValues["mstp", "rstp", "rapid-pvst", "none"]] | None = None spanning_tree_priority: int | None = 32768 """ Spanning-tree priority configured for the selected mode. @@ -20962,7 +23313,7 @@ def __init__( automatically affect any parent/child devices configuration, so it must be set on each applicable node/node-group/node- type as needed. """ - inband_mgmt_vrf: Annotated[str, ConvertTypes[int]] | None = "default" + inband_mgmt_vrf: str | None = "default" """ VRF configured on the Inband Management Interface. The VRF is created if not already created by other means. @@ -21020,19 +23371,19 @@ def __init__( When using 'inband_mgmt_ip' the VLAN and SVI will only be created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be created using network services data models. """ - mpls_overlay_role: Literal["client", "server", "none"] | None = None + mpls_overlay_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None """ Set the default mpls overlay role. Acting role in overlay control plane. """ - overlay_address_families: list[str] | None = None + overlay_address_families: list[Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None """Set the default overlay address families.""" mpls_route_reflectors: list[str] | None = None """List of inventory hostname acting as MPLS route-reflectors.""" - bgp_cluster_id: Annotated[str, ConvertTypes[int]] | None = None + bgp_cluster_id: str | None = None """Set BGP cluster id.""" ptp: Ptp | None = None - wan_role: Literal["client", "server"] | None = None + wan_role: Annotated[str, ValidValues["client", "server"]] | None = None """ Override the default WAN role. @@ -21044,7 +23395,7 @@ def __init__( Only supported if `overlay_routing_protocol` is set to `ibgp`. """ - cv_pathfinder_transit_mode: Literal["region", "zone"] | None = None + cv_pathfinder_transit_mode: Annotated[str, ValidValues["region", "zone"]] | None = None """ Configure the transit mode for a WAN client for CV Pathfinder designs only when the `wan_mode` root key is set to @@ -21079,7 +23430,7 @@ def __init__( Maximum 2 devices supported by group for HA. """ - dps_mss_ipv4: Annotated[str, ConvertTypes[int]] | None = "auto" + dps_mss_ipv4: str | None = "auto" """IPv4 MSS value configured under "router path-selection" on WAN Devices.""" l3_interfaces: list[L3InterfacesItem] | None = None """ @@ -21092,7 +23443,7 @@ def __init__( This setting is useful on virtual Route Reflectors and Pathfinders where more CPU cores should be allocated for control plane. """ - flow_tracker_type: Literal["sampled", "hardware"] | None = None + flow_tracker_type: Annotated[str, ValidValues["sampled", "hardware"]] | None = None """ Set the flow tracker type. Override the `default_flow_tracker_type`` set at the `node_type_key` level. @@ -21104,7 +23455,7 @@ def __init__( group: str = None, nodes: list[NodesItem] | None = None, id: int | None = None, - platform: Annotated[str, ConvertTypes[int]] | None = None, + platform: str | None = None, mac_address: str | None = None, system_mac_address: str | None = None, serial_number: str | None = None, @@ -21119,10 +23470,10 @@ def __init__( always_configure_ip_routing: bool | None = False, raw_eos_cli: str | None = None, structured_config: StructuredConfig | None = None, - uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None = "p2p", + uplink_type: Annotated[str, ValidValues["p2p", "port-channel", "p2p-vrfs", "lan"]] | None = "p2p", uplink_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, - uplink_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, - uplink_switch_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, + uplink_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, + uplink_switch_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, uplink_switches: list[str] | None = None, uplink_interface_speed: str | None = None, uplink_switch_interface_speed: str | None = None, @@ -21140,9 +23491,9 @@ def __init__( mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | None = None, mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | None = None, short_esi: str | None = None, - isis_system_id_prefix: Annotated[str, Pattern["[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None, + isis_system_id_prefix: Annotated[str, Pattern[r"[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None, isis_maximum_paths: int | None = None, - is_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2", + is_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2", node_sid_base: int | None = 0, loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, vtep_loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, @@ -21150,10 +23501,10 @@ def __init__( loopback_ipv6_pool: Annotated[str, Format["ipv6_cidr"]] | None = None, loopback_ipv6_offset: int | None = 0, vtep: bool | None = None, - vtep_loopback: Annotated[str, Pattern["Loopback[\d/]+"]] | None = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None, + vtep_loopback: Annotated[str, Pattern[r"Loopback[\d/]+"]] | None = None, + bgp_as: str | None = None, bgp_defaults: list[str] | None = None, - evpn_role: Literal["client", "server", "none"] | None = None, + evpn_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None, evpn_route_servers: list[str] | None = None, evpn_services_l2_only: bool | None = False, filter: Filter | None = None, @@ -21169,12 +23520,12 @@ def __init__( mlag_peer_l3_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, mlag_peer_vlan: int | None = 4094, mlag_peer_link_allowed_vlans: str | None = None, - mlag_peer_address_family: Literal["ipv4", "ipv6"] | None = "ipv4", + mlag_peer_address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = "ipv4", mlag_peer_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, mlag_peer_ipv6_pool: Annotated[str, Format["ipv6_cidr"]] | None = None, mlag_port_channel_id: int | None = None, mlag_domain_id: str | None = None, - spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None = None, + spanning_tree_mode: Annotated[str, ValidValues["mstp", "rstp", "rapid-pvst", "none"]] | None = None, spanning_tree_priority: int | None = 32768, spanning_tree_root_super: bool | None = False, virtual_router_mac_address: Annotated[str, Format["mac"]] | None = None, @@ -21188,26 +23539,26 @@ def __init__( inband_mgmt_ipv6_gateway: Annotated[str, Format["ipv6"]] | None = None, inband_mgmt_description: str | None = "Inband Management", inband_mgmt_vlan_name: str | None = "Inband Management", - inband_mgmt_vrf: Annotated[str, ConvertTypes[int]] | None = "default", + inband_mgmt_vrf: str | None = "default", inband_mgmt_mtu: int | None = 1500, inband_ztp: bool | None = False, inband_ztp_lacp_fallback_delay: int | None = 30, inband_management_subnet: Annotated[str, Format["ipv4_cidr"]] | None = None, inband_management_vlan: int | None = 4092, - mpls_overlay_role: Literal["client", "server", "none"] | None = None, - overlay_address_families: list[str] | None = None, + mpls_overlay_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None, + overlay_address_families: list[Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None, mpls_route_reflectors: list[str] | None = None, - bgp_cluster_id: Annotated[str, ConvertTypes[int]] | None = None, + bgp_cluster_id: str | None = None, ptp: Ptp | None = None, - wan_role: Literal["client", "server"] | None = None, - cv_pathfinder_transit_mode: Literal["region", "zone"] | None = None, + wan_role: Annotated[str, ValidValues["client", "server"]] | None = None, + cv_pathfinder_transit_mode: Annotated[str, ValidValues["region", "zone"]] | None = None, cv_pathfinder_region: str | None = None, cv_pathfinder_site: str | None = None, wan_ha: WanHa | None = None, - dps_mss_ipv4: Annotated[str, ConvertTypes[int]] | None = "auto", + dps_mss_ipv4: str | None = "auto", l3_interfaces: list[L3InterfacesItem] | None = None, data_plane_cpu_allocation_max: int | None = None, - flow_tracker_type: Literal["sampled", "hardware"] | None = None, + flow_tracker_type: Annotated[str, ValidValues["sampled", "hardware"]] | None = None, **kwargs, ): """ @@ -21941,13 +24292,13 @@ class Filter(AvdDictBaseModel): """ tags: list[str] | None = ["all"] """Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default).""" - allow_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"] + allow_vrfs: list[str] | None = ["all"] """ Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs (default). This list also limits VRFs included by `always_include_vrfs_in_tenants`. """ - deny_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"] + deny_vrfs: list[str] | None = ["all"] """ Prevent configuration of Network Services defined under these VRFs. This list prevents the given VRFs to be included by @@ -21971,8 +24322,8 @@ def __init__( self, tenants: list[str] | None = ["all"], tags: list[str] | None = ["all"], - allow_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"], - deny_vrfs: list[Annotated[str, ConvertTypes[int]]] | None = ["all"], + allow_vrfs: list[str] | None = ["all"], + deny_vrfs: list[str] | None = ["all"], always_include_vrfs_in_tenants: list[str] | None = None, only_vlans_in_use: bool | None = False, **kwargs, @@ -22018,7 +24369,7 @@ class RemotePeersItem(AvdDictBaseModel): """Hostname of remote EVPN GW server.""" ip_address: Annotated[str, Format["ipv4"]] | None = None """Peering IP of remote Route Server.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None + bgp_as: str | None = None """ Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in @@ -22026,11 +24377,7 @@ class RemotePeersItem(AvdDictBaseModel): """ def __init__( - self, - hostname: str | None = None, - ip_address: Annotated[str, Format["ipv4"]] | None = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None, - **kwargs, + self, hostname: str | None = None, ip_address: Annotated[str, Format["ipv4"]] | None = None, bgp_as: str | None = None, **kwargs ): """ Args: @@ -22117,20 +24464,14 @@ class RemotePeersItem(AvdDictBaseModel): """Hostname of remote IPVPN Peer.""" ip_address: Annotated[str, Format["ipv4"]] = None """Peering IP of remote IPVPN Peer.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] = None + bgp_as: str = None """ Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float number. """ - def __init__( - self, - hostname: str = None, - ip_address: Annotated[str, Format["ipv4"]] = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] = None, - **kwargs, - ): + def __init__(self, hostname: str = None, ip_address: Annotated[str, Format["ipv4"]] = None, bgp_as: str = None, **kwargs): """ Args: ----- @@ -22156,7 +24497,7 @@ def __init__( """Enable D-path for use with BGP bestpath selection algorithm.""" maximum_routes: int | None = 0 """Maximum routes to accept from IPVPN remote peers.""" - local_as: Annotated[str, ConvertTypes[int]] | None = "none" + local_as: str | None = "none" """ Local BGP AS applied to peering with IPVPN remote peers. BGP AS <1-4294967295> or AS number in asdot notation @@ -22175,7 +24516,7 @@ def __init__( ipvpn_domain_id: str | None = "65535:2", enable_d_path: bool | None = True, maximum_routes: int | None = 0, - local_as: Annotated[str, ConvertTypes[int]] | None = "none", + local_as: str | None = "none", address_families: list[str] | None = ["vpn-ipv4"], remote_peers: list[RemotePeersItem] | None = None, **kwargs, @@ -22352,7 +24693,7 @@ def __init__( return super().__init__(**kwargs) enabled: bool | None = False - profile: Literal["aes67", "smpte2059-2", "aes67-r16-2016"] | None = "aes67-r16-2016" + profile: Annotated[str, ValidValues["aes67", "smpte2059-2", "aes67-r16-2016"]] | None = "aes67-r16-2016" mlag: bool | None = False """ Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be configured on the MLAG @@ -22385,7 +24726,7 @@ def __init__( the recommended behaviour. This can be set manually if required, for example, to a value of "10.1.2.3". """ - mode: Literal["boundary"] | None = "boundary" + mode: Annotated[str, ValidValues["boundary"]] | None = "boundary" mode_one_step: bool | None = False ttl: int | None = None forward_unicast: bool | None = False @@ -22396,7 +24737,7 @@ def __init__( def __init__( self, enabled: bool | None = False, - profile: Literal["aes67", "smpte2059-2", "aes67-r16-2016"] | None = "aes67-r16-2016", + profile: Annotated[str, ValidValues["aes67", "smpte2059-2", "aes67-r16-2016"]] | None = "aes67-r16-2016", mlag: bool | None = False, domain: int | None = 127, priority1: int | None = None, @@ -22405,7 +24746,7 @@ def __init__( clock_identity_prefix: str | None = None, clock_identity: str | None = None, source_ip: str | None = None, - mode: Literal["boundary"] | None = "boundary", + mode: Annotated[str, ValidValues["boundary"]] | None = "boundary", mode_one_step: bool | None = False, ttl: int | None = None, forward_unicast: bool | None = False, @@ -22487,7 +24828,7 @@ def __init__(self, enabled: bool | None = None, name: str | None = None, **kwarg """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" ipsec: bool | None = True """Enable / Disable IPsec over HA path-group when HA is enabled.""" - ha_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + ha_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """ Local WAN HA interfaces Overwrite the default behavior which is to pick all the `uplink_interfaces`. @@ -22516,7 +24857,7 @@ def __init__( self, enabled: bool | None = True, ipsec: bool | None = True, - ha_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, + ha_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, ha_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, max_ha_interfaces: int | None = None, flow_tracking: FlowTracking | None = None, @@ -22630,7 +24971,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): profile: str | None = None """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" - name: Annotated[str, Pattern["Ethernet[\d/]+(.[\d]+)?"]] = None + name: Annotated[str, Pattern[r"Ethernet[\d/]+(.[\d]+)?"]] = None """ Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. For a subinterface, the parent @@ -22684,7 +25025,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true and `ip` is an IP address. """ - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_in: str | None = None """ Name of the IPv4 access-list to be assigned in the ingress direction. The access-list must be defined under `ipv4_acls` @@ -22692,7 +25033,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Required for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under `wan_carriers`. """ - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None + ipv4_acl_out: str | None = None """ Name of the IPv4 Access-list to be assigned in the egress direction. The access-list must be defined under `ipv4_acls` @@ -22710,7 +25051,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): Unless the carrier is marked as 'trusted' under `wan_carriers`, `ipv4_acl_in` is also required on all WAN interfaces. """ - wan_circuit_id: Annotated[str, ConvertTypes[int]] | None = None + wan_circuit_id: str | None = None """ The WAN circuit ID for this interface. This is not rendered in the configuration but used for WAN designs. @@ -22729,7 +25070,7 @@ class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): def __init__( self, profile: str | None = None, - name: Annotated[str, Pattern["Ethernet[\d/]+(.[\d]+)?"]] = None, + name: Annotated[str, Pattern[r"Ethernet[\d/]+(.[\d]+)?"]] = None, description: str | None = None, ip_address: str | None = None, dhcp_ip: str | None = None, @@ -22741,12 +25082,12 @@ def __init__( peer: str | None = None, peer_interface: str | None = None, peer_ip: str | None = None, - ipv4_acl_in: Annotated[str, ConvertTypes[int]] | None = None, - ipv4_acl_out: Annotated[str, ConvertTypes[int]] | None = None, + ipv4_acl_in: str | None = None, + ipv4_acl_out: str | None = None, static_routes: list[StaticRoutesItem] | None = None, qos_profile: str | None = None, wan_carrier: str | None = None, - wan_circuit_id: Annotated[str, ConvertTypes[int]] | None = None, + wan_circuit_id: str | None = None, connected_to_pathfinder: bool | None = True, cv_pathfinder_internet_exit: CvPathfinderInternetExit | None = None, raw_eos_cli: str | None = None, @@ -22858,7 +25199,7 @@ def __init__( """ id: int | None = None """Unique identifier used for IP addressing and other algorithms.""" - platform: Annotated[str, ConvertTypes[int]] | None = None + platform: str | None = None """Arista platform family.""" mac_address: str | None = None """Leverage to document management interface mac address.""" @@ -22916,7 +25257,7 @@ def __init__( """EOS CLI rendered directly on the root level of the final EOS configuration.""" structured_config: StructuredConfig | None = None """Custom structured config for eos_cli_config_gen.""" - uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None = "p2p" + uplink_type: Annotated[str, ValidValues["p2p", "port-channel", "p2p-vrfs", "lan"]] | None = "p2p" """ Override the default `uplink_type` set at the `node_type_key` level. `uplink_type` must be "p2p" if `vtep` or @@ -22924,7 +25265,7 @@ def __init__( """ uplink_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None """IPv4 subnet to use to connect to uplink switches.""" - uplink_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + uplink_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """ Local uplink interfaces. Each list item supports range syntax that can be expanded into a list of interfaces. @@ -22932,7 +25273,7 @@ def __init__( uplink_interfaces is not defined, platform-specific defaults (defined under default_interfaces) will be used instead. Please note that default_interfaces are not defined by default, you should define these yourself. """ - uplink_switch_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None + uplink_switch_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None """Interfaces located on uplink switches.""" uplink_switches: list[str] | None = None uplink_interface_speed: str | None = None @@ -23063,11 +25404,11 @@ def __init__( automatically using a hash of configuration elements. < 0000:0000:0000 | auto >. """ - isis_system_id_prefix: Annotated[str, Pattern["[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None + isis_system_id_prefix: Annotated[str, Pattern[r"[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None """(4.4 hexadecimal).""" isis_maximum_paths: int | None = None """Number of path to configure in ECMP for ISIS.""" - is_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2" + is_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2" node_sid_base: int | None = 0 """Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID.""" loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None @@ -23098,9 +25439,9 @@ def __init__( Overrides VTEP setting inherited from node_type_keys. """ - vtep_loopback: Annotated[str, Pattern["Loopback[\d/]+"]] | None = None + vtep_loopback: Annotated[str, Pattern[r"Loopback[\d/]+"]] | None = None """Set VXLAN source interface.""" - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None + bgp_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". For asdot notation in YAML inputs, the value @@ -23109,7 +25450,7 @@ def __init__( """ bgp_defaults: list[str] | None = None """List of EOS commands to apply to BGP daemon.""" - evpn_role: Literal["client", "server", "none"] | None = None + evpn_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None """ Acting role in EVPN control plane. Default is set in node_type definition from node_type_keys. @@ -23186,7 +25527,7 @@ def __init__( mlag_peer_vlan: int | None = 4094 """MLAG Peer Link (control link) SVI interface id.""" mlag_peer_link_allowed_vlans: str | None = None - mlag_peer_address_family: Literal["ipv4", "ipv6"] | None = "ipv4" + mlag_peer_address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = "ipv4" """ IP address family used to establish MLAG Peer Link (control link). `ipv6` requires EOS version 4.31.1F or higher. @@ -23213,7 +25554,7 @@ def __init__( """ mlag_domain_id: str | None = None """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" - spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None = None + spanning_tree_mode: Annotated[str, ValidValues["mstp", "rstp", "rapid-pvst", "none"]] | None = None spanning_tree_priority: int | None = 32768 """ Spanning-tree priority configured for the selected mode. @@ -23347,7 +25688,7 @@ def __init__( automatically affect any parent/child devices configuration, so it must be set on each applicable node/node-group/node- type as needed. """ - inband_mgmt_vrf: Annotated[str, ConvertTypes[int]] | None = "default" + inband_mgmt_vrf: str | None = "default" """ VRF configured on the Inband Management Interface. The VRF is created if not already created by other means. @@ -23405,19 +25746,19 @@ def __init__( When using 'inband_mgmt_ip' the VLAN and SVI will only be created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be created using network services data models. """ - mpls_overlay_role: Literal["client", "server", "none"] | None = None + mpls_overlay_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None """ Set the default mpls overlay role. Acting role in overlay control plane. """ - overlay_address_families: list[str] | None = None + overlay_address_families: list[Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None """Set the default overlay address families.""" mpls_route_reflectors: list[str] | None = None """List of inventory hostname acting as MPLS route-reflectors.""" - bgp_cluster_id: Annotated[str, ConvertTypes[int]] | None = None + bgp_cluster_id: str | None = None """Set BGP cluster id.""" ptp: Ptp | None = None - wan_role: Literal["client", "server"] | None = None + wan_role: Annotated[str, ValidValues["client", "server"]] | None = None """ Override the default WAN role. @@ -23429,7 +25770,7 @@ def __init__( Only supported if `overlay_routing_protocol` is set to `ibgp`. """ - cv_pathfinder_transit_mode: Literal["region", "zone"] | None = None + cv_pathfinder_transit_mode: Annotated[str, ValidValues["region", "zone"]] | None = None """ Configure the transit mode for a WAN client for CV Pathfinder designs only when the `wan_mode` root key is set to @@ -23464,7 +25805,7 @@ def __init__( Maximum 2 devices supported by group for HA. """ - dps_mss_ipv4: Annotated[str, ConvertTypes[int]] | None = "auto" + dps_mss_ipv4: str | None = "auto" """IPv4 MSS value configured under "router path-selection" on WAN Devices.""" l3_interfaces: list[L3InterfacesItem] | None = None """ @@ -23477,7 +25818,7 @@ def __init__( This setting is useful on virtual Route Reflectors and Pathfinders where more CPU cores should be allocated for control plane. """ - flow_tracker_type: Literal["sampled", "hardware"] | None = None + flow_tracker_type: Annotated[str, ValidValues["sampled", "hardware"]] | None = None """ Set the flow tracker type. Override the `default_flow_tracker_type`` set at the `node_type_key` level. @@ -23489,7 +25830,7 @@ def __init__( name: str = None, downlink_pools: list[DownlinkPoolsItem] | None = None, id: int | None = None, - platform: Annotated[str, ConvertTypes[int]] | None = None, + platform: str | None = None, mac_address: str | None = None, system_mac_address: str | None = None, serial_number: str | None = None, @@ -23504,10 +25845,10 @@ def __init__( always_configure_ip_routing: bool | None = False, raw_eos_cli: str | None = None, structured_config: StructuredConfig | None = None, - uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None = "p2p", + uplink_type: Annotated[str, ValidValues["p2p", "port-channel", "p2p-vrfs", "lan"]] | None = "p2p", uplink_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, - uplink_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, - uplink_switch_interfaces: list[Annotated[str, Pattern["Ethernet[\d/]+"]]] | None = None, + uplink_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, + uplink_switch_interfaces: list[Annotated[str, Pattern[r"Ethernet[\d/]+"]]] | None = None, uplink_switches: list[str] | None = None, uplink_interface_speed: str | None = None, uplink_switch_interface_speed: str | None = None, @@ -23525,9 +25866,9 @@ def __init__( mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | None = None, mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | None = None, short_esi: str | None = None, - isis_system_id_prefix: Annotated[str, Pattern["[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None, + isis_system_id_prefix: Annotated[str, Pattern[r"[0-9a-f]{4}\.[0-9a-f]{4}"]] | None = None, isis_maximum_paths: int | None = None, - is_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2", + is_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2", node_sid_base: int | None = 0, loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, vtep_loopback_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, @@ -23535,10 +25876,10 @@ def __init__( loopback_ipv6_pool: Annotated[str, Format["ipv6_cidr"]] | None = None, loopback_ipv6_offset: int | None = 0, vtep: bool | None = None, - vtep_loopback: Annotated[str, Pattern["Loopback[\d/]+"]] | None = None, - bgp_as: Annotated[str, ConvertTypes[int, float]] | None = None, + vtep_loopback: Annotated[str, Pattern[r"Loopback[\d/]+"]] | None = None, + bgp_as: str | None = None, bgp_defaults: list[str] | None = None, - evpn_role: Literal["client", "server", "none"] | None = None, + evpn_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None, evpn_route_servers: list[str] | None = None, evpn_services_l2_only: bool | None = False, filter: Filter | None = None, @@ -23554,12 +25895,12 @@ def __init__( mlag_peer_l3_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, mlag_peer_vlan: int | None = 4094, mlag_peer_link_allowed_vlans: str | None = None, - mlag_peer_address_family: Literal["ipv4", "ipv6"] | None = "ipv4", + mlag_peer_address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = "ipv4", mlag_peer_ipv4_pool: Annotated[str, Format["ipv4_cidr"]] | None = None, mlag_peer_ipv6_pool: Annotated[str, Format["ipv6_cidr"]] | None = None, mlag_port_channel_id: int | None = None, mlag_domain_id: str | None = None, - spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None = None, + spanning_tree_mode: Annotated[str, ValidValues["mstp", "rstp", "rapid-pvst", "none"]] | None = None, spanning_tree_priority: int | None = 32768, spanning_tree_root_super: bool | None = False, virtual_router_mac_address: Annotated[str, Format["mac"]] | None = None, @@ -23573,26 +25914,26 @@ def __init__( inband_mgmt_ipv6_gateway: Annotated[str, Format["ipv6"]] | None = None, inband_mgmt_description: str | None = "Inband Management", inband_mgmt_vlan_name: str | None = "Inband Management", - inband_mgmt_vrf: Annotated[str, ConvertTypes[int]] | None = "default", + inband_mgmt_vrf: str | None = "default", inband_mgmt_mtu: int | None = 1500, inband_ztp: bool | None = False, inband_ztp_lacp_fallback_delay: int | None = 30, inband_management_subnet: Annotated[str, Format["ipv4_cidr"]] | None = None, inband_management_vlan: int | None = 4092, - mpls_overlay_role: Literal["client", "server", "none"] | None = None, - overlay_address_families: list[str] | None = None, + mpls_overlay_role: Annotated[str, ValidValues["client", "server", "none"]] | None = None, + overlay_address_families: list[Annotated[str, ValidValues["evpn", "vpn-ipv4", "vpn-ipv6"]]] | None = None, mpls_route_reflectors: list[str] | None = None, - bgp_cluster_id: Annotated[str, ConvertTypes[int]] | None = None, + bgp_cluster_id: str | None = None, ptp: Ptp | None = None, - wan_role: Literal["client", "server"] | None = None, - cv_pathfinder_transit_mode: Literal["region", "zone"] | None = None, + wan_role: Annotated[str, ValidValues["client", "server"]] | None = None, + cv_pathfinder_transit_mode: Annotated[str, ValidValues["region", "zone"]] | None = None, cv_pathfinder_region: str | None = None, cv_pathfinder_site: str | None = None, wan_ha: WanHa | None = None, - dps_mss_ipv4: Annotated[str, ConvertTypes[int]] | None = "auto", + dps_mss_ipv4: str | None = "auto", l3_interfaces: list[L3InterfacesItem] | None = None, data_plane_cpu_allocation_max: int | None = None, - flow_tracker_type: Literal["sampled", "hardware"] | None = None, + flow_tracker_type: Annotated[str, ValidValues["sampled", "hardware"]] | None = None, **kwargs, ): """ @@ -24261,7 +26602,8 @@ def __init__( _allow_other_keys = True application_classification: ApplicationClassification | None = None - avd_data_conversion_mode: Literal["disabled", "error", "warning", "info", "debug", "quiet"] | None = "debug" + """Application traffic recognition configuration.""" + avd_data_conversion_mode: Annotated[str, ValidValues["disabled", "error", "warning", "info", "debug", "quiet"]] | None = "debug" """ Conversion Mode for AVD input data conversion. Input data conversion will perform type conversion of input variables as @@ -24279,7 +26621,7 @@ def __init__( messages viewable with -v. "quiet" will not produce any messages. """ - avd_data_validation_mode: Literal["disabled", "error", "warning", "info", "debug"] | None = "warning" + avd_data_validation_mode: Annotated[str, ValidValues["disabled", "error", "warning", "info", "debug"]] | None = "warning" """ Validation Mode for AVD input data validation. Input data validation will validate the input variables according to the @@ -24295,7 +26637,7 @@ def __init__( """ bfd_multihop: BfdMultihop | None = {"interval": 300, "min_rx": 300, "multiplier": 3} """BFD Multihop tuning.""" - bgp_as: Annotated[str, ConvertTypes[int]] | None = None + bgp_as: str | None = None """ BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>" to use to configure overlay when "overlay_routing_protocol" == ibgp. @@ -24374,7 +26716,9 @@ def __init__( and modify them. """ core_interfaces: CoreInterfaces | None = None - custom_structured_configuration_list_merge: Literal["replace", "append", "keep", "prepend", "append_rp", "prepend_rp"] | None = "append_rp" + custom_structured_configuration_list_merge: Annotated[str, ValidValues["replace", "append", "keep", "prepend", "append_rp", "prepend_rp"]] | None = ( + "append_rp" + ) """ The List-merge strategy used when merging custom structured configurations. @@ -24460,7 +26804,7 @@ def __init__( Make sure to set it in a common group_vars file. """ - cv_tags_topology_type: Literal["leaf", "spine", "core", "edge"] | None = None + cv_tags_topology_type: Annotated[str, ValidValues["leaf", "spine", "core", "edge"]] | None = None """ PREVIEW: This key is currently not supported Device type that CloudVision should use when generating the Topology. @@ -24540,7 +26884,7 @@ def __init__( Default uplink, downlink, and MLAG interfaces, which will be used if these interfaces are not defined on a device (either directly or through inheritance). """ - default_mgmt_method: Literal["oob", "inband", "none"] | None = "oob" + default_mgmt_method: Annotated[str, ValidValues["oob", "inband", "none"]] | None = "oob" """ `default_mgmt_method` controls the default VRF and source interface used for the following management and monitoring protocols configured with `eos_designs`: @@ -24646,7 +26990,7 @@ def __init__( regular MAC-VRFs. """ evpn_vlan_bundles: list[EvpnVlanBundlesItem] | None = None - fabric_evpn_encapsulation: Literal["vxlan", "mpls"] | None = "vxlan" + fabric_evpn_encapsulation: Annotated[str, ValidValues["vxlan", "mpls"]] | None = "vxlan" """Should be set to mpls for evpn-mpls scenario.""" fabric_flow_tracking: FabricFlowTracking | None = None """ @@ -24716,13 +27060,13 @@ def __init__( attempt to move or apply configurations to the device. """ isis_advertise_passive_only: bool | None = False - isis_area_id: Annotated[str, ConvertTypes[int, float]] | None = "49.0001" - isis_default_circuit_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2" + isis_area_id: str | None = "49.0001" + isis_default_circuit_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2" """ These fabric level parameters can be used with core_interfaces running ISIS, and may be overridden on link profile or link level. """ - isis_default_is_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2" + isis_default_is_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2" isis_default_metric: int | None = 50 """ These fabric level parameters can be used with core_interfaces running ISIS, and may be overridden at link profile or @@ -24730,7 +27074,7 @@ def __init__( """ isis_maximum_paths: int | None = None """Number of path to configure in ECMP for ISIS.""" - isis_system_id_format: Literal["node_id", "underlay_loopback"] | None = "node_id" + isis_system_id_format: Annotated[str, ValidValues["node_id", "underlay_loopback"]] | None = "node_id" """ Configures source for the system-id within the ISIS net id. By default the `id` and `isis_system_id_prefix` fields @@ -24774,7 +27118,7 @@ def __init__( """OOB Management interface.""" mgmt_interface_description: str | None = "oob_management" """Management interface description.""" - mgmt_interface_vrf: Annotated[str, ConvertTypes[int]] | None = "MGMT" + mgmt_interface_vrf: str | None = "MGMT" """OOB Management VRF.""" mgmt_vrf_routing: bool | None = False """Configure IP routing for the OOB Management VRF.""" @@ -24860,7 +27204,7 @@ def __init__( This will make `eos_designs` consider configured VLANs per VTEP, and only include the relevant VTEPs to each VNI's flood-list. """ - overlay_her_flood_list_scope: Literal["fabric", "dc"] | None = "fabric" + overlay_her_flood_list_scope: Annotated[str, ValidValues["fabric", "dc"]] | None = "fabric" """ When using Head-End Replication, set the scope of flood-lists to Fabric or DC. By default all VTEPs in the Fabric (part @@ -24899,7 +27243,7 @@ def __init__( a problem with large VNIs. For 16-bit ASN/number the assigned number can be a 32-bit number. """ - overlay_routing_protocol: Annotated[Literal["ebgp", "ibgp", "cvx", "her", "none"], ToLower] | None = "ebgp" + overlay_routing_protocol: Annotated[str, ToLower, ValidValues["ebgp", "ibgp", "cvx", "her", "none"]] | None = "ebgp" """ - The following overlay routing protocols are supported: - eBGP: Configures fabric with eBGP, default for l3ls-evpn @@ -24912,7 +27256,7 @@ def __init__( - none: No overlay configuration will be generated, default for l2ls design. """ - overlay_routing_protocol_address_family: Literal["ipv4", "ipv6"] | None = "ipv4" + overlay_routing_protocol_address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = "ipv4" """ When set to `ipv6`, enable overlay EVPN peering with IPv6 addresses. This feature depends on underlay_ipv6 variable. As @@ -25076,7 +27420,7 @@ def __init__( queue_monitor_length: QueueMonitorLength | None = None redundancy: Redundancy | None = None """Redundancy for chassis platforms with dual supervisors | Optional.""" - serial_number: Annotated[str, ConvertTypes[int]] | None = None + serial_number: str | None = None """ Serial Number of the device. Used for documentation purpose in the fabric documentation as can also be used by the @@ -25238,7 +27582,7 @@ def __init__( Requires 'underlay_multicast: true'. """ - underlay_ospf_area: Annotated[str, ConvertTypes[int], Format["ipv4"]] | None = "0.0.0.0" + underlay_ospf_area: Annotated[str, Format["ipv4"]] | None = "0.0.0.0" underlay_ospf_bfd_enable: bool | None = False underlay_ospf_max_lsa: int | None = 12000 underlay_ospf_process_id: int | None = 100 @@ -25247,7 +27591,9 @@ def __init__( Point to Point Underlay with RFC 5549(eBGP), i.e. IPv6 Unnumbered. Requires "underlay_routing_protocol: ebgp". """ - underlay_routing_protocol: Annotated[Literal["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"], ToLower] | None = None + underlay_routing_protocol: Annotated[str, ToLower, ValidValues["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"]] | None = ( + None + ) """ - The following underlay routing protocols are supported: - EBGP (default for l3ls-evpn) @@ -25282,7 +27628,7 @@ def __init__( """PREVIEW: The `wan_ha` key is currently not supported.""" wan_ipsec_profiles: WanIpsecProfiles | None = None """Define IPsec profiles parameters for WAN configuration.""" - wan_mode: Literal["autovpn", "cv-pathfinder"] | None = "cv-pathfinder" + wan_mode: Annotated[str, ValidValues["autovpn", "cv-pathfinder"]] | None = "cv-pathfinder" """Select if the WAN should be run using CV Pathfinder or AutoVPN only.""" wan_path_groups: list[WanPathGroupsItem] | None = None """List of path-groups used for the WAN configuration.""" @@ -25340,10 +27686,10 @@ def __init__( def __init__( self, application_classification: ApplicationClassification | None = None, - avd_data_conversion_mode: Literal["disabled", "error", "warning", "info", "debug", "quiet"] | None = "debug", - avd_data_validation_mode: Literal["disabled", "error", "warning", "info", "debug"] | None = "warning", + avd_data_conversion_mode: Annotated[str, ValidValues["disabled", "error", "warning", "info", "debug", "quiet"]] | None = "debug", + avd_data_validation_mode: Annotated[str, ValidValues["disabled", "error", "warning", "info", "debug"]] | None = "warning", bfd_multihop: BfdMultihop | None = {"interval": 300, "min_rx": 300, "multiplier": 3}, - bgp_as: Annotated[str, ConvertTypes[int]] | None = None, + bgp_as: str | None = None, bgp_default_ipv4_unicast: bool | None = False, bgp_distance: BgpDistance | None = None, bgp_ecmp: int | None = None, @@ -25368,13 +27714,15 @@ def __init__( {"key": "generic_devices", "type": "generic_device", "description": "Generic Device."}, ], core_interfaces: CoreInterfaces | None = None, - custom_structured_configuration_list_merge: Literal["replace", "append", "keep", "prepend", "append_rp", "prepend_rp"] | None = "append_rp", + custom_structured_configuration_list_merge: ( + Annotated[str, ValidValues["replace", "append", "keep", "prepend", "append_rp", "prepend_rp"]] | None + ) = "append_rp", custom_structured_configuration_prefix: list[str] | None = ["custom_structured_configuration_"], cv_pathfinder_global_sites: list[CvPathfinderGlobalSitesItem] | None = None, cv_pathfinder_internet_exit_policies: list[CvPathfinderInternetExitPoliciesItem] | None = None, cv_pathfinder_regions: list[CvPathfinderRegionsItem] | None = None, cv_server: str | None = None, - cv_tags_topology_type: Literal["leaf", "spine", "core", "edge"] | None = None, + cv_tags_topology_type: Annotated[str, ValidValues["leaf", "spine", "core", "edge"]] | None = None, cv_token: str | None = None, cv_topology: list[CvTopologyItem] | None = None, cvp_ingestauth_key: str | None = None, @@ -25385,7 +27733,7 @@ def __init__( default_igmp_snooping_enabled: bool | None = True, default_interface_mtu: int | None = None, default_interfaces: list[DefaultInterfacesItem] | None = None, - default_mgmt_method: Literal["oob", "inband", "none"] | None = "oob", + default_mgmt_method: Annotated[str, ValidValues["oob", "inband", "none"]] | None = "oob", default_node_types: list[DefaultNodeTypesItem] | None = None, design: Design | None = None, enable_trunk_groups: bool | None = False, @@ -25403,7 +27751,7 @@ def __init__( evpn_short_esi_prefix: str | None = "0000:0000:", evpn_vlan_aware_bundles: bool | None = False, evpn_vlan_bundles: list[EvpnVlanBundlesItem] | None = None, - fabric_evpn_encapsulation: Literal["vxlan", "mpls"] | None = "vxlan", + fabric_evpn_encapsulation: Annotated[str, ValidValues["vxlan", "mpls"]] | None = "vxlan", fabric_flow_tracking: FabricFlowTracking | None = None, fabric_ip_addressing: FabricIpAddressing | None = None, fabric_name: str = None, @@ -25417,12 +27765,12 @@ def __init__( ipv6_mgmt_gateway: Annotated[str, Format["ipv6"]] | None = None, is_deployed: bool | None = True, isis_advertise_passive_only: bool | None = False, - isis_area_id: Annotated[str, ConvertTypes[int, float]] | None = "49.0001", - isis_default_circuit_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2", - isis_default_is_type: Literal["level-1-2", "level-1", "level-2"] | None = "level-2", + isis_area_id: str | None = "49.0001", + isis_default_circuit_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2", + isis_default_is_type: Annotated[str, ValidValues["level-1-2", "level-1", "level-2"]] | None = "level-2", isis_default_metric: int | None = 50, isis_maximum_paths: int | None = None, - isis_system_id_format: Literal["node_id", "underlay_loopback"] | None = "node_id", + isis_system_id_format: Annotated[str, ValidValues["node_id", "underlay_loopback"]] | None = "node_id", isis_ti_lfa: IsisTiLfa | None = None, l3_edge: L3Edge | None = None, l3_interface_profiles: list[L3InterfaceProfilesItem] | None = None, @@ -25433,7 +27781,7 @@ def __init__( mgmt_gateway: str | None = None, mgmt_interface: str | None = "Management1", mgmt_interface_description: str | None = "oob_management", - mgmt_interface_vrf: Annotated[str, ConvertTypes[int]] | None = "MGMT", + mgmt_interface_vrf: str | None = "MGMT", mgmt_vrf_routing: bool | None = False, mlag_ibgp_peering_vrfs: MlagIbgpPeeringVrfs | None = None, mlag_on_orphan_port_channel_downlink: bool | None = True, @@ -25446,12 +27794,12 @@ def __init__( only_local_vlan_trunk_groups: bool | None = False, overlay_cvx_servers: list[str] | None = None, overlay_her_flood_list_per_vni: bool | None = False, - overlay_her_flood_list_scope: Literal["fabric", "dc"] | None = "fabric", + overlay_her_flood_list_scope: Annotated[str, ValidValues["fabric", "dc"]] | None = "fabric", overlay_loopback_description: str | None = None, overlay_mlag_rfc5549: bool | None = False, overlay_rd_type: OverlayRdType | None = None, - overlay_routing_protocol: Annotated[Literal["ebgp", "ibgp", "cvx", "her", "none"], ToLower] | None = "ebgp", - overlay_routing_protocol_address_family: Literal["ipv4", "ipv6"] | None = "ipv4", + overlay_routing_protocol: Annotated[str, ToLower, ValidValues["ebgp", "ibgp", "cvx", "her", "none"]] | None = "ebgp", + overlay_routing_protocol_address_family: Annotated[str, ValidValues["ipv4", "ipv6"]] | None = "ipv4", overlay_rt_type: OverlayRtType | None = None, p2p_uplinks_mtu: int | None = 9214, p2p_uplinks_qos_profile: str | None = None, @@ -25572,7 +27920,7 @@ def __init__( ], queue_monitor_length: QueueMonitorLength | None = None, redundancy: Redundancy | None = None, - serial_number: Annotated[str, ConvertTypes[int]] | None = None, + serial_number: str | None = None, sflow_settings: SflowSettings | None = None, shutdown_bgp_towards_undeployed_peers: bool | None = False, shutdown_interfaces_towards_undeployed_peers: bool | None = False, @@ -25595,19 +27943,21 @@ def __init__( underlay_multicast: bool | None = False, underlay_multicast_anycast_rp: UnderlayMulticastAnycastRp | None = None, underlay_multicast_rps: list[UnderlayMulticastRpsItem] | None = None, - underlay_ospf_area: Annotated[str, ConvertTypes[int], Format["ipv4"]] | None = "0.0.0.0", + underlay_ospf_area: Annotated[str, Format["ipv4"]] | None = "0.0.0.0", underlay_ospf_bfd_enable: bool | None = False, underlay_ospf_max_lsa: int | None = 12000, underlay_ospf_process_id: int | None = 100, underlay_rfc5549: bool | None = False, - underlay_routing_protocol: Annotated[Literal["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"], ToLower] | None = None, + underlay_routing_protocol: ( + Annotated[str, ToLower, ValidValues["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"]] | None + ) = None, uplink_ptp: UplinkPtp | None = None, use_cv_topology: bool | None = None, vtep_vvtep_ip: str | None = None, wan_carriers: list[WanCarriersItem] | None = None, wan_ha: WanHa | None = None, wan_ipsec_profiles: WanIpsecProfiles | None = None, - wan_mode: Literal["autovpn", "cv-pathfinder"] | None = "cv-pathfinder", + wan_mode: Annotated[str, ValidValues["autovpn", "cv-pathfinder"]] | None = "cv-pathfinder", wan_path_groups: list[WanPathGroupsItem] | None = None, wan_route_servers: list[WanRouteServersItem] | None = None, wan_stun_dtls_disable: bool | None = False, @@ -25621,7 +27971,7 @@ def __init__( """ Args: ----- - application_classification: application_classification + application_classification: Application traffic recognition configuration. avd_data_conversion_mode: Conversion Mode for AVD input data conversion. Input data conversion will perform type conversion of input variables as diff --git a/python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml b/python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml index 72198b4ddf6..79e54a74012 100644 --- a/python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml +++ b/python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml @@ -1363,17 +1363,17 @@ keys: type: str default: first_id description: "This variable defines the Multi-chassis Link Aggregation - (MLAG) algorithm used.\nEach MLAG link will have a /31* subnet with + (MLAG) algorithm used.\nEach MLAG link will have a /31\xB9 subnet with each subnet allocated from the relevant MLAG pool via a calculated offset.\nThe offset is calculated using one of the following algorithms:\n - first_id: `(mlag_primary_id - 1) * 2` where `mlag_primary_id` is the ID of the first node defined under the node_group.\n This allocation method - will skip every other /31* subnet making it less space efficient than - `odd_id`.\n - odd_id: `(odd_id - 1) / 2`. Requires the node_group to - have a node with an odd ID and a node with an even ID.\n - same_subnet: + will skip every other /31\xB9 subnet making it less space efficient + than `odd_id`.\n - odd_id: `(odd_id - 1) / 2`. Requires the node_group + to have a node with an odd ID and a node with an even ID.\n - same_subnet: the offset will always be zero.\n This allocation method will cause - every MLAG link to be addressed with the same /31* subnet.\n\\* - The - prefix length is configurable with a default of /31." + every MLAG link to be addressed with the same /31\xB9 subnet.\n\xB9 + The prefix length is configurable with a default of /31." valid_values: - first_id - odd_id diff --git a/python-avd/pyavd/_schema/__init__.py b/python-avd/pyavd/_schema/__init__.py deleted file mode 100644 index 10305061a5b..00000000000 --- a/python-avd/pyavd/_schema/__init__.py +++ /dev/null @@ -1,8 +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 .eos_cli_config_gen import EosCliConfigGen -from .eos_designs import EosDesigns - -__all__ = ["EosCliConfigGen", "EosDesigns"] diff --git a/python-avd/pyavd/_schema/models.py b/python-avd/pyavd/_schema/models.py index fd03b83f84a..57569153556 100644 --- a/python-avd/pyavd/_schema/models.py +++ b/python-avd/pyavd/_schema/models.py @@ -3,78 +3,156 @@ # that can be found in the LICENSE file. from __future__ import annotations -from typing import Any, TYPE_CHECKING, get_type_hints, get_origin, get_args, Annotated +from collections import ChainMap from types import NoneType, UnionType +from typing import TYPE_CHECKING, Annotated, Any, Generator, Optional, Union, get_args, get_origin, get_type_hints from warnings import warn from .._utils import get_all from .types import InvalidKey +from .validator import validator if TYPE_CHECKING: - from .eos_designs import EosDesigns - from typing import TypeVar + from .._eos_designs.schema.eos_designs import EosDesigns + T = TypeVar("T") class AvdBase: + + _allow_other_keys: bool = False + + def __init__(self, *args, **kwargs): + pass + def __repr__(self) -> str: # cls_name = super().__repr__().split(maxsplit=1)[0] cls_name = self.__class__.__name__ - attrs = [f"{key}={repr(getattr(self, key, None))}" for key in self._get_type_hints() if not key.startswith("_") and key[0].islower()] + attrs = [f"{key}={repr(getattr(self, key, None))}" for key in self.keys()] return f"<{cls_name}({', '.join(attrs)})>" - def validate(self, data: Any) -> bool: - pass - - def _set_with_coercion(self, attr: str, value: Any): - type_hints = self._get_type_hints()[attr] - if isinstance(value, type_hints): - return setattr(self, attr, value) - base_class = self._get_attr_base_class(attr) - print(base_class) - if issubclass(base_class, AvdBase) and isinstance(value, dict): - return setattr(self, attr, base_class(**value)) - if base_class is int and isinstance(value, (str, bool)): - value = int(value) - return setattr(self, attr, value) - if base_class is str and isinstance(value, (int, bool, float)): - value = str(value) - return setattr(self, attr, value) - raise TypeError(f"Invalid type '{type(value)}. Expected '{base_class}'") - @classmethod - def _get_type_hints(cls) -> type: - return get_type_hints(cls, include_extras=True) + def keys(cls) -> Generator[str, None, None]: + return (key for key in cls._get_type_hints() if not key.startswith("_") and key[0].islower()) + + def items(self) -> Generator[tuple[str, Any], None, None]: + return ((key, getattr(self, key, None)) for key in self.keys()) @classmethod - def _get_attr_base_class(cls, attr: str) -> type: - type_hints = cls._get_type_hints()[attr] - type_hints = cls._strip_union_none_from_type_hints(type_hints) - origin = get_origin(type_hints) - if origin is Annotated: - return get_args(type_hints)[0] - - return type_hints - - @staticmethod - def _strip_union_none_from_type_hints(type_hints: type) -> type: - origin = get_origin(type_hints) - if origin is UnionType: - args = tuple(arg for arg in get_args(type_hints) if arg is not NoneType) - if len(args) > 1: - raise TypeError("Unable to remove union since this field has more non-NonType than one") - return args[0] - return type_hints + def validate(cls, data: dict, path: list | None = None) -> bool: # TODO: Rename all methods to something that cannot collide with schema keys + if warnings := validator(data, cls, path or []): + for warning in warnings: + warn(warning) + return False + return True + + # if not isinstance(data, (dict, ChainMap)): + # raise TypeError("Invalid data type '{type(data)}'. Expected dict.") + + # valid = True + # if path is None: + # path = [] + + # base_type_hints = cls._get_type_hints(include_extras=False) + # for key, value in data.items(): + # if not isinstance(key, str) or key.startswith("_") or key not in base_type_hints: + # if not cls._allow_other_keys: + # warn(InvalidKey(str([*path, key]), path=[*path, key])) + # valid = False + # continue + + # type_hints = base_type_hints[key] + # base_class = cls._get_attr_base_class(key) + + # if value is None and cls._is_optional(type_hints): + # # No need to try further validation if the value is None. + # continue + + # try: + # if issubclass(base_class, AvdBase): + # avd_class: AvdBase = cls._strip_union_none_from_type_hints(type_hints) + # if not isinstance(value, (avd_class, dict, ChainMap)): + # warn(f"{key}: Invalid type '{type(value)}'. Expected '{avd_class}' or dict or ChainMap. Optional: {cls._is_optional(type_hints)}") + # valid = False + # # No need to try further validation if the type is wrong. + # continue + # # Perform validation of the value on the base_class + # valid = avd_class.validate(value, path=[*path, key]) and valid + + # elif not (isinstance(value, base_class) or (base_class in ACCEPTED_COERCION_MAP and isinstance(value, ACCEPTED_COERCION_MAP[base_class]))): + # warn(f"{key}: Invalid type '{type(value)}'. Expected '{base_class}'") + # valid = False + # # No need to try further validation if the type is wrong. + # continue + # except TypeError as e: + # raise TypeError(f"type_hints: {type_hints}, base_class: {base_class}", e) + + # return valid + + # @staticmethod + # def _is_optional(type_hints: type) -> bool: + # origin = get_origin(type_hints) + # if origin is Optional: + # return True + + # if origin is UnionType or origin is Union: + # return NoneType in get_args(type_hints) + + # return False + + # def _set_with_coercion(self, attr: str, value: Any): + # type_hints = self._get_type_hints(include_extras=False)[attr] + # if isinstance(value, type_hints): + # return setattr(self, attr, value) + + # base_class = self._get_attr_base_class(attr) + # print(base_class) + + # if issubclass(base_class, AvdBase) and isinstance(value, dict): + # avd_class: AvdBase = self._strip_union_none_from_type_hints(type_hints) + # return setattr(self, attr, avd_class(**value)) + + # if base_class in ACCEPTED_COERCION_MAP and isinstance(value, ACCEPTED_COERCION_MAP[base_class]): + # value = base_class(value) + # return setattr(self, attr, value) + + # raise TypeError(f"Invalid type '{type(value)}. Expected '{base_class}'") @classmethod - def _get_attr_annotations(cls, attr: str) -> tuple[type]: - type_hints = cls._get_type_hints()[attr] - type_hints = cls._strip_union_none_from_type_hints(type_hints) - origin = get_origin(type_hints) - if origin is Annotated: - return get_args(type_hints)[1:] + def _get_type_hints(cls, include_extras: bool = True) -> dict[str, type]: + return get_type_hints(cls, include_extras=include_extras) + + # @classmethod + # def _get_attr_base_class(cls, attr: str) -> type: + # org_type_hints = cls._get_type_hints(include_extras=False)[attr] + # type_hints = cls._strip_union_none_from_type_hints(org_type_hints) + # origin = get_origin(type_hints) + # if origin is None: + # return type_hints + # return origin + + # @staticmethod + # def _strip_union_none_from_type_hints(type_hints: type) -> type: + # while True: + # origin = get_origin(type_hints) + # if origin is UnionType or origin is Union: + # args = tuple(arg for arg in get_args(type_hints) if arg is not NoneType) + # if len(args) > 1: + # raise TypeError("Unable to remove union since this field has more non-NonType than one") + # type_hints = args[0] + # continue + + # if origin is Optional: + # args = get_args(type_hints) + # if len(args) > 1: + # raise TypeError("Unable to remove Optional since this field has types inside than one") + # type_hints = args[0] + # continue + + # break + # return type_hints class AvdDictBaseModel(AvdBase): @@ -86,7 +164,6 @@ class AvdDictBaseModel(AvdBase): """ _custom_data: dict[str, Any] | None = None - _allow_other_keys: bool = False def __init__(self, **kwargs): """ @@ -95,7 +172,7 @@ def __init__(self, **kwargs): self._custom_data = {key: kwargs.pop(key) for key in kwargs if key.startswith("_")} if kwargs and not self._allow_other_keys: for kwarg in kwargs: - warn(kwarg, InvalidKey) + warn(InvalidKey(kwarg, [kwarg])) class AvdEosDesignsRootDictBase(AvdBase): @@ -172,7 +249,7 @@ def _extract_dynamic_keys(self: EosDesigns, kwargs: dict[str, Any]): model_key: str = dynamic_key_map["model_key"] model_key_list = [] - dynamic_keys = get_all(self, dynamic_keys_path, required=True) + dynamic_keys = get_all(self, dynamic_keys_path) for dynamic_key in dynamic_keys: # dynamic_key is one key like "l3leaf". if kwargs.get(dynamic_key) is None: diff --git a/python-avd/pyavd/_schema/types.py b/python-avd/pyavd/_schema/types.py index 350fe7295c2..b5363fcdc05 100644 --- a/python-avd/pyavd/_schema/types.py +++ b/python-avd/pyavd/_schema/types.py @@ -3,84 +3,87 @@ # that can be found in the LICENSE file. from __future__ import annotations -from typing import Iterator from types import GenericAlias +from typing import Any, ClassVar -from annotated_types import BaseMetadata, GroupedMetadata -from pydantic import BeforeValidator +class ValidationOption: + is_validation_type: ClassVar[bool] = True -class ConvertTypes: def __class_getitem__(cls, item): return GenericAlias(cls, item) -class Format: - def __class_getitem__(cls, item): - return GenericAlias(cls, item) +class Format(ValidationOption): + pass -class MaxLen: - def __class_getitem__(cls, item): - return GenericAlias(cls, item) +class MaxLen(ValidationOption): + pass -class MinLen: - def __class_getitem__(cls, item): - return GenericAlias(cls, item) +class MinLen(ValidationOption): + pass -class Pattern: - def __class_getitem__(cls, item): - return GenericAlias(cls, item) +class Max(ValidationOption): + pass + + +class Min(ValidationOption): + pass + + +class Pattern(ValidationOption): + pass class ToLower: + is_validation_type: ClassVar[bool] = True + + +class ValidValues(ValidationOption): pass -class InvalidKey(UserWarning): - def __init__(self, msg, path: list[str | int] | None = None): +class ValidationWarning(UserWarning): + msg: str + """Message""" + path: list[str | int] + """Data path to key that raised this warning""" + + +class InvalidKey(ValidationWarning): + def __init__(self, key: str, path: list[str | int] | None = None): + self.path = path + self.msg = f"Got invalid key '{key}'" + return super().__init__(self.msg) + + +class InvalidType(ValidationWarning): + def __init__(self, key: str, invalid_type: type, valid_type: type, path: list[str | int] | None = None): + self.path = path + self.msg = f"Got invalid type for '{key}'. Expected '{valid_type}', got '{invalid_type}'" + return super().__init__(self.msg) + + +class InvalidValue(ValidationWarning): + def __init__(self, key: str, value: Any, valid_values: tuple | str, path: list[str | int] | None = None): + self.path = path + self.msg = f"Got invalid value for '{key}'. Expected '{valid_values}', got '{value}'" + return super().__init__(self.msg) + + +class InvalidLength(ValidationWarning): + def __init__(self, key: str, length: int, valid_length: str, path: list[str | int] | None = None): + self.path = path + + self.msg = f"Got invalid length for '{key}'. Expected {valid_length}, got '{length}'" + return super().__init__(self.msg) + + +class InvalidPattern(ValidationWarning): + def __init__(self, key: str, value: Any, pattern: str, path: list[str | int] | None = None): self.path = path - msg = f"Got invalid key '{msg}'" - return super().__init__(msg) - - -class StrConvert(GroupedMetadata): - def __init__( - self, - convert_types: tuple[type] | None = None, - to_lower: bool = False, - ): - self.convert_types = convert_types - self.to_lower = to_lower - - def __iter__(self) -> Iterator[BaseMetadata]: - if self.to_lower: - yield BeforeValidator(lambda v: v.lower() if isinstance(v, str) else v) - if self.convert_types is not None: - yield BeforeValidator(lambda v: str(v) if isinstance(v, self.convert_types) else v) - - -class IntConvert(GroupedMetadata): - def __init__( - self, - convert_types: tuple[type] | None = None, - ): - self.convert_types = convert_types - - def __iter__(self) -> Iterator[BaseMetadata]: - if self.convert_types is not None: - yield BeforeValidator(lambda v: int(v) if isinstance(v, self.convert_types) else v) - - -class BoolConvert(GroupedMetadata): - def __init__( - self, - convert_types: tuple[type] | None = None, - ): - self.convert_types = convert_types - - def __iter__(self) -> Iterator[BaseMetadata]: - if self.convert_types is not None: - yield BeforeValidator(lambda v: bool(v) if isinstance(v, self.convert_types) else v) + self.msg = f"Got invalid value for '{key}'. Expected a value matching the pattern '{pattern}', got '{value}'" + return super().__init__(self.msg) diff --git a/python-avd/pyavd/_schema/validator.py b/python-avd/pyavd/_schema/validator.py index 68729dfc73e..61f2bc9872e 100644 --- a/python-avd/pyavd/_schema/validator.py +++ b/python-avd/pyavd/_schema/validator.py @@ -1,42 +1,260 @@ -from typing import Any, Type -from warnings import warn +# 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 re from collections import ChainMap +from types import NoneType, UnionType +from typing import TYPE_CHECKING, Annotated, Any, Optional, TypeVar, Union, get_args, get_origin -SCHEMA_SIMPLE_TYPES_TO_PYTHON_MAP = { - "int": int, - "str": str, - "bool": bool, -} -SCHEMA_TYPES_TO_ACCEPTED_PYTHON_TYPES = { - "int": (int, str), - "str": (str, int, bool, float), - "bool": bool, - "dict": dict, - "list": list, +from .types import Format, InvalidKey, InvalidLength, InvalidPattern, InvalidType, InvalidValue, Max, MaxLen, Min, MinLen, Pattern, ToLower, ValidValues + +if TYPE_CHECKING: + from .models import AvdBase + + T = TypeVar("T") + TT = TypeVar("TT") + + +ACCEPTED_COERCION_MAP = { + int: (str, bool), + str: (int, bool, float), + bool: (str, int), } -def validator(value: Any, schema: dict, cls: Type | None) -> bool: - if value is None or not schema: - return True +def coerce_type(value: T, target_type: type[TT]) -> T | TT: + if not isinstance(value, target_type) and target_type in ACCEPTED_COERCION_MAP and isinstance(value, ACCEPTED_COERCION_MAP[target_type]): + return target_type(value) + return value + + +def annotated_validator(value: Any, type_hint: type[Annotated[type, Any]], path: list[str | int]) -> set[UserWarning] | None: + args = get_args(type_hint) + + # First perform basic type validation. If this fails we don't have to check all the annotations. + if arg_warnings := validator(value, args[0], path): + return arg_warnings + + # If basic type validation succeeded we can dig deeper into the annotations and validate each. + + # First coerce the value to the correct. + value = coerce_type(value, args[0]) + + warnings = set() + for arg in args[1:]: + # Special handling of ToLower since we need to modify the value used in subsequent validation. + if arg is ToLower: + value = str(value).lower() + continue + if arg_warnings := validator(value, arg, path): + warnings.update(arg_warnings) + + return warnings or None + + +def none_validator(value: Any, type_hint: type[NoneType], path: list[str | int]) -> set[UserWarning] | None: + if value is not None: + return {InvalidType(path[-1], type(value), NoneType, path)} + + +def union_validator(value: Any, type_hint: type[UnionType | Union[Any, Any]], path: list[str | int]) -> set[UserWarning] | None: + warnings = set() + for arg in get_args(type_hint): + if not (arg_warnings := validator(value, arg, path)): + return + + # Ignore warnings for NoneType if there is another type in the union + if arg is not NoneType: + warnings.update(arg_warnings) + + return warnings or None + + +def str_validator(value: Any, type_hint: type[str], path: list[str | int]) -> set[UserWarning] | None: + if isinstance(value, str): + return + + if isinstance(value, ACCEPTED_COERCION_MAP[str]): + try: + str(value) + return + except ValueError: + pass + + return {InvalidType(path[-1], type(value), str, path)} + + +def int_validator(value: Any, type_hint: type[int], path: list[str | int]) -> set[UserWarning] | None: + if isinstance(value, int): + return + + if isinstance(value, ACCEPTED_COERCION_MAP[int]): + try: + int(value) + return + except ValueError: + pass + + return {InvalidType(path[-1], type(value), int, path)} + + +def bool_validator(value: Any, type_hint: type[bool], path: list[str | int]) -> set[UserWarning] | None: + if isinstance(value, bool): + return + + if isinstance(value, ACCEPTED_COERCION_MAP[bool]): + try: + bool(value) + return + except ValueError: + pass + + return {InvalidType(path[-1], type(value), bool, path)} + + +def dict_validator(value: Any, type_hint: type[dict], path: list[str | int]) -> set[UserWarning] | None: + if isinstance(value, dict): + return - if schema["type"] == "dict": - if not isinstance(value, (dict, ChainMap, cls)): - warn(f"Wrong type {type(value)}. Excepted dict or {cls.__name__}.", UserWarning) - elif not isinstance(SCHEMA_TYPES_TO_ACCEPTED_PYTHON_TYPES[schema["type"]]): - warn(f"Wrong type {type(value)}. Excepted {' or '.join(SCHEMA_TYPES_TO_ACCEPTED_PYTHON_TYPES[schema['type']])}.", UserWarning) + return {InvalidType(path[-1], type(value), dict, path)} + + +def list_validator(value: Any, type_hint: type[list | list[Any]], path: list[str | int]) -> set[UserWarning] | None: + if not isinstance(value, list): + return {InvalidType(path[-1], type(value), list, path)} + + if not (args := get_args(type_hint)): + # We know it's a list and we have no further information + return + + warnings = set() + for index, item_value in enumerate(value): + if item_warnings := validator(item_value, args[0], [*path, index]): + warnings.update(item_warnings) + + return warnings or None + + +def avd_class_validator(value: AvdBase | dict | ChainMap, type_hint: type[AvdBase], path: list[str | int]) -> set[UserWarning] | None: + if not isinstance(value, (type_hint, dict, ChainMap)): + return {InvalidType(path[-1], type(value), dict, path)} # TODO: reconsider which type we should use as expected type (or types?) + + warnings = set() + # Validate the given data key by key + avd_class_type_hints = type_hint._get_type_hints() + for attr, attr_value in value.items(): + try: + attr_type_hint = avd_class_type_hints[attr] + except KeyError: + # Could be caused by a system keyword used as field name. + if f"field_{attr}" in avd_class_type_hints: + attr = f"field_{attr}" + attr_type_hint = avd_class_type_hints[attr] + + else: + if not type_hint._allow_other_keys: + warnings.add(InvalidKey(attr, [*path, attr])) + continue + + if attr_warnings := validator(attr_value, attr_type_hint, [*path, attr]): + warnings.update(attr_warnings) + + # TODO: Validate required fields + + return warnings or None + + +def optional_validator(value: Any, type_hint: type[Optional[Any]], path: list[str | int]) -> set[UserWarning] | None: + if value is None: + return + return validator(value, get_args(type_hint)[0], path) + + +def valid_values_validator(value: Any, type_hint: type[ValidValues[Any]], path: list[str | int]) -> set[UserWarning] | None: + valid_values = get_args(type_hint) + if value in valid_values: + return + + return {InvalidValue(path[-1], value, valid_values, path)} + + +def format_values_validator(value: Any, type_hint: type[Format[str]], path: list[str | int]) -> set[UserWarning] | None: + # TODO + pass + + +def max_len_validator(value: Any, type_hint: type[MaxLen[int]], path: list[str | int]) -> set[UserWarning] | None: + max_len = get_args(type_hint)[0] + if (length := len(value)) <= max_len: + return + return {InvalidLength(path[-1], length, f"<={max_len}")} + + +def min_len_validator(value: Any, type_hint: type[MinLen[int]], path: list[str | int]) -> set[UserWarning] | None: + min_len = get_args(type_hint)[0] + if (length := len(value)) >= min_len: + return + return {InvalidLength(path[-1], length, f">={min_len}")} + + +def pattern_validator(value: Any, type_hint: type[Pattern[str]], path: list[str | int]) -> set[UserWarning] | None: + pattern = get_args(type_hint)[0] + if re.fullmatch(pattern, value): + return + + return {InvalidPattern(path[-1], value, pattern, path)} + + +def max_validator(value: Any, type_hint: type[Max[int]], path: list[str | int]) -> set[UserWarning] | None: + max_value = get_args(type_hint)[0] + if value <= max_value: + return + return {InvalidValue(path[-1], value, f"<={max_value}")} + + +def min_validator(value: Any, type_hint: type[Min[int]], path: list[str | int]) -> set[UserWarning] | None: + min_value = get_args(type_hint)[0] + if value >= min_value: + return + return {InvalidValue(path[-1], value, f">={min_value}")} + + +VALIDATORS = { + Annotated: annotated_validator, + NoneType: none_validator, + UnionType: union_validator, + Union: union_validator, + Optional: optional_validator, + str: str_validator, + int: int_validator, + bool: bool_validator, + list: list_validator, + dict: dict_validator, + "avd_class": avd_class_validator, + ValidValues: valid_values_validator, + Format: format_values_validator, + MaxLen: max_len_validator, + MinLen: min_len_validator, + Max: max_validator, + Min: min_validator, + Pattern: pattern_validator, +} -def coercer(value: Any, schema: dict, cls: Type | None) -> bool: - if value is None or schema is None: - return value - if schema["type"] == "dict": - if isinstance(value, cls): - return value - return cls(**value) +def validator(value: Any, type_hint: type, path: list[str | int]) -> set[UserWarning] | None: + # Identify subclass of AvdBase without importing AvdBase (circular import) + if hasattr(type_hint, "_allow_other_keys"): + origin = "avd_class" + # Identify Validation types without importing the base type (circular import) + elif hasattr(type_hint, "is_validation_type") and hasattr(type_hint, "__origin__"): + origin = type_hint.__origin__ + else: + if not (origin := get_origin(type_hint)): + origin = type_hint - if schema["type"] in SCHEMA_SIMPLE_TYPES_TO_PYTHON_MAP: - python_type = SCHEMA_SIMPLE_TYPES_TO_PYTHON_MAP[schema["type"]] - if isinstance(value, python_type): - return value - return python_type(value) + try: + return VALIDATORS[origin](value, type_hint, path) + except KeyError: + raise TypeError(f"Unable to validate type {origin} for path {path} from type hint {type_hint}") diff --git a/python-avd/schema_tools/constants.py b/python-avd/schema_tools/constants.py index bd12b07ba01..db871204c36 100644 --- a/python-avd/schema_tools/constants.py +++ b/python-avd/schema_tools/constants.py @@ -43,8 +43,8 @@ "eos_designs": EOS_DESIGNS_JSONSCHEMA_PATH, } PYDANTIC_MODEL_PATHS = { - "eos_cli_config_gen": REPO_ROOT.joinpath("python-avd/pyavd/_schema/eos_cli_config_gen.py"), - "eos_designs": REPO_ROOT.joinpath("python-avd/pyavd/_schema/eos_designs.py"), + "eos_cli_config_gen": EOS_CLI_CONFIG_GEN_SCHEMA_DIR.joinpath("eos_cli_config_gen.py"), + "eos_designs": EOS_DESIGNS_SCHEMA_DIR.joinpath("eos_designs.py"), } DOCS_PATHS = { "eos_cli_config_gen": EOS_CLI_CONFIG_GEN_DOCS_PATH, diff --git a/python-avd/schema_tools/generate_pydantic/pydanticsrcgen.py b/python-avd/schema_tools/generate_pydantic/pydanticsrcgen.py index a3b8fce6625..13d25136d4e 100644 --- a/python-avd/schema_tools/generate_pydantic/pydanticsrcgen.py +++ b/python-avd/schema_tools/generate_pydantic/pydanticsrcgen.py @@ -7,7 +7,7 @@ from keyword import iskeyword from typing import TYPE_CHECKING -from .models import FieldSrc, FieldTypeHintSrc, ModelSrc, SrcData +from .src_generators import FieldSrc, FieldTypeHintSrc, ModelSrc, SrcData from .utils import generate_class_name, generate_class_name_from_ref, get_annotations_for_field if TYPE_CHECKING: @@ -16,15 +16,13 @@ class SrcGenBase(ABC): # TODO: - # Optimize ref handling? # add deprecation handling # dynamic_valid_values - # format # Create a base model for lists so child items can be rendered by their own generators instead of trying to handle it inside lists. def generate_pydantic_src(self, schema: AvdSchemaField, class_name: str | None = None) -> FieldSrc: """ - Yields ModelSrc for the given schema. + Returns ModelSrc for the given schema. Requires an input schema of type "AvdSchemaDict". Recursively walks child schemas and creates nested classes and fields. @@ -119,19 +117,19 @@ class SrcGenInt(SrcGenBase): # return field_args - def get_type_hints(self) -> list[str]: - if self.schema.valid_values: - valid_values_as_string = [str(valid_value) for valid_value in self.schema.valid_values] - field_type = f"Literal[{', '.join(valid_values_as_string)}]" - else: - field_type = "int" + # def get_type_hints(self) -> list[str]: + # if self.schema.valid_values: + # valid_values_as_string = [str(valid_value) for valid_value in self.schema.valid_values] + # field_type = f"Literal[{', '.join(valid_values_as_string)}]" + # else: + # field_type = "int" - return [ - FieldTypeHintSrc( - field_type=field_type, - annotations=get_annotations_for_field(self.schema), - ) - ] + # return [ + # FieldTypeHintSrc( + # field_type=field_type, + # annotations=get_annotations_for_field(self.schema), + # ) + # ] class SrcGenBool(SrcGenBase): @@ -157,19 +155,19 @@ def get_default(self) -> str: else: return str(self.schema.default) - def get_type_hints(self) -> list[str]: - if self.schema.valid_values: - valid_values_with_quotes = [f'"{valid_value}"' for valid_value in self.schema.valid_values] - field_type = f"Literal[{', '.join(valid_values_with_quotes)}]" - else: - field_type = "str" + # def get_type_hints(self) -> list[str]: + # if self.schema.valid_values: + # valid_values_with_quotes = [f'"{valid_value}"' for valid_value in self.schema.valid_values] + # field_type = f"Literal[{', '.join(valid_values_with_quotes)}]" + # else: + # field_type = "str" - return [ - FieldTypeHintSrc( - field_type=field_type, - annotations=get_annotations_for_field(self.schema), - ) - ] + # return [ + # FieldTypeHintSrc( + # field_type=field_type, + # annotations=get_annotations_for_field(self.schema), + # ) + # ] class SrcGenList(SrcGenBase): @@ -275,7 +273,7 @@ def get_imports(self) -> set[str]: imports = set() if self.schema.field_ref: schema_name = self.schema.field_ref.split("#", maxsplit=1)[0] - imports.add(f"from .{schema_name} import {generate_class_name(schema_name)}") + imports.add(f"from pyavd._{schema_name}.schema.{schema_name} import {generate_class_name(schema_name)}") return imports @@ -301,13 +299,15 @@ def get_base_classes(self) -> list[str]: if self.get_class_name() == "EosDesigns": return ["AvdEosDesignsRootDictBase"] if self.get_class_name() == "EosCliConfigGen": - return ["object"] + return ["AvdBase"] return [] def get_imports(self) -> set[str]: imports = super().get_imports() or set() if self.get_class_name() == "EosDesigns": - imports.add("from .models import AvdEosDesignsRootDictBase") + imports.add("from pyavd._schema.models import AvdEosDesignsRootDictBase") + if self.get_class_name() == "EosCliConfigGen": + imports.add("from pyavd._schema.models import AvdBase") return imports def get_children_classes_and_fields(self) -> tuple[list[ModelSrc], list[AvdSchemaField]]: diff --git a/python-avd/schema_tools/generate_pydantic/models.py b/python-avd/schema_tools/generate_pydantic/src_generators.py similarity index 89% rename from python-avd/schema_tools/generate_pydantic/models.py rename to python-avd/schema_tools/generate_pydantic/src_generators.py index fbf7a318bf0..28487fea5b8 100644 --- a/python-avd/schema_tools/generate_pydantic/models.py +++ b/python-avd/schema_tools/generate_pydantic/src_generators.py @@ -6,6 +6,7 @@ from abc import ABC, abstractmethod from dataclasses import dataclass from textwrap import indent, wrap +from typing import Any import isort @@ -17,7 +18,7 @@ # from dataclasses import dataclass, field BASE_IMPORTS = """\ -from .models import AvdDictBaseModel +from pyavd._schema.models import AvdDictBaseModel """ BASE_MODEL_NAME = "AvdDictBaseModel" # "BaseModel" DECORATOR = "" # "@dataclass" @@ -305,17 +306,6 @@ def get_imports(self) -> set: return imports -@dataclass -class ConvertTypesSrc(AnnotationSrc): - types: list[str] - - def __str__(self) -> str: - return f"ConvertTypes[{', '.join(self.types)}]" - - def get_imports(self) -> set: - return {"from .types import ConvertTypes"} - - @dataclass class FormatSrc(AnnotationSrc): format: str @@ -324,7 +314,7 @@ def __str__(self) -> str: return f"Format['{self.format}']" def get_imports(self) -> set: - return {"from .types import Format"} + return {"from pyavd._schema.types import Format"} @dataclass @@ -335,7 +325,7 @@ def __str__(self) -> str: return f"MinLen[{self.min_len}]" def get_imports(self) -> set: - return {"from .types import MinLen"} + return {"from pyavd._schema.types import MinLen"} @dataclass @@ -346,7 +336,29 @@ def __str__(self) -> str: return f"MaxLen[{self.max_len}]" def get_imports(self) -> set: - return {"from .types import MaxLen"} + return {"from pyavd._schema.types import MaxLen"} + + +@dataclass +class MinSrc(AnnotationSrc): + min_value: int + + def __str__(self) -> str: + return f"Min[{self.min_value}]" + + def get_imports(self) -> set: + return {"from pyavd._schema.types import Min"} + + +@dataclass +class MaxSrc(AnnotationSrc): + max_value: list[str] + + def __str__(self) -> str: + return f"Max[{self.max_value}]" + + def get_imports(self) -> set: + return {"from pyavd._schema.types import Max"} @dataclass @@ -354,10 +366,10 @@ class PatternSrc(AnnotationSrc): pattern: str def __str__(self) -> str: - return f"Pattern['{self.pattern}']" + return f'Pattern[r"{self.pattern}"]' def get_imports(self) -> set: - return {"from .types import Pattern"} + return {"from pyavd._schema.types import Pattern"} @dataclass @@ -366,4 +378,22 @@ def __str__(self) -> str: return "ToLower" def get_imports(self) -> set: - return {"from .types import ToLower"} + return {"from pyavd._schema.types import ToLower"} + + +@dataclass +class ValidValuesSrc(AnnotationSrc): + valid_values: list[Any] + + def __str__(self) -> str: + valid_values = [self.quote_string(valid_value) for valid_value in self.valid_values] + return f"ValidValues[{', '.join(valid_values)}]" + + @staticmethod + def quote_string(value: Any) -> Any: + if isinstance(value, str): + value = f"'{value}'" + return str(value) + + def get_imports(self) -> set: + return {"from pyavd._schema.types import ValidValues"} diff --git a/python-avd/schema_tools/generate_pydantic/utils.py b/python-avd/schema_tools/generate_pydantic/utils.py index a1c499c4007..f4f0022f537 100644 --- a/python-avd/schema_tools/generate_pydantic/utils.py +++ b/python-avd/schema_tools/generate_pydantic/utils.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING -from .models import ConvertTypesSrc, MinLenSrc, MaxLenSrc, FormatSrc, PatternSrc, ToLowerSrc +from .src_generators import FormatSrc, MaxLenSrc, MaxSrc, MinLenSrc, MinSrc, PatternSrc, ToLowerSrc, ValidValuesSrc if TYPE_CHECKING: from ..metaschema.meta_schema_model import AvdSchemaField @@ -52,9 +52,8 @@ def generate_class_name_from_ref(ref: str) -> str: def get_annotations_for_field(schema: AvdSchemaField) -> list[type]: annotations = [] if schema.type == "str": - if schema.convert_types: - annotations.append(ConvertTypesSrc(schema.convert_types)) if schema.convert_to_lower_case: + # This *must* come first to ensure we lower the value before further validation. annotations.append(ToLowerSrc()) if schema.min_length: annotations.append(MinLenSrc(schema.min_length)) @@ -64,19 +63,30 @@ def get_annotations_for_field(schema: AvdSchemaField) -> list[type]: annotations.append(FormatSrc(schema.format)) if schema.pattern: annotations.append(PatternSrc(schema.pattern)) + if schema.valid_values: + annotations.append(ValidValuesSrc(schema.valid_values)) + + elif schema.type == "int": + if schema.min: + annotations.append(MinSrc(schema.min)) + if schema.max: + annotations.append(MaxSrc(schema.max)) + if schema.valid_values: + annotations.append(ValidValuesSrc(schema.valid_values)) + # TODO: The rest... + + elif schema.type == "list": + if schema.min_length: + annotations.append(MinLenSrc(schema.min_length)) + if schema.max_length: + annotations.append(MaxLenSrc(schema.max_length)) + # TODO: The rest... + + elif schema.type == "bool": + if schema.valid_values: + annotations.append(ValidValuesSrc(schema.valid_values)) + # TODO: The rest... - # elif schema.type == "int": - # annotation = IntConvertSrc( - # convert_types=schema.convert_types, - # ) - # if annotation: - # annotations.append(annotation) - - # elif schema.type == "bool": - # annotation = BoolConvertSrc( - # convert_types=schema.convert_types, - # ) - # if annotation: - # annotations.append(annotation) + # TODO: The rest... return annotations diff --git a/python-avd/schema_tools/metaschema/meta_schema_model.py b/python-avd/schema_tools/metaschema/meta_schema_model.py index 6801faf2454..19df0a3c002 100644 --- a/python-avd/schema_tools/metaschema/meta_schema_model.py +++ b/python-avd/schema_tools/metaschema/meta_schema_model.py @@ -6,14 +6,14 @@ from abc import ABC from enum import Enum from functools import cached_property -from typing import Annotated, Any, ClassVar, Generator, List, Literal, Union +from typing import Annotated, Any, ClassVar, Generator, Literal, Union from pydantic import BaseModel, ConfigDict, Field, constr from ..generate_docs.tablerowgen import TableRow, TableRowGenBase, TableRowGenBool, TableRowGenDict, TableRowGenInt, TableRowGenList, TableRowGenStr from ..generate_docs.yamllinegen import YamlLine, YamlLineGenBase, YamlLineGenBool, YamlLineGenDict, YamlLineGenInt, YamlLineGenList, YamlLineGenStr -from ..generate_pydantic.models import SrcData from ..generate_pydantic.pydanticsrcgen import SrcGenBase, SrcGenBool, SrcGenDict, SrcGenInt, SrcGenList, SrcGenRootDict, SrcGenStr +from ..generate_pydantic.src_generators import SrcData from .resolvemodel import merge_schema_from_ref """ @@ -123,12 +123,12 @@ class DocumentationOptions(BaseModel): # Signal to __init__ if the $ref in the schema should be resolved before initializing the pydantic model. _resolve_schema: ClassVar[bool] = True - _only_resolve_schema: ClassVar[str | None] = None + _resolve_hide_keys: ClassVar[bool | None] = None - def __init__(self, resolve_schema: bool | None = None, only_resolve_schema: str | None = None, **data): + def __init__(self, resolve_schema: bool | None = None, resolve_hide_keys: bool | None = None, **data): """ Overrides BaseModel.__init__(**data). - Takes a kwarg "resolve_schema" which controls if all subclasses of AvdSchemaBaseModel should expand any $ref in the input schema. + Takes a kwarg "resolve_hide_keys" which controls how all subclasses of AvdSchemaBaseModel should expand any $ref in the input schema. The $ref expansion _only_ covers this field. Any $ref on child fields are expanded as they are initialized by Pydantic since they are based on this base class. @@ -137,11 +137,11 @@ def __init__(self, resolve_schema: bool | None = None, only_resolve_schema: str # Setting the resolve_schema attribute on the class, so all sub-classes will inherit this automatically. if resolve_schema is not None: AvdSchemaBaseModel._resolve_schema = resolve_schema - if only_resolve_schema is not None: - AvdSchemaBaseModel._only_resolve_schema = only_resolve_schema + if resolve_hide_keys is not None: + AvdSchemaBaseModel._resolve_hide_keys = resolve_hide_keys if self._resolve_schema: - data = merge_schema_from_ref(data, only_resolve_schema=self._only_resolve_schema) + data = merge_schema_from_ref(data, resolve_hide_keys=self._resolve_hide_keys) super().__init__(**data) diff --git a/python-avd/schema_tools/metaschema/resolvemodel.py b/python-avd/schema_tools/metaschema/resolvemodel.py index dc98dabff19..5b4571ea8f3 100644 --- a/python-avd/schema_tools/metaschema/resolvemodel.py +++ b/python-avd/schema_tools/metaschema/resolvemodel.py @@ -11,7 +11,7 @@ from ..store import create_store -def merge_schema_from_ref(schema: dict, only_resolve_schema: str | None = None) -> dict: +def merge_schema_from_ref(schema: dict, resolve_hide_keys: bool | None = None) -> dict: """ Returns a copy of the schema with any $ref resolved. @@ -19,18 +19,18 @@ def merge_schema_from_ref(schema: dict, only_resolve_schema: str | None = None) Any child schemas will _not_ be resolved. - By setting "only_resolve_schema" it is possible to prevent dicts from other schemas from being resolved. + By setting "resolve_hide_keys: False" it is possible to prevent dicts with hide_keys set in the schema from being resolved. """ if "$ref" not in schema: return schema - if schema.get("type") == "dict" and only_resolve_schema and not str(schema["$ref"]).startswith(only_resolve_schema + "#"): - # Do not resolve a dict ref if the ref does not match the given "only_resolve_schema" + if schema.get("documentation_options", {}).get("hide_keys") and resolve_hide_keys is False: + # Do not resolve a dict ref if it has hide_keys and resolve_hide_keys is false return schema schema = deepcopy(schema) ref = schema.pop("$ref") - ref_schema = merge_schema_from_ref(get_schema_from_ref(ref), only_resolve_schema) + ref_schema = merge_schema_from_ref(get_schema_from_ref(ref), resolve_hide_keys) if ref_schema["type"] != schema["type"]: # TODO: Consider if this should be a pyavd specific error raise ValueError( diff --git a/python-avd/scripts/build-pydantic-models.py b/python-avd/scripts/build-pydantic-models.py index 38f3def7a61..a5ca5d3bfc6 100755 --- a/python-avd/scripts/build-pydantic-models.py +++ b/python-avd/scripts/build-pydantic-models.py @@ -2,7 +2,7 @@ # 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. -import subprocess +# import subprocess from pathlib import Path from sys import path @@ -10,7 +10,7 @@ path.insert(0, str(Path(__file__).parents[1])) from schema_tools.constants import PYDANTIC_MODEL_PATHS -from schema_tools.generate_pydantic.models import FileSrc +from schema_tools.generate_pydantic.src_generators import FileSrc from schema_tools.metaschema.meta_schema_model import AristaAvdSchema from schema_tools.store import create_store @@ -20,12 +20,12 @@ if schema_name not in STORE: raise KeyError(f"Invalid schema name '{schema_name}'") - schema = AristaAvdSchema(only_resolve_schema=schema_name, **STORE[schema_name]) + schema = AristaAvdSchema(resolve_hide_keys=False, **STORE[schema_name]) print(f"Building pydantic from schema '{schema_name}'") schemasrc = schema._generate_pydantic_src(class_name=schema_name) src_file_contents = FileSrc(classes=[schemasrc.cls]) with open(pydantic_model_path, mode="w", encoding="UTF-8") as file: file.write(str(src_file_contents)) - print(f"Running 'black' for pydantic model file '{pydantic_model_path}'") - subprocess.run(["black", str(pydantic_model_path)], check=False) + # print(f"Running 'black' for pydantic model file '{pydantic_model_path}'") + # subprocess.run(["black", str(pydantic_model_path)], check=False) diff --git a/python-avd/tests/pyavd/eos_cli_config_gen/test_pydantic_model.py b/python-avd/tests/pyavd/eos_cli_config_gen/test_pydantic_model.py index 0b6e123ece6..e83108db9d1 100644 --- a/python-avd/tests/pyavd/eos_cli_config_gen/test_pydantic_model.py +++ b/python-avd/tests/pyavd/eos_cli_config_gen/test_pydantic_model.py @@ -1,12 +1,10 @@ -# Copyright (c) 2023 Arista Networks, Inc. +# 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. -import pytest -from pyavd.avd_schema_tools import AvdSchemaTools -from pyavd.schema.eos_cli_config_gen import EosCliConfigGen -from pydantic_core import ValidationError +from pyavd._eos_cli_config_gen.schema.eos_cli_config_gen import EosCliConfigGen +from pyavd._schema.store import create_store -SCHEMA = AvdSchemaTools(schema_id="eos_cli_config_gen").avdschema.resolved_schema +SCHEMA = create_store()["eos_cli_config_gen"] def test_eos_cli_config_gen_with_valid_data(hostname: str, all_inputs: dict): @@ -14,6 +12,9 @@ def test_eos_cli_config_gen_with_valid_data(hostname: str, all_inputs: dict): Test EosCliConfigGen pydantic model with valid data. """ structured_config = all_inputs[hostname] + + assert EosCliConfigGen.validate(structured_config) + EosCliConfigGen(**structured_config) # If nothing raises, the model is accepted. @@ -38,5 +39,7 @@ def test_eos_cli_config_gen_with_invalid_data(hostname: str, all_inputs: dict): structured_config.update({"ethernet_interfaces": [{"name": "dummy", "invalid_key": "some_value"}]}) updated = "ethernet_interfaces.0.invalid_key" - with pytest.raises(ValidationError, match=rf"{updated}\n Extra inputs are not permitted"): - EosCliConfigGen(**structured_config) + # with pytest.raises(ValidationError, match=rf"{updated}\n Extra inputs are not permitted"): + # EosCliConfigGen(**structured_config) + assert not EosCliConfigGen.validate(structured_config) + # TODO: assert warnings diff --git a/python-avd/tests/pyavd/eos_designs/test_pydantic_model.py b/python-avd/tests/pyavd/eos_designs/test_pydantic_model.py index 2a39b74527a..d1d12f6da88 100644 --- a/python-avd/tests/pyavd/eos_designs/test_pydantic_model.py +++ b/python-avd/tests/pyavd/eos_designs/test_pydantic_model.py @@ -1,13 +1,12 @@ -# Copyright (c) 2023 Arista Networks, Inc. +# 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. -import pytest -from pyavd.avd_schema_tools import AvdSchemaTools -from pyavd.schema.eos_cli_config_gen import EosCliConfigGen -from pyavd.schema.eos_designs import EosDesigns -from pydantic_core import ValidationError +# import pytest +# from pyavd._eos_cli_config_gen.schema.eos_cli_config_gen import EosCliConfigGen +from pyavd._eos_designs.schema.eos_designs import EosDesigns +from pyavd._schema.store import create_store -SCHEMA = AvdSchemaTools(schema_id="eos_designs").avdschema.resolved_schema +SCHEMA = create_store()["eos_designs"] CSC_DATA = { "fabric_name": "test", @@ -22,92 +21,104 @@ ] -@pytest.mark.parametrize(("prefix", "expected_data"), CSC_TESTS) -def test_eos_designs_custom_structured_configuration(prefix: str, expected_data: dict): - data = {**CSC_DATA, "custom_structured_configuration_prefix": prefix} - loaded_model = EosDesigns(**data) - assert hasattr(loaded_model, "custom_structured_configurations") - assert isinstance(loaded_model.custom_structured_configurations, list) - returned_data = [] - for entry in loaded_model.custom_structured_configurations: - assert isinstance(entry, EosDesigns.CustomStructuredConfiguration) - returned_data.append(entry.model_dump(exclude_defaults=True, exclude_unset=True, by_alias=True)) +# @pytest.mark.parametrize(("prefix", "expected_data"), CSC_TESTS) +# def test_eos_designs_custom_structured_configuration(prefix: str, expected_data: dict): +# data = {**CSC_DATA, "custom_structured_configuration_prefix": prefix} +# loaded_model = EosDesigns(**data) +# assert hasattr(loaded_model, "custom_structured_configurations") +# assert isinstance(loaded_model.custom_structured_configurations, list) +# returned_data = [] +# for entry in loaded_model.custom_structured_configurations: +# assert isinstance(entry, EosDesigns.CustomStructuredConfiguration) +# returned_data.append(entry.model_dump(exclude_defaults=True, exclude_unset=True, by_alias=True)) - assert returned_data == expected_data +# assert returned_data == expected_data - # Ensure the keys got popped before validation. - assert not [key for key in (loaded_model.model_extra or {}) if key.startswith(prefix)] +# # Ensure the keys got popped before validation. +# assert not [key for key in (loaded_model.model_extra or {}) if key.startswith(prefix)] def test_eos_designs_with_valid_data(hostname: str, all_inputs: dict): """ Test EosDesigns pydantic model with valid data. """ - structured_config = all_inputs[hostname] - EosDesigns(**structured_config) - # If nothing raises, the model is accepted. + inputs = all_inputs[hostname] + assert EosDesigns.validate(inputs) -def test_eos_designs_with_invalid_data(hostname: str, all_inputs: dict): - """ - Test EosDesigns pydantic model with invalid data. - """ - 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 key not in SCHEMA["keys"]: - continue - value.update({"invalid_key": "some_value"}) - updated = f"{key}.invalid_key" - break - - # No dict found, so we insert our own instead - if not updated: - structured_config.update({"bgp_peer_groups": {"invalid_key": "some_value"}}) - updated = "bgp_peer_groups.invalid_key" - - with pytest.raises(ValidationError) as exc_info: - EosDesigns(**structured_config) - errors = exc_info.value.errors() - msgs = set(error["msg"] for error in errors) - assert msgs == {"Extra inputs are not permitted"} - - -def test_eos_cli_config_gen_with_valid_data(hostname: str, structured_configs: dict): - """ - Test EosCliConfigGen pydantic model with valid data. - Here we test with the structured configs of eos_designs so we get broader coverage. - """ - structured_config = structured_configs[hostname] - EosCliConfigGen(**structured_config) + # EosDesigns(**inputs) # If nothing raises, the model is accepted. -def test_eos_cli_config_gen_with_invalid_data(hostname: str, structured_configs: dict): - """ - Test EosCliConfigGen pydantic model with invalid data. - Here we test with the structured configs of eos_designs so we get broader coverage. - """ - structured_config: dict = 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 = f"{key}.invalid_key" - break - - # No dict found, so we insert our own instead - if not updated: - structured_config.update({"ethernet_interfaces": [{"name": "dummy", "invalid_key": "some_value"}]}) - updated = "ethernet_interfaces.0.invalid_key" - - with pytest.raises(ValidationError) as exc_info: - EosCliConfigGen(**structured_config) - errors = exc_info.value.errors() - msgs = set(error["msg"] for error in errors) - assert msgs == {"Extra inputs are not permitted"} +# def test_eos_designs_with_invalid_data(hostname: str, all_inputs: dict): +# """ +# Test EosDesigns pydantic model with invalid data. +# """ +# inputs: 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 inputs.items(): +# if not isinstance(value, dict) or key not in SCHEMA["keys"]: +# continue +# value.update({"invalid_key": "some_value"}) +# updated = f"{key}.invalid_key" +# break + +# # No dict found, so we insert our own instead +# if not updated: +# inputs.update({"bgp_peer_groups": {"invalid_key": "some_value"}}) +# updated = "bgp_peer_groups.invalid_key" + +# # with pytest.raises(ValidationError) as exc_info: +# # EosDesigns(**inputs) +# # errors = exc_info.value.errors() +# # msgs = set(error["msg"] for error in errors) +# # assert msgs == {"Extra inputs are not permitted"} + +# assert not EosDesigns.validate(inputs) +# # TODO: assert warnings + + +# def test_eos_cli_config_gen_with_valid_data(hostname: str, structured_configs: dict): +# """ +# Test EosCliConfigGen pydantic model with valid data. +# Here we test with the structured configs of eos_designs so we get broader coverage. +# """ +# structured_config = structured_configs[hostname] + +# assert EosCliConfigGen.validate(structured_config) + +# # EosCliConfigGen(**structured_config) +# # If nothing raises, the model is accepted. + + +# def test_eos_cli_config_gen_with_invalid_data(hostname: str, structured_configs: dict): +# """ +# Test EosCliConfigGen pydantic model with invalid data. +# Here we test with the structured configs of eos_designs so we get broader coverage. +# """ +# structured_config: dict = 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 = f"{key}.invalid_key" +# break + +# # No dict found, so we insert our own instead +# if not updated: +# structured_config.update({"ethernet_interfaces": [{"name": "dummy", "invalid_key": "some_value"}]}) +# updated = "ethernet_interfaces.0.invalid_key" + +# # with pytest.raises(ValidationError) as exc_info: +# # EosCliConfigGen(**structured_config) +# # errors = exc_info.value.errors() +# # msgs = set(error["msg"] for error in errors) +# # assert msgs == {"Extra inputs are not permitted"} + +# assert not EosCliConfigGen.validate(structured_config) +# # TODO: assert warnings diff --git a/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_bool.py b/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_bool.py index fde2a0f12df..352e9292440 100644 --- a/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_bool.py +++ b/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_bool.py @@ -5,18 +5,18 @@ from importlib import import_module from pathlib import Path from sys import path +from typing import Generator from unittest import mock import pytest -from pydantic import BaseModel, ValidationError # Override global path to load schema from source instead of any installed version. path.insert(0, str(Path(__file__).parents[3])) -import pyavd.schema.models -import pyavd.schema.types +import pyavd._schema.models +import pyavd._schema.types -from schema_tools.generate_pydantic.models import PydanticFileSrc +from schema_tools.generate_pydantic.src_generators import FileSrc from schema_tools.generate_pydantic.utils import generate_class_name from schema_tools.metaschema.meta_schema_model import AristaAvdSchema @@ -30,7 +30,7 @@ "keys": { "test_value": { "type": "bool", - "convert_types": ["int", "str"], + "convert_types": ["int", "str"], # Part of meta schema but not implemented in converter "default": True, "valid_values": [True], # Part of meta schema but not implemented in converter "dynamic_valid_values": "valid_booleans", # Part of meta schema but not implemented in converter @@ -42,29 +42,37 @@ } TESTS = [ - # (test_value: int | None, expected_errors: set, expected_value: int) - (True, None, True), # Valid value. No errors. - (False, None, False), # Valid value. No errors. - (11.0123, {"Input should be a valid boolean"}, None), # Invalid value. - (None, {"Input should be a valid boolean"}, None), # Required is set, so None is not ignored. - ("11", None, True), # Converted to True. No errors. - ("", None, False), # Converted to False. No errors. - (12, None, True), # Converted to True. No errors. - (0, None, False), # Converted to False. No errors. + # (test_value, expected_warnings: tuple, expected_warning_pattern: str) + (True, None, None), # Valid value. No errors. + (False, None, None), # Valid value. No errors. + ( + 11.0123, + (pyavd._schema.types.InvalidType,), + "Got invalid type for 'test_value'. Expected '', got ''", + ), # Invalid value. + ( + None, + (pyavd._schema.types.InvalidType,), + "Got invalid type for 'test_value'. Expected '', got ''", + ), # Required is set, so None is not ignored. + ("11", None, None), # Converted to True. No errors. + ("", None, None), # Converted to False. No errors. + (12, None, None), # Converted to True. No errors. + (0, None, None), # Converted to False. No errors. ] @pytest.fixture(scope="module") -def BoolSchemaModel() -> type[BaseModel]: +def BoolSchemaModel() -> Generator[type, None, None]: schema_name = "bool_schema" schema_model = AristaAvdSchema(**TEST_SCHEMA) output_file = Path(__file__).parent.joinpath(f"artifacts/{schema_name}.py") schemasrc = schema_model._generate_pydantic_src(class_name=schema_name) - src_file_contents = PydanticFileSrc(classes=[schemasrc.cls]) + src_file_contents = FileSrc(classes=[schemasrc.cls]) with open(output_file, mode="w", encoding="UTF-8") as file: file.write(str(src_file_contents)) - with mock.patch.dict(sys.modules, {"artifacts.types": pyavd.schema.types, "artifacts.models": pyavd.schema.models}): + with mock.patch.dict(sys.modules, {"artifacts.types": pyavd._schema.types, "artifacts.models": pyavd._schema.models}): module = import_module(f"artifacts.{schema_name}") class_name = generate_class_name(schema_name) Cls = getattr(module, class_name) @@ -75,21 +83,16 @@ def BoolSchemaModel() -> type[BaseModel]: # output_file.unlink() -@pytest.mark.parametrize(("test_value", "expected_errors", "expected_value"), TESTS) -def test_generated_schema(test_value, expected_errors: set, expected_value: int | None, BoolSchemaModel: type[BaseModel]): +@pytest.mark.parametrize(("test_value", "expected_warnings", "expected_warning_pattern"), TESTS) +def test_generated_schema(test_value, expected_warnings: tuple | None, expected_warning_pattern: str | None, BoolSchemaModel: type): test_value_id = id(test_value) - if expected_errors: - with pytest.raises(ValidationError) as exc_info: - BoolSchemaModel(test_value=test_value) - errors = exc_info.value.errors() - msgs = set(error["msg"] for error in errors) - assert msgs == expected_errors + if expected_warnings: + with pytest.warns(expected_warnings, match=expected_warning_pattern): + assert not BoolSchemaModel.validate({"test_value": test_value}) else: # No errors expected. - data = BoolSchemaModel(test_value=test_value) - assert hasattr(data, "test_value") - assert getattr(data, "test_value") == expected_value + assert BoolSchemaModel.validate({"test_value": test_value}) # Make sure the test value was not changed assert id(test_value) == test_value_id diff --git a/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_int.py b/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_int.py index dce6d0b91b7..de87a99c2a3 100644 --- a/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_int.py +++ b/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_int.py @@ -5,18 +5,18 @@ from importlib import import_module from pathlib import Path from sys import path +from typing import Generator from unittest import mock import pytest -from pydantic import BaseModel, ValidationError # Override global path to load schema from source instead of any installed version. path.insert(0, str(Path(__file__).parents[3])) -import pyavd.schema.models -import pyavd.schema.types +import pyavd._schema.models +import pyavd._schema.types -from schema_tools.generate_pydantic.models import PydanticFileSrc +from schema_tools.generate_pydantic.src_generators import FileSrc from schema_tools.generate_pydantic.utils import generate_class_name from schema_tools.metaschema.meta_schema_model import AristaAvdSchema @@ -27,7 +27,6 @@ TEST_SCHEMA = { "type": "dict", "keys": { - "valid_values": {"type": "list"}, "test_value": { "type": "int", "convert_types": ["bool", "str", "float"], @@ -35,7 +34,7 @@ "min": 2, "max": 20, "valid_values": [0, 11, 22], - "dynamic_valid_values": "valid_values", + "dynamic_valid_values": "valid_values", # Part of meta schema but not implemented in converter "required": True, "description": "Some integer", "display_name": "Integer", @@ -44,31 +43,47 @@ } TESTS = [ - # (test_value: int | None, valid_values: list[int] | None, expected_errors: set, expected_value: int) - (11, None, None, 11), # Valid value. No errors. - (False, None, {"Input should be greater than or equal to 2"}, None), # False is converted to 0 which is valid but below min. - (True, None, {"Input should be 0, 11 or 22"}, None), # True is converted to 1 which is not valid. - ("11", None, None, 11), # Converted to 11. No errors. - (11.0123, None, None, 11), # Converted to 11. No errors. - (None, None, {"Input should be 0, 11 or 22"}, None), # Required is set, so None is not ignored. - (12, None, {"Input should be 0, 11 or 22"}, None), # Invalid value. - ([], None, {"Input should be 0, 11 or 22"}, None), # Invalid type. - (0, None, {"Input should be greater than or equal to 2"}, None), # Valid but below min. - (22, None, {"Input should be less than or equal to 20"}, None), # Valid but above max. + # (test_value, expected_warnings: tuple, expected_warning_pattern: str) + (11, None, None), # Valid value. No errors. + ( + False, + (pyavd._schema.types.InvalidValue,), + r"Got invalid value for 'test_value'. Expected '>=2', got 'False'", + ), # False is converted to 0 which is valid but below min. + ( + True, + (pyavd._schema.types.InvalidValue,), + r"Got invalid value for 'test_value'. Expected '\(0, 11, 22\)', got 'True'", + ), # True is converted to 1 which is not valid. + ("11", None, None), # Converted to 11. No errors. + ( + 11.0123, + (pyavd._schema.types.InvalidType,), + r"Got invalid type for 'test_value'. Expected '', got ''", + ), # Converted to 11. No errors. + ( + None, + (pyavd._schema.types.InvalidType,), + r"Got invalid type for 'test_value'. Expected '', got ''", + ), # Required is set, so None is not ignored. + (12, (pyavd._schema.types.InvalidValue,), r"Got invalid value for 'test_value'. Expected '\(0, 11, 22\)', got '12'"), # Invalid value. + ([], (pyavd._schema.types.InvalidType,), r"Got invalid type for 'test_value'. Expected '', got ''"), # Invalid type. + (0, (pyavd._schema.types.InvalidValue,), r"Got invalid value for 'test_value'. Expected '>=2', got '0'"), # Valid but below min. + (22, (pyavd._schema.types.InvalidValue,), r"Got invalid value for 'test_value'. Expected '<=20', got '22'"), # Valid but above max. ] @pytest.fixture(scope="module") -def IntSchemaModel() -> type[BaseModel]: +def IntSchemaModel() -> Generator[type, None, None]: schema_name = "int_schema" schema_model = AristaAvdSchema(**TEST_SCHEMA) output_file = Path(__file__).parent.joinpath(f"artifacts/{schema_name}.py") schemasrc = schema_model._generate_pydantic_src(class_name=schema_name) - src_file_contents = PydanticFileSrc(classes=[schemasrc.cls]) + src_file_contents = FileSrc(classes=[schemasrc.cls]) with open(output_file, mode="w", encoding="UTF-8") as file: file.write(str(src_file_contents)) - with mock.patch.dict(sys.modules, {"artifacts.types": pyavd.schema.types, "artifacts.models": pyavd.schema.models}): + with mock.patch.dict(sys.modules, {"artifacts.types": pyavd._schema.types, "artifacts.models": pyavd._schema.models}): module = import_module(f"artifacts.{schema_name}") class_name = generate_class_name(schema_name) Cls = getattr(module, class_name) @@ -79,21 +94,16 @@ def IntSchemaModel() -> type[BaseModel]: # output_file.unlink() -@pytest.mark.parametrize(("test_value", "valid_values", "expected_errors", "expected_value"), TESTS) -def test_generated_schema(test_value, valid_values: list | None, expected_errors: set, expected_value: int | None, IntSchemaModel: type[BaseModel]): +@pytest.mark.parametrize(("test_value", "expected_warnings", "expected_warning_pattern"), TESTS) +def test_generated_schema(test_value, expected_warnings: tuple | None, expected_warning_pattern: str | None, IntSchemaModel: type): test_value_id = id(test_value) - if expected_errors: - with pytest.raises(ValidationError) as exc_info: - IntSchemaModel(test_value=test_value, valid_values=valid_values) - errors = exc_info.value.errors() - msgs = set(error["msg"] for error in errors) - assert msgs == expected_errors + if expected_warnings: + with pytest.warns(expected_warnings, match=expected_warning_pattern): + assert not IntSchemaModel.validate({"test_value": test_value}) else: # No errors expected. - data = IntSchemaModel(test_value=test_value, valid_values=valid_values) - assert hasattr(data, "test_value") - assert getattr(data, "test_value") == expected_value + assert IntSchemaModel.validate({"test_value": test_value}) # Make sure the test value was not changed assert id(test_value) == test_value_id diff --git a/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_str.py b/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_str.py index 4c9f85282a2..2e66e5ac47c 100644 --- a/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_str.py +++ b/python-avd/tests/schema_tools/generate_pydantic/test_generated_schema_str.py @@ -5,18 +5,18 @@ from importlib import import_module from pathlib import Path from sys import path +from typing import Generator from unittest import mock import pytest -from pydantic import BaseModel, ValidationError # Override global path to load schema from source instead of any installed version. path.insert(0, str(Path(__file__).parents[3])) -import pyavd.schema.models -import pyavd.schema.types +import pyavd._schema.models +import pyavd._schema.types -from schema_tools.generate_pydantic.models import PydanticFileSrc +from schema_tools.generate_pydantic.src_generators import FileSrc from schema_tools.generate_pydantic.utils import generate_class_name from schema_tools.metaschema.meta_schema_model import AristaAvdSchema @@ -28,7 +28,6 @@ TEST_SCHEMA = { "type": "dict", "keys": { - "valid_values": {"type": "list"}, "test_value": { "type": "str", "convert_types": ["bool", "int", "float"], @@ -37,7 +36,7 @@ "convert_to_lower_case": True, "max_length": 4, "min_length": 2, - "dynamic_valid_values": "valid_strings", + "dynamic_valid_values": "valid_strings", # Part of meta schema but not implemented in converter "pattern": "[abf14t].*", "required": True, "description": "Some string", @@ -47,33 +46,49 @@ } TESTS = [ - # (test_value: str | None, valid_values: list[str] | None, expected_errors: set, expected_value: str) - ("foo", None, None, "foo"), # Valid value. No errors. - ("FoO", None, None, "foo"), # Lowered to "foo" which is valid. - (True, None, None, "true"), # True is converted and lowered to "true" which is valid. - (False, None, {"Input should be 'a', 'foo', 'zoo', 'baaar', '1.0', '42' or 'true'"}, None), # False is converted and lowered to "false" which is not valid. - (42, None, None, "42"), # Converted to "42". No errors. - (1.000, None, None, "1.0"), # Converted to "1.0". No errors. - (None, None, {"Input should be 'a', 'foo', 'zoo', 'baaar', '1.0', '42' or 'true'"}, None), # Required is set, so None is not ignored. - ([], None, {"Input should be 'a', 'foo', 'zoo', 'baaar', '1.0', '42' or 'true'"}, None), # Invalid type. - ("a", None, {"Value should have at least 2 items after validation, not 1"}, None), # Valid but below min length. - ("baaar", None, {"Value should have at most 4 items after validation, not 5"}, None), # Valid but below min length. - (22, None, {"Input should be 'a', 'foo', 'zoo', 'baaar', '1.0', '42' or 'true'"}, None), # Converted to "22" which is not valid. - ("zoo", None, {"String should match pattern '[abf14t].*'"}, None), # Valid value but does not match pattern. + # (test_value, expected_warnings: tuple, expected_warning_pattern: str) + ("foo", None, None), # Valid value. No errors. + ("FoO", None, None), # Lowered to "foo" which is valid. + (True, None, None), # True is converted and lowered to "true" which is valid. + ( + False, + (pyavd._schema.types.InvalidValue,), + r"Got invalid value for 'test_value'. Expected '\('a', 'foo', 'zoo', 'baaar', '1.0', '42', 'true'\)', got 'false'", + ), # False is converted and lowered to "false" which is not valid. + (42, None, None), # Converted to "42". No errors. + (1.000, None, None), # Converted to "1.0". No errors. + ( + None, + (pyavd._schema.types.InvalidType,), + r"Got invalid type for 'test_value'. Expected '', got ''", + ), # Required is set, so None is not ignored. + ([], (pyavd._schema.types.InvalidType,), r"Got invalid type for 'test_value'. Expected '', got ''"), # Invalid type. + ("a", (pyavd._schema.types.InvalidLength,), r"Got invalid length for 'test_value'\. Expected >=2, got '1'"), # Valid but below min length. + ("baaar", (pyavd._schema.types.InvalidLength,), r"Got invalid length for 'test_value'\. Expected <=4, got '5'"), # Valid but below min length. + ( + 22, + (pyavd._schema.types.InvalidValue, pyavd._schema.types.InvalidPattern), + r"(Got invalid value for 'test_value'. Expected '\('a', 'foo', 'zoo', 'baaar', '1.0', '42', 'true'\)', got '22')|(Got invalid value for 'test_value'. Expected a value matching the pattern '\[abf14t\]\.\*', got '22')", + ), # Converted to "22" which is not valid. + ( + "zoo", + (pyavd._schema.types.InvalidPattern,), + r"Got invalid value for 'test_value'. Expected a value matching the pattern '\[abf14t\]\.\*', got 'zoo'", + ), # Valid value but does not match pattern. ] @pytest.fixture(scope="module") -def StrSchemaModel() -> type[BaseModel]: +def StrSchemaModel() -> Generator[type, None, None]: schema_name = "str_schema" schema_model = AristaAvdSchema(**TEST_SCHEMA) output_file = Path(__file__).parent.joinpath(f"artifacts/{schema_name}.py") schemasrc = schema_model._generate_pydantic_src(class_name=schema_name) - src_file_contents = PydanticFileSrc(classes=[schemasrc.cls]) + src_file_contents = FileSrc(classes=[schemasrc.cls]) with open(output_file, mode="w", encoding="UTF-8") as file: file.write(str(src_file_contents)) - with mock.patch.dict(sys.modules, {"artifacts.types": pyavd.schema.types, "artifacts.models": pyavd.schema.models}): + with mock.patch.dict(sys.modules, {"artifacts.types": pyavd._schema.types, "artifacts.models": pyavd._schema.models}): module = import_module(f"artifacts.{schema_name}") class_name = generate_class_name(schema_name) Cls = getattr(module, class_name) @@ -84,21 +99,16 @@ def StrSchemaModel() -> type[BaseModel]: # output_file.unlink() -@pytest.mark.parametrize(("test_value", "valid_values", "expected_errors", "expected_value"), TESTS) -def test_generated_schema(test_value, valid_values: list | None, expected_errors: set, expected_value: int | None, StrSchemaModel: type[BaseModel]): +@pytest.mark.parametrize(("test_value", "expected_warnings", "expected_warning_pattern"), TESTS) +def test_generated_schema(test_value, expected_warnings: tuple | None, expected_warning_pattern: str | None, StrSchemaModel: type): test_value_id = id(test_value) - if expected_errors: - with pytest.raises(ValidationError) as exc_info: - StrSchemaModel(test_value=test_value, valid_values=valid_values) - errors = exc_info.value.errors() - msgs = set(error["msg"] for error in errors) - assert msgs == expected_errors + if expected_warnings: + with pytest.warns(expected_warnings, match=expected_warning_pattern): + assert not StrSchemaModel.validate({"test_value": test_value}) else: # No errors expected. - data = StrSchemaModel(test_value=test_value, valid_values=valid_values) - assert hasattr(data, "test_value") - assert getattr(data, "test_value") == expected_value + assert StrSchemaModel.validate({"test_value": test_value}) # Make sure the test value was not changed assert id(test_value) == test_value_id diff --git a/python-avd/tests/schema_tools/generate_pydantic/test_pydanticsrcgen.py b/python-avd/tests/schema_tools/generate_pydantic/test_pydanticsrcgen.py index f49df464c5c..5e3a7c18cc9 100644 --- a/python-avd/tests/schema_tools/generate_pydantic/test_pydanticsrcgen.py +++ b/python-avd/tests/schema_tools/generate_pydantic/test_pydanticsrcgen.py @@ -8,16 +8,16 @@ from unittest import mock import pytest -from pydantic import BaseModel -from pytest_benchmark.fixture import BenchmarkFixture + +# from pytest_benchmark.fixture import BenchmarkFixture # Override global path to load schema from source instead of any installed version. sys.path.insert(0, str(Path(__file__).parents[3])) -import pyavd.schema.models -import pyavd.schema.types +import pyavd._schema.models +import pyavd._schema.types -from schema_tools.generate_pydantic.models import PydanticFileSrc +from schema_tools.generate_pydantic.src_generators import FileSrc from schema_tools.generate_pydantic.utils import generate_class_name from schema_tools.metaschema.meta_schema_model import AristaAvdSchema from schema_tools.store import create_store @@ -55,11 +55,11 @@ def test_generate_pydantic_src(schema_name: str): Builds pydantic models from the schemas in the schema store. Writes the resulting models to python files under artifacts/. """ - schema = AristaAvdSchema(only_resolve_schema=schema_name, **STORE[schema_name]) + schema = AristaAvdSchema(resolve_hide_keys=False, **STORE[schema_name]) output_file = Path(__file__).parent.joinpath(f"artifacts/{schema_name}.py") print(f"Building pydantic from schema {schema_name}") schemasrc = schema._generate_pydantic_src(class_name=schema_name) - src_file_contents = PydanticFileSrc(classes=[schemasrc.cls]) + src_file_contents = FileSrc(classes=[schemasrc.cls]) with open(output_file, mode="w", encoding="UTF-8") as file: file.write(str(src_file_contents)) @@ -70,62 +70,65 @@ def test_import_and_load_model(schema_name: str, data_file: str, artifacts_path: Imports the generated pydantic models and initializes them with no data. Assert that default values are hidden with "exclude_unset=True" and otherwise not. """ - with mock.patch.dict(sys.modules, {"artifacts.types": pyavd.schema.types, "artifacts.models": pyavd.schema.models}): + with mock.patch.dict(sys.modules, {"artifacts.types": pyavd._schema.types, "artifacts.models": pyavd._schema.models}): module = import_module(f"artifacts.{schema_name}") class_name = generate_class_name(schema_name) Cls = getattr(module, class_name) - assert issubclass(Cls, BaseModel) + assert issubclass(Cls, pyavd._schema.models.AvdBase) if data_file is None: data = {} else: data = load_data_file(artifacts_path.joinpath(data_file)) + # Validate the data + assert Cls.validate(data) + # Initialize the loaded class with data. model = Cls(**data) - assert isinstance(model, BaseModel) - if data: - # Data is a full data set, meaning it might include other stuff than what we cover in the model. - # So we just check that we can dump something and it contains some keys. - assert model.model_dump(by_alias=True, exclude_unset=True) - else: - # Data is empty so we can verify that nothing is dumped if input is empty - assert model.model_dump(by_alias=True, exclude_unset=True) == data - assert model.model_dump(by_alias=True) != data - - -@pytest.mark.parametrize("schema_name", TEST_SCHEMAS_FROM_STORE) -def test_benchmark_import(schema_name: str, benchmark: BenchmarkFixture): - """ - Benchmark imports the generated pydantic models. - """ - with mock.patch.dict(sys.modules, {"artifacts.types": pyavd.schema.types, "artifacts.models": pyavd.schema.models}): - - def importer(module): - for schema_name in STORE.keys(): - if f"artifacts.{schema_name}" in sys.modules: - del sys.modules[f"artifacts.{schema_name}"] - import_module(module) - - benchmark(importer, f"artifacts.{schema_name}") - - -@pytest.mark.parametrize("schema_name,data_file", TEST_DATA) -def test_benchmark_init(schema_name: str, data_file: str, artifacts_path: Path, benchmark: BenchmarkFixture): - """ - Benchmark initialization of the generated pydantic models. - """ - with mock.patch.dict(sys.modules, {"artifacts.types": pyavd.schema.types, "artifacts.models": pyavd.schema.models}): - module = import_module(f"artifacts.{schema_name}") - class_name = generate_class_name(schema_name) - Cls = getattr(module, class_name) - assert issubclass(Cls, BaseModel) - - if data_file is None: - data = {} - else: - data = load_data_file(artifacts_path.joinpath(data_file)) - - # Initialize the loaded class with data. - benchmark(Cls, **data) + assert isinstance(model, pyavd._schema.models.AvdBase) + # if data: + # # Data is a full data set, meaning it might include other stuff than what we cover in the model. + # # So we just check that we can dump something and it contains some keys. + # assert model.model_dump(by_alias=True, exclude_unset=True) + # else: + # # Data is empty so we can verify that nothing is dumped if input is empty + # assert model.model_dump(by_alias=True, exclude_unset=True) == data + # assert model.model_dump(by_alias=True) != data + + +# @pytest.mark.parametrize("schema_name", TEST_SCHEMAS_FROM_STORE) +# def test_benchmark_import(schema_name: str, benchmark: BenchmarkFixture): +# """ +# Benchmark imports the generated pydantic models. +# """ +# with mock.patch.dict(sys.modules, {"artifacts.types": pyavd.schema.types, "artifacts.models": pyavd.schema.models}): + +# def importer(module): +# for schema_name in STORE.keys(): +# if f"artifacts.{schema_name}" in sys.modules: +# del sys.modules[f"artifacts.{schema_name}"] +# import_module(module) + +# benchmark(importer, f"artifacts.{schema_name}") + + +# @pytest.mark.parametrize("schema_name,data_file", TEST_DATA) +# def test_benchmark_init(schema_name: str, data_file: str, artifacts_path: Path, benchmark: BenchmarkFixture): +# """ +# Benchmark initialization of the generated pydantic models. +# """ +# with mock.patch.dict(sys.modules, {"artifacts.types": pyavd.schema.types, "artifacts.models": pyavd.schema.models}): +# module = import_module(f"artifacts.{schema_name}") +# class_name = generate_class_name(schema_name) +# Cls = getattr(module, class_name) +# assert issubclass(Cls, BaseModel) + +# if data_file is None: +# data = {} +# else: +# data = load_data_file(artifacts_path.joinpath(data_file)) + +# # Initialize the loaded class with data. +# benchmark(Cls, **data)