diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0e898359731..a7444315ae0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,7 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks +ci: + autoupdate_commit_msg: "Bump: pre-commit autoupdate" repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/patch-panel.md b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/patch-panel.md index 263534b389d..62afa97e662 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/patch-panel.md +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/patch-panel.md @@ -40,6 +40,14 @@ interface Management1 ### Patch Panel Summary +Patch Panel Connector Interface Recovery Review Delay Min: 10 + +Patch Panel Connector Interface Recovery Review Delay Max: 900 + +Patch Panel Connector Interface Path BGP VPWS Remote Failure Errdisable is enabled. + +#### Patch Panel Connections + | Patch Name | Enabled | Connector A Type | Connector A Endpoint | Connector B Type | Connector B Endpoint | | ---------- | ------- | ---------------- | -------------------- | ---------------- | -------------------- | | TEN_B_site2_site5_eline | True | Interface | Ethernet5 | Pseudowire | bgp vpws TENANT_A pseudowire TEN_B_site2_site5_eline | @@ -50,6 +58,9 @@ interface Management1 ```eos ! patch panel + connector interface recovery review delay 10 900 + connector interface patch bgp vpws remote-failure errdisable + ! patch TEN_B_site2_site5_eline connector 1 interface Ethernet5 connector 2 pseudowire bgp vpws TENANT_A pseudowire TEN_B_site2_site5_eline diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/patch-panel.cfg b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/patch-panel.cfg index 18b85373113..4b8b56555ce 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/patch-panel.cfg +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/patch-panel.cfg @@ -13,6 +13,9 @@ interface Management1 ip address 10.73.255.122/24 ! patch panel + connector interface recovery review delay 10 900 + connector interface patch bgp vpws remote-failure errdisable + ! patch TEN_B_site2_site5_eline connector 1 interface Ethernet5 connector 2 pseudowire bgp vpws TENANT_A pseudowire TEN_B_site2_site5_eline diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/patch-panel.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/patch-panel.yml index 16fefacacee..eae65a12d27 100644 --- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/patch-panel.yml +++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/patch-panel.yml @@ -1,4 +1,12 @@ patch_panel: + connector: + interface: + patch: + bgp_vpws_remote_failure_errdisable: true + recovery: + review_delay: + min: 10 + max: 900 patches: - name: TEN_B_site2_site5_eline connectors: diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER1.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER1.md index 0b6d141428d..449e8d9855c 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER1.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER1.md @@ -814,6 +814,8 @@ mpls ldp ### Patch Panel Summary +#### Patch Panel Connections + | Patch Name | Enabled | Connector A Type | Connector A Endpoint | Connector B Type | Connector B Endpoint | | ---------- | ------- | ---------------- | -------------------- | ---------------- | -------------------- | | TEN_A_site2_site5_eline_port_based | True | Interface | Ethernet6 | Pseudowire | bgp vpws TENANT_A pseudowire TEN_A_site2_site5_eline_port_based | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER2.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER2.md index 358bbdd751c..aacf885452a 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER2.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE1-LER2.md @@ -818,6 +818,8 @@ mpls ldp ### Patch Panel Summary +#### Patch Panel Connections + | Patch Name | Enabled | Connector A Type | Connector A Endpoint | Connector B Type | Connector B Endpoint | | ---------- | ------- | ---------------- | -------------------- | ---------------- | -------------------- | | TEN_B_site3_site5_eline_vlan_based_1000 | True | Interface | Port-Channel3.1000 | Pseudowire | bgp vpws TENANT_B pseudowire TEN_B_site3_site5_eline_vlan_based_1000 | diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LER1.md b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LER1.md index ff0e7e9c4e9..18309e6e88f 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LER1.md +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/documentation/devices/SITE2-LER1.md @@ -929,6 +929,8 @@ mpls ldp ### Patch Panel Summary +#### Patch Panel Connections + | Patch Name | Enabled | Connector A Type | Connector A Endpoint | Connector B Type | Connector B Endpoint | | ---------- | ------- | ---------------- | -------------------- | ---------------- | -------------------- | | TEN_A_site2_site5_eline_port_based | True | Interface | Ethernet7 | Pseudowire | bgp vpws TENANT_A pseudowire TEN_A_site2_site5_eline_port_based | diff --git a/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/ansible_eos_device.py b/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/ansible_eos_device.py index ce4b4d90476..7e8a93bd183 100644 --- a/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/ansible_eos_device.py +++ b/ansible_collections/arista/avd/plugins/plugin_utils/eos_validate_state_utils/ansible_eos_device.py @@ -84,11 +84,21 @@ def __init__(self, name: str, connection: ConnectionBase, tags: list | None = No super().__init__(name, tags, disable_cache=False) self.check_mode = check_mode + + # Check the ansible connection is defined + if not self.check_mode and not hasattr(connection, "_sub_plugin"): + raise AristaAvdError( + message="AVD could not determine the Ansible connection plugin used. " + "Please ensure that the 'ansible_network_os' and 'ansible_connection' variables are set to 'eos' and 'httpapi' respectively for this host." + ) # In check_mode we don't care that we cannot connect to the device if self.check_mode or (plugin_name := connection._sub_plugin.get("name")) == ANSIBLE_EOS_PLUGIN_NAME: self._connection = connection else: - raise AristaAvdError(message=f"The provided Ansible connection does not use EOS HttpApi plugin: {plugin_name}") + raise AristaAvdError( + message=f"The provided Ansible connection does not use EOS HttpApi plugin: {plugin_name}. " + "Please ensure that the 'ansible_network_os' and 'ansible_connection' variables are set to 'eos' and 'httpapi' respectively for this host." + ) @property def _keys(self) -> tuple: diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/patch-panel.md b/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/patch-panel.md index 8279046c39c..e6cd4909b9a 100644 --- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/patch-panel.md +++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/patch-panel.md @@ -8,6 +8,14 @@ | Variable | Type | Required | Default | Value Restrictions | Description | | -------- | ---- | -------- | ------- | ------------------ | ----------- | | [patch_panel](## "patch_panel") | Dictionary | | | | | + | [  connector](## "patch_panel.connector") | Dictionary | | | | | + | [    interface](## "patch_panel.connector.interface") | Dictionary | | | | | + | [      patch](## "patch_panel.connector.interface.patch") | Dictionary | | | | | + | [        bgp_vpws_remote_failure_errdisable](## "patch_panel.connector.interface.patch.bgp_vpws_remote_failure_errdisable") | Boolean | | | | | + | [      recovery](## "patch_panel.connector.interface.recovery") | Dictionary | | | | | + | [        review_delay](## "patch_panel.connector.interface.recovery.review_delay") | Dictionary | | | | | + | [          min](## "patch_panel.connector.interface.recovery.review_delay.min") | Integer | Required | | Min: 10 | Minimum delay (10-600). | + | [          max](## "patch_panel.connector.interface.recovery.review_delay.max") | Integer | Required | | Min: 15 | Maximum delay (15-900). | | [  patches](## "patch_panel.patches") | List, items: Dictionary | | | | | | [    - name](## "patch_panel.patches.[].name") | String | Required, Unique | | | | | [      enabled](## "patch_panel.patches.[].enabled") | Boolean | | | | | @@ -20,6 +28,18 @@ ```yaml patch_panel: + connector: + interface: + patch: + bgp_vpws_remote_failure_errdisable: + recovery: + review_delay: + + # Minimum delay (10-600). + min: =10; required> + + # Maximum delay (15-900). + max: =15; required> patches: - name: enabled: diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/eos_cli_config_gen.jsonschema.json b/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/eos_cli_config_gen.jsonschema.json index fe20d3b33d5..305d6cb6532 100644 --- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/eos_cli_config_gen.jsonschema.json +++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/eos_cli_config_gen.jsonschema.json @@ -13096,6 +13096,76 @@ "patch_panel": { "type": "object", "properties": { + "connector": { + "type": "object", + "properties": { + "interface": { + "type": "object", + "properties": { + "patch": { + "type": "object", + "properties": { + "bgp_vpws_remote_failure_errdisable": { + "type": "boolean", + "title": "BGP Vpws Remote Failure Errdisable" + } + }, + "additionalProperties": false, + "patternProperties": { + "^_.+$": {} + }, + "title": "Patch" + }, + "recovery": { + "type": "object", + "properties": { + "review_delay": { + "type": "object", + "properties": { + "min": { + "type": "integer", + "minimum": 10, + "description": "Minimum delay (10-600).", + "title": "Min" + }, + "max": { + "type": "integer", + "minimum": 15, + "description": "Maximum delay (15-900).", + "title": "Max" + } + }, + "required": [ + "min", + "max" + ], + "additionalProperties": false, + "patternProperties": { + "^_.+$": {} + }, + "title": "Review Delay" + } + }, + "additionalProperties": false, + "patternProperties": { + "^_.+$": {} + }, + "title": "Recovery" + } + }, + "additionalProperties": false, + "patternProperties": { + "^_.+$": {} + }, + "title": "Interface" + } + }, + "additionalProperties": false, + "patternProperties": { + "^_.+$": {} + }, + "title": "Connector" + }, "patches": { "type": "array", "items": { diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/eos_cli_config_gen.schema.yml b/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/eos_cli_config_gen.schema.yml index 98108a05c2e..3a6d6b16ec3 100644 --- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/eos_cli_config_gen.schema.yml +++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/eos_cli_config_gen.schema.yml @@ -7751,6 +7751,37 @@ keys: patch_panel: type: dict keys: + connector: + type: dict + keys: + interface: + type: dict + keys: + patch: + type: dict + keys: + bgp_vpws_remote_failure_errdisable: + type: bool + recovery: + type: dict + keys: + review_delay: + type: dict + keys: + min: + type: int + required: true + min: 10 + convert_types: + - str + description: Minimum delay (10-600). + max: + type: int + required: true + min: 15 + convert_types: + - str + description: Maximum delay (15-900). patches: type: list primary_key: name diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/schema_fragments/patch_panel.schema.yml b/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/schema_fragments/patch_panel.schema.yml index 9d7749f15aa..de853e9ddd3 100644 --- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/schema_fragments/patch_panel.schema.yml +++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/schemas/schema_fragments/patch_panel.schema.yml @@ -9,11 +9,42 @@ keys: patch_panel: type: dict keys: + connector: + type: dict + keys: + interface: + type: dict + keys: + patch: + type: dict + keys: + bgp_vpws_remote_failure_errdisable: + type: bool + recovery: + type: dict + keys: + review_delay: + type: dict + keys: + min: + type: int + required: true + min: 10 + convert_types: + - str + description: Minimum delay (10-600). + max: + type: int + required: true + min: 15 + convert_types: + - str + description: Maximum delay (15-900). patches: type: list primary_key: name convert_types: - - dict + - dict items: type: dict keys: @@ -25,7 +56,7 @@ keys: type: list primary_key: id convert_types: - - dict + - dict min_length: 2 max_length: 2 description: Must have exactly two connectors to a patch of which at least one must be of type "interface". @@ -35,12 +66,12 @@ keys: id: type: str convert_types: - - int + - int type: type: str valid_values: - - interface - - pseudowire + - interface + - pseudowire required: true endpoint: type: str diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/documentation/patch-panel.j2 b/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/documentation/patch-panel.j2 index 64bccb51ee9..9939123f10b 100644 --- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/documentation/patch-panel.j2 +++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/documentation/patch-panel.j2 @@ -9,6 +9,20 @@ ## Patch Panel ### Patch Panel Summary +{% if patch_panel.connector.interface.recovery.review_delay.min is arista.avd.defined %} + +Patch Panel Connector Interface Recovery Review Delay Min: {{ patch_panel.connector.interface.recovery.review_delay.min }} +{% endif %} +{% if patch_panel.connector.interface.recovery.review_delay.max is arista.avd.defined %} + +Patch Panel Connector Interface Recovery Review Delay Max: {{ patch_panel.connector.interface.recovery.review_delay.max }} +{% endif %} +{% if patch_panel.connector.interface.patch.bgp_vpws_remote_failure_errdisable is arista.avd.defined(true) %} + +Patch Panel Connector Interface Path BGP VPWS Remote Failure Errdisable is enabled. +{% endif %} + +#### Patch Panel Connections | Patch Name | Enabled | Connector A Type | Connector A Endpoint | Connector B Type | Connector B Endpoint | | ---------- | ------- | ---------------- | -------------------- | ---------------- | -------------------- | diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/eos/patch-panel.j2 b/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/eos/patch-panel.j2 index b718628d3e7..846e2f19671 100644 --- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/eos/patch-panel.j2 +++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/eos/patch-panel.j2 @@ -7,6 +7,15 @@ {% if patch_panel is arista.avd.defined %} ! patch panel +{% if patch_panel.connector.interface is arista.avd.defined %} +{% if patch_panel.connector.interface.recovery.review_delay.min is arista.avd.defined and patch_panel.connector.interface.recovery.review_delay.max is arista.avd.defined %} + connector interface recovery review delay {{ patch_panel.connector.interface.recovery.review_delay.min }} {{ patch_panel.connector.interface.recovery.review_delay.max }} +{% endif %} +{% if patch_panel.connector.interface.patch.bgp_vpws_remote_failure_errdisable is arista.avd.defined(true) %} + connector interface patch bgp vpws remote-failure errdisable +{% endif %} + ! +{% endif %} {% for patch in patch_panel.patches | arista.avd.default([]) %} {% if patch.name is arista.avd.defined %} patch {{ patch.name }} diff --git a/ansible_collections/arista/avd/roles/eos_designs/schemas/eos_designs.jsonschema.json b/ansible_collections/arista/avd/roles/eos_designs/schemas/eos_designs.jsonschema.json index 56b9c6ae697..bbc42cee4bc 100644 --- a/ansible_collections/arista/avd/roles/eos_designs/schemas/eos_designs.jsonschema.json +++ b/ansible_collections/arista/avd/roles/eos_designs/schemas/eos_designs.jsonschema.json @@ -30154,6 +30154,76 @@ "patch_panel": { "type": "object", "properties": { + "connector": { + "type": "object", + "properties": { + "interface": { + "type": "object", + "properties": { + "patch": { + "type": "object", + "properties": { + "bgp_vpws_remote_failure_errdisable": { + "type": "boolean", + "title": "BGP Vpws Remote Failure Errdisable" + } + }, + "additionalProperties": false, + "patternProperties": { + "^_.+$": {} + }, + "title": "Patch" + }, + "recovery": { + "type": "object", + "properties": { + "review_delay": { + "type": "object", + "properties": { + "min": { + "type": "integer", + "minimum": 10, + "description": "Minimum delay (10-600).", + "title": "Min" + }, + "max": { + "type": "integer", + "minimum": 15, + "description": "Maximum delay (15-900).", + "title": "Max" + } + }, + "required": [ + "min", + "max" + ], + "additionalProperties": false, + "patternProperties": { + "^_.+$": {} + }, + "title": "Review Delay" + } + }, + "additionalProperties": false, + "patternProperties": { + "^_.+$": {} + }, + "title": "Recovery" + } + }, + "additionalProperties": false, + "patternProperties": { + "^_.+$": {} + }, + "title": "Interface" + } + }, + "additionalProperties": false, + "patternProperties": { + "^_.+$": {} + }, + "title": "Connector" + }, "patches": { "type": "array", "items": { diff --git a/python-avd/schema_tools/metaschema/meta_schema_model.py b/python-avd/schema_tools/metaschema/meta_schema_model.py index 1a99aec3a77..bd672edd681 100644 --- a/python-avd/schema_tools/metaschema/meta_schema_model.py +++ b/python-avd/schema_tools/metaschema/meta_schema_model.py @@ -24,7 +24,7 @@ - AvdSchemaList - AvdSchemaDict -The alias "AvdSchemaField" is a union of of all the models above, and can be used as easy type hint for any field type. +The alias "AvdSchemaField" is a union of all the models above, and can be used as an easy type hint for any field type. All the type-specific Pydantic models inherit the common base class "AvdSchemaBaseModel", and have local overrides as needed. For example, only "AvdSchemaList" and "AvdSchemaDict" need to parse child fields. @@ -35,10 +35,6 @@ KEY_PATTERN = r"^[a-z][a-z0-9_]*$" """Common pattern to match legal key strings""" -DYNAMIC_KEY_PATTERN = r"^[a-z][a-z0-9_.]*$" -"""Common pattern to match legal dynamic key strings""" -KEY_PATTERN_WITH_UPPERCASE = r"^[a-zA-Z][a-zA-Z0-9_]*$" -"""This is a temporary pattern allowing uppercase keys too""" class AvdSchemaBaseModel(BaseModel, ABC): @@ -89,7 +85,7 @@ class DocumentationOptions(BaseModel): display_name: str | None = Field(None, pattern=r"^[^\n]+$") """Free text display name for forms and documentation (single line)""" description: Annotated[str, constr(min_length=1)] | None = None - """Free text description for forms and documentation (multi line)""" + """Free text description for forms and documentation (multi-line)""" required: bool | None = None """Key is required""" deprecation: Deprecation | None = None @@ -478,14 +474,13 @@ class DocumentationOptions(AvdSchemaBaseModel.DocumentationOptions): default: dict[str, Any] | None = None """Default value""" - # TODO: Change pattern to KEY_PATTERN once we have removed all upper case keys from the schema - keys: dict[constr(pattern=KEY_PATTERN_WITH_UPPERCASE), Annotated[AvdSchemaField, Field(discriminator="type")]] | None = None + keys: dict[str, Annotated[AvdSchemaField, Field(discriminator="type")]] | None = None """ Dictionary of dictionary-keys in the format `{: {}}`. `keyname` must use snake_case. `schema` is the schema for each key. This is a recursive schema, so the value must conform to AVD Schema. """ - dynamic_keys: dict[constr(pattern=DYNAMIC_KEY_PATTERN), Annotated[AvdSchemaField, Field(discriminator="type")]] | None = None + dynamic_keys: dict[str, Annotated[AvdSchemaField, Field(discriminator="type")]] | None = None """ Dictionary of dynamic dictionary-keys in the format `{: {}}`. `variable.path` is a variable path using dot-notation and pointing to a variable under the parent dictionary containing dictionary-keys. @@ -501,7 +496,7 @@ class DocumentationOptions(AvdSchemaBaseModel.DocumentationOptions): """Schema name used when exporting to JSON schema""" field_id: str | None = Field(None, alias="$id") """Schema ID used when exporting to JSON schema""" - field_defs: dict[constr(pattern=KEY_PATTERN), Annotated[AvdSchemaField, Field(discriminator="type")]] = Field(None, alias="$defs") + field_defs: dict[str, Annotated[AvdSchemaField, Field(discriminator="type")]] = Field(None, alias="$defs") """Storage for reusable schema fragments""" # Type of schema docs generators to use for this schema field.