From 90dbd955a93e4c47b211fab2378123266b538dc9 Mon Sep 17 00:00:00 2001 From: hellt Date: Fri, 15 Aug 2025 17:42:05 +0200 Subject: [PATCH 1/5] use ruff out of band and copy venv --- README.md | 4 ++-- gen_models.py | 24 +++++++++++++++++++++--- pyproject.toml | 2 +- uv.lock | 13 ++++++------- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 3cfc53f..6a1e00b 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,13 @@ Pydantic models for EDA OpenAPI spec. Models are generated for the EDA Core API Install dev dependencies: -``` +```bash uv sync --all-groups ``` Generate models for a specific version of the openapi repo (git ref): -``` +```bash python gen_models.py --version v25.4.1 ``` diff --git a/gen_models.py b/gen_models.py index 66f0c68..6ca9ad5 100644 --- a/gen_models.py +++ b/gen_models.py @@ -3,6 +3,7 @@ import argparse import json import logging +import os import shutil import subprocess import sys @@ -135,8 +136,9 @@ def generate_classes_for_spec( "schemas", "--output-model-type", "pydantic_v2.BaseModel", - "--formatters", - "ruff-format", + # we will format manually using ruff in the venv + # "--formatters", + # "ruff-format", "--use-annotated", "--parent-scoped-naming", "--collapse-root-models", @@ -159,7 +161,23 @@ def generate_classes_for_spec( try: logger.info(f"Generating models for {spec_file}...") - subprocess.run(cmd, check=True) + + # Create environment with explicit path to virtual env binaries + env = os.environ.copy() + venv_path = os.environ.get("VIRTUAL_ENV", ".venv") + venv_bin = Path(venv_path) / "bin" + + # Prepend venv bin directory to PATH + current_path = env.get("PATH", "") + env["PATH"] = f"{venv_bin}:{current_path}" + + subprocess.run(cmd, check=True, env=env) + + # Format the generated file with ruff + logger.debug(f"Formatting {dest_file} with ruff...") + ruff_cmd = ["ruff", "format", str(dest_file)] + subprocess.run(ruff_cmd, check=True, env=env) + except subprocess.CalledProcessError as e: logger.error(f"Error generating models for {spec_file}: {e}") diff --git a/pyproject.toml b/pyproject.toml index e92abeb..90c016d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ requires-python = "~=3.12" dependencies = ["pydantic>=2.10.6"] [dependency-groups] -dev = ["datamodel-code-generator[http]>=0.30.1", "rich>=13.9.4", "ruff>=0.9.3"] +dev = ["datamodel-code-generator[http]==0.33.0", "rich>=13.9.4", "ruff>=0.9.3"] [build-system] requires = ["hatchling"] diff --git a/uv.lock b/uv.lock index a4a3726..fb88fd6 100644 --- a/uv.lock +++ b/uv.lock @@ -1,4 +1,5 @@ version = 1 +revision = 1 requires-python = ">=3.12, <4" [[package]] @@ -89,7 +90,7 @@ wheels = [ [[package]] name = "datamodel-code-generator" -version = "0.30.1" +version = "0.33.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "argcomplete" }, @@ -102,9 +103,9 @@ dependencies = [ { name = "pydantic" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ef/bc/627a77eafcf7101c9f5710130b2def98593709a8d29676e4a58f09cd2a23/datamodel_code_generator-0.30.1.tar.gz", hash = "sha256:d125012face4cd1eca6c9300297a1f5775a9d5ff8fc3f68d34d0944a7beea105", size = 446630 } +sdist = { url = "https://files.pythonhosted.org/packages/7d/a0/3f81c5c0c31d6f25f459e370e04553810f096e5dbd3cf7eda2a67709cd78/datamodel_code_generator-0.33.0.tar.gz", hash = "sha256:7635ef788201d69bd3e98ba88ce6afe479400dc2737fe9d5e21f87408f352c08", size = 458695 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/b3/01aab190372914399bbc77f89ac3b24b439c3d97a52a6198f1cd1396ef3a/datamodel_code_generator-0.30.1-py3-none-any.whl", hash = "sha256:9601dfa3da8aa8d8d54e182059f78836b1768a807d5c26df798db12d4054c8f3", size = 118045 }, + { url = "https://files.pythonhosted.org/packages/3b/d0/acd7a19dad4dc4118d2b6ba06df9a4a3725729e91fa3f2c63a765d4e7d44/datamodel_code_generator-0.33.0-py3-none-any.whl", hash = "sha256:e229264aa612b2d5bb4901bcd6c520a799ae0d5c19262577a0f876eb48afaaa3", size = 121148 }, ] [package.optional-dependencies] @@ -347,7 +348,7 @@ wheels = [ [[package]] name = "pydantic-eda" -version = "0.1.0" +version = "0.3.2" source = { editable = "." } dependencies = [ { name = "pydantic" }, @@ -356,7 +357,6 @@ dependencies = [ [package.dev-dependencies] dev = [ { name = "datamodel-code-generator", extra = ["http"] }, - { name = "httpx" }, { name = "rich" }, { name = "ruff" }, ] @@ -366,8 +366,7 @@ requires-dist = [{ name = "pydantic", specifier = ">=2.10.6" }] [package.metadata.requires-dev] dev = [ - { name = "datamodel-code-generator", extras = ["http"], specifier = ">=0.30.1" }, - { name = "httpx", specifier = ">=0.28.1" }, + { name = "datamodel-code-generator", extras = ["http"], specifier = "==0.33.0" }, { name = "rich", specifier = ">=13.9.4" }, { name = "ruff", specifier = ">=0.9.3" }, ] From 39e5679a4f397add54fbd957ef9f8c86bb3cd5bf Mon Sep 17 00:00:00 2001 From: hellt Date: Fri, 15 Aug 2025 17:42:11 +0200 Subject: [PATCH 2/5] generated models --- pydantic_eda/apps/aaa/v1alpha1/models.py | 126 +- .../apps/aifabrics/v1alpha1/models.py | 129 +- pydantic_eda/apps/appstore/v1/models.py | 302 +- .../apps/bootstrap/v1alpha1/models.py | 126 +- pydantic_eda/apps/components/v1/models.py | 174 +- pydantic_eda/apps/config/v1alpha1/models.py | 126 +- pydantic_eda/apps/core/v1/models.py | 180 +- .../apps/environment/v1alpha1/models.py | 248 + pydantic_eda/apps/fabrics/v1alpha1/models.py | 365 +- pydantic_eda/apps/filters/v1alpha1/models.py | 180 +- .../apps/interfaces/v1alpha1/models.py | 234 +- pydantic_eda/apps/oam/v1alpha1/models.py | 403 +- pydantic_eda/apps/os/v1alpha1/models.py | 381 +- pydantic_eda/apps/protocols/v1/models.py | 4654 +++++++++++++ .../apps/protocols/v1alpha1/models.py | 199 +- pydantic_eda/apps/qos/v1/models.py | 1968 ++++++ pydantic_eda/apps/qos/v1alpha1/models.py | 126 +- pydantic_eda/apps/routing/v1alpha1/models.py | 450 +- .../apps/routingpolicies/v1alpha1/models.py | 402 +- pydantic_eda/apps/security/v1alpha1/models.py | 126 +- pydantic_eda/apps/services/v1/models.py | 5775 +++++++++++++++++ pydantic_eda/apps/services/v1alpha1/models.py | 385 +- pydantic_eda/apps/siteinfo/v1alpha1/models.py | 126 +- pydantic_eda/apps/system/v1alpha1/models.py | 126 +- pydantic_eda/apps/timing/v1alpha1/models.py | 129 +- .../apps/topologies/v1alpha1/models.py | 567 +- pydantic_eda/core/v25_8_1-rc1/models.py | 1815 ++++++ 27 files changed, 19122 insertions(+), 700 deletions(-) create mode 100644 pydantic_eda/apps/environment/v1alpha1/models.py create mode 100644 pydantic_eda/apps/protocols/v1/models.py create mode 100644 pydantic_eda/apps/qos/v1/models.py create mode 100644 pydantic_eda/apps/services/v1/models.py create mode 100644 pydantic_eda/core/v25_8_1-rc1/models.py diff --git a/pydantic_eda/apps/aaa/v1alpha1/models.py b/pydantic_eda/apps/aaa/v1alpha1/models.py index f26d524..f015963 100644 --- a/pydantic_eda/apps/aaa/v1alpha1/models.py +++ b/pydantic_eda/apps/aaa/v1alpha1/models.py @@ -2,8 +2,10 @@ # filename: aaa.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -37,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -91,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -110,6 +118,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -208,7 +253,7 @@ class NodeGroupStatus(BaseModel): class NodeGroupDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -251,6 +296,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class NodeGroup(BaseModel): """ NodeGroup is the Schema for the nodegroups API @@ -280,3 +390,13 @@ class NodeGroupList(BaseModel): apiVersion: str items: Optional[List[NodeGroup]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/aifabrics/v1alpha1/models.py b/pydantic_eda/apps/aifabrics/v1alpha1/models.py index d5fd477..8528809 100644 --- a/pydantic_eda/apps/aifabrics/v1alpha1/models.py +++ b/pydantic_eda/apps/aifabrics/v1alpha1/models.py @@ -2,9 +2,10 @@ # filename: aifabrics.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Optional -from pydantic import BaseModel, Field, RootModel -from datetime import date + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -38,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,6 +118,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -375,7 +419,7 @@ class BackendStatus(BaseModel): ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The time when the state of the resource last changed.", title="Last Change", @@ -399,7 +443,7 @@ class BackendStatus(BaseModel): class BackendDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -442,6 +486,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class Backend(BaseModel): """ Backend is the Schema for the backends API @@ -474,3 +583,13 @@ class BackendList(BaseModel): apiVersion: str items: Optional[List[Backend]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/appstore/v1/models.py b/pydantic_eda/apps/appstore/v1/models.py index aa3061d..1c203ff 100644 --- a/pydantic_eda/apps/appstore/v1/models.py +++ b/pydantic_eda/apps/appstore/v1/models.py @@ -2,9 +2,10 @@ # filename: appstore.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel -from datetime import datetime + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -38,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,10 +118,181 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str +class WorkflowGetInputsRespElem(BaseModel): + ackPrompt: Optional[str] = None + group: str + kind: str + name: str + namespace: Optional[str] = None + schemaPrompt: Optional[Dict[str, Any]] = None + version: str + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowIdentifier(BaseModel): + group: str + kind: str + name: str + namespace: Optional[str] = None + version: str + + +class WorkflowInputDataElem(BaseModel): + ack: Annotated[ + Optional[bool], Field(description="acknowledge or reject the input request") + ] = None + input: Annotated[ + Optional[Dict[str, Any]], + Field(description="provide a json blob to the workflow"), + ] = None + subflow: Optional[WorkflowIdentifier] = None + + +class AppInstallerSpecAppVersion(BaseModel): + """ + Version of the App that is to be installed. + """ + + type: Annotated[ + Optional[Literal["semver", "commit"]], + Field( + description="The version type of the App. Currently supported: semver, commit.\nDefault is semver.", + title="Type", + ), + ] = "semver" + value: Annotated[ + str, + Field( + description='The version of the App.\nIf the VersionType is set to semver,\nthen the semantic version of the git tag in the form of "apps//" is used.\nIf the VersionType is set to commit,\nthen the commit reference (e.g. git hash) is expected.', + title="Value", + ), + ] + + +class AppInstallerSpecApp(BaseModel): + appId: Annotated[ + str, + Field( + description="AppID of the app, which is the unique identifier of an app. It should be equal to the group of the app.", + title="App ID", + ), + ] + appSettings: Annotated[ + Optional[Dict[str, Any]], + Field( + description="AppSettings defines a list of variables and their value. Only variables that are customised need to be mentioned.\nIf AppSettings are not again mentioned on upgrade, values will remain as is.", + title="App Settings", + ), + ] = None + catalog: Annotated[ + str, + Field( + description="Catalog of the app to be installed.\nThis is where app manifest is retrieved from, along with some other metadata.", + title="Catalog", + ), + ] + version: Annotated[ + AppInstallerSpecAppVersion, + Field( + description="Version of the App that is to be installed.", title="Version" + ), + ] + + +class AppInstallerSpec(BaseModel): + apps: Annotated[ + List[AppInstallerSpecApp], + Field(description="Apps are the input apps to the installer.", title="Apps"), + ] + autoProcessRequirements: Annotated[ + Optional[List[str]], + Field( + description="AutoProcessRequirements tells the installer what it can do w.r.t. the requirements of an app.\nCurrently only 'strict' is supported.", + title="Auto Process Requirements", + ), + ] = None + operation: Annotated[ + Literal["install", "delete"], + Field( + description="Operation is the installing operation.\nCurrently supported are 'install', 'delete'.", + title="Operation", + ), + ] + + +class AppInstallerStatus(BaseModel): + error: Annotated[Optional[str], Field(title="Error")] = None + id: Annotated[ + Optional[int], + Field( + description="ID is the workflow ID that can be used to get more information on.", + title="ID", + ), + ] = None + result: Annotated[str, Field(title="Result")] + + +class AppInstallerMetadata(BaseModel): + annotations: Optional[Dict[str, str]] = None + labels: Optional[Dict[str, str]] = None + name: Annotated[ + str, + Field( + max_length=253, + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + ), + ] + + class CatalogSpec(BaseModel): """ CatalogSpec defines the desired state of a Catalog. @@ -186,7 +364,7 @@ class CatalogStatus(BaseModel): ), ] = None lastRefreshTime: Annotated[ - Optional[datetime], + Optional[AwareDatetime], Field( description="LastRefreshTime is the last attempt to refresh the catalog cache by the controller.", title="Last Refresh Time", @@ -202,7 +380,7 @@ class CatalogStatus(BaseModel): class CatalogDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None transactionId: Optional[int] = None @@ -212,16 +390,7 @@ class CatalogDeletedResources(RootModel[List[CatalogDeletedResourceEntry]]): root: List[CatalogDeletedResourceEntry] -class CatalogMetadata(BaseModel): - annotations: Optional[Dict[str, str]] = None - labels: Optional[Dict[str, str]] = None - name: Annotated[ - str, - Field( - max_length=253, - pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", - ), - ] +CatalogMetadata = AppInstallerMetadata class RegistrySpec(BaseModel): @@ -294,7 +463,7 @@ class RegistryDeletedResources(RootModel[List[RegistryDeletedResourceEntry]]): root: List[RegistryDeletedResourceEntry] -RegistryMetadata = CatalogMetadata +RegistryMetadata = AppInstallerMetadata class AppGroup(BaseModel): @@ -316,6 +485,97 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class WorkflowInputData(RootModel[List[WorkflowInputDataElem]]): + root: List[WorkflowInputDataElem] + + +class AppInstaller(BaseModel): + """ + AppInstaller is the Schema for the appinstallers API + """ + + apiVersion: str + kind: str + metadata: AppInstallerMetadata + spec: Annotated[AppInstallerSpec, Field(title="Specification")] + status: Annotated[Optional[AppInstallerStatus], Field(title="Status")] = None + + +class AppInstallerList(BaseModel): + """ + AppInstallerList is a list of appinstallers + """ + + apiVersion: str + items: Optional[List[AppInstaller]] = None + kind: str + + class Catalog(BaseModel): """ Catalog is the Schema for the catalogs API @@ -382,3 +642,13 @@ class RegistryList(BaseModel): apiVersion: str items: Optional[List[Registry]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/bootstrap/v1alpha1/models.py b/pydantic_eda/apps/bootstrap/v1alpha1/models.py index b4d8b46..2972516 100644 --- a/pydantic_eda/apps/bootstrap/v1alpha1/models.py +++ b/pydantic_eda/apps/bootstrap/v1alpha1/models.py @@ -2,8 +2,10 @@ # filename: bootstrap.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Optional -from pydantic import BaseModel, Field, RootModel + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -37,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -91,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -110,6 +118,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -180,7 +225,7 @@ class InitSpec(BaseModel): class InitDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -256,6 +301,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class Init(BaseModel): """ Init is the Schema for the inits API @@ -321,3 +431,13 @@ class ManagementRouterList(BaseModel): apiVersion: str items: Optional[List[ManagementRouter]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/components/v1/models.py b/pydantic_eda/apps/components/v1/models.py index 17f2269..4e5eca4 100644 --- a/pydantic_eda/apps/components/v1/models.py +++ b/pydantic_eda/apps/components/v1/models.py @@ -2,9 +2,11 @@ # filename: components.json from __future__ import annotations -from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel + from datetime import date +from typing import Annotated, Any, Dict, List, Literal, Optional + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -38,6 +40,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +100,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,6 +119,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -156,14 +201,14 @@ class ChassisStatus(BaseModel): Field(description="The CLEI code of this component", title="CLEI Code"), ] = None lastBooted: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last booted", title="Last Booted", ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last changed operational state", title="Last Change", @@ -274,7 +319,7 @@ class ComponentStatus(BaseModel): ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this Component last changed operational state", title="Last Change", @@ -359,14 +404,14 @@ class ControlModuleStatus(BaseModel): Field(description="The CLEI code of this component", title="CLEI Code"), ] = None lastBooted: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last booted", title="Last Booted", ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last changed operational state", title="Last Change", @@ -485,14 +530,14 @@ class FabricModuleStatus(BaseModel): Field(description="The CLEI code of this component", title="CLEI Code"), ] = None lastBooted: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last booted", title="Last Booted", ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last changed operational state", title="Last Change", @@ -604,14 +649,14 @@ class FanStatus(BaseModel): Field(description="The CLEI code of this component", title="CLEI Code"), ] = None lastBooted: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last booted", title="Last Booted", ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last changed operational state", title="Last Change", @@ -712,14 +757,14 @@ class InterfaceModuleStatus(BaseModel): Field(description="The CLEI code of this component", title="CLEI Code"), ] = None lastBooted: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last booted", title="Last Booted", ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last changed operational state", title="Last Change", @@ -1051,7 +1096,7 @@ class MonitorStatus(BaseModel): class MonitorDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -1091,14 +1136,14 @@ class PowerSupplyStatus(BaseModel): Field(description="The CLEI code of this component", title="CLEI Code"), ] = None lastBooted: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last booted", title="Last Booted", ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The date and time this component last changed operational state", title="Last Change", @@ -1219,6 +1264,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class Chassis(BaseModel): """ Chassis is the Schema for the chassis API @@ -1228,12 +1338,12 @@ class Chassis(BaseModel): kind: str metadata: ChassisMetadata spec: Annotated[ - Dict[str, Any], + Optional[Dict[str, Any]], Field( description="ChassisSpec defines the desired state of Chassis", title="Specification", ), - ] + ] = None status: Annotated[ Optional[ChassisStatus], Field( @@ -1296,12 +1406,12 @@ class ControlModule(BaseModel): kind: str metadata: ControlModuleMetadata spec: Annotated[ - Dict[str, Any], + Optional[Dict[str, Any]], Field( description="ControlModuleSpec defines the desired state of ControlModule", title="Specification", ), - ] + ] = None status: Annotated[ Optional[ControlModuleStatus], Field( @@ -1330,12 +1440,12 @@ class FabricModule(BaseModel): kind: str metadata: FabricModuleMetadata spec: Annotated[ - Dict[str, Any], + Optional[Dict[str, Any]], Field( description="FabricModuleSpec defines the desired state of FabricModule", title="Specification", ), - ] + ] = None status: Annotated[ Optional[FabricModuleStatus], Field( @@ -1364,12 +1474,12 @@ class Fan(BaseModel): kind: str metadata: FanMetadata spec: Annotated[ - Dict[str, Any], + Optional[Dict[str, Any]], Field( description="FanSpec defines the desired state of Fan", title="Specification", ), - ] + ] = None status: Annotated[ Optional[FanStatus], Field( @@ -1397,12 +1507,12 @@ class InterfaceModule(BaseModel): kind: str metadata: InterfaceModuleMetadata spec: Annotated[ - Dict[str, Any], + Optional[Dict[str, Any]], Field( description="InterfaceModuleSpec defines the desired state of InterfaceModule", title="Specification", ), - ] + ] = None status: Annotated[ Optional[InterfaceModuleStatus], Field( @@ -1488,3 +1598,13 @@ class PowerSupplyList(BaseModel): apiVersion: str items: Optional[List[PowerSupply]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/config/v1alpha1/models.py b/pydantic_eda/apps/config/v1alpha1/models.py index 2da86d6..16c423c 100644 --- a/pydantic_eda/apps/config/v1alpha1/models.py +++ b/pydantic_eda/apps/config/v1alpha1/models.py @@ -2,8 +2,10 @@ # filename: config.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -37,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -91,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -110,6 +118,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -205,7 +250,7 @@ class ConfigletStatus(BaseModel): class ConfigletDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -248,6 +293,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class Configlet(BaseModel): """ Configlet is the Schema for the configlets API @@ -277,3 +387,13 @@ class ConfigletList(BaseModel): apiVersion: str items: Optional[List[Configlet]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/core/v1/models.py b/pydantic_eda/apps/core/v1/models.py index 760c451..0e272d0 100644 --- a/pydantic_eda/apps/core/v1/models.py +++ b/pydantic_eda/apps/core/v1/models.py @@ -2,9 +2,11 @@ # filename: core.json from __future__ import annotations -from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel, SecretStr + from datetime import date +from typing import Annotated, Any, Dict, List, Literal, Optional + +from pydantic import AwareDatetime, BaseModel, Field, RootModel, SecretStr class AppGroupVersion(BaseModel): @@ -38,6 +40,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +100,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,6 +119,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -228,7 +273,7 @@ class ClusterRoleSpec(BaseModel): class ClusterRoleDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None transactionId: Optional[int] = None @@ -378,7 +423,7 @@ class DeviationActionStatus(BaseModel): class DeviationActionDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -521,6 +566,20 @@ class IPAllocationPoolSpecSegmentReservation(BaseModel): class IPAllocationPoolSpecSegment(BaseModel): + allocateBroadcastAddress: Annotated[ + Optional[bool], + Field( + description="Permit the allocation of the broadcast address.", + title="Allocate Broadcast Address", + ), + ] = None + allocateNetworkAddress: Annotated[ + Optional[bool], + Field( + description="Permit the allocation of the network address.", + title="Allocate Network Address", + ), + ] = None allocations: Annotated[ Optional[List[IPAllocationPoolSpecSegmentAllocation]], Field( @@ -583,6 +642,20 @@ class IPAllocationPoolDeletedResources( class IPInSubnetAllocationPoolSpecSegment(BaseModel): + allocateBroadcastAddress: Annotated[ + Optional[bool], + Field( + description="Permit the allocation of the broadcast address.", + title="Allocate Broadcast Address", + ), + ] = None + allocateNetworkAddress: Annotated[ + Optional[bool], + Field( + description="Permit the allocation of the network address.", + title="Allocate Network Address", + ), + ] = None allocations: Annotated[ Optional[List[IPInSubnetAllocationPoolSpecSegmentAllocation]], Field( @@ -1116,21 +1189,21 @@ class NodeProfileSpec(BaseModel): ), ] onboardingPassword: Annotated[ - Optional[SecretStr], + SecretStr, Field( description="The password to use when onboarding TopoNodes referencing this NodeProfile, e.g. admin.", title="Onboarding Password", ), - ] = None + ] onboardingUsername: Annotated[ - Optional[str], + str, Field( description="The username to use when onboarding TopoNodes referencing this NodeProfile, e.g. admin.", title="Onboarding Username", ), - ] = None + ] operatingSystem: Annotated[ - Literal["srl", "sros", "nxos"], + Literal["srl", "sros", "eos", "sonic", "ios-xr", "nxos", "linux"], Field( description="Sets the operating system of this NodeProfile, e.g. srl.", title="Operating System", @@ -1629,6 +1702,7 @@ class TopoLinkDeletedResources(RootModel[List[TopoLinkDeletedResourceEntry]]): class TopoNodeSpecComponentItem(BaseModel): kind: Annotated[ Literal[ + "controlCard", "lineCard", "fabric", "mda", @@ -1732,7 +1806,7 @@ class TopoNodeSpec(BaseModel): ), ] = False operatingSystem: Annotated[ - Literal["srl", "sros", "nxos"], + Literal["srl", "sros", "eos", "sonic", "ios-xr", "nxos", "linux"], Field( description="Operating system running on this TopoNode, e.g. srl.", title="Operating System", @@ -1762,7 +1836,7 @@ class TopoNodeSpec(BaseModel): systemInterface: Annotated[ Optional[str], Field( - description="Name of the Interface resource representing the primary loopback on the TopoNode.", + description="Deprecated: Name of the Interface resource representing the primary loopback on the TopoNode, this field will be removed in the future version.", title="System Interface", ), ] = None @@ -1977,6 +2051,13 @@ class WorkflowDefinitionSpec(BaseModel): title="Image Pull Secrets", ), ] = None + namespaced: Annotated[ + Optional[bool], + Field( + description="If set, resources of this CRD are namespace scoped", + title="Namespaced", + ), + ] = True WorkflowDefinitionDeletedResourceEntry = ClusterRoleDeletedResourceEntry @@ -2010,6 +2091,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class ClusterRole(BaseModel): """ ClusterRole is the Schema for the clusterroles API @@ -2640,3 +2786,13 @@ class WorkflowDefinitionList(BaseModel): apiVersion: str items: Optional[List[WorkflowDefinition]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/environment/v1alpha1/models.py b/pydantic_eda/apps/environment/v1alpha1/models.py new file mode 100644 index 0000000..901382f --- /dev/null +++ b/pydantic_eda/apps/environment/v1alpha1/models.py @@ -0,0 +1,248 @@ +# generated by datamodel-codegen: +# filename: environment.json + +from __future__ import annotations + +from typing import Annotated, Any, Dict, List, Optional + +from pydantic import BaseModel, Field, RootModel + + +class ErrorIndex(BaseModel): + index: Optional[int] = None + + +class ErrorItem(BaseModel): + error: Optional[Dict[str, Any]] = None + type: Optional[str] = None + + +class ErrorResponse(BaseModel): + """ + Generic error response for REST APIs + """ + + code: Annotated[ + int, Field(description="the numeric HTTP error code for the response.") + ] + details: Annotated[ + Optional[str], Field(description="The optional details of the error response.") + ] = None + dictionary: Annotated[ + Optional[Dict[str, Any]], + Field( + description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' + ), + ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None + errors: Annotated[ + Optional[List[ErrorItem]], + Field( + description="Collection of errors in cases where more than one exists. This needs to be\nflexible so we can support multiple formats" + ), + ] = None + index: Optional[ErrorIndex] = None + internal: Annotated[ + Optional[int], + Field( + description="Internal error code in cases where we don't have an array of errors" + ), + ] = None + message: Annotated[ + str, Field(description="The basic text error message for the error response.") + ] + ref: Annotated[ + Optional[str], + Field( + description="Reference to the error source. Should typically be the URI of the request" + ), + ] = None + type: Annotated[ + Optional[str], + Field( + description="URI pointing at a document that describes the error and mitigation steps\nIf there is no document, point to the RFC for the HTTP error code" + ), + ] = None + + +class WorkflowGetInputsRespElem(BaseModel): + ackPrompt: Optional[str] = None + group: str + kind: str + name: str + namespace: Optional[str] = None + schemaPrompt: Optional[Dict[str, Any]] = None + version: str + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowIdentifier(BaseModel): + group: str + kind: str + name: str + namespace: Optional[str] = None + version: str + + +class WorkflowInputDataElem(BaseModel): + ack: Annotated[ + Optional[bool], Field(description="acknowledge or reject the input request") + ] = None + input: Annotated[ + Optional[Dict[str, Any]], + Field(description="provide a json blob to the workflow"), + ] = None + subflow: Optional[WorkflowIdentifier] = None + + +class CliPluginSpec(BaseModel): + """ + This workflow is used to push a CLI plugin to a node. + """ + + content: Annotated[ + Optional[str], + Field(description="Content of the plugin to push.", title="Plugin Content"), + ] = None + fileName: Annotated[ + Optional[str], + Field( + description='Name of the plugin to push. For SR Linux this should include the .py extension, without leading slashes.\ne.g. "myplugin.py".', + title="Plugin Name", + ), + ] = None + + +class CliPluginStatus(BaseModel): + """ + CliPluginStatus defines the observed state of CliPlugin + """ + + id: Annotated[Optional[int], Field(description="Id", title="ID")] = None + result: Annotated[ + Optional[str], Field(description="Aggregate result of the Flow", title="Result") + ] = None + + +class CliPluginMetadata(BaseModel): + annotations: Optional[Dict[str, str]] = None + labels: Optional[Dict[str, str]] = None + name: Annotated[ + str, + Field( + max_length=253, + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + ), + ] + namespace: str + + +class SetupEnvSpec(BaseModel): + """ + This workflow is used to set up the global environment on a node. + For SR Linux this results in an overwrite of the /etc/opt/srlinux/env file. + """ + + env: Annotated[ + Optional[str], + Field(description="Content of the environment file to push.", title="env"), + ] = None + + +class SetupEnvStatus(BaseModel): + """ + SetupEnvStatus defines the observed state of SetupEnv + """ + + id: Annotated[Optional[int], Field(description="Id", title="ID")] = None + result: Annotated[ + Optional[str], Field(description="Aggregate result of the Flow", title="Result") + ] = None + + +SetupEnvMetadata = CliPluginMetadata + + +class WorkflowInputData(RootModel[List[WorkflowInputDataElem]]): + root: List[WorkflowInputDataElem] + + +class CliPlugin(BaseModel): + """ + CliPlugin is the Schema for the cliplugins API + """ + + apiVersion: str + kind: str + metadata: CliPluginMetadata + spec: Annotated[ + CliPluginSpec, + Field( + description="This workflow is used to push a CLI plugin to a node.", + title="Specification", + ), + ] + status: Annotated[ + Optional[CliPluginStatus], + Field( + description="CliPluginStatus defines the observed state of CliPlugin", + title="Status", + ), + ] = None + + +class CliPluginList(BaseModel): + """ + CliPluginList is a list of cliplugins + """ + + apiVersion: str + items: Optional[List[CliPlugin]] = None + kind: str + + +class SetupEnv(BaseModel): + """ + SetupEnv is the Schema for the setupenvs API + """ + + apiVersion: str + kind: str + metadata: SetupEnvMetadata + spec: Annotated[ + SetupEnvSpec, + Field( + description="This workflow is used to set up the global environment on a node.\nFor SR Linux this results in an overwrite of the /etc/opt/srlinux/env file.", + title="Specification", + ), + ] + status: Annotated[ + Optional[SetupEnvStatus], + Field( + description="SetupEnvStatus defines the observed state of SetupEnv", + title="Status", + ), + ] = None + + +class SetupEnvList(BaseModel): + """ + SetupEnvList is a list of setupenvs + """ + + apiVersion: str + items: Optional[List[SetupEnv]] = None + kind: str diff --git a/pydantic_eda/apps/fabrics/v1alpha1/models.py b/pydantic_eda/apps/fabrics/v1alpha1/models.py index c4a8719..21dbd7a 100644 --- a/pydantic_eda/apps/fabrics/v1alpha1/models.py +++ b/pydantic_eda/apps/fabrics/v1alpha1/models.py @@ -2,9 +2,10 @@ # filename: fabrics.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel -from datetime import date + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -38,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,10 +118,85 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str +class WorkflowGetInputsRespElem(BaseModel): + ackPrompt: Optional[str] = None + group: str + kind: str + name: str + namespace: Optional[str] = None + schemaPrompt: Optional[Dict[str, Any]] = None + version: str + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowIdentifier(BaseModel): + group: str + kind: str + name: str + namespace: Optional[str] = None + version: str + + +class WorkflowInputDataElem(BaseModel): + ack: Annotated[ + Optional[bool], Field(description="acknowledge or reject the input request") + ] = None + input: Annotated[ + Optional[Dict[str, Any]], + Field(description="provide a json blob to the workflow"), + ] = None + subflow: Optional[WorkflowIdentifier] = None + + class FabricSpecBorderLeafsRouteLeaking(BaseModel): """ Route leaking controlled by routing policies in and out of the DefaultRouters on each node. If specifided under the Leafs, Spines, SuperSpines, or BorderLeafs those will take precedence. @@ -180,6 +262,15 @@ class FabricSpecInterSwitchLinksQos(BaseModel): class FabricSpecInterSwitchLinks(BaseModel): + ipMTU: Annotated[ + Optional[int], + Field( + description="Sets the IP MTU for the DefaultInterface.", + ge=1280, + le=9486, + title="IP MTU", + ), + ] = None linkSelector: Annotated[ Optional[List[str]], Field( @@ -306,6 +397,15 @@ class FabricSpecOverlayProtocolBfd(BaseModel): title="Receive Interval", ), ] = 1000000 + ttl: Annotated[ + Optional[int], + Field( + description="Sets custom IP TTL or Hop Limit for multi-hop BFD sessions packets. Not appllicable to single-hop BFD sessions.", + ge=2, + le=255, + title="IP TTL/Hop Limit", + ), + ] = None class FabricSpecOverlayProtocolBgpTimers(BaseModel): @@ -590,6 +690,15 @@ class FabricSpecUnderlayProtocolBfd(BaseModel): title="Receive Interval", ), ] = 1000000 + ttl: Annotated[ + Optional[int], + Field( + description="Sets custom IP TTL or Hop Limit for multi-hop BFD sessions packets. Not appllicable to single-hop BFD sessions.", + ge=2, + le=255, + title="IP TTL/Hop Limit", + ), + ] = None FabricSpecUnderlayProtocolBgpTimers = FabricSpecOverlayProtocolBgpTimers @@ -772,7 +881,7 @@ class FabricStatus(BaseModel): ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The time when the state of the resource last changed.", title="Last Change", @@ -803,7 +912,7 @@ class FabricStatus(BaseModel): class FabricDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -872,6 +981,15 @@ class ISLSpecBfd(BaseModel): title="Receive Interval", ), ] = 1000000 + ttl: Annotated[ + Optional[int], + Field( + description="Sets custom IP TTL or Hop Limit for multi-hop BFD sessions packets. Not appllicable to single-hop BFD sessions.", + ge=2, + le=255, + title="IP TTL/Hop Limit", + ), + ] = None class ISLSpecBgp(BaseModel): @@ -946,6 +1064,15 @@ class ISLSpec(BaseModel): ), ] = None bgp: Annotated[Optional[ISLSpecBgp], Field(title="BGP")] = None + ipMTU: Annotated[ + Optional[int], + Field( + description="Sets the IP MTU for the local and remote Interfaces", + ge=1280, + le=9486, + title="IP MTU", + ), + ] = None localDefaultRouter: Annotated[ str, Field( @@ -1074,7 +1201,7 @@ class ISLStatus(BaseModel): ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The time when the state of the resource last changed", title="Last Change", @@ -1104,6 +1231,119 @@ class ISLDeletedResources(RootModel[List[ISLDeletedResourceEntry]]): ISLMetadata = FabricMetadata +class IslPingSpec(BaseModel): + """ + This workflow is used to ping ISLs (Inter-Switch Links) to verify connectivity within a Fabric. + It accepts a list of fabrics, ISLs, or selectors for both to match ISLs, + and returns the results of the pings, including the status of each ISL. + """ + + count: Annotated[ + Optional[int], + Field(description="Count is the number of pings to send.", title="Count"), + ] = 1 + fabricSelectors: Annotated[ + Optional[List[str]], + Field( + description='Fabric Selectors is a list of fabric selectors to execute ISL pings for.\nThis is a list of label expressions, e.g. ["eda.nokia.com/role=leaf", "eda.nokia.com/region=us-west"].', + title="Fabric Selectors", + ), + ] = None + fabrics: Annotated[ + Optional[List[str]], + Field( + description="Fabrics is a list of fabrics to execute ISL pings for.", + title="Fabrics", + ), + ] = None + islSelectors: Annotated[ + Optional[List[str]], + Field( + description='Inter-Switch Link Selectors is a list of selectors to execute ISL pings for.\nThis is a list of label expressions, e.g. ["eda.nokia.com/role=leaf", "eda.nokia.com/region=us-west"].', + title="Inter-Switch Link Selectors", + ), + ] = None + isls: Annotated[ + Optional[List[str]], + Field( + description="Inter-Switch Links is a list of named ISL resources to execute ISL pings for.", + title="Inter-Switch Links", + ), + ] = None + timeoutSeconds: Annotated[ + Optional[int], + Field( + description="TimeoutSeconds is the timeout for the ping in seconds.", + title="Timeout Seconds", + ), + ] = 5 + + +class IslPingStatusDetailDetails(BaseModel): + averageTimeNanoseconds: Annotated[ + Optional[int], + Field( + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + ), + ] = None + maxTimeNanoseconds: Annotated[ + Optional[int], + Field( + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + ), + ] = None + minTimeNanoseconds: Annotated[ + Optional[int], + Field( + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + ), + ] = None + received: Optional[int] = None + sent: Optional[int] = None + stdDevNanoseconds: Annotated[ + Optional[int], + Field( + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + ), + ] = None + totalTimeNanoseconds: Annotated[ + Optional[int], + Field( + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + ), + ] = None + + +class IslPingStatusDetail(BaseModel): + details: Optional[IslPingStatusDetailDetails] = None + error: Optional[str] = None + name: Optional[str] = None + success: Optional[bool] = None + + +class IslPingStatus(BaseModel): + """ + IslPingStatus defines the observed state of IslPing + """ + + details: Annotated[ + Optional[List[IslPingStatusDetail]], + Field( + description="Details contains the results of the pings performed for each ISL.\nEach entry in the list corresponds to an ISL that was pinged." + ), + ] = None + result: Annotated[ + Optional[Literal["Success", "Failed", "PartialSuccess"]], + Field( + description='Result is the overall result of the ping operation.\nIt can be one of the following values:\n- "Success": All pings were successful.\n- "Failed": No pings were successful.\n- "PartialSuccess": Some pings were successful, but not all.', + title="Result", + ), + ] = None + + +IslPingMetadata = FabricMetadata + + class AppGroup(BaseModel): apiVersion: Optional[str] = None kind: Optional[str] = None @@ -1123,6 +1363,75 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class WorkflowInputData(RootModel[List[WorkflowInputDataElem]]): + root: List[WorkflowInputDataElem] + + class Fabric(BaseModel): """ Fabric is the Schema for the fabrics API @@ -1188,3 +1497,47 @@ class ISLList(BaseModel): apiVersion: str items: Optional[List[ISL]] = None kind: str + + +class IslPing(BaseModel): + """ + IslPing is the Schema for the islpings API + """ + + apiVersion: str + kind: str + metadata: IslPingMetadata + spec: Annotated[ + IslPingSpec, + Field( + description="This workflow is used to ping ISLs (Inter-Switch Links) to verify connectivity within a Fabric.\nIt accepts a list of fabrics, ISLs, or selectors for both to match ISLs,\nand returns the results of the pings, including the status of each ISL.", + title="Specification", + ), + ] + status: Annotated[ + Optional[IslPingStatus], + Field( + description="IslPingStatus defines the observed state of IslPing", + title="Status", + ), + ] = None + + +class IslPingList(BaseModel): + """ + IslPingList is a list of islpings + """ + + apiVersion: str + items: Optional[List[IslPing]] = None + kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/filters/v1alpha1/models.py b/pydantic_eda/apps/filters/v1alpha1/models.py index 61ee6af..046535a 100644 --- a/pydantic_eda/apps/filters/v1alpha1/models.py +++ b/pydantic_eda/apps/filters/v1alpha1/models.py @@ -2,8 +2,10 @@ # filename: filters.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -37,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -91,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -110,6 +118,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -415,6 +460,10 @@ class ControlPlaneFilterSpecEntryIpEntry(BaseModel): title="ICMP Type Number", ), ] = None + log: Annotated[ + Optional[bool], + Field(description="Log the matches for this entry.", title="Log"), + ] = None protocolName: Annotated[ Optional[ Literal[ @@ -733,6 +782,10 @@ class ControlPlaneFilterSpecEntryMacEntry(BaseModel): title="Ethertype", ), ] = None + log: Annotated[ + Optional[bool], + Field(description="Log the matches for this entry.", title="Log"), + ] = None outerVLANIDOperator: Annotated[ Optional[Literal["Equals", "GreaterOrEquals", "LessOrEquals"]], Field( @@ -778,13 +831,23 @@ class ControlPlaneFilterSpecEntryMacEntry(BaseModel): class ControlPlaneFilterSpecEntry(BaseModel): + description: Annotated[ + Optional[str], + Field(description="Description of the FilterEntry.", title="Description"), + ] = None ipEntry: Annotated[ Optional[ControlPlaneFilterSpecEntryIpEntry], Field(title="IP Entry") ] = None macEntry: Annotated[ Optional[ControlPlaneFilterSpecEntryMacEntry], Field(title="MAC Entry") ] = None - type: Annotated[Literal["IPV4", "IPV6", "MAC", "Auto"], Field(title="Type")] + type: Annotated[ + Literal["IPV4", "IPV6", "MAC", "Auto"], + Field( + description="Type of the entry which can be IPV4, IPV6, MAC or Auto.", + title="Type", + ), + ] class ControlPlaneFilterSpec(BaseModel): @@ -813,10 +876,17 @@ class ControlPlaneFilterSpec(BaseModel): title="Nodes", ), ] = None + statisticsPerEntry: Annotated[ + Optional[bool], + Field( + description="Enable or disable per-entry counters.", + title="Per-entry counters", + ), + ] = None class ControlPlaneFilterDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -1117,6 +1187,10 @@ class FilterSpecEntryIpEntry(BaseModel): title="ICMP Type Number", ), ] = None + log: Annotated[ + Optional[bool], + Field(description="Log the matches for this entry.", title="Log"), + ] = None protocolName: Annotated[ Optional[ Literal[ @@ -1433,6 +1507,10 @@ class FilterSpecEntryMacEntry(BaseModel): title="Ethertype", ), ] = None + log: Annotated[ + Optional[bool], + Field(description="Log the matches for this entry.", title="Log"), + ] = None outerVLANIDOperator: Annotated[ Optional[Literal["Equals", "GreaterOrEquals", "LessOrEquals"]], Field( @@ -1478,11 +1556,21 @@ class FilterSpecEntryMacEntry(BaseModel): class FilterSpecEntry(BaseModel): + description: Annotated[ + Optional[str], + Field(description="Description of the FilterEntry.", title="Description"), + ] = None ipEntry: Annotated[Optional[FilterSpecEntryIpEntry], Field(title="IP Entry")] = None macEntry: Annotated[Optional[FilterSpecEntryMacEntry], Field(title="MAC Entry")] = ( None ) - type: Annotated[Literal["IPV4", "IPV6", "MAC", "Auto"], Field(title="Type")] + type: Annotated[ + Literal["IPV4", "IPV6", "MAC", "Auto"], + Field( + description="Type of the entry which can be IPV4, IPV6, MAC or Auto.", + title="Type", + ), + ] class FilterSpec(BaseModel): @@ -1497,6 +1585,13 @@ class FilterSpec(BaseModel): title="Entries", ), ] + statisticsPerEntry: Annotated[ + Optional[bool], + Field( + description="Enable or disable per-entry counters.", + title="Per-entry counters", + ), + ] = None FilterDeletedResourceEntry = ControlPlaneFilterDeletedResourceEntry @@ -1528,6 +1623,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class ControlPlaneFilter(BaseModel): """ ControlPlaneFilter is the Schema for the controlplanefilters API @@ -1594,3 +1754,13 @@ class FilterList(BaseModel): apiVersion: str items: Optional[List[Filter]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/interfaces/v1alpha1/models.py b/pydantic_eda/apps/interfaces/v1alpha1/models.py index f9bd049..616d698 100644 --- a/pydantic_eda/apps/interfaces/v1alpha1/models.py +++ b/pydantic_eda/apps/interfaces/v1alpha1/models.py @@ -2,9 +2,10 @@ # filename: interfaces.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel -from datetime import date + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -38,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,10 +118,85 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str +class WorkflowGetInputsRespElem(BaseModel): + ackPrompt: Optional[str] = None + group: str + kind: str + name: str + namespace: Optional[str] = None + schemaPrompt: Optional[Dict[str, Any]] = None + version: str + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowIdentifier(BaseModel): + group: str + kind: str + name: str + namespace: Optional[str] = None + version: str + + +class WorkflowInputDataElem(BaseModel): + ack: Annotated[ + Optional[bool], Field(description="acknowledge or reject the input request") + ] = None + input: Annotated[ + Optional[Dict[str, Any]], + Field(description="provide a json blob to the workflow"), + ] = None + subflow: Optional[WorkflowIdentifier] = None + + class BreakoutSpec(BaseModel): """ Breakout allows for the configuration of interface breakouts on specified Nodes. This resource specifies the Nodes, parent Interfaces, the number of breakout channels, and the speed of each channel. @@ -157,7 +239,7 @@ class BreakoutSpec(BaseModel): class BreakoutDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -181,6 +263,33 @@ class BreakoutMetadata(BaseModel): namespace: str +class CheckInterfacesSpec(BaseModel): + """ + CheckInterfacesSpec defines the desired state of CheckInterfaces + """ + + interfaceSelector: Annotated[ + Optional[List[str]], Field(title="interfaceselector") + ] = None + nodeSelector: Annotated[Optional[List[str]], Field(title="nodeselector")] = None + nodes: Annotated[Optional[List[str]], Field(title="nodes")] = None + waitFor: Annotated[Optional[int], Field(title="waitfor")] = None + + +class CheckInterfacesStatus(BaseModel): + """ + CheckInterfacesStatus defines the observed state of CheckInterfaces + """ + + id: Annotated[Optional[int], Field(description="Id", title="ID")] = None + result: Annotated[ + Optional[str], Field(description="Aggregate result of the Flow", title="Result") + ] = None + + +CheckInterfacesMetadata = BreakoutMetadata + + class InterfaceSpecEthernetStormControl(BaseModel): """ Enables storm control. @@ -561,7 +670,7 @@ class InterfaceStatusMember(BaseModel): ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="Indicates when this member last changed state.", title="Last Change", @@ -611,7 +720,7 @@ class InterfaceStatus(BaseModel): ] = None lag: Annotated[Optional[InterfaceStatusLag], Field(title="Lag")] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="Indicates when this Interface last changed state.", title="Last Change", @@ -730,6 +839,75 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class WorkflowInputData(RootModel[List[WorkflowInputDataElem]]): + root: List[WorkflowInputDataElem] + + class Breakout(BaseModel): """ Breakout is the Schema for the breakouts API @@ -764,6 +942,40 @@ class BreakoutList(BaseModel): kind: str +class CheckInterfaces(BaseModel): + """ + CheckInterfaces is the Schema for the checkinterfacess API + """ + + apiVersion: str + kind: str + metadata: CheckInterfacesMetadata + spec: Annotated[ + CheckInterfacesSpec, + Field( + description="CheckInterfacesSpec defines the desired state of CheckInterfaces", + title="Specification", + ), + ] + status: Annotated[ + Optional[CheckInterfacesStatus], + Field( + description="CheckInterfacesStatus defines the observed state of CheckInterfaces", + title="Status", + ), + ] = None + + +class CheckInterfacesList(BaseModel): + """ + CheckInterfacesList is a list of checkinterfacess + """ + + apiVersion: str + items: Optional[List[CheckInterfaces]] = None + kind: str + + class Interface(BaseModel): """ Interface is the Schema for the interfaces API @@ -818,3 +1030,13 @@ class InterfaceStateList(BaseModel): apiVersion: str items: Optional[List[InterfaceState]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/oam/v1alpha1/models.py b/pydantic_eda/apps/oam/v1alpha1/models.py index 44cb5c3..e47c0be 100644 --- a/pydantic_eda/apps/oam/v1alpha1/models.py +++ b/pydantic_eda/apps/oam/v1alpha1/models.py @@ -2,9 +2,10 @@ # filename: oam.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel -from datetime import date + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -38,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,10 +118,85 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str +class WorkflowGetInputsRespElem(BaseModel): + ackPrompt: Optional[str] = None + group: str + kind: str + name: str + namespace: Optional[str] = None + schemaPrompt: Optional[Dict[str, Any]] = None + version: str + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowIdentifier(BaseModel): + group: str + kind: str + name: str + namespace: Optional[str] = None + version: str + + +class WorkflowInputDataElem(BaseModel): + ack: Annotated[ + Optional[bool], Field(description="acknowledge or reject the input request") + ] = None + input: Annotated[ + Optional[Dict[str, Any]], + Field(description="provide a json blob to the workflow"), + ] = None + subflow: Optional[WorkflowIdentifier] = None + + class MirrorSpecLocalDestination(BaseModel): """ Local destination for the mirror, there can only be either a remote destination or local destination provisioned for a Mirror. @@ -475,6 +557,10 @@ class MirrorSpecSourcesFilterFilterEntryIpEntry(BaseModel): title="ICMP Type Number", ), ] = None + log: Annotated[ + Optional[bool], + Field(description="Log the matches for this entry.", title="Log"), + ] = None protocolName: Annotated[ Optional[ Literal[ @@ -739,10 +825,20 @@ class MirrorSpecSourcesFilterFilterEntryIpEntry(BaseModel): class MirrorSpecSourcesFilterFilterEntry(BaseModel): + description: Annotated[ + Optional[str], + Field(description="Description of the FilterEntry.", title="Description"), + ] = None ipEntry: Annotated[ Optional[MirrorSpecSourcesFilterFilterEntryIpEntry], Field(title="IP Entry") ] = None - type: Annotated[Literal["IPV4", "IPV6", "Auto"], Field(title="Type")] + type: Annotated[ + Literal["IPV4", "IPV6", "Auto"], + Field( + description="Type of the entry which can be IPV4, IPV6 or Auto.", + title="Type", + ), + ] class MirrorSpecSourcesFilterFilter(BaseModel): @@ -757,6 +853,13 @@ class MirrorSpecSourcesFilterFilter(BaseModel): title="Entries", ), ] + statisticsPerEntry: Annotated[ + Optional[bool], + Field( + description="Enable or disable per-entry counters.", + title="Per-entry counters", + ), + ] = None class MirrorSpecSourcesFilterSubinterfacesSubinterface(BaseModel): @@ -971,7 +1074,7 @@ class MirrorStatus(BaseModel): """ lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="Indicates when this SubInterface last changed state.", title="Last Change", @@ -1040,7 +1143,7 @@ class MirrorStatus(BaseModel): class MirrorDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -1064,47 +1167,149 @@ class MirrorMetadata(BaseModel): namespace: str -class PingSpec(BaseModel): +class NewPingSpec(BaseModel): """ - PingSpec defines the desired state of Ping + Ping allows a ping to be initiated to a specific address on node/set of nodes. """ - address: Annotated[Optional[str], Field(title="address")] = None - networkInstance: Annotated[Optional[str], Field(title="NetworkInstance")] = None - node: Annotated[Optional[str], Field(title="node")] = None - pingType: Annotated[Literal["isl", "node", "system"], Field(title="pingtype")] - pods: Annotated[Optional[List[str]], Field(title="Pods")] = None - roles: Annotated[Optional[List[str]], Field(title="roles")] = None + address: Annotated[ + str, + Field( + description="Address to ping.\nThis is a single IP address (IPv4 or IPv6) or a hostname that resolves to an IP address.", + title="Target Address", + ), + ] + count: Annotated[ + Optional[int], + Field(description="Count is the number of pings to send.", title="Count"), + ] = 1 + networkInstance: Annotated[ + Optional[str], + Field( + description='The network instance to use for the ping. This is the named network instance on the node, typically "default" or some other base name.\nIf not specified, the default network instance will be used, which is typically the main/default/global network interface on the node.', + title="Network Instance", + ), + ] = None + nodeSelectors: Annotated[ + Optional[List[str]], + Field( + description="NodeSelectors is a list of node selectors to select nodes to perform pings on.\nThis matches labels on TopoNode resources, including those TopoNodes in the list of nodes that pings will be performed on.\nIf no nodes are specified, and no node selectors are specified, all nodes in the given namespace will be selected.", + title="Node Selectors", + ), + ] = None + nodes: Annotated[ + Optional[List[str]], + Field( + description="Nodes is a list of nodes to perform pings on.\nItems in the list should be the names of the nodes, where each node will have a ping performed on it.\nIf no nodes are specified, and no node selectors are specified, all nodes in the given namespace will be selected.", + title="Nodes", + ), + ] = None + timeoutSeconds: Annotated[ + Optional[int], + Field( + description="TimeoutSeconds is the timeout for the ping in seconds.", + title="Timeout Seconds", + ), + ] = 5 + + +class NewPingStatusDetailDetails(BaseModel): + averageTimeNanoseconds: Annotated[ + Optional[int], + Field( + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + ), + ] = None + maxTimeNanoseconds: Annotated[ + Optional[int], + Field( + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + ), + ] = None + minTimeNanoseconds: Annotated[ + Optional[int], + Field( + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + ), + ] = None + received: Optional[int] = None + sent: Optional[int] = None + stdDevNanoseconds: Annotated[ + Optional[int], + Field( + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + ), + ] = None + totalTimeNanoseconds: Annotated[ + Optional[int], + Field( + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + ), + ] = None + +class NewPingStatusDetail(BaseModel): + details: Optional[NewPingStatusDetailDetails] = None + error: Optional[str] = None + networkInstance: Optional[str] = None + node: Optional[str] = None + success: Optional[bool] = None -class PingStatus(BaseModel): + +class NewPingStatus(BaseModel): """ - PingStatus defines the observed state of Ping + NewPingStatus defines the observed state of NewPing """ - id: Annotated[Optional[int], Field(description="Id", title="ID")] = None + details: Annotated[ + Optional[List[NewPingStatusDetail]], + Field( + description="Details contains the results of the pings performed on each node.\nEach entry in the list corresponds to a node that was pinged." + ), + ] = None result: Annotated[ - Literal[ - "OK", - "Failed", - "Terminated", - "WaitingForInput", - "Running", - "WaitingToStart", - "SubflowWaitingForInput", - ], - Field(description="Aggregate result of the Flow", title="Result"), - ] + Optional[Literal["Success", "Failed", "PartialSuccess"]], + Field( + description='Result is the overall result of the ping operation.\nIt can be one of the following values:\n- "Success": All pings were successful.\n- "Failed": No pings were successful.\n- "PartialSuccess": Some pings were successful, but not all.', + title="Result", + ), + ] = "Success" -PingDeletedResourceEntry = MirrorDeletedResourceEntry +NewPingMetadata = MirrorMetadata -class PingDeletedResources(RootModel[List[PingDeletedResourceEntry]]): - root: List[PingDeletedResourceEntry] +class TechSupportSpec(BaseModel): + """ + Generate technical support packages for a node or set of nodes. + """ + + nodeSelectors: Annotated[ + Optional[List[str]], + Field( + description='List of node selectors to select nodes generate technical support packages for.\nThis matches labels on TopoNode resources.\nIf no nodes are specified, and no node selectors are specified, all nodes in the given namespace will be selected.\nThis is a list of label expressions, e.g. ["eda.nokia.com/role=leaf"].', + title="Node Selectors", + ), + ] = None + nodes: Annotated[ + Optional[List[str]], + Field( + description="List of nodes to generate and collect technical support packages for.", + title="Nodes", + ), + ] = None -PingMetadata = MirrorMetadata +class TechSupportStatus(BaseModel): + """ + Result of the technical support package generation. + """ + + id: Annotated[Optional[int], Field(description="Id", title="ID")] = None + result: Annotated[Optional[str], Field(description="Result", title="Result")] = None + + +TechSupportMetadata = MirrorMetadata class ThresholdSpecAlarm(BaseModel): @@ -1280,6 +1485,75 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class WorkflowInputData(RootModel[List[WorkflowInputDataElem]]): + root: List[WorkflowInputDataElem] + + class Mirror(BaseModel): """ Mirror is the Schema for the mirrors API @@ -1314,36 +1588,71 @@ class MirrorList(BaseModel): kind: str -class Ping(BaseModel): +class NewPing(BaseModel): + """ + NewPing is the Schema for the newpings API + """ + + apiVersion: str + kind: str + metadata: NewPingMetadata + spec: Annotated[ + NewPingSpec, + Field( + description="Ping allows a ping to be initiated to a specific address on node/set of nodes.", + title="Specification", + ), + ] + status: Annotated[ + Optional[NewPingStatus], + Field( + description="NewPingStatus defines the observed state of NewPing", + title="Status", + ), + ] = None + + +class NewPingList(BaseModel): + """ + NewPingList is a list of newpings + """ + + apiVersion: str + items: Optional[List[NewPing]] = None + kind: str + + +class TechSupport(BaseModel): """ - Ping is the Schema for the pings API + TechSupport is the Schema for the techsupports API """ apiVersion: str kind: str - metadata: PingMetadata + metadata: TechSupportMetadata spec: Annotated[ - PingSpec, + TechSupportSpec, Field( - description="PingSpec defines the desired state of Ping", + description="Generate technical support packages for a node or set of nodes.", title="Specification", ), ] status: Annotated[ - Optional[PingStatus], + Optional[TechSupportStatus], Field( - description="PingStatus defines the observed state of Ping", title="Status" + description="Result of the technical support package generation.", + title="Status", ), ] = None -class PingList(BaseModel): +class TechSupportList(BaseModel): """ - PingList is a list of pings + TechSupportList is a list of techsupports """ apiVersion: str - items: Optional[List[Ping]] = None + items: Optional[List[TechSupport]] = None kind: str @@ -1379,3 +1688,13 @@ class ThresholdList(BaseModel): apiVersion: str items: Optional[List[Threshold]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/os/v1alpha1/models.py b/pydantic_eda/apps/os/v1alpha1/models.py index 25fd862..bb76091 100644 --- a/pydantic_eda/apps/os/v1alpha1/models.py +++ b/pydantic_eda/apps/os/v1alpha1/models.py @@ -2,14 +2,10 @@ # filename: os.json from __future__ import annotations -from typing import Annotated, Any, Dict, List, Literal, Optional, Union -from pydantic import BaseModel, Field, RootModel -from enum import Enum +from typing import Annotated, Any, Dict, List, Literal, Optional -class AppGroupVersion(BaseModel): - groupVersion: Optional[str] = None - version: Optional[str] = None +from pydantic import AwareDatetime, BaseModel, Field, RootModel class ErrorIndex(BaseModel): @@ -38,6 +34,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -68,140 +70,293 @@ class ErrorResponse(BaseModel): ] = None -class K8SPatchOp(BaseModel): - from_: Annotated[Optional[str], Field(alias="from")] = None - op: str - path: str - value: Optional[Dict[str, Any]] = None - x_permissive: Annotated[Optional[bool], Field(alias="x-permissive")] = None - - -class Patch(RootModel[List[K8SPatchOp]]): - root: List[K8SPatchOp] - - -class Resource(BaseModel): - kind: Optional[str] = None - name: Optional[str] = None - namespaced: Optional[bool] = None - readOnly: Optional[bool] = None - singularName: Optional[str] = None - uiCategory: Optional[str] = None - - -class ResourceHistoryEntry(BaseModel): - author: Optional[str] = None - changeType: Optional[str] = None - commitTime: Optional[str] = None - hash: Optional[str] = None - message: Optional[str] = None - transactionId: Optional[int] = None +class WorkflowGetInputsRespElem(BaseModel): + ackPrompt: Optional[str] = None + group: str + kind: str + name: str + namespace: Optional[str] = None + schemaPrompt: Optional[Dict[str, Any]] = None + version: str -class ResourceList(BaseModel): - apiVersion: Optional[str] = None - groupVersion: Optional[str] = None - kind: Optional[str] = None - resources: Optional[List[Resource]] = None +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None -class StatusDetails(BaseModel): - group: Optional[str] = None - kind: Optional[str] = None - name: Optional[str] = None +class WorkflowIdentifier(BaseModel): + group: str + kind: str + name: str + namespace: Optional[str] = None + version: str -class UIResult(RootModel[str]): - root: str +class WorkflowInputDataElem(BaseModel): + ack: Annotated[ + Optional[bool], Field(description="acknowledge or reject the input request") + ] = None + input: Annotated[ + Optional[Dict[str, Any]], + Field(description="provide a json blob to the workflow"), + ] = None + subflow: Optional[WorkflowIdentifier] = None -class DeployImageSpecChecksChecks(Enum): +class DeployImageSpecChecks(BaseModel): """ - Checks to run before (pre) and after (post) any image changes + Configure pre and post checks. """ - Interface = "Interface" - DefaultBGP = "DefaultBGP" - PingISL = "PingISL" - PingSystem = "PingSystem" - - -class DeployImageSpecChecks(BaseModel): checks: Annotated[ - Union[List[str], DeployImageSpecChecksChecks], + Optional[List[Literal["Interface", "DefaultBGP", "PingISL", "PingSystem"]]], Field( - description="Checks to run before (pre) and after (post) any image changes", - title="checks", + description="Checks to run before (pre) and after (post) any image changes.\nIf none are specified, a default set of checks will be run.", + title="Checks to Run", ), - ] + ] = None force: Annotated[ - bool, Field(description="Do not prompt for user input, even if checks fail") - ] - skip: Annotated[bool, Field(description="Do not run any checks")] - - -class DeployImageSpecDrains(BaseModel): - interfaceDisableSelectors: Annotated[ - Optional[List[str]], Field(title="InterfaceDisableSelectors") + Optional[bool], + Field( + description="Ignore result of pre and post checks, do not prompt on failure.", + title="Force", + ), ] = None - minimumWaitTime: Annotated[Optional[int], Field(title="minimumWaitTime")] = None skip: Annotated[ - Optional[bool], Field(description="Do not run any drains", title="skip") + Optional[bool], + Field( + description="Do not run any checks pre or post image change.", + title="Skip Checks", + ), ] = None -class DeployImageSpecPrompt(Enum): - AfterPreChecks = "AfterPreChecks" - AfterPostChecks = "AfterPostChecks" +class DeployImageSpecDrains(BaseModel): + """ + Configure drains to gracefully drain traffic away from nodes before imaging. + """ + + minimumWaitTimeSeconds: Annotated[ + Optional[int], + Field( + description="Seconds to wait before rebooting a node after it has been drained.\nThis is used to allow time for any traffic to drain away from the node before reboot.", + title="Minimum Wait Time", + ), + ] = 60 + skip: Annotated[ + Optional[bool], + Field( + description="Do not run any drain operations. Nodes will be rebooted without attempting to gracefully drain them.", + title="Skip Drains", + ), + ] = None class DeployImageSpecTranch(BaseModel): - name: Annotated[Optional[str], Field(title="name")] = None - nodeSelector: Annotated[Optional[List[str]], Field(title="nodeSelector")] = None + name: Annotated[ + Optional[str], + Field( + description="Name of the tranche.\nThis is used to identify the tranche in the UI and in logs.", + title="Name", + ), + ] = None + nodeSelectors: Annotated[ + Optional[List[str]], + Field( + description='Node Selectors is a list of node selectors to select nodes to deploy images on in this tranche.\nThis matches labels on TopoNode resources, including those TopoNodes in the list of nodes that will be imaged.\nThis is a list of label expressions, e.g. ["eda.nokia.com/role=leaf"].', + title="Node Selectors", + ), + ] = None class DeployImageSpec(BaseModel): """ - DeployImageSpec defines the desired state of DeployImage + Upgrade / downgrade images on targets. + This workflow can be used directly on a target or list of targets, or with selectors to select targets through labels. + It also supports tranches, which are groups of targets that can be upgraded together. + By default a set of checks are run before and after the image change, but this can be controlled via the checks field. + It also supports canaries, which are upgraded before any other targets. """ - canaries: Annotated[Optional[List[str]], Field(title="canaries")] = None - checks: Annotated[Optional[DeployImageSpecChecks], Field(title="checks")] = None - drains: Annotated[Optional[DeployImageSpecDrains], Field(title="drains")] = None - nodeProfile: Annotated[Optional[str], Field(title="nodeProfile")] = None - nodeSelector: Annotated[Optional[List[str]], Field(title="nodeSelector")] = None - nodes: Annotated[Optional[List[str]], Field(title="nodes")] = None + canaries: Annotated[ + Optional[List[str]], + Field( + description='List of node selectors to use to match canary nodes.\nThis matches labels on TopoNode resources, including those TopoNodes in the list of nodes that will be imaged.\nCanary nodes are upgraded before any other nodes, and are used to test images before broader roll out.\nThis is a list of label expressions, e.g. ["eda.nokia.com/role=canary"].', + title="Canaries", + ), + ] = None + checks: Annotated[ + Optional[DeployImageSpecChecks], + Field(description="Configure pre and post checks.", title="Checks"), + ] = None + drains: Annotated[ + Optional[DeployImageSpecDrains], + Field( + description="Configure drains to gracefully drain traffic away from nodes before imaging.", + title="Drains", + ), + ] = None + nodeProfile: Annotated[ + str, + Field( + description="Destination profile to use for imaging.\nThis profile contains the image to deploy, and other configuration for the node.", + title="Node Profile", + ), + ] + nodeSelectors: Annotated[ + Optional[List[str]], + Field( + description='List of node selectors to select nodes to deploy images on.\nThis matches labels on TopoNode resources, including those TopoNodes in the list of nodes that will be imaged.\nIf no nodes are specified, and no node selectors are specified, all nodes in the given namespace will be selected.\nThis is a list of label expressions, e.g. ["eda.nokia.com/role=leaf"].', + title="Node Selectors", + ), + ] = None + nodes: Annotated[ + Optional[List[str]], + Field(description="List of nodes to deploy images on.", title="Nodes"), + ] = None prompt: Annotated[ - Optional[Union[List[str], DeployImageSpecPrompt]], Field(title="prompt") + Optional[List[Literal["AfterPreChecks", "AfterPostChecks"]]], + Field( + description="Control when to prompt the user for input.\nIf any pre or post checks fail, the user will be prompted for input, but this may be used to prompt even if they're successful.", + title="Prompt", + ), ] = None tranches: Annotated[ - Optional[List[DeployImageSpecTranch]], Field(title="tranches") + Optional[List[DeployImageSpecTranch]], + Field( + description="List of tranches to use for imaging.\nA tranche is a list of node selectors, and a name.\nTranches are upgraded in order, sequentially.", + title="Tranches", + ), + ] = None + + +class DeployImageStatusDetail(BaseModel): + drainedTime: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the node was drained.\nThis is the time when the node was drained before the imaging operation.", + title="Drained Time", + ), + ] = None + newNodeProfile: Annotated[ + Optional[str], + Field(description="The new profile of the node.", title="New Node Profile"), + ] = None + newVersion: Annotated[ + Optional[str], + Field(description="The new version of the node.", title="New Version"), + ] = None + node: Annotated[ + Optional[str], + Field(description="The name of the node this result is for.", title="Node"), + ] = None + postCheckSuccessful: Annotated[ + Optional[bool], + Field( + description="Indicates if post checks were successful for this node.\nThis is true if all post checks passed, false if any post checks failed.", + title="Post Check Successful", + ), + ] = None + preCheckSuccessful: Annotated[ + Optional[bool], + Field( + description="Indicates if pre checks were successful for this node.\nThis is true if all pre checks passed, false if any pre checks failed.", + title="Pre Check Successful", + ), + ] = None + previousNodeProfile: Annotated[ + Optional[str], + Field( + description="The previous profile of the node.\nThis is the node profile that was running before the imaging operation.", + title="Previous Node Profile", + ), + ] = None + previousVersion: Annotated[ + Optional[str], + Field( + description="The previous version of the node.\nThis is the version of the image that was running before the imaging operation.", + title="Previous Version", + ), + ] = None + rebootRecoveryTime: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the node was recovered after reboot.\nThis is the time when the node was recovered after the imaging operation.", + title="Reboot Recovery Time", + ), + ] = None + rebootTime: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the node was rebooted.\nThis is the time when the node was rebooted during the imaging operation.", + title="Reboot Time", + ), + ] = None + success: Annotated[ + Optional[bool], + Field( + description="Indicates if the imaging operation was successful for this node.\nThis is true if the imaging operation was successful, false if it failed.", + title="Success", + ), + ] = None + undrainedTime: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the node was undrained.\nThis is the time when the node was undrained after the imaging operation.", + title="Undrained Time", + ), ] = None - type: Annotated[Literal["node", "nodeselector", "tranche"], Field(title="type")] - version: Annotated[Optional[str], Field(title="version")] = None class DeployImageStatus(BaseModel): """ - DeployImageStatus defines the observed state of DeployImage + Status of the imaging operation. """ - id: Annotated[Optional[int], Field(description="Id", title="ID")] = None - result: Annotated[ - Optional[str], Field(description="Aggregate result of the Flow", title="Result") + details: Annotated[ + Optional[List[DeployImageStatusDetail]], + Field(description="Per-node image deployment details.", title="Details"), ] = None - - -class DeployImageDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None - hash: Optional[str] = None - name: Optional[str] = None - namespace: Optional[str] = None - transactionId: Optional[int] = None - - -class DeployImageDeletedResources(RootModel[List[DeployImageDeletedResourceEntry]]): - root: List[DeployImageDeletedResourceEntry] + firstNodeDrained: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the first node was drained.", + title="First Node Drained", + ), + ] = None + firstNodeRebooted: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the first node was rebooted.", + title="First Node Rebooted", + ), + ] = None + lastNodeRebootRecovered: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the last node recovered post reboot.", + title="Last Node Recovered", + ), + ] = None + lastNodeUndrained: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the last node was undrained.", + title="Last Node Undrained", + ), + ] = None + result: Annotated[ + Literal["Success", "Failed", "PartialSuccess"], + Field( + description='Result is the overall result of the image operation.\nIt can be one of the following values:\n- "Success": All images were successfully deployed.\n- "Failed": No images were successfully deployed.\n- "PartialSuccess": Some images were successfully deployed, but not all.', + title="Result", + ), + ] class DeployImageMetadata(BaseModel): @@ -217,23 +372,8 @@ class DeployImageMetadata(BaseModel): namespace: str -class AppGroup(BaseModel): - apiVersion: Optional[str] = None - kind: Optional[str] = None - name: Optional[str] = None - preferredVersion: Optional[AppGroupVersion] = None - versions: Optional[List[AppGroupVersion]] = None - - -class ResourceHistory(RootModel[List[ResourceHistoryEntry]]): - root: List[ResourceHistoryEntry] - - -class Status(BaseModel): - apiVersion: Optional[str] = None - details: Optional[StatusDetails] = None - kind: Optional[str] = None - string: Optional[str] = None +class WorkflowInputData(RootModel[List[WorkflowInputDataElem]]): + root: List[WorkflowInputDataElem] class DeployImage(BaseModel): @@ -247,16 +387,13 @@ class DeployImage(BaseModel): spec: Annotated[ DeployImageSpec, Field( - description="DeployImageSpec defines the desired state of DeployImage", + description="Upgrade / downgrade images on targets.\nThis workflow can be used directly on a target or list of targets, or with selectors to select targets through labels.\nIt also supports tranches, which are groups of targets that can be upgraded together.\nBy default a set of checks are run before and after the image change, but this can be controlled via the checks field.\nIt also supports canaries, which are upgraded before any other targets.", title="Specification", ), ] status: Annotated[ Optional[DeployImageStatus], - Field( - description="DeployImageStatus defines the observed state of DeployImage", - title="Status", - ), + Field(description="Status of the imaging operation.", title="Status"), ] = None diff --git a/pydantic_eda/apps/protocols/v1/models.py b/pydantic_eda/apps/protocols/v1/models.py new file mode 100644 index 0000000..7aa78d2 --- /dev/null +++ b/pydantic_eda/apps/protocols/v1/models.py @@ -0,0 +1,4654 @@ +# generated by datamodel-codegen: +# filename: protocols.json + +from __future__ import annotations + +from typing import Annotated, Any, Dict, List, Literal, Optional + +from pydantic import AwareDatetime, BaseModel, Field, RootModel + + +class AppGroupVersion(BaseModel): + groupVersion: Optional[str] = None + version: Optional[str] = None + + +class ErrorIndex(BaseModel): + index: Optional[int] = None + + +class ErrorItem(BaseModel): + error: Optional[Dict[str, Any]] = None + type: Optional[str] = None + + +class ErrorResponse(BaseModel): + """ + Generic error response for REST APIs + """ + + code: Annotated[ + int, Field(description="the numeric HTTP error code for the response.") + ] + details: Annotated[ + Optional[str], Field(description="The optional details of the error response.") + ] = None + dictionary: Annotated[ + Optional[Dict[str, Any]], + Field( + description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' + ), + ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None + errors: Annotated[ + Optional[List[ErrorItem]], + Field( + description="Collection of errors in cases where more than one exists. This needs to be\nflexible so we can support multiple formats" + ), + ] = None + index: Optional[ErrorIndex] = None + internal: Annotated[ + Optional[int], + Field( + description="Internal error code in cases where we don't have an array of errors" + ), + ] = None + message: Annotated[ + str, Field(description="The basic text error message for the error response.") + ] + ref: Annotated[ + Optional[str], + Field( + description="Reference to the error source. Should typically be the URI of the request" + ), + ] = None + type: Annotated[ + Optional[str], + Field( + description="URI pointing at a document that describes the error and mitigation steps\nIf there is no document, point to the RFC for the HTTP error code" + ), + ] = None + + +class K8SPatchOp(BaseModel): + from_: Annotated[Optional[str], Field(alias="from")] = None + op: str + path: str + value: Optional[Dict[str, Any]] = None + x_permissive: Annotated[Optional[bool], Field(alias="x-permissive")] = None + + +class Patch(RootModel[List[K8SPatchOp]]): + root: List[K8SPatchOp] + + +class Resource(BaseModel): + kind: Optional[str] = None + name: Optional[str] = None + namespaced: Optional[bool] = None + readOnly: Optional[bool] = None + singularName: Optional[str] = None + uiCategory: Optional[str] = None + + +class ResourceHistoryEntry(BaseModel): + author: Optional[str] = None + changeType: Optional[str] = None + commitTime: Optional[AwareDatetime] = None + hash: Optional[str] = None + message: Optional[str] = None + transactionId: Optional[int] = None + + +class ResourceList(BaseModel): + apiVersion: Optional[str] = None + groupVersion: Optional[str] = None + kind: Optional[str] = None + resources: Optional[List[Resource]] = None + + +class StatusDetails(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + name: Optional[str] = None + + +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + +class UIResult(RootModel[str]): + root: str + + +class WorkflowGetInputsRespElem(BaseModel): + ackPrompt: Optional[str] = None + group: str + kind: str + name: str + namespace: Optional[str] = None + schemaPrompt: Optional[Dict[str, Any]] = None + version: str + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowIdentifier(BaseModel): + group: str + kind: str + name: str + namespace: Optional[str] = None + version: str + + +class WorkflowInputDataElem(BaseModel): + ack: Annotated[ + Optional[bool], Field(description="acknowledge or reject the input request") + ] = None + input: Annotated[ + Optional[Dict[str, Any]], + Field(description="provide a json blob to the workflow"), + ] = None + subflow: Optional[WorkflowIdentifier] = None + + +class AggregateRouteSpec(BaseModel): + """ + The AggregateRoute enables the configuration of aggregated routes on a specified Router. This resource allows for the definition of destination prefixes, the selection of a router, and optionally, specific nodes where the aggregate routes should be configured. Advanced options include the ability to generate ICMP unreachable messages for packets matching the aggregate route, and the ability to block the advertisement of all contributing routes in dynamic protocols like BGP. + """ + + aggregatorASN: Annotated[ + Optional[int], + Field(description="Specifies the aggregator's ASN.", title="Aggregator ASN"), + ] = None + aggregatorIP: Annotated[ + Optional[str], + Field( + description="Specifies the aggregator's IP address.", title="Aggregator IP" + ), + ] = None + generateICMP: Annotated[ + Optional[bool], + Field( + description="When set to true the router generares ICMP unreachable messages for packets matching the aggregate route (and not a more specific route).", + title="Generate ICMP", + ), + ] = None + nodes: Annotated[ + Optional[List[str]], + Field( + description="List of nodes on which to configure the aggregate routes. An AND operation is executed against the nodes in this list and the nodes on which the Router is configured to determine the Nodes on which to configure the aggregate routes.", + title="Nodes", + ), + ] = None + prefixes: Annotated[ + List[str], + Field( + description="List of destination prefixes for the aggregate routes.", + title="Prefixes", + ), + ] + router: Annotated[ + str, + Field( + description="Reference to a Router on which to configure the aggregate routes. If no Nodes are provided then the aggregate routes will be provisioned on all Nodes on which the Router is provisioned.", + title="Router", + ), + ] + summaryOnly: Annotated[ + Optional[bool], + Field( + description="When set to true the router blocks the advertisement of all contributing routes of this aggregate route in dynamic protocols such as BGP.", + title="Summary Only", + ), + ] = None + + +class AggregateRouteDeletedResourceEntry(BaseModel): + commitTime: Optional[AwareDatetime] = None + hash: Optional[str] = None + name: Optional[str] = None + namespace: Optional[str] = None + transactionId: Optional[int] = None + + +class AggregateRouteDeletedResources( + RootModel[List[AggregateRouteDeletedResourceEntry]] +): + root: List[AggregateRouteDeletedResourceEntry] + + +class AggregateRouteMetadata(BaseModel): + annotations: Optional[Dict[str, str]] = None + labels: Optional[Dict[str, str]] = None + name: Annotated[ + str, + Field( + max_length=253, + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + ), + ] + namespace: str + + +class BGPGroupSpecAsPathOptionsRemovePrivateAS(BaseModel): + """ + Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers. + """ + + ignorePeerAS: Annotated[ + bool, + Field( + description="If set to true then do not delete or replace a private AS number that is the same as the peer AS number.", + title="Ignore Peer AS", + ), + ] + leadingOnly: Annotated[ + bool, + Field( + description="If set to true then only delete or replace private AS numbers that appear before the first occurrence of a non-private ASN in the sequence of most recent ASNs in the AS path.", + title="Leading Only", + ), + ] + removePrivateASMode: Annotated[ + Literal["DISABLED", "REPLACE", "DELETE"], + Field( + description="The method by which private AS numbers are removed from the advertised AS_PATH attribute.", + title="Remove Private AS Mode", + ), + ] + + +class BGPGroupSpecAsPathOptions(BaseModel): + """ + AS Path Options + """ + + allowOwnAS: Annotated[ + int, + Field( + description="The maximum number of times the global AS number or a local AS number of the BGP instance can appear in any received AS_PATH before it is considered a loop and considered invalid.", + ge=0, + le=255, + title="Allow Own AS", + ), + ] + removePrivateAS: Annotated[ + Optional[BGPGroupSpecAsPathOptionsRemovePrivateAS], + Field( + description="Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers.", + title="Remove Private AS", + ), + ] = None + + +class BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted(BaseModel): + logOnly: Annotated[ + Optional[bool], + Field( + description="Defines the action to take when the maximum number of prefixes is exceeded. Session is reset if set to false, otherwise only a warning is logged.", + title="Log Only", + ), + ] = None + maxReceivedRoutes: Annotated[ + Optional[int], + Field( + description="Maximum number of prefixes allowed to be received from the neighbor, counting only accepted routes.", + ge=1, + le=4294967295, + title="Max Received Routes", + ), + ] = None + warningThreshold: Annotated[ + Optional[int], + Field( + description="A percentage of the maximum number of prefixes that can be accepted before a warning is logged.", + ge=1, + le=100, + title="Warning Threshold Percentage", + ), + ] = None + + +class BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived(BaseModel): + logOnly: Annotated[ + Optional[bool], + Field( + description="Defines the action to take when the maximum number of prefixes is exceeded. Session is reset if set to false, otherwise only a warning is logged.", + title="Log Only", + ), + ] = None + maxReceivedRoutes: Annotated[ + Optional[int], + Field( + description="Maximum number of prefixes allowed to be received from the neighbor, counting all routes (accepted and rejected by import policies).", + ge=1, + le=4294967295, + title="Max Received Routes", + ), + ] = None + warningThreshold: Annotated[ + Optional[int], + Field( + description="A percentage of the maximum number of prefixes that can be received before a warning is logged.", + ge=1, + le=100, + title="Warning Threshold Percentage", + ), + ] = None + + +class BGPGroupSpecIpv4UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class BGPGroupSpecIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[BGPGroupSpecIpv4UnicastPrefixLimit], Field(title="Prefix Limit") + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +BGPGroupSpecIpv6UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +BGPGroupSpecIpv6UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class BGPGroupSpecIpv6UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[BGPGroupSpecIpv6UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[BGPGroupSpecIpv6UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class BGPGroupSpecIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[BGPGroupSpecIpv6UnicastPrefixLimit], Field(title="Prefix Limit") + ] = None + + +class BGPGroupSpecLocalAS(BaseModel): + """ + The local autonomous system number advertised to peers. + """ + + autonomousSystem: Annotated[ + int, + Field( + description="Local Autonomous System number.", + ge=1, + le=4294967295, + title="Local Autonomous System", + ), + ] + prependGlobalAS: Annotated[ + Optional[bool], + Field( + description="When set to true, the global ASN value is prepended to the AS path in outbound routes towards each BGP peer.", + title="Prepend Global Autonomous System", + ), + ] = None + prependLocalAS: Annotated[ + Optional[bool], + Field( + description="When set to true, the local AS value is prepended to the AS path of inbound routes from each EBGP peer.", + title="Prepend Local Autonomous System", + ), + ] = None + + +class BGPGroupSpecPeerAS(BaseModel): + """ + The autonomous system number expected from peers. + """ + + autonomousSystem: Annotated[ + int, + Field( + description="Local Autonomous System number.", + ge=1, + le=4294967295, + title="Peer Autonomous System", + ), + ] + + +class BGPGroupSpecSendDefaultRoute(BaseModel): + """ + Options for controlling the generation of default routes towards BGP peers. + """ + + addressFamily: Annotated[ + List[Literal["IPV4-UNICAST", "IPV6-UNICAST"]], + Field( + description="Enables the sending of a synthetically generated default IPv4 or IPV6 route to each peer.", + title="Address Families", + ), + ] + exportPolicy: Annotated[ + Optional[str], + Field( + description="Reference to a Policy that should be applied to the advertised default routes, in order to set their attributes to non-default values.", + title="Export Policy", + ), + ] = None + + +class BGPGroupSpecTimers(BaseModel): + """ + Timer configurations + """ + + connectRetry: Annotated[ + Optional[int], + Field( + description="The time interval in seconds between successive attempts to establish a session with a peer.", + ge=1, + le=65535, + title="Connect Retry", + ), + ] = None + holdTime: Annotated[ + Optional[int], + Field( + description="The hold-time interval in seconds that the router proposes to the peer in its OPEN message.", + ge=0, + le=65535, + title="Hold Time", + ), + ] = None + keepAlive: Annotated[ + Optional[int], + Field( + description="The interval in seconds between successive keepalive messages sent to the peer.", + ge=0, + le=21845, + title="Keep Alive", + ), + ] = None + minimumAdvertisementInterval: Annotated[ + Optional[int], + Field( + description="The value assigned to the MinRouteAdvertisementIntervalTimer of RFC 4271, for both EBGP and IBGP sessions.", + ge=1, + le=255, + title="Minimum Advertisement Interval", + ), + ] = None + + +class BGPGroupSpec(BaseModel): + """ + The BGPGroup enables centralized management of BGP peer configurations. This resource allows setting a description, common BGP settings, and peer-specific configurations, simplifying the consistent application of policies across multiple peers. It also includes transport settings, such as local TCP address configuration, passive mode, and TCP MSS. + """ + + asPathOptions: Annotated[ + Optional[BGPGroupSpecAsPathOptions], + Field(description="AS Path Options", title="AS Path Options"), + ] = None + bfd: Annotated[ + Optional[bool], + Field( + description="Enable or disable Bi-forward Forwarding Detection (BFD) with fast failover.", + title="BFD", + ), + ] = None + client: Annotated[ + Optional[bool], + Field( + description="When set to true, all configured and dynamic BGP peers are considered RR clients.", + title="Route Reflector Client", + ), + ] = None + clusterID: Annotated[ + Optional[str], + Field( + description="Enables route reflect client and sets the cluster ID.", + title="Cluster ID", + ), + ] = None + description: Annotated[ + Optional[str], + Field( + description="Sets the description on the BGP group.", title="Description" + ), + ] = None + exportPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes advertised to peers.", + title="Export Policy", + ), + ] = None + grStaleRouteTime: Annotated[ + Optional[int], + Field( + description="Enables Graceful Restart on the peer and sets the stale route time.", + ge=1, + le=3600, + title="GR Stale Route Time", + ), + ] = None + importPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes received from peers.", + title="Import Policy", + ), + ] = None + ipv4Unicast: Annotated[ + Optional[BGPGroupSpecIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[BGPGroupSpecIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field( + description="Reference to a Keychain resource that will be used for authentication with the BGP peer.", + title="Keychain", + ), + ] = None + localAS: Annotated[ + Optional[BGPGroupSpecLocalAS], + Field( + description="The local autonomous system number advertised to peers.", + title="Local AS", + ), + ] = None + localPreference: Annotated[ + Optional[int], + Field( + description="Local Preference attribute added to received routes from the BGP peers, also sets local preference for generated routes.", + ge=0, + le=4294967295, + title="Local Preference", + ), + ] = None + multiHopMaxHop: Annotated[ + Optional[int], + Field( + description="Enable multihop for eBGP peers and sets the maximum number of hops allowed.", + ge=1, + le=255, + title="Multihop Max Hop Count", + ), + ] = None + nextHopSelf: Annotated[ + Optional[bool], + Field( + description="When set to true, the next-hop in all IPv4-unicast, IPv6-unicast and EVPN BGP routes advertised to the peer is set to the local-address.", + title="Next Hop Self", + ), + ] = None + peerAS: Annotated[ + Optional[BGPGroupSpecPeerAS], + Field( + description="The autonomous system number expected from peers.", + title="Peer AS", + ), + ] = None + sendCommunityLarge: Annotated[ + Optional[bool], + Field( + description="When false, all large (12 byte) BGP communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Large", + ), + ] = None + sendCommunityStandard: Annotated[ + Optional[bool], + Field( + description="When false, all standard (4 byte) communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Standard", + ), + ] = None + sendDefaultRoute: Annotated[ + Optional[BGPGroupSpecSendDefaultRoute], + Field( + description="Options for controlling the generation of default routes towards BGP peers.", + title="Send Default Route", + ), + ] = None + timers: Annotated[ + Optional[BGPGroupSpecTimers], + Field(description="Timer configurations", title="Timers"), + ] = None + + +class BGPGroupStatus(BaseModel): + """ + BGPGroupStatus defines the observed state of BGPGroup + """ + + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the BGP group.", title="Health" + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + numPeers: Annotated[ + Optional[int], + Field( + description="Number of configured BGP peers within the BGP Group.", + title="Number of Peers", + ), + ] = None + numPeersOperDown: Annotated[ + Optional[int], + Field( + description="Number of configured BGP peers which have an Operational State of down within the BGP Group.", + title="Number of Peers Operational Down", + ), + ] = None + numPeersUnknown: Annotated[ + Optional[int], + Field( + description="Number of configured BGP peers within the BGP Group which cannot be reached by npp.", + title="Number of unknown BGP Peers", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the BGP group.", title="Operational State" + ), + ] = None + + +BGPGroupDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class BGPGroupDeletedResources(RootModel[List[BGPGroupDeletedResourceEntry]]): + root: List[BGPGroupDeletedResourceEntry] + + +BGPGroupMetadata = AggregateRouteMetadata + + +BGPPeerSpecAsPathOptionsRemovePrivateAS = BGPGroupSpecAsPathOptionsRemovePrivateAS + + +class BGPPeerSpecAsPathOptions(BaseModel): + """ + AS Path Options + """ + + allowOwnAS: Annotated[ + int, + Field( + description="The maximum number of times the global AS number or a local AS number of the BGP instance can appear in any received AS_PATH before it is considered a loop and considered invalid.", + ge=0, + le=255, + title="Allow Own AS", + ), + ] + removePrivateAS: Annotated[ + Optional[BGPPeerSpecAsPathOptionsRemovePrivateAS], + Field( + description="Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers.", + title="Remove Private AS", + ), + ] = None + + +BGPPeerSpecIpv4UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +BGPPeerSpecIpv4UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class BGPPeerSpecIpv4UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[BGPPeerSpecIpv4UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[BGPPeerSpecIpv4UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class BGPPeerSpecIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[BGPPeerSpecIpv4UnicastPrefixLimit], Field(title="Prefix Limit") + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +BGPPeerSpecIpv6UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +BGPPeerSpecIpv6UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class BGPPeerSpecIpv6UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[BGPPeerSpecIpv6UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[BGPPeerSpecIpv6UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class BGPPeerSpecIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[BGPPeerSpecIpv6UnicastPrefixLimit], Field(title="Prefix Limit") + ] = None + + +BGPPeerSpecLocalAS = BGPGroupSpecLocalAS + + +BGPPeerSpecPeerAS = BGPGroupSpecPeerAS + + +BGPPeerSpecSendDefaultRoute = BGPGroupSpecSendDefaultRoute + + +BGPPeerSpecTimers = BGPGroupSpecTimers + + +class BGPPeerSpec(BaseModel): + """ + BGPPeer enables the configuration of BGP sessions. It allows specifying a description, an interface reference (either RoutedInterface or IrbInterface), and the peer IP address. The resource also supports dynamic neighbors, common BGP settings, and peer-specific configurations. + """ + + asPathOptions: Annotated[ + Optional[BGPPeerSpecAsPathOptions], + Field(description="AS Path Options", title="AS Path Options"), + ] = None + bfd: Annotated[ + Optional[bool], + Field( + description="Enable or disable Bi-forward Forwarding Detection (BFD) with fast failover.", + title="BFD", + ), + ] = None + client: Annotated[ + Optional[bool], + Field( + description="When set to true, all configured and dynamic BGP peers are considered RR clients.", + title="Route Reflector Client", + ), + ] = None + clusterID: Annotated[ + Optional[str], + Field( + description="Enables route reflect client and sets the cluster ID.", + title="Cluster ID", + ), + ] = None + description: Annotated[ + Optional[str], + Field(description="Sets the description on the BGP peer", title="Description"), + ] = None + dynamicNeighbor: Annotated[ + Optional[bool], + Field( + description="When set to true the Interface is added to the dynamic-neighbor list for dynamic peering.", + title="Dynamic Neighbor", + ), + ] = False + dynamicNeighborAllowedPeerAS: Annotated[ + Optional[List[int]], + Field( + description="The autonomous system numbers allowed from peers if dynamic peering is enabled.", + title="Dynamic Neighbor Allowed Peer AS", + ), + ] = None + exportPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes advertised to peers.", + title="Export Policy", + ), + ] = None + grStaleRouteTime: Annotated[ + Optional[int], + Field( + description="Enables Graceful Restart on the peer and sets the stale route time.", + ge=1, + le=3600, + title="GR Stale Route Time", + ), + ] = None + group: Annotated[ + str, + Field( + description="Reference to a BGPGroup. When present this BGP peer will be added to the BGP group", + title="Group", + ), + ] + importPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes received from peers.", + title="Import Policy", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to a RoutedInterface or IrbInterface resource whose IP will be used as a source IP for the BGP session.", + title="Interface Reference", + ), + ] + interfaceKind: Annotated[ + Literal["ROUTEDINTERFACE", "IRBINTERFACE"], + Field( + description="InterfaceReference type defines whether the provided Reference is a RoutedInterface or IrbInterface.", + title="Interface Reference Type", + ), + ] + ipv4Unicast: Annotated[ + Optional[BGPPeerSpecIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[BGPPeerSpecIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field( + description="Reference to a Keychain resource that will be used for authentication with the BGP peer.", + title="Keychain", + ), + ] = None + localAS: Annotated[ + Optional[BGPPeerSpecLocalAS], + Field( + description="The local autonomous system number advertised to peers.", + title="Local AS", + ), + ] = None + localPreference: Annotated[ + Optional[int], + Field( + description="Local Preference attribute added to received routes from the BGP peers, also sets local preference for generated routes.", + ge=0, + le=4294967295, + title="Local Preference", + ), + ] = None + multiHopMaxHop: Annotated[ + Optional[int], + Field( + description="Enable multihop for eBGP peers and sets the maximum number of hops allowed.", + ge=1, + le=255, + title="Multihop Max Hop Count", + ), + ] = None + nextHopSelf: Annotated[ + Optional[bool], + Field( + description="When set to true, the next-hop in all IPv4-unicast, IPv6-unicast and EVPN BGP routes advertised to the peer is set to the local-address.", + title="Next Hop Self", + ), + ] = None + node: Annotated[ + Optional[str], + Field( + description="Node on which to configure the BGP peer. This node must be one of the nodes on which the IRBInterface is configured. When left blank or if the node is not part of the IRBInterface, the peer will not be deployed. Ignored for RoutedInterfaces.", + title="Node", + ), + ] = None + peerAS: Annotated[ + Optional[BGPPeerSpecPeerAS], + Field( + description="The autonomous system number expected from peers.", + title="Peer AS", + ), + ] = None + peerIP: Annotated[ + Optional[str], + Field( + description="Peer IP to which the peering session will be established.", + title="Peer IP", + ), + ] = None + sendCommunityLarge: Annotated[ + Optional[bool], + Field( + description="When false, all large (12 byte) BGP communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Large", + ), + ] = None + sendCommunityStandard: Annotated[ + Optional[bool], + Field( + description="When false, all standard (4 byte) communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Standard", + ), + ] = None + sendDefaultRoute: Annotated[ + Optional[BGPPeerSpecSendDefaultRoute], + Field( + description="Options for controlling the generation of default routes towards BGP peers.", + title="Send Default Route", + ), + ] = None + timers: Annotated[ + Optional[BGPPeerSpecTimers], + Field(description="Timer configurations", title="Timers"), + ] = None + + +class BGPPeerStatus(BaseModel): + """ + BGPPeerStatus defines the observed state of BGPPeer + """ + + enabled: Annotated[ + Optional[bool], + Field( + description="Indicated whether the BGP Peer is administratively enabled.", + title="Enabled", + ), + ] = None + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the BGP peer.", title="Health" + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + lastEvent: Annotated[ + Optional[str], + Field(description="Last event of the BGP peer.", title="Last Event"), + ] = None + lastState: Annotated[ + Optional[str], + Field(description="Last state of the BGP peer.", title="Last State"), + ] = None + negotiatedHoldTime: Annotated[ + Optional[int], + Field( + description="Hold time negotiated with the BGP peer.", + title="Negotiated Hold Time", + ), + ] = None + negotiatedKeepaliveInterval: Annotated[ + Optional[int], + Field( + description="Keepalive interval negotiated with the BGP peer.", + title="Negotiated Keepalive Interval", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the BGP peer", title="Operational State" + ), + ] = None + peerAS: Annotated[ + Optional[int], Field(description="Peer AS of the BGP peer.", title="Peer AS") + ] = None + sessionState: Annotated[ + Optional[str], + Field(description="The state of the BGP session.", title="Session State"), + ] = None + underMaintenance: Annotated[ + Optional[bool], + Field( + description="Indicates if the BGP peer is under maintenance.", + title="Under Maintenance", + ), + ] = None + + +class BGPPeerStateSpec(BaseModel): + """ + BGPPeerStateSpec defines the desired state of BGPPeerState + """ + + afiSAFI: Annotated[ + Optional[List[str]], + Field(description="List of configured AFI-SAFI on the BGP peer"), + ] = None + defaultNetworkInstance: Annotated[ + bool, Field(description="Denotes if the router is a DefaultRouter or Router") + ] + dynamicNeighbor: Annotated[ + bool, + Field( + description="When set to true the PeerDefaultInterface is added to the dynamic-neighbor list for dynamic peering." + ), + ] + group: Annotated[Optional[str], Field(description="Reference to a BGPGroup")] = None + networkInstanceName: Annotated[ + str, + Field( + description="The name of the network-instance or VPRN in which the BGP peer is configured" + ), + ] + node: Annotated[ + Optional[str], + Field(description="The Node on which the BGP peer configuration resides"), + ] = None + nodeInterface: Annotated[ + Optional[str], + Field( + description="Node interface of the default interface which is configured to peer as a dynamic neighbor" + ), + ] = None + operatingSystem: Annotated[ + Optional[str], Field(description="Operating System of the Node") + ] = None + peerIP: Annotated[Optional[str], Field(description="The IP of the BGP peer")] = None + router: Annotated[ + str, Field(description="Router to which the BGP peer is attached") + ] + subInterfaceIndex: Annotated[ + Optional[int], + Field( + description="Sub interface index of the default interface which is configured to peer as a dynamic neighbor" + ), + ] = None + + +BGPPeerStateDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class BGPPeerStateDeletedResources(RootModel[List[BGPPeerStateDeletedResourceEntry]]): + root: List[BGPPeerStateDeletedResourceEntry] + + +BGPPeerStateMetadata = AggregateRouteMetadata + + +BGPPeerDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class BGPPeerDeletedResources(RootModel[List[BGPPeerDeletedResourceEntry]]): + root: List[BGPPeerDeletedResourceEntry] + + +BGPPeerMetadata = AggregateRouteMetadata + + +class CheckDefaultBgpPeersSpec(BaseModel): + """ + CheckDefaultBgpPeersSpec defines the desired state of CheckDefaultBgpPeers + """ + + nodeSelector: Annotated[Optional[List[str]], Field(title="nodeselector")] = None + nodes: Annotated[Optional[List[str]], Field(title="nodes")] = None + waitFor: Annotated[Optional[int], Field(title="waitfor")] = None + + +class CheckDefaultBgpPeersStatus(BaseModel): + """ + CheckDefaultBgpPeersStatus defines the observed state of CheckDefaultBgpPeers + """ + + id: Annotated[Optional[int], Field(description="Id", title="ID")] = None + result: Annotated[ + Optional[str], Field(description="Aggregate result of the Flow", title="Result") + ] = None + + +CheckDefaultBgpPeersMetadata = AggregateRouteMetadata + + +class DefaultAggregateRouteSpec(BaseModel): + """ + DefaultAggregateRoute allows the configuration of aggregate routes on a DefaultRouter. It includes specifying destination prefixes, the DefaultRouter, and settings for generating ICMP unreachable messages or blocking route advertisement. Additionally, it configures the aggregator’s IP address and ASN for efficient route management. + """ + + aggregatorASN: Annotated[ + Optional[int], + Field(description="Specifies the aggregator's ASN.", title="Aggregator ASN"), + ] = None + aggregatorIP: Annotated[ + Optional[str], + Field( + description="Specifies the aggregator's IP address.", title="Aggregator IP" + ), + ] = None + defaultRouter: Annotated[ + str, + Field( + description="Reference to a Default Router on which to configure the aggregate routes. If no Nodes are provided then the aggregate routes will be provisioned on all Nodes on which the Router is provisioned.", + title="DefaultRouter", + ), + ] + generateICMP: Annotated[ + Optional[bool], + Field( + description="When set to true the router generares ICMP unreachable messages for packets matching the aggregate route (and not a more specific route).", + title="Generate ICMP", + ), + ] = None + prefixes: Annotated[ + List[str], + Field( + description="List of destination prefixes for the aggregate routes.", + title="Prefixes", + ), + ] + summaryOnly: Annotated[ + Optional[bool], + Field( + description="When set to true the router blocks the advertisement of all contributing routes of this aggregate route in dynamic protocols such as BGP.", + title="Summary Only", + ), + ] = None + + +DefaultAggregateRouteDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class DefaultAggregateRouteDeletedResources( + RootModel[List[DefaultAggregateRouteDeletedResourceEntry]] +): + root: List[DefaultAggregateRouteDeletedResourceEntry] + + +DefaultAggregateRouteMetadata = AggregateRouteMetadata + + +DefaultBGPGroupSpecAsPathOptionsRemovePrivateAS = ( + BGPGroupSpecAsPathOptionsRemovePrivateAS +) + + +class DefaultBGPGroupSpecAsPathOptions(BaseModel): + """ + AS Path Options + """ + + allowOwnAS: Annotated[ + int, + Field( + description="The maximum number of times the global AS number or a local AS number of the BGP instance can appear in any received AS_PATH before it is considered a loop and considered invalid.", + ge=0, + le=255, + title="Allow Own AS", + ), + ] + removePrivateAS: Annotated[ + Optional[DefaultBGPGroupSpecAsPathOptionsRemovePrivateAS], + Field( + description="Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers.", + title="Remove Private AS", + ), + ] = None + + +DefaultBGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultBGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultBGPGroupSpecIpv4UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[DefaultBGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[DefaultBGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultBGPGroupSpecIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultBGPGroupSpecIpv4UnicastPrefixLimit], Field(title="Prefix Limit") + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +DefaultBGPGroupSpecIpv6UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultBGPGroupSpecIpv6UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultBGPGroupSpecIpv6UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[DefaultBGPGroupSpecIpv6UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[DefaultBGPGroupSpecIpv6UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultBGPGroupSpecIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultBGPGroupSpecIpv6UnicastPrefixLimit], Field(title="Prefix Limit") + ] = None + + +DefaultBGPGroupSpecL2VPNEVPNPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultBGPGroupSpecL2VPNEVPNPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultBGPGroupSpecL2VPNEVPNPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[DefaultBGPGroupSpecL2VPNEVPNPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[DefaultBGPGroupSpecL2VPNEVPNPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultBGPGroupSpecL2VPNEVPN(BaseModel): + """ + Parameters relating to the EVPN AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of EVPN routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the L2VPN EVPN AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultBGPGroupSpecL2VPNEVPNPrefixLimit], Field(title="Prefix Limit") + ] = None + + +DefaultBGPGroupSpecLocalAS = BGPGroupSpecLocalAS + + +DefaultBGPGroupSpecPeerAS = BGPGroupSpecPeerAS + + +DefaultBGPGroupSpecSendDefaultRoute = BGPGroupSpecSendDefaultRoute + + +DefaultBGPGroupSpecTimers = BGPGroupSpecTimers + + +class DefaultBGPGroupSpec(BaseModel): + """ + The DefaultBGPGroup enables centralized management of BGP peer configurations within a DefaultRouter. This resource allows setting a description, common BGP settings, and peer-specific configurations, simplifying the consistent application of policies across multiple peers. It also includes transport settings, such as local TCP address configuration, passive mode, and TCP MSS. type DefaultBGPGroupSpec struct { + """ + + asPathOptions: Annotated[ + Optional[DefaultBGPGroupSpecAsPathOptions], + Field(description="AS Path Options", title="AS Path Options"), + ] = None + bfd: Annotated[ + Optional[bool], + Field( + description="Enable or disable Bi-forward Forwarding Detection (BFD) with fast failover.", + title="BFD", + ), + ] = None + client: Annotated[ + Optional[bool], + Field( + description="When set to true, all configured and dynamic BGP peers are considered RR clients.", + title="Route Reflector Client", + ), + ] = None + clusterID: Annotated[ + Optional[str], + Field( + description="Enables route reflect client and sets the cluster ID.", + title="Cluster ID", + ), + ] = None + description: Annotated[ + Optional[str], + Field( + description="Sets the description on the BGP group.", title="Description" + ), + ] = None + exportPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes advertised to peers.", + title="Export Policy", + ), + ] = None + grStaleRouteTime: Annotated[ + Optional[int], + Field( + description="Enables Graceful Restart on the peer and sets the stale route time.", + ge=1, + le=3600, + title="GR Stale Route Time", + ), + ] = None + importPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes received from peers.", + title="Import Policy", + ), + ] = None + ipv4Unicast: Annotated[ + Optional[DefaultBGPGroupSpecIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[DefaultBGPGroupSpecIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field( + description="Reference to a Keychain resource that will be used for authentication with the BGP peer.", + title="Keychain", + ), + ] = None + l2VPNEVPN: Annotated[ + Optional[DefaultBGPGroupSpecL2VPNEVPN], + Field( + description="Parameters relating to the EVPN AFI/SAFI.", + title="L2VPN EVPN Settings", + ), + ] = None + localAS: Annotated[ + Optional[DefaultBGPGroupSpecLocalAS], + Field( + description="The local autonomous system number advertised to peers.", + title="Local AS", + ), + ] = None + localPreference: Annotated[ + Optional[int], + Field( + description="Local Preference attribute added to received routes from the BGP peers, also sets local preference for generated routes.", + ge=0, + le=4294967295, + title="Local Preference", + ), + ] = None + multiHopMaxHop: Annotated[ + Optional[int], + Field( + description="Enable multihop for eBGP peers and sets the maximum number of hops allowed.", + ge=1, + le=255, + title="Multihop Max Hop Count", + ), + ] = None + nextHopSelf: Annotated[ + Optional[bool], + Field( + description="When set to true, the next-hop in all IPv4-unicast, IPv6-unicast and EVPN BGP routes advertised to the peer is set to the local-address.", + title="Next Hop Self", + ), + ] = None + peerAS: Annotated[ + Optional[DefaultBGPGroupSpecPeerAS], + Field( + description="The autonomous system number expected from peers.", + title="Peer AS", + ), + ] = None + sendCommunityLarge: Annotated[ + Optional[bool], + Field( + description="When false, all large (12 byte) BGP communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Large", + ), + ] = None + sendCommunityStandard: Annotated[ + Optional[bool], + Field( + description="When false, all standard (4 byte) communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Standard", + ), + ] = None + sendDefaultRoute: Annotated[ + Optional[DefaultBGPGroupSpecSendDefaultRoute], + Field( + description="Options for controlling the generation of default routes towards BGP peers.", + title="Send Default Route", + ), + ] = None + timers: Annotated[ + Optional[DefaultBGPGroupSpecTimers], + Field(description="Timer configurations", title="Timers"), + ] = None + + +class DefaultBGPGroupStatus(BaseModel): + """ + DefaultBGPGroupStatus defines the observed state of DefaultBGPGroup. + """ + + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the BGP group.", title="Health" + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + numPeers: Annotated[ + Optional[int], + Field( + description="Number of configured BGP peers within the BGP Group.", + title="Number of Peers", + ), + ] = None + numPeersOperDown: Annotated[ + Optional[int], + Field( + description="Number of configured BGP peers which have an Operational State of down within the BGP Group.", + title="Number of Peers Operational Down", + ), + ] = None + numPeersUnknown: Annotated[ + Optional[int], + Field( + description="Number of configured BGP peers within the BGP Group which cannot be reached by npp.", + title="Number of unknown BGP Peers", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the BGP group.", title="Operational State" + ), + ] = None + + +DefaultBGPGroupDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class DefaultBGPGroupDeletedResources( + RootModel[List[DefaultBGPGroupDeletedResourceEntry]] +): + root: List[DefaultBGPGroupDeletedResourceEntry] + + +DefaultBGPGroupMetadata = AggregateRouteMetadata + + +DefaultBGPPeerSpecAsPathOptionsRemovePrivateAS = ( + BGPGroupSpecAsPathOptionsRemovePrivateAS +) + + +class DefaultBGPPeerSpecAsPathOptions(BaseModel): + """ + AS Path Options + """ + + allowOwnAS: Annotated[ + int, + Field( + description="The maximum number of times the global AS number or a local AS number of the BGP instance can appear in any received AS_PATH before it is considered a loop and considered invalid.", + ge=0, + le=255, + title="Allow Own AS", + ), + ] + removePrivateAS: Annotated[ + Optional[DefaultBGPPeerSpecAsPathOptionsRemovePrivateAS], + Field( + description="Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers.", + title="Remove Private AS", + ), + ] = None + + +DefaultBGPPeerSpecIpv4UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultBGPPeerSpecIpv4UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultBGPPeerSpecIpv4UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[DefaultBGPPeerSpecIpv4UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[DefaultBGPPeerSpecIpv4UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultBGPPeerSpecIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultBGPPeerSpecIpv4UnicastPrefixLimit], Field(title="Prefix Limit") + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +DefaultBGPPeerSpecIpv6UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultBGPPeerSpecIpv6UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultBGPPeerSpecIpv6UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[DefaultBGPPeerSpecIpv6UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[DefaultBGPPeerSpecIpv6UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultBGPPeerSpecIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultBGPPeerSpecIpv6UnicastPrefixLimit], Field(title="Prefix Limit") + ] = None + + +DefaultBGPPeerSpecL2VPNEVPNPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultBGPPeerSpecL2VPNEVPNPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultBGPPeerSpecL2VPNEVPNPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[DefaultBGPPeerSpecL2VPNEVPNPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[DefaultBGPPeerSpecL2VPNEVPNPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultBGPPeerSpecL2VPNEVPN(BaseModel): + """ + Parameters relating to the EVPN AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of EVPN routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the L2VPN EVPN AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultBGPPeerSpecL2VPNEVPNPrefixLimit], Field(title="Prefix Limit") + ] = None + + +DefaultBGPPeerSpecLocalAS = BGPGroupSpecLocalAS + + +DefaultBGPPeerSpecPeerAS = BGPGroupSpecPeerAS + + +DefaultBGPPeerSpecSendDefaultRoute = BGPGroupSpecSendDefaultRoute + + +DefaultBGPPeerSpecTimers = BGPGroupSpecTimers + + +class DefaultBGPPeerSpec(BaseModel): + """ + DefaultBGPPeer enables the configuration of BGP sessions within a DefaultRouter. It allows specifying a description, a DefaultInterface reference, and the peer IP address. The resource also supports dynamic neighbors, common BGP settings, and peer-specific configurations. + """ + + asPathOptions: Annotated[ + Optional[DefaultBGPPeerSpecAsPathOptions], + Field(description="AS Path Options", title="AS Path Options"), + ] = None + bfd: Annotated[ + Optional[bool], + Field( + description="Enable or disable Bi-forward Forwarding Detection (BFD) with fast failover.", + title="BFD", + ), + ] = None + client: Annotated[ + Optional[bool], + Field( + description="When set to true, all configured and dynamic BGP peers are considered RR clients.", + title="Route Reflector Client", + ), + ] = None + clusterID: Annotated[ + Optional[str], + Field( + description="Enables route reflect client and sets the cluster ID.", + title="Cluster ID", + ), + ] = None + description: Annotated[ + Optional[str], + Field(description="Sets the description on the BGP peer.", title="Description"), + ] = None + dynamicNeighbor: Annotated[ + Optional[bool], + Field( + description="When set to true the DefaultInterface is added to the dynamic-neighbor list for dynamic peering.", + title="Dynamic Neighbor", + ), + ] = False + dynamicNeighborAllowedPeerAS: Annotated[ + Optional[List[int]], + Field( + description="The autonomous system numbers allowed from peers if dynamic peering is enabled.", + title="Dynamic Neighbor Allowed Peer AS", + ), + ] = None + exportPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes advertised to peers.", + title="Export Policy", + ), + ] = None + grStaleRouteTime: Annotated[ + Optional[int], + Field( + description="Enables Graceful Restart on the peer and sets the stale route time.", + ge=1, + le=3600, + title="GR Stale Route Time", + ), + ] = None + group: Annotated[ + str, Field(description="Reference to a DefaultBGPGroup.", title="Group") + ] + importPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes received from peers.", + title="Import Policy", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to either a DefaultInterface or SystemInterface whose IP will be used as a source IP for the BGP session.", + title="Interface", + ), + ] + interfaceKind: Annotated[ + Literal["DEFAULTINTERFACE", "SYSTEMINTERFACE"], + Field( + description="Reference to a the Kind of interface whose IP will be used as a source IP for the BGP session.", + title="Interface Kind", + ), + ] + ipv4Unicast: Annotated[ + Optional[DefaultBGPPeerSpecIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[DefaultBGPPeerSpecIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field( + description="Reference to a Keychain resource that will be used for authentication with the BGP peer.", + title="Keychain", + ), + ] = None + l2VPNEVPN: Annotated[ + Optional[DefaultBGPPeerSpecL2VPNEVPN], + Field( + description="Parameters relating to the EVPN AFI/SAFI.", title="L2VPN EVPN" + ), + ] = None + localAS: Annotated[ + Optional[DefaultBGPPeerSpecLocalAS], + Field( + description="The local autonomous system number advertised to peers.", + title="Local AS", + ), + ] = None + localPreference: Annotated[ + Optional[int], + Field( + description="Local Preference attribute added to received routes from the BGP peers, also sets local preference for generated routes.", + ge=0, + le=4294967295, + title="Local Preference", + ), + ] = None + multiHopMaxHop: Annotated[ + Optional[int], + Field( + description="Enable multihop for eBGP peers and sets the maximum number of hops allowed.", + ge=1, + le=255, + title="Multihop Max Hop Count", + ), + ] = None + nextHopSelf: Annotated[ + Optional[bool], + Field( + description="When set to true, the next-hop in all IPv4-unicast, IPv6-unicast and EVPN BGP routes advertised to the peer is set to the local-address.", + title="Next Hop Self", + ), + ] = None + peerAS: Annotated[ + Optional[DefaultBGPPeerSpecPeerAS], + Field( + description="The autonomous system number expected from peers.", + title="Peer AS", + ), + ] = None + peerIP: Annotated[ + Optional[str], + Field( + description="Peer IP to which the peering session will be established. There cannot be both a PeerIp and PeerDefaultInterface property set.", + title="Peer IP", + ), + ] = None + peerInterface: Annotated[ + Optional[str], + Field( + description="Reference to a DefaultInterface or SystemInterface resource to which the peering session will be established. There cannot be both a PeerIp and PeerDefaultInterface property set.", + title="Peer DefaultInterface", + ), + ] = None + peerInterfaceKind: Annotated[ + Optional[Literal["DEFAULTINTERFACE", "SYSTEMINTERFACE"]], + Field( + description="Reference to a the Kind of interface to which to peer to.", + title="Peer DefaultInterface Kind", + ), + ] = None + sendCommunityLarge: Annotated[ + Optional[bool], + Field( + description="When false, all large (12 byte) BGP communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Large", + ), + ] = None + sendCommunityStandard: Annotated[ + Optional[bool], + Field( + description="When false, all standard (4 byte) communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Standard", + ), + ] = None + sendDefaultRoute: Annotated[ + Optional[DefaultBGPPeerSpecSendDefaultRoute], + Field( + description="Options for controlling the generation of default routes towards BGP peers.", + title="Send Default Route", + ), + ] = None + timers: Annotated[ + Optional[DefaultBGPPeerSpecTimers], + Field(description="Timer configurations", title="Timers"), + ] = None + + +class DefaultBGPPeerStatus(BaseModel): + """ + DefaultBGPPeerStatus defines the observed state of DefaultBGPPeer + """ + + enabled: Annotated[ + Optional[bool], + Field( + description="Indicated whether the BGP Peer is administratively enabled.", + title="Enabled", + ), + ] = None + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the BGP peer.", title="Health" + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + lastEvent: Annotated[ + Optional[str], + Field(description="Last event of the BGP peer.", title="Last Event"), + ] = None + lastState: Annotated[ + Optional[str], + Field(description="Last state of the BGP peer.", title="Last State"), + ] = None + negotiatedHoldTime: Annotated[ + Optional[int], + Field( + description="Hold time negotiated with the BGP peer.", + title="Negotiated Hold Time", + ), + ] = None + negotiatedKeepaliveInterval: Annotated[ + Optional[int], + Field( + description="Keepalive interval negotiated with the BGP peer.", + title="Negotiated Keepalive Interval", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the BGP peer", title="Operational State" + ), + ] = None + peerAS: Annotated[ + Optional[int], Field(description="Peer AS of the BGP peer.", title="Peer AS") + ] = None + sessionState: Annotated[ + Optional[str], + Field(description="The state of the BGP session.", title="Session State"), + ] = None + underMaintenance: Annotated[ + Optional[bool], + Field( + description="Indicates if the BGP peer is under maintenance.", + title="Under Maintenance", + ), + ] = None + + +DefaultBGPPeerDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class DefaultBGPPeerDeletedResources( + RootModel[List[DefaultBGPPeerDeletedResourceEntry]] +): + root: List[DefaultBGPPeerDeletedResourceEntry] + + +DefaultBGPPeerMetadata = AggregateRouteMetadata + + +DefaultRouteReflectorSpecAsPathOptionsRemovePrivateAS = ( + BGPGroupSpecAsPathOptionsRemovePrivateAS +) + + +class DefaultRouteReflectorSpecAsPathOptions(BaseModel): + """ + AS Path Options + """ + + allowOwnAS: Annotated[ + int, + Field( + description="The maximum number of times the global AS number or a local AS number of the BGP instance can appear in any received AS_PATH before it is considered a loop and considered invalid.", + ge=0, + le=255, + title="Allow Own AS", + ), + ] + removePrivateAS: Annotated[ + Optional[DefaultRouteReflectorSpecAsPathOptionsRemovePrivateAS], + Field( + description="Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers.", + title="Remove Private AS", + ), + ] = None + + +DefaultRouteReflectorSpecIpv4UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultRouteReflectorSpecIpv4UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultRouteReflectorSpecIpv4UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[DefaultRouteReflectorSpecIpv4UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[DefaultRouteReflectorSpecIpv4UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultRouteReflectorSpecIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultRouteReflectorSpecIpv4UnicastPrefixLimit], + Field(title="Prefix Limit"), + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +DefaultRouteReflectorSpecIpv6UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultRouteReflectorSpecIpv6UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultRouteReflectorSpecIpv6UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[DefaultRouteReflectorSpecIpv6UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[DefaultRouteReflectorSpecIpv6UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultRouteReflectorSpecIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultRouteReflectorSpecIpv6UnicastPrefixLimit], + Field(title="Prefix Limit"), + ] = None + + +DefaultRouteReflectorSpecL2VPNEVPNPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultRouteReflectorSpecL2VPNEVPNPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultRouteReflectorSpecL2VPNEVPNPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[DefaultRouteReflectorSpecL2VPNEVPNPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[DefaultRouteReflectorSpecL2VPNEVPNPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultRouteReflectorSpecL2VPNEVPN(BaseModel): + """ + Parameters relating to the EVPN AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of EVPN routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the L2VPN EVPN AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultRouteReflectorSpecL2VPNEVPNPrefixLimit], + Field(title="Prefix Limit"), + ] = None + + +DefaultRouteReflectorSpecLocalAS = BGPGroupSpecLocalAS + + +DefaultRouteReflectorSpecPeerAS = BGPGroupSpecPeerAS + + +DefaultRouteReflectorSpecSendDefaultRoute = BGPGroupSpecSendDefaultRoute + + +DefaultRouteReflectorSpecTimers = BGPGroupSpecTimers + + +class DefaultRouteReflectorSpec(BaseModel): + """ + DefaultRouteReflector enables the configuration of iBGP sessions to RouteReflectorClients. It includes settings for the DefaultInterface, BGP group, client selectors, and the Cluster ID. Additionally, it allows for the configuration of L2VPN EVPN settings and applies common BGP configuration settings to manage routing efficiently within the network. + """ + + asPathOptions: Annotated[ + Optional[DefaultRouteReflectorSpecAsPathOptions], + Field(description="AS Path Options", title="AS Path Options"), + ] = None + bfd: Annotated[ + Optional[bool], + Field( + description="Enable or disable Bi-forward Forwarding Detection (BFD) with fast failover.", + title="BFD", + ), + ] = None + clientIPs: Annotated[ + Optional[List[str]], + Field( + description="List of RR client IPs to which the iBGP sessions are established.", + title="Client IPs", + ), + ] = None + clientSelector: Annotated[ + Optional[List[str]], + Field( + description="Label selector used to select the RouteReflectorClients to which the iBGP sessions are established.", + title="Client Selector", + ), + ] = None + clusterID: Annotated[ + str, + Field( + description="Sets the cluster ID for route reflectors.", title="Cluster ID" + ), + ] + defaultBGPRRGroup: Annotated[ + str, + Field( + description="Reference to a DefaultBGPGroup.", title="Default BGP RR Group" + ), + ] + exportPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes advertised to peers.", + title="Export Policy", + ), + ] = None + grStaleRouteTime: Annotated[ + Optional[int], + Field( + description="Enables Graceful Restart on the peer and sets the stale route time.", + ge=1, + le=3600, + title="GR Stale Route Time", + ), + ] = None + importPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes received from peers.", + title="Import Policy", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to either a DefaultInterface or SystemInterface from which the session to the client will be done from.", + title="Interface Reference", + ), + ] + interfaceKind: Annotated[ + Literal["DEFAULTINTERFACE", "SYSTEMINTERFACE"], + Field( + description="Reference to a the Kind of interface from which the session to the client will be done from.", + title="Interface Kind", + ), + ] + ipv4Unicast: Annotated[ + Optional[DefaultRouteReflectorSpecIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[DefaultRouteReflectorSpecIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field( + description="Reference to a Keychain resource that will be used for authentication with the BGP peer.", + title="Keychain", + ), + ] = None + l2VPNEVPN: Annotated[ + Optional[DefaultRouteReflectorSpecL2VPNEVPN], + Field( + description="Parameters relating to the EVPN AFI/SAFI.", title="L2VPN EVPN" + ), + ] = None + localAS: Annotated[ + Optional[DefaultRouteReflectorSpecLocalAS], + Field( + description="The local autonomous system number advertised to peers.", + title="Local AS", + ), + ] = None + peerAS: Annotated[ + Optional[DefaultRouteReflectorSpecPeerAS], + Field( + description="The autonomous system number expected from peers.", + title="Peer AS", + ), + ] = None + sendCommunityLarge: Annotated[ + Optional[bool], + Field( + description="When false, all large (12 byte) BGP communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Large", + ), + ] = None + sendCommunityStandard: Annotated[ + Optional[bool], + Field( + description="When false, all standard (4 byte) communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Standard", + ), + ] = None + sendDefaultRoute: Annotated[ + Optional[DefaultRouteReflectorSpecSendDefaultRoute], + Field( + description="Options for controlling the generation of default routes towards BGP peers.", + title="Send Default Route", + ), + ] = None + timers: Annotated[ + Optional[DefaultRouteReflectorSpecTimers], + Field(description="Timer configurations", title="Timers"), + ] = None + + +class DefaultRouteReflectorStatus(BaseModel): + """ + DefaultRouteReflectorStatus defines the observed state of DefaultRouteReflector + """ + + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the Route Reflector.", + title="Health", + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + numRouteReflectorBGPPeers: Annotated[ + Optional[int], + Field( + description="Total number of configured route reflector client peers on the route reflector.", + title="Number of Route Reflector BGP Peers", + ), + ] = None + numRouteReflectorBGPPeersOperDown: Annotated[ + Optional[int], + Field( + description="Total number of configured route reflector client peers on the route reflector that are operationally down.", + title="Number of Oper Down Route Reflector BGP Peers", + ), + ] = None + operDownRouteReflectorPeers: Annotated[ + Optional[List[str]], + Field( + description="List of route reflector BGPPeers which are operationally down.", + title="Oper Down Route Reflector Peers", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the Route Reflector.", + title="Operational State", + ), + ] = None + + +DefaultRouteReflectorClientSpecAsPathOptionsRemovePrivateAS = ( + BGPGroupSpecAsPathOptionsRemovePrivateAS +) + + +class DefaultRouteReflectorClientSpecAsPathOptions(BaseModel): + """ + AS Path Options + """ + + allowOwnAS: Annotated[ + int, + Field( + description="The maximum number of times the global AS number or a local AS number of the BGP instance can appear in any received AS_PATH before it is considered a loop and considered invalid.", + ge=0, + le=255, + title="Allow Own AS", + ), + ] + removePrivateAS: Annotated[ + Optional[DefaultRouteReflectorClientSpecAsPathOptionsRemovePrivateAS], + Field( + description="Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers.", + title="Remove Private AS", + ), + ] = None + + +DefaultRouteReflectorClientSpecIpv4UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultRouteReflectorClientSpecIpv4UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultRouteReflectorClientSpecIpv4UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[ + DefaultRouteReflectorClientSpecIpv4UnicastPrefixLimitPrefixLimitAccepted + ], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[ + DefaultRouteReflectorClientSpecIpv4UnicastPrefixLimitPrefixLimitReceived + ], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultRouteReflectorClientSpecIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultRouteReflectorClientSpecIpv4UnicastPrefixLimit], + Field(title="Prefix Limit"), + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +DefaultRouteReflectorClientSpecIpv6UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultRouteReflectorClientSpecIpv6UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultRouteReflectorClientSpecIpv6UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[ + DefaultRouteReflectorClientSpecIpv6UnicastPrefixLimitPrefixLimitAccepted + ], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[ + DefaultRouteReflectorClientSpecIpv6UnicastPrefixLimitPrefixLimitReceived + ], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultRouteReflectorClientSpecIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultRouteReflectorClientSpecIpv6UnicastPrefixLimit], + Field(title="Prefix Limit"), + ] = None + + +DefaultRouteReflectorClientSpecL2VPNEVPNPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +DefaultRouteReflectorClientSpecL2VPNEVPNPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class DefaultRouteReflectorClientSpecL2VPNEVPNPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[ + DefaultRouteReflectorClientSpecL2VPNEVPNPrefixLimitPrefixLimitAccepted + ], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[ + DefaultRouteReflectorClientSpecL2VPNEVPNPrefixLimitPrefixLimitReceived + ], + Field(title="Prefix Limit Received"), + ] = None + + +class DefaultRouteReflectorClientSpecL2VPNEVPN(BaseModel): + """ + Parameters relating to the EVPN AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of EVPN routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the L2VPN EVPN AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[DefaultRouteReflectorClientSpecL2VPNEVPNPrefixLimit], + Field(title="Prefix Limit"), + ] = None + + +DefaultRouteReflectorClientSpecLocalAS = BGPGroupSpecLocalAS + + +DefaultRouteReflectorClientSpecPeerAS = BGPGroupSpecPeerAS + + +DefaultRouteReflectorClientSpecSendDefaultRoute = BGPGroupSpecSendDefaultRoute + + +DefaultRouteReflectorClientSpecTimers = BGPGroupSpecTimers + + +class DefaultRouteReflectorClientSpec(BaseModel): + """ + DefaultRouteReflectorClient enables the configuration of iBGP sessions from a client to RouteReflectors. It includes settings for the DefaultInterface, BGP group, client selectors, and a list of Route Reflector IPs. Additionally, it allows for the configuration of L2VPN EVPN settings and applies common BGP configuration settings to manage routing efficiently within the network. + """ + + asPathOptions: Annotated[ + Optional[DefaultRouteReflectorClientSpecAsPathOptions], + Field(description="AS Path Options", title="AS Path Options"), + ] = None + bfd: Annotated[ + Optional[bool], + Field( + description="Enable or disable Bi-forward Forwarding Detection (BFD) with fast failover.", + title="BFD", + ), + ] = None + defaultBgpClientGroup: Annotated[ + str, + Field( + description="Reference to Default Bgp Group.", + title="Default BGP Client Group", + ), + ] + exportPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes advertised to peers.", + title="Export Policy", + ), + ] = None + grStaleRouteTime: Annotated[ + Optional[int], + Field( + description="Enables Graceful Restart on the peer and sets the stale route time.", + ge=1, + le=3600, + title="GR Stale Route Time", + ), + ] = None + importPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes received from peers.", + title="Import Policy", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to either a DefaultInterface or SystemInterface from which the session to the RR will be done from.", + title="Interface", + ), + ] + interfaceKind: Annotated[ + Literal["DEFAULTINTERFACE", "SYSTEMINTERFACE"], + Field( + description="Reference to a the Kind of interface from which the session to the RR will be done from.", + title="Interface Kind", + ), + ] + ipv4Unicast: Annotated[ + Optional[DefaultRouteReflectorClientSpecIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[DefaultRouteReflectorClientSpecIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field( + description="Reference to a Keychain resource that will be used for authentication with the BGP peer.", + title="Keychain", + ), + ] = None + l2VPNEVPN: Annotated[ + Optional[DefaultRouteReflectorClientSpecL2VPNEVPN], + Field( + description="Parameters relating to the EVPN AFI/SAFI.", title="L2VPN EVPN" + ), + ] = None + localAS: Annotated[ + Optional[DefaultRouteReflectorClientSpecLocalAS], + Field( + description="The local autonomous system number advertised to peers.", + title="Local AS", + ), + ] = None + peerAS: Annotated[ + Optional[DefaultRouteReflectorClientSpecPeerAS], + Field( + description="The autonomous system number expected from peers.", + title="Peer AS", + ), + ] = None + routeReflectorIPs: Annotated[ + Optional[List[str]], + Field( + description="List of the peering IPs on the RRs to which peering session is established.", + title="Route Reflector IPs", + ), + ] = None + routeReflectorSelector: Annotated[ + Optional[List[str]], + Field( + description="Label selector used to select the RouteReflectors to which the iBGP sessions are established.", + title="Route Reflector Selector", + ), + ] = None + sendCommunityLarge: Annotated[ + Optional[bool], + Field( + description="When false, all large (12 byte) BGP communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Large", + ), + ] = None + sendCommunityStandard: Annotated[ + Optional[bool], + Field( + description="When false, all standard (4 byte) communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Standard", + ), + ] = None + sendDefaultRoute: Annotated[ + Optional[DefaultRouteReflectorClientSpecSendDefaultRoute], + Field( + description="Options for controlling the generation of default routes towards BGP peers.", + title="Send Default Route", + ), + ] = None + timers: Annotated[ + Optional[DefaultRouteReflectorClientSpecTimers], + Field(description="Timer configurations", title="Timers"), + ] = None + + +class DefaultRouteReflectorClientStatus(BaseModel): + """ + DefaultRouteReflectorClientStatus defines the observed state of DefaultRouteReflectorClient + """ + + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the DefaultRouteReflectorClient.", + title="Health", + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + numRouteReflectorClientBGPPeers: Annotated[ + Optional[int], + Field( + description="Total number of configured route reflector peers on the route reflector client.", + title="Number of Route Reflector Client BGP Peers", + ), + ] = None + numRouteReflectorClientBGPPeersOperDown: Annotated[ + Optional[int], + Field( + description="Total number of configured route reflector peers on the route reflector client that are operationally down.", + title="Number of Oper Down Route Reflector Client BGP Peers", + ), + ] = None + operDownRouteReflectorClientPeers: Annotated[ + Optional[List[str]], + Field( + description="List of route reflector BGPPeers which are operationally down.", + title="Oper Down Route Reflector Client Peers", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the DefaultRouteReflectorClient.", + title="Operational State", + ), + ] = None + + +DefaultRouteReflectorClientDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class DefaultRouteReflectorClientDeletedResources( + RootModel[List[DefaultRouteReflectorClientDeletedResourceEntry]] +): + root: List[DefaultRouteReflectorClientDeletedResourceEntry] + + +DefaultRouteReflectorClientMetadata = AggregateRouteMetadata + + +DefaultRouteReflectorDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class DefaultRouteReflectorDeletedResources( + RootModel[List[DefaultRouteReflectorDeletedResourceEntry]] +): + root: List[DefaultRouteReflectorDeletedResourceEntry] + + +DefaultRouteReflectorMetadata = AggregateRouteMetadata + + +class DefaultStaticRouteSpecNexthopGroupBfd(BaseModel): + """ + Enables BFD to the next-hops in the group. Local and Remote discriminator parameters have been deprecated at this level. Use Nexthop to set these parameters. + """ + + enabled: Annotated[ + Optional[bool], + Field( + description="Defines whether BFD should be enabled towards the nexthops.", + title="Enabled", + ), + ] = False + localAddress: Annotated[ + Optional[str], + Field( + description="Defines the local address to use when establishing the BFD session with the nexthop.", + title="Local Address", + ), + ] = None + + +class DefaultStaticRouteSpecNexthopGroupNexthopBfd(BaseModel): + """ + Enables BFD to the next-hops in the group. This overrides the configuration at the group. + """ + + enabled: Annotated[ + Optional[bool], + Field( + description="Defines whether BFD should be enabled towards the nexthops.", + title="Enabled", + ), + ] = False + localAddress: Annotated[ + Optional[str], + Field( + description="Defines the local address to use when establishing the BFD session with the nexthop.", + title="Local Address", + ), + ] = None + localDiscriminator: Annotated[ + Optional[int], + Field( + description="Defines the local discriminator.", title="Local Discriminator" + ), + ] = None + remoteDiscriminator: Annotated[ + Optional[int], + Field( + description="Defines the remote discriminator.", + title="Remote Discriminator", + ), + ] = None + + +class DefaultStaticRouteSpecNexthopGroupNexthop(BaseModel): + bfd: Annotated[ + Optional[DefaultStaticRouteSpecNexthopGroupNexthopBfd], + Field( + description="Enables BFD to the next-hops in the group. This overrides the configuration at the group.", + title="BFD", + ), + ] = None + ipPrefix: Annotated[str, Field(description="Address to use.", title="IP Prefix")] + resolve: Annotated[ + Optional[bool], + Field( + description="If set to true the next-hops can be destinations which are resolved in the route table. This overrides the configuration at the group.", + title="Resolve", + ), + ] = False + + +class DefaultStaticRouteSpecNexthopGroup(BaseModel): + """ + Group of nexthops for the list of prefixes. + """ + + bfd: Annotated[ + Optional[DefaultStaticRouteSpecNexthopGroupBfd], + Field( + description="Enables BFD to the next-hops in the group. Local and Remote discriminator parameters have been deprecated at this level. Use Nexthop to set these parameters.", + title="BFD", + ), + ] = None + blackhole: Annotated[ + Optional[bool], + Field( + description="If set to true all traffic destined to the prefixes will be blackholed. If enabled, next-hops are ignored and this takes precedence.", + title="Blackhole", + ), + ] = False + blackholeSendICMP: Annotated[ + Optional[bool], + Field( + description="When enabled, the router will generate ICMP Unreachable messages for packets destined to the blackhole route.", + title="Blackhole ICMP Generation", + ), + ] = None + nexthops: Annotated[ + Optional[List[DefaultStaticRouteSpecNexthopGroupNexthop]], + Field(description="Ordered list of nexthops.", title="Nexthops"), + ] = None + resolve: Annotated[ + Optional[bool], + Field( + description="If set to true the next-hops can be destinations which are resolved in the route table.", + title="Resolve", + ), + ] = False + + +class DefaultStaticRouteSpec(BaseModel): + """ + DefaultStaticRoute enables the configuration of static routes within a DefaultRouter. It allows specifying destination prefixes, route preference, and a nexthop group. This resource facilitates precise control over routing behavior, including options for BFD, route resolution, and blackholing traffic. + """ + + defaultRouter: Annotated[ + str, + Field( + description="Reference to a DefaultRouter on which to configure the static routes.", + title="Default Router", + ), + ] + nexthopGroup: Annotated[ + DefaultStaticRouteSpecNexthopGroup, + Field( + description="Group of nexthops for the list of prefixes.", + title="Nexthop Group", + ), + ] + preference: Annotated[ + Optional[int], + Field(description="Defines the route preference.", title="Preference"), + ] = None + prefixes: Annotated[ + List[str], + Field( + description="List of destination prefixes and mask to use for the static routes.", + title="Prefixes", + ), + ] + + +class DefaultStaticRouteStatus(BaseModel): + """ + DefaultStaticRouteStatus defines the observed state of default static route + """ + + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the static routes.", + title="Health", + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the static routes.", + title="Operational State", + ), + ] = None + + +DefaultStaticRouteDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class DefaultStaticRouteDeletedResources( + RootModel[List[DefaultStaticRouteDeletedResourceEntry]] +): + root: List[DefaultStaticRouteDeletedResourceEntry] + + +DefaultStaticRouteMetadata = AggregateRouteMetadata + + +RouteReflectorSpecAsPathOptionsRemovePrivateAS = ( + BGPGroupSpecAsPathOptionsRemovePrivateAS +) + + +class RouteReflectorSpecAsPathOptions(BaseModel): + """ + AS Path Options + """ + + allowOwnAS: Annotated[ + int, + Field( + description="The maximum number of times the global AS number or a local AS number of the BGP instance can appear in any received AS_PATH before it is considered a loop and considered invalid.", + ge=0, + le=255, + title="Allow Own AS", + ), + ] + removePrivateAS: Annotated[ + Optional[RouteReflectorSpecAsPathOptionsRemovePrivateAS], + Field( + description="Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers.", + title="Remove Private AS", + ), + ] = None + + +RouteReflectorSpecIpv4UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +RouteReflectorSpecIpv4UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class RouteReflectorSpecIpv4UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[RouteReflectorSpecIpv4UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[RouteReflectorSpecIpv4UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class RouteReflectorSpecIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[RouteReflectorSpecIpv4UnicastPrefixLimit], Field(title="Prefix Limit") + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +RouteReflectorSpecIpv6UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +RouteReflectorSpecIpv6UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class RouteReflectorSpecIpv6UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[RouteReflectorSpecIpv6UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[RouteReflectorSpecIpv6UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class RouteReflectorSpecIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[RouteReflectorSpecIpv6UnicastPrefixLimit], Field(title="Prefix Limit") + ] = None + + +RouteReflectorSpecLocalAS = BGPGroupSpecLocalAS + + +RouteReflectorSpecPeerAS = BGPGroupSpecPeerAS + + +RouteReflectorSpecSendDefaultRoute = BGPGroupSpecSendDefaultRoute + + +RouteReflectorSpecTimers = BGPGroupSpecTimers + + +class RouteReflectorSpec(BaseModel): + """ + RouteReflector enables the configuration of iBGP sessions with RouteReflectorClients. It includes settings for selecting Interfaces, client selectors for IPv4 and IPv6, and the option to specify a BGP group and cluster ID. + """ + + asPathOptions: Annotated[ + Optional[RouteReflectorSpecAsPathOptions], + Field(description="AS Path Options", title="AS Path Options"), + ] = None + bfd: Annotated[ + Optional[bool], + Field( + description="Enable or disable Bi-forward Forwarding Detection (BFD) with fast failover.", + title="BFD", + ), + ] = None + bgpGroup: Annotated[ + str, Field(description="Reference to BgpGroup", title="BGP Group") + ] + clientIPs: Annotated[ + Optional[List[str]], + Field( + description="List of RR client IPs to which the iBGP sessions are established.", + title="Client IPs", + ), + ] = None + clusterID: Annotated[ + str, + Field( + description="Sets the cluster ID for route reflectors.", title="Cluster ID" + ), + ] + exportPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes advertised to peers.", + title="Export Policy", + ), + ] = None + grStaleRouteTime: Annotated[ + Optional[int], + Field( + description="Enables Graceful Restart on the peer and sets the stale route time.", + ge=1, + le=3600, + title="GR Stale Route Time", + ), + ] = None + importPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes received from peers.", + title="Import Policy", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to a RoutedInterface or IrbInterface resource whose IP will be used as a source IP for the BGP session.", + title="Interface Reference", + ), + ] + interfaceKind: Annotated[ + Literal["ROUTEDINTERFACE", "IRBINTERFACE"], + Field( + description="InterfaceReference type defines whether the provided Reference is a RoutedInterface or IrbInterface.", + title="Interface Reference Type", + ), + ] + ipv4ClientSelector: Annotated[ + Optional[List[str]], + Field( + description="Label selector used to select the RouteReflectorClients to which the iBGP sessions are established for IPv4.", + title="IPv4 Client Selector", + ), + ] = None + ipv4Unicast: Annotated[ + Optional[RouteReflectorSpecIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6ClientSelector: Annotated[ + Optional[List[str]], + Field( + description="Label selector used to select the RouteReflectorClients to which the iBGP sessions are established for IPv6.", + title="IPv6 Client Selector", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[RouteReflectorSpecIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field( + description="Reference to a Keychain resource that will be used for authentication with the BGP peer.", + title="Keychain", + ), + ] = None + localAS: Annotated[ + Optional[RouteReflectorSpecLocalAS], + Field( + description="The local autonomous system number advertised to peers.", + title="Local AS", + ), + ] = None + peerAS: Annotated[ + Optional[RouteReflectorSpecPeerAS], + Field( + description="The autonomous system number expected from peers.", + title="Peer AS", + ), + ] = None + sendCommunityLarge: Annotated[ + Optional[bool], + Field( + description="When false, all large (12 byte) BGP communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Large", + ), + ] = None + sendCommunityStandard: Annotated[ + Optional[bool], + Field( + description="When false, all standard (4 byte) communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Standard", + ), + ] = None + sendDefaultRoute: Annotated[ + Optional[RouteReflectorSpecSendDefaultRoute], + Field( + description="Options for controlling the generation of default routes towards BGP peers.", + title="Send Default Route", + ), + ] = None + timers: Annotated[ + Optional[RouteReflectorSpecTimers], + Field(description="Timer configurations", title="Timers"), + ] = None + + +class RouteReflectorStatus(BaseModel): + """ + RouteReflectorStatus defines the observed state of RouteReflector + """ + + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the RouteReflector.", + title="Health", + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + numRouteReflectorBGPPeers: Annotated[ + Optional[int], + Field( + description="Total number of configured route reflector client peers on the route reflector.", + title="Number of Route Reflector BGP Peers", + ), + ] = None + numRouteReflectorBGPPeersOperDown: Annotated[ + Optional[int], + Field( + description="Total number of configured route reflector client peers on the route reflector that are operationally down.", + title="Number of Oper Down Route Reflector BGP Peers", + ), + ] = None + operDownRouteReflectorPeers: Annotated[ + Optional[List[str]], + Field( + description="List of route reflector BGPPeers which are operationally down.", + title="Oper Down Route Reflector Peers", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the RouteReflector.", + title="Operational State", + ), + ] = None + + +RouteReflectorClientSpecAsPathOptionsRemovePrivateAS = ( + BGPGroupSpecAsPathOptionsRemovePrivateAS +) + + +class RouteReflectorClientSpecAsPathOptions(BaseModel): + """ + AS Path Options + """ + + allowOwnAS: Annotated[ + int, + Field( + description="The maximum number of times the global AS number or a local AS number of the BGP instance can appear in any received AS_PATH before it is considered a loop and considered invalid.", + ge=0, + le=255, + title="Allow Own AS", + ), + ] + removePrivateAS: Annotated[ + Optional[RouteReflectorClientSpecAsPathOptionsRemovePrivateAS], + Field( + description="Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers.", + title="Remove Private AS", + ), + ] = None + + +RouteReflectorClientSpecIpv4UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +RouteReflectorClientSpecIpv4UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class RouteReflectorClientSpecIpv4UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[RouteReflectorClientSpecIpv4UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[RouteReflectorClientSpecIpv4UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class RouteReflectorClientSpecIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[RouteReflectorClientSpecIpv4UnicastPrefixLimit], + Field(title="Prefix Limit"), + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +RouteReflectorClientSpecIpv6UnicastPrefixLimitPrefixLimitAccepted = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +RouteReflectorClientSpecIpv6UnicastPrefixLimitPrefixLimitReceived = ( + BGPGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class RouteReflectorClientSpecIpv6UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[RouteReflectorClientSpecIpv6UnicastPrefixLimitPrefixLimitAccepted], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[RouteReflectorClientSpecIpv6UnicastPrefixLimitPrefixLimitReceived], + Field(title="Prefix Limit Received"), + ] = None + + +class RouteReflectorClientSpecIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[RouteReflectorClientSpecIpv6UnicastPrefixLimit], + Field(title="Prefix Limit"), + ] = None + + +RouteReflectorClientSpecLocalAS = BGPGroupSpecLocalAS + + +RouteReflectorClientSpecPeerAS = BGPGroupSpecPeerAS + + +RouteReflectorClientSpecSendDefaultRoute = BGPGroupSpecSendDefaultRoute + + +RouteReflectorClientSpecTimers = BGPGroupSpecTimers + + +class RouteReflectorClientSpec(BaseModel): + """ + RouteReflectorClient manages the configuration of iBGP sessions between a client and RouteReflectors. This resource allows you to specify the Interface for BGP sessions, set selectors for RouteReflectors, and configure common BGP settings. + """ + + asPathOptions: Annotated[ + Optional[RouteReflectorClientSpecAsPathOptions], + Field(description="AS Path Options", title="AS Path Options"), + ] = None + bfd: Annotated[ + Optional[bool], + Field( + description="Enable or disable Bi-forward Forwarding Detection (BFD) with fast failover.", + title="BFD", + ), + ] = None + bgpGroup: Annotated[ + str, Field(description="Reference to BgpGroup.", title="BGP Group") + ] + exportPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes advertised to peers.", + title="Export Policy", + ), + ] = None + grStaleRouteTime: Annotated[ + Optional[int], + Field( + description="Enables Graceful Restart on the peer and sets the stale route time.", + ge=1, + le=3600, + title="GR Stale Route Time", + ), + ] = None + importPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes received from peers.", + title="Import Policy", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to a RoutedInterface or IrbInterface resource whose IP will be used as a source IP for the BGP session.", + title="Interface Reference", + ), + ] + interfaceKind: Annotated[ + Literal["ROUTEDINTERFACE", "IRBINTERFACE"], + Field( + description="InterfaceReference type defines whether the provided Reference is a RoutedInterface or IrbInterface.", + title="Interface Reference Type", + ), + ] + ipv4RouteReflectorSelector: Annotated[ + Optional[List[str]], + Field( + description="Label selector used to select the RouteReflectors to which the iBGP sessions are established for IPv4.", + title="IPv4 Route Reflector Selector", + ), + ] = None + ipv4Unicast: Annotated[ + Optional[RouteReflectorClientSpecIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6RouteReflectorSelector: Annotated[ + Optional[List[str]], + Field( + description="Label selector used to select the RouteReflectors to which the iBGP sessions are established for IPv6.", + title="IPv6 Route Reflector Selector", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[RouteReflectorClientSpecIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field( + description="Reference to a Keychain resource that will be used for authentication with the BGP peer.", + title="Keychain", + ), + ] = None + localAS: Annotated[ + Optional[RouteReflectorClientSpecLocalAS], + Field( + description="The local autonomous system number advertised to peers.", + title="Local AS", + ), + ] = None + peerAS: Annotated[ + Optional[RouteReflectorClientSpecPeerAS], + Field( + description="The autonomous system number expected from peers.", + title="Peer AS", + ), + ] = None + routeReflectorIPs: Annotated[ + Optional[List[str]], + Field( + description="List of the peering IPs on the RRs to which peering session is established.", + title="Route Reflector IPs", + ), + ] = None + sendCommunityLarge: Annotated[ + Optional[bool], + Field( + description="When false, all large (12 byte) BGP communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Large", + ), + ] = None + sendCommunityStandard: Annotated[ + Optional[bool], + Field( + description="When false, all standard (4 byte) communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Standard", + ), + ] = None + sendDefaultRoute: Annotated[ + Optional[RouteReflectorClientSpecSendDefaultRoute], + Field( + description="Options for controlling the generation of default routes towards BGP peers.", + title="Send Default Route", + ), + ] = None + timers: Annotated[ + Optional[RouteReflectorClientSpecTimers], + Field(description="Timer configurations", title="Timers"), + ] = None + + +class RouteReflectorClientStatus(BaseModel): + """ + RouteReflectorClientStatus defines the observed state of RouteReflectorClient + """ + + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the RouteReflectorClient.", + title="Health", + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + numRouteReflectorClientBGPPeers: Annotated[ + Optional[int], + Field( + description="Total number of configured route reflector peers on the route reflector client.", + title="Number of Route Reflector Client BGP Peers", + ), + ] = None + numRouteReflectorClientBGPPeersOperDown: Annotated[ + Optional[int], + Field( + description="Total number of configured route reflector peers on the route reflector client that are operationally down.", + title="Number of Oper Down Route Reflector Client BGP Peers", + ), + ] = None + operDownRouteReflectorClientPeers: Annotated[ + Optional[List[str]], + Field( + description="List of route reflector BGPPeers which are operationally down.", + title="Oper Down Route Reflector Client Peers", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the RouteReflectorClient.", + title="Operational State", + ), + ] = None + + +class RouteReflectorClientStateSpec(BaseModel): + """ + RouteReflectorClientStateSpec defines the desired state of RouteReflectorClientState + """ + + defaultRouteReflectorClient: Annotated[ + Optional[bool], + Field( + description="Denotes if the route reflector client is a DefaultRouteReflectorClient or RouteReflectorClient" + ), + ] = None + routeReflectorClientBGPPeers: Annotated[ + Optional[List[str]], + Field( + description="A list of BGPPeers configured on the route reflector client to peer with route reflectors" + ), + ] = None + + +RouteReflectorClientStateDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class RouteReflectorClientStateDeletedResources( + RootModel[List[RouteReflectorClientStateDeletedResourceEntry]] +): + root: List[RouteReflectorClientStateDeletedResourceEntry] + + +RouteReflectorClientStateMetadata = AggregateRouteMetadata + + +RouteReflectorClientDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class RouteReflectorClientDeletedResources( + RootModel[List[RouteReflectorClientDeletedResourceEntry]] +): + root: List[RouteReflectorClientDeletedResourceEntry] + + +RouteReflectorClientMetadata = AggregateRouteMetadata + + +class RouteReflectorStateSpec(BaseModel): + """ + RouteReflectorStateSpec defines the desired state of RouteReflectorState + """ + + defaultRouteReflector: Annotated[ + Optional[bool], + Field( + description="Denotes if the route reflector is a DefaultRouteReflector or RouteReflector" + ), + ] = None + routeReflectorBGPPeers: Annotated[ + Optional[List[str]], + Field( + description="A list of BGPPeers configured on the route reflector to peer with clients" + ), + ] = None + + +RouteReflectorStateDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class RouteReflectorStateDeletedResources( + RootModel[List[RouteReflectorStateDeletedResourceEntry]] +): + root: List[RouteReflectorStateDeletedResourceEntry] + + +RouteReflectorStateMetadata = AggregateRouteMetadata + + +RouteReflectorDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class RouteReflectorDeletedResources( + RootModel[List[RouteReflectorDeletedResourceEntry]] +): + root: List[RouteReflectorDeletedResourceEntry] + + +RouteReflectorMetadata = AggregateRouteMetadata + + +StaticRouteSpecNexthopGroupBfd = DefaultStaticRouteSpecNexthopGroupBfd + + +StaticRouteSpecNexthopGroupNexthopBfd = DefaultStaticRouteSpecNexthopGroupNexthopBfd + + +class StaticRouteSpecNexthopGroupNexthop(BaseModel): + bfd: Annotated[ + Optional[StaticRouteSpecNexthopGroupNexthopBfd], + Field( + description="Enables BFD to the next-hops in the group. This overrides the configuration at the group.", + title="BFD", + ), + ] = None + ipPrefix: Annotated[str, Field(description="Address to use.", title="IP Prefix")] + resolve: Annotated[ + Optional[bool], + Field( + description="If set to true the next-hops can be destinations which are resolved in the route table. This overrides the configuration at the group.", + title="Resolve", + ), + ] = False + + +class StaticRouteSpecNexthopGroup(BaseModel): + """ + Group of nexthops for the list of prefixes. + """ + + bfd: Annotated[ + Optional[StaticRouteSpecNexthopGroupBfd], + Field( + description="Enables BFD to the next-hops in the group. Local and Remote discriminator parameters have been deprecated at this level. Use Nexthop to set these parameters.", + title="BFD", + ), + ] = None + blackhole: Annotated[ + Optional[bool], + Field( + description="If set to true all traffic destined to the prefixes will be blackholed. If enabled, next-hops are ignored and this takes precedence.", + title="Blackhole", + ), + ] = False + blackholeSendICMP: Annotated[ + Optional[bool], + Field( + description="When enabled, the router will generate ICMP Unreachable messages for packets destined to the blackhole route.", + title="Blackhole ICMP Generation", + ), + ] = None + nexthops: Annotated[ + Optional[List[StaticRouteSpecNexthopGroupNexthop]], + Field(description="Ordered list of nexthops.", title="Nexthops"), + ] = None + resolve: Annotated[ + Optional[bool], + Field( + description="If set to true the next-hops can be destinations which are resolved in the route table.", + title="Resolve", + ), + ] = False + + +class StaticRouteSpec(BaseModel): + """ + StaticRoute allows for the specification of destination prefixes, route preferences, and the associated Router. It also supports configuring nexthop groups and specifying the nodes where the static routes should be provisioned. + """ + + nexthopGroup: Annotated[ + StaticRouteSpecNexthopGroup, + Field( + description="Group of nexthops for the list of prefixes.", + title="Nexthop Group", + ), + ] + nodes: Annotated[ + Optional[List[str]], + Field( + description="List of nodes on which to configure the static routes. An AND operation is executed against the nodes in this list and the nodes on which the Router is configured to determine the Nodes on which to configure the static routes.", + title="Nodes", + ), + ] = None + preference: Annotated[ + Optional[int], + Field(description="Defines the route preference.", title="Preference"), + ] = None + prefixes: Annotated[ + List[str], + Field( + description="List of destination prefixes and mask to use for the static routes.", + title="Prefixes", + ), + ] + router: Annotated[ + str, + Field( + description="Reference to a Router on which to configure the static routes. If no Nodes are provided then the static routes will be provisioned on all Nodes on which the Router is provisioned.", + title="Router", + ), + ] + + +class StaticRouteStatus(BaseModel): + """ + StaticRouteStatus defines the observed state of Static Route + """ + + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the static routes.", + title="Health", + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + nodes: Annotated[ + Optional[List[str]], + Field( + description="List of Nodes on which the static routes are configured.", + title="Nodes", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the static routes.", + title="Operational State", + ), + ] = None + + +StaticRouteDeletedResourceEntry = AggregateRouteDeletedResourceEntry + + +class StaticRouteDeletedResources(RootModel[List[StaticRouteDeletedResourceEntry]]): + root: List[StaticRouteDeletedResourceEntry] + + +StaticRouteMetadata = AggregateRouteMetadata + + +class AppGroup(BaseModel): + apiVersion: Optional[str] = None + kind: Optional[str] = None + name: Optional[str] = None + preferredVersion: Optional[AppGroupVersion] = None + versions: Optional[List[AppGroupVersion]] = None + + +class ResourceHistory(RootModel[List[ResourceHistoryEntry]]): + root: List[ResourceHistoryEntry] + + +class Status(BaseModel): + apiVersion: Optional[str] = None + details: Optional[StatusDetails] = None + kind: Optional[str] = None + string: Optional[str] = None + + +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class WorkflowInputData(RootModel[List[WorkflowInputDataElem]]): + root: List[WorkflowInputDataElem] + + +class AggregateRoute(BaseModel): + """ + AggregateRoute is the Schema for the aggregateroutes API + """ + + apiVersion: str + kind: str + metadata: AggregateRouteMetadata + spec: Annotated[ + AggregateRouteSpec, + Field( + description="The AggregateRoute enables the configuration of aggregated routes on a specified Router. This resource allows for the definition of destination prefixes, the selection of a router, and optionally, specific nodes where the aggregate routes should be configured. Advanced options include the ability to generate ICMP unreachable messages for packets matching the aggregate route, and the ability to block the advertisement of all contributing routes in dynamic protocols like BGP.", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="AggregateRouteStatus defines the observed state of AggregateRoute", + title="Status", + ), + ] = None + + +class AggregateRouteList(BaseModel): + """ + AggregateRouteList is a list of aggregateroutes + """ + + apiVersion: str + items: Optional[List[AggregateRoute]] = None + kind: str + + +class BGPGroup(BaseModel): + """ + BGPGroup is the Schema for the bgpgroups API + """ + + apiVersion: str + kind: str + metadata: BGPGroupMetadata + spec: Annotated[ + BGPGroupSpec, + Field( + description="The BGPGroup enables centralized management of BGP peer configurations. This resource allows setting a description, common BGP settings, and peer-specific configurations, simplifying the consistent application of policies across multiple peers. It also includes transport settings, such as local TCP address configuration, passive mode, and TCP MSS.", + title="Specification", + ), + ] + status: Annotated[ + Optional[BGPGroupStatus], + Field( + description="BGPGroupStatus defines the observed state of BGPGroup", + title="Status", + ), + ] = None + + +class BGPGroupList(BaseModel): + """ + BGPGroupList is a list of bgpgroups + """ + + apiVersion: str + items: Optional[List[BGPGroup]] = None + kind: str + + +class BGPPeer(BaseModel): + """ + BGPPeer is the Schema for the bgppeers API + """ + + apiVersion: str + kind: str + metadata: BGPPeerMetadata + spec: Annotated[ + BGPPeerSpec, + Field( + description="BGPPeer enables the configuration of BGP sessions. It allows specifying a description, an interface reference (either RoutedInterface or IrbInterface), and the peer IP address. The resource also supports dynamic neighbors, common BGP settings, and peer-specific configurations.", + title="Specification", + ), + ] + status: Annotated[ + Optional[BGPPeerStatus], + Field( + description="BGPPeerStatus defines the observed state of BGPPeer", + title="Status", + ), + ] = None + + +class BGPPeerList(BaseModel): + """ + BGPPeerList is a list of bgppeers + """ + + apiVersion: str + items: Optional[List[BGPPeer]] = None + kind: str + + +class BGPPeerState(BaseModel): + """ + BGPPeerState is the Schema for the bgppeerstates API + """ + + apiVersion: str + kind: str + metadata: BGPPeerStateMetadata + spec: Annotated[ + BGPPeerStateSpec, + Field( + description="BGPPeerStateSpec defines the desired state of BGPPeerState", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="BGPPeerStateStatus defines the observed state of BGPPeerState", + title="Status", + ), + ] = None + + +class BGPPeerStateList(BaseModel): + """ + BGPPeerStateList is a list of bgppeerstates + """ + + apiVersion: str + items: Optional[List[BGPPeerState]] = None + kind: str + + +class CheckDefaultBgpPeers(BaseModel): + """ + CheckDefaultBgpPeers is the Schema for the checkdefaultbgppeerss API + """ + + apiVersion: str + kind: str + metadata: CheckDefaultBgpPeersMetadata + spec: Annotated[ + CheckDefaultBgpPeersSpec, + Field( + description="CheckDefaultBgpPeersSpec defines the desired state of CheckDefaultBgpPeers", + title="Specification", + ), + ] + status: Annotated[ + Optional[CheckDefaultBgpPeersStatus], + Field( + description="CheckDefaultBgpPeersStatus defines the observed state of CheckDefaultBgpPeers", + title="Status", + ), + ] = None + + +class CheckDefaultBgpPeersList(BaseModel): + """ + CheckDefaultBgpPeersList is a list of checkdefaultbgppeerss + """ + + apiVersion: str + items: Optional[List[CheckDefaultBgpPeers]] = None + kind: str + + +class DefaultAggregateRoute(BaseModel): + """ + DefaultAggregateRoute is the Schema for the defaultaggregateroutes API + """ + + apiVersion: str + kind: str + metadata: DefaultAggregateRouteMetadata + spec: Annotated[ + DefaultAggregateRouteSpec, + Field( + description="DefaultAggregateRoute allows the configuration of aggregate routes on a DefaultRouter. It includes specifying destination prefixes, the DefaultRouter, and settings for generating ICMP unreachable messages or blocking route advertisement. Additionally, it configures the aggregator’s IP address and ASN for efficient route management.", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="DefaultAggregateRouteStatus defines the observed state of DefaultAggregateRoute", + title="Status", + ), + ] = None + + +class DefaultAggregateRouteList(BaseModel): + """ + DefaultAggregateRouteList is a list of defaultaggregateroutes + """ + + apiVersion: str + items: Optional[List[DefaultAggregateRoute]] = None + kind: str + + +class DefaultBGPGroup(BaseModel): + """ + DefaultBGPGroup is the Schema for the defaultbgpgroups API + """ + + apiVersion: str + kind: str + metadata: DefaultBGPGroupMetadata + spec: Annotated[ + DefaultBGPGroupSpec, + Field( + description="The DefaultBGPGroup enables centralized management of BGP peer configurations within a DefaultRouter. This resource allows setting a description, common BGP settings, and peer-specific configurations, simplifying the consistent application of policies across multiple peers. It also includes transport settings, such as local TCP address configuration, passive mode, and TCP MSS. type DefaultBGPGroupSpec struct {", + title="Specification", + ), + ] + status: Annotated[ + Optional[DefaultBGPGroupStatus], + Field( + description="DefaultBGPGroupStatus defines the observed state of DefaultBGPGroup.", + title="Status", + ), + ] = None + + +class DefaultBGPGroupList(BaseModel): + """ + DefaultBGPGroupList is a list of defaultbgpgroups + """ + + apiVersion: str + items: Optional[List[DefaultBGPGroup]] = None + kind: str + + +class DefaultBGPPeer(BaseModel): + """ + DefaultBGPPeer is the Schema for the defaultbgppeers API + """ + + apiVersion: str + kind: str + metadata: DefaultBGPPeerMetadata + spec: Annotated[ + DefaultBGPPeerSpec, + Field( + description="DefaultBGPPeer enables the configuration of BGP sessions within a DefaultRouter. It allows specifying a description, a DefaultInterface reference, and the peer IP address. The resource also supports dynamic neighbors, common BGP settings, and peer-specific configurations.", + title="Specification", + ), + ] + status: Annotated[ + Optional[DefaultBGPPeerStatus], + Field( + description="DefaultBGPPeerStatus defines the observed state of DefaultBGPPeer", + title="Status", + ), + ] = None + + +class DefaultBGPPeerList(BaseModel): + """ + DefaultBGPPeerList is a list of defaultbgppeers + """ + + apiVersion: str + items: Optional[List[DefaultBGPPeer]] = None + kind: str + + +class DefaultRouteReflector(BaseModel): + """ + DefaultRouteReflector is the Schema for the defaultroutereflectors API + """ + + apiVersion: str + kind: str + metadata: DefaultRouteReflectorMetadata + spec: Annotated[ + DefaultRouteReflectorSpec, + Field( + description="DefaultRouteReflector enables the configuration of iBGP sessions to RouteReflectorClients. It includes settings for the DefaultInterface, BGP group, client selectors, and the Cluster ID. Additionally, it allows for the configuration of L2VPN EVPN settings and applies common BGP configuration settings to manage routing efficiently within the network.", + title="Specification", + ), + ] + status: Annotated[ + Optional[DefaultRouteReflectorStatus], + Field( + description="DefaultRouteReflectorStatus defines the observed state of DefaultRouteReflector", + title="Status", + ), + ] = None + + +class DefaultRouteReflectorClient(BaseModel): + """ + DefaultRouteReflectorClient is the Schema for the defaultroutereflectorclients API + """ + + apiVersion: str + kind: str + metadata: DefaultRouteReflectorClientMetadata + spec: Annotated[ + DefaultRouteReflectorClientSpec, + Field( + description="DefaultRouteReflectorClient enables the configuration of iBGP sessions from a client to RouteReflectors. It includes settings for the DefaultInterface, BGP group, client selectors, and a list of Route Reflector IPs. Additionally, it allows for the configuration of L2VPN EVPN settings and applies common BGP configuration settings to manage routing efficiently within the network.", + title="Specification", + ), + ] + status: Annotated[ + Optional[DefaultRouteReflectorClientStatus], + Field( + description="DefaultRouteReflectorClientStatus defines the observed state of DefaultRouteReflectorClient", + title="Status", + ), + ] = None + + +class DefaultRouteReflectorClientList(BaseModel): + """ + DefaultRouteReflectorClientList is a list of defaultroutereflectorclients + """ + + apiVersion: str + items: Optional[List[DefaultRouteReflectorClient]] = None + kind: str + + +class DefaultRouteReflectorList(BaseModel): + """ + DefaultRouteReflectorList is a list of defaultroutereflectors + """ + + apiVersion: str + items: Optional[List[DefaultRouteReflector]] = None + kind: str + + +class DefaultStaticRoute(BaseModel): + """ + DefaultStaticRoute is the Schema for the defaultstaticroutes API + """ + + apiVersion: str + kind: str + metadata: DefaultStaticRouteMetadata + spec: Annotated[ + DefaultStaticRouteSpec, + Field( + description="DefaultStaticRoute enables the configuration of static routes within a DefaultRouter. It allows specifying destination prefixes, route preference, and a nexthop group. This resource facilitates precise control over routing behavior, including options for BFD, route resolution, and blackholing traffic.", + title="Specification", + ), + ] + status: Annotated[ + Optional[DefaultStaticRouteStatus], + Field( + description="DefaultStaticRouteStatus defines the observed state of default static route", + title="Status", + ), + ] = None + + +class DefaultStaticRouteList(BaseModel): + """ + DefaultStaticRouteList is a list of defaultstaticroutes + """ + + apiVersion: str + items: Optional[List[DefaultStaticRoute]] = None + kind: str + + +class RouteReflector(BaseModel): + """ + RouteReflector is the Schema for the routereflectors API + """ + + apiVersion: str + kind: str + metadata: RouteReflectorMetadata + spec: Annotated[ + RouteReflectorSpec, + Field( + description="RouteReflector enables the configuration of iBGP sessions with RouteReflectorClients. It includes settings for selecting Interfaces, client selectors for IPv4 and IPv6, and the option to specify a BGP group and cluster ID.", + title="Specification", + ), + ] + status: Annotated[ + Optional[RouteReflectorStatus], + Field( + description="RouteReflectorStatus defines the observed state of RouteReflector", + title="Status", + ), + ] = None + + +class RouteReflectorClient(BaseModel): + """ + RouteReflectorClient is the Schema for the routereflectorclients API + """ + + apiVersion: str + kind: str + metadata: RouteReflectorClientMetadata + spec: Annotated[ + RouteReflectorClientSpec, + Field( + description="RouteReflectorClient manages the configuration of iBGP sessions between a client and RouteReflectors. This resource allows you to specify the Interface for BGP sessions, set selectors for RouteReflectors, and configure common BGP settings.", + title="Specification", + ), + ] + status: Annotated[ + Optional[RouteReflectorClientStatus], + Field( + description="RouteReflectorClientStatus defines the observed state of RouteReflectorClient", + title="Status", + ), + ] = None + + +class RouteReflectorClientList(BaseModel): + """ + RouteReflectorClientList is a list of routereflectorclients + """ + + apiVersion: str + items: Optional[List[RouteReflectorClient]] = None + kind: str + + +class RouteReflectorClientState(BaseModel): + """ + RouteReflectorClientState is the Schema for the routereflectorclientstates API + """ + + apiVersion: str + kind: str + metadata: RouteReflectorClientStateMetadata + spec: Annotated[ + RouteReflectorClientStateSpec, + Field( + description="RouteReflectorClientStateSpec defines the desired state of RouteReflectorClientState", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="RouteReflectorClientStateStatus defines the observed state of RouteReflectorClientState", + title="Status", + ), + ] = None + + +class RouteReflectorClientStateList(BaseModel): + """ + RouteReflectorClientStateList is a list of routereflectorclientstates + """ + + apiVersion: str + items: Optional[List[RouteReflectorClientState]] = None + kind: str + + +class RouteReflectorList(BaseModel): + """ + RouteReflectorList is a list of routereflectors + """ + + apiVersion: str + items: Optional[List[RouteReflector]] = None + kind: str + + +class RouteReflectorState(BaseModel): + """ + RouteReflectorState is the Schema for the routereflectorstates API + """ + + apiVersion: str + kind: str + metadata: RouteReflectorStateMetadata + spec: Annotated[ + RouteReflectorStateSpec, + Field( + description="RouteReflectorStateSpec defines the desired state of RouteReflectorState", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="RouteReflectorStateStatus defines the observed state of RouteReflectorState", + title="Status", + ), + ] = None + + +class RouteReflectorStateList(BaseModel): + """ + RouteReflectorStateList is a list of routereflectorstates + """ + + apiVersion: str + items: Optional[List[RouteReflectorState]] = None + kind: str + + +class StaticRoute(BaseModel): + """ + StaticRoute is the Schema for the staticroutes API + """ + + apiVersion: str + kind: str + metadata: StaticRouteMetadata + spec: Annotated[ + StaticRouteSpec, + Field( + description="StaticRoute allows for the specification of destination prefixes, route preferences, and the associated Router. It also supports configuring nexthop groups and specifying the nodes where the static routes should be provisioned.", + title="Specification", + ), + ] + status: Annotated[ + Optional[StaticRouteStatus], + Field( + description="StaticRouteStatus defines the observed state of Static Route", + title="Status", + ), + ] = None + + +class StaticRouteList(BaseModel): + """ + StaticRouteList is a list of staticroutes + """ + + apiVersion: str + items: Optional[List[StaticRoute]] = None + kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/protocols/v1alpha1/models.py b/pydantic_eda/apps/protocols/v1alpha1/models.py index 183fc49..cd9aadc 100644 --- a/pydantic_eda/apps/protocols/v1alpha1/models.py +++ b/pydantic_eda/apps/protocols/v1alpha1/models.py @@ -2,9 +2,11 @@ # filename: protocols.json from __future__ import annotations -from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel + from datetime import date +from typing import Annotated, Any, Dict, List, Literal, Optional + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -38,6 +40,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +100,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,10 +119,56 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + class AggregateRouteSpec(BaseModel): """ The AggregateRoute enables the configuration of aggregated routes on a specified Router. This resource allows for the definition of destination prefixes, the selection of a router, and optionally, specific nodes where the aggregate routes should be configured. Advanced options include the ability to generate ICMP unreachable messages for packets matching the aggregate route, and the ability to block the advertisement of all contributing routes in dynamic protocols like BGP. @@ -168,7 +222,7 @@ class AggregateRouteSpec(BaseModel): class AggregateRouteDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -1002,6 +1056,30 @@ class BGPPeerDeletedResources(RootModel[List[BGPPeerDeletedResourceEntry]]): BGPPeerMetadata = AggregateRouteMetadata +class CheckDefaultBgpPeersSpec(BaseModel): + """ + CheckDefaultBgpPeersSpec defines the desired state of CheckDefaultBgpPeers + """ + + nodeSelector: Annotated[Optional[List[str]], Field(title="nodeselector")] = None + nodes: Annotated[Optional[List[str]], Field(title="nodes")] = None + waitFor: Annotated[Optional[int], Field(title="waitfor")] = None + + +class CheckDefaultBgpPeersStatus(BaseModel): + """ + CheckDefaultBgpPeersStatus defines the observed state of CheckDefaultBgpPeers + """ + + id: Annotated[Optional[int], Field(description="Id", title="ID")] = None + result: Annotated[ + Optional[str], Field(description="Aggregate result of the Flow", title="Result") + ] = None + + +CheckDefaultBgpPeersMetadata = AggregateRouteMetadata + + class DefaultAggregateRouteSpec(BaseModel): """ DefaultAggregateRoute allows the configuration of aggregate routes on a DefaultRouter. It includes specifying destination prefixes, the DefaultRouter, and settings for generating ICMP unreachable messages or blocking route advertisement. Additionally, it configures the aggregator’s IP address and ASN for efficient route management. @@ -2318,6 +2396,13 @@ class DefaultStaticRouteSpecNexthopGroup(BaseModel): title="Blackhole", ), ] = False + blackholeSendICMP: Annotated[ + Optional[bool], + Field( + description="When enabled, the router will generate ICMP Unreachable messages for packets destined to the blackhole route.", + title="Blackhole ICMP Generation", + ), + ] = None nexthops: Annotated[ Optional[List[DefaultStaticRouteSpecNexthopGroupNexthop]], Field(description="Ordered list of nexthops.", title="Nexthops"), @@ -3027,6 +3112,13 @@ class StaticRouteSpecNexthopGroup(BaseModel): title="Blackhole", ), ] = False + blackholeSendICMP: Annotated[ + Optional[bool], + Field( + description="When enabled, the router will generate ICMP Unreachable messages for packets destined to the blackhole route.", + title="Blackhole ICMP Generation", + ), + ] = None nexthops: Annotated[ Optional[List[StaticRouteSpecNexthopGroupNexthop]], Field(description="Ordered list of nexthops.", title="Nexthops"), @@ -3150,6 +3242,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class AggregateRoute(BaseModel): """ AggregateRoute is the Schema for the aggregateroutes API @@ -3286,6 +3443,30 @@ class BGPPeerStateList(BaseModel): kind: str +class CheckDefaultBgpPeers(BaseModel): + """ + CheckDefaultBgpPeers is the Schema for the checkdefaultbgppeerss API + """ + + apiVersion: str + kind: str + metadata: CheckDefaultBgpPeersMetadata + spec: Annotated[ + CheckDefaultBgpPeersSpec, + Field( + description="CheckDefaultBgpPeersSpec defines the desired state of CheckDefaultBgpPeers", + title="Specification", + ), + ] + status: Annotated[ + Optional[CheckDefaultBgpPeersStatus], + Field( + description="CheckDefaultBgpPeersStatus defines the observed state of CheckDefaultBgpPeers", + title="Status", + ), + ] = None + + class DefaultAggregateRoute(BaseModel): """ DefaultAggregateRoute is the Schema for the defaultaggregateroutes API @@ -3658,3 +3839,13 @@ class StaticRouteList(BaseModel): apiVersion: str items: Optional[List[StaticRoute]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/qos/v1/models.py b/pydantic_eda/apps/qos/v1/models.py new file mode 100644 index 0000000..84e5e60 --- /dev/null +++ b/pydantic_eda/apps/qos/v1/models.py @@ -0,0 +1,1968 @@ +# generated by datamodel-codegen: +# filename: qos.json + +from __future__ import annotations + +from typing import Annotated, Any, Dict, List, Literal, Optional + +from pydantic import AwareDatetime, BaseModel, Field, RootModel + + +class AppGroupVersion(BaseModel): + groupVersion: Optional[str] = None + version: Optional[str] = None + + +class ErrorIndex(BaseModel): + index: Optional[int] = None + + +class ErrorItem(BaseModel): + error: Optional[Dict[str, Any]] = None + type: Optional[str] = None + + +class ErrorResponse(BaseModel): + """ + Generic error response for REST APIs + """ + + code: Annotated[ + int, Field(description="the numeric HTTP error code for the response.") + ] + details: Annotated[ + Optional[str], Field(description="The optional details of the error response.") + ] = None + dictionary: Annotated[ + Optional[Dict[str, Any]], + Field( + description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' + ), + ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None + errors: Annotated[ + Optional[List[ErrorItem]], + Field( + description="Collection of errors in cases where more than one exists. This needs to be\nflexible so we can support multiple formats" + ), + ] = None + index: Optional[ErrorIndex] = None + internal: Annotated[ + Optional[int], + Field( + description="Internal error code in cases where we don't have an array of errors" + ), + ] = None + message: Annotated[ + str, Field(description="The basic text error message for the error response.") + ] + ref: Annotated[ + Optional[str], + Field( + description="Reference to the error source. Should typically be the URI of the request" + ), + ] = None + type: Annotated[ + Optional[str], + Field( + description="URI pointing at a document that describes the error and mitigation steps\nIf there is no document, point to the RFC for the HTTP error code" + ), + ] = None + + +class K8SPatchOp(BaseModel): + from_: Annotated[Optional[str], Field(alias="from")] = None + op: str + path: str + value: Optional[Dict[str, Any]] = None + x_permissive: Annotated[Optional[bool], Field(alias="x-permissive")] = None + + +class Patch(RootModel[List[K8SPatchOp]]): + root: List[K8SPatchOp] + + +class Resource(BaseModel): + kind: Optional[str] = None + name: Optional[str] = None + namespaced: Optional[bool] = None + readOnly: Optional[bool] = None + singularName: Optional[str] = None + uiCategory: Optional[str] = None + + +class ResourceHistoryEntry(BaseModel): + author: Optional[str] = None + changeType: Optional[str] = None + commitTime: Optional[AwareDatetime] = None + hash: Optional[str] = None + message: Optional[str] = None + transactionId: Optional[int] = None + + +class ResourceList(BaseModel): + apiVersion: Optional[str] = None + groupVersion: Optional[str] = None + kind: Optional[str] = None + resources: Optional[List[Resource]] = None + + +class StatusDetails(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + name: Optional[str] = None + + +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + +class UIResult(RootModel[str]): + root: str + + +class EgressPolicySpecDot1pRewritePolicyDot1pMapItemDropProbabilityItem(BaseModel): + level: Annotated[ + Optional[Literal["High", "Medium", "Low"]], + Field( + description="A drop probability level within the forwarding class for which a different remarking is desired", + title="Level", + ), + ] = None + pcpValue: Annotated[ + Optional[int], + Field( + description="The PCP value to be used for packets associated with the forwarding class and the specific drop probability. This overrides the general PCP value.", + ge=0, + le=7, + title="PCP Value", + ), + ] = None + + +class EgressPolicySpecDot1pRewritePolicyDot1pMapItem(BaseModel): + dropProbability: Annotated[ + Optional[ + List[EgressPolicySpecDot1pRewritePolicyDot1pMapItemDropProbabilityItem] + ], + Field( + description="Drop probability specific overrides within the forwarding class", + title="Drop Probability", + ), + ] = None + forwardingClasses: Annotated[ + List[str], + Field( + description="The forwarding class matched to apply the rewrite policy", + title="Forwarding Class", + ), + ] + pcpValue: Annotated[ + Optional[int], + Field( + description="The PCP value to be used for all packets associated with the forwarding class, except those with a drop-probability-specific or profile-specific override", + ge=0, + le=7, + title="PCP Value", + ), + ] = None + + +class EgressPolicySpecDot1pRewritePolicy(BaseModel): + """ + Dot1pRewritePolicy enables the configuration of rewrite policies for Dot1p values. It includes mappings of forwarding classes to Dot1p values, with options for drop probability-specific overrides within each forwarding class. + """ + + dot1pMap: Annotated[ + List[EgressPolicySpecDot1pRewritePolicyDot1pMapItem], + Field(description="Map of forwarding classes to PCP values", title="Map"), + ] + + +class EgressPolicySpecDscpRewritePolicyDscpMapItemDropProbabilityItem(BaseModel): + dscp: Annotated[ + Optional[int], + Field( + description="The DSCP value to be used for packets associated with the forwarding class and the specific drop probability. This overrides the general DSCP value.", + ge=0, + le=63, + title="DSCP", + ), + ] = None + level: Annotated[ + Optional[Literal["High", "Medium", "Low"]], + Field( + description="A drop probability level within the forwarding class for which a different remarking is desired.", + title="Level", + ), + ] = None + + +class EgressPolicySpecDscpRewritePolicyDscpMapItem(BaseModel): + dropProbability: Annotated[ + Optional[List[EgressPolicySpecDscpRewritePolicyDscpMapItemDropProbabilityItem]], + Field( + description="A drop probability within the forwarding class for which a different remarking is desired.", + title="Drop Probability", + ), + ] = None + dscp: Annotated[ + Optional[int], + Field( + description="The DSCP value to be used for all packets associated with the forwarding class, except those with a drop-probability-specific or profile-specific override.", + ge=0, + le=63, + title="DSCP", + ), + ] = None + forwardingClasses: Annotated[ + List[str], + Field( + description="The forwarding class matched to apply the rewrite policy.", + title="Forwarding Class", + ), + ] + + +class EgressPolicySpecDscpRewritePolicy(BaseModel): + """ + DSCPRewritePolicy enables the configuration of rewrite policies for Differentiated Services Code Point (DSCP) values. It includes mappings of forwarding classes to DSCP values, with options for drop probability-specific overrides within each forwarding class. If a DSCPRewritePolicy is not specified, the DSCP value of the packet is unchanged. If a DSCP policy is specific and ECN is enabled on any of the queues, the DSCP policy will be applied to all ECN capable packets. + """ + + dscpMap: Annotated[ + List[EgressPolicySpecDscpRewritePolicyDscpMapItem], + Field(description="Map of forwarding classes to DSCP values.", title="Map"), + ] + + +class EgressPolicySpecForwardingClassToQueueMappingItem(BaseModel): + forwardingClasses: Annotated[ + List[str], + Field( + description="The forwarding classes to which the mapping applies, these are references to ForwardingClass resources.", + min_length=1, + title="Forwarding Classes", + ), + ] + queue: Annotated[ + str, + Field( + description="The queue to which the forwarding classes are mapped, this is a reference to a Queue resource.", + title="Queue", + ), + ] + queueGroup: Annotated[ + Optional[str], + Field( + description="The queue-group name for queue to forwarding class mapping.", + title="Queue Group", + ), + ] = None + + +class EgressPolicySpecPfcDeadlockAvoidance(BaseModel): + """ + Parameters related to avoid a deadlock related to pfc on outgoing interface. + """ + + deadlockAvoidance: Annotated[ + bool, + Field( + description="Parameters related to avoid a deadlock related to pfc on outgoing interface", + title="Deadlock Avoidance", + ), + ] + deadlockDetectionTimer: Annotated[ + int, + Field( + description="Number of milliseconds during which outgoing interface is receiving pfc-pause-frames before triggering recovery-timer.", + title="Deadlock Detection Timer", + ), + ] + deadlockRecoveryTimer: Annotated[ + int, + Field( + description="Number of milliseconds during which the pfc-pause-frames will be ignored.", + title="Deadlock Recovery Timer", + ), + ] + + +class EgressPolicySpecQueueManagementItemQueue(BaseModel): + committedBurstSize: Annotated[ + Optional[int], + Field(description="Committed Burst Size.", title="Committed Burst Size"), + ] = None + maximumBurstSize: Annotated[ + int, + Field( + description="Maximum amount of shared buffer memory available to the queue in bytes.", + ge=0, + le=4294967295, + title="Maximum Burst Size", + ), + ] + pfcPauseFramePriority: Annotated[ + Optional[int], + Field( + description="The pfc-priority received in pfc-pause-frame.", + title="PFC Priority", + ), + ] = None + queue: Annotated[ + str, Field(description="Reference to a Queue resource.", title="Queue") + ] + schedulerPeakRatePercent: Annotated[ + Optional[int], + Field( + description="The peak rate percent used by the scheduler for the queue.", + ge=1, + le=100, + title="Scheduler Peak Rate Percent", + ), + ] = None + schedulerPriorityLevel: Annotated[ + Optional[int], + Field( + description="The priority level at this Port Scheduler Policy.", + ge=1, + le=8, + title="Scheduler Priority Level", + ), + ] = None + schedulerWeight: Annotated[ + Optional[int], + Field( + description="The weight factor used for the WRR scheduler. If any of the queues have a configured weight the set of queues will use a WRR scheduler and thus all queues must have a weight configured. If no weights are set then the queues are scheduled in strict priority from lowest to higher queue ID.", + ge=0, + le=255, + title="Scheduler Weight", + ), + ] = None + + +class EgressPolicySpecQueueManagementItemWredSlopPolicy(BaseModel): + drop: Annotated[ + bool, + Field( + description="When set to true, and if the ECN field in the packet indicates that the endpoints are not ECN-capable, and the WRED algorithm determines that the packet should be dropped based on the drop probability, the packet will be dropped", + title="Drop", + ), + ] + dropProbability: Annotated[ + Literal["High", "Medium", "Low", "All"], Field(title="Drop Probability") + ] + ecn: Annotated[ + bool, + Field( + description="When set to true and the queue length is between the thresholds and the ECN field indicates ECN-capable endpoints, the CE bits are set to 1, and the packet is transmitted based on WRED. If false, such packets are discarded.", + title="ECN", + ), + ] + maxDropProbabilityPercent: Annotated[ + Optional[int], + Field( + description="If the queue depth is between min and max threshold then this the probability with which packets are dropped or marked.", + title="Max Drop Probability Percent", + ), + ] = None + maxThreshold: Annotated[ + Optional[int], + Field( + description="The maximum threshold parameter for a RED-managed queue in bytes. When the average queue length exceeds the max value, all packets are dropped (or marked if ECN is enabled). Mutually exclusive with min-threshold-percent and max-threshold-percent.", + title="Max Threshold", + ), + ] = None + maxThresholdPercent: Annotated[ + Optional[int], + Field( + description="The maximum threshold parameter for a RED-managed queue in percent. When the average queue length exceeds the max value, all packets are dropped (or marked if ECN is enabled). Mutually exclusive with min-threshold and max-threshold.", + title="Max Threshold Percent", + ), + ] = None + minThreshold: Annotated[ + Optional[int], + Field( + description="The mininum threshold parameter for a RED-managed queue in bytes. When the average queue length is less than min, all packets are admitted to the queue. Mututally exclusive with min-threshold-percent and max-threshold-percent.", + title="Min Threshold", + ), + ] = None + minThresholdPercent: Annotated[ + Optional[int], + Field( + description="The mininum threshold parameter for a RED-managed queue in percent. When the average queue length is less than min, all packets are admitted to the queue. Mutually exclusive with min-threshold and max-threshold.", + title="Min Threshold Percent", + ), + ] = None + trafficType: Annotated[ + Literal["Tcp", "NonTcp", "All"], + Field( + description="The traffic type to which the WRED slope applies.", + title="Traffic Type", + ), + ] + + +class EgressPolicySpecQueueManagementItem(BaseModel): + queues: Annotated[ + List[EgressPolicySpecQueueManagementItemQueue], + Field(description="List of queues.", title="Queues"), + ] + slopePolicyWeight: Annotated[ + Optional[int], + Field( + description="The average queue size is calculated using both the previous average and the current queue size: average = (previous average)(1 - 2^(-n)) + (current size)(2^(-n)), where n is a user-configurable weight factor. A higher n gives more importance to the previous average, smoothing peaks and lows in the queue. Lower n makes the average closer to the current queue size. If this leaf is absent, the default value is used.", + ge=0, + le=15, + title="Slope Policy Weight", + ), + ] = 0 + wredSlopPolicies: Annotated[ + Optional[List[EgressPolicySpecQueueManagementItemWredSlopPolicy]], + Field( + description="Slope policy to apply to the set of queues.", + title="Slope Policy", + ), + ] = None + + +class EgressPolicySpec(BaseModel): + """ + EgressPolicySpec defines the desired state of EgressPolicy + """ + + dot1pRewritePolicy: Annotated[ + Optional[EgressPolicySpecDot1pRewritePolicy], + Field( + description="Dot1pRewritePolicy enables the configuration of rewrite policies for Dot1p values. It includes mappings of forwarding classes to Dot1p values, with options for drop probability-specific overrides within each forwarding class.", + title="Dot1p Rewrite Policy", + ), + ] = None + dscpRewritePolicy: Annotated[ + Optional[EgressPolicySpecDscpRewritePolicy], + Field( + description="DSCPRewritePolicy enables the configuration of rewrite policies for Differentiated Services Code Point (DSCP) values. It includes mappings of forwarding classes to DSCP values, with options for drop probability-specific overrides within each forwarding class. If a DSCPRewritePolicy is not specified, the DSCP value of the packet is unchanged. If a DSCP policy is specific and ECN is enabled on any of the queues, the DSCP policy will be applied to all ECN capable packets.", + title="DSCP Rewrite Policy", + ), + ] = None + forwardingClassToQueueMapping: Annotated[ + Optional[List[EgressPolicySpecForwardingClassToQueueMappingItem]], + Field( + description="Forwarding class to queue mapping policy.", + title="Forwarding Class to Queue Mapping", + ), + ] = None + pfcDeadlockAvoidance: Annotated[ + Optional[EgressPolicySpecPfcDeadlockAvoidance], + Field( + description="Parameters related to avoid a deadlock related to pfc on outgoing interface.", + title="Deadlock Avoidance", + ), + ] = None + queueManagement: Annotated[ + Optional[List[EgressPolicySpecQueueManagementItem]], + Field( + description="Queue management policy for egress queues.", + title="Queue Management", + ), + ] = None + + +class EgressPolicyDeletedResourceEntry(BaseModel): + commitTime: Optional[AwareDatetime] = None + hash: Optional[str] = None + name: Optional[str] = None + namespace: Optional[str] = None + transactionId: Optional[int] = None + + +class EgressPolicyDeletedResources(RootModel[List[EgressPolicyDeletedResourceEntry]]): + root: List[EgressPolicyDeletedResourceEntry] + + +class EgressPolicyMetadata(BaseModel): + annotations: Optional[Dict[str, str]] = None + labels: Optional[Dict[str, str]] = None + name: Annotated[ + str, + Field( + max_length=253, + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + ), + ] + namespace: str + + +ForwardingClassDeletedResourceEntry = EgressPolicyDeletedResourceEntry + + +class ForwardingClassDeletedResources( + RootModel[List[ForwardingClassDeletedResourceEntry]] +): + root: List[ForwardingClassDeletedResourceEntry] + + +ForwardingClassMetadata = EgressPolicyMetadata + + +class IngressPolicySpecClassifierEntryDot1pPolicyEntryPcpValue(BaseModel): + rangeEnd: Annotated[ + Optional[int], + Field( + description="Optional end of PCP range (inclusive) which would start from the Value to the RangeEnd.", + ge=0, + le=7, + title="PCP Range End", + ), + ] = None + value: Annotated[ + int, + Field( + description="Single PCP value or start of range.", + ge=0, + le=7, + title="PCP Value", + ), + ] + + +class IngressPolicySpecClassifierEntryDot1pPolicyEntry(BaseModel): + """ + A Dot1p policy entry - only a single Dot1p entry is allowed per classifier resource. + """ + + directToPFCQueue: Annotated[ + Optional[bool], + Field( + description="In addition to creating a Dot1p PCP value to Forwarding Class mapping, this will map the PCP values directly to the PFC queue specified in the Forwarding Class to Queue mapping.", + title="Direct to PFC Queue", + ), + ] = None + dropProbabilityLevel: Annotated[ + Optional[Literal["High", "Medium", "Low"]], + Field( + description="Assign matching packets to the specified drop probability level.", + title="Drop Probability Level", + ), + ] = "Low" + forwardingClass: Annotated[ + Optional[str], + Field( + description="Reference to a ForwardingClass resource to which the value is mapped.", + title="Forwarding Class", + ), + ] = None + pcpValues: Annotated[ + List[IngressPolicySpecClassifierEntryDot1pPolicyEntryPcpValue], + Field( + description="List of PCP values or ranges used to match packets to classify into Forwarding Classes.", + min_length=1, + title="PCP Values", + ), + ] + + +class IngressPolicySpecClassifierEntryDscpPolicyEntryDscpValue(BaseModel): + rangeEnd: Annotated[ + Optional[int], + Field( + description="Optional end of DSCP range (inclusive) which would start from the Value to the RangeEnd.", + ge=0, + le=63, + title="DSCP Range End", + ), + ] = None + value: Annotated[ + int, + Field( + description="Single DSCP value or start of range.", + ge=0, + le=63, + title="DSCP Value", + ), + ] + + +class IngressPolicySpecClassifierEntryDscpPolicyEntry(BaseModel): + """ + A DSCP policy entry - only a single DSCP entry is allowed per classifier resource. + """ + + dropProbabilityLevel: Annotated[ + Optional[Literal["High", "Medium", "Low"]], + Field( + description="Assign matching packets to the specified drop probability level.", + title="Drop Probability Level", + ), + ] = "Low" + dscpValues: Annotated[ + List[IngressPolicySpecClassifierEntryDscpPolicyEntryDscpValue], + Field( + description="List of DSCP values or ranges used to match packets to classify into Forwarding Classes.", + min_length=1, + title="DSCP Values", + ), + ] + forwardingClass: Annotated[ + Optional[str], + Field( + description="Reference to a ForwardingClass resource to which the value is mapped.", + title="Forwarding Class", + ), + ] = None + + +class IngressPolicySpecClassifierEntryIpEntryAction(BaseModel): + """ + An action to take on the matched packets. + """ + + dropProbabilityLevel: Annotated[ + Optional[Literal["High", "Medium", "Low"]], + Field( + description="Assign matching packets to the specified drop probability level.", + title="Drop Probability Level", + ), + ] = "Low" + dscpRewriteValue: Annotated[ + Optional[int], + Field( + description="Rewrite actions associated with packets that match the classifier entry.", + ge=0, + le=63, + title="DSCP Rewrite Value", + ), + ] = None + forwardingClass: Annotated[ + Optional[str], + Field( + description="Reference to a ForwardingClass resource to which the value is mapped.", + title="Forwarding Class", + ), + ] = None + + +class IngressPolicySpecClassifierEntryIpEntry(BaseModel): + """ + An IPv4 or IPv6 multifield classifier entry. + """ + + action: Annotated[ + IngressPolicySpecClassifierEntryIpEntryAction, + Field(description="An action to take on the matched packets.", title="Action"), + ] + destinationPortName: Annotated[ + Optional[ + Literal[ + "ACAP", + "AFP-TCP", + "ARNS", + "ASF-RMCP", + "ASHARE", + "ATALK-RM", + "AURP", + "AUTH", + "BFD", + "BFD-ECHO", + "BFTP", + "BGMP", + "BGP", + "BOOTPC", + "BOOTPS", + "CCSO-NS", + "CHARGEN", + "CISCO-TDP", + "CITADEL", + "CLEARCASE", + "COMMERCE", + "COURIER", + "DAYTIME", + "DHCP-FAILOVER", + "DHCPV6-CLIENT", + "DHCPV6-SERVER", + "DICOM", + "DISCARD", + "DNSIX", + "DOMAIN", + "DSP", + "ECHO", + "EPP", + "ESRO", + "EXEC", + "FINGER", + "FTP", + "FTP-DATA", + "FTPS", + "FTPS-DATA", + "GODI", + "GOPHER", + "GTP-C", + "GTP-PRIME", + "GTP-U", + "HA-CLUSTER", + "HOSTNAME", + "HP-ALARM-MGR", + "HTTP", + "HTTP-ALT", + "HTTP-MGMT", + "HTTP-RPC", + "HTTPS", + "IEEE-MMS-SSL", + "IMAP", + "IMAP3", + "IMAPS", + "IPP", + "IPSEC", + "IPX", + "IRC", + "IRIS-BEEP", + "ISAKMP", + "ISAKMP-NAT", + "ISCSI", + "ISO-TSAP", + "KERBEROS", + "KERBEROS-ADM", + "KLOGIN", + "KPASSWD", + "KSHELL", + "L2TP", + "LDAP", + "LDAPS", + "LDP", + "LMP", + "LOGIN", + "LPD", + "LSP-PING", + "MAC-SERVER-ADM", + "MATIP-A", + "MATIP-B", + "MICRO-BFD", + "MICROSOFT-DS", + "MOBILE-IP", + "MONITOR", + "MPP", + "MS-EXCHANGE", + "MSDP", + "MSP", + "MSSQL-M", + "MSSQL-S", + "MULTIHOP-BFD", + "NAS", + "NCP", + "NETBIOS-DATA", + "NETBIOS-NS", + "NETBIOS-SS", + "NETNEWS", + "NETRJS-1", + "NETRJS-2", + "NETRJS-3", + "NETRJS-4", + "NETWALL", + "NEW-RWHO", + "NFS", + "NNTP", + "NNTPS", + "NTP", + "ODMR", + "OLSR", + "OPENVPN", + "PIM-AUTO-RP", + "PKIX-TIMESTAMP", + "POP2", + "POP3", + "POP3S", + "PPTP", + "PRINT-SRV", + "PTP-EVENT", + "PTP-GENERAL", + "QMTP", + "QOTD", + "RADIUS", + "RADIUS-ACCT", + "REMOTE-MAIL", + "REMOTEFS", + "REMOTECMD", + "RIP", + "RJE", + "RLP", + "RLZDB", + "RMC", + "RMONITOR", + "RPC2PORTMAP", + "RSYNC", + "RTELNET", + "RTSP", + "SGMP", + "SILC", + "SMUX", + "SNA-GW", + "SNMP", + "SNMP-TRAP", + "SNPP", + "SMTP", + "SQL-SVCS", + "SQL", + "SSH", + "SUBMISSION", + "SUNRPC", + "SVCLOC", + "SYSLOG", + "SYSTAT", + "TACACS", + "TALK", + "TCPMUX", + "TCPNETHASPSRV", + "TFTP", + "TIME", + "TIMED", + "UPS", + "XDMCP", + "XNS-CH", + "XNS-MAIL", + "XNS-TIME", + "Z3950", + ] + ], + Field( + description="Destination port to match by name.", + title="Destination Port Name", + ), + ] = None + destinationPortNumber: Annotated[ + Optional[int], + Field( + description="Destination port to match by numerical value.", + ge=0, + le=65535, + title="Destination Port Number", + ), + ] = None + destinationPortOperator: Annotated[ + Optional[Literal["Equals", "GreaterOrEquals", "LessOrEquals"]], + Field( + description="Operator to use when matching destinationPort, either Equals, GreaterOrEquals, or LessOrEquals.", + title="Destination Port Operator", + ), + ] = None + destinationPortRange: Annotated[ + Optional[str], + Field( + description="Range of destination ports to match, in the format n-m, e.g. 100-200, The start and end of the range must be port numbers.", + title="Destination Port Range", + ), + ] = None + destinationPrefix: Annotated[ + Optional[str], + Field(description="Destination prefix to match.", title="Destination Prefix"), + ] = None + firstFragment: Annotated[ + Optional[bool], + Field(description="Match the first fragment only.", title="First Fragment"), + ] = None + fragment: Annotated[ + Optional[bool], Field(description="Match any fragment.", title="Fragment") + ] = None + icmpCode: Annotated[ + Optional[List[int]], + Field( + description="Match a specific ICMP code, as a number between 0-255, e.g. 0.", + max_length=255, + min_length=0, + title="ICMP Code", + ), + ] = None + icmpTypeName: Annotated[ + Optional[ + Literal[ + "DestUnreachable", + "Echo", + "EchoReply", + "EchoRequest", + "McastRtrAdv", + "McastRtrSolicit", + "McastRtrTerm", + "MldDone", + "MldQuery", + "MldReport", + "MldV2", + "NeighborAdvertise", + "NeighborSolicit", + "NodeInfoQuery", + "NodeInfoResponse", + "PacketTooBig", + "ParamProblem", + "Redirect", + "RouterAdvertise", + "RouterRenumber", + "RouterSolicit", + "SourceQuench", + "TimeExceeded", + "Timestamp", + "TimestampReply", + ] + ], + Field( + description="Match a specific ICMP type by name, e.g. dest-unreachable.", + title="ICMP Type Name", + ), + ] = None + icmpTypeNumber: Annotated[ + Optional[int], + Field( + description="Match a specific ICMP type by number.", + ge=0, + le=255, + title="ICMP Type Number", + ), + ] = None + protocolName: Annotated[ + Optional[ + Literal[ + "AH", + "EGP", + "EIGRP", + "ESP", + "GGP", + "GRE", + "ICMP", + "ICMP6", + "IDRP", + "IGMP", + "IGP", + "IPV4", + "IPV6", + "IPV6-DEST-OPTS", + "IPV6-HOP", + "L2TP", + "MPLS-IN-IP", + "NO-NEXT-HDR", + "OSPF", + "PIM", + "ROHC", + "RSVP", + "SCTP", + "ST", + "TCP", + "UDP", + "VRRP", + ] + ], + Field( + description="Match a specific IP protocol name (specified in the type field of the IP header).", + title="Protocol Name", + ), + ] = None + protocolNumber: Annotated[ + Optional[int], + Field( + description="Match a specific IP protocol number (specified in the type field of the IP header).", + ge=0, + le=255, + title="Protocol Number", + ), + ] = None + sourcePortName: Annotated[ + Optional[ + Literal[ + "ACAP", + "AFP-TCP", + "ARNS", + "ASF-RMCP", + "ASHARE", + "ATALK-RM", + "AURP", + "AUTH", + "BFD", + "BFD-ECHO", + "BFTP", + "BGMP", + "BGP", + "BOOTPC", + "BOOTPS", + "CCSO-NS", + "CHARGEN", + "CISCO-TDP", + "CITADEL", + "CLEARCASE", + "COMMERCE", + "COURIER", + "DAYTIME", + "DHCP-FAILOVER", + "DHCPV6-CLIENT", + "DHCPV6-SERVER", + "DICOM", + "DISCARD", + "DNSIX", + "DOMAIN", + "DSP", + "ECHO", + "EPP", + "ESRO", + "EXEC", + "FINGER", + "FTP", + "FTP-DATA", + "FTPS", + "FTPS-DATA", + "GODI", + "GOPHER", + "GTP-C", + "GTP-PRIME", + "GTP-U", + "HA-CLUSTER", + "HOSTNAME", + "HP-ALARM-MGR", + "HTTP", + "HTTP-ALT", + "HTTP-MGMT", + "HTTP-RPC", + "HTTPS", + "IEEE-MMS-SSL", + "IMAP", + "IMAP3", + "IMAPS", + "IPP", + "IPSEC", + "IPX", + "IRC", + "IRIS-BEEP", + "ISAKMP", + "ISAKMP-NAT", + "ISCSI", + "ISO-TSAP", + "KERBEROS", + "KERBEROS-ADM", + "KLOGIN", + "KPASSWD", + "KSHELL", + "L2TP", + "LDAP", + "LDAPS", + "LDP", + "LMP", + "LOGIN", + "LPD", + "LSP-PING", + "MAC-SERVER-ADM", + "MATIP-A", + "MATIP-B", + "MICRO-BFD", + "MICROSOFT-DS", + "MOBILE-IP", + "MONITOR", + "MPP", + "MS-EXCHANGE", + "MSDP", + "MSP", + "MSSQL-M", + "MSSQL-S", + "MULTIHOP-BFD", + "NAS", + "NCP", + "NETBIOS-DATA", + "NETBIOS-NS", + "NETBIOS-SS", + "NETNEWS", + "NETRJS-1", + "NETRJS-2", + "NETRJS-3", + "NETRJS-4", + "NETWALL", + "NEW-RWHO", + "NFS", + "NNTP", + "NNTPS", + "NTP", + "ODMR", + "OLSR", + "OPENVPN", + "PIM-AUTO-RP", + "PKIX-TIMESTAMP", + "POP2", + "POP3", + "POP3S", + "PPTP", + "PRINT-SRV", + "PTP-EVENT", + "PTP-GENERAL", + "QMTP", + "QOTD", + "RADIUS", + "RADIUS-ACCT", + "REMOTE-MAIL", + "REMOTEFS", + "REMOTECMD", + "RIP", + "RJE", + "RLP", + "RLZDB", + "RMC", + "RMONITOR", + "RPC2PORTMAP", + "RSYNC", + "RTELNET", + "RTSP", + "SGMP", + "SILC", + "SMUX", + "SNA-GW", + "SNMP", + "SNMP-TRAP", + "SNPP", + "SMTP", + "SQL-SVCS", + "SQL", + "SSH", + "SUBMISSION", + "SUNRPC", + "SVCLOC", + "SYSLOG", + "SYSTAT", + "TACACS", + "TALK", + "TCPMUX", + "TCPNETHASPSRV", + "TFTP", + "TIME", + "TIMED", + "UPS", + "XDMCP", + "XNS-CH", + "XNS-MAIL", + "XNS-TIME", + "Z3950", + ] + ], + Field(description="Source port to match by name.", title="Source Port Name"), + ] = None + sourcePortNumber: Annotated[ + Optional[int], + Field( + description="Source port to match by numerical value.", + ge=0, + le=65535, + title="Source Port Number", + ), + ] = None + sourcePortOperator: Annotated[ + Optional[Literal["Equals", "GreaterOrEquals", "LessOrEquals"]], + Field( + description="Operator to use when matching sourcePort, either Equals, GreaterOrEquals, or LessOrEquals.", + title="Source Port Operator", + ), + ] = None + sourcePortRange: Annotated[ + Optional[str], + Field( + description="Range of source ports to match, in the format n-m, e.g. 100-200. The start and end of the range must be port numbers.", + title="Source Port Range", + ), + ] = None + sourcePrefix: Annotated[ + Optional[str], + Field(description="Source prefix to match.", title="Source Prefix"), + ] = None + tcpFlags: Annotated[ + Optional[str], + Field( + description="Match TCP flags, usable with !, &, | and the flags RST, SYN, and ACK.", + title="TCP Flags", + ), + ] = None + + +class IngressPolicySpecClassifierEntry(BaseModel): + dot1pPolicyEntry: Annotated[ + Optional[IngressPolicySpecClassifierEntryDot1pPolicyEntry], + Field( + description="A Dot1p policy entry - only a single Dot1p entry is allowed per classifier resource.", + title="Dot1p Policy Entry", + ), + ] = None + dscpPolicyEntry: Annotated[ + Optional[IngressPolicySpecClassifierEntryDscpPolicyEntry], + Field( + description="A DSCP policy entry - only a single DSCP entry is allowed per classifier resource.", + title="DSCP Policy Entry", + ), + ] = None + ipEntry: Annotated[ + Optional[IngressPolicySpecClassifierEntryIpEntry], + Field( + description="An IPv4 or IPv6 multifield classifier entry.", title="IP Entry" + ), + ] = None + type: Annotated[ + Literal["IPV4", "IPV6", "DOT1P", "DSCP", "AUTO"], + Field( + description="Type of the entry which can be IPV4, IPV6, Dot1pPolicy, DSCPPolicy, or Auto.", + title="Type", + ), + ] + + +class IngressPolicySpecClassifier(BaseModel): + """ + Classifier manages the configuration of traffic classification policies in a network. It includes various entry types like IPv4, IPv6, Dot1p, and DSCP policies. Each entry specifies how traffic should be classified and what actions should be taken on the matched packets. + """ + + entries: Annotated[ + List[IngressPolicySpecClassifierEntry], + Field( + description="Specifies the list of filter entries, in order.\nA classifier containing multiple entry types may result in multiple classifiers being created on the target node.\nIPV4 and IPV6 entries will create multifield classifier policies.", + title="Entries", + ), + ] + + +class IngressPolicySpecForwardingClassToQueueMappingItem(BaseModel): + forwardingClasses: Annotated[ + List[str], + Field( + description="The forwarding classes to which the mapping applies, these are references to ForwardingClass resources.", + min_length=1, + title="Forwarding Classes", + ), + ] + queue: Annotated[ + str, + Field( + description="The queue to which the forwarding classes are mapped, this is a reference to a Queue resource.", + title="Queue", + ), + ] + + +class IngressPolicySpecPolicerExceedAction(BaseModel): + """ + Applies a drop-probability to packets that the policer has determined are exceeding (yellow). + """ + + dropProbabilityLevel: Annotated[ + Optional[Literal["High", "Medium", "Low"]], + Field(title="Drop Probability Level"), + ] = "Medium" + + +class IngressPolicySpecPolicerForwardingClass(BaseModel): + forwardingClasses: Annotated[ + Optional[List[str]], + Field( + description="The forwarding class of the packets on which to apply the Policer. To match all traffic set this to 'ALL'.", + title="Forwarding Class", + ), + ] = None + forwardingTypes: Annotated[ + List[ + Literal[ + "Broadcast", + "Unicast", + "Multicast", + "UnknownMulticast", + "UnknownUnicast", + "All", + ] + ], + Field(title="Forwarding Type"), + ] + + +class IngressPolicySpecPolicerViolateAction(BaseModel): + """ + Applies a drop-probability to packets that the policer has determined are exceeding (red). + """ + + dropProbabilityLevel: Annotated[ + Optional[Literal["High", "Medium", "Low", "All"]], + Field(title="Drop Probability Level"), + ] = "High" + + +class IngressPolicySpecPolicer(BaseModel): + committedBurstSize: Annotated[ + Optional[int], + Field( + description="Maximum CIR bucket depth in bytes.", + ge=0, + le=4294967295, + title="Committed Burst Size", + ), + ] = None + committedRate: Annotated[ + Optional[int], + Field( + description="The committed information rate (CIR) of the policer, defined in kilobits (1024 bits) per second.", + title="Committed Rate", + ), + ] = None + committedRatePercent: Annotated[ + Optional[int], + Field( + description="The committed information rate (CIR) of the policer, defined as a percentage of the Interface speed on which it is applied.", + ge=0, + le=100, + title="Committed Rate Percentage", + ), + ] = None + exceedAction: Annotated[ + Optional[IngressPolicySpecPolicerExceedAction], + Field( + description="Applies a drop-probability to packets that the policer has determined are exceeding (yellow).", + title="Exceed Action", + ), + ] = None + forwardingClasses: Annotated[ + Optional[List[IngressPolicySpecPolicerForwardingClass]], + Field( + description="The list of forwarding classes with traffic to be sent to the policer. Unless specified all traffic is matched for this policer.", + title="Forwarding Class", + ), + ] = None + maximumBurstSize: Annotated[ + Optional[int], + Field( + description="Maximum PIR bucket depth in bytes.", + ge=0, + le=4294967295, + title="Maximum Burst Size", + ), + ] = None + minInterfaceSpeed: Annotated[ + Optional[int], + Field( + description="Minimum interface speed (kbps) to calculate PeakRate and CommittedRate for devices where configuration is not supported in percentage.", + title="Minimum Interface Speed", + ), + ] = None + peakRate: Annotated[ + Optional[int], + Field( + description="The peak information rate (PIR) of the policer, defined in kilobits (1024 bits) per second.", + title="Peak Rate", + ), + ] = None + peakRatePercent: Annotated[ + Optional[int], + Field( + description="The peak information rate (PIR) of the policer, defined as a percentage of the Interface speed on which it is applied.", + ge=0, + le=100, + title="Peak Rate Percentage", + ), + ] = None + violateAction: Annotated[ + Optional[IngressPolicySpecPolicerViolateAction], + Field( + description="Applies a drop-probability to packets that the policer has determined are exceeding (red).", + title="Violate Action", + ), + ] = None + + +class IngressPolicySpecQueueManagementItemQueue(BaseModel): + committedBurstSize: Annotated[ + Optional[int], + Field(description="Committed Burst Size.", title="Committed Burst Size"), + ] = None + maximumBurstSize: Annotated[ + Optional[int], + Field( + description="Maximum amount of shared buffer memory available to the queue in bytes.", + ge=0, + le=4294967295, + title="Maximum Burst Size", + ), + ] = None + pfcOffThreshold: Annotated[ + Optional[int], + Field( + description="PFC off threshold.", ge=0, le=100, title="PFC Off Threshold" + ), + ] = None + pfcOnThreshold: Annotated[ + Optional[int], + Field(description="PFC on threshold.", ge=0, le=100, title="PFC On Threshold"), + ] = None + pfcPauseFramePriority: Annotated[ + Optional[int], + Field( + description="PFC priorities indicated in generated pfc-pause-frame if congestion occurs in a given pfc-queue.", + title="PFC Priority", + ), + ] = None + pfcReservedShareBufferPercent: Annotated[ + Optional[int], + Field( + description="Maximum level the pfc-queue can take from pfc-reserved buffer configured per given forwarding-complex.", + ge=0, + le=100, + title="PFC Reserved Buffer", + ), + ] = None + queue: Annotated[ + str, Field(description="Reference to a Queue resource.", title="Queue") + ] + + +class IngressPolicySpecQueueManagementItem(BaseModel): + pfcReservedBufferPercent: Annotated[ + Optional[int], + Field( + description="Percentage of the linecard buffer reserved for accomodating incoming traffic while upstream node reacts to generated PFC-pause frames. Note: this percentage must be common across all EgressPolicies and QueuesSets used on the same linecard.", + ge=0, + le=100, + title="PFC Reserved Linecard Buffer Percent", + ), + ] = None + queues: Annotated[ + List[IngressPolicySpecQueueManagementItemQueue], + Field(description="List of queues.", title="Queues"), + ] + + +class IngressPolicySpec(BaseModel): + """ + IngressPolicySpec defines the desired state of IngressPolicy + """ + + classifier: Annotated[ + Optional[IngressPolicySpecClassifier], + Field( + description="Classifier manages the configuration of traffic classification policies in a network. It includes various entry types like IPv4, IPv6, Dot1p, and DSCP policies. Each entry specifies how traffic should be classified and what actions should be taken on the matched packets.", + title="Classifiers", + ), + ] = None + forwardingClassToQueueMapping: Annotated[ + Optional[List[IngressPolicySpecForwardingClassToQueueMappingItem]], + Field( + description="Forwarding class to queue mapping policy.", + title="Forwarding Class to Queue Mapping", + ), + ] = None + policers: Annotated[ + Optional[List[IngressPolicySpecPolicer]], + Field( + description="Ordered list of policers where the first policer is evaluated first before proceeding to the next.", + title="Policers", + ), + ] = None + queueManagement: Annotated[ + Optional[List[IngressPolicySpecQueueManagementItem]], + Field( + description="Queue management policy for egress queues.", + title="Queue Management", + ), + ] = None + + +IngressPolicyDeletedResourceEntry = EgressPolicyDeletedResourceEntry + + +class IngressPolicyDeletedResources(RootModel[List[IngressPolicyDeletedResourceEntry]]): + root: List[IngressPolicyDeletedResourceEntry] + + +IngressPolicyMetadata = EgressPolicyMetadata + + +class PolicyAttachmentSpecAttachment(BaseModel): + interface: Annotated[ + Optional[str], + Field( + description="Specifies the Interface on which to deploy the policies.", + title="Interface", + ), + ] = None + interfaceType: Annotated[ + Optional[Literal["ACCESS", "NETWORK"]], + Field( + description="Used for platforms that differentiate between access/service interfaces and network interface. These platforms may require different classifiers depending on whether they are applied on access/service interfaces or network interfaces. Specifies whether the classifier should be configured as a service Egress classifier or network Egress classifier", + title="Interface Type", + ), + ] = None + subInterfaceIndex: Annotated[ + Optional[int], + Field( + description="Specifies the SubInterfaceIndex on which to deploy the policies.", + title="SubInterface Index", + ), + ] = None + + +class PolicyAttachmentSpec(BaseModel): + """ + PolicyAttachmentSpec defines the desired state of PolicyAttachment + """ + + attachments: Annotated[ + List[PolicyAttachmentSpecAttachment], + Field( + description="Specifies a list of Interfaces and subinterfaces on which to deploy the policies.", + title="Interfaces", + ), + ] + egressPolicy: Annotated[ + Optional[str], + Field( + description="Specifies an EgressPolicy to deploy on the specified Node.", + title="Egress Policy", + ), + ] = None + ingressPolicy: Annotated[ + Optional[str], + Field( + description="Specifies the IngressPolicy to deploy on the specified Node.", + title="Ingress Policy", + ), + ] = None + + +PolicyAttachmentDeletedResourceEntry = EgressPolicyDeletedResourceEntry + + +class PolicyAttachmentDeletedResources( + RootModel[List[PolicyAttachmentDeletedResourceEntry]] +): + root: List[PolicyAttachmentDeletedResourceEntry] + + +PolicyAttachmentMetadata = EgressPolicyMetadata + + +class PolicyDeploymentSpec(BaseModel): + """ + PolicyDeploymentSpec defines the desired state of PolicyDeployment + """ + + egressPolicy: Annotated[ + Optional[str], + Field( + description="Specifies an EgressPolicy to deploy on the specified Node.", + title="Egress Policy", + ), + ] = None + ingressPolicy: Annotated[ + Optional[str], + Field( + description="Specifies the IngressPolicy to deploy on the specified Node.", + title="Ingress Policy", + ), + ] = None + interfaceSelector: Annotated[ + Optional[List[str]], + Field( + description="Specifies a label selector to filter the interfaces on which to deploy the policies.", + title="Interface Selector", + ), + ] = None + interfaceType: Annotated[ + Optional[Literal["ACCESS", "NETWORK"]], + Field( + description="Used for platforms that differentiate between access/service interfaces and network interface. These platforms may require different classifiers depending on whether they are applied on access/service interfaces or network interfaces. Specifies whether the classifier should be configured as a service Egress classifier or network Egress classifier", + title="Interface Type", + ), + ] = None + interfaces: Annotated[ + Optional[List[str]], + Field( + description="Specifies a list of Interfaces on which to deploy the policies.", + title="Interfaces", + ), + ] = None + node: Annotated[ + Optional[str], + Field(description="Specifies a Node to deploy the policies on.", title="Node"), + ] = None + nodeSelector: Annotated[ + Optional[List[str]], + Field( + description="Specifies a label selector to filter the nodes on which to deploy the policies.", + title="Node Selector", + ), + ] = None + + +PolicyDeploymentDeletedResourceEntry = EgressPolicyDeletedResourceEntry + + +class PolicyDeploymentDeletedResources( + RootModel[List[PolicyDeploymentDeletedResourceEntry]] +): + root: List[PolicyDeploymentDeletedResourceEntry] + + +PolicyDeploymentMetadata = EgressPolicyMetadata + + +class QueueSpec(BaseModel): + """ + The Queue resource is used to define the properties of a queue, which can then be referenced by other resources. + """ + + queueID: Annotated[ + Optional[int], + Field( + description="The ID of the queue on which to apply the properties. This is mandatory for usage of queus on SROS and is ignored on other operating systems.", + title="Queue ID", + ), + ] = None + queueType: Annotated[ + Literal["Normal", "Pfc"], + Field( + description="QueueType specifies whether this is a normal queue or a PFC queue", + title="Queue Type", + ), + ] + trafficType: Annotated[ + Literal["Unicast", "Multicast"], + Field( + description="The traffic type of the queue, either unicast or multicast.", + title="Traffic Type", + ), + ] + + +QueueDeletedResourceEntry = EgressPolicyDeletedResourceEntry + + +class QueueDeletedResources(RootModel[List[QueueDeletedResourceEntry]]): + root: List[QueueDeletedResourceEntry] + + +QueueMetadata = EgressPolicyMetadata + + +class AppGroup(BaseModel): + apiVersion: Optional[str] = None + kind: Optional[str] = None + name: Optional[str] = None + preferredVersion: Optional[AppGroupVersion] = None + versions: Optional[List[AppGroupVersion]] = None + + +class ResourceHistory(RootModel[List[ResourceHistoryEntry]]): + root: List[ResourceHistoryEntry] + + +class Status(BaseModel): + apiVersion: Optional[str] = None + details: Optional[StatusDetails] = None + kind: Optional[str] = None + string: Optional[str] = None + + +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class EgressPolicy(BaseModel): + """ + EgressPolicy is the Schema for the egresspolicys API + """ + + apiVersion: str + kind: str + metadata: EgressPolicyMetadata + spec: Annotated[ + EgressPolicySpec, + Field( + description="EgressPolicySpec defines the desired state of EgressPolicy", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="EgressPolicyStatus defines the observed state of EgressPolicy", + title="Status", + ), + ] = None + + +class EgressPolicyList(BaseModel): + """ + EgressPolicyList is a list of egresspolicys + """ + + apiVersion: str + items: Optional[List[EgressPolicy]] = None + kind: str + + +class ForwardingClass(BaseModel): + """ + ForwardingClass is the Schema for the forwardingclasss API + """ + + apiVersion: str + kind: str + metadata: ForwardingClassMetadata + spec: Annotated[ + Optional[Dict[str, Any]], + Field( + description="The ForwaringClass is used as a placeholder for to allow multiple other resources to reference the same forwarding class.", + title="Specification", + ), + ] = None + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="ForwardingClassStatus defines the observed state of ForwardingClass", + title="Status", + ), + ] = None + + +class ForwardingClassList(BaseModel): + """ + ForwardingClassList is a list of forwardingclasss + """ + + apiVersion: str + items: Optional[List[ForwardingClass]] = None + kind: str + + +class IngressPolicy(BaseModel): + """ + IngressPolicy is the Schema for the ingresspolicys API + """ + + apiVersion: str + kind: str + metadata: IngressPolicyMetadata + spec: Annotated[ + IngressPolicySpec, + Field( + description="IngressPolicySpec defines the desired state of IngressPolicy", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="IngressPolicyStatus defines the observed state of IngressPolicy", + title="Status", + ), + ] = None + + +class IngressPolicyList(BaseModel): + """ + IngressPolicyList is a list of ingresspolicys + """ + + apiVersion: str + items: Optional[List[IngressPolicy]] = None + kind: str + + +class PolicyAttachment(BaseModel): + """ + PolicyAttachment is the Schema for the policyattachments API + """ + + apiVersion: str + kind: str + metadata: PolicyAttachmentMetadata + spec: Annotated[ + PolicyAttachmentSpec, + Field( + description="PolicyAttachmentSpec defines the desired state of PolicyAttachment", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="PolicyAttachmentStatus defines the observed state of PolicyAttachment", + title="Status", + ), + ] = None + + +class PolicyAttachmentList(BaseModel): + """ + PolicyAttachmentList is a list of policyattachments + """ + + apiVersion: str + items: Optional[List[PolicyAttachment]] = None + kind: str + + +class PolicyDeployment(BaseModel): + """ + PolicyDeployment is the Schema for the policydeployments API + """ + + apiVersion: str + kind: str + metadata: PolicyDeploymentMetadata + spec: Annotated[ + PolicyDeploymentSpec, + Field( + description="PolicyDeploymentSpec defines the desired state of PolicyDeployment", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="PolicyDeploymentStatus defines the observed state of PolicyDeployment", + title="Status", + ), + ] = None + + +class PolicyDeploymentList(BaseModel): + """ + PolicyDeploymentList is a list of policydeployments + """ + + apiVersion: str + items: Optional[List[PolicyDeployment]] = None + kind: str + + +class Queue(BaseModel): + """ + Queue is the Schema for the queues API + """ + + apiVersion: str + kind: str + metadata: QueueMetadata + spec: Annotated[ + QueueSpec, + Field( + description="The Queue resource is used to define the properties of a queue, which can then be referenced by other resources.", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="QueueStatus defines the observed state of Queue", + title="Status", + ), + ] = None + + +class QueueList(BaseModel): + """ + QueueList is a list of queues + """ + + apiVersion: str + items: Optional[List[Queue]] = None + kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/qos/v1alpha1/models.py b/pydantic_eda/apps/qos/v1alpha1/models.py index 1dc8443..b6a84e9 100644 --- a/pydantic_eda/apps/qos/v1alpha1/models.py +++ b/pydantic_eda/apps/qos/v1alpha1/models.py @@ -2,8 +2,10 @@ # filename: qos.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -37,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -91,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -110,6 +118,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -462,7 +507,7 @@ class EgressPolicySpec(BaseModel): class EgressPolicyDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -1644,6 +1689,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class EgressPolicy(BaseModel): """ EgressPolicy is the Schema for the egresspolicys API @@ -1846,3 +1956,13 @@ class QueueList(BaseModel): apiVersion: str items: Optional[List[Queue]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/routing/v1alpha1/models.py b/pydantic_eda/apps/routing/v1alpha1/models.py index cd4debb..cd02ebe 100644 --- a/pydantic_eda/apps/routing/v1alpha1/models.py +++ b/pydantic_eda/apps/routing/v1alpha1/models.py @@ -2,9 +2,10 @@ # filename: routing.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel -from datetime import date + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -38,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,10 +118,153 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str +class WorkflowGetInputsRespElem(BaseModel): + ackPrompt: Optional[str] = None + group: str + kind: str + name: str + namespace: Optional[str] = None + schemaPrompt: Optional[Dict[str, Any]] = None + version: str + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowIdentifier(BaseModel): + group: str + kind: str + name: str + namespace: Optional[str] = None + version: str + + +class WorkflowInputDataElem(BaseModel): + ack: Annotated[ + Optional[bool], Field(description="acknowledge or reject the input request") + ] = None + input: Annotated[ + Optional[Dict[str, Any]], + Field(description="provide a json blob to the workflow"), + ] = None + subflow: Optional[WorkflowIdentifier] = None + + +class AttachmentLookupSpec(BaseModel): + """ + This workflow is used to look up attachments (where an address is attached in the network) on a set of nodes. + It takes an address, and an optional list of nodes (or node selectors - a list of label expressions) to perform the lookup on, + and returns the matching attachments, including the node, + network instance, prefix, interface, and next hop group ID. + """ + + address: Annotated[ + str, + Field( + description="Address to perform a lookup for.\nThis is a standard IPv4 or IPv6 address, excluding mask or prefix length, e.g. 12.0.0.1.", + title="Address", + ), + ] + networkInstance: Annotated[ + Optional[str], + Field( + description="Network Instance is the locally named network instance to use for the lookup.\nCan be omitted if the default network instance is to be used.", + title="Network Instance", + ), + ] = None + nodeSelectors: Annotated[ + Optional[List[str]], + Field( + description='NodeSelectors is a list of node selectors to execute lookups on.\nThis is a list of label expressions, e.g. ["eda.nokia.com/role=leaf", "eda.nokia.com/region=us-west"].', + title="Node Selectors", + ), + ] = None + nodes: Annotated[ + Optional[List[str]], + Field( + description="Nodes is a list of node names to execute lookups on.", + title="Nodes", + ), + ] = None + + +class AttachmentLookupStatusResult(BaseModel): + interface: Optional[str] = None + networkInstance: Optional[str] = None + nextHopGroupId: Optional[int] = None + node: Optional[str] = None + prefix: Optional[str] = None + + +class AttachmentLookupStatus(BaseModel): + """ + AttachmentLookupStatus defines the observed state of AttachmentLookup + """ + + found: bool + results: Optional[List[AttachmentLookupStatusResult]] = None + + +class AttachmentLookupMetadata(BaseModel): + annotations: Optional[Dict[str, str]] = None + labels: Optional[Dict[str, str]] = None + name: Annotated[ + str, + Field( + max_length=253, + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + ), + ] + namespace: str + + class DefaultInterfaceSpecBfd(BaseModel): """ Enable or disable BFD on this DefaultInterface. @@ -162,6 +312,15 @@ class DefaultInterfaceSpecBfd(BaseModel): title="Receive Interval", ), ] + ttl: Annotated[ + Optional[int], + Field( + description="Sets custom IP TTL or Hop Limit for multi-hop BFD sessions packets. Not appllicable to single-hop BFD sessions.", + ge=2, + le=255, + title="IP TTL/Hop Limit", + ), + ] = None class DefaultInterfaceSpecIpv4Address(BaseModel): @@ -195,6 +354,12 @@ class DefaultInterfaceSpec(BaseModel): defaultRouter: Annotated[ str, Field(description="Reference to a DefaultRouter.", title="Default Router") ] + description: Annotated[ + Optional[str], + Field( + description="The description of the DefaultInterface.", title="Description" + ), + ] = None interface: Annotated[ str, Field( @@ -263,7 +428,7 @@ class DefaultInterfaceStatus(BaseModel): ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="Indicates when this Interface last changed state.", title="Last Change", @@ -279,7 +444,7 @@ class DefaultInterfaceStatus(BaseModel): class DefaultInterfaceDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -292,17 +457,7 @@ class DefaultInterfaceDeletedResources( root: List[DefaultInterfaceDeletedResourceEntry] -class DefaultInterfaceMetadata(BaseModel): - annotations: Optional[Dict[str, str]] = None - labels: Optional[Dict[str, str]] = None - name: Annotated[ - str, - Field( - max_length=253, - pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", - ), - ] - namespace: str +DefaultInterfaceMetadata = AttachmentLookupMetadata class DefaultRouterSpecBgpIpv4UnicastMultipath(BaseModel): @@ -619,7 +774,7 @@ class DefaultRouterStatus(BaseModel): ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The time when the state of the resource last changed.", title="Last Change", @@ -640,7 +795,7 @@ class DefaultRouterDeletedResources(RootModel[List[DefaultRouterDeletedResourceE root: List[DefaultRouterDeletedResourceEntry] -DefaultRouterMetadata = DefaultInterfaceMetadata +DefaultRouterMetadata = AttachmentLookupMetadata class DrainSpec(BaseModel): @@ -687,7 +842,98 @@ class DrainDeletedResources(RootModel[List[DrainDeletedResourceEntry]]): root: List[DrainDeletedResourceEntry] -DrainMetadata = DefaultInterfaceMetadata +DrainMetadata = AttachmentLookupMetadata + + +class RouteLookupSpec(BaseModel): + """ + This workflow is used to look up routes on a set of nodes. + It takes an address, and an optional list of nodes (or node selectors - a list of label expressions) to perform the lookup on, + and returns the matching route, and the set of egress interfaces that would be used to reach it. + """ + + address: Annotated[ + str, + Field( + description="Address to perform a lookup for.\nThis is a standard IPv4 or IPv6 address, excluding mask or prefix length, e.g. 12.0.0.1.", + title="Address", + ), + ] + networkInstance: Annotated[ + Optional[str], + Field( + description="Network Instance is the locally named network instance to use for the lookup.\nCan be omitted if the default network instance is to be used.", + title="Network Instance", + ), + ] = None + nodeSelectors: Annotated[ + Optional[List[str]], + Field( + description='Node Selectors is a list of node label selectors to execute lookups on.\nThis is a list of label expressions, e.g. ["eda.nokia.com/role=leaf", "eda.nokia.com/region=us-west"].', + title="Node Selectors", + ), + ] = None + nodes: Annotated[ + Optional[List[str]], + Field( + description="Nodes is a list of node names to execute lookups on.", + title="Nodes", + ), + ] = None + resolve: Annotated[ + bool, + Field( + description="Resolve indicates whether indirect next hops should be resolved.", + title="Resolve", + ), + ] + + +class RouteLookupStatusResultNextHopIndirect(BaseModel): + ipPrefix: Optional[str] = None + nextHopGroupId: Optional[int] = None + resolved: Optional[bool] = None + type: Optional[str] = None + + +class RouteLookupStatusResultNextHopInterface(BaseModel): + name: Annotated[str, Field(description="Name of the egress interface.")] + peerNode: Annotated[ + Optional[str], Field(description="The node this interface is connected to.") + ] = None + + +class RouteLookupStatusResultNextHop(BaseModel): + indirect: Optional[RouteLookupStatusResultNextHopIndirect] = None + interfaces: Optional[List[RouteLookupStatusResultNextHopInterface]] = None + ipAddress: Optional[str] = None + nextHopId: Optional[int] = None + type: Optional[str] = None + + +class RouteLookupStatusResult(BaseModel): + error: Optional[str] = None + found: bool + networkInstance: Optional[str] = None + nextHopGroupId: Optional[int] = None + nextHops: Optional[List[RouteLookupStatusResultNextHop]] = None + node: Optional[str] = None + rawOutput: Optional[str] = None + route: Optional[str] = None + + +class RouteLookupStatus(BaseModel): + """ + RouteLookupStatus defines the observed state of RouteLookup + """ + + found: bool + nodesWithRoute: Optional[int] = None + results: Optional[List[RouteLookupStatusResult]] = None + totalNodes: Optional[int] = None + + +RouteLookupMetadata = AttachmentLookupMetadata class SystemInterfaceSpecBfd(BaseModel): @@ -737,6 +983,15 @@ class SystemInterfaceSpecBfd(BaseModel): title="Receive Interval", ), ] + ttl: Annotated[ + Optional[int], + Field( + description="Sets custom IP TTL or Hop Limit for multi-hop BFD sessions packets. Not appllicable to single-hop BFD sessions.", + ge=2, + le=255, + title="IP TTL/Hop Limit", + ), + ] = None class SystemInterfaceSpec(BaseModel): @@ -754,6 +1009,12 @@ class SystemInterfaceSpec(BaseModel): defaultRouter: Annotated[ str, Field(description="Reference to a DefaultRouter.", title="Default Router") ] + description: Annotated[ + Optional[str], + Field( + description="The description of the SystemInterface.", title="Description" + ), + ] = None ipv4Address: Annotated[ Optional[str], Field( @@ -790,7 +1051,7 @@ class SystemInterfaceStatus(BaseModel): ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="Indicates when this Interface last changed state.", title="Last Change", @@ -814,7 +1075,7 @@ class SystemInterfaceDeletedResources( root: List[SystemInterfaceDeletedResourceEntry] -SystemInterfaceMetadata = DefaultInterfaceMetadata +SystemInterfaceMetadata = AttachmentLookupMetadata class AppGroup(BaseModel): @@ -836,6 +1097,109 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class WorkflowInputData(RootModel[List[WorkflowInputDataElem]]): + root: List[WorkflowInputDataElem] + + +class AttachmentLookup(BaseModel): + """ + AttachmentLookup is the Schema for the attachmentlookups API + """ + + apiVersion: str + kind: str + metadata: AttachmentLookupMetadata + spec: Annotated[ + AttachmentLookupSpec, + Field( + description="This workflow is used to look up attachments (where an address is attached in the network) on a set of nodes.\nIt takes an address, and an optional list of nodes (or node selectors - a list of label expressions) to perform the lookup on,\nand returns the matching attachments, including the node,\nnetwork instance, prefix, interface, and next hop group ID.", + title="Specification", + ), + ] + status: Annotated[ + Optional[AttachmentLookupStatus], + Field( + description="AttachmentLookupStatus defines the observed state of AttachmentLookup", + title="Status", + ), + ] = None + + +class AttachmentLookupList(BaseModel): + """ + AttachmentLookupList is a list of attachmentlookups + """ + + apiVersion: str + items: Optional[List[AttachmentLookup]] = None + kind: str + + class DefaultInterface(BaseModel): """ DefaultInterface is the Schema for the defaultinterfaces API @@ -938,6 +1302,40 @@ class DrainList(BaseModel): kind: str +class RouteLookup(BaseModel): + """ + RouteLookup is the Schema for the routelookups API + """ + + apiVersion: str + kind: str + metadata: RouteLookupMetadata + spec: Annotated[ + RouteLookupSpec, + Field( + description="This workflow is used to look up routes on a set of nodes.\nIt takes an address, and an optional list of nodes (or node selectors - a list of label expressions) to perform the lookup on,\nand returns the matching route, and the set of egress interfaces that would be used to reach it.", + title="Specification", + ), + ] + status: Annotated[ + Optional[RouteLookupStatus], + Field( + description="RouteLookupStatus defines the observed state of RouteLookup", + title="Status", + ), + ] = None + + +class RouteLookupList(BaseModel): + """ + RouteLookupList is a list of routelookups + """ + + apiVersion: str + items: Optional[List[RouteLookup]] = None + kind: str + + class SystemInterface(BaseModel): """ SystemInterface is the Schema for the systeminterfaces API @@ -970,3 +1368,13 @@ class SystemInterfaceList(BaseModel): apiVersion: str items: Optional[List[SystemInterface]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/routingpolicies/v1alpha1/models.py b/pydantic_eda/apps/routingpolicies/v1alpha1/models.py index 25833ad..b95f65f 100644 --- a/pydantic_eda/apps/routingpolicies/v1alpha1/models.py +++ b/pydantic_eda/apps/routingpolicies/v1alpha1/models.py @@ -2,8 +2,10 @@ # filename: routingpolicies.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -37,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -91,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -110,44 +118,81 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str -class CommunitySetSpec(BaseModel): +class ASPathSetSpec(BaseModel): """ - CommunitySetSpec defines the desired state of CommunitySet + ASPathSetSpec defines the desired state of ASPathSet """ - expressionMatch: Annotated[ - Optional[str], + members: Annotated[ + Optional[List[str]], Field( - description="Options that determine the matching criteria that applies to the list of community members.", - title="Expression Match", + description="Members is a list of AS path regular expressions.", + title="AS Path Members", ), ] = None - members: Annotated[ - Optional[List[str]], + regexMode: Annotated[ + Optional[Literal["ASN", "Character"]], Field( - description="A standard BGP community value, regular expression or well-known name or else a large BGP community value or regular expression.", - title="Community Set Members", + description="Defines how AS_PATH attribute is converted into a string for regex matching.", + title="Regex Mode", ), ] = None -class CommunitySetDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None +class ASPathSetDeletedResourceEntry(BaseModel): + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None transactionId: Optional[int] = None -class CommunitySetDeletedResources(RootModel[List[CommunitySetDeletedResourceEntry]]): - root: List[CommunitySetDeletedResourceEntry] +class ASPathSetDeletedResources(RootModel[List[ASPathSetDeletedResourceEntry]]): + root: List[ASPathSetDeletedResourceEntry] -class CommunitySetMetadata(BaseModel): +class ASPathSetMetadata(BaseModel): annotations: Optional[Dict[str, str]] = None labels: Optional[Dict[str, str]] = None name: Annotated[ @@ -160,6 +205,104 @@ class CommunitySetMetadata(BaseModel): namespace: str +class CommunitySetSpec(BaseModel): + """ + CommunitySetSpec defines the desired state of CommunitySet + """ + + expressionMatch: Annotated[ + Optional[str], + Field( + description="Options that determine the matching criteria that applies to the list of community members.", + title="Expression Match", + ), + ] = None + matchSetOptions: Annotated[ + Optional[Literal["All", "Any", "Invert"]], + Field( + description="The matching criteria that applies to the Members list.", + title="Match Set Options", + ), + ] = None + members: Annotated[ + Optional[List[str]], + Field( + description="A standard BGP community value, regular expression or well-known name or else a large BGP community value or regular expression.", + title="Community Set Members", + ), + ] = None + + +CommunitySetDeletedResourceEntry = ASPathSetDeletedResourceEntry + + +class CommunitySetDeletedResources(RootModel[List[CommunitySetDeletedResourceEntry]]): + root: List[CommunitySetDeletedResourceEntry] + + +CommunitySetMetadata = ASPathSetMetadata + + +class PolicySpecDefaultActionBgpCommunitySet(BaseModel): + """ + Modify BGP communities associated with the route using hybrid Community Sets. + """ + + add: Annotated[ + Optional[List[str]], + Field( + description="List of community sets to add to the route.", + max_length=1, + title="Add Communities", + ), + ] = None + remove: Annotated[ + Optional[List[str]], + Field( + description="List of community sets to remove from the route.", + max_length=1, + title="Remove Communities", + ), + ] = None + replace: Annotated[ + Optional[List[str]], + Field( + description="List of community sets to replace the existing communities with. Cannot be combined with Add or Remove.", + max_length=1, + title="Replace Communities", + ), + ] = None + + +class PolicySpecDefaultActionBgpMed(BaseModel): + """ + Set a new MED value. + """ + + numericalValue: Annotated[ + Optional[int], + Field( + description="Fixed numerical value to set or add/subtract.", + ge=0, + le=4294967295, + title="MED Value", + ), + ] = None + operation: Annotated[ + Optional[Literal["Set", "Add", "Subtract"]], + Field( + description="The operation to perform on the MED value.", title="Operation" + ), + ] = None + valueType: Annotated[ + Optional[Literal["Fixed", "IGP"]], + Field( + description="Use a fixed value or an IGP metric to adjust the MED.", + title="Value Type", + ), + ] = None + + class PolicySpecDefaultActionBgp(BaseModel): """ Actions related to the BGP protocol. @@ -187,6 +330,13 @@ class PolicySpecDefaultActionBgp(BaseModel): title="AS Path Replace", ), ] = None + communitySet: Annotated[ + Optional[PolicySpecDefaultActionBgpCommunitySet], + Field( + description="Modify BGP communities associated with the route using hybrid Community Sets.", + title="Modify Communities", + ), + ] = None localPreference: Annotated[ Optional[int], Field( @@ -196,6 +346,10 @@ class PolicySpecDefaultActionBgp(BaseModel): title="Set Local Preference", ), ] = None + med: Annotated[ + Optional[PolicySpecDefaultActionBgpMed], + Field(description="Set a new MED value.", title="Set MED"), + ] = None setOrigin: Annotated[ Optional[Literal["egp", "igp", "incomplete"]], Field( @@ -215,12 +369,71 @@ class PolicySpecDefaultAction(BaseModel): Field(description="Actions related to the BGP protocol.", title="BGP"), ] = None policyResult: Annotated[ - Optional[Literal["accept", "reject"]], + Optional[Literal["accept", "reject", "NextPolicy", "NextStatement"]], Field(description="Final disposition for the route.", title="Policy Result"), ] = None -PolicySpecStatementItemActionBgp = PolicySpecDefaultActionBgp +PolicySpecStatementItemActionBgpCommunitySet = PolicySpecDefaultActionBgpCommunitySet + + +PolicySpecStatementItemActionBgpMed = PolicySpecDefaultActionBgpMed + + +class PolicySpecStatementItemActionBgp(BaseModel): + """ + Actions related to the BGP protocol. + """ + + asPathPrepend: Annotated[ + Optional[int], + Field( + description="AS number to prepend to the AS Path attributes.", + ge=1, + le=4294967295, + title="AS Path Prepend", + ), + ] = None + asPathRemove: Annotated[ + Optional[bool], + Field( + description="Clear the AS path to make it empty.", title="AS Path Remove" + ), + ] = None + asPathReplace: Annotated[ + Optional[List[int]], + Field( + description="Replace the existing AS path with a new AS_SEQUENCE containing the listed AS numbers.", + title="AS Path Replace", + ), + ] = None + communitySet: Annotated[ + Optional[PolicySpecStatementItemActionBgpCommunitySet], + Field( + description="Modify BGP communities associated with the route using hybrid Community Sets.", + title="Modify Communities", + ), + ] = None + localPreference: Annotated[ + Optional[int], + Field( + description="Set a new LOCAL_PREF value for matching BGP routes.", + ge=0, + le=4294967295, + title="Set Local Preference", + ), + ] = None + med: Annotated[ + Optional[PolicySpecStatementItemActionBgpMed], + Field(description="Set a new MED value.", title="Set MED"), + ] = None + setOrigin: Annotated[ + Optional[Literal["egp", "igp", "incomplete"]], + Field( + description="Set a new ORIGIN attribute for matching BGP routes.", + title="Set Origin", + ), + ] = None class PolicySpecStatementItemAction(BaseModel): @@ -233,16 +446,48 @@ class PolicySpecStatementItemAction(BaseModel): Field(description="Actions related to the BGP protocol.", title="BGP"), ] = None policyResult: Annotated[ - Optional[Literal["accept", "reject"]], + Optional[Literal["accept", "reject", "NextPolicy", "NextStatement"]], Field(description="Final disposition for the route.", title="Policy Result"), ] = None +class PolicySpecStatementItemMatchBgpAsPathMatch(BaseModel): + """ + AS Path match criteria. + """ + + asPathExpression: Annotated[ + Optional[str], + Field( + description="A singular regular expression string to match against AS_PATH objects. Mutually exclusive with the ASPathSet reference.", + title="AS Path Expression", + ), + ] = None + asPathSet: Annotated[ + Optional[str], + Field( + description="Reference to an ASPathSet resource. Mutually exclusive with the ASPathExpression.", + title="AS Path Set", + ), + ] = None + matchSetOptions: Annotated[ + Optional[Literal["Any", "All", "Invert"]], + Field( + description="The matching criteria that applies to the members in the referenced set.", + title="Match Set Options", + ), + ] = None + + class PolicySpecStatementItemMatchBgp(BaseModel): """ Configuration for BGP-specific policy match criteria. """ + asPathMatch: Annotated[ + Optional[PolicySpecStatementItemMatchBgpAsPathMatch], + Field(description="AS Path match criteria.", title="AS Path"), + ] = None communitySet: Annotated[ Optional[str], Field( @@ -339,14 +584,14 @@ class PolicySpec(BaseModel): ] = None -PolicyDeletedResourceEntry = CommunitySetDeletedResourceEntry +PolicyDeletedResourceEntry = ASPathSetDeletedResourceEntry class PolicyDeletedResources(RootModel[List[PolicyDeletedResourceEntry]]): root: List[PolicyDeletedResourceEntry] -PolicyMetadata = CommunitySetMetadata +PolicyMetadata = ASPathSetMetadata class PrefixSetSpecPrefixItem(BaseModel): @@ -398,14 +643,14 @@ class PrefixSetSpec(BaseModel): ] -PrefixSetDeletedResourceEntry = CommunitySetDeletedResourceEntry +PrefixSetDeletedResourceEntry = ASPathSetDeletedResourceEntry class PrefixSetDeletedResources(RootModel[List[PrefixSetDeletedResourceEntry]]): root: List[PrefixSetDeletedResourceEntry] -PrefixSetMetadata = CommunitySetMetadata +PrefixSetMetadata = ASPathSetMetadata class AppGroup(BaseModel): @@ -427,6 +672,105 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class ASPathSet(BaseModel): + """ + ASPathSet is the Schema for the aspathsets API + """ + + apiVersion: str + kind: str + metadata: ASPathSetMetadata + spec: Annotated[ + ASPathSetSpec, + Field( + description="ASPathSetSpec defines the desired state of ASPathSet", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="ASPathSetStatus defines the observed state of ASPathSet", + title="Status", + ), + ] = None + + +class ASPathSetList(BaseModel): + """ + ASPathSetList is a list of aspathsets + """ + + apiVersion: str + items: Optional[List[ASPathSet]] = None + kind: str + + class CommunitySet(BaseModel): """ CommunitySet is the Schema for the communitysets API @@ -527,3 +871,13 @@ class PrefixSetList(BaseModel): apiVersion: str items: Optional[List[PrefixSet]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/security/v1alpha1/models.py b/pydantic_eda/apps/security/v1alpha1/models.py index 3e775fb..6e8324e 100644 --- a/pydantic_eda/apps/security/v1alpha1/models.py +++ b/pydantic_eda/apps/security/v1alpha1/models.py @@ -2,8 +2,10 @@ # filename: security.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -37,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -91,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -110,6 +118,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -145,7 +190,7 @@ class KeychainDeploymentSpec(BaseModel): class KeychainDeploymentDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -200,6 +245,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class Keychain(BaseModel): """ Keychain is the Schema for the keychains API @@ -266,3 +376,13 @@ class KeychainList(BaseModel): apiVersion: str items: Optional[List[Keychain]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/services/v1/models.py b/pydantic_eda/apps/services/v1/models.py new file mode 100644 index 0000000..c2793b8 --- /dev/null +++ b/pydantic_eda/apps/services/v1/models.py @@ -0,0 +1,5775 @@ +# generated by datamodel-codegen: +# filename: services.json + +from __future__ import annotations + +from typing import Annotated, Any, Dict, List, Literal, Optional + +from pydantic import AwareDatetime, BaseModel, Field, RootModel + + +class AppGroupVersion(BaseModel): + groupVersion: Optional[str] = None + version: Optional[str] = None + + +class ErrorIndex(BaseModel): + index: Optional[int] = None + + +class ErrorItem(BaseModel): + error: Optional[Dict[str, Any]] = None + type: Optional[str] = None + + +class ErrorResponse(BaseModel): + """ + Generic error response for REST APIs + """ + + code: Annotated[ + int, Field(description="the numeric HTTP error code for the response.") + ] + details: Annotated[ + Optional[str], Field(description="The optional details of the error response.") + ] = None + dictionary: Annotated[ + Optional[Dict[str, Any]], + Field( + description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' + ), + ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None + errors: Annotated[ + Optional[List[ErrorItem]], + Field( + description="Collection of errors in cases where more than one exists. This needs to be\nflexible so we can support multiple formats" + ), + ] = None + index: Optional[ErrorIndex] = None + internal: Annotated[ + Optional[int], + Field( + description="Internal error code in cases where we don't have an array of errors" + ), + ] = None + message: Annotated[ + str, Field(description="The basic text error message for the error response.") + ] + ref: Annotated[ + Optional[str], + Field( + description="Reference to the error source. Should typically be the URI of the request" + ), + ] = None + type: Annotated[ + Optional[str], + Field( + description="URI pointing at a document that describes the error and mitigation steps\nIf there is no document, point to the RFC for the HTTP error code" + ), + ] = None + + +class K8SPatchOp(BaseModel): + from_: Annotated[Optional[str], Field(alias="from")] = None + op: str + path: str + value: Optional[Dict[str, Any]] = None + x_permissive: Annotated[Optional[bool], Field(alias="x-permissive")] = None + + +class Patch(RootModel[List[K8SPatchOp]]): + root: List[K8SPatchOp] + + +class Resource(BaseModel): + kind: Optional[str] = None + name: Optional[str] = None + namespaced: Optional[bool] = None + readOnly: Optional[bool] = None + singularName: Optional[str] = None + uiCategory: Optional[str] = None + + +class ResourceHistoryEntry(BaseModel): + author: Optional[str] = None + changeType: Optional[str] = None + commitTime: Optional[AwareDatetime] = None + hash: Optional[str] = None + message: Optional[str] = None + transactionId: Optional[int] = None + + +class ResourceList(BaseModel): + apiVersion: Optional[str] = None + groupVersion: Optional[str] = None + kind: Optional[str] = None + resources: Optional[List[Resource]] = None + + +class StatusDetails(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + name: Optional[str] = None + + +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + +class UIResult(RootModel[str]): + root: str + + +class WorkflowGetInputsRespElem(BaseModel): + ackPrompt: Optional[str] = None + group: str + kind: str + name: str + namespace: Optional[str] = None + schemaPrompt: Optional[Dict[str, Any]] = None + version: str + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowIdentifier(BaseModel): + group: str + kind: str + name: str + namespace: Optional[str] = None + version: str + + +class WorkflowInputDataElem(BaseModel): + ack: Annotated[ + Optional[bool], Field(description="acknowledge or reject the input request") + ] = None + input: Annotated[ + Optional[Dict[str, Any]], + Field(description="provide a json blob to the workflow"), + ] = None + subflow: Optional[WorkflowIdentifier] = None + + +class BridgeDomainSpecL2proxyARPNDDynamicLearning(BaseModel): + ageTime: Annotated[ + Optional[int], + Field( + description="Aging timer value for the proxy entries in seconds. If not set, this indicates that the entries are never flushed.", + ge=60, + le=86400, + title="Age Time", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables or disables Dynamic Learning.", title="Enabled"), + ] = False + sendRefresh: Annotated[ + Optional[int], + Field( + description="The interval determines the frequency at which the system generates three ARP Requests or Neighbor Solicitations with the intent to refresh the proxy entry. The refresh is sent within the age-time window.", + ge=120, + le=86400, + title="Send Refresh Interval", + ), + ] = None + + +class BridgeDomainSpecL2proxyARPNDIpDuplication(BaseModel): + enabled: Annotated[ + Optional[bool], + Field(description="Enables or disables IP Duplication.", title="Enabled"), + ] = False + holdDownTime: Annotated[ + Optional[int], + Field( + description="Time to wait in minutes from the moment an IP is declared duplicate to the time the IP is removed from the proxy ARP/ND table.", + ge=2, + le=60, + title="Hold Down Time", + ), + ] = 9 + monitoringWindow: Annotated[ + Optional[int], + Field( + description="Monitoring window for detecting duplication on a given IP address in the proxy ARP/ND table.", + ge=1, + le=15, + title="Monitoring Window", + ), + ] = 3 + numMoves: Annotated[ + Optional[int], + Field( + description="Number of moves in the proxy ARP/ND table that an IP is allowed within the monitoring-window.", + ge=3, + le=10, + title="Number of Moves", + ), + ] = 5 + + +class BridgeDomainSpecL2proxyARPND(BaseModel): + """ + Enables / Disabled Proxy ARP / Proxy ND. + """ + + dynamicLearning: Annotated[ + Optional[BridgeDomainSpecL2proxyARPNDDynamicLearning], + Field(title="Dynamic Learning"), + ] = None + ipDuplication: Annotated[ + Optional[BridgeDomainSpecL2proxyARPNDIpDuplication], + Field(title="L2 Proxy ARP/ND IP Duplication Detection"), + ] = None + proxyARP: Annotated[ + Optional[bool], Field(description="Enables proxy ARP.", title="Proxy ARP") + ] = False + proxyND: Annotated[ + Optional[bool], Field(description="Enables proxy ND.", title="Proxy ND") + ] = False + tableSize: Annotated[ + Optional[int], + Field( + description="Maximum number of entries allowed in the proxy table of the bridge domain.", + ge=1, + le=8192, + title="L2 Proxy ARP/ND Table Size", + ), + ] = 250 + + +class BridgeDomainSpecMacDuplicationDetection(BaseModel): + """ + Enable or disable MAC duplication detection and resolution mechanisms. + """ + + action: Annotated[ + Optional[Literal["Blackhole", "OperDown", "StopLearning"]], + Field( + description="Action to take on the subinterface upon detecting at least one mac addresses as duplicate on the subinterface.", + title="Action", + ), + ] = "StopLearning" + enabled: Annotated[ + Optional[bool], + Field( + description="Enables or disables Mac Duplication Detection.", + title="Enabled", + ), + ] = False + holdDownTime: Annotated[ + Optional[int], + Field( + description="Time to wait in minutes from the moment a mac is declared duplicate to the mac is flushed from the bridge table.", + ge=2, + le=60, + title="Hold Down Time", + ), + ] = 9 + monitoringWindow: Annotated[ + Optional[int], + Field( + description="Monitoring window in minutes for detecting duplication on a given mac address.", + ge=1, + le=15, + title="Monitoring Window", + ), + ] = 3 + numMoves: Annotated[ + Optional[int], + Field( + description="Number of moves a mac is allowed within the monitoring-window, before it is declared duplicate.", + ge=3, + title="Number of Moves", + ), + ] = 5 + + +class BridgeDomainSpec(BaseModel): + """ + The BridgeDomain enables the configuration and management of Layer 2 virtual networks. It includes settings for VNI, EVI, route targets for import and export, and tunnel index allocation. Additionally, the specification allows for advanced features such as MAC address table limits, aging, Proxy ARP and detection of MAC and IP duplication. + """ + + description: Annotated[ + Optional[str], + Field(description="The description of the BridgeDomain.", title="Description"), + ] = None + evi: Annotated[ + Optional[int], + Field( + description="EVI to use for this BridgeDomain, can be optionally left blank to have it automatically allocated using the EVI Pool.", + ge=1, + le=65535, + title="EVI", + ), + ] = None + eviPool: Annotated[ + Optional[str], + Field( + description="Reference to an EVI pool to use for allocations if EVI is left blank.", + title="EVI Allocation Pool", + ), + ] = "evi-pool" + exportTarget: Annotated[ + Optional[str], + Field( + description="Export route target in 'target:N:N' format, if not specified, the default value taken as \"target:1:\".", + pattern="^target.*$", + title="Export Target", + ), + ] = None + importTarget: Annotated[ + Optional[str], + Field( + description="Import route target in 'target:N:N' format, if not specified, the default value taken as \"target:1:\".", + pattern="^target.*$", + title="Import Target", + ), + ] = None + l2proxyARPND: Annotated[ + Optional[BridgeDomainSpecL2proxyARPND], + Field( + description="Enables / Disabled Proxy ARP / Proxy ND.", + title="L2 Proxy ARP/ND", + ), + ] = None + macAging: Annotated[ + Optional[int], + Field( + description="Configurable aging time for dynamically learned mac addresses.", + ge=60, + le=86400, + title="MAC Aging", + ), + ] = 300 + macDuplicationDetection: Annotated[ + Optional[BridgeDomainSpecMacDuplicationDetection], + Field( + description="Enable or disable MAC duplication detection and resolution mechanisms.", + title="MAC Duplication Detection", + ), + ] = None + macLearning: Annotated[ + Optional[bool], + Field( + description="Enable MAC learning for this BridgeDomain.", + title="MAC Learning", + ), + ] = True + macLimit: Annotated[ + Optional[int], + Field( + description="Sets the maximum number of MAC entries accepted in the bridge table.", + ge=1, + title="MAC Limit", + ), + ] = None + tunnelIndexPool: Annotated[ + Optional[str], + Field( + description="Reference to a tunnel index pool to use for allocations.", + title="Tunnel Index Allocation Pool", + ), + ] = "tunnel-index-pool" + type: Annotated[ + Optional[Literal["SIMPLE", "EVPNVXLAN"]], + Field( + description="Select the type of BridgeDomain. Simple doesn't include any overlay control plane or dataplane properties (EVPN/VXLAN). EVPNVXLAN includes the properties needed to provision this BridgeDomain over an IP Fabric.", + title="Type", + ), + ] = "EVPNVXLAN" + vni: Annotated[ + Optional[int], + Field( + description="VNI to use for this BridgeDomain, can be optionally left blank to have it allocated using the VNI Pool.", + ge=1, + le=16777215, + title="VNI", + ), + ] = None + vniPool: Annotated[ + Optional[str], + Field( + description="Reference to a VNI pool to use for allocations if VNI is left blank.", + title="VNI Allocation Pool", + ), + ] = "vni-pool" + + +class BridgeDomainStatus(BaseModel): + """ + BridgeDomainStatus defines the observed state of BridgeDomain + """ + + evi: Annotated[ + Optional[int], + Field(description="EVI in use for this bridge domain.", title="EVI"), + ] = None + exportTarget: Annotated[ + Optional[str], + Field( + description="Export route target for this bridge domain.", + title="Export Target", + ), + ] = None + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the VNET.", title="Health Score" + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + importTarget: Annotated[ + Optional[str], + Field( + description="Import route target for this bridge domain.", + title="Import Target", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + nodes: Annotated[ + Optional[List[str]], + Field( + description="Nodes which have the BridgeDomain configured (min 1 sub-interface).", + title="Nodes", + ), + ] = None + numNodes: Annotated[ + Optional[int], + Field( + description="Number of nodes which have the BridgeDomain configured (min 1 sub-interface).", + title="Number of Nodes", + ), + ] = None + numSubInterfaces: Annotated[ + Optional[int], + Field( + description="Number of sub-interfaces attached to the BridgeDomain.", + title="Number of Sub-Interfaces", + ), + ] = None + numSubInterfacesOperDown: Annotated[ + Optional[int], + Field( + description="Number of oper-down sub-interfaces attached to the BridgeDomain.", + title="Number of Operational Down Sub-Interfaces", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field(description="Operational state of the VNET.", title="Operational State"), + ] = None + tunnelIndex: Annotated[ + Optional[int], + Field(description="Vxlan tunnel index in use.", title="Tunnel Index"), + ] = None + vni: Annotated[ + Optional[int], + Field(description="VNI in use for this bridge domain.", title="VNI"), + ] = None + + +class BridgeDomainDeletedResourceEntry(BaseModel): + commitTime: Optional[AwareDatetime] = None + hash: Optional[str] = None + name: Optional[str] = None + namespace: Optional[str] = None + transactionId: Optional[int] = None + + +class BridgeDomainDeletedResources(RootModel[List[BridgeDomainDeletedResourceEntry]]): + root: List[BridgeDomainDeletedResourceEntry] + + +class BridgeDomainMetadata(BaseModel): + annotations: Optional[Dict[str, str]] = None + labels: Optional[Dict[str, str]] = None + name: Annotated[ + str, + Field( + max_length=253, + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + ), + ] + namespace: str + + +class BridgeInterfaceSpecEgress(BaseModel): + """ + Manages actions on traffic at Egress. + """ + + filters: Annotated[ + Optional[List[str]], + Field( + description="List of Filter references to use at egress.", title="Filters" + ), + ] = None + qosPolicy: Annotated[ + Optional[List[str]], + Field( + description="List of QoS Egress policy references to use at egress.", + title="QoS Egress Policy", + ), + ] = None + + +class BridgeInterfaceSpecIngress(BaseModel): + """ + Manages actions on traffic at Ingress. + """ + + filters: Annotated[ + Optional[List[str]], + Field( + description="List of Filter references to use at ingress.", title="Filters" + ), + ] = None + qosPolicy: Annotated[ + Optional[List[str]], + Field( + description="List of QoS Ingress policy references to use at ingress.", + title="QoS Ingress Policy", + ), + ] = None + + +class BridgeInterfaceSpecUplinkEgress(BaseModel): + """ + Manages actions on traffic at Egress of the Local enpoint of the Uplink. + """ + + filters: Annotated[ + Optional[List[str]], + Field( + description="List of Filter references to use at egress.", title="Filters" + ), + ] = None + qosPolicy: Annotated[ + Optional[List[str]], + Field( + description="List of QoS Egress policy references to use at egress.", + title="QoS Egress Policy", + ), + ] = None + + +class BridgeInterfaceSpecUplinkIngress(BaseModel): + """ + Manages actions on traffic at Ingress of the Local enpoint of the Uplink. + """ + + filters: Annotated[ + Optional[List[str]], + Field( + description="List of Filter references to use at ingress.", title="Filters" + ), + ] = None + qosPolicy: Annotated[ + Optional[List[str]], + Field( + description="List of QoS Ingress policy references to use at ingress.", + title="QoS Ingress Policy", + ), + ] = None + + +class BridgeInterfaceSpecUplink(BaseModel): + """ + The Uplink between your access breakout switch and your leaf switch. + """ + + egress: Annotated[ + Optional[BridgeInterfaceSpecUplinkEgress], + Field( + description="Manages actions on traffic at Egress of the Local enpoint of the Uplink.", + title="Egress", + ), + ] = None + ingress: Annotated[ + Optional[BridgeInterfaceSpecUplinkIngress], + Field( + description="Manages actions on traffic at Ingress of the Local enpoint of the Uplink.", + title="Ingress", + ), + ] = None + uplinkSelector: Annotated[ + Optional[List[str]], + Field( + description="Selects TopoLinks which connect a leaf switch to a breakout switch. This is the uplink between your access breakout switch and your leaf switch. There can only be a single TopoLink between the access breakout switch and the leaf switch, if more than one TopoLink is present between two devices the transaction will fail.", + title="Uplink Selector", + ), + ] = None + uplinkVLANID: Annotated[ + Optional[str], + Field( + description="The VLAN ID to be utilized to isolate traffic from the VLAN on the access breakout switch to the leaf switch on the selected uplink TopoLink.", + title="Uplink VLAN ID", + ), + ] = "pool" + uplinkVLANPool: Annotated[ + Optional[str], + Field( + description="A VLAN from this pool will be utilized to isolate traffic from the VLAN on the access breakout switch to the leaf switch on the selected uplink TopoLink.", + title="Uplink VLAN Pool", + ), + ] = None + + +class BridgeInterfaceSpec(BaseModel): + """ + The BridgeInterface enables the attachment of network interfaces to a Bridge Domain. It includes settings for VLAN ID allocation, interface attachment, and actions on ingress and egress traffic. The specification supports integration with other network resources, such as Bridge Domains and Interfaces, and provides advanced features like MAC Duplication Detection with configurable actions. + """ + + bridgeDomain: Annotated[ + str, + Field( + description="Reference to a BridgeDomain in which to attach the BridgeInterface.", + title="Bridge Domain", + ), + ] + description: Annotated[ + Optional[str], + Field( + description="The description of the BridgeInterface.", title="Description" + ), + ] = None + egress: Annotated[ + Optional[BridgeInterfaceSpecEgress], + Field( + description="Manages actions on traffic at Egress.", title="Egress Actions" + ), + ] = None + ingress: Annotated[ + Optional[BridgeInterfaceSpecIngress], + Field( + description="Manages actions on traffic at Ingress.", + title="Ingress Actions", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to an Interface resource to attach this BridgeInterface.", + title="Interface", + ), + ] + l2MTU: Annotated[ + Optional[int], + Field( + description="L2 MTU specifies the maximum sized Ethernet frame that can be transmitted on the subinterface. If a frame exceeds this size it is discarded. If the l2-mtu of the subinterface exceeds the port-mtu of the associated interface, the subinterface will remain operationally down.", + ge=1450, + le=9500, + title="L2 MTU", + ), + ] = None + macDuplicationDetectionAction: Annotated[ + Optional[ + Literal["Blackhole", "OperDown", "StopLearning", "UseBridgeDomainAction"] + ], + Field( + description="Override for Mac Duplication Detection action if enabled in the associated BridgeDomain.", + title="MAC Duplication Detection Action", + ), + ] = None + splitHorizonGroup: Annotated[ + Optional[str], + Field( + description="Split Horizon Group to be used for this BridgeInterface. The subinterface within this BridgeInterface will be a member of this Split Horizon Group.", + title="Split Horizon Group", + ), + ] = None + uplink: Annotated[ + Optional[BridgeInterfaceSpecUplink], + Field( + description="The Uplink between your access breakout switch and your leaf switch.", + title="Uplink", + ), + ] = None + vlanID: Annotated[ + str, + Field( + description="Single value between 1-4094 support, ranges supported in the format x-y,x-y, or the special keyword null, any, untagged or pool for auto allocation.", + title="VLAN ID", + ), + ] + + +class BridgeInterfaceStatusSubInterface(BaseModel): + enabled: Annotated[ + Optional[bool], + Field( + description="The administrative status of the SubInterface.", + title="Enabled", + ), + ] = None + interface: Annotated[ + str, Field(description="Normalized interface name.", title="Interface") + ] + interfaceResource: Annotated[ + str, Field(description="Eda interface resource.", title="Interface Resource") + ] + lastChange: Annotated[ + Optional[str], + Field( + description="Indicates when this SubInterface last changed state.", + title="Last Change", + ), + ] = None + node: Annotated[str, Field(description="Reference to Node object.", title="Node")] + nodeInterface: Annotated[ + str, Field(description="Node specific interface name.", title="Node Interface") + ] + operatingSystem: Annotated[ + Optional[str], + Field(description="Operating System of the Node.", title="Operating System"), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Indicates the current operational state of the SubInterface.", + title="Operational State", + ), + ] = None + subInterfaceIndex: Annotated[ + Optional[int], + Field( + description="Index allocated to the subinterface on the associated interface for the given VLAN.", + title="Sub Interface Index", + ), + ] = None + vlanID: Annotated[ + Optional[str], + Field(description="vlan assigned to this subinterface.", title="VLAN ID"), + ] = None + + +class BridgeInterfaceStatus(BaseModel): + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the BridgeInterface.", + title="Health Score", + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the BridgeInterface.", + title="Operational State", + ), + ] = None + subInterfaces: Annotated[ + Optional[List[BridgeInterfaceStatusSubInterface]], + Field( + description="Sub-interfaces status within the BridgeInterface.", + title="Sub-Interfaces Status", + ), + ] = None + + +BridgeInterfaceDeletedResourceEntry = BridgeDomainDeletedResourceEntry + + +class BridgeInterfaceDeletedResources( + RootModel[List[BridgeInterfaceDeletedResourceEntry]] +): + root: List[BridgeInterfaceDeletedResourceEntry] + + +BridgeInterfaceMetadata = BridgeDomainMetadata + + +class DHCPRelaySpec(BaseModel): + """ + The DHCPRelay enables the forwarding of DHCP requests and responses between clients and servers across different networks. This resource allows for the configuration of various DHCP relay sub-options, such as CircuitID, RemoteID, and ClientLinkLayerAddress, to provide detailed client information. It also includes settings for specifying the router to reach the DHCP server, the list of DHCP servers to forward requests to, and selectors for Routed and IRB interfaces where the relay will be configured. Additionally, the GI Address option can be set to derive the Gateway IP address from the selected interface, ensuring correct routing of DHCP messages. + """ + + giAddress: Annotated[ + Optional[bool], + Field( + description="Set GI Address to the IP derived from the IRBInterface or RoutedInterface on which the DHCP relay is configured.", + title="Use GI Address", + ), + ] = None + irbInterfaceSelector: Annotated[ + Optional[List[str]], + Field( + description="Label selector to select the IRBInterface on which to configure the DHCP relay.", + title="IRB Interface Selector", + ), + ] = None + routedInterfaceSelector: Annotated[ + Optional[List[str]], + Field( + description="Label selector to select the RoutedInterface on which to configure the DHCP relay.", + title="Routed Interface Selector", + ), + ] = None + router: Annotated[ + Optional[str], + Field( + description="Router to be used to reach the DHCP server, if not specified the Router under which the source IRBInterface or RoutedInterface resides will be used.", + title="Router", + ), + ] = None + servers: Annotated[ + List[str], + Field( + description="List of servers to send the DHCP relayed packet to. These can be IP addresses or FQDN.", + min_length=1, + title="Servers", + ), + ] + subOptions: Annotated[ + Optional[List[str]], + Field( + description="DHCP Relay sub-options; available options are CircuitID, RemoteID, and ClientLinkLayerAddress.", + title="Sub Options", + ), + ] = None + + +DHCPRelayDeletedResourceEntry = BridgeDomainDeletedResourceEntry + + +class DHCPRelayDeletedResources(RootModel[List[DHCPRelayDeletedResourceEntry]]): + root: List[DHCPRelayDeletedResourceEntry] + + +DHCPRelayMetadata = BridgeDomainMetadata + + +class EdgePingSpec(BaseModel): + """ + EdgePingSpec defines the desired state of EdgePing + """ + + destination: Annotated[Optional[str], Field(title="destination")] = None + interfaceResource: Annotated[Optional[str], Field(title="interfaceresource")] = None + pingType: Annotated[Literal["gateway", "edgemesh", "edge"], Field(title="pingtype")] + virtualNetwork: Annotated[Optional[str], Field(title="virtualnetwork")] = None + vlanID: Annotated[Optional[int], Field(title="vlanid")] = None + + +class EdgePingStatus(BaseModel): + """ + EdgePingStatus defines the observed state of EdgePing + """ + + id: Annotated[Optional[int], Field(description="Id", title="ID")] = None + result: Annotated[ + Optional[str], Field(description="Aggregate result of the Flow", title="Result") + ] = None + + +EdgePingMetadata = BridgeDomainMetadata + + +class IRBInterfaceSpecBfd(BaseModel): + """ + Enable BFD on the IRBInterface. + """ + + desiredMinTransmitInt: Annotated[ + Optional[int], + Field( + description="The minimum interval in microseconds between transmission of BFD control packets.", + ge=10000, + le=100000000, + title="Transmit Interval", + ), + ] = 1000000 + detectionMultiplier: Annotated[ + Optional[int], + Field( + description="The number of packets that must be missed to declare this session as down.", + ge=3, + le=20, + title="Multiplier", + ), + ] = 3 + enabled: Annotated[ + bool, Field(description="Enables Biforward Detection.", title="Enabled") + ] + minEchoReceiveInterval: Annotated[ + Optional[int], + Field( + description="The minimum interval between echo packets the local node can receive.", + ge=0, + le=100000000, + title="Minimum Echo Receive Interval", + ), + ] = 0 + requiredMinReceive: Annotated[ + Optional[int], + Field( + description="The minimum interval in microseconds between received BFD control packets that this system should support.", + ge=10000, + le=100000000, + title="Receive Interval", + ), + ] = 1000000 + ttl: Annotated[ + Optional[int], + Field( + description="Sets custom IP TTL or Hop Limit for multi-hop BFD sessions packets. Not appllicable to single-hop BFD sessions.", + ge=2, + le=255, + title="IP TTL/Hop Limit", + ), + ] = None + + +IRBInterfaceSpecEgress = BridgeInterfaceSpecEgress + + +class IRBInterfaceSpecEvpnRouteAdvertisementType(BaseModel): + """ + Controls the type of ARP/ND entries to advertise. + """ + + arpDynamic: Annotated[ + Optional[bool], + Field( + description="Advertise dynamic ARP entries.", title="Advertise Dynamic ARP" + ), + ] = False + arpStatic: Annotated[ + Optional[bool], + Field( + description="Advertise static ARP entries.", title="Advertise Static ARP" + ), + ] = False + ndDynamic: Annotated[ + Optional[bool], + Field( + description="Advertise dynamic ND entries.", title="Advertise Dynamic ND" + ), + ] = False + ndStatic: Annotated[ + Optional[bool], + Field(description="Advertise static ND entries.", title="Advertise Static ND"), + ] = False + + +class IRBInterfaceSpecHostRoutePopulate(BaseModel): + """ + Configures host route population based on ARP entries. + """ + + dynamic: Annotated[ + Optional[bool], + Field( + description="Create host routes out of dynamic ARP entries.", + title="Dynamic ARP Entries", + ), + ] = True + evpn: Annotated[ + Optional[bool], + Field( + description="Create host routes out of EVPN learned ARP entries.", + title="EVPN Learned ARP Entries", + ), + ] = False + static: Annotated[ + Optional[bool], + Field( + description="Create host routes out of static ARP entries.", + title="Static ARP Entries", + ), + ] = True + + +IRBInterfaceSpecIngress = BridgeInterfaceSpecIngress + + +class IRBInterfaceSpecIpAddressIpv4Address(BaseModel): + """ + IPv4 address in IP/mask form, e.g., 192.168.0.1/24. + """ + + ipPrefix: Annotated[ + str, Field(description="Address and mask to use", title="IP Prefix") + ] + primary: Annotated[ + Optional[bool], + Field( + description="Indicates which address to use as primary for broadcast", + title="Primary", + ), + ] = None + + +class IRBInterfaceSpecIpAddressIpv6Address(BaseModel): + """ + IPv6 address in IP/mask form, e.g., fc00::1/120. + """ + + ipPrefix: Annotated[ + str, Field(description="Address and mask to use", title="IP Prefix") + ] + primary: Annotated[ + Optional[bool], + Field( + description="Indicates which address to use as primary for broadcast", + title="Primary", + ), + ] = None + + +class IRBInterfaceSpecIpAddress(BaseModel): + ipv4Address: Annotated[ + Optional[IRBInterfaceSpecIpAddressIpv4Address], + Field( + description="IPv4 address in IP/mask form, e.g., 192.168.0.1/24.", + title="IPv4 Addresses", + ), + ] = None + ipv6Address: Annotated[ + Optional[IRBInterfaceSpecIpAddressIpv6Address], + Field( + description="IPv6 address in IP/mask form, e.g., fc00::1/120.", + title="IPv6 Addresses", + ), + ] = None + node: Annotated[ + Optional[str], + Field( + description="Reference to a TopoNode resource, if not specified the IP address will be assigned to all nodes on which the IRB is deployed. If specified the IP address will be assigned to the specified node.", + title="Node", + ), + ] = None + + +class IRBInterfaceSpecIpv4Parameters(BaseModel): + directedBroadcast: Annotated[ + Optional[bool], + Field( + description="Allow receiving and forwarding of directed broadcast packets. Enabled when set to true.", + title="Directed Broadcast", + ), + ] = None + + +class IRBInterfaceSpecIpv6RouterAdvertisementPrefix(BaseModel): + """ + IPv6Prefix defines the configuration for an IPv6 prefix advertisement. + """ + + autonomousFlag: Annotated[ + Optional[bool], + Field( + description="When this is set in the prefix information option hosts can use the prefix for stateless address autoconfiguration (SLAAC).", + title="Autonomous Flag", + ), + ] = True + onLinkFlag: Annotated[ + Optional[bool], + Field( + description="When this is set in the prefix information option hosts can use the prefix for on-link determination.", + title="On-Link Flag", + ), + ] = True + preferredLifetime: Annotated[ + Optional[int], + Field( + description="The length of time in seconds (relative to the time the packet is sent) that addresses generated from the prefix via stateless address autoconfiguration remain preferred.", + ge=0, + le=4294967295, + title="Preferred Lifetime", + ), + ] = 604800 + prefix: Annotated[ + str, + Field( + description="An IPv6 global unicast address prefix.", title="IPv6 Prefix" + ), + ] + validLifetime: Annotated[ + Optional[int], + Field( + description="The length of time in seconds (relative to the time the packet is sent) that the prefix is valid for the purpose of on-link determination.", + ge=0, + le=4294967295, + title="Valid Lifetime", + ), + ] = 2592000 + + +class IRBInterfaceSpecIpv6RouterAdvertisement(BaseModel): + currentHopLimit: Annotated[ + int, + Field( + description="The current hop limit to advertise in the router advertisement messages.", + ge=0, + le=255, + title="Current Hop Limit", + ), + ] + enabled: Annotated[ + bool, + Field( + description="Enable or disable IPv6 router advertisements.", + title="Enable Router Advertisements", + ), + ] + ipMTU: Annotated[ + Optional[int], + Field( + description="The IP MTU to advertise in the router advertisement messages.", + ge=1280, + le=9486, + title="IP MTU", + ), + ] = None + managedConfigurationFlag: Annotated[ + bool, + Field( + description="Enable DHCPv6 for address configuration (M-bit).", + title="Managed Configuration Flag", + ), + ] + maxAdvertisementInterval: Annotated[ + int, + Field( + description="Maximum time between router advertisements (in seconds).", + ge=4, + le=1800, + title="Maximum Advertisement Interval", + ), + ] + minAdvertisementInterval: Annotated[ + int, + Field( + description="Minimum time between router advertisements (in seconds).", + ge=3, + le=1350, + title="Minimum Advertisement Interval", + ), + ] + otherConfigurationFlag: Annotated[ + bool, + Field( + description="Enable DHCPv6 for other configuration (O-bit).", + title="Other Configuration Flag", + ), + ] + prefixes: Annotated[ + Optional[List[IRBInterfaceSpecIpv6RouterAdvertisementPrefix]], + Field( + description="IPv6 prefixes to advertise in router advertisements.", + title="Prefixes", + ), + ] = None + reachableTime: Annotated[ + Optional[int], + Field( + description="Time in milliseconds for Neighbor Unreachability Detection.", + ge=0, + le=3600000, + title="Reachable Time", + ), + ] = 0 + retransmitTime: Annotated[ + int, + Field( + description="Time in milliseconds between retransmitted NS messages.", + ge=0, + le=1800000, + title="Retransmit Time", + ), + ] + routerLifetime: Annotated[ + int, + Field( + description="Router lifetime in seconds for default gateway.", + ge=0, + le=9000, + title="Router Lifetime", + ), + ] + + +class IRBInterfaceSpecL3ProxyARPND(BaseModel): + """ + L3 Proxy ARP and ND configuration. + """ + + proxyARP: Annotated[ + Optional[bool], + Field( + description="Select whether Proxy ARP should be enabled.", + title="Proxy ARP Enabled", + ), + ] = False + proxyND: Annotated[ + Optional[bool], + Field( + description="Select whether Proxy ND should be enabled.", + title="Proxy ND Enabled", + ), + ] = False + + +class IRBInterfaceSpecVirtualIPDiscoveryItem(BaseModel): + address: Annotated[str, Field(description="Virtual IP Address.", title="Address")] + allowedMAC: Annotated[ + Optional[List[str]], + Field( + description="List of allowed MAC addresses for a discovered virtual IP address.", + title="Allowed MAC Addresses", + ), + ] = None + bridgeInterfaceToProbe: Annotated[ + Optional[List[str]], + Field( + description="List of BridgeInterfaces on the associated MAC-VRF to which the ARP probes are sent. If left blank, the probes are sent on all BridgeInterfaces associated with the BridgeDomain.", + title="Bridge Interfaces to Probe", + ), + ] = None + probeInterval: Annotated[ + Optional[int], + Field( + description="ARP probe interval in seconds.", + ge=0, + le=86400, + title="Probe Interval", + ), + ] = 0 + vlanToProbe: Annotated[ + Optional[List[str]], + Field( + description="List of VLANs on the associated BridgeDomain to which the ARP probes are sent. If left blank, the probes are sent on all VLANs associated with the BridgeDomain.", + title="VLANs to Probe", + ), + ] = None + + +class IRBInterfaceSpec(BaseModel): + """ + The IRBInterface enables the configuration and management of Layer 3 interfaces associated with a BridgeDomain. This resource allows for the specification of various parameters, including IP MTU, learning of unsolicited ARPs, IPv4 and IPv6 addresses, and unnumbered interface settings. It also supports advanced features such as BFD configuration, Virtual IP discovery, and ARP/ND-related settings like Proxy ARP/ND and EVPN route advertisement. + """ + + anycastGatewayMAC: Annotated[ + Optional[str], + Field( + description="The gateway MAC to use on the anycast address, if left empty the node will automatically assign one.", + title="Anycast GW MAC", + ), + ] = None + arpTimeout: Annotated[ + Optional[int], + Field( + description="Duration of time that dynamic ARP entries remain in the ARP cache before they expire.", + title="ARP Timeout", + ), + ] = 14400 + bfd: Annotated[ + Optional[IRBInterfaceSpecBfd], + Field(description="Enable BFD on the IRBInterface.", title="BFD Configuration"), + ] = None + bridgeDomain: Annotated[ + str, Field(description="Reference to a BridgeDomain.", title="Bridge Domain") + ] + description: Annotated[ + Optional[str], + Field(description="The description of the IRBInterface.", title="Description"), + ] = None + egress: Annotated[ + Optional[IRBInterfaceSpecEgress], + Field( + description="Manages actions on traffic at Egress.", title="Egress Actions" + ), + ] = None + evpnRouteAdvertisementType: Annotated[ + Optional[IRBInterfaceSpecEvpnRouteAdvertisementType], + Field( + description="Controls the type of ARP/ND entries to advertise.", + title="EVPN Route Advertisement Type", + ), + ] = None + hostRoutePopulate: Annotated[ + Optional[IRBInterfaceSpecHostRoutePopulate], + Field( + description="Configures host route population based on ARP entries.", + title="Host Route Population", + ), + ] = None + ingress: Annotated[ + Optional[IRBInterfaceSpecIngress], + Field( + description="Manages actions on traffic at Ingress.", + title="Ingress Actions", + ), + ] = None + ipAddresses: Annotated[ + Optional[List[IRBInterfaceSpecIpAddress]], Field(title="IP Addresses") + ] = None + ipMTU: Annotated[ + Optional[int], + Field( + description="IP MTU for the IRBInterface [default=1500].", + ge=1280, + le=9486, + title="IP MTU", + ), + ] = 1500 + ipv4Parameters: Annotated[ + Optional[IRBInterfaceSpecIpv4Parameters], + Field(title="IPv4-specific Parameters"), + ] = None + ipv6RouterAdvertisement: Annotated[ + Optional[IRBInterfaceSpecIpv6RouterAdvertisement], + Field(title="IPv6 Router Advertisement"), + ] = None + l3ProxyARPND: Annotated[ + Optional[IRBInterfaceSpecL3ProxyARPND], + Field( + description="L3 Proxy ARP and ND configuration.", title="L3 Proxy ARP/ND" + ), + ] = None + learnUnsolicited: Annotated[ + Optional[Literal["BOTH", "GLOBAL", "LINK-LOCAL", "NONE"]], + Field( + description="Enable or disable learning of unsolicited ARPs.", + title="Learn Unsolicited ARPs", + ), + ] = "NONE" + router: Annotated[str, Field(description="Reference to a Router.", title="Router")] + unnumbered: Annotated[ + Optional[Literal["IPV6"]], + Field( + description="Enables the use of unnumbered interfaces on the IRBInterface. If IPv6 is specified, no IP address are configured on the sub-interface and only the link local address will be used. If any IP addresses are specified for either IPv4 or IPv6 that will take precedence and IPs will be assigned to the interfaces.(Deprecated, Use IPv6RouterAdvertisement)", + title="Unnumbered", + ), + ] = None + virtualIPDiscovery: Annotated[ + Optional[List[IRBInterfaceSpecVirtualIPDiscoveryItem]], + Field( + description="Configuration for Virtual IP discovery on the interface.", + title="Virtual IP Discovery", + ), + ] = None + + +class IRBInterfaceStatusInterfaceIpv4Address(BaseModel): + ipPrefix: Annotated[ + str, Field(description="Address and mask to use", title="IP Prefix") + ] + primary: Annotated[ + Optional[bool], + Field( + description="Indicates which address to use as primary for broadcast", + title="Primary", + ), + ] = None + + +IRBInterfaceStatusInterfaceIpv6Address = IRBInterfaceStatusInterfaceIpv4Address + + +class IRBInterfaceStatusInterface(BaseModel): + enabled: Annotated[ + Optional[bool], + Field( + description="Administrative status of the SubInterface.", title="Enabled" + ), + ] = None + ipv4Addresses: Annotated[ + Optional[List[IRBInterfaceStatusInterfaceIpv4Address]], + Field(description="List of IPv4 addresses", title="IPv4 Addresses"), + ] = None + ipv6Addresses: Annotated[ + Optional[List[IRBInterfaceStatusInterfaceIpv6Address]], + Field(description="List of IPv6 addresses", title="IPv6 Addresses"), + ] = None + lastChange: Annotated[ + Optional[str], + Field( + description="Timestamp of when this SubInterface last changed state.", + title="Last Change", + ), + ] = None + node: Annotated[str, Field(description="Reference to Node object.", title="Node")] + nodeInterface: Annotated[ + str, Field(description="Node specific interface name.", title="Node Interface") + ] + operatingSystem: Annotated[ + Optional[str], + Field(description="Operating System of the Node.", title="Operating System"), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Current operational state of the SubInterface.", + title="Operational State", + ), + ] = None + + +class IRBInterfaceStatus(BaseModel): + """ + IRBInterfaceStatus defines the observed state of IRBInterface + """ + + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the VNET.", title="Health Score" + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Explains the reason for the health score.", + title="Health Score Reason", + ), + ] = None + interfaces: Annotated[ + Optional[List[IRBInterfaceStatusInterface]], + Field( + description="Details of the interfaces associated with the IRB.", + title="Interface Statuses", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field(description="Timestamp of the last state change.", title="Last Change"), + ] = None + operationalState: Annotated[ + Optional[str], + Field(description="Operational state of the VNET.", title="Operational State"), + ] = None + + +IRBInterfaceDeletedResourceEntry = BridgeDomainDeletedResourceEntry + + +class IRBInterfaceDeletedResources(RootModel[List[IRBInterfaceDeletedResourceEntry]]): + root: List[IRBInterfaceDeletedResourceEntry] + + +IRBInterfaceMetadata = BridgeDomainMetadata + + +class RoutedInterfaceSpecBfd(BaseModel): + """ + Enables BFD on the RoutedInterface. + """ + + desiredMinTransmitInt: Annotated[ + Optional[int], + Field( + description="The minimum interval in microseconds between transmission of BFD control packets.", + ge=10000, + le=100000000, + title="Transmit Interval", + ), + ] = 1000000 + detectionMultiplier: Annotated[ + Optional[int], + Field( + description="The number of packets that must be missed to declare this session as down.", + ge=3, + le=20, + title="Multiplier", + ), + ] = 3 + enabled: Annotated[ + bool, Field(description="Enables Biforward Detection.", title="Enabled") + ] + minEchoReceiveInterval: Annotated[ + Optional[int], + Field( + description="The minimum interval between echo packets the local node can receive.", + ge=0, + le=100000000, + title="Minimum Echo Receive Interval", + ), + ] = 0 + requiredMinReceive: Annotated[ + Optional[int], + Field( + description="The minimum interval in microseconds between received BFD control packets that this system should support.", + ge=10000, + le=100000000, + title="Receive Interval", + ), + ] = 1000000 + ttl: Annotated[ + Optional[int], + Field( + description="Sets custom IP TTL or Hop Limit for multi-hop BFD sessions packets. Not appllicable to single-hop BFD sessions.", + ge=2, + le=255, + title="IP TTL/Hop Limit", + ), + ] = None + + +RoutedInterfaceSpecEgress = BridgeInterfaceSpecEgress + + +RoutedInterfaceSpecIngress = BridgeInterfaceSpecIngress + + +RoutedInterfaceSpecIpv4Address = IRBInterfaceStatusInterfaceIpv4Address + + +RoutedInterfaceSpecIpv4Parameters = IRBInterfaceSpecIpv4Parameters + + +RoutedInterfaceSpecIpv6Address = IRBInterfaceStatusInterfaceIpv4Address + + +RoutedInterfaceSpecIpv6RouterAdvertisementPrefix = ( + IRBInterfaceSpecIpv6RouterAdvertisementPrefix +) + + +class RoutedInterfaceSpecIpv6RouterAdvertisement(BaseModel): + currentHopLimit: Annotated[ + int, + Field( + description="The current hop limit to advertise in the router advertisement messages.", + ge=0, + le=255, + title="Current Hop Limit", + ), + ] + enabled: Annotated[ + bool, + Field( + description="Enable or disable IPv6 router advertisements.", + title="Enable Router Advertisements", + ), + ] + ipMTU: Annotated[ + Optional[int], + Field( + description="The IP MTU to advertise in the router advertisement messages.", + ge=1280, + le=9486, + title="IP MTU", + ), + ] = None + managedConfigurationFlag: Annotated[ + bool, + Field( + description="Enable DHCPv6 for address configuration (M-bit).", + title="Managed Configuration Flag", + ), + ] + maxAdvertisementInterval: Annotated[ + int, + Field( + description="Maximum time between router advertisements (in seconds).", + ge=4, + le=1800, + title="Maximum Advertisement Interval", + ), + ] + minAdvertisementInterval: Annotated[ + int, + Field( + description="Minimum time between router advertisements (in seconds).", + ge=3, + le=1350, + title="Minimum Advertisement Interval", + ), + ] + otherConfigurationFlag: Annotated[ + bool, + Field( + description="Enable DHCPv6 for other configuration (O-bit).", + title="Other Configuration Flag", + ), + ] + prefixes: Annotated[ + Optional[List[RoutedInterfaceSpecIpv6RouterAdvertisementPrefix]], + Field( + description="IPv6 prefixes to advertise in router advertisements.", + title="Prefixes", + ), + ] = None + reachableTime: Annotated[ + Optional[int], + Field( + description="Time in milliseconds for Neighbor Unreachability Detection.", + ge=0, + le=3600000, + title="Reachable Time", + ), + ] = 0 + retransmitTime: Annotated[ + int, + Field( + description="Time in milliseconds between retransmitted NS messages.", + ge=0, + le=1800000, + title="Retransmit Time", + ), + ] + routerLifetime: Annotated[ + int, + Field( + description="Router lifetime in seconds for default gateway.", + ge=0, + le=9000, + title="Router Lifetime", + ), + ] + + +RoutedInterfaceSpecL3ProxyARPND = IRBInterfaceSpecL3ProxyARPND + + +class RoutedInterfaceSpec(BaseModel): + """ + The RoutedInterface enables the configuration and management of Layer 3 interfaces for routing traffic between different networks. This resource allows for specifying an underlying Interface and Router, configuring VLAN IDs, and setting the IP MTU. It also supports the learning of unsolicited ARPs, defining both IPv4 and IPv6 addresses, and enabling unnumbered interfaces. Advanced features such as BFD configuration, Proxy ARP/ND, and ARP timeout settings are included to ensure robust and efficient routing. + """ + + arpTimeout: Annotated[ + Optional[int], + Field( + description="Duration of time that dynamic ARP entries remain in the ARP cache before they expire.", + title="ARP Timeout", + ), + ] = 14400 + bfd: Annotated[ + Optional[RoutedInterfaceSpecBfd], + Field( + description="Enables BFD on the RoutedInterface.", title="BFD Configuration" + ), + ] = None + description: Annotated[ + Optional[str], + Field( + description="The description of the RoutedInterface.", title="Description" + ), + ] = None + egress: Annotated[ + Optional[RoutedInterfaceSpecEgress], + Field( + description="Manages actions on traffic at Egress.", title="Egress Actions" + ), + ] = None + ingress: Annotated[ + Optional[RoutedInterfaceSpecIngress], + Field( + description="Manages actions on traffic at Ingress.", + title="Ingress Actions", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to an Interface to use for attachment.", + title="Interface", + ), + ] + ipMTU: Annotated[ + Optional[int], + Field( + description="IP MTU for the RoutedInterface.", + ge=1280, + le=9486, + title="IP MTU", + ), + ] = 1500 + ipv4Addresses: Annotated[ + Optional[List[RoutedInterfaceSpecIpv4Address]], + Field( + description="List of IPv4 addresses in IP/mask form, e.g., 192.168.0.1/24.", + title="IPv4 Addresses", + ), + ] = None + ipv4Parameters: Annotated[ + Optional[RoutedInterfaceSpecIpv4Parameters], + Field(title="IPv4-specific Parameters"), + ] = None + ipv6Addresses: Annotated[ + Optional[List[RoutedInterfaceSpecIpv6Address]], + Field( + description="List of IPv6 addresses in IP/mask form, e.g., fc00::1/120.", + title="IPv6 Addresses", + ), + ] = None + ipv6RouterAdvertisement: Annotated[ + Optional[RoutedInterfaceSpecIpv6RouterAdvertisement], + Field(title="IPv6 Router Advertisement"), + ] = None + l3ProxyARPND: Annotated[ + Optional[RoutedInterfaceSpecL3ProxyARPND], + Field( + description="L3 Proxy ARP and ND configuration.", title="L3 Proxy ARP/ND" + ), + ] = None + learnUnsolicited: Annotated[ + Optional[Literal["BOTH", "GLOBAL", "LINK-LOCAL", "NONE"]], + Field( + description="Enable or disable learning of unsolicited ARPs.", + title="Learn Unsolicited ARPs", + ), + ] = "NONE" + router: Annotated[str, Field(description="Reference to a Router.", title="Router")] + unnumbered: Annotated[ + Optional[Literal["IPV6"]], + Field( + description="Enables the use of unnumbered interfaces on the IRBInterface. If IPv6 is specified, no IP address are configured on the sub-interface and only the link local address will be used. If any IP addresses are specified for either IPv4 or IPv6 that will take precedence and IPs will be assigned to the interfaces. (Deprecated, Use IPv6RouterAdvertisement)", + title="Unnumbered", + ), + ] = None + vlanID: Annotated[ + Optional[str], + Field( + description="Single value between 1-4094 support, ranges supported in the format x-y,x-y, or the special keyword null, any, untagged or pool for auto allocation.", + title="VLAN ID", + ), + ] = "pool" + vlanPool: Annotated[ + Optional[str], + Field( + description="Reference to a VLAN pool to use for allocations.", + title="VLAN Pool", + ), + ] = "vlan-pool" + + +RoutedInterfaceStatusInterface = BridgeInterfaceStatusSubInterface + + +class RoutedInterfaceStatus(BaseModel): + """ + RoutedInterfaceStatus defines the observed state of RoutedInterface + """ + + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the RoutedInterface.", + title="Health Score", + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + interfaces: Annotated[ + Optional[List[RoutedInterfaceStatusInterface]], + Field( + description="Sub-interface status within the RoutedInterface.", + title="Sub-Interfaces Status", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the RoutedInterface.", + title="Operational State", + ), + ] = None + + +RoutedInterfaceDeletedResourceEntry = BridgeDomainDeletedResourceEntry + + +class RoutedInterfaceDeletedResources( + RootModel[List[RoutedInterfaceDeletedResourceEntry]] +): + root: List[RoutedInterfaceDeletedResourceEntry] + + +RoutedInterfaceMetadata = BridgeDomainMetadata + + +class RouterSpecBgpIpAliasNexthop(BaseModel): + esi: Annotated[ + Optional[str], + Field( + description="10 byte Ethernet Segment Identifier, if not set a type 0 ESI is generated.", + title="ESI", + ), + ] = "auto" + nextHop: Annotated[ + str, + Field( + description="The nexthop IP address to track for the IP alias.", + title="IP Alias Address", + ), + ] + preferredActiveNode: Annotated[ + Optional[str], + Field( + description="When not set the ES is used in an all active mode. This references the ToppNode object and when set, the DF algorithm is configured to type preference and the selected Node is set with a higher preference value. All other Nodes have a lower value configured.", + title="Preferred Active Node", + ), + ] = None + + +class RouterSpecBgpIpv4UnicastMultipath(BaseModel): + """ + Enable multipath. + """ + + allowMultipleAS: Annotated[ + bool, + Field( + description="When set to true, BGP is allowed to build a multipath set using BGP routes with different neighbor AS (most recent AS in the AS_PATH), When set to false, BGP is only allowed to use non-best paths for ECMP if they meet the multipath criteria and they have the same neighbor AS as the best path.", + title="Allow Multiple Autonomous Systems Per Path", + ), + ] + maxAllowedPaths: Annotated[ + int, + Field( + description="The maximum number of BGP ECMP next-hops for BGP routes with an NLRI belonging to the address family of this configuration context.", + ge=1, + le=256, + title="Maximum Number of Paths", + ), + ] + + +class RouterSpecBgpIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + bool, Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled") + ] + multipath: Annotated[ + Optional[RouterSpecBgpIpv4UnicastMultipath], + Field(description="Enable multipath.", title="Multipath"), + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +class RouterSpecBgpIpv6UnicastMultipath(BaseModel): + """ + Enable multipath + """ + + allowMultipleAS: Annotated[ + bool, + Field( + description="When set to true, BGP is allowed to build a multipath set using BGP routes with different neighbor AS (most recent AS in the AS_PATH), When set to false, BGP is only allowed to use non-best paths for ECMP if they meet the multipath criteria and they have the same neighbor AS as the best path.", + title="Allow Multiple Autonomous Systems Per Path", + ), + ] + maxAllowedPaths: Annotated[ + int, + Field( + description="The maximum number of BGP ECMP next-hops for BGP routes with an NLRI belonging to the address family of this configuration context.", + ge=1, + le=256, + title="Maximum Number of Paths", + ), + ] + + +class RouterSpecBgpIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + bool, Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled") + ] + multipath: Annotated[ + Optional[RouterSpecBgpIpv6UnicastMultipath], + Field(description="Enable multipath", title="Multipath"), + ] = None + + +class RouterSpecBgp(BaseModel): + """ + BGP configuration. + """ + + autonomousSystem: Annotated[ + Optional[int], + Field( + description="Autonomous System number for BGP.", + ge=1, + le=4294967295, + title="Autonomous System", + ), + ] = None + ebgpPreference: Annotated[ + Optional[int], + Field( + description="Preference to be set for eBGP [default=170].", + ge=1, + le=255, + title="eBGP Preference", + ), + ] = 170 + enabled: Annotated[ + Optional[bool], Field(description="Enable or disable BGP.", title="Enable BGP") + ] = False + ibgpPreference: Annotated[ + Optional[int], + Field( + description="Preference to be set for iBGP [default=170].", + ge=1, + le=255, + title="iBGP Preference", + ), + ] = 170 + ipAliasNexthops: Annotated[ + Optional[List[RouterSpecBgpIpAliasNexthop]], + Field(description="IP aliasing configuration.", title="IP Alias Nexthops"), + ] = None + ipv4Unicast: Annotated[ + Optional[RouterSpecBgpIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[RouterSpecBgpIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field(description="Keychain to be used for authentication", title="Keychain"), + ] = None + minWaitToAdvertise: Annotated[ + Optional[int], + Field( + description="Minimum wait time before advertising routes post BGP restart.", + ge=0, + le=3600, + title="Min Wait To Advertise Time", + ), + ] = 0 + rapidWithdrawl: Annotated[ + Optional[bool], + Field( + description="Enable rapid withdrawal in BGP.", + title="Enable Rapid Withdrawal", + ), + ] = True + waitForFIBInstall: Annotated[ + Optional[bool], + Field( + description="Wait for FIB installation before advertising routes.", + title="Wait for FIB Installation", + ), + ] = False + + +class RouterSpecIpLoadBalancingPrefixItem(BaseModel): + hashBucketsPerPath: Annotated[ + int, + Field( + description="The number of times each next-hop is repeated in the fill pattern if there are max-paths ECMP next-hops.", + ge=1, + le=32, + title="Max Paths", + ), + ] + maxECMP: Annotated[ + int, + Field( + description="The maximum number of ECMP next-hops per route associated with the resilient-hash prefix.", + ge=1, + le=64, + title="Max ECMP", + ), + ] + prefix: Annotated[ + str, + Field( + description="IPv4 or IPv6 prefix. Active routes in the FIB that exactly match this prefix or that are longer matches of this prefix are provided with resilient-hash programming.", + title="Prefix", + ), + ] + + +class RouterSpecIpLoadBalancing(BaseModel): + """ + IPv4 or IPv6 prefix. Active routes in the FIB that exactly match this prefix or that are longer matches of this prefix are provided with resilient-hash programming. + """ + + prefix: Annotated[ + Optional[List[RouterSpecIpLoadBalancingPrefixItem]], + Field( + description="IPv4 or IPv6 prefix. Active routes in the FIB that exactly match this prefix or that are longer matches of this prefix are provided with resilient-hash programming.", + title="Prefix", + ), + ] = None + + +class RouterSpecRouteLeaking(BaseModel): + """ + Route leaking controlled by routing policies in and out of the DefaultRouter. + """ + + exportPolicy: Annotated[ + Optional[str], + Field( + description="Reference to a Policy resource to use when evaluating route exports from the DefaultRouter.", + title="Export Policy", + ), + ] = None + importPolicy: Annotated[ + Optional[str], + Field( + description="Reference to a Policy resource to use when evaluating route imports into the DefaultRouter.", + title="Import Policy", + ), + ] = None + + +class RouterSpec(BaseModel): + """ + The Router enables the configuration and management of routing functions within a network. This resource allows for setting a unique Router ID, configuring VNIs and EVIs with options for automatic allocation, and defining import and export route targets. It also includes advanced configuration options such as BGP settings, including autonomous system numbers, AFI/SAFI options, and route advertisement preferences. Node selectors can be used to constrain the deployment of the router to specific nodes within the network. + """ + + bgp: Annotated[ + Optional[RouterSpecBgp], + Field(description="BGP configuration.", title="BGP Configuration"), + ] = None + description: Annotated[ + Optional[str], + Field(description="The description of the Router.", title="Description"), + ] = None + evi: Annotated[ + Optional[int], + Field( + description="EVI for the Router; leave blank for auto-allocation from EVI pool.", + ge=1, + le=65535, + title="EVI", + ), + ] = None + eviPool: Annotated[ + Optional[str], + Field( + description="Reference to EVI pool for auto-allocation.", + title="EVI Allocation Pool", + ), + ] = "evi-pool" + exportTarget: Annotated[ + Optional[str], + Field( + description="Export route target in 'target:N:N' format, if not specified, the default value taken as \"target:1:\".", + pattern="^target.*$", + title="Export Target", + ), + ] = None + importTarget: Annotated[ + Optional[str], + Field( + description="Import route target in 'target:N:N' format, if not specified, the default value taken as \"target:1:\".", + pattern="^target.*$", + title="Import Target", + ), + ] = None + ipLoadBalancing: Annotated[ + Optional[RouterSpecIpLoadBalancing], + Field( + description="IPv4 or IPv6 prefix. Active routes in the FIB that exactly match this prefix or that are longer matches of this prefix are provided with resilient-hash programming.", + title="Prefix", + ), + ] = None + nodeSelector: Annotated[ + Optional[List[str]], + Field( + description="Node selectors for deployment constraints. If Nodes are selected, the Router will only be deployed on the Nodes selected, if left blank it will be deployed on all Nodes for which there are IRB or RoutedInterfaces referencing this Router.", + title="Node Selector", + ), + ] = None + routeLeaking: Annotated[ + Optional[RouterSpecRouteLeaking], + Field( + description="Route leaking controlled by routing policies in and out of the DefaultRouter.", + title="Route Leaking", + ), + ] = None + routerID: Annotated[ + Optional[str], Field(description="Router ID.", title="Router ID") + ] = None + tunnelIndexPool: Annotated[ + Optional[str], + Field( + description="Reference to tunnel index allocation pool.", + title="Tunnel Index Pool", + ), + ] = "tunnel-index-pool" + type: Annotated[ + Optional[Literal["SIMPLE", "EVPNVXLAN"]], + Field( + description="Select the type of Router. Simple doesn't include any overlay control plane or dataplane properties (EVPN/VXLAN). EVPNVXLAN includes the properties needed to provision this Router over an IP Fabric.", + title="Type", + ), + ] = "EVPNVXLAN" + vni: Annotated[ + Optional[int], + Field( + description="VNI for the Router; leave blank for auto-allocation from VNI pool.", + ge=1, + le=16777215, + title="VNI", + ), + ] = None + vniPool: Annotated[ + Optional[str], + Field( + description="Reference to VNI pool for auto-allocation.", + title="VNI Allocation Pool", + ), + ] = "vni-pool" + + +class RouterStatus(BaseModel): + """ + RouterStatus defines the observed state of Router + """ + + bgpPeers: Annotated[ + Optional[List[str]], + Field( + description="List of BGPPeers attached to the router.", title="BGP Peers" + ), + ] = None + evi: Annotated[ + Optional[int], Field(description="EVI in use for this Router.", title="EVI") + ] = None + exportTarget: Annotated[ + Optional[str], + Field( + description="Export route target for this Router.", title="Export Target" + ), + ] = None + health: Annotated[ + Optional[int], + Field( + description="Indicates the health score of the Router.", + title="Health Score", + ), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Explains the reason for the health score.", + title="Health Score Reason", + ), + ] = None + importTarget: Annotated[ + Optional[str], + Field( + description="Import route target for this Router.", title="Import Target" + ), + ] = None + irbInterfaces: Annotated[ + Optional[List[str]], + Field( + description="List of IRBInterfaces attached to the router.", + title="IRB Interfaces", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field(description="Timestamp of the last state change.", title="Last Change"), + ] = None + nodes: Annotated[ + Optional[List[str]], + Field( + description="List of nodes on which the Router is deployed.", title="Nodes" + ), + ] = None + numNodes: Annotated[ + Optional[int], + Field( + description="Number of nodes on which the Router is configured.", + title="Number of Nodes", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field( + description="Operational state of the Router.", title="Operational State" + ), + ] = None + routedInterfaces: Annotated[ + Optional[List[str]], + Field( + description="List of RoutedInterfaces attached to the router.", + title="Routed Interfaces", + ), + ] = None + tunnelIndex: Annotated[ + Optional[int], + Field(description="Vxlan tunnel index in use.", title="Tunnel Index"), + ] = None + vni: Annotated[ + Optional[int], Field(description="VNI in use for this Router.", title="VNI") + ] = None + + +RouterDeletedResourceEntry = BridgeDomainDeletedResourceEntry + + +class RouterDeletedResources(RootModel[List[RouterDeletedResourceEntry]]): + root: List[RouterDeletedResourceEntry] + + +RouterMetadata = BridgeDomainMetadata + + +VLANSpecEgress = BridgeInterfaceSpecEgress + + +VLANSpecIngress = BridgeInterfaceSpecIngress + + +VLANSpecUplinkEgress = BridgeInterfaceSpecUplinkEgress + + +VLANSpecUplinkIngress = BridgeInterfaceSpecUplinkIngress + + +class VLANSpecUplink(BaseModel): + """ + The Uplink between your access breakout switch and your leaf switch. + """ + + egress: Annotated[ + Optional[VLANSpecUplinkEgress], + Field( + description="Manages actions on traffic at Egress of the Local enpoint of the Uplink.", + title="Egress", + ), + ] = None + ingress: Annotated[ + Optional[VLANSpecUplinkIngress], + Field( + description="Manages actions on traffic at Ingress of the Local enpoint of the Uplink.", + title="Ingress", + ), + ] = None + uplinkSelector: Annotated[ + Optional[List[str]], + Field( + description="Selects TopoLinks which connect a leaf switch to a breakout switch. This is the uplink between your access breakout switch and your leaf switch. There can only be a single TopoLink between the access breakout switch and the leaf switch, if more than one TopoLink is present between two devices the transaction will fail.", + title="Uplink Selector", + ), + ] = None + uplinkVLANID: Annotated[ + Optional[str], + Field( + description="The VLAN ID to be utilized to isolate traffic from the VLAN on the access breakout switch to the leaf switch on the selected uplink TopoLink.", + title="Uplink VLAN ID", + ), + ] = "pool" + uplinkVLANPool: Annotated[ + Optional[str], + Field( + description="A VLAN from this pool will be utilized to isolate traffic from the VLAN on the access breakout switch to the leaf switch on the selected uplink TopoLink.", + title="Uplink VLAN Pool", + ), + ] = None + + +class VLANSpec(BaseModel): + """ + The VLAN enables the configuration and management of VLAN and their association with BridgeDomains. This resource allows for specifying the associated BridgeDomain, selecting interfaces based on label selectors, and configuring VLAN IDs with options for auto-allocation from a VLAN pool. It also supports advanced configurations such as ingress and egress traffic management, and overrides for MAC Duplication Detection actions when enabled in the associated BridgeDomain. + """ + + bridgeDomain: Annotated[ + str, + Field( + description="Reference to a BridgeDomain or SimpleBridgeDomain.", + title="Bridge Domain", + ), + ] + description: Annotated[ + Optional[str], + Field(description="The description of the VLAN.", title="Description"), + ] = None + egress: Annotated[ + Optional[VLANSpecEgress], + Field(description="Manages actions on traffic at Egress.", title="Egress"), + ] = None + ingress: Annotated[ + Optional[VLANSpecIngress], + Field(description="Manages actions on traffic at Ingress.", title="Ingress"), + ] = None + interfaceSelector: Annotated[ + List[str], + Field( + description="Interfaces to use for attachment to this VLAN based on the label selector. Selects Interfaces based on their associated labels.", + title="Interface Selector", + ), + ] + l2MTU: Annotated[ + Optional[int], + Field( + description="L2 MTU specifies the maximum sized Ethernet frame that can be transmitted on the subinterface. If a frame exceeds this size it is discarded. If the l2-mtu of the subinterface exceeds the port-mtu of the associated interface, the subinterface will remain operationally down.", + ge=1450, + le=9500, + title="L2 MTU", + ), + ] = None + macDuplicationDetectionAction: Annotated[ + Optional[ + Literal["Blackhole", "OperDown", "StopLearning", "UseBridgeDomainAction"] + ], + Field( + description="If Mac Duplication Detection is enabled on the associated Bridge Domain, this property will override the MDD action set in the BridgeDomain.", + title="MAC Duplication Detection Action", + ), + ] = None + splitHorizonGroup: Annotated[ + Optional[str], + Field( + description="Name of the Split Horizon Group to be used for this VLAN. All subinterfaces within this VLAN will be members of this Split Horizon Group.", + title="Split Horizon Group", + ), + ] = None + uplink: Annotated[ + Optional[VLANSpecUplink], + Field( + description="The Uplink between your access breakout switch and your leaf switch.", + title="Uplink", + ), + ] = None + vlanID: Annotated[ + Optional[str], + Field( + description="Single value between 1-4094 support, ranges supported in the format x-y,x-y, or the special keyword null, any, untagged or pool for auto allocation.", + title="VLAN ID", + ), + ] = "pool" + vlanPool: Annotated[ + Optional[str], + Field( + description='Reference to a VLAN pool to use for allocations. [default="vlan-pool"]', + title="VLAN Pool", + ), + ] = None + + +VLANStatusSubInterface = BridgeInterfaceStatusSubInterface + + +class VLANStatus(BaseModel): + health: Annotated[ + Optional[int], + Field(description="Indicates the health score of the VNET.", title="Health"), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + numSubInterfaces: Annotated[ + Optional[int], + Field( + description="Total number of sub-interfaces configured by the VNET.", + title="Number of Sub Interfaces", + ), + ] = None + numSubInterfacesOperDown: Annotated[ + Optional[int], + Field( + description="Total number of sub-interfaces configured by the VNET which are oper-down.", + title="Number of Sub Interfaces Oper Down", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field(description="Operational state of the VNET.", title="Operational State"), + ] = None + subInterfaces: Annotated[ + Optional[List[VLANStatusSubInterface]], + Field(description="List of members in this Interface.", title="Sub Interfaces"), + ] = None + + +VLANDeletedResourceEntry = BridgeDomainDeletedResourceEntry + + +class VLANDeletedResources(RootModel[List[VLANDeletedResourceEntry]]): + root: List[VLANDeletedResourceEntry] + + +VLANMetadata = BridgeDomainMetadata + + +VirtualNetworkSpecBridgeDomainSpecL2proxyARPNDDynamicLearning = ( + BridgeDomainSpecL2proxyARPNDDynamicLearning +) + + +VirtualNetworkSpecBridgeDomainSpecL2proxyARPNDIpDuplication = ( + BridgeDomainSpecL2proxyARPNDIpDuplication +) + + +class VirtualNetworkSpecBridgeDomainSpecL2proxyARPND(BaseModel): + """ + Enables / Disabled Proxy ARP / Proxy ND. + """ + + dynamicLearning: Annotated[ + Optional[VirtualNetworkSpecBridgeDomainSpecL2proxyARPNDDynamicLearning], + Field(title="Dynamic Learning"), + ] = None + ipDuplication: Annotated[ + Optional[VirtualNetworkSpecBridgeDomainSpecL2proxyARPNDIpDuplication], + Field(title="L2 Proxy ARP/ND IP Duplication Detection"), + ] = None + proxyARP: Annotated[ + Optional[bool], Field(description="Enables proxy ARP.", title="Proxy ARP") + ] = False + proxyND: Annotated[ + Optional[bool], Field(description="Enables proxy ND.", title="Proxy ND") + ] = False + tableSize: Annotated[ + Optional[int], + Field( + description="Maximum number of entries allowed in the proxy table of the bridge domain.", + ge=1, + le=8192, + title="L2 Proxy ARP/ND Table Size", + ), + ] = 250 + + +VirtualNetworkSpecBridgeDomainSpecMacDuplicationDetection = ( + BridgeDomainSpecMacDuplicationDetection +) + + +class VirtualNetworkSpecBridgeDomainSpec(BaseModel): + """ + Specification of the BridgeDomain + """ + + description: Annotated[ + Optional[str], + Field(description="The description of the BridgeDomain.", title="Description"), + ] = None + evi: Annotated[ + Optional[int], + Field( + description="EVI to use for this BridgeDomain, can be optionally left blank to have it automatically allocated using the EVI Pool.", + ge=1, + le=65535, + title="EVI", + ), + ] = None + eviPool: Annotated[ + Optional[str], + Field( + description="Reference to an EVI pool to use for allocations if EVI is left blank.", + title="EVI Allocation Pool", + ), + ] = "evi-pool" + exportTarget: Annotated[ + Optional[str], + Field( + description="Export route target in 'target:N:N' format, if not specified, the default value taken as \"target:1:\".", + pattern="^target.*$", + title="Export Target", + ), + ] = None + importTarget: Annotated[ + Optional[str], + Field( + description="Import route target in 'target:N:N' format, if not specified, the default value taken as \"target:1:\".", + pattern="^target.*$", + title="Import Target", + ), + ] = None + l2proxyARPND: Annotated[ + Optional[VirtualNetworkSpecBridgeDomainSpecL2proxyARPND], + Field( + description="Enables / Disabled Proxy ARP / Proxy ND.", + title="L2 Proxy ARP/ND", + ), + ] = None + macAging: Annotated[ + Optional[int], + Field( + description="Configurable aging time for dynamically learned mac addresses.", + ge=60, + le=86400, + title="MAC Aging", + ), + ] = 300 + macDuplicationDetection: Annotated[ + Optional[VirtualNetworkSpecBridgeDomainSpecMacDuplicationDetection], + Field( + description="Enable or disable MAC duplication detection and resolution mechanisms.", + title="MAC Duplication Detection", + ), + ] = None + macLearning: Annotated[ + Optional[bool], + Field( + description="Enable MAC learning for this BridgeDomain.", + title="MAC Learning", + ), + ] = True + macLimit: Annotated[ + Optional[int], + Field( + description="Sets the maximum number of MAC entries accepted in the bridge table.", + ge=1, + title="MAC Limit", + ), + ] = None + tunnelIndexPool: Annotated[ + Optional[str], + Field( + description="Reference to a tunnel index pool to use for allocations.", + title="Tunnel Index Allocation Pool", + ), + ] = "tunnel-index-pool" + type: Annotated[ + Optional[Literal["SIMPLE", "EVPNVXLAN"]], + Field( + description="Select the type of BridgeDomain. Simple doesn't include any overlay control plane or dataplane properties (EVPN/VXLAN). EVPNVXLAN includes the properties needed to provision this BridgeDomain over an IP Fabric.", + title="Type", + ), + ] = "EVPNVXLAN" + vni: Annotated[ + Optional[int], + Field( + description="VNI to use for this BridgeDomain, can be optionally left blank to have it allocated using the VNI Pool.", + ge=1, + le=16777215, + title="VNI", + ), + ] = None + vniPool: Annotated[ + Optional[str], + Field( + description="Reference to a VNI pool to use for allocations if VNI is left blank.", + title="VNI Allocation Pool", + ), + ] = "vni-pool" + + +class VirtualNetworkSpecBridgeDomain(BaseModel): + name: Annotated[ + str, + Field(description="The name of the BridgeDomain.", title="Bridge Domain Name"), + ] + spec: Annotated[ + VirtualNetworkSpecBridgeDomainSpec, + Field( + description="Specification of the BridgeDomain", title="Bridge Domain Spec" + ), + ] + + +VirtualNetworkSpecBridgeInterfaceSpecEgress = BridgeInterfaceSpecEgress + + +VirtualNetworkSpecBridgeInterfaceSpecIngress = BridgeInterfaceSpecIngress + + +VirtualNetworkSpecBridgeInterfaceSpecUplinkEgress = BridgeInterfaceSpecUplinkEgress + + +VirtualNetworkSpecBridgeInterfaceSpecUplinkIngress = BridgeInterfaceSpecUplinkIngress + + +class VirtualNetworkSpecBridgeInterfaceSpecUplink(BaseModel): + """ + The Uplink between your access breakout switch and your leaf switch. + """ + + egress: Annotated[ + Optional[VirtualNetworkSpecBridgeInterfaceSpecUplinkEgress], + Field( + description="Manages actions on traffic at Egress of the Local enpoint of the Uplink.", + title="Egress", + ), + ] = None + ingress: Annotated[ + Optional[VirtualNetworkSpecBridgeInterfaceSpecUplinkIngress], + Field( + description="Manages actions on traffic at Ingress of the Local enpoint of the Uplink.", + title="Ingress", + ), + ] = None + uplinkSelector: Annotated[ + Optional[List[str]], + Field( + description="Selects TopoLinks which connect a leaf switch to a breakout switch. This is the uplink between your access breakout switch and your leaf switch. There can only be a single TopoLink between the access breakout switch and the leaf switch, if more than one TopoLink is present between two devices the transaction will fail.", + title="Uplink Selector", + ), + ] = None + uplinkVLANID: Annotated[ + Optional[str], + Field( + description="The VLAN ID to be utilized to isolate traffic from the VLAN on the access breakout switch to the leaf switch on the selected uplink TopoLink.", + title="Uplink VLAN ID", + ), + ] = "pool" + uplinkVLANPool: Annotated[ + Optional[str], + Field( + description="A VLAN from this pool will be utilized to isolate traffic from the VLAN on the access breakout switch to the leaf switch on the selected uplink TopoLink.", + title="Uplink VLAN Pool", + ), + ] = None + + +class VirtualNetworkSpecBridgeInterfaceSpec(BaseModel): + """ + Specification of the BridgeInterface + """ + + bridgeDomain: Annotated[ + str, + Field( + description="Reference to a BridgeDomain in which to attach the BridgeInterface.", + title="Bridge Domain", + ), + ] + description: Annotated[ + Optional[str], + Field( + description="The description of the BridgeInterface.", title="Description" + ), + ] = None + egress: Annotated[ + Optional[VirtualNetworkSpecBridgeInterfaceSpecEgress], + Field( + description="Manages actions on traffic at Egress.", title="Egress Actions" + ), + ] = None + ingress: Annotated[ + Optional[VirtualNetworkSpecBridgeInterfaceSpecIngress], + Field( + description="Manages actions on traffic at Ingress.", + title="Ingress Actions", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to an Interface resource to attach this BridgeInterface.", + title="Interface", + ), + ] + l2MTU: Annotated[ + Optional[int], + Field( + description="L2 MTU specifies the maximum sized Ethernet frame that can be transmitted on the subinterface. If a frame exceeds this size it is discarded. If the l2-mtu of the subinterface exceeds the port-mtu of the associated interface, the subinterface will remain operationally down.", + ge=1450, + le=9500, + title="L2 MTU", + ), + ] = None + macDuplicationDetectionAction: Annotated[ + Optional[ + Literal["Blackhole", "OperDown", "StopLearning", "UseBridgeDomainAction"] + ], + Field( + description="Override for Mac Duplication Detection action if enabled in the associated BridgeDomain.", + title="MAC Duplication Detection Action", + ), + ] = None + splitHorizonGroup: Annotated[ + Optional[str], + Field( + description="Split Horizon Group to be used for this BridgeInterface. The subinterface within this BridgeInterface will be a member of this Split Horizon Group.", + title="Split Horizon Group", + ), + ] = None + uplink: Annotated[ + Optional[VirtualNetworkSpecBridgeInterfaceSpecUplink], + Field( + description="The Uplink between your access breakout switch and your leaf switch.", + title="Uplink", + ), + ] = None + vlanID: Annotated[ + str, + Field( + description="Single value between 1-4094 support, ranges supported in the format x-y,x-y, or the special keyword null, any, untagged or pool for auto allocation.", + title="VLAN ID", + ), + ] + + +class VirtualNetworkSpecBridgeInterface(BaseModel): + name: Annotated[ + str, + Field( + description="The name of the BridgeInterface.", + title="Bridge Interface Name", + ), + ] + spec: Annotated[ + VirtualNetworkSpecBridgeInterfaceSpec, + Field( + description="Specification of the BridgeInterface", + title="Bridge Interface Spec", + ), + ] + + +VirtualNetworkSpecIrbInterfaceSpecBfd = IRBInterfaceSpecBfd + + +VirtualNetworkSpecIrbInterfaceSpecEgress = BridgeInterfaceSpecEgress + + +VirtualNetworkSpecIrbInterfaceSpecEvpnRouteAdvertisementType = ( + IRBInterfaceSpecEvpnRouteAdvertisementType +) + + +VirtualNetworkSpecIrbInterfaceSpecHostRoutePopulate = IRBInterfaceSpecHostRoutePopulate + + +VirtualNetworkSpecIrbInterfaceSpecIngress = BridgeInterfaceSpecIngress + + +VirtualNetworkSpecIrbInterfaceSpecIpAddressIpv4Address = ( + IRBInterfaceSpecIpAddressIpv4Address +) + + +VirtualNetworkSpecIrbInterfaceSpecIpAddressIpv6Address = ( + IRBInterfaceSpecIpAddressIpv6Address +) + + +class VirtualNetworkSpecIrbInterfaceSpecIpAddress(BaseModel): + ipv4Address: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecIpAddressIpv4Address], + Field( + description="IPv4 address in IP/mask form, e.g., 192.168.0.1/24.", + title="IPv4 Addresses", + ), + ] = None + ipv6Address: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecIpAddressIpv6Address], + Field( + description="IPv6 address in IP/mask form, e.g., fc00::1/120.", + title="IPv6 Addresses", + ), + ] = None + node: Annotated[ + Optional[str], + Field( + description="Reference to a TopoNode resource, if not specified the IP address will be assigned to all nodes on which the IRB is deployed. If specified the IP address will be assigned to the specified node.", + title="Node", + ), + ] = None + + +VirtualNetworkSpecIrbInterfaceSpecIpv4Parameters = IRBInterfaceSpecIpv4Parameters + + +VirtualNetworkSpecIrbInterfaceSpecIpv6RouterAdvertisementPrefix = ( + IRBInterfaceSpecIpv6RouterAdvertisementPrefix +) + + +class VirtualNetworkSpecIrbInterfaceSpecIpv6RouterAdvertisement(BaseModel): + currentHopLimit: Annotated[ + int, + Field( + description="The current hop limit to advertise in the router advertisement messages.", + ge=0, + le=255, + title="Current Hop Limit", + ), + ] + enabled: Annotated[ + bool, + Field( + description="Enable or disable IPv6 router advertisements.", + title="Enable Router Advertisements", + ), + ] + ipMTU: Annotated[ + Optional[int], + Field( + description="The IP MTU to advertise in the router advertisement messages.", + ge=1280, + le=9486, + title="IP MTU", + ), + ] = None + managedConfigurationFlag: Annotated[ + bool, + Field( + description="Enable DHCPv6 for address configuration (M-bit).", + title="Managed Configuration Flag", + ), + ] + maxAdvertisementInterval: Annotated[ + int, + Field( + description="Maximum time between router advertisements (in seconds).", + ge=4, + le=1800, + title="Maximum Advertisement Interval", + ), + ] + minAdvertisementInterval: Annotated[ + int, + Field( + description="Minimum time between router advertisements (in seconds).", + ge=3, + le=1350, + title="Minimum Advertisement Interval", + ), + ] + otherConfigurationFlag: Annotated[ + bool, + Field( + description="Enable DHCPv6 for other configuration (O-bit).", + title="Other Configuration Flag", + ), + ] + prefixes: Annotated[ + Optional[List[VirtualNetworkSpecIrbInterfaceSpecIpv6RouterAdvertisementPrefix]], + Field( + description="IPv6 prefixes to advertise in router advertisements.", + title="Prefixes", + ), + ] = None + reachableTime: Annotated[ + Optional[int], + Field( + description="Time in milliseconds for Neighbor Unreachability Detection.", + ge=0, + le=3600000, + title="Reachable Time", + ), + ] = 0 + retransmitTime: Annotated[ + int, + Field( + description="Time in milliseconds between retransmitted NS messages.", + ge=0, + le=1800000, + title="Retransmit Time", + ), + ] + routerLifetime: Annotated[ + int, + Field( + description="Router lifetime in seconds for default gateway.", + ge=0, + le=9000, + title="Router Lifetime", + ), + ] + + +VirtualNetworkSpecIrbInterfaceSpecL3ProxyARPND = IRBInterfaceSpecL3ProxyARPND + + +VirtualNetworkSpecIrbInterfaceSpecVirtualIPDiscoveryItem = ( + IRBInterfaceSpecVirtualIPDiscoveryItem +) + + +class VirtualNetworkSpecIrbInterfaceSpec(BaseModel): + """ + Specification of the IrbInterface + """ + + anycastGatewayMAC: Annotated[ + Optional[str], + Field( + description="The gateway MAC to use on the anycast address, if left empty the node will automatically assign one.", + title="Anycast GW MAC", + ), + ] = None + arpTimeout: Annotated[ + Optional[int], + Field( + description="Duration of time that dynamic ARP entries remain in the ARP cache before they expire.", + title="ARP Timeout", + ), + ] = 14400 + bfd: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecBfd], + Field(description="Enable BFD on the IRBInterface.", title="BFD Configuration"), + ] = None + bridgeDomain: Annotated[ + str, Field(description="Reference to a BridgeDomain.", title="Bridge Domain") + ] + description: Annotated[ + Optional[str], + Field(description="The description of the IRBInterface.", title="Description"), + ] = None + egress: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecEgress], + Field( + description="Manages actions on traffic at Egress.", title="Egress Actions" + ), + ] = None + evpnRouteAdvertisementType: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecEvpnRouteAdvertisementType], + Field( + description="Controls the type of ARP/ND entries to advertise.", + title="EVPN Route Advertisement Type", + ), + ] = None + hostRoutePopulate: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecHostRoutePopulate], + Field( + description="Configures host route population based on ARP entries.", + title="Host Route Population", + ), + ] = None + ingress: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecIngress], + Field( + description="Manages actions on traffic at Ingress.", + title="Ingress Actions", + ), + ] = None + ipAddresses: Annotated[ + Optional[List[VirtualNetworkSpecIrbInterfaceSpecIpAddress]], + Field(title="IP Addresses"), + ] = None + ipMTU: Annotated[ + Optional[int], + Field( + description="IP MTU for the IRBInterface [default=1500].", + ge=1280, + le=9486, + title="IP MTU", + ), + ] = 1500 + ipv4Parameters: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecIpv4Parameters], + Field(title="IPv4-specific Parameters"), + ] = None + ipv6RouterAdvertisement: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecIpv6RouterAdvertisement], + Field(title="IPv6 Router Advertisement"), + ] = None + l3ProxyARPND: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecL3ProxyARPND], + Field( + description="L3 Proxy ARP and ND configuration.", title="L3 Proxy ARP/ND" + ), + ] = None + learnUnsolicited: Annotated[ + Optional[Literal["BOTH", "GLOBAL", "LINK-LOCAL", "NONE"]], + Field( + description="Enable or disable learning of unsolicited ARPs.", + title="Learn Unsolicited ARPs", + ), + ] = "NONE" + router: Annotated[str, Field(description="Reference to a Router.", title="Router")] + unnumbered: Annotated[ + Optional[Literal["IPV6"]], + Field( + description="Enables the use of unnumbered interfaces on the IRBInterface. If IPv6 is specified, no IP address are configured on the sub-interface and only the link local address will be used. If any IP addresses are specified for either IPv4 or IPv6 that will take precedence and IPs will be assigned to the interfaces.(Deprecated, Use IPv6RouterAdvertisement)", + title="Unnumbered", + ), + ] = None + virtualIPDiscovery: Annotated[ + Optional[List[VirtualNetworkSpecIrbInterfaceSpecVirtualIPDiscoveryItem]], + Field( + description="Configuration for Virtual IP discovery on the interface.", + title="Virtual IP Discovery", + ), + ] = None + + +class VirtualNetworkSpecIrbInterface(BaseModel): + name: Annotated[ + str, + Field(description="The name of the IrbInterface.", title="IRB Interface Name"), + ] + spec: Annotated[ + VirtualNetworkSpecIrbInterfaceSpec, + Field( + description="Specification of the IrbInterface", title="IRB Interface Spec" + ), + ] + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecAsPathOptionsRemovePrivateAS(BaseModel): + """ + Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers. + """ + + ignorePeerAS: Annotated[ + bool, + Field( + description="If set to true then do not delete or replace a private AS number that is the same as the peer AS number.", + title="Ignore Peer AS", + ), + ] + leadingOnly: Annotated[ + bool, + Field( + description="If set to true then only delete or replace private AS numbers that appear before the first occurrence of a non-private ASN in the sequence of most recent ASNs in the AS path.", + title="Leading Only", + ), + ] + removePrivateASMode: Annotated[ + Literal["DISABLED", "REPLACE", "DELETE"], + Field( + description="The method by which private AS numbers are removed from the advertised AS_PATH attribute.", + title="Remove Private AS Mode", + ), + ] + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecAsPathOptions(BaseModel): + """ + AS Path Options + """ + + allowOwnAS: Annotated[ + int, + Field( + description="The maximum number of times the global AS number or a local AS number of the BGP instance can appear in any received AS_PATH before it is considered a loop and considered invalid.", + ge=0, + le=255, + title="Allow Own AS", + ), + ] + removePrivateAS: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsBgpBgpGroupSpecAsPathOptionsRemovePrivateAS + ], + Field( + description="Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers.", + title="Remove Private AS", + ), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted( + BaseModel +): + logOnly: Annotated[ + Optional[bool], + Field( + description="Defines the action to take when the maximum number of prefixes is exceeded. Session is reset if set to false, otherwise only a warning is logged.", + title="Log Only", + ), + ] = None + maxReceivedRoutes: Annotated[ + Optional[int], + Field( + description="Maximum number of prefixes allowed to be received from the neighbor, counting only accepted routes.", + ge=1, + le=4294967295, + title="Max Received Routes", + ), + ] = None + warningThreshold: Annotated[ + Optional[int], + Field( + description="A percentage of the maximum number of prefixes that can be accepted before a warning is logged.", + ge=1, + le=100, + title="Warning Threshold Percentage", + ), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived( + BaseModel +): + logOnly: Annotated[ + Optional[bool], + Field( + description="Defines the action to take when the maximum number of prefixes is exceeded. Session is reset if set to false, otherwise only a warning is logged.", + title="Log Only", + ), + ] = None + maxReceivedRoutes: Annotated[ + Optional[int], + Field( + description="Maximum number of prefixes allowed to be received from the neighbor, counting all routes (accepted and rejected by import policies).", + ge=1, + le=4294967295, + title="Max Received Routes", + ), + ] = None + warningThreshold: Annotated[ + Optional[int], + Field( + description="A percentage of the maximum number of prefixes that can be received before a warning is logged.", + ge=1, + le=100, + title="Warning Threshold Percentage", + ), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted + ], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived + ], + Field(title="Prefix Limit Received"), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimit], + Field(title="Prefix Limit"), + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv6UnicastPrefixLimitPrefixLimitAccepted = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv6UnicastPrefixLimitPrefixLimitReceived = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv6UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv6UnicastPrefixLimitPrefixLimitAccepted + ], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv6UnicastPrefixLimitPrefixLimitReceived + ], + Field(title="Prefix Limit Received"), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv6UnicastPrefixLimit], + Field(title="Prefix Limit"), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecLocalAS(BaseModel): + """ + The local autonomous system number advertised to peers. + """ + + autonomousSystem: Annotated[ + int, + Field( + description="Local Autonomous System number.", + ge=1, + le=4294967295, + title="Local Autonomous System", + ), + ] + prependGlobalAS: Annotated[ + Optional[bool], + Field( + description="When set to true, the global ASN value is prepended to the AS path in outbound routes towards each BGP peer.", + title="Prepend Global Autonomous System", + ), + ] = None + prependLocalAS: Annotated[ + Optional[bool], + Field( + description="When set to true, the local AS value is prepended to the AS path of inbound routes from each EBGP peer.", + title="Prepend Local Autonomous System", + ), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecPeerAS(BaseModel): + """ + The autonomous system number expected from peers. + """ + + autonomousSystem: Annotated[ + int, + Field( + description="Local Autonomous System number.", + ge=1, + le=4294967295, + title="Peer Autonomous System", + ), + ] + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecSendDefaultRoute(BaseModel): + """ + Options for controlling the generation of default routes towards BGP peers. + """ + + addressFamily: Annotated[ + List[Literal["IPV4-UNICAST", "IPV6-UNICAST"]], + Field( + description="Enables the sending of a synthetically generated default IPv4 or IPV6 route to each peer.", + title="Address Families", + ), + ] + exportPolicy: Annotated[ + Optional[str], + Field( + description="Reference to a Policy that should be applied to the advertised default routes, in order to set their attributes to non-default values.", + title="Export Policy", + ), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpecTimers(BaseModel): + """ + Timer configurations + """ + + connectRetry: Annotated[ + Optional[int], + Field( + description="The time interval in seconds between successive attempts to establish a session with a peer.", + ge=1, + le=65535, + title="Connect Retry", + ), + ] = None + holdTime: Annotated[ + Optional[int], + Field( + description="The hold-time interval in seconds that the router proposes to the peer in its OPEN message.", + ge=0, + le=65535, + title="Hold Time", + ), + ] = None + keepAlive: Annotated[ + Optional[int], + Field( + description="The interval in seconds between successive keepalive messages sent to the peer.", + ge=0, + le=21845, + title="Keep Alive", + ), + ] = None + minimumAdvertisementInterval: Annotated[ + Optional[int], + Field( + description="The value assigned to the MinRouteAdvertisementIntervalTimer of RFC 4271, for both EBGP and IBGP sessions.", + ge=1, + le=255, + title="Minimum Advertisement Interval", + ), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpGroupSpec(BaseModel): + """ + Specification of the BgpGroup + """ + + asPathOptions: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpGroupSpecAsPathOptions], + Field(description="AS Path Options", title="AS Path Options"), + ] = None + bfd: Annotated[ + Optional[bool], + Field( + description="Enable or disable Bi-forward Forwarding Detection (BFD) with fast failover.", + title="BFD", + ), + ] = None + client: Annotated[ + Optional[bool], + Field( + description="When set to true, all configured and dynamic BGP peers are considered RR clients.", + title="Route Reflector Client", + ), + ] = None + clusterID: Annotated[ + Optional[str], + Field( + description="Enables route reflect client and sets the cluster ID.", + title="Cluster ID", + ), + ] = None + description: Annotated[ + Optional[str], + Field( + description="Sets the description on the BGP group.", title="Description" + ), + ] = None + exportPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes advertised to peers.", + title="Export Policy", + ), + ] = None + grStaleRouteTime: Annotated[ + Optional[int], + Field( + description="Enables Graceful Restart on the peer and sets the stale route time.", + ge=1, + le=3600, + title="GR Stale Route Time", + ), + ] = None + importPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes received from peers.", + title="Import Policy", + ), + ] = None + ipv4Unicast: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field( + description="Reference to a Keychain resource that will be used for authentication with the BGP peer.", + title="Keychain", + ), + ] = None + localAS: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpGroupSpecLocalAS], + Field( + description="The local autonomous system number advertised to peers.", + title="Local AS", + ), + ] = None + localPreference: Annotated[ + Optional[int], + Field( + description="Local Preference attribute added to received routes from the BGP peers, also sets local preference for generated routes.", + ge=0, + le=4294967295, + title="Local Preference", + ), + ] = None + multiHopMaxHop: Annotated[ + Optional[int], + Field( + description="Enable multihop for eBGP peers and sets the maximum number of hops allowed.", + ge=1, + le=255, + title="Multihop Max Hop Count", + ), + ] = None + nextHopSelf: Annotated[ + Optional[bool], + Field( + description="When set to true, the next-hop in all IPv4-unicast, IPv6-unicast and EVPN BGP routes advertised to the peer is set to the local-address.", + title="Next Hop Self", + ), + ] = None + peerAS: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpGroupSpecPeerAS], + Field( + description="The autonomous system number expected from peers.", + title="Peer AS", + ), + ] = None + sendCommunityLarge: Annotated[ + Optional[bool], + Field( + description="When false, all large (12 byte) BGP communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Large", + ), + ] = None + sendCommunityStandard: Annotated[ + Optional[bool], + Field( + description="When false, all standard (4 byte) communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Standard", + ), + ] = None + sendDefaultRoute: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpGroupSpecSendDefaultRoute], + Field( + description="Options for controlling the generation of default routes towards BGP peers.", + title="Send Default Route", + ), + ] = None + timers: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpGroupSpecTimers], + Field(description="Timer configurations", title="Timers"), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpGroup(BaseModel): + name: Annotated[ + str, Field(description="The name of the BgpGroup.", title="BGP Group Name") + ] + spec: Annotated[ + VirtualNetworkSpecProtocolsBgpBgpGroupSpec, + Field(description="Specification of the BgpGroup", title="BGP Group Spec"), + ] + + +VirtualNetworkSpecProtocolsBgpBgpPeerSpecAsPathOptionsRemovePrivateAS = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecAsPathOptionsRemovePrivateAS +) + + +class VirtualNetworkSpecProtocolsBgpBgpPeerSpecAsPathOptions(BaseModel): + """ + AS Path Options + """ + + allowOwnAS: Annotated[ + int, + Field( + description="The maximum number of times the global AS number or a local AS number of the BGP instance can appear in any received AS_PATH before it is considered a loop and considered invalid.", + ge=0, + le=255, + title="Allow Own AS", + ), + ] + removePrivateAS: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpPeerSpecAsPathOptionsRemovePrivateAS], + Field( + description="Options for removing private AS numbers (2-byte and 4-byte) from the advertised AS path towards all peers.", + title="Remove Private AS", + ), + ] = None + + +VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv4UnicastPrefixLimitPrefixLimitAccepted = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv4UnicastPrefixLimitPrefixLimitReceived = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv4UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv4UnicastPrefixLimitPrefixLimitAccepted + ], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv4UnicastPrefixLimitPrefixLimitReceived + ], + Field(title="Prefix Limit Received"), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv4UnicastPrefixLimit], + Field(title="Prefix Limit"), + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv6UnicastPrefixLimitPrefixLimitAccepted = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimitPrefixLimitAccepted +) + + +VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv6UnicastPrefixLimitPrefixLimitReceived = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecIpv4UnicastPrefixLimitPrefixLimitReceived +) + + +class VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv6UnicastPrefixLimit(BaseModel): + prefixLimitAccepted: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv6UnicastPrefixLimitPrefixLimitAccepted + ], + Field(title="Prefix Limit Accepted"), + ] = None + prefixLimitReceived: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv6UnicastPrefixLimitPrefixLimitReceived + ], + Field(title="Prefix Limit Received"), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + Optional[bool], + Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled"), + ] = None + prefixLimit: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv6UnicastPrefixLimit], + Field(title="Prefix Limit"), + ] = None + + +VirtualNetworkSpecProtocolsBgpBgpPeerSpecLocalAS = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecLocalAS +) + + +VirtualNetworkSpecProtocolsBgpBgpPeerSpecPeerAS = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecPeerAS +) + + +VirtualNetworkSpecProtocolsBgpBgpPeerSpecSendDefaultRoute = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecSendDefaultRoute +) + + +VirtualNetworkSpecProtocolsBgpBgpPeerSpecTimers = ( + VirtualNetworkSpecProtocolsBgpBgpGroupSpecTimers +) + + +class VirtualNetworkSpecProtocolsBgpBgpPeerSpec(BaseModel): + """ + Specification of the BgpPeer + """ + + asPathOptions: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpPeerSpecAsPathOptions], + Field(description="AS Path Options", title="AS Path Options"), + ] = None + bfd: Annotated[ + Optional[bool], + Field( + description="Enable or disable Bi-forward Forwarding Detection (BFD) with fast failover.", + title="BFD", + ), + ] = None + client: Annotated[ + Optional[bool], + Field( + description="When set to true, all configured and dynamic BGP peers are considered RR clients.", + title="Route Reflector Client", + ), + ] = None + clusterID: Annotated[ + Optional[str], + Field( + description="Enables route reflect client and sets the cluster ID.", + title="Cluster ID", + ), + ] = None + description: Annotated[ + Optional[str], + Field(description="Sets the description on the BGP peer", title="Description"), + ] = None + dynamicNeighbor: Annotated[ + Optional[bool], + Field( + description="When set to true the Interface is added to the dynamic-neighbor list for dynamic peering.", + title="Dynamic Neighbor", + ), + ] = False + dynamicNeighborAllowedPeerAS: Annotated[ + Optional[List[int]], + Field( + description="The autonomous system numbers allowed from peers if dynamic peering is enabled.", + title="Dynamic Neighbor Allowed Peer AS", + ), + ] = None + exportPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes advertised to peers.", + title="Export Policy", + ), + ] = None + grStaleRouteTime: Annotated[ + Optional[int], + Field( + description="Enables Graceful Restart on the peer and sets the stale route time.", + ge=1, + le=3600, + title="GR Stale Route Time", + ), + ] = None + group: Annotated[ + str, + Field( + description="Reference to a BGPGroup. When present this BGP peer will be added to the BGP group", + title="Group", + ), + ] + importPolicy: Annotated[ + Optional[List[str]], + Field( + description="Reference to a Policy CR that will be used to filter routes received from peers.", + title="Import Policy", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to a RoutedInterface or IrbInterface resource whose IP will be used as a source IP for the BGP session.", + title="Interface Reference", + ), + ] + interfaceKind: Annotated[ + Literal["ROUTEDINTERFACE", "IRBINTERFACE"], + Field( + description="InterfaceReference type defines whether the provided Reference is a RoutedInterface or IrbInterface.", + title="Interface Reference Type", + ), + ] + ipv4Unicast: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpPeerSpecIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field( + description="Reference to a Keychain resource that will be used for authentication with the BGP peer.", + title="Keychain", + ), + ] = None + localAS: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpPeerSpecLocalAS], + Field( + description="The local autonomous system number advertised to peers.", + title="Local AS", + ), + ] = None + localPreference: Annotated[ + Optional[int], + Field( + description="Local Preference attribute added to received routes from the BGP peers, also sets local preference for generated routes.", + ge=0, + le=4294967295, + title="Local Preference", + ), + ] = None + multiHopMaxHop: Annotated[ + Optional[int], + Field( + description="Enable multihop for eBGP peers and sets the maximum number of hops allowed.", + ge=1, + le=255, + title="Multihop Max Hop Count", + ), + ] = None + nextHopSelf: Annotated[ + Optional[bool], + Field( + description="When set to true, the next-hop in all IPv4-unicast, IPv6-unicast and EVPN BGP routes advertised to the peer is set to the local-address.", + title="Next Hop Self", + ), + ] = None + node: Annotated[ + Optional[str], + Field( + description="Node on which to configure the BGP peer. This node must be one of the nodes on which the IRBInterface is configured. When left blank or if the node is not part of the IRBInterface, the peer will not be deployed. Ignored for RoutedInterfaces.", + title="Node", + ), + ] = None + peerAS: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpPeerSpecPeerAS], + Field( + description="The autonomous system number expected from peers.", + title="Peer AS", + ), + ] = None + peerIP: Annotated[ + Optional[str], + Field( + description="Peer IP to which the peering session will be established.", + title="Peer IP", + ), + ] = None + sendCommunityLarge: Annotated[ + Optional[bool], + Field( + description="When false, all large (12 byte) BGP communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Large", + ), + ] = None + sendCommunityStandard: Annotated[ + Optional[bool], + Field( + description="When false, all standard (4 byte) communities from all outbound routes advertised to the peer are stripped.", + title="Send Community Standard", + ), + ] = None + sendDefaultRoute: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpPeerSpecSendDefaultRoute], + Field( + description="Options for controlling the generation of default routes towards BGP peers.", + title="Send Default Route", + ), + ] = None + timers: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgpBgpPeerSpecTimers], + Field(description="Timer configurations", title="Timers"), + ] = None + + +class VirtualNetworkSpecProtocolsBgpBgpPeer(BaseModel): + name: Annotated[ + str, Field(description="The name of the BgpPeer.", title="BGP Peer Name") + ] + spec: Annotated[ + VirtualNetworkSpecProtocolsBgpBgpPeerSpec, + Field(description="Specification of the BgpPeer", title="BGP Peer Spec"), + ] + + +class VirtualNetworkSpecProtocolsBgp(BaseModel): + """ + BGP Protocol. + """ + + bgpGroups: Annotated[ + Optional[List[VirtualNetworkSpecProtocolsBgpBgpGroup]], + Field(description="List of BgpGroups. [emits=BGPGroup]", title="BGP Groups"), + ] = None + bgpPeers: Annotated[ + Optional[List[VirtualNetworkSpecProtocolsBgpBgpPeer]], + Field(description="List of BgpPeers [emits=BGPPeer]", title="BGP Peers"), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgpCommunitySet( + BaseModel +): + """ + Modify BGP communities associated with the route using hybrid Community Sets. + """ + + add: Annotated[ + Optional[List[str]], + Field( + description="List of community sets to add to the route.", + max_length=1, + title="Add Communities", + ), + ] = None + remove: Annotated[ + Optional[List[str]], + Field( + description="List of community sets to remove from the route.", + max_length=1, + title="Remove Communities", + ), + ] = None + replace: Annotated[ + Optional[List[str]], + Field( + description="List of community sets to replace the existing communities with. Cannot be combined with Add or Remove.", + max_length=1, + title="Replace Communities", + ), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgpMed( + BaseModel +): + """ + Set a new MED value. + """ + + numericalValue: Annotated[ + Optional[int], + Field( + description="Fixed numerical value to set or add/subtract.", + ge=0, + le=4294967295, + title="MED Value", + ), + ] = None + operation: Annotated[ + Optional[Literal["Set", "Add", "Subtract"]], + Field( + description="The operation to perform on the MED value.", title="Operation" + ), + ] = None + valueType: Annotated[ + Optional[Literal["Fixed", "IGP"]], + Field( + description="Use a fixed value or an IGP metric to adjust the MED.", + title="Value Type", + ), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgp(BaseModel): + """ + Actions related to the BGP protocol. + """ + + asPathPrepend: Annotated[ + Optional[int], + Field( + description="AS number to prepend to the AS Path attributes.", + ge=1, + le=4294967295, + title="AS Path Prepend", + ), + ] = None + asPathRemove: Annotated[ + Optional[bool], + Field( + description="Clear the AS path to make it empty.", title="AS Path Remove" + ), + ] = None + asPathReplace: Annotated[ + Optional[List[int]], + Field( + description="Replace the existing AS path with a new AS_SEQUENCE containing the listed AS numbers.", + title="AS Path Replace", + ), + ] = None + communitySet: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgpCommunitySet + ], + Field( + description="Modify BGP communities associated with the route using hybrid Community Sets.", + title="Modify Communities", + ), + ] = None + localPreference: Annotated[ + Optional[int], + Field( + description="Set a new LOCAL_PREF value for matching BGP routes.", + ge=0, + le=4294967295, + title="Set Local Preference", + ), + ] = None + med: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgpMed + ], + Field(description="Set a new MED value.", title="Set MED"), + ] = None + setOrigin: Annotated[ + Optional[Literal["egp", "igp", "incomplete"]], + Field( + description="Set a new ORIGIN attribute for matching BGP routes.", + title="Set Origin", + ), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultAction(BaseModel): + """ + The default action to apply if no other actions are defined. + """ + + bgp: Annotated[ + Optional[VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgp], + Field(description="Actions related to the BGP protocol.", title="BGP"), + ] = None + policyResult: Annotated[ + Optional[Literal["accept", "reject", "NextPolicy", "NextStatement"]], + Field(description="Final disposition for the route.", title="Policy Result"), + ] = None + + +VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemActionBgpCommunitySet = VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgpCommunitySet + + +VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemActionBgpMed = ( + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgpMed +) + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemActionBgp( + BaseModel +): + """ + Actions related to the BGP protocol. + """ + + asPathPrepend: Annotated[ + Optional[int], + Field( + description="AS number to prepend to the AS Path attributes.", + ge=1, + le=4294967295, + title="AS Path Prepend", + ), + ] = None + asPathRemove: Annotated[ + Optional[bool], + Field( + description="Clear the AS path to make it empty.", title="AS Path Remove" + ), + ] = None + asPathReplace: Annotated[ + Optional[List[int]], + Field( + description="Replace the existing AS path with a new AS_SEQUENCE containing the listed AS numbers.", + title="AS Path Replace", + ), + ] = None + communitySet: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemActionBgpCommunitySet + ], + Field( + description="Modify BGP communities associated with the route using hybrid Community Sets.", + title="Modify Communities", + ), + ] = None + localPreference: Annotated[ + Optional[int], + Field( + description="Set a new LOCAL_PREF value for matching BGP routes.", + ge=0, + le=4294967295, + title="Set Local Preference", + ), + ] = None + med: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemActionBgpMed + ], + Field(description="Set a new MED value.", title="Set MED"), + ] = None + setOrigin: Annotated[ + Optional[Literal["egp", "igp", "incomplete"]], + Field( + description="Set a new ORIGIN attribute for matching BGP routes.", + title="Set Origin", + ), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemAction( + BaseModel +): + """ + Actions for routes that match the policy statement. + """ + + bgp: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemActionBgp + ], + Field(description="Actions related to the BGP protocol.", title="BGP"), + ] = None + policyResult: Annotated[ + Optional[Literal["accept", "reject", "NextPolicy", "NextStatement"]], + Field(description="Final disposition for the route.", title="Policy Result"), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemMatchBgpAsPathMatch( + BaseModel +): + """ + AS Path match criteria. + """ + + asPathExpression: Annotated[ + Optional[str], + Field( + description="A singular regular expression string to match against AS_PATH objects. Mutually exclusive with the ASPathSet reference.", + title="AS Path Expression", + ), + ] = None + asPathSet: Annotated[ + Optional[str], + Field( + description="Reference to an ASPathSet resource. Mutually exclusive with the ASPathExpression.", + title="AS Path Set", + ), + ] = None + matchSetOptions: Annotated[ + Optional[Literal["Any", "All", "Invert"]], + Field( + description="The matching criteria that applies to the members in the referenced set.", + title="Match Set Options", + ), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemMatchBgp( + BaseModel +): + """ + Configuration for BGP-specific policy match criteria. + """ + + asPathMatch: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemMatchBgpAsPathMatch + ], + Field(description="AS Path match criteria.", title="AS Path"), + ] = None + communitySet: Annotated[ + Optional[str], + Field( + description="Match conditions for BGP communities.", title="BGP Community" + ), + ] = None + evpnRouteType: Annotated[ + Optional[List[int]], + Field( + description="Match conditions for EVPN route types.", + title="EVPN Route Type", + ), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemMatch(BaseModel): + """ + Match conditions of the policy statement. + """ + + bgp: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemMatchBgp + ], + Field( + description="Configuration for BGP-specific policy match criteria.", + title="BGP", + ), + ] = None + family: Annotated[ + Optional[List[str]], + Field( + description="Address families that the route belongs to.", title="Family" + ), + ] = None + prefixSet: Annotated[ + Optional[str], + Field(description="Reference to a PrefixSet resource.", title="Prefix Set"), + ] = None + protocol: Annotated[ + Optional[ + Literal[ + "AGGREGATE", + "ARP_ND", + "BGP", + "BGP_EVPN", + "DHCP", + "GRIBI", + "HOST", + "ISIS", + "LOCAL", + "LINUX", + "NDK1", + "NDK2", + "OSPFV2", + "OSPFV3", + "STATIC", + ] + ], + Field(description="The route protocol type to match.", title="Protocol"), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItem(BaseModel): + action: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemAction + ], + Field( + description="Actions for routes that match the policy statement.", + title="Action", + ), + ] = None + match: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemMatch + ], + Field(description="Match conditions of the policy statement.", title="Match"), + ] = None + name: Annotated[ + str, Field(description="Name of the policy statement.", title="Name") + ] + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpec(BaseModel): + """ + A policy + """ + + defaultAction: Annotated[ + Optional[VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultAction], + Field( + description="The default action to apply if no other actions are defined.", + title="Default Action", + ), + ] = None + statement: Annotated[ + Optional[ + List[VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItem] + ], + Field(description="List of policy statements.", title="Statements"), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicy(BaseModel): + name: Annotated[str, Field(description="Name of the Policy.", title="Policy Name")] + spec: Annotated[ + Optional[VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpec], + Field(description="A policy", title="Policy Spec"), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPrefixSetSpecPrefixItem(BaseModel): + endRange: Annotated[ + Optional[int], + Field( + description="The end range when using a range to match prefixes.", + ge=0, + le=128, + title="End Range", + ), + ] = None + exact: Annotated[ + Optional[bool], + Field( + description="Indicates if it is an exact match. Ignores the StartRange and EndRange if this param is set.", + title="Exact", + ), + ] = None + prefix: Annotated[ + str, + Field( + description="The IPv4 or IPv6 prefix in CIDR notation with mask.", + title="Prefix", + ), + ] + startRange: Annotated[ + Optional[int], + Field( + description="If specifying a range, this is the start of the range.", + ge=0, + le=128, + title="Start Range", + ), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPrefixSetSpec(BaseModel): + """ + A PrefixSets + """ + + prefix: Annotated[ + List[VirtualNetworkSpecProtocolsRoutingPoliciesPrefixSetSpecPrefixItem], + Field( + description="List of IPv4 or IPv6 prefixes in CIDR notation.", + title="Prefixes", + ), + ] + + +class VirtualNetworkSpecProtocolsRoutingPoliciesPrefixSet(BaseModel): + name: Annotated[ + str, Field(description="Name of the PrefixSet.", title="Prefix Set Name") + ] + spec: Annotated[ + Optional[VirtualNetworkSpecProtocolsRoutingPoliciesPrefixSetSpec], + Field(description="A PrefixSets", title="Prefix Set Spec"), + ] = None + + +class VirtualNetworkSpecProtocolsRoutingPolicies(BaseModel): + """ + Routing Policies. + """ + + policies: Annotated[ + Optional[List[VirtualNetworkSpecProtocolsRoutingPoliciesPolicy]], + Field(description="List of Policies. [emits=Policy]", title="Policies"), + ] = None + prefixSets: Annotated[ + Optional[List[VirtualNetworkSpecProtocolsRoutingPoliciesPrefixSet]], + Field(description="List of PrefixSet [emits=PrefixSet]", title="Prefix Sets"), + ] = None + + +class VirtualNetworkSpecProtocolsStaticRouteSpecNexthopGroupBfd(BaseModel): + """ + Enables BFD to the next-hops in the group. Local and Remote discriminator parameters have been deprecated at this level. Use Nexthop to set these parameters. + """ + + enabled: Annotated[ + Optional[bool], + Field( + description="Defines whether BFD should be enabled towards the nexthops.", + title="Enabled", + ), + ] = False + localAddress: Annotated[ + Optional[str], + Field( + description="Defines the local address to use when establishing the BFD session with the nexthop.", + title="Local Address", + ), + ] = None + + +class VirtualNetworkSpecProtocolsStaticRouteSpecNexthopGroupNexthopBfd(BaseModel): + """ + Enables BFD to the next-hops in the group. This overrides the configuration at the group. + """ + + enabled: Annotated[ + Optional[bool], + Field( + description="Defines whether BFD should be enabled towards the nexthops.", + title="Enabled", + ), + ] = False + localAddress: Annotated[ + Optional[str], + Field( + description="Defines the local address to use when establishing the BFD session with the nexthop.", + title="Local Address", + ), + ] = None + localDiscriminator: Annotated[ + Optional[int], + Field( + description="Defines the local discriminator.", title="Local Discriminator" + ), + ] = None + remoteDiscriminator: Annotated[ + Optional[int], + Field( + description="Defines the remote discriminator.", + title="Remote Discriminator", + ), + ] = None + + +class VirtualNetworkSpecProtocolsStaticRouteSpecNexthopGroupNexthop(BaseModel): + bfd: Annotated[ + Optional[VirtualNetworkSpecProtocolsStaticRouteSpecNexthopGroupNexthopBfd], + Field( + description="Enables BFD to the next-hops in the group. This overrides the configuration at the group.", + title="BFD", + ), + ] = None + ipPrefix: Annotated[str, Field(description="Address to use.", title="IP Prefix")] + resolve: Annotated[ + Optional[bool], + Field( + description="If set to true the next-hops can be destinations which are resolved in the route table. This overrides the configuration at the group.", + title="Resolve", + ), + ] = False + + +class VirtualNetworkSpecProtocolsStaticRouteSpecNexthopGroup(BaseModel): + """ + Group of nexthops for the list of prefixes. + """ + + bfd: Annotated[ + Optional[VirtualNetworkSpecProtocolsStaticRouteSpecNexthopGroupBfd], + Field( + description="Enables BFD to the next-hops in the group. Local and Remote discriminator parameters have been deprecated at this level. Use Nexthop to set these parameters.", + title="BFD", + ), + ] = None + blackhole: Annotated[ + Optional[bool], + Field( + description="If set to true all traffic destined to the prefixes will be blackholed. If enabled, next-hops are ignored and this takes precedence.", + title="Blackhole", + ), + ] = False + blackholeSendICMP: Annotated[ + Optional[bool], + Field( + description="When enabled, the router will generate ICMP Unreachable messages for packets destined to the blackhole route.", + title="Blackhole ICMP Generation", + ), + ] = None + nexthops: Annotated[ + Optional[List[VirtualNetworkSpecProtocolsStaticRouteSpecNexthopGroupNexthop]], + Field(description="Ordered list of nexthops.", title="Nexthops"), + ] = None + resolve: Annotated[ + Optional[bool], + Field( + description="If set to true the next-hops can be destinations which are resolved in the route table.", + title="Resolve", + ), + ] = False + + +class VirtualNetworkSpecProtocolsStaticRouteSpec(BaseModel): + """ + A StaticRoutes + """ + + nexthopGroup: Annotated[ + VirtualNetworkSpecProtocolsStaticRouteSpecNexthopGroup, + Field( + description="Group of nexthops for the list of prefixes.", + title="Nexthop Group", + ), + ] + nodes: Annotated[ + Optional[List[str]], + Field( + description="List of nodes on which to configure the static routes. An AND operation is executed against the nodes in this list and the nodes on which the Router is configured to determine the Nodes on which to configure the static routes.", + title="Nodes", + ), + ] = None + preference: Annotated[ + Optional[int], + Field(description="Defines the route preference.", title="Preference"), + ] = None + prefixes: Annotated[ + List[str], + Field( + description="List of destination prefixes and mask to use for the static routes.", + title="Prefixes", + ), + ] + router: Annotated[ + str, + Field( + description="Reference to a Router on which to configure the static routes. If no Nodes are provided then the static routes will be provisioned on all Nodes on which the Router is provisioned.", + title="Router", + ), + ] + + +class VirtualNetworkSpecProtocolsStaticRoute(BaseModel): + name: Annotated[ + str, Field(description="Name of the StaticRoute.", title="Static Route Name") + ] + spec: Annotated[ + Optional[VirtualNetworkSpecProtocolsStaticRouteSpec], + Field(description="A StaticRoutes", title="Static Route Spec"), + ] = None + + +class VirtualNetworkSpecProtocols(BaseModel): + """ + Protocols to configure. + """ + + bgp: Annotated[ + Optional[VirtualNetworkSpecProtocolsBgp], + Field(description="BGP Protocol.", title="BGP"), + ] = None + routingPolicies: Annotated[ + Optional[VirtualNetworkSpecProtocolsRoutingPolicies], + Field(description="Routing Policies.", title="Routing Policies"), + ] = None + staticRoutes: Annotated[ + Optional[List[VirtualNetworkSpecProtocolsStaticRoute]], + Field( + description="List of Static Routes within this VirtualNetwork. [emits=StaticRoute]", + title="Static Routes", + ), + ] = None + + +VirtualNetworkSpecRoutedInterfaceSpecBfd = RoutedInterfaceSpecBfd + + +VirtualNetworkSpecRoutedInterfaceSpecEgress = BridgeInterfaceSpecEgress + + +VirtualNetworkSpecRoutedInterfaceSpecIngress = BridgeInterfaceSpecIngress + + +VirtualNetworkSpecRoutedInterfaceSpecIpv4Address = ( + IRBInterfaceStatusInterfaceIpv4Address +) + + +VirtualNetworkSpecRoutedInterfaceSpecIpv4Parameters = IRBInterfaceSpecIpv4Parameters + + +VirtualNetworkSpecRoutedInterfaceSpecIpv6Address = ( + IRBInterfaceStatusInterfaceIpv4Address +) + + +VirtualNetworkSpecRoutedInterfaceSpecIpv6RouterAdvertisementPrefix = ( + IRBInterfaceSpecIpv6RouterAdvertisementPrefix +) + + +class VirtualNetworkSpecRoutedInterfaceSpecIpv6RouterAdvertisement(BaseModel): + currentHopLimit: Annotated[ + int, + Field( + description="The current hop limit to advertise in the router advertisement messages.", + ge=0, + le=255, + title="Current Hop Limit", + ), + ] + enabled: Annotated[ + bool, + Field( + description="Enable or disable IPv6 router advertisements.", + title="Enable Router Advertisements", + ), + ] + ipMTU: Annotated[ + Optional[int], + Field( + description="The IP MTU to advertise in the router advertisement messages.", + ge=1280, + le=9486, + title="IP MTU", + ), + ] = None + managedConfigurationFlag: Annotated[ + bool, + Field( + description="Enable DHCPv6 for address configuration (M-bit).", + title="Managed Configuration Flag", + ), + ] + maxAdvertisementInterval: Annotated[ + int, + Field( + description="Maximum time between router advertisements (in seconds).", + ge=4, + le=1800, + title="Maximum Advertisement Interval", + ), + ] + minAdvertisementInterval: Annotated[ + int, + Field( + description="Minimum time between router advertisements (in seconds).", + ge=3, + le=1350, + title="Minimum Advertisement Interval", + ), + ] + otherConfigurationFlag: Annotated[ + bool, + Field( + description="Enable DHCPv6 for other configuration (O-bit).", + title="Other Configuration Flag", + ), + ] + prefixes: Annotated[ + Optional[ + List[VirtualNetworkSpecRoutedInterfaceSpecIpv6RouterAdvertisementPrefix] + ], + Field( + description="IPv6 prefixes to advertise in router advertisements.", + title="Prefixes", + ), + ] = None + reachableTime: Annotated[ + Optional[int], + Field( + description="Time in milliseconds for Neighbor Unreachability Detection.", + ge=0, + le=3600000, + title="Reachable Time", + ), + ] = 0 + retransmitTime: Annotated[ + int, + Field( + description="Time in milliseconds between retransmitted NS messages.", + ge=0, + le=1800000, + title="Retransmit Time", + ), + ] + routerLifetime: Annotated[ + int, + Field( + description="Router lifetime in seconds for default gateway.", + ge=0, + le=9000, + title="Router Lifetime", + ), + ] + + +VirtualNetworkSpecRoutedInterfaceSpecL3ProxyARPND = IRBInterfaceSpecL3ProxyARPND + + +class VirtualNetworkSpecRoutedInterfaceSpec(BaseModel): + """ + Specification of the RoutedInterface + """ + + arpTimeout: Annotated[ + Optional[int], + Field( + description="Duration of time that dynamic ARP entries remain in the ARP cache before they expire.", + title="ARP Timeout", + ), + ] = 14400 + bfd: Annotated[ + Optional[VirtualNetworkSpecRoutedInterfaceSpecBfd], + Field( + description="Enables BFD on the RoutedInterface.", title="BFD Configuration" + ), + ] = None + description: Annotated[ + Optional[str], + Field( + description="The description of the RoutedInterface.", title="Description" + ), + ] = None + egress: Annotated[ + Optional[VirtualNetworkSpecRoutedInterfaceSpecEgress], + Field( + description="Manages actions on traffic at Egress.", title="Egress Actions" + ), + ] = None + ingress: Annotated[ + Optional[VirtualNetworkSpecRoutedInterfaceSpecIngress], + Field( + description="Manages actions on traffic at Ingress.", + title="Ingress Actions", + ), + ] = None + interface: Annotated[ + str, + Field( + description="Reference to an Interface to use for attachment.", + title="Interface", + ), + ] + ipMTU: Annotated[ + Optional[int], + Field( + description="IP MTU for the RoutedInterface.", + ge=1280, + le=9486, + title="IP MTU", + ), + ] = 1500 + ipv4Addresses: Annotated[ + Optional[List[VirtualNetworkSpecRoutedInterfaceSpecIpv4Address]], + Field( + description="List of IPv4 addresses in IP/mask form, e.g., 192.168.0.1/24.", + title="IPv4 Addresses", + ), + ] = None + ipv4Parameters: Annotated[ + Optional[VirtualNetworkSpecRoutedInterfaceSpecIpv4Parameters], + Field(title="IPv4-specific Parameters"), + ] = None + ipv6Addresses: Annotated[ + Optional[List[VirtualNetworkSpecRoutedInterfaceSpecIpv6Address]], + Field( + description="List of IPv6 addresses in IP/mask form, e.g., fc00::1/120.", + title="IPv6 Addresses", + ), + ] = None + ipv6RouterAdvertisement: Annotated[ + Optional[VirtualNetworkSpecRoutedInterfaceSpecIpv6RouterAdvertisement], + Field(title="IPv6 Router Advertisement"), + ] = None + l3ProxyARPND: Annotated[ + Optional[VirtualNetworkSpecRoutedInterfaceSpecL3ProxyARPND], + Field( + description="L3 Proxy ARP and ND configuration.", title="L3 Proxy ARP/ND" + ), + ] = None + learnUnsolicited: Annotated[ + Optional[Literal["BOTH", "GLOBAL", "LINK-LOCAL", "NONE"]], + Field( + description="Enable or disable learning of unsolicited ARPs.", + title="Learn Unsolicited ARPs", + ), + ] = "NONE" + router: Annotated[str, Field(description="Reference to a Router.", title="Router")] + unnumbered: Annotated[ + Optional[Literal["IPV6"]], + Field( + description="Enables the use of unnumbered interfaces on the IRBInterface. If IPv6 is specified, no IP address are configured on the sub-interface and only the link local address will be used. If any IP addresses are specified for either IPv4 or IPv6 that will take precedence and IPs will be assigned to the interfaces. (Deprecated, Use IPv6RouterAdvertisement)", + title="Unnumbered", + ), + ] = None + vlanID: Annotated[ + Optional[str], + Field( + description="Single value between 1-4094 support, ranges supported in the format x-y,x-y, or the special keyword null, any, untagged or pool for auto allocation.", + title="VLAN ID", + ), + ] = "pool" + vlanPool: Annotated[ + Optional[str], + Field( + description="Reference to a VLAN pool to use for allocations.", + title="VLAN Pool", + ), + ] = "vlan-pool" + + +class VirtualNetworkSpecRoutedInterface(BaseModel): + name: Annotated[ + str, + Field( + description="The name of the RoutedInterface.", + title="Routed Interface Name", + ), + ] + spec: Annotated[ + VirtualNetworkSpecRoutedInterfaceSpec, + Field( + description="Specification of the RoutedInterface", + title="Routed Interface Spec", + ), + ] + + +VirtualNetworkSpecRouterSpecBgpIpAliasNexthop = RouterSpecBgpIpAliasNexthop + + +VirtualNetworkSpecRouterSpecBgpIpv4UnicastMultipath = RouterSpecBgpIpv4UnicastMultipath + + +class VirtualNetworkSpecRouterSpecBgpIpv4Unicast(BaseModel): + """ + Parameters relating to the IPv4 unicast AFI/SAFI. + """ + + advertiseIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables advertisement of IPv4 Unicast routes with IPv6 next-hops to peers.", + title="Advertise IPv6 Next Hops", + ), + ] = None + enabled: Annotated[ + bool, Field(description="Enables the IPv4 unicast AFISAFI.", title="Enabled") + ] + multipath: Annotated[ + Optional[VirtualNetworkSpecRouterSpecBgpIpv4UnicastMultipath], + Field(description="Enable multipath.", title="Multipath"), + ] = None + receiveIPV6NextHops: Annotated[ + Optional[bool], + Field( + description="Enables the advertisement of the RFC 5549 capability to receive IPv4 routes with IPv6 next-hops.", + title="Receive IPv6 Next Hops", + ), + ] = None + + +VirtualNetworkSpecRouterSpecBgpIpv6UnicastMultipath = RouterSpecBgpIpv6UnicastMultipath + + +class VirtualNetworkSpecRouterSpecBgpIpv6Unicast(BaseModel): + """ + Parameters relating to the IPv6 unicast AFI/SAFI. + """ + + enabled: Annotated[ + bool, Field(description="Enables the IPv6 unicast AFISAFI", title="Enabled") + ] + multipath: Annotated[ + Optional[VirtualNetworkSpecRouterSpecBgpIpv6UnicastMultipath], + Field(description="Enable multipath", title="Multipath"), + ] = None + + +class VirtualNetworkSpecRouterSpecBgp(BaseModel): + """ + BGP configuration. + """ + + autonomousSystem: Annotated[ + Optional[int], + Field( + description="Autonomous System number for BGP.", + ge=1, + le=4294967295, + title="Autonomous System", + ), + ] = None + ebgpPreference: Annotated[ + Optional[int], + Field( + description="Preference to be set for eBGP [default=170].", + ge=1, + le=255, + title="eBGP Preference", + ), + ] = 170 + enabled: Annotated[ + Optional[bool], Field(description="Enable or disable BGP.", title="Enable BGP") + ] = False + ibgpPreference: Annotated[ + Optional[int], + Field( + description="Preference to be set for iBGP [default=170].", + ge=1, + le=255, + title="iBGP Preference", + ), + ] = 170 + ipAliasNexthops: Annotated[ + Optional[List[VirtualNetworkSpecRouterSpecBgpIpAliasNexthop]], + Field(description="IP aliasing configuration.", title="IP Alias Nexthops"), + ] = None + ipv4Unicast: Annotated[ + Optional[VirtualNetworkSpecRouterSpecBgpIpv4Unicast], + Field( + description="Parameters relating to the IPv4 unicast AFI/SAFI.", + title="IPv4 Unicast", + ), + ] = None + ipv6Unicast: Annotated[ + Optional[VirtualNetworkSpecRouterSpecBgpIpv6Unicast], + Field( + description="Parameters relating to the IPv6 unicast AFI/SAFI.", + title="IPv6 Unicast", + ), + ] = None + keychain: Annotated[ + Optional[str], + Field(description="Keychain to be used for authentication", title="Keychain"), + ] = None + minWaitToAdvertise: Annotated[ + Optional[int], + Field( + description="Minimum wait time before advertising routes post BGP restart.", + ge=0, + le=3600, + title="Min Wait To Advertise Time", + ), + ] = 0 + rapidWithdrawl: Annotated[ + Optional[bool], + Field( + description="Enable rapid withdrawal in BGP.", + title="Enable Rapid Withdrawal", + ), + ] = True + waitForFIBInstall: Annotated[ + Optional[bool], + Field( + description="Wait for FIB installation before advertising routes.", + title="Wait for FIB Installation", + ), + ] = False + + +VirtualNetworkSpecRouterSpecIpLoadBalancingPrefixItem = ( + RouterSpecIpLoadBalancingPrefixItem +) + + +class VirtualNetworkSpecRouterSpecIpLoadBalancing(BaseModel): + """ + IPv4 or IPv6 prefix. Active routes in the FIB that exactly match this prefix or that are longer matches of this prefix are provided with resilient-hash programming. + """ + + prefix: Annotated[ + Optional[List[VirtualNetworkSpecRouterSpecIpLoadBalancingPrefixItem]], + Field( + description="IPv4 or IPv6 prefix. Active routes in the FIB that exactly match this prefix or that are longer matches of this prefix are provided with resilient-hash programming.", + title="Prefix", + ), + ] = None + + +VirtualNetworkSpecRouterSpecRouteLeaking = RouterSpecRouteLeaking + + +class VirtualNetworkSpecRouterSpec(BaseModel): + """ + Specification of the Router + """ + + bgp: Annotated[ + Optional[VirtualNetworkSpecRouterSpecBgp], + Field(description="BGP configuration.", title="BGP Configuration"), + ] = None + description: Annotated[ + Optional[str], + Field(description="The description of the Router.", title="Description"), + ] = None + evi: Annotated[ + Optional[int], + Field( + description="EVI for the Router; leave blank for auto-allocation from EVI pool.", + ge=1, + le=65535, + title="EVI", + ), + ] = None + eviPool: Annotated[ + Optional[str], + Field( + description="Reference to EVI pool for auto-allocation.", + title="EVI Allocation Pool", + ), + ] = "evi-pool" + exportTarget: Annotated[ + Optional[str], + Field( + description="Export route target in 'target:N:N' format, if not specified, the default value taken as \"target:1:\".", + pattern="^target.*$", + title="Export Target", + ), + ] = None + importTarget: Annotated[ + Optional[str], + Field( + description="Import route target in 'target:N:N' format, if not specified, the default value taken as \"target:1:\".", + pattern="^target.*$", + title="Import Target", + ), + ] = None + ipLoadBalancing: Annotated[ + Optional[VirtualNetworkSpecRouterSpecIpLoadBalancing], + Field( + description="IPv4 or IPv6 prefix. Active routes in the FIB that exactly match this prefix or that are longer matches of this prefix are provided with resilient-hash programming.", + title="Prefix", + ), + ] = None + nodeSelector: Annotated[ + Optional[List[str]], + Field( + description="Node selectors for deployment constraints. If Nodes are selected, the Router will only be deployed on the Nodes selected, if left blank it will be deployed on all Nodes for which there are IRB or RoutedInterfaces referencing this Router.", + title="Node Selector", + ), + ] = None + routeLeaking: Annotated[ + Optional[VirtualNetworkSpecRouterSpecRouteLeaking], + Field( + description="Route leaking controlled by routing policies in and out of the DefaultRouter.", + title="Route Leaking", + ), + ] = None + routerID: Annotated[ + Optional[str], Field(description="Router ID.", title="Router ID") + ] = None + tunnelIndexPool: Annotated[ + Optional[str], + Field( + description="Reference to tunnel index allocation pool.", + title="Tunnel Index Pool", + ), + ] = "tunnel-index-pool" + type: Annotated[ + Optional[Literal["SIMPLE", "EVPNVXLAN"]], + Field( + description="Select the type of Router. Simple doesn't include any overlay control plane or dataplane properties (EVPN/VXLAN). EVPNVXLAN includes the properties needed to provision this Router over an IP Fabric.", + title="Type", + ), + ] = "EVPNVXLAN" + vni: Annotated[ + Optional[int], + Field( + description="VNI for the Router; leave blank for auto-allocation from VNI pool.", + ge=1, + le=16777215, + title="VNI", + ), + ] = None + vniPool: Annotated[ + Optional[str], + Field( + description="Reference to VNI pool for auto-allocation.", + title="VNI Allocation Pool", + ), + ] = "vni-pool" + + +class VirtualNetworkSpecRouter(BaseModel): + name: Annotated[ + str, Field(description="The name of the Router.", title="Router Name") + ] + spec: Annotated[ + VirtualNetworkSpecRouterSpec, + Field(description="Specification of the Router", title="Router Spec"), + ] + + +VirtualNetworkSpecVlanSpecEgress = BridgeInterfaceSpecEgress + + +VirtualNetworkSpecVlanSpecIngress = BridgeInterfaceSpecIngress + + +VirtualNetworkSpecVlanSpecUplinkEgress = BridgeInterfaceSpecUplinkEgress + + +VirtualNetworkSpecVlanSpecUplinkIngress = BridgeInterfaceSpecUplinkIngress + + +class VirtualNetworkSpecVlanSpecUplink(BaseModel): + """ + The Uplink between your access breakout switch and your leaf switch. + """ + + egress: Annotated[ + Optional[VirtualNetworkSpecVlanSpecUplinkEgress], + Field( + description="Manages actions on traffic at Egress of the Local enpoint of the Uplink.", + title="Egress", + ), + ] = None + ingress: Annotated[ + Optional[VirtualNetworkSpecVlanSpecUplinkIngress], + Field( + description="Manages actions on traffic at Ingress of the Local enpoint of the Uplink.", + title="Ingress", + ), + ] = None + uplinkSelector: Annotated[ + Optional[List[str]], + Field( + description="Selects TopoLinks which connect a leaf switch to a breakout switch. This is the uplink between your access breakout switch and your leaf switch. There can only be a single TopoLink between the access breakout switch and the leaf switch, if more than one TopoLink is present between two devices the transaction will fail.", + title="Uplink Selector", + ), + ] = None + uplinkVLANID: Annotated[ + Optional[str], + Field( + description="The VLAN ID to be utilized to isolate traffic from the VLAN on the access breakout switch to the leaf switch on the selected uplink TopoLink.", + title="Uplink VLAN ID", + ), + ] = "pool" + uplinkVLANPool: Annotated[ + Optional[str], + Field( + description="A VLAN from this pool will be utilized to isolate traffic from the VLAN on the access breakout switch to the leaf switch on the selected uplink TopoLink.", + title="Uplink VLAN Pool", + ), + ] = None + + +class VirtualNetworkSpecVlanSpec(BaseModel): + """ + Specification of the Vlan + """ + + bridgeDomain: Annotated[ + str, + Field( + description="Reference to a BridgeDomain or SimpleBridgeDomain.", + title="Bridge Domain", + ), + ] + description: Annotated[ + Optional[str], + Field(description="The description of the VLAN.", title="Description"), + ] = None + egress: Annotated[ + Optional[VirtualNetworkSpecVlanSpecEgress], + Field(description="Manages actions on traffic at Egress.", title="Egress"), + ] = None + ingress: Annotated[ + Optional[VirtualNetworkSpecVlanSpecIngress], + Field(description="Manages actions on traffic at Ingress.", title="Ingress"), + ] = None + interfaceSelector: Annotated[ + List[str], + Field( + description="Interfaces to use for attachment to this VLAN based on the label selector. Selects Interfaces based on their associated labels.", + title="Interface Selector", + ), + ] + l2MTU: Annotated[ + Optional[int], + Field( + description="L2 MTU specifies the maximum sized Ethernet frame that can be transmitted on the subinterface. If a frame exceeds this size it is discarded. If the l2-mtu of the subinterface exceeds the port-mtu of the associated interface, the subinterface will remain operationally down.", + ge=1450, + le=9500, + title="L2 MTU", + ), + ] = None + macDuplicationDetectionAction: Annotated[ + Optional[ + Literal["Blackhole", "OperDown", "StopLearning", "UseBridgeDomainAction"] + ], + Field( + description="If Mac Duplication Detection is enabled on the associated Bridge Domain, this property will override the MDD action set in the BridgeDomain.", + title="MAC Duplication Detection Action", + ), + ] = None + splitHorizonGroup: Annotated[ + Optional[str], + Field( + description="Name of the Split Horizon Group to be used for this VLAN. All subinterfaces within this VLAN will be members of this Split Horizon Group.", + title="Split Horizon Group", + ), + ] = None + uplink: Annotated[ + Optional[VirtualNetworkSpecVlanSpecUplink], + Field( + description="The Uplink between your access breakout switch and your leaf switch.", + title="Uplink", + ), + ] = None + vlanID: Annotated[ + Optional[str], + Field( + description="Single value between 1-4094 support, ranges supported in the format x-y,x-y, or the special keyword null, any, untagged or pool for auto allocation.", + title="VLAN ID", + ), + ] = "pool" + vlanPool: Annotated[ + Optional[str], + Field( + description='Reference to a VLAN pool to use for allocations. [default="vlan-pool"]', + title="VLAN Pool", + ), + ] = None + + +class VirtualNetworkSpecVlan(BaseModel): + name: Annotated[str, Field(description="The name of the VLAN.", title="VLAN Name")] + spec: Annotated[ + VirtualNetworkSpecVlanSpec, + Field(description="Specification of the Vlan", title="VLAN Spec"), + ] + + +class VirtualNetworkSpec(BaseModel): + """ + VirtualNetworkSpec defines the desired state of VirtualNetwork + """ + + bridgeDomains: Annotated[ + Optional[List[VirtualNetworkSpecBridgeDomain]], + Field( + description="List of Subnets. [emits=BridgeDomain]", title="Bridge Domains" + ), + ] = None + bridgeInterfaces: Annotated[ + Optional[List[VirtualNetworkSpecBridgeInterface]], + Field( + description="List of BridgeInterfaces. [emits=BridgeInterface]", + title="Bridge Interfaces", + ), + ] = None + irbInterfaces: Annotated[ + Optional[List[VirtualNetworkSpecIrbInterface]], + Field( + description="List of IRBInterfaces. [emits=IRBInterface]", + title="IRB Interfaces", + ), + ] = None + protocols: Annotated[ + Optional[VirtualNetworkSpecProtocols], + Field(description="Protocols to configure.", title="Protocols"), + ] = None + routedInterfaces: Annotated[ + Optional[List[VirtualNetworkSpecRoutedInterface]], + Field( + description="List of RoutedInterface. [emits=RoutedInterface]", + title="Routed Interfaces", + ), + ] = None + routers: Annotated[ + Optional[List[VirtualNetworkSpecRouter]], + Field(description="List of Routers.[emits=Router]", title="Routers"), + ] = None + vlans: Annotated[ + Optional[List[VirtualNetworkSpecVlan]], + Field(description="List of VLANs. [emits=VLAN]", title="VLAN"), + ] = None + + +class VirtualNetworkStatus(BaseModel): + health: Annotated[ + Optional[int], + Field(description="Indicates the health score of the VNET.", title="Health"), + ] = None + healthScoreReason: Annotated[ + Optional[str], + Field( + description="Indicates the reason for the health score.", + title="Health Score Reason", + ), + ] = None + lastChange: Annotated[ + Optional[AwareDatetime], + Field( + description="The time when the state of the resource last changed.", + title="Last Change", + ), + ] = None + nodes: Annotated[ + Optional[List[str]], + Field( + description="List of Nodes on which the Router is deployed.", title="Nodes" + ), + ] = None + numBGPPeers: Annotated[ + Optional[int], + Field( + description="Total number of configured BGP Peers.", + title="Number of BGP Peers", + ), + ] = None + numBGPPeersOperDown: Annotated[ + Optional[int], + Field( + description="Total Number of BGP Peer operationally down.", + title="Number of BGP Peers Oper Down", + ), + ] = None + numIRBInterfaces: Annotated[ + Optional[int], + Field( + description="Total number of irb-interfaces configured by the VNET.", + title="Number of IRB Interfaces", + ), + ] = None + numIRBInterfacesOperDown: Annotated[ + Optional[int], + Field( + description="Total number of irb-interfaces configured by the VNET which are oper-down.", + title="Number of IRB Interfaces Oper Down", + ), + ] = None + numNodes: Annotated[ + Optional[int], + Field( + description="Total number of Nodes on which the VNET is configured.", + title="Number of Nodes", + ), + ] = None + numRoutedInterfaces: Annotated[ + Optional[int], + Field( + description="Total number of routed-interfaces configured by the VNET.", + title="Number of Routed Interfaces", + ), + ] = None + numRoutedInterfacesOperDown: Annotated[ + Optional[int], + Field( + description="Total number of routed-interfaces configured by the VNET which are oper-down.", + title="Number of Routed Interfaces Oper Down", + ), + ] = None + numSubInterfaces: Annotated[ + Optional[int], + Field( + description="Total number of sub-interfaces configured by the VNET.", + title="Number of Sub Interfaces", + ), + ] = None + numSubInterfacesOperDown: Annotated[ + Optional[int], + Field( + description="Total number of sub-interfaces configured by the VNET which are oper-down.", + title="Number of Sub Interfaces Oper Down", + ), + ] = None + operationalState: Annotated[ + Optional[str], + Field(description="Operational state of the VNET.", title="Operational State"), + ] = None + + +VirtualNetworkDeletedResourceEntry = BridgeDomainDeletedResourceEntry + + +class VirtualNetworkDeletedResources( + RootModel[List[VirtualNetworkDeletedResourceEntry]] +): + root: List[VirtualNetworkDeletedResourceEntry] + + +VirtualNetworkMetadata = BridgeDomainMetadata + + +class AppGroup(BaseModel): + apiVersion: Optional[str] = None + kind: Optional[str] = None + name: Optional[str] = None + preferredVersion: Optional[AppGroupVersion] = None + versions: Optional[List[AppGroupVersion]] = None + + +class ResourceHistory(RootModel[List[ResourceHistoryEntry]]): + root: List[ResourceHistoryEntry] + + +class Status(BaseModel): + apiVersion: Optional[str] = None + details: Optional[StatusDetails] = None + kind: Optional[str] = None + string: Optional[str] = None + + +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class WorkflowInputData(RootModel[List[WorkflowInputDataElem]]): + root: List[WorkflowInputDataElem] + + +class BridgeDomain(BaseModel): + """ + BridgeDomain is the Schema for the bridgedomains API + """ + + apiVersion: str + kind: str + metadata: BridgeDomainMetadata + spec: Annotated[ + BridgeDomainSpec, + Field( + description="The BridgeDomain enables the configuration and management of Layer 2 virtual networks. It includes settings for VNI, EVI, route targets for import and export, and tunnel index allocation. Additionally, the specification allows for advanced features such as MAC address table limits, aging, Proxy ARP and detection of MAC and IP duplication.", + title="Specification", + ), + ] + status: Annotated[ + Optional[BridgeDomainStatus], + Field( + description="BridgeDomainStatus defines the observed state of BridgeDomain", + title="Status", + ), + ] = None + + +class BridgeDomainList(BaseModel): + """ + BridgeDomainList is a list of bridgedomains + """ + + apiVersion: str + items: Optional[List[BridgeDomain]] = None + kind: str + + +class BridgeInterface(BaseModel): + """ + BridgeInterface is the Schema for the bridgeinterfaces API + """ + + apiVersion: str + kind: str + metadata: BridgeInterfaceMetadata + spec: Annotated[ + BridgeInterfaceSpec, + Field( + description="The BridgeInterface enables the attachment of network interfaces to a Bridge Domain. It includes settings for VLAN ID allocation, interface attachment, and actions on ingress and egress traffic. The specification supports integration with other network resources, such as Bridge Domains and Interfaces, and provides advanced features like MAC Duplication Detection with configurable actions.", + title="Specification", + ), + ] + status: Annotated[Optional[BridgeInterfaceStatus], Field(title="Status")] = None + + +class BridgeInterfaceList(BaseModel): + """ + BridgeInterfaceList is a list of bridgeinterfaces + """ + + apiVersion: str + items: Optional[List[BridgeInterface]] = None + kind: str + + +class DHCPRelay(BaseModel): + """ + DHCPRelay is the Schema for the dhcprelays API + """ + + apiVersion: str + kind: str + metadata: DHCPRelayMetadata + spec: Annotated[ + DHCPRelaySpec, + Field( + description="The DHCPRelay enables the forwarding of DHCP requests and responses between clients and servers across different networks. This resource allows for the configuration of various DHCP relay sub-options, such as CircuitID, RemoteID, and ClientLinkLayerAddress, to provide detailed client information. It also includes settings for specifying the router to reach the DHCP server, the list of DHCP servers to forward requests to, and selectors for Routed and IRB interfaces where the relay will be configured. Additionally, the GI Address option can be set to derive the Gateway IP address from the selected interface, ensuring correct routing of DHCP messages.", + title="Specification", + ), + ] + status: Annotated[ + Optional[Dict[str, Any]], + Field( + description="DHCPRelayStatus defines the observed state of DHCPRelay", + title="Status", + ), + ] = None + + +class DHCPRelayList(BaseModel): + """ + DHCPRelayList is a list of dhcprelays + """ + + apiVersion: str + items: Optional[List[DHCPRelay]] = None + kind: str + + +class EdgePing(BaseModel): + """ + EdgePing is the Schema for the edgepings API + """ + + apiVersion: str + kind: str + metadata: EdgePingMetadata + spec: Annotated[ + EdgePingSpec, + Field( + description="EdgePingSpec defines the desired state of EdgePing", + title="Specification", + ), + ] + status: Annotated[ + Optional[EdgePingStatus], + Field( + description="EdgePingStatus defines the observed state of EdgePing", + title="Status", + ), + ] = None + + +class EdgePingList(BaseModel): + """ + EdgePingList is a list of edgepings + """ + + apiVersion: str + items: Optional[List[EdgePing]] = None + kind: str + + +class IRBInterface(BaseModel): + """ + IRBInterface is the Schema for the irbinterfaces API + """ + + apiVersion: str + kind: str + metadata: IRBInterfaceMetadata + spec: Annotated[ + IRBInterfaceSpec, + Field( + description="The IRBInterface enables the configuration and management of Layer 3 interfaces associated with a BridgeDomain. This resource allows for the specification of various parameters, including IP MTU, learning of unsolicited ARPs, IPv4 and IPv6 addresses, and unnumbered interface settings. It also supports advanced features such as BFD configuration, Virtual IP discovery, and ARP/ND-related settings like Proxy ARP/ND and EVPN route advertisement.", + title="Specification", + ), + ] + status: Annotated[ + Optional[IRBInterfaceStatus], + Field( + description="IRBInterfaceStatus defines the observed state of IRBInterface", + title="Status", + ), + ] = None + + +class IRBInterfaceList(BaseModel): + """ + IRBInterfaceList is a list of irbinterfaces + """ + + apiVersion: str + items: Optional[List[IRBInterface]] = None + kind: str + + +class RoutedInterface(BaseModel): + """ + RoutedInterface is the Schema for the routedinterfaces API + """ + + apiVersion: str + kind: str + metadata: RoutedInterfaceMetadata + spec: Annotated[ + RoutedInterfaceSpec, + Field( + description="The RoutedInterface enables the configuration and management of Layer 3 interfaces for routing traffic between different networks. This resource allows for specifying an underlying Interface and Router, configuring VLAN IDs, and setting the IP MTU. It also supports the learning of unsolicited ARPs, defining both IPv4 and IPv6 addresses, and enabling unnumbered interfaces. Advanced features such as BFD configuration, Proxy ARP/ND, and ARP timeout settings are included to ensure robust and efficient routing.", + title="Specification", + ), + ] + status: Annotated[ + Optional[RoutedInterfaceStatus], + Field( + description="RoutedInterfaceStatus defines the observed state of RoutedInterface", + title="Status", + ), + ] = None + + +class RoutedInterfaceList(BaseModel): + """ + RoutedInterfaceList is a list of routedinterfaces + """ + + apiVersion: str + items: Optional[List[RoutedInterface]] = None + kind: str + + +class Router(BaseModel): + """ + Router is the Schema for the routers API + """ + + apiVersion: str + kind: str + metadata: RouterMetadata + spec: Annotated[ + RouterSpec, + Field( + description="The Router enables the configuration and management of routing functions within a network. This resource allows for setting a unique Router ID, configuring VNIs and EVIs with options for automatic allocation, and defining import and export route targets. It also includes advanced configuration options such as BGP settings, including autonomous system numbers, AFI/SAFI options, and route advertisement preferences. Node selectors can be used to constrain the deployment of the router to specific nodes within the network.", + title="Specification", + ), + ] + status: Annotated[ + Optional[RouterStatus], + Field( + description="RouterStatus defines the observed state of Router", + title="Status", + ), + ] = None + + +class RouterList(BaseModel): + """ + RouterList is a list of routers + """ + + apiVersion: str + items: Optional[List[Router]] = None + kind: str + + +class VLAN(BaseModel): + """ + VLAN is the Schema for the vlans API + """ + + apiVersion: str + kind: str + metadata: VLANMetadata + spec: Annotated[ + VLANSpec, + Field( + description="The VLAN enables the configuration and management of VLAN and their association with BridgeDomains. This resource allows for specifying the associated BridgeDomain, selecting interfaces based on label selectors, and configuring VLAN IDs with options for auto-allocation from a VLAN pool. It also supports advanced configurations such as ingress and egress traffic management, and overrides for MAC Duplication Detection actions when enabled in the associated BridgeDomain.", + title="Specification", + ), + ] + status: Annotated[Optional[VLANStatus], Field(title="Status")] = None + + +class VLANList(BaseModel): + """ + VLANList is a list of vlans + """ + + apiVersion: str + items: Optional[List[VLAN]] = None + kind: str + + +class VirtualNetwork(BaseModel): + """ + VirtualNetwork is the Schema for the virtualnetworks API + """ + + apiVersion: str + kind: str + metadata: VirtualNetworkMetadata + spec: Annotated[ + VirtualNetworkSpec, + Field( + description="VirtualNetworkSpec defines the desired state of VirtualNetwork", + title="Specification", + ), + ] + status: Annotated[Optional[VirtualNetworkStatus], Field(title="Status")] = None + + +class VirtualNetworkList(BaseModel): + """ + VirtualNetworkList is a list of virtualnetworks + """ + + apiVersion: str + items: Optional[List[VirtualNetwork]] = None + kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/services/v1alpha1/models.py b/pydantic_eda/apps/services/v1alpha1/models.py index b0fe99a..79fbae9 100644 --- a/pydantic_eda/apps/services/v1alpha1/models.py +++ b/pydantic_eda/apps/services/v1alpha1/models.py @@ -2,9 +2,11 @@ # filename: services.json from __future__ import annotations -from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel + from datetime import date +from typing import Annotated, Any, Dict, List, Literal, Optional + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -38,6 +40,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +100,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,10 +119,56 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + class BridgeDomainSpecL2proxyARPNDDynamicLearning(BaseModel): ageTime: Annotated[ Optional[int], @@ -440,7 +494,7 @@ class BridgeDomainStatus(BaseModel): class BridgeDomainDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -824,6 +878,32 @@ class DHCPRelayDeletedResources(RootModel[List[DHCPRelayDeletedResourceEntry]]): DHCPRelayMetadata = BridgeDomainMetadata +class EdgePingSpec(BaseModel): + """ + EdgePingSpec defines the desired state of EdgePing + """ + + destination: Annotated[Optional[str], Field(title="destination")] = None + interfaceResource: Annotated[Optional[str], Field(title="interfaceresource")] = None + pingType: Annotated[Literal["gateway", "edgemesh", "edge"], Field(title="pingtype")] + virtualNetwork: Annotated[Optional[str], Field(title="virtualnetwork")] = None + vlanID: Annotated[Optional[int], Field(title="vlanid")] = None + + +class EdgePingStatus(BaseModel): + """ + EdgePingStatus defines the observed state of EdgePing + """ + + id: Annotated[Optional[int], Field(description="Id", title="ID")] = None + result: Annotated[ + Optional[str], Field(description="Aggregate result of the Flow", title="Result") + ] = None + + +EdgePingMetadata = BridgeDomainMetadata + + class IRBInterfaceSpecBfd(BaseModel): """ Enable BFD on the IRBInterface. @@ -854,11 +934,11 @@ class IRBInterfaceSpecBfd(BaseModel): Optional[int], Field( description="The minimum interval between echo packets the local node can receive.", - ge=250000, + ge=0, le=100000000, title="Minimum Echo Receive Interval", ), - ] = 1000000 + ] = 0 requiredMinReceive: Annotated[ Optional[int], Field( @@ -868,6 +948,15 @@ class IRBInterfaceSpecBfd(BaseModel): title="Receive Interval", ), ] = 1000000 + ttl: Annotated[ + Optional[int], + Field( + description="Sets custom IP TTL or Hop Limit for multi-hop BFD sessions packets. Not appllicable to single-hop BFD sessions.", + ge=2, + le=255, + title="IP TTL/Hop Limit", + ), + ] = None IRBInterfaceSpecEgress = BridgeInterfaceSpecEgress @@ -991,6 +1080,16 @@ class IRBInterfaceSpecIpAddress(BaseModel): ] = None +class IRBInterfaceSpecIpv4Parameters(BaseModel): + directedBroadcast: Annotated[ + Optional[bool], + Field( + description="Allow receiving and forwarding of directed broadcast packets. Enabled when set to true.", + title="Directed Broadcast", + ), + ] = None + + class IRBInterfaceSpecIpv6RouterAdvertisementPrefix(BaseModel): """ IPv6Prefix defines the configuration for an IPv6 prefix advertisement. @@ -1254,6 +1353,10 @@ class IRBInterfaceSpec(BaseModel): title="IP MTU", ), ] = 1500 + ipv4Parameters: Annotated[ + Optional[IRBInterfaceSpecIpv4Parameters], + Field(title="IPv4-specific Parameters"), + ] = None ipv6RouterAdvertisement: Annotated[ Optional[IRBInterfaceSpecIpv6RouterAdvertisement], Field(title="IPv6 Router Advertisement"), @@ -1418,11 +1521,11 @@ class RoutedInterfaceSpecBfd(BaseModel): Optional[int], Field( description="The minimum interval between echo packets the local node can receive.", - ge=250000, + ge=0, le=100000000, title="Minimum Echo Receive Interval", ), - ] = 1000000 + ] = 0 requiredMinReceive: Annotated[ Optional[int], Field( @@ -1432,6 +1535,15 @@ class RoutedInterfaceSpecBfd(BaseModel): title="Receive Interval", ), ] = 1000000 + ttl: Annotated[ + Optional[int], + Field( + description="Sets custom IP TTL or Hop Limit for multi-hop BFD sessions packets. Not appllicable to single-hop BFD sessions.", + ge=2, + le=255, + title="IP TTL/Hop Limit", + ), + ] = None RoutedInterfaceSpecEgress = BridgeInterfaceSpecEgress @@ -1443,6 +1555,9 @@ class RoutedInterfaceSpecBfd(BaseModel): RoutedInterfaceSpecIpv4Address = IRBInterfaceStatusInterfaceIpv4Address +RoutedInterfaceSpecIpv4Parameters = IRBInterfaceSpecIpv4Parameters + + RoutedInterfaceSpecIpv6Address = IRBInterfaceStatusInterfaceIpv4Address @@ -1608,6 +1723,10 @@ class RoutedInterfaceSpec(BaseModel): title="IPv4 Addresses", ), ] = None + ipv4Parameters: Annotated[ + Optional[RoutedInterfaceSpecIpv4Parameters], + Field(title="IPv4-specific Parameters"), + ] = None ipv6Addresses: Annotated[ Optional[List[RoutedInterfaceSpecIpv6Address]], Field( @@ -2718,6 +2837,9 @@ class VirtualNetworkSpecIrbInterfaceSpecIpAddress(BaseModel): ] = None +VirtualNetworkSpecIrbInterfaceSpecIpv4Parameters = IRBInterfaceSpecIpv4Parameters + + VirtualNetworkSpecIrbInterfaceSpecIpv6RouterAdvertisementPrefix = ( IRBInterfaceSpecIpv6RouterAdvertisementPrefix ) @@ -2895,6 +3017,10 @@ class VirtualNetworkSpecIrbInterfaceSpec(BaseModel): title="IP MTU", ), ] = 1500 + ipv4Parameters: Annotated[ + Optional[VirtualNetworkSpecIrbInterfaceSpecIpv4Parameters], + Field(title="IPv4-specific Parameters"), + ] = None ipv6RouterAdvertisement: Annotated[ Optional[VirtualNetworkSpecIrbInterfaceSpecIpv6RouterAdvertisement], Field(title="IPv6 Router Advertisement"), @@ -3591,6 +3717,37 @@ class VirtualNetworkSpecProtocolsBgp(BaseModel): ] = None +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgpMed( + BaseModel +): + """ + Set a new MED value. + """ + + numericalValue: Annotated[ + Optional[int], + Field( + description="Fixed numerical value to set or add/subtract.", + ge=0, + le=4294967295, + title="MED Value", + ), + ] = None + operation: Annotated[ + Optional[Literal["Set", "Add", "Subtract"]], + Field( + description="The operation to perform on the MED value.", title="Operation" + ), + ] = None + valueType: Annotated[ + Optional[Literal["Fixed", "IGP"]], + Field( + description="Use a fixed value or an IGP metric to adjust the MED.", + title="Value Type", + ), + ] = None + + class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgp(BaseModel): """ Actions related to the BGP protocol. @@ -3627,6 +3784,12 @@ class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgp(BaseM title="Set Local Preference", ), ] = None + med: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgpMed + ], + Field(description="Set a new MED value.", title="Set MED"), + ] = None setOrigin: Annotated[ Optional[Literal["egp", "igp", "incomplete"]], Field( @@ -3651,11 +3814,64 @@ class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultAction(BaseMode ] = None -VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemActionBgp = ( - VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgp +VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemActionBgpMed = ( + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecDefaultActionBgpMed ) +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemActionBgp( + BaseModel +): + """ + Actions related to the BGP protocol. + """ + + asPathPrepend: Annotated[ + Optional[int], + Field( + description="AS number to prepend to the AS Path attributes.", + ge=1, + le=4294967295, + title="AS Path Prepend", + ), + ] = None + asPathRemove: Annotated[ + Optional[bool], + Field( + description="Clear the AS path to make it empty.", title="AS Path Remove" + ), + ] = None + asPathReplace: Annotated[ + Optional[List[int]], + Field( + description="Replace the existing AS path with a new AS_SEQUENCE containing the listed AS numbers.", + title="AS Path Replace", + ), + ] = None + localPreference: Annotated[ + Optional[int], + Field( + description="Set a new LOCAL_PREF value for matching BGP routes.", + ge=0, + le=4294967295, + title="Set Local Preference", + ), + ] = None + med: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemActionBgpMed + ], + Field(description="Set a new MED value.", title="Set MED"), + ] = None + setOrigin: Annotated[ + Optional[Literal["egp", "igp", "incomplete"]], + Field( + description="Set a new ORIGIN attribute for matching BGP routes.", + title="Set Origin", + ), + ] = None + + class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemAction( BaseModel ): @@ -3675,6 +3891,36 @@ class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemAction( ] = None +class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemMatchBgpAsPathMatch( + BaseModel +): + """ + AS Path match criteria. + """ + + asPathExpression: Annotated[ + Optional[str], + Field( + description="A singular regular expression string to match against AS_PATH objects. Mutually exclusive with the ASPathSet reference.", + title="AS Path Expression", + ), + ] = None + asPathSet: Annotated[ + Optional[str], + Field( + description="Reference to an ASPathSet resource. Mutually exclusive with the ASPathExpression.", + title="AS Path Set", + ), + ] = None + matchSetOptions: Annotated[ + Optional[Literal["Any", "All", "Invert"]], + Field( + description="The matching criteria that applies to the members in the referenced set.", + title="Match Set Options", + ), + ] = None + + class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemMatchBgp( BaseModel ): @@ -3682,6 +3928,12 @@ class VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemMatchBgp( Configuration for BGP-specific policy match criteria. """ + asPathMatch: Annotated[ + Optional[ + VirtualNetworkSpecProtocolsRoutingPoliciesPolicySpecStatementItemMatchBgpAsPathMatch + ], + Field(description="AS Path match criteria.", title="AS Path"), + ] = None communitySet: Annotated[ Optional[str], Field( @@ -3973,6 +4225,13 @@ class VirtualNetworkSpecProtocolsStaticRouteSpecNexthopGroup(BaseModel): title="Blackhole", ), ] = False + blackholeSendICMP: Annotated[ + Optional[bool], + Field( + description="When enabled, the router will generate ICMP Unreachable messages for packets destined to the blackhole route.", + title="Blackhole ICMP Generation", + ), + ] = None nexthops: Annotated[ Optional[List[VirtualNetworkSpecProtocolsStaticRouteSpecNexthopGroupNexthop]], Field(description="Ordered list of nexthops.", title="Nexthops"), @@ -4071,6 +4330,9 @@ class VirtualNetworkSpecProtocols(BaseModel): ) +VirtualNetworkSpecRoutedInterfaceSpecIpv4Parameters = IRBInterfaceSpecIpv4Parameters + + VirtualNetworkSpecRoutedInterfaceSpecIpv6Address = ( IRBInterfaceStatusInterfaceIpv4Address ) @@ -4240,6 +4502,10 @@ class VirtualNetworkSpecRoutedInterfaceSpec(BaseModel): title="IPv4 Addresses", ), ] = None + ipv4Parameters: Annotated[ + Optional[VirtualNetworkSpecRoutedInterfaceSpecIpv4Parameters], + Field(title="IPv4-specific Parameters"), + ] = None ipv6Addresses: Annotated[ Optional[List[VirtualNetworkSpecRoutedInterfaceSpecIpv6Address]], Field( @@ -4883,6 +5149,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class BridgeDomain(BaseModel): """ BridgeDomain is the Schema for the bridgedomains API @@ -4979,6 +5310,30 @@ class DHCPRelayList(BaseModel): kind: str +class EdgePing(BaseModel): + """ + EdgePing is the Schema for the edgepings API + """ + + apiVersion: str + kind: str + metadata: EdgePingMetadata + spec: Annotated[ + EdgePingSpec, + Field( + description="EdgePingSpec defines the desired state of EdgePing", + title="Specification", + ), + ] + status: Annotated[ + Optional[EdgePingStatus], + Field( + description="EdgePingStatus defines the observed state of EdgePing", + title="Status", + ), + ] = None + + class IRBInterface(BaseModel): """ IRBInterface is the Schema for the irbinterfaces API @@ -5135,3 +5490,13 @@ class VirtualNetworkList(BaseModel): apiVersion: str items: Optional[List[VirtualNetwork]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/siteinfo/v1alpha1/models.py b/pydantic_eda/apps/siteinfo/v1alpha1/models.py index c90474f..1af862f 100644 --- a/pydantic_eda/apps/siteinfo/v1alpha1/models.py +++ b/pydantic_eda/apps/siteinfo/v1alpha1/models.py @@ -2,8 +2,10 @@ # filename: siteinfo.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Optional -from pydantic import BaseModel, Field, RootModel + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -37,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -91,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -110,6 +118,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -163,7 +208,7 @@ class BannerStatus(BaseModel): class BannerDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -206,6 +251,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class Banner(BaseModel): """ Banner is the Schema for the banners API @@ -238,3 +348,13 @@ class BannerList(BaseModel): apiVersion: str items: Optional[List[Banner]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/system/v1alpha1/models.py b/pydantic_eda/apps/system/v1alpha1/models.py index b85a3b8..e444041 100644 --- a/pydantic_eda/apps/system/v1alpha1/models.py +++ b/pydantic_eda/apps/system/v1alpha1/models.py @@ -2,8 +2,10 @@ # filename: system.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Optional -from pydantic import BaseModel, Field, RootModel + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -37,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -91,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -110,6 +118,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -357,7 +402,7 @@ class MonitorAggregateStateSpec(BaseModel): class MonitorAggregateStateDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -537,6 +582,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class Monitor(BaseModel): """ Monitor is the Schema for the monitors API @@ -637,3 +747,13 @@ class MonitorStateList(BaseModel): apiVersion: str items: Optional[List[MonitorState]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/timing/v1alpha1/models.py b/pydantic_eda/apps/timing/v1alpha1/models.py index ff1b7c7..ae19e04 100644 --- a/pydantic_eda/apps/timing/v1alpha1/models.py +++ b/pydantic_eda/apps/timing/v1alpha1/models.py @@ -2,9 +2,10 @@ # filename: timing.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel -from datetime import date + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -38,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -92,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -111,6 +118,43 @@ class StatusDetails(BaseModel): name: Optional[str] = None +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + class UIResult(RootModel[str]): root: str @@ -216,7 +260,7 @@ class NTPClientStatus(BaseModel): ), ] = None lastChange: Annotated[ - Optional[date], + Optional[AwareDatetime], Field( description="The time when the state of the resource last changed", title="Last Change", @@ -238,7 +282,7 @@ class NTPClientStatus(BaseModel): class NTPClientDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None name: Optional[str] = None namespace: Optional[str] = None @@ -281,6 +325,71 @@ class Status(BaseModel): string: Optional[str] = None +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + class NTPClient(BaseModel): """ NTPClient is the Schema for the ntpclients API @@ -313,3 +422,13 @@ class NTPClientList(BaseModel): apiVersion: str items: Optional[List[NTPClient]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/apps/topologies/v1alpha1/models.py b/pydantic_eda/apps/topologies/v1alpha1/models.py index 8b9dd95..21d5ce4 100644 --- a/pydantic_eda/apps/topologies/v1alpha1/models.py +++ b/pydantic_eda/apps/topologies/v1alpha1/models.py @@ -2,8 +2,10 @@ # filename: topologies.json from __future__ import annotations + from typing import Annotated, Any, Dict, List, Optional -from pydantic import BaseModel, Field, RootModel + +from pydantic import AwareDatetime, BaseModel, Field, RootModel class AppGroupVersion(BaseModel): @@ -37,6 +39,12 @@ class ErrorResponse(BaseModel): description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' ), ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None errors: Annotated[ Optional[List[ErrorItem]], Field( @@ -91,7 +99,7 @@ class Resource(BaseModel): class ResourceHistoryEntry(BaseModel): author: Optional[str] = None changeType: Optional[str] = None - commitTime: Optional[str] = None + commitTime: Optional[AwareDatetime] = None hash: Optional[str] = None message: Optional[str] = None transactionId: Optional[int] = None @@ -110,241 +118,164 @@ class StatusDetails(BaseModel): name: Optional[str] = None -class UIResult(RootModel[str]): - root: str +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None -class CPUUtilOverlaySpecTopology(BaseModel): - """ - Reference to the topology that this overlay is extending. - """ +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None - group: Annotated[ - str, - Field( - description="The group of the application which published the topology this overlay is extending.", - title="Group", - ), - ] - name: Annotated[ - str, + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + +class TopologySpecOverlay(BaseModel): + enabled: Annotated[ + bool, Field( - description="The name of the resource which published the topology this overlay is extending.", - title="Name", + description="Enable or disable the generation of the status of this overlay", + title="Enabled", ), ] - version: Annotated[ + key: Annotated[ str, Field( - description="The version of the application which published the topology this overlay is extending.", - title="Version", + description="A unique key for identifying this overlay within the topology. This is used internally\nonly.", + title="Key", ), ] -class CPUUtilOverlaySpec(BaseModel): +class TopologySpec(BaseModel): """ - CPUUtilOverlaySpec defines the desired state of CPUUtilOverlay + TopologySpec defines the desired state of Topology """ enabled: Annotated[ bool, Field( - description="Enable or disable the generation of the status of this overlay", + description="Enable or disable the generation of the status of this topology", title="Enabled", ), ] - topology: Annotated[ - CPUUtilOverlaySpecTopology, - Field( - description="Reference to the topology that this overlay is extending.", - title="Topology", - ), - ] - uiDescription: Annotated[ - Optional[str], - Field( - description="A description of the overlay to expose in the UI", - title="UI Description", - ), - ] = None - uiDescriptionKey: Annotated[ + endpointSubtitle: Annotated[ Optional[str], Field( - description="The translation key for the description of the overlay to expose in the UI", - title="UI Description Key", + description="Override the subtitle to show for endpoints in the topology", + title="Endpoint Subtitle", ), ] = None - uiName: Annotated[ + linkSubtitle: Annotated[ Optional[str], Field( - description="The name of the overlay to expose in the UI", title="UI Name" + description="Override the subtitle to show for links in the topology", + title="Link Subtitle", ), ] = None - uiNameKey: Annotated[ + nodeSubtitle: Annotated[ Optional[str], Field( - description="The translation key for the name of the overlay to expose in the UI", - title="UI Name Key", + description="Override the subtitle to show for nodes in the topology", + title="Node Subtitle", ), ] = None - - -class CPUUtilOverlayDeletedResourceEntry(BaseModel): - commitTime: Optional[str] = None - hash: Optional[str] = None - name: Optional[str] = None - transactionId: Optional[int] = None - - -class CPUUtilOverlayDeletedResources( - RootModel[List[CPUUtilOverlayDeletedResourceEntry]] -): - root: List[CPUUtilOverlayDeletedResourceEntry] - - -class CPUUtilOverlayMetadata(BaseModel): - annotations: Optional[Dict[str, str]] = None - labels: Optional[Dict[str, str]] = None - name: Annotated[ - str, - Field( - max_length=253, - pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", - ), - ] - - -DeviationOverlaySpecTopology = CPUUtilOverlaySpecTopology - - -class DeviationOverlaySpec(BaseModel): - """ - DeviationOverlaySpec defines the desired state of DeviationOverlay - """ - - enabled: Annotated[ - bool, - Field( - description="Enable or disable the generation of the status of this overlay", - title="Enabled", - ), - ] - topology: Annotated[ - DeviationOverlaySpecTopology, + overlays: Annotated[ + List[TopologySpecOverlay], Field( - description="Reference to the topology that this overlay is extending.", - title="Topology", + description="The set of overlays supported with this topology", + title="Overlays", ), ] uiDescription: Annotated[ Optional[str], Field( - description="A description of the overlay to expose in the UI", + description="A description of the topology to expose in the UI", title="UI Description", ), ] = None uiDescriptionKey: Annotated[ Optional[str], Field( - description="The translation key for the description of the overlay to expose in the UI", + description="The translation key for the description of the topology to expose in the UI", title="UI Description Key", ), ] = None uiName: Annotated[ Optional[str], Field( - description="The name of the overlay to expose in the UI", title="UI Name" + description="The name of the topology to expose in the UI", title="UI Name" ), ] = None uiNameKey: Annotated[ Optional[str], Field( - description="The translation key for the name of the overlay to expose in the UI", + description="The translation key for the name of the topology to expose in the UI", title="UI Name Key", ), ] = None -DeviationOverlayDeletedResourceEntry = CPUUtilOverlayDeletedResourceEntry - - -class DeviationOverlayDeletedResources( - RootModel[List[DeviationOverlayDeletedResourceEntry]] -): - root: List[DeviationOverlayDeletedResourceEntry] - - -DeviationOverlayMetadata = CPUUtilOverlayMetadata - - -DiskOverlaySpecTopology = CPUUtilOverlaySpecTopology +class UIResult(RootModel[str]): + root: str -class DiskOverlaySpec(BaseModel): +class DeviationOverlaySpecTopology(BaseModel): """ - DiskOverlaySpec defines the desired state of DiskOverlay + Reference to the topology that this overlay is extending. """ - enabled: Annotated[ - bool, + group: Annotated[ + str, Field( - description="Enable or disable the generation of the status of this overlay", - title="Enabled", + description="The group of the application which published the topology this overlay is extending.", + title="Group", ), ] - topology: Annotated[ - DiskOverlaySpecTopology, + name: Annotated[ + str, Field( - description="Reference to the topology that this overlay is extending.", - title="Topology", + description="The name of the resource which published the topology this overlay is extending.", + title="Name", ), ] - uiDescription: Annotated[ - Optional[str], - Field( - description="A description of the overlay to expose in the UI", - title="UI Description", - ), - ] = None - uiDescriptionKey: Annotated[ - Optional[str], - Field( - description="The translation key for the description of the overlay to expose in the UI", - title="UI Description Key", - ), - ] = None - uiName: Annotated[ - Optional[str], - Field( - description="The name of the overlay to expose in the UI", title="UI Name" - ), - ] = None - uiNameKey: Annotated[ - Optional[str], + version: Annotated[ + str, Field( - description="The translation key for the name of the overlay to expose in the UI", - title="UI Name Key", + description="The version of the application which published the topology this overlay is extending.", + title="Version", ), - ] = None - - -DiskOverlayDeletedResourceEntry = CPUUtilOverlayDeletedResourceEntry - - -class DiskOverlayDeletedResources(RootModel[List[DiskOverlayDeletedResourceEntry]]): - root: List[DiskOverlayDeletedResourceEntry] - - -DiskOverlayMetadata = CPUUtilOverlayMetadata - - -LldpOverlaySpecTopology = CPUUtilOverlaySpecTopology + ] -class LldpOverlaySpec(BaseModel): +class DeviationOverlaySpec(BaseModel): """ - LldpOverlaySpec defines the desired state of lldp + DeviationOverlaySpec defines the desired state of DeviationOverlay """ enabled: Annotated[ @@ -355,7 +286,7 @@ class LldpOverlaySpec(BaseModel): ), ] topology: Annotated[ - LldpOverlaySpecTopology, + DeviationOverlaySpecTopology, Field( description="Reference to the topology that this overlay is extending.", title="Topology", @@ -390,22 +321,37 @@ class LldpOverlaySpec(BaseModel): ] = None -LldpOverlayDeletedResourceEntry = CPUUtilOverlayDeletedResourceEntry +class DeviationOverlayDeletedResourceEntry(BaseModel): + commitTime: Optional[AwareDatetime] = None + hash: Optional[str] = None + name: Optional[str] = None + transactionId: Optional[int] = None -class LldpOverlayDeletedResources(RootModel[List[LldpOverlayDeletedResourceEntry]]): - root: List[LldpOverlayDeletedResourceEntry] +class DeviationOverlayDeletedResources( + RootModel[List[DeviationOverlayDeletedResourceEntry]] +): + root: List[DeviationOverlayDeletedResourceEntry] -LldpOverlayMetadata = CPUUtilOverlayMetadata +class DeviationOverlayMetadata(BaseModel): + annotations: Optional[Dict[str, str]] = None + labels: Optional[Dict[str, str]] = None + name: Annotated[ + str, + Field( + max_length=253, + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + ), + ] -MemoryOverlaySpecTopology = CPUUtilOverlaySpecTopology +LldpOverlaySpecTopology = DeviationOverlaySpecTopology -class MemoryOverlaySpec(BaseModel): +class LldpOverlaySpec(BaseModel): """ - MemoryOverlaySpec defines the desired state of MemoryOverlay + LldpOverlaySpec defines the desired state of lldp """ enabled: Annotated[ @@ -416,7 +362,7 @@ class MemoryOverlaySpec(BaseModel): ), ] topology: Annotated[ - MemoryOverlaySpecTopology, + LldpOverlaySpecTopology, Field( description="Reference to the topology that this overlay is extending.", title="Topology", @@ -451,100 +397,14 @@ class MemoryOverlaySpec(BaseModel): ] = None -MemoryOverlayDeletedResourceEntry = CPUUtilOverlayDeletedResourceEntry - +LldpOverlayDeletedResourceEntry = DeviationOverlayDeletedResourceEntry -class MemoryOverlayDeletedResources(RootModel[List[MemoryOverlayDeletedResourceEntry]]): - root: List[MemoryOverlayDeletedResourceEntry] - - -MemoryOverlayMetadata = CPUUtilOverlayMetadata - - -class TopologySpecOverlay(BaseModel): - enabled: Annotated[ - bool, - Field( - description="Enable or disable the generation of the status of this overlay", - title="Enabled", - ), - ] - key: Annotated[ - str, - Field( - description="A unique key for identifying this overlay within the topology. This is used internally\nonly.", - title="Key", - ), - ] +class LldpOverlayDeletedResources(RootModel[List[LldpOverlayDeletedResourceEntry]]): + root: List[LldpOverlayDeletedResourceEntry] -class TopologySpec(BaseModel): - """ - TopologySpec defines the desired state of Topology - """ - enabled: Annotated[ - bool, - Field( - description="Enable or disable the generation of the status of this topology", - title="Enabled", - ), - ] - endpointSubtitle: Annotated[ - Optional[str], - Field( - description="Override the subtitle to show for endpoints in the topology", - title="Endpoint Subtitle", - ), - ] = None - linkSubtitle: Annotated[ - Optional[str], - Field( - description="Override the subtitle to show for links in the topology", - title="Link Subtitle", - ), - ] = None - nodeSubtitle: Annotated[ - Optional[str], - Field( - description="Override the subtitle to show for nodes in the topology", - title="Node Subtitle", - ), - ] = None - overlays: Annotated[ - List[TopologySpecOverlay], - Field( - description="The set of overlays supported with this topology", - title="Overlays", - ), - ] - uiDescription: Annotated[ - Optional[str], - Field( - description="A description of the topology to expose in the UI", - title="UI Description", - ), - ] = None - uiDescriptionKey: Annotated[ - Optional[str], - Field( - description="The translation key for the description of the topology to expose in the UI", - title="UI Description Key", - ), - ] = None - uiName: Annotated[ - Optional[str], - Field( - description="The name of the topology to expose in the UI", title="UI Name" - ), - ] = None - uiNameKey: Annotated[ - Optional[str], - Field( - description="The translation key for the name of the topology to expose in the UI", - title="UI Name Key", - ), - ] = None +LldpOverlayMetadata = DeviationOverlayMetadata class TopologyGroupingSpecGroupSelector(BaseModel): @@ -630,7 +490,7 @@ class TopologyGroupingSpec(BaseModel): ] = None -TopologyGroupingDeletedResourceEntry = CPUUtilOverlayDeletedResourceEntry +TopologyGroupingDeletedResourceEntry = DeviationOverlayDeletedResourceEntry class TopologyGroupingDeletedResources( @@ -639,20 +499,20 @@ class TopologyGroupingDeletedResources( root: List[TopologyGroupingDeletedResourceEntry] -TopologyGroupingMetadata = CPUUtilOverlayMetadata +TopologyGroupingMetadata = DeviationOverlayMetadata -TopologyDeletedResourceEntry = CPUUtilOverlayDeletedResourceEntry +TopologyDeletedResourceEntry = DeviationOverlayDeletedResourceEntry class TopologyDeletedResources(RootModel[List[TopologyDeletedResourceEntry]]): root: List[TopologyDeletedResourceEntry] -TopologyMetadata = CPUUtilOverlayMetadata +TopologyMetadata = DeviationOverlayMetadata -TrafficRateOverlaySpecTopology = CPUUtilOverlaySpecTopology +TrafficRateOverlaySpecTopology = DeviationOverlaySpecTopology class TrafficRateOverlaySpec(BaseModel): @@ -703,7 +563,7 @@ class TrafficRateOverlaySpec(BaseModel): ] = None -TrafficRateOverlayDeletedResourceEntry = CPUUtilOverlayDeletedResourceEntry +TrafficRateOverlayDeletedResourceEntry = DeviationOverlayDeletedResourceEntry class TrafficRateOverlayDeletedResources( @@ -712,7 +572,7 @@ class TrafficRateOverlayDeletedResources( root: List[TrafficRateOverlayDeletedResourceEntry] -TrafficRateOverlayMetadata = CPUUtilOverlayMetadata +TrafficRateOverlayMetadata = DeviationOverlayMetadata class AppGroup(BaseModel): @@ -734,40 +594,81 @@ class Status(BaseModel): string: Optional[str] = None -class CPUUtilOverlay(BaseModel): +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): """ - CPUUtilOverlay is the Schema for the cpuutiloverlays API + Topology is the Schema for the topologies API """ apiVersion: str kind: str - metadata: CPUUtilOverlayMetadata + metadata: TopologyMetadata spec: Annotated[ - CPUUtilOverlaySpec, + TopologySpec, Field( - description="CPUUtilOverlaySpec defines the desired state of CPUUtilOverlay", + description="TopologySpec defines the desired state of Topology", title="Specification", ), ] status: Annotated[ Optional[Dict[str, Any]], Field( - description="CPUUtilOverlayStatus defines the observed state of CPUUtilOverlay", + description="TopologyStatus defines the observed state of Topology", title="Status", ), ] = None -class CPUUtilOverlayList(BaseModel): - """ - CPUUtilOverlayList is a list of cpuutiloverlays - """ - - apiVersion: str - items: Optional[List[CPUUtilOverlay]] = None - kind: str - - class DeviationOverlay(BaseModel): """ DeviationOverlay is the Schema for the deviationoverlays API @@ -802,40 +703,6 @@ class DeviationOverlayList(BaseModel): kind: str -class DiskOverlay(BaseModel): - """ - DiskOverlay is the Schema for the diskoverlays API - """ - - apiVersion: str - kind: str - metadata: DiskOverlayMetadata - spec: Annotated[ - DiskOverlaySpec, - Field( - description="DiskOverlaySpec defines the desired state of DiskOverlay", - title="Specification", - ), - ] - status: Annotated[ - Optional[Dict[str, Any]], - Field( - description="DiskOverlayStatus defines the observed state of DiskOverlay", - title="Status", - ), - ] = None - - -class DiskOverlayList(BaseModel): - """ - DiskOverlayList is a list of diskoverlays - """ - - apiVersion: str - items: Optional[List[DiskOverlay]] = None - kind: str - - class LldpOverlay(BaseModel): """ LldpOverlay is the Schema for the lldpoverlays API @@ -870,64 +737,6 @@ class LldpOverlayList(BaseModel): kind: str -class MemoryOverlay(BaseModel): - """ - MemoryOverlay is the Schema for the memoryoverlays API - """ - - apiVersion: str - kind: str - metadata: MemoryOverlayMetadata - spec: Annotated[ - MemoryOverlaySpec, - Field( - description="MemoryOverlaySpec defines the desired state of MemoryOverlay", - title="Specification", - ), - ] - status: Annotated[ - Optional[Dict[str, Any]], - Field( - description="MemoryOverlayStatus defines the observed state of MemoryOverlay", - title="Status", - ), - ] = None - - -class MemoryOverlayList(BaseModel): - """ - MemoryOverlayList is a list of memoryoverlays - """ - - apiVersion: str - items: Optional[List[MemoryOverlay]] = None - kind: str - - -class Topology(BaseModel): - """ - Topology is the Schema for the topologies API - """ - - apiVersion: str - kind: str - metadata: TopologyMetadata - spec: Annotated[ - TopologySpec, - Field( - description="TopologySpec defines the desired state of Topology", - title="Specification", - ), - ] - status: Annotated[ - Optional[Dict[str, Any]], - Field( - description="TopologyStatus defines the observed state of Topology", - title="Status", - ), - ] = None - - class TopologyGrouping(BaseModel): """ TopologyGrouping is the Schema for the topologygroupings API @@ -1004,3 +813,13 @@ class TrafficRateOverlayList(BaseModel): apiVersion: str items: Optional[List[TrafficRateOverlay]] = None kind: str + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class ResourceTopology(BaseModel): + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None diff --git a/pydantic_eda/core/v25_8_1-rc1/models.py b/pydantic_eda/core/v25_8_1-rc1/models.py new file mode 100644 index 0000000..2c5428e --- /dev/null +++ b/pydantic_eda/core/v25_8_1-rc1/models.py @@ -0,0 +1,1815 @@ +# generated by datamodel-codegen: +# filename: core.json + +from __future__ import annotations + +from typing import Annotated, Any, Dict, List, Literal, Optional + +from pydantic import AwareDatetime, BaseModel, Field, RootModel + + +class AlarmData(BaseModel): + """ + The information about a single alarm or alarm history + """ + + acknowledged: Annotated[ + Optional[bool], + Field(description="An indication if the alarm has been acknowledged."), + ] = None + acknowledgedUntil: Annotated[ + Optional[str], + Field(description="Indicates the end time of the acknowledgement."), + ] = None + cleared: Annotated[ + Optional[bool], + Field(description="An indication if the alarm has been cleared."), + ] = None + clusterMember: Annotated[ + Optional[str], + Field(description="The cluster member that generated this alarm."), + ] = None + description: Annotated[ + Optional[str], Field(description="A description for the alarm.") + ] = None + group: Annotated[ + Optional[str], + Field( + description="Indicates the group of the resource the alarm is present on." + ), + ] = None + jsPath: Annotated[ + Optional[str], + Field( + description='a unnormalized jspath relating to the object in the alarm state. For\nexample\n.node{.name=="spine-1-1"}.srl{.version=="24.10.1"}.interface{.name=="ethernet-1-1"}.' + ), + ] = None + kind: Annotated[ + Optional[str], + Field(description="Indicates the kind of resource the alarm is present on."), + ] = None + lastAcknowledged: Annotated[ + Optional[str], Field(description="the time this alarm was last acknowledged.") + ] = None + lastChanged: Annotated[ + Optional[str], + Field( + description="The last time that the alarm was changed; as provided by the raiser of the alarm." + ), + ] = None + lastSuppressed: Annotated[ + Optional[str], Field(description="the time this alarm was last suppressed.") + ] = None + name: Annotated[ + Optional[str], + Field( + description="The unique name for the alarm, e.g. InterfaceDown-spine-1-1-ethernet-1-1." + ), + ] = None + namespace: Annotated[ + Optional[str], Field(description="The namespace of the alarm") + ] = None + occurrences: Annotated[ + Optional[int], + Field( + description="The number of occurrences of this alarm (the number of times it has been raised)." + ), + ] = None + parentAlarms: Annotated[ + Optional[List[str]], + Field( + description="The names of other alarms that are parents of this alarm. This may be used to\nfilter out alarms that are not a root cause." + ), + ] = None + probableCause: Annotated[ + Optional[str], + Field( + description="the probable cause for raising the alarm. This field is optional, and\nshould also be a description indicating the primary probable cause of the\nalarm, which may be enriched with relevant information from this specific\nalarm instance. The complete alarm below contains an example." + ), + ] = None + remedialAction: Annotated[ + Optional[str], + Field( + description="any remedial actions the user could try to resolve/clear the alarm. This\nfield is optional, and may also be enriched with relevant information\nfrom this specific alarm instance. The complete alarm below contains an\nexample." + ), + ] = None + resource: Annotated[ + Optional[str], + Field(description="The name of the resource that this alarm is present on."), + ] = None + severity: Annotated[ + Optional[Literal["warning", "minor", "major", "critical"]], + Field(description="Severity of the alarm"), + ] = None + sourceGroup: Annotated[ + Optional[str], + Field( + description="Indicates indicates the group of the resource that raised this alarm, e.g. interfaces.eda.nokia.com." + ), + ] = None + sourceKind: Annotated[ + Optional[str], + Field( + description="Indicates the Kind of the resource that raised this alarm, e.g. InterfaceState." + ), + ] = None + sourceResource: Annotated[ + Optional[str], + Field( + description="Indicates the the name of the resource that raised this alarm, e.g. spine-1-1-ethernet-1-1." + ), + ] = None + suppressed: Annotated[ + Optional[bool], + Field(description="An indication if the alarm has been suppressed."), + ] = None + suppressedUntil: Annotated[ + Optional[str], Field(description="Indicates the end time of the suppression.") + ] = None + type: Annotated[ + Optional[str], Field(description="A kind for the alarm, e.g. InterfaceDown") + ] = None + + +class AlarmHistoryData(BaseModel): + alarm: Optional[AlarmData] = None + index: Annotated[ + Optional[str], + Field( + description="The index of the history entry within the entries for a single alarm.." + ), + ] = None + + +class AlarmNamespaceAndName(BaseModel): + name: Annotated[Optional[str], Field(description="The name of an alarm")] = None + namespace: Annotated[ + Optional[str], Field(description="The namespace of an alarm") + ] = None + + +class AuthPasswordPolicy(BaseModel): + allowUserName: Annotated[ + Optional[bool], + Field( + description="If true, prevents passwords from being or containing the user name." + ), + ] = None + digits: Annotated[ + Optional[int], + Field( + description="Minimum number of digits required in a password. Can be zero.", + ge=0, + ), + ] = None + forceExpiredPasswordChange: Annotated[ + Optional[int], + Field( + description="The maximum number of days until a password change is enforced.\nA value of zero means no change is required.", + ge=0, + ), + ] = None + hashingAlgorithm: Annotated[ + Optional[Literal["argon2", "pbkdf2-sha512", "pbkdf2-sha256", "pbkdf2"]], + Field( + description="The hashing algorithm to use when hashing stored passwords." + ), + ] = None + length: Annotated[ + Optional[int], + Field(description="Minimum password length. This must be at least 1.", ge=1), + ] = None + lowerCase: Annotated[ + Optional[int], + Field( + description="Minimum number of lower case characters required in a password. Can be zero.", + ge=0, + ), + ] = None + maxFailureWaitSeconds: Annotated[ + Optional[int], + Field( + description="The number of seconds before the users access will be restored, after too many authentication failures.", + ge=0, + ), + ] = None + maxLoginFailure: Annotated[ + Optional[int], + Field( + description="The number of login/authentication failures before a lockout policy takes effect. Zero means no enforcement.", + ge=0, + ), + ] = None + passwordHistory: Annotated[ + Optional[int], + Field( + description="The number of passwords remembered to enforce no re-use of passwords. Zero means no re-use enforcement.", + ge=0, + ), + ] = None + permanentLockout: Annotated[ + Optional[bool], + Field( + description='If true, lockout is permanent and the users access must be re-enabled by an administrator.\nIf false, the users access will be re-enabled after "maxFailureWaitSeconds" seconds.' + ), + ] = None + resetTimeSeconds: Annotated[ + Optional[int], + Field( + description="When lockout is not permanent, the count of authentication failures for a user will be reset\nthis many seconds after the last authentication failure.", + ge=0, + ), + ] = None + specialChars: Annotated[ + Optional[int], + Field( + description="Minimum number of special characters required in a password. Can be zero.", + ge=0, + ), + ] = None + upperCase: Annotated[ + Optional[int], + Field( + description="Minimum number of upper case characters required in a password. Can be zero.", + ge=0, + ), + ] = None + + +class Credentials(BaseModel): + temporary: Annotated[ + Optional[bool], + Field( + description="This is true if the password being set is a temporary password. In this case the user\nis required to change the password after they login using the temporary password." + ), + ] = None + value: Annotated[ + Optional[str], Field(description="The new password for the user.") + ] = None + + +class ErrorIndex(BaseModel): + index: Optional[int] = None + + +class ErrorItem(BaseModel): + error: Optional[Dict[str, Any]] = None + type: Optional[str] = None + + +class ErrorResponse(BaseModel): + """ + Generic error response for REST APIs + """ + + code: Annotated[ + int, Field(description="the numeric HTTP error code for the response.") + ] + details: Annotated[ + Optional[str], Field(description="The optional details of the error response.") + ] = None + dictionary: Annotated[ + Optional[Dict[str, Any]], + Field( + description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' + ), + ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None + errors: Annotated[ + Optional[List[ErrorItem]], + Field( + description="Collection of errors in cases where more than one exists. This needs to be\nflexible so we can support multiple formats" + ), + ] = None + index: Optional[ErrorIndex] = None + internal: Annotated[ + Optional[int], + Field( + description="Internal error code in cases where we don't have an array of errors" + ), + ] = None + message: Annotated[ + str, Field(description="The basic text error message for the error response.") + ] + ref: Annotated[ + Optional[str], + Field( + description="Reference to the error source. Should typically be the URI of the request" + ), + ] = None + type: Annotated[ + Optional[str], + Field( + description="URI pointing at a document that describes the error and mitigation steps\nIf there is no document, point to the RFC for the HTTP error code" + ), + ] = None + + +class FlowListEntry(BaseModel): + id: Annotated[Optional[int], Field(description="The id of the workflow")] = None + name: Annotated[Optional[str], Field(description="Name of the workflow")] = None + namespace: Annotated[ + Optional[str], Field(description="The namespace in which the workflow ran") + ] = None + parentId: Annotated[ + Optional[int], Field(description="The id of the parent workflow, if any") + ] = None + state: Optional[ + Literal[ + "waitingToStart", + "running", + "waitingForInput", + "terminated", + "failed", + "completed", + "subflowWaitingForInput", + ] + ] = None + type: Annotated[Optional[str], Field(description="The type of workflow")] = None + + +class FlowListResult(BaseModel): + """ + A list of flows + """ + + flows: Optional[List[FlowListEntry]] = None + + +class FlowStage(BaseModel): + """ + Describes the stage of a workflow + """ + + completed: Annotated[ + Optional[bool], Field(description="True if the stage has completed") + ] = None + hadError: Annotated[ + Optional[bool], + Field(description="True if the stage is complete and there was an error"), + ] = None + name: Annotated[Optional[str], Field(description="Name of the flow stage")] = None + skipped: Annotated[ + Optional[bool], Field(description="True if the stage was skipped") + ] = None + started: Annotated[ + Optional[bool], Field(description="True if the stage has started") + ] = None + subFlowIds: Annotated[ + Optional[List[int]], + Field(description="The ids of flows triggered by the stage"), + ] = None + + +class GroupIDs(RootModel[List[str]]): + root: Annotated[ + List[str], Field(title="A list of user group identifiers (uuid values).") + ] + + +class GroupVersionKind(BaseModel): + group: Annotated[Optional[str], Field(description="Name of the API group")] = None + kind: Annotated[Optional[str], Field(description="The Kind of the resource")] = None + version: Annotated[Optional[str], Field(description="Version of the API group")] = ( + None + ) + + +class GroupVersionResource(BaseModel): + group: Annotated[Optional[str], Field(description="Name of the API group")] = None + resource: Annotated[ + Optional[str], Field(description="The plural name of the resource") + ] = None + version: Annotated[Optional[str], Field(description="Version of the API group")] = ( + None + ) + + +class HealthServiceStatus(BaseModel): + error: Annotated[ + Optional[str], Field(description="Detailed status if the service is not up.") + ] = None + status: Annotated[ + Literal["UP", "DOWN"], + Field(description="Health status of the given service. UP or DOWN."), + ] + + +class Identifier(BaseModel): + group: Optional[str] = None + id: Optional[int] = None + kind: Optional[str] = None + name: Optional[str] = None + namespace: Optional[str] = None + version: Optional[str] = None + + +class K8SPatchOp(BaseModel): + from_: Annotated[Optional[str], Field(alias="from")] = None + op: str + path: str + value: Optional[Dict[str, Any]] = None + x_permissive: Annotated[Optional[bool], Field(alias="x-permissive")] = None + + +class LabelCompletionResponse(BaseModel): + results: Optional[List[str]] = None + + +class LineSegment(BaseModel): + endLine: Optional[int] = None + startLine: Optional[int] = None + + +class Metadata(BaseModel): + annotations: Optional[Dict[str, str]] = None + labels: Optional[Dict[str, str]] = None + name: Annotated[ + str, + Field( + max_length=253, + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + ), + ] + namespace: Optional[str] = None + + +class NamespaceData(BaseModel): + """ + Information about an individual namespace + """ + + description: Annotated[ + Optional[str], Field(description="The description of the namespace") + ] = None + name: Annotated[Optional[str], Field(description="The namespace name")] = None + + +class NamespaceGetResponse(BaseModel): + """ + Body of the non streaming namespace get request + """ + + allNamesapces: Annotated[ + Optional[bool], + Field( + description="If true, the requestor is considered to have permission to access all namespaces" + ), + ] = None + namespaces: Annotated[ + Optional[List[NamespaceData]], Field(description="The list of namespaces") + ] = None + + +class NsCrGvkName(BaseModel): + gvk: Optional[GroupVersionKind] = None + name: Optional[str] = None + namespace: Optional[str] = None + + +class ProviderAuth(BaseModel): + bindCredential: Annotated[ + str, Field(description="Credentials to use when binding to an LDAP provider") + ] + bindDN: Annotated[ + str, Field(description="DN to use when binding to an LDAP provider") + ] + + +class QueryCompletion(BaseModel): + completion: Optional[str] = None + token: Optional[str] = None + + +class QueryCompletionResponse(BaseModel): + """ + The result of a successful query auto-completion request + """ + + completions: Annotated[ + Optional[List[QueryCompletion]], + Field(description="Array of possible auto-completion results."), + ] = None + + +class QueryFieldAnnotation(BaseModel): + end_char: Optional[int] = None + start_char: Optional[int] = None + + +class ResourceRule(BaseModel): + apiGroups: Annotated[ + List[str], + Field( + description='The API groups for the resources controlled by the rule.\nAn API group consists of an apiGroup and a version, e.g. "apigroup/version".\nThe API group can be a wildcard ("*"), in which case it will match any API group.\nIn addition, the version can be a wildcard.' + ), + ] + permissions: Annotated[ + Optional[Literal["none", "read", "readWrite"]], + Field(description="Permissions for resources specified by the rule."), + ] = None + resources: Annotated[ + List[str], + Field( + description='Names for the resources controlled by the rule.\nIt can be a wildcard ("*"), in which case it will match any resource\nin the matching API groups.' + ), + ] + + +class StoreAppInstalledSettings(BaseModel): + appId: Annotated[ + Optional[str], Field(description="The application identifier.") + ] = None + settings: Annotated[ + Optional[Dict[str, Dict[str, Any]]], + Field(description="The settings for the application as a JSON object."), + ] = None + + +class StoreAppVersion(BaseModel): + """ + The information about an application version available from a catalog. + At least one of "semVer" or "commitHash" must/will be defined. + """ + + appId: Annotated[ + Optional[str], Field(description="The identifier for the application") + ] = None + catalog: Annotated[ + Optional[str], + Field(description="The catalog in which this application version was found"), + ] = None + commitHash: Annotated[ + Optional[str], Field(description="The commit hash for the application version.") + ] = None + semVer: Annotated[ + Optional[str], + Field(description="The semantic version for the application version."), + ] = None + + +class StoreAppVersionMetadata(BaseModel): + publishedTime: Annotated[ + Optional[AwareDatetime], + Field( + description="The date and time when the application version was published." + ), + ] = None + + +class StoreAppVersionWithMetadata(BaseModel): + metadata: Optional[StoreAppVersionMetadata] = None + version: Optional[StoreAppVersion] = None + + +class StoreCategoryList(RootModel[List[str]]): + root: List[str] + + +class TableRule(BaseModel): + """ + A role rule controlling access to a EDB table. Note that + there is never write access to EDB. + """ + + path: Annotated[ + str, + Field( + description='EDB path to which this rule applies. It can end in ".*"\nin which case the final portion of the table path can be anything, if the\nprefix matches. It can end in ".**" in which case the table path can be\nanything if the prefix matches.', + min_length=1, + pattern="^\\\\..*", + ), + ] + permissions: Annotated[ + Literal["none", "read"], + Field(description="Permissions for the given EDB path."), + ] + + +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayAttrMetadata(BaseModel): + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoOverlayAttrQuery(BaseModel): + attributes: Optional[Dict[str, TopoOverlayAttrMetadata]] = None + query: Optional[str] = None + + +class TopoOverlayBadgeMetadata(BaseModel): + badge_name: Optional[str] = None + badge_path: Optional[str] = None + color: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + value: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoOverlayStateMetadata(BaseModel): + color: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + value: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + +class TopologyStateGroupSelector(BaseModel): + group: Annotated[ + Optional[str], + Field( + description='The group to assign to nodes that match the selector.\n+eda:ui:title="Group"' + ), + ] = None + nodeSelector: Annotated[ + Optional[List[str]], + Field( + description='+kubebuilder:validation:Optional\n+eda:ui:title="Node Selector"\n+eda:ui:format="labelselector"\nLabel selector to use to match nodes that should be assigned to this group.' + ), + ] = None + + +class TopologyStateTierSelector(BaseModel): + nodeSelector: Annotated[ + Optional[List[str]], + Field( + description='+kubebuilder:validation:Optional\n+eda:ui:title="Node Selector"\n+eda:ui:format="labelselector"\nLabel selector to use to match nodes that should be assigned to this tier.' + ), + ] = None + tier: Annotated[ + Optional[int], + Field( + description='The tier to assign to nodes that match the selector.\n+eda:ui:title="Tier"' + ), + ] = None + + +class TransactionContent(BaseModel): + apiVersion: Optional[str] = None + kind: Optional[str] = None + metadata: Optional[Metadata] = None + spec: Optional[Dict[str, Any]] = None + + +class TransactionId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A transaction identifier; these are assigned by the system to a posted transaction." + ), + ] = None + + +class TransactionInputResource(BaseModel): + isDelete: Optional[bool] = None + name: Optional[NsCrGvkName] = None + + +class TransactionNodeResult(BaseModel): + """ + The name of a node with changes from a transaction, and a list + of errors that occurred for the node + """ + + errors: Annotated[ + Optional[List[str]], Field(description="Resulting errors for the node") + ] = None + name: Annotated[Optional[str], Field(description="The name of the node")] = None + namespace: Annotated[ + Optional[str], Field(description="The namespace of the node") + ] = None + + +class TransactionNsCrGvkNames(BaseModel): + gvk: Optional[GroupVersionKind] = None + names: Optional[List[str]] = None + namespace: Optional[str] = None + + +class TransactionPatch(BaseModel): + patchOps: List[K8SPatchOp] + target: NsCrGvkName + + +class TransactionResultInputResources(BaseModel): + inputCrs: Annotated[ + Optional[List[TransactionInputResource]], + Field(description="List of input resources from the transaction"), + ] = None + limitedAccess: Annotated[ + Optional[bool], + Field( + description="This field is true if the list returned here is not the complete list of input resources in the transaction because the user does not have read-access to some of them" + ), + ] = None + + +class TransactionResultObjectString(BaseModel): + data: Optional[str] = None + + +class TransactionScriptResults(BaseModel): + executionTime: Optional[int] = None + + +class TransactionState(BaseModel): + state: Annotated[ + Optional[str], Field(description="The state of the transaction") + ] = None + + +class TransactionStructuredAppError(BaseModel): + message: Optional[str] = None + messageKey: Optional[str] = None + values: Optional[Dict[str, Dict[str, Any]]] = None + + +class TransactionSummaryResult(BaseModel): + """ + Summary of the result of a transaction + """ + + commitHash: Annotated[ + Optional[str], Field(description="The git commit hash for the transaction") + ] = None + description: Annotated[ + Optional[str], + Field( + description="The description of the transaction, as posted in the transaction request." + ), + ] = None + details: Annotated[ + Optional[str], + Field( + description="The type of details available for the transaction, as posted in the transaction request." + ), + ] = None + dryRun: Annotated[ + Optional[bool], + Field( + description="If true the transaction was not committed and ran in dry run mode." + ), + ] = None + id: Annotated[Optional[int], Field(description="The transaction identifier")] = None + lastChangeTimestamp: Annotated[ + Optional[str], Field(description="The time that the transaction completed.") + ] = None + state: Annotated[ + Optional[str], Field(description="The state of the transaction.") + ] = None + success: Annotated[ + Optional[bool], Field(description="True if the transaction was successful.") + ] = None + username: Annotated[ + Optional[str], Field(description="The user who posted the transaction.") + ] = None + + +class TransactionSummaryResults(BaseModel): + results: Annotated[ + Optional[List[TransactionSummaryResult]], + Field(description="array of summary-results for transactions"), + ] = None + + +class TransactionValue(BaseModel): + value: Optional[TransactionContent] = None + + +class UrlRule(BaseModel): + path: Annotated[ + str, + Field( + description='The API server URL path to which this rule applies. It can end in "/*"\nin which case the final portion of the URL path can be anything, if the\nprefix matches. It can end in "/**" in which case the URL path can be\nanything if the prefix matches.",', + min_length=1, + pattern="^/.*", + ), + ] + permissions: Annotated[ + Optional[Literal["none", "read", "readWrite"]], + Field(description="The permissions for the API server URL for the rule."), + ] = None + + +class UserStatus(BaseModel): + failedLoginSinceSuccessfulLogin: Optional[int] = None + isFederatedUser: Annotated[ + Optional[bool], + Field(description="True if the user comes from a federated LDAP server"), + ] = None + lastFailedLogin: Optional[str] = None + lastSuccessfulLogin: Optional[str] = None + temporarilyDisabled: Optional[bool] = None + + +class UserStorageInFileContent(BaseModel): + file_content: Annotated[ + str, + Field( + alias="file-content", + description="The desired content of the user-storage file. This will be base64 decoded before storing if the request indicates that the content is base64 encoded.", + ), + ] + + +class UserStorageOutDirEntry(BaseModel): + """ + user-storage directory entry + """ + + modification_time: Annotated[ + Optional[AwareDatetime], + Field( + alias="modification-time", + description="modification type of the item, if a file", + ), + ] = None + name: Annotated[str, Field(description="name of the item within the directory")] + type: Annotated[str, Field(description='type of the item; "file" or "directory"')] + + +class UserStorageOutFileContent(BaseModel): + file_content: Annotated[ + Optional[str], + Field( + alias="file-content", + description="content of the file, will be base64 encoded if the request asked for this", + ), + ] = None + file_deleted: Annotated[ + Optional[bool], + Field( + alias="file-deleted", + description="if present and true, indicates the file has been deleted; used for\nstreamed responses", + ), + ] = None + file_name: Annotated[str, Field(alias="file-name", description="name of the file")] + modification_time: Annotated[ + Optional[AwareDatetime], + Field( + alias="modification-time", + description="UTC modification time of the file, as an RFC 3339 date/time.\nNot valid if file-deleted is true (in a streamed response)", + ), + ] = None + + +class Workflow(BaseModel): + cr: Annotated[ + Dict[str, Dict[str, Any]], + Field(description="Custom resource that defines the workflow to execute"), + ] + description: Annotated[ + str, Field(description="Description message for the workflow") + ] + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowState(BaseModel): + runningState: Optional[str] = None + state: Optional[str] = None + + +class SingleVersionInfo(BaseModel): + builtDate: Annotated[ + Optional[str], Field(description="The build-time for the component.") + ] = None + version: Annotated[ + Optional[str], Field(description="The version string for the component.") + ] = None + + +class VersionInfo(RootModel[Optional[Dict[str, SingleVersionInfo]]]): + root: Optional[Dict[str, SingleVersionInfo]] = None + + +class AuthProviderAuth(BaseModel): + """ + If present, bind to LDAP server with the given credentials. Otherwise do not bind. + """ + + bindCredential: Annotated[ + str, Field(description="Credentials to use when binding to an LDAP provider") + ] + bindDN: Annotated[ + str, Field(description="DN to use when binding to an LDAP provider") + ] + + +class AuthProviderGroupSupport(BaseModel): + """ + Configuration for group import/sync with LDAP. If not present, groups will not synchronized with EDA. + """ + + NameLDAPAttribute: Annotated[ + str, Field(description="The LDAP group name attribute") + ] + filter: Annotated[ + Optional[str], + Field( + description="Further for filtering when retrieving LDAP groups. Ensure starts and ends with parentheses if using." + ), + ] = None + groupLDAPDN: Annotated[ + str, Field(description="The LDAP DN where groups are found.") + ] + memberAttribute: Annotated[ + Optional[str], + Field( + description='The group attribute for a members. Usually "member" or "memberUid".' + ), + ] = None + memberOfAttribute: Annotated[ + Optional[str], + Field( + description='If retrievalStrategy is "memberOf", this is the LDAP user attribute for group memberships.' + ), + ] = None + membershipAttributeType: Annotated[ + Optional[Literal["DN", "UID"]], + Field( + description="How users are identified in a group member entry: either DN or UID." + ), + ] = None + membershipUserAttribute: Annotated[ + Optional[str], + Field( + description="Only required if membershipAttributeType is UID; then it is the user attribute that should match the group member value." + ), + ] = None + objectClasses: Annotated[ + str, + Field( + description="The LDAP object class or classes used for groups. If more than one, they must be comma-separated." + ), + ] + retrievalStrategy: Annotated[ + Optional[Literal["member", "memberOf"]], + Field( + description='The strategy for retrieving groups. Should be "member" to get group membership from the group, or "memberOf" to get group membership from the user.' + ), + ] = None + + +class StoreAppRequirementsGraphItemInstalledAppVersion(BaseModel): + """ + The application version installed in the cluster, if installed. + """ + + appId: Annotated[ + Optional[str], Field(description="The identifier for the application") + ] = None + catalog: Annotated[ + Optional[str], + Field(description="The catalog in which this application version was found"), + ] = None + commitHash: Annotated[ + Optional[str], Field(description="The commit hash for the application version.") + ] = None + semVer: Annotated[ + Optional[str], + Field(description="The semantic version for the application version."), + ] = None + + +class StoreAppRequirementsGraphItemTargetAppVersion(BaseModel): + """ + This graph item instance contains the dependencies for this particular application version. + """ + + appId: Annotated[ + Optional[str], Field(description="The identifier for the application") + ] = None + catalog: Annotated[ + Optional[str], + Field(description="The catalog in which this application version was found"), + ] = None + commitHash: Annotated[ + Optional[str], Field(description="The commit hash for the application version.") + ] = None + semVer: Annotated[ + Optional[str], + Field(description="The semantic version for the application version."), + ] = None + + +class AccessQuery(BaseModel): + gvk: Optional[GroupVersionKind] = None + gvr: Optional[GroupVersionResource] = None + namespace: Annotated[ + Optional[str], + Field( + description="The namespace to check. Empty string (or omit) to check for cluster-wide access" + ), + ] = None + path: Annotated[ + Optional[str], + Field( + description="Target url or table of the access check. Provided when type is table or url" + ), + ] = None + permissions: Annotated[ + Optional[Literal["read", "readWrite"]], + Field(description="The permissions for the requested resource/url/table."), + ] = None + type: Annotated[ + Literal["gvk", "gvr", "url", "table"], + Field(description="The type of rule to check for"), + ] + + +class AccessResult(BaseModel): + access: Annotated[ + Optional[bool], + Field(description="Indicates if the user can access the requested resource"), + ] = None + error: Optional[ErrorResponse] = None + + +class AuthProvider(BaseModel): + auth: Optional[AuthProviderAuth] = None + enabled: Annotated[ + Optional[bool], + Field(description="If true, checking/syncing this LDAP provider is enabled."), + ] = None + groupSupport: Optional[AuthProviderGroupSupport] = None + idAttribute: Annotated[ + str, + Field( + description="Name of the LDAP attribute, which is used as a unique object identifier (UUID) for objects in LDAP." + ), + ] + import_: Annotated[ + Optional[bool], + Field( + alias="import", + description="If true, the LDAP information will be imported into the EDA (Keycloak) database.", + ), + ] = None + name: Annotated[ + str, Field(description="The name to give to the LDAP provider; must be unique.") + ] + pagination: Annotated[ + Optional[bool], + Field(description="Set to true if the LDAP server supports pagination."), + ] = None + periodicSync: Annotated[ + Optional[bool], + Field( + description="If true, periodic synchronization of new changed or newly created LDAP users to Keycloak will occur." + ), + ] = None + periodicSyncSecs: Annotated[ + Optional[int], + Field( + description="If periodic sync is enabled, this is the period in seconds that synchronization will occur." + ), + ] = None + rdnLDAPAttribute: Annotated[ + str, + Field( + description="Name of the LDAP attribute, which is used as RDN (top attribute) of typical user DN. Usually it's the same as the Username LDAP attribute, however it is not required." + ), + ] + readOnly: Annotated[ + bool, + Field( + description="If false, changes made to LDAP-mapped attribute via EDA will be synced back to the LDAP server. Otherwise, changes are not made in LDAP." + ), + ] + scope: Annotated[ + Optional[Literal["One Level", "Subtree"]], + Field( + description='Must be "One Level" or "Subtree". If "One Level", the search applies only for users in the DNs specified by User DNs. If "Subtree", the search applies to the whole subtree.' + ), + ] = None + timeout: Annotated[ + Optional[int], Field(description="LDAP connection timeout in milliseconds") + ] = None + tls: Annotated[ + Optional[bool], + Field(description="If true, encrypts the connection to LDAP using STARTTLS"), + ] = None + type: Annotated[ + Literal["ldap"], + Field(description='The type of provider. Currently only "ldap" is supported.'), + ] + url: Annotated[str, Field(description="Connection URL to your LDAP server")] + userDN: Annotated[ + str, + Field( + description="Full DN of LDAP tree where your users are. This DN is the parent of LDAP users." + ), + ] + userObjectClasses: Annotated[ + str, + Field( + description="All values of LDAP objectClass attribute for users in LDAP, divided by commas. (e.g. inetOrgPerson, organizationalPerson)." + ), + ] + userSearchFilter: Annotated[ + Optional[str], + Field( + description="Additional LDAP filter for filtering searched users. Leave this empty if you don't need an additional filter. Make sure that it starts with '(' and ends with ')'." + ), + ] = None + usernameAttribute: Annotated[ + str, + Field( + description="Name of the LDAP attribute, which is mapped as EDA username. For many LDAP server vendors it can be 'uid'." + ), + ] + uuid: Annotated[ + Optional[str], + Field( + description="The unique identifier given to the entry when it is created." + ), + ] = None + vendor: Annotated[str, Field(description="LDAP vendor (provider).")] + + +class AuthProviderTestParams(BaseModel): + action: Annotated[ + Literal["connection", "authentication"], + Field(description="The test action to take."), + ] + auth: Optional[ProviderAuth] = None + name: Annotated[ + Optional[str], Field(description="The name of the provider to test") + ] = None + timeout: Annotated[ + Optional[int], Field(description="LDAP connection timeout in milliseconds") + ] = None + tls: Annotated[ + Optional[bool], + Field(description="If true, encrypts the connection to LDAP using STARTTLS"), + ] = None + url: Annotated[str, Field(description="Connection URL to your LDAP server")] + + +class AuthProviders(RootModel[List[AuthProvider]]): + root: List[AuthProvider] + + +class AuthRole(BaseModel): + description: str + name: Annotated[ + str, + Field( + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" + ), + ] + namespace: Annotated[ + Optional[str], Field(pattern="^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$") + ] = None + resourceRules: Annotated[ + Optional[List[ResourceRule]], + Field(description="Rules for access to resources."), + ] = None + tableRules: Annotated[ + Optional[List[TableRule]], + Field(description="Rules for access to EDB tables, including via EQL."), + ] = None + urlRules: Annotated[ + Optional[List[UrlRule]], + Field(description="Rules for access to APIServer routes."), + ] = None + + +class AuthRoles(RootModel[List[AuthRole]]): + root: List[AuthRole] + + +class AuthUser(BaseModel): + email: Optional[str] = None + enabled: Optional[bool] = None + firstName: Optional[str] = None + groups: Annotated[ + Optional[List[str]], + Field( + description="contains the UUIDs of the groups of which the user is a member." + ), + ] = None + lastName: Optional[str] = None + maxSessions: Optional[int] = None + password: Optional[str] = None + status: Optional[UserStatus] = None + username: Optional[str] = None + uuid: Optional[str] = None + + +class AuthUserGroup(BaseModel): + description: Optional[str] = None + full_users: Annotated[ + Optional[List[AuthUser]], + Field( + alias="full-users", + description="contains the full user definitions of the users who are members of the group, if requested", + ), + ] = None + fullRoles: Annotated[ + Optional[List[AuthRole]], + Field( + description="contains the full role definitions of the Roles and ClusterRoles associated with the group, if requested" + ), + ] = None + isFederated: Annotated[ + Optional[bool], + Field( + description="if true, indicates that the group was imported from a federated LDAP server" + ), + ] = None + name: Optional[str] = None + roles: Annotated[ + Optional[List[str]], + Field( + description='Contains the names of the ClusterRoles and Roles roles associated with the group.\nA Role name has the form "namesspace:rolename", whereas a ClusteRole name is a\nsimple "rolename", without a colon or a namespace.' + ), + ] = None + users: Annotated[ + Optional[List[str]], + Field( + description="contains the usernames of the users who are members of the group" + ), + ] = None + uuid: Optional[str] = None + + +class AuthUserGroups(RootModel[List[AuthUserGroup]]): + root: List[AuthUserGroup] + + +class AuthUsers(RootModel[List[AuthUser]]): + root: List[AuthUser] + + +class CheckAccessRequest(RootModel[Optional[Dict[str, AccessQuery]]]): + """ + Body of a checkAccess request. Contains a key and AccessQuery for each resource/url/table to be checked for user access + """ + + root: Optional[Dict[str, AccessQuery]] = None + + +class CheckAccessResponse(RootModel[Optional[Dict[str, AccessResult]]]): + """ + Body of a access check response. Contains an AccessResult for each of the keys provided in the request + """ + + root: Optional[Dict[str, AccessResult]] = None + + +class CrAnnotation(BaseModel): + cr: Optional[NsCrGvkName] = None + lines: Optional[List[LineSegment]] = None + + +class FlowGetResponse(BaseModel): + error: Annotated[ + Optional[str], + Field(description="If no error is present, the flow completed successfully"), + ] = None + id: Annotated[Optional[int], Field(description="The id of the workflow")] = None + jsonResult: Annotated[ + Optional[str], Field(description="A JSON representation of the result") + ] = None + log: Annotated[Optional[str], Field(description="Log output from the flow")] = None + name: Annotated[Optional[str], Field(description="Name of the workflow")] = None + namespace: Annotated[ + Optional[str], Field(description="The namespace in which the flow ran") + ] = None + parentId: Annotated[ + Optional[int], Field(description="The id of the parent workflow, if any") + ] = None + stages: Annotated[ + Optional[List[FlowStage]], + Field(description="The list of stages of the workflow"), + ] = None + state: Optional[ + Literal[ + "waitingToStart", + "running", + "waitingForInput", + "terminated", + "failed", + "completed", + "subflowWaitingForInput", + ] + ] = None + subflowsWaitingForInput: Annotated[ + Optional[List[int]], + Field(description="The ids of any subflows that are waiting for user input"), + ] = None + type: Annotated[Optional[str], Field(description="The type of workflow")] = None + waitForInputPrompt: Annotated[ + Optional[str], Field(description="Set if the state is waiting for input") + ] = None + + +class GetLabelCompletionRequest(BaseModel): + gvk: Optional[GroupVersionKind] = None + limit: Annotated[ + Optional[int], Field(description="The maximum number of results to return") + ] = None + namespace: Annotated[ + Optional[str], + Field( + description="The namespace of the GVK if the CRD is namespaced\nrequired: true if the GVK is namespaced" + ), + ] = None + value: Annotated[ + str, + Field( + description="A key value string delimited by =. If the Value does not include an =\nit is assumed to be a Key lookup. If there is an =, everything before\nthe = is assumed to be the key and the lookup will be a value lookup" + ), + ] + + +class Health(BaseModel): + mode: Annotated[ + Literal["ACTIVE", "STANDBY"], + Field(description="Indication of the activity of this cluster."), + ] + services: Annotated[ + Optional[Dict[str, HealthServiceStatus]], + Field( + description="Detailed health of the services comprising the EDA cluster. Keyed by the name of the service." + ), + ] = None + status: Annotated[ + Literal["UP", "DEGRADED", "DOWN"], + Field(description="Overall health status of the EDA cluster."), + ] + timestamp: Annotated[ + AwareDatetime, Field(description="Time that the health report was generated.") + ] + + +class NodeConfigResponse(BaseModel): + annotations: Annotated[ + Optional[List[CrAnnotation]], + Field(description="The the list of annotations for the node configuration"), + ] = None + running: Annotated[ + Optional[str], Field(description="The current node configuration for the node") + ] = None + + +class Overlay(BaseModel): + endpoint_attr_queries: Optional[List[TopoOverlayAttrQuery]] = None + endpoint_state: Optional[List[TopoOverlayStateMetadata]] = None + endpoint_state_heading: Optional[str] = None + endpoint_state_heading_key: Optional[str] = None + group: Optional[str] = None + link_attr_queries: Optional[List[TopoOverlayAttrQuery]] = None + link_state: Optional[List[TopoOverlayStateMetadata]] = None + link_state_heading: Optional[str] = None + link_state_heading_key: Optional[str] = None + name: Optional[str] = None + node_attr_queries: Optional[List[TopoOverlayAttrQuery]] = None + node_badge: Optional[List[TopoOverlayBadgeMetadata]] = None + node_state: Optional[List[TopoOverlayStateMetadata]] = None + node_state_heading: Optional[str] = None + node_state_heading_key: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class Overlays(RootModel[List[Overlay]]): + root: List[Overlay] + + +class QueryField(BaseModel): + alias: Optional[bool] = None + annotations: Optional[List[QueryFieldAnnotation]] = None + display_name: Optional[str] = None + name: Optional[str] = None + type: Optional[str] = None + + +class QuerySchema(BaseModel): + fields: Optional[List[QueryField]] = None + + +class StoreAppManifest(BaseModel): + manifest: Annotated[ + Optional[Dict[str, Dict[str, Any]]], + Field(description="The application manifest as JSON"), + ] = None + metadata: Optional[StoreAppVersionMetadata] = None + version: Optional[StoreAppVersion] = None + + +class StoreAppRequirementsGraphItem(BaseModel): + appId: Annotated[ + str, + Field( + description="The application identifier to which the 'requires' elements of graph items will refer." + ), + ] + installedAppVersion: Optional[StoreAppRequirementsGraphItemInstalledAppVersion] = ( + None + ) + requires: Annotated[ + Optional[List[str]], + Field( + description="The identifiers for the applications on which this application version depends." + ), + ] = None + targetAppVersion: StoreAppRequirementsGraphItemTargetAppVersion + + +class StoreAppSummary(BaseModel): + appId: Annotated[ + Optional[str], Field(description="Unique ID identifying this application") + ] = None + catalogs: Annotated[ + Optional[List[str]], Field(description="Catalogs where this app was found") + ] = None + categories: Annotated[ + Optional[List[str]], Field(description="Application categories.") + ] = None + description: Annotated[ + Optional[str], + Field( + description="Application description that can be used for user display purposes" + ), + ] = None + infoVersion: Optional[StoreAppVersion] = None + infoVersionMetadata: Optional[StoreAppVersionMetadata] = None + installed: Annotated[ + Optional[bool], Field(description='"true" if the app is installed') + ] = None + installedVersion: Optional[StoreAppVersion] = None + installedVersionMetadata: Optional[StoreAppVersionMetadata] = None + latestVersion: Optional[StoreAppVersion] = None + latestVersionMetadata: Optional[StoreAppVersionMetadata] = None + supportedEndpoints: Annotated[ + Optional[List[str]], Field(description="Application supported endpoints.") + ] = None + title: Annotated[ + Optional[str], + Field( + description="Application title that can be used for user display purposes" + ), + ] = None + upgradable: Annotated[ + Optional[bool], + Field(description='"true" if there is a new version that can be installed'), + ] = None + + +class StoreAppSummaryList(RootModel[List[StoreAppSummary]]): + root: List[StoreAppSummary] + + +class StoreAppVersionList(RootModel[List[StoreAppVersionWithMetadata]]): + root: List[StoreAppVersionWithMetadata] + + +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class TopologyStateGroupingBase(BaseModel): + """ + Embed this type inside your topology tier CRD spec to determine the tiers and the + groups of the nodes in the topology. + """ + + groupSelectors: Annotated[ + Optional[List[TopologyStateGroupSelector]], + Field( + description='The set of selectors for assigning nodes to groups\n+eda:ui:title="Group Selectors"' + ), + ] = None + tierSelectors: Annotated[ + Optional[List[TopologyStateTierSelector]], + Field( + description='The set of selectors for assigning nodes to tiers\n+eda:ui:title="Tier Selectors"' + ), + ] = None + uiDescription: Annotated[ + Optional[str], + Field( + description='A description of the topology grouping to expose in the UI\n+eda:ui:title="UI Description"' + ), + ] = None + uiDescriptionKey: Annotated[ + Optional[str], + Field( + description='The translation key for the description of the topology grouping to expose in the UI\n+eda:ui:title="UI Description Key"' + ), + ] = None + uiName: Annotated[ + Optional[str], + Field( + description='The name of the topology grouping to expose in the UI\n+eda:ui:title="UI Name"' + ), + ] = None + uiNameKey: Annotated[ + Optional[str], + Field( + description='The translation key for the name of the topology grouping to expose in the UI\n+eda:ui:title="UI Name Key"' + ), + ] = None + + +class TransactionAppError(BaseModel): + rawError: Optional[str] = None + structuredError: Optional[TransactionStructuredAppError] = None + + +class TransactionIntentResult(BaseModel): + errors: Optional[List[TransactionAppError]] = None + intentName: Optional[NsCrGvkName] = None + outputCrs: Optional[List[NsCrGvkName]] = None + script: Optional[TransactionScriptResults] = None + + +class TransactionResultObject(BaseModel): + after: Optional[TransactionResultObjectString] = None + before: Optional[TransactionResultObjectString] = None + dataUnavailable: Annotated[ + Optional[bool], + Field(description="True if there is no data available for the result"), + ] = None + format: Annotated[ + Optional[str], Field(description="The format of the response - Text or YAML") + ] = None + + +class TransactionType(BaseModel): + create: Optional[TransactionValue] = None + delete: Optional[NsCrGvkName] = None + modify: Optional[TransactionValue] = None + patch: Optional[TransactionPatch] = None + replace: Optional[TransactionValue] = None + + +class UserStorageOutDirContent(BaseModel): + directory_path: Annotated[ + str, + Field( + alias="directory-path", + description="path for the directory within the users storage", + ), + ] + entries: Annotated[ + List[UserStorageOutDirEntry], + Field(description="array of entries for the items in the directory"), + ] + + +class WorkflowResult(BaseModel): + errorMessage: Optional[str] = None + resultMessage: Optional[str] = None + state: Optional[WorkflowState] = None + success: Optional[bool] = None + + +class WorkflowStatusSummary(BaseModel): + creationTime: Optional[str] = None + group: Optional[str] = None + id: Optional[int] = None + kind: Optional[str] = None + lastUpdate: Optional[str] = None + name: Optional[str] = None + namespace: Optional[str] = None + parent: Optional[Identifier] = None + rootWorkflow: Optional[Identifier] = None + state: Optional[WorkflowResult] = None + username: Optional[str] = None + version: Optional[str] = None + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class QueryResponse(BaseModel): + """ + The response for a non-streaming query request + """ + + data: Optional[List[Dict[str, Any]]] = None + jsonSchema: Annotated[ + Optional[Dict[str, Dict[str, Any]]], + Field( + description="The JSON schema definition for the query data being returned." + ), + ] = None + schema_: Annotated[Optional[QuerySchema], Field(alias="schema")] = None + + +class StoreAppRequirementsGraph(BaseModel): + graphItems: Annotated[ + Optional[List[StoreAppRequirementsGraphItem]], + Field( + description="The items in the requirements graph resulting from the request. Only present if the state is FINISHED." + ), + ] = None + state: Annotated[ + Optional[Literal["UNKNOWN", "RUNNING", "FINISHED", "FAILED"]], + Field(description="The state of the requirements graph generation request."), + ] = None + + +class TopoGroupingStateRequest(BaseModel): + name: Optional[str] = None + spec: Optional[TopologyStateGroupingBase] = None + + +class TopoStateRequest(BaseModel): + grouping: Optional[TopoGroupingStateRequest] = None + namespace: Optional[str] = None + overlays: Optional[List[str]] = None + + +class Topologies(RootModel[List[Topology]]): + root: List[Topology] + + +class TransactionCr(BaseModel): + type: Optional[TransactionType] = None + + +class TransactionExecutionResult(BaseModel): + changedCrs: Annotated[ + Optional[List[TransactionNsCrGvkNames]], + Field(description="List of changed CRs as part of the transaction"), + ] = None + executionSummary: Annotated[ + Optional[str], + Field(description="Information about time taken during processing"), + ] = None + generalErrors: Annotated[ + Optional[List[str]], + Field(description="List of general errors while running the transaction"), + ] = None + intentsRun: Annotated[ + Optional[List[TransactionIntentResult]], + Field(description="List of intents which ran as part of the transaction"), + ] = None + nodesWithConfigChanges: Annotated[ + Optional[List[TransactionNodeResult]], + Field( + description="List of nodes with configuration changes from the transaction" + ), + ] = None + topologySupported: Annotated[ + Optional[bool], + Field( + description="Whether a topology representation of this transaction is supported" + ), + ] = None + + +class TransactionTopologyResult(BaseModel): + overlayMetadata: Optional[Overlay] = None + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None + + +class Transaction(BaseModel): + crs: Annotated[ + List[TransactionCr], + Field(description="List of CRs to include in the transaction"), + ] + description: Annotated[ + str, Field(description="Description/commit message for the transaction") + ] + dryRun: Annotated[ + bool, + Field( + description="If true the transaction will not be committed and will run in dry run mode. If false the\ntransaction will be committed" + ), + ] + resultType: Annotated[ + Optional[str], + Field(description="The type of result - errors only, normal, or debug"), + ] = None + retain: Annotated[ + Optional[bool], + Field( + description="retain after results fetched - e.g. after call to get transaction result" + ), + ] = None From 2015ab0c0294d9c30e5c785fa1ae9f5adbc76471 Mon Sep 17 00:00:00 2001 From: hellt Date: Fri, 15 Aug 2025 17:43:00 +0200 Subject: [PATCH 3/5] added table --- README.md | 1 + pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a1e00b..0edb312 100644 --- a/README.md +++ b/README.md @@ -31,3 +31,4 @@ The following table matches the project version with the version of the EDA deli | pydantic_eda | EDA release | | ------------ | ----------- | | 0.3.2 | 25.4.1 | +| 0.4.0 | 25.8.1 | diff --git a/pyproject.toml b/pyproject.toml index 90c016d..ea09e02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "pydantic-eda" -version = "0.3.2" +version = "0.4.0" description = "Pydantic models for EDA OpenAPI specification" readme = "README.md" requires-python = "~=3.12" From 56c97503035f8523a3ce67c36337fad1601cb0e2 Mon Sep 17 00:00:00 2001 From: hellt Date: Sat, 16 Aug 2025 00:29:14 +0200 Subject: [PATCH 4/5] added replace for - in version --- gen_models.py | 2 +- pydantic_eda/core/v25_4_1/models.py | 1517 ----------------- .../{v25_8_1-rc1 => v25_8_1_rc1}/models.py | 0 3 files changed, 1 insertion(+), 1518 deletions(-) delete mode 100644 pydantic_eda/core/v25_4_1/models.py rename pydantic_eda/core/{v25_8_1-rc1 => v25_8_1_rc1}/models.py (100%) diff --git a/gen_models.py b/gen_models.py index 6ca9ad5..620beb4 100644 --- a/gen_models.py +++ b/gen_models.py @@ -96,7 +96,7 @@ def process_specs(self): api_name = "core" # core api has a v0.0.1 in the spec but that will change # for now use the version provided by a user from the cmd - api_version = self.version.replace(".", "_") + api_version = self.version.replace(".", "_").replace("-", "_") logger.debug(f"API name: {api_name}, API version: {api_version}") self.sanitize_schema_objects(spec_file, api_name, api_version) self.generate_classes_for_spec(spec_file, api_name, api_version) diff --git a/pydantic_eda/core/v25_4_1/models.py b/pydantic_eda/core/v25_4_1/models.py deleted file mode 100644 index 88611b7..0000000 --- a/pydantic_eda/core/v25_4_1/models.py +++ /dev/null @@ -1,1517 +0,0 @@ -# generated by datamodel-codegen: -# filename: core.json - -from __future__ import annotations -from typing import Annotated, Any, Dict, List, Literal, Optional -from pydantic import BaseModel, Field, RootModel -from datetime import datetime - - -class AlarmData(BaseModel): - """ - The information about a single alarm or alarm history - """ - - acknowledged: Annotated[ - Optional[bool], - Field(description="An indication if the alarm has been acknowledged."), - ] = None - acknowledgedUntil: Annotated[ - Optional[str], - Field(description="Indicates the end time of the acknowledgement."), - ] = None - cleared: Annotated[ - Optional[bool], - Field(description="An indication if the alarm has been cleared."), - ] = None - clusterMember: Annotated[ - Optional[str], - Field(description="The cluster member that generated this alarm."), - ] = None - description: Annotated[ - Optional[str], Field(description="A description for the alarm.") - ] = None - group: Annotated[ - Optional[str], - Field( - description="Indicates the group of the resource the alarm is present on." - ), - ] = None - jsPath: Annotated[ - Optional[str], - Field( - description='a unnormalized jspath relating to the object in the alarm state. For\nexample\n.node{.name=="spine-1-1"}.srl{.version=="24.10.1"}.interface{.name=="ethernet-1-1"}.' - ), - ] = None - kind: Annotated[ - Optional[str], - Field(description="Indicates the kind of resource the alarm is present on."), - ] = None - lastAcknowledged: Annotated[ - Optional[str], Field(description="the time this alarm was last acknowledged.") - ] = None - lastChanged: Annotated[ - Optional[str], - Field( - description="The last time that the alarm was changed; as provided by the raiser of the alarm." - ), - ] = None - lastSuppressed: Annotated[ - Optional[str], Field(description="the time this alarm was last suppressed.") - ] = None - name: Annotated[ - Optional[str], - Field( - description="The unique name for the alarm, e.g. InterfaceDown-spine-1-1-ethernet-1-1." - ), - ] = None - namespace: Annotated[ - Optional[str], Field(description="The namespace of the alarm") - ] = None - occurrences: Annotated[ - Optional[int], - Field( - description="The number of occurrences of this alarm (the number of times it has been raised)." - ), - ] = None - parentAlarms: Annotated[ - Optional[List[str]], - Field( - description="The names of other alarms that is are parents of this alarm. This is used to\nfilter out alarms that are not a root cause." - ), - ] = None - probableCause: Annotated[ - Optional[str], - Field( - description="the probable cause for raising the alarm. This field is optional, and\nshould also be a description indicating the primary probable cause of the\nalarm, which may be enriched with relevant information from this specific\nalarm instance. The complete alarm below contains an example." - ), - ] = None - remedialAction: Annotated[ - Optional[str], - Field( - description="any remedial actions the user could try to resolve/clear the alarm. This\nfield is optional, and may also be enriched with relevant information\nfrom this specific alarm instance. The complete alarm below contains an\nexample." - ), - ] = None - resource: Annotated[ - Optional[str], - Field(description="The name of the resource that this alarm is present on."), - ] = None - severity: Annotated[ - Optional[Literal["warning", "minor", "major", "critical"]], - Field(description="Severity of the alarm"), - ] = None - sourceGroup: Annotated[ - Optional[str], - Field( - description="Indicates indicates the group of the resource that raised this alarm, e.g. interfaces.eda.nokia.com." - ), - ] = None - sourceKind: Annotated[ - Optional[str], - Field( - description="Indicates the Kind of the resource that raised this alarm, e.g. InterfaceState." - ), - ] = None - sourceResource: Annotated[ - Optional[str], - Field( - description="Indicates the the name of the resource that raised this alarm, e.g. spine-1-1-ethernet-1-1." - ), - ] = None - suppressed: Annotated[ - Optional[bool], - Field(description="An indication if the alarm has been suppressed."), - ] = None - suppressedUntil: Annotated[ - Optional[str], Field(description="Indicates the end time of the suppression.") - ] = None - type: Annotated[ - Optional[str], Field(description="A kind for the alarm, e.g. InterfaceDown") - ] = None - - -class AlarmHistoryData(BaseModel): - alarm: Optional[AlarmData] = None - index: Annotated[ - Optional[str], - Field( - description="The index of the history entry within the entries for a single alarm.." - ), - ] = None - - -class AlarmNamespaceAndName(BaseModel): - name: Annotated[Optional[str], Field(description="The name of an alarm")] = None - namespace: Annotated[ - Optional[str], Field(description="The namespace of an alarm") - ] = None - - -class AuthPasswordPolicy(BaseModel): - allowUserName: Annotated[ - Optional[bool], - Field( - description="If true, prevents passwords from being or containing the user name." - ), - ] = None - digits: Annotated[ - Optional[int], - Field( - description="Minimum number of digits required in a password. Can be zero.", - ge=0, - ), - ] = None - forceExpiredPasswordChange: Annotated[ - Optional[int], - Field( - description="The maximum number of days until a password change is enforced.\nA value of zero means no change is required.", - ge=0, - ), - ] = None - hashingAlgorithm: Annotated[ - Optional[Literal["argon2", "pbkdf2-sha512", "pbkdf2-sha256", "pbkdf2"]], - Field( - description="The hashing algorithm to use when hashing stored passwords." - ), - ] = None - length: Annotated[ - Optional[int], - Field(description="Minimum password length. This must be at least 1.", ge=1), - ] = None - lowerCase: Annotated[ - Optional[int], - Field( - description="Minimum number of lower case characters required in a password. Can be zero.", - ge=0, - ), - ] = None - maxFailureWaitSeconds: Annotated[ - Optional[int], - Field( - description="The number of seconds before the users access will be restored, after too many authentication failures.", - ge=0, - ), - ] = None - maxLoginFailure: Annotated[ - Optional[int], - Field( - description="The number of login/authentication failures before a lockout policy takes effect. Zero means no enforcement.", - ge=0, - ), - ] = None - passwordHistory: Annotated[ - Optional[int], - Field( - description="The number of passwords remembered to enforce no re-use of passwords. Zero means no re-use enforcement.", - ge=0, - ), - ] = None - permanentLockout: Annotated[ - Optional[bool], - Field( - description='If true, lockout is permanent and the users access must be re-enabled by an administrator.\nIf false, the users access will be re-enabled after "maxFailureWaitSeconds" seconds.' - ), - ] = None - resetTimeSeconds: Annotated[ - Optional[int], - Field( - description="When lockout is not permanent, the count of authentication failures for a user will be reset\nthis many seconds after the last authentication failure.", - ge=0, - ), - ] = None - specialChars: Annotated[ - Optional[int], - Field( - description="Minimum number of special characters required in a password. Can be zero.", - ge=0, - ), - ] = None - upperCase: Annotated[ - Optional[int], - Field( - description="Minimum number of upper case characters required in a password. Can be zero.", - ge=0, - ), - ] = None - - -class Credentials(BaseModel): - temporary: Annotated[ - Optional[bool], - Field( - description="This is true if the password being set is a temporary password. In this case the user\nis required to change the password after they login using the temporary password." - ), - ] = None - value: Annotated[ - Optional[str], Field(description="The new password for the user.") - ] = None - - -class ErrorIndex(BaseModel): - index: Optional[int] = None - - -class ErrorItem(BaseModel): - error: Optional[Dict[str, Any]] = None - type: Optional[str] = None - - -class ErrorResponse(BaseModel): - """ - Generic error response for REST APIs - """ - - code: Annotated[ - int, Field(description="the numeric HTTP error code for the response.") - ] - details: Annotated[ - Optional[str], Field(description="The optional details of the error response.") - ] = None - dictionary: Annotated[ - Optional[Dict[str, Any]], - Field( - description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' - ), - ] = None - errors: Annotated[ - Optional[List[ErrorItem]], - Field( - description="Collection of errors in cases where more than one exists. This needs to be\nflexible so we can support multiple formats" - ), - ] = None - index: Optional[ErrorIndex] = None - internal: Annotated[ - Optional[int], - Field( - description="Internal error code in cases where we don't have an array of errors" - ), - ] = None - message: Annotated[ - str, Field(description="The basic text error message for the error response.") - ] - ref: Annotated[ - Optional[str], - Field( - description="Reference to the error source. Should typically be the URI of the request" - ), - ] = None - type: Annotated[ - Optional[str], - Field( - description="URI pointing at a document that describes the error and mitigation steps\nIf there is no document, point to the RFC for the HTTP error code" - ), - ] = None - - -class FlowListEntry(BaseModel): - id: Annotated[Optional[int], Field(description="The id of the workflow")] = None - name: Annotated[Optional[str], Field(description="Name of the workflow")] = None - namespace: Annotated[ - Optional[str], Field(description="The namespace in which the workflow ran") - ] = None - parentId: Annotated[ - Optional[int], Field(description="The id of the parent workflow, if any") - ] = None - state: Optional[ - Literal[ - "waitingToStart", - "running", - "waitingForInput", - "terminated", - "failed", - "completed", - "subflowWaitingForInput", - ] - ] = None - type: Annotated[Optional[str], Field(description="The type of workflow")] = None - - -class FlowListResult(BaseModel): - """ - A list of flows - """ - - flows: Optional[List[FlowListEntry]] = None - - -class FlowStage(BaseModel): - """ - Describes the stage of a workflow - """ - - completed: Annotated[ - Optional[bool], Field(description="True if the stage has completed") - ] = None - hadError: Annotated[ - Optional[bool], - Field(description="True if the stage is complete and there was an error"), - ] = None - name: Annotated[Optional[str], Field(description="Name of the flow stage")] = None - skipped: Annotated[ - Optional[bool], Field(description="True if the stage was skipped") - ] = None - started: Annotated[ - Optional[bool], Field(description="True if the stage has started") - ] = None - subFlowIds: Annotated[ - Optional[List[int]], - Field(description="The ids of flows triggered by the stage"), - ] = None - - -class GroupIDs(RootModel[List[str]]): - root: Annotated[ - List[str], Field(title="A list of user group identifiers (uuid values).") - ] - - -class GroupVersionKind(BaseModel): - group: Optional[str] = None - kind: Optional[str] = None - version: Optional[str] = None - - -class HealthServiceStatus(BaseModel): - error: Annotated[ - Optional[str], Field(description="Detailed status if the service is not up.") - ] = None - status: Annotated[ - Literal["UP", "DOWN"], - Field(description="Health status of the given service. UP or DOWN."), - ] - - -class K8SPatchOp(BaseModel): - from_: Annotated[Optional[str], Field(alias="from")] = None - op: str - path: str - value: Optional[Dict[str, Any]] = None - x_permissive: Annotated[Optional[bool], Field(alias="x-permissive")] = None - - -class LabelCompletionResponse(BaseModel): - results: Optional[List[str]] = None - - -class LineSegment(BaseModel): - endLine: Optional[int] = None - startLine: Optional[int] = None - - -class Metadata(BaseModel): - annotations: Optional[Dict[str, str]] = None - labels: Optional[Dict[str, str]] = None - name: Annotated[ - str, - Field( - max_length=253, - pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", - ), - ] - namespace: Optional[str] = None - - -class NamespaceData(BaseModel): - """ - Information about an individual namespace - """ - - description: Annotated[ - Optional[str], Field(description="The description of the namespace") - ] = None - name: Annotated[Optional[str], Field(description="The namespace name")] = None - - -class NamespaceGetResponse(BaseModel): - """ - Body of the non streaming namespace get request - """ - - allNamesapces: Annotated[ - Optional[bool], - Field( - description="If true, the requestor is considered to have permission to access all namespaces" - ), - ] = None - namespaces: Annotated[ - Optional[List[NamespaceData]], Field(description="The list of namespaces") - ] = None - - -class NsCrGvkName(BaseModel): - gvk: Optional[GroupVersionKind] = None - name: Optional[str] = None - namespace: Optional[str] = None - - -class ProviderAuth(BaseModel): - bindCredential: Annotated[ - str, Field(description="Credentials to use when binding to an LDAP provider") - ] - bindDN: Annotated[ - str, Field(description="DN to use when binding to an LDAP provider") - ] - - -class QueryCompletion(BaseModel): - completion: Optional[str] = None - token: Optional[str] = None - - -class QueryCompletionResponse(BaseModel): - """ - The result of a successful query auto-completion request - """ - - completions: Annotated[ - Optional[List[QueryCompletion]], - Field(description="Array of possible auto-completion results."), - ] = None - - -class ResourceRule(BaseModel): - apiGroups: Annotated[ - List[str], - Field( - description='The API groups for the resources controlled by the rule.\nAn API group consists of an apiGroup and a version, e.g. "apigroup/version".\nThe API group can be a wildcard ("*"), in which case it will match any API group.\nIn addition, the version can be a wildcard.' - ), - ] - permissions: Annotated[ - Optional[Literal["none", "read", "readWrite"]], - Field(description="Permissions for resources specified by the rule."), - ] = None - resources: Annotated[ - List[str], - Field( - description='Names for the resources controlled by the rule.\nIt can be a wildcard ("*"), in which case it will match any resource\nin the matching API groups.' - ), - ] - - -class StreamResult(BaseModel): - details: Annotated[ - Optional[str], - Field( - description="The details for the streaming request; e.g. the query string in the corresponding GET request." - ), - ] = None - stream: Annotated[ - Optional[str], - Field( - description="The stream identifier specified in the corresponding streaming GET request." - ), - ] = None - - -class TableRule(BaseModel): - """ - A role rule controlling access to a EDB table. Note that - there is never write access to EDB. - """ - - path: Annotated[ - str, - Field( - description='EDB path to which this rule applies. It can end in ".*"\nin which case the final portion of the table path can be anything, if the\nprefix matches. It can end in ".**" in which case the table path can be\nanything if the prefix matches.', - min_length=1, - pattern="^\\\\..*", - ), - ] - permissions: Annotated[ - Literal["none", "read"], - Field(description="Permissions for the given EDB path."), - ] - - -class TopoAttrMetadata(BaseModel): - type: Optional[str] = None - ui_description: Optional[str] = None - ui_description_key: Optional[str] = None - ui_name: Optional[str] = None - ui_name_key: Optional[str] = None - - -class TopoLinkEndpoint(BaseModel): - endpoint: Optional[str] = None - node: Optional[str] = None - node_key: Optional[str] = None - - -class TopoNodeGrouping(BaseModel): - group: Optional[str] = None - tier: Optional[int] = None - - -class TopoOverlayBadgeMetadata(BaseModel): - badge_name: Optional[str] = None - badge_path: Optional[str] = None - color: Optional[str] = None - ui_description: Optional[str] = None - ui_description_key: Optional[str] = None - ui_name: Optional[str] = None - ui_name_key: Optional[str] = None - value: Optional[int] = None - - -class TopoOverlayStateMetadata(BaseModel): - color: Optional[str] = None - ui_description: Optional[str] = None - ui_description_key: Optional[str] = None - ui_name: Optional[str] = None - ui_name_key: Optional[str] = None - value: Optional[int] = None - - -class TopoOverlayStateRequest(BaseModel): - badge: Optional[str] = None - status: Optional[str] = None - - -TopoSchema = GroupVersionKind - - -class TopologyStateGroupSelector(BaseModel): - group: Annotated[ - Optional[str], - Field( - description='The group to assign to nodes that match the selector.\n+eda:ui:title="Group"' - ), - ] = None - nodeSelector: Annotated[ - Optional[List[str]], - Field( - description='+kubebuilder:validation:Optional\n+eda:ui:title="Node Selector"\n+eda:ui:format="labelselector"\nLabel selector to use to match nodes that should be assigned to this group.' - ), - ] = None - - -class TopologyStateTierSelector(BaseModel): - nodeSelector: Annotated[ - Optional[List[str]], - Field( - description='+kubebuilder:validation:Optional\n+eda:ui:title="Node Selector"\n+eda:ui:format="labelselector"\nLabel selector to use to match nodes that should be assigned to this tier.' - ), - ] = None - tier: Annotated[ - Optional[int], - Field( - description='The tier to assign to nodes that match the selector.\n+eda:ui:title="Tier"' - ), - ] = None - - -class TransactionContent(BaseModel): - apiVersion: Optional[str] = None - kind: Optional[str] = None - metadata: Optional[Metadata] = None - spec: Optional[Dict[str, Any]] = None - - -class TransactionId(BaseModel): - id: Annotated[ - Optional[int], - Field( - description="A transaction identifier; these are assigned by the system to a posted transaction." - ), - ] = None - - -class TransactionInputResource(BaseModel): - isDelete: Optional[bool] = None - name: Optional[NsCrGvkName] = None - - -class TransactionNodeResult(BaseModel): - """ - The name of a node with changes from a transaction, and a list - of errors that occurred for the node - """ - - errors: Annotated[ - Optional[List[str]], Field(description="Resulting errors for the node") - ] = None - name: Annotated[Optional[str], Field(description="The name of the node")] = None - namespace: Annotated[ - Optional[str], Field(description="The namespace of the node") - ] = None - - -class TransactionNsCrGvkNames(BaseModel): - gvk: Optional[GroupVersionKind] = None - names: Optional[List[str]] = None - namespace: Optional[str] = None - - -class TransactionPatch(BaseModel): - patchOps: List[K8SPatchOp] - target: NsCrGvkName - - -class TransactionPoolAllocation(BaseModel): - key: Optional[str] = None - poolName: Optional[str] = None - poolTemplate: Optional[str] = None - value: Optional[str] = None - - -class TransactionResultInputResources(BaseModel): - inputCrs: Annotated[ - Optional[List[TransactionInputResource]], - Field(description="List of input resources from the transaction"), - ] = None - limitedAccess: Annotated[ - Optional[bool], - Field( - description="This field is true if the list returned here is not the complete list of input resources in the transaction because the user does not have read-access to some of them" - ), - ] = None - - -class TransactionResultObjectString(BaseModel): - data: Optional[str] = None - - -class TransactionScriptResults(BaseModel): - executionTime: Optional[int] = None - output: Optional[str] = None - - -class TransactionState(BaseModel): - state: Annotated[ - Optional[str], Field(description="The state of the transaction") - ] = None - - -class TransactionStructuredAppError(BaseModel): - message: Optional[str] = None - messageKey: Optional[str] = None - values: Optional[Dict[str, Dict[str, Any]]] = None - - -class TransactionSummaryResult(BaseModel): - """ - Summary of the result of a transaction - """ - - commitHash: Annotated[ - Optional[str], Field(description="The git commit hash for the transaction") - ] = None - description: Annotated[ - Optional[str], - Field( - description="The description of the transaction, as posted in the transaction request." - ), - ] = None - details: Annotated[ - Optional[str], - Field( - description="The type of details available for the transaction, as posted in the transaction request." - ), - ] = None - dryRun: Annotated[ - Optional[bool], - Field( - description="If true the transaction was not committed and ran in dry run mode." - ), - ] = None - id: Annotated[Optional[int], Field(description="The transaction identifier")] = None - lastChangeTimestamp: Annotated[ - Optional[str], Field(description="The time that the transaction completed.") - ] = None - state: Annotated[ - Optional[str], Field(description="The state of the transaction.") - ] = None - success: Annotated[ - Optional[bool], Field(description="True if the transaction was successful.") - ] = None - username: Annotated[ - Optional[str], Field(description="The user who posted the transaction.") - ] = None - - -class TransactionSummaryResults(BaseModel): - results: Annotated[ - Optional[List[TransactionSummaryResult]], - Field(description="array of summary-results for transactions"), - ] = None - - -class TransactionValue(BaseModel): - value: Optional[TransactionContent] = None - - -class UrlRule(BaseModel): - path: Annotated[ - str, - Field( - description='The API server URL path to which this rule applies. It can end in "/*"\nin which case the final portion of the URL path can be anything, if the\nprefix matches. It can end in "/**" in which case the URL path can be\nanything if the prefix matches.",', - min_length=1, - pattern="^/.*", - ), - ] - permissions: Annotated[ - Optional[Literal["none", "read", "readWrite"]], - Field(description="The permissions for the API server URL for the rule."), - ] = None - - -class UserStatus(BaseModel): - failedLoginSinceSuccessfulLogin: Optional[int] = None - isFederatedUser: Annotated[ - Optional[bool], - Field(description="True if the user comes from a federated LDAP server"), - ] = None - lastFailedLogin: Optional[str] = None - lastSuccessfulLogin: Optional[str] = None - temporarilyDisabled: Optional[bool] = None - - -class UserStorageInFileContent(BaseModel): - file_content: Annotated[ - str, - Field( - alias="file-content", - description="The desired content of the user-storage file. This will be base64 decoded before storing if the request indicates that the content is base64 encoded.", - ), - ] - - -class UserStorageOutDirEntry(BaseModel): - """ - user-storage directory entry - """ - - modification_time: Annotated[ - Optional[datetime], - Field( - alias="modification-time", - description="modification type of the item, if a file", - ), - ] = None - name: Annotated[str, Field(description="name of the item within the directory")] - type: Annotated[str, Field(description='type of the item; "file" or "directory"')] - - -class UserStorageOutFileContent(BaseModel): - file_content: Annotated[ - Optional[str], - Field( - alias="file-content", - description="content of the file, will be base64 encoded if the request asked for this", - ), - ] = None - file_deleted: Annotated[ - Optional[bool], - Field( - alias="file-deleted", - description="if present and true, indicates the file has been deleted; used for\nstreamed responses", - ), - ] = None - file_name: Annotated[str, Field(alias="file-name", description="name of the file")] - modification_time: Annotated[ - Optional[datetime], - Field( - alias="modification-time", - description="UTC modification time of the file, as an RFC 3339 date/time.\nNot valid if file-deleted is true (in a streamed response)", - ), - ] = None - - -class Workflow(BaseModel): - cr: Annotated[ - Dict[str, Dict[str, Any]], - Field(description="Custom resource that defines the workflow to execute"), - ] - description: Annotated[ - str, Field(description="Description message for the workflow") - ] - - -class WorkflowId(BaseModel): - id: Annotated[ - Optional[int], - Field( - description="A workflow identifier; these are assigned by the system to a posted workflow." - ), - ] = None - - -class WorkflowState(BaseModel): - runningState: Optional[str] = None - state: Optional[str] = None - - -class SingleVersionInfo(BaseModel): - builtDate: Annotated[ - Optional[str], Field(description="The build-time for the component.") - ] = None - version: Annotated[ - Optional[str], Field(description="The version string for the component.") - ] = None - - -class VersionInfo(RootModel[Optional[Dict[str, SingleVersionInfo]]]): - root: Optional[Dict[str, SingleVersionInfo]] = None - - -class AuthProviderAuth(BaseModel): - """ - If present, bind to LDAP server with the given credentials. Otherwise do not bind. - """ - - bindCredential: Annotated[ - str, Field(description="Credentials to use when binding to an LDAP provider") - ] - bindDN: Annotated[ - str, Field(description="DN to use when binding to an LDAP provider") - ] - - -class AuthProviderGroupSupport(BaseModel): - """ - Configuration for group import/sync with LDAP. If not present, groups will not synchronized with EDA. - """ - - NameLDAPAttribute: Annotated[ - str, Field(description="The LDAP group name attribute") - ] - filter: Annotated[ - Optional[str], - Field( - description="Further for filtering when retrieving LDAP groups. Ensure starts and ends with parentheses if using." - ), - ] = None - groupLDAPDN: Annotated[ - str, Field(description="The LDAP DN where groups are found.") - ] - memberAttribute: Annotated[ - Optional[str], - Field( - description='The group attribute for a members. Usually "member" or "memberUid".' - ), - ] = None - memberOfAttribute: Annotated[ - Optional[str], - Field( - description='If retrievalStrategy is "memberOf", this is the LDAP user attribute for group memberships.' - ), - ] = None - membershipAttributeType: Annotated[ - Optional[Literal["DN", "UID"]], - Field( - description="How users are identified in a group member entry: either DN or UID." - ), - ] = None - membershipUserAttribute: Annotated[ - Optional[str], - Field( - description="Only required if membershipAttributeType is UID; then it is the user attribute that should match the group member value." - ), - ] = None - objectClasses: Annotated[ - str, - Field( - description="The LDAP object class or classes used for groups. If more than one, they must be comma-separated." - ), - ] - retrievalStrategy: Annotated[ - Optional[Literal["member", "memberOf"]], - Field( - description='The strategy for retrieving groups. Should be "member" to get group membership from the group, or "memberOf" to get group membership from the user.' - ), - ] = None - - -class AuthProvider(BaseModel): - auth: Optional[AuthProviderAuth] = None - enabled: Annotated[ - Optional[bool], - Field(description="If true, checking/syncing this LDAP provider is enabled."), - ] = None - groupSupport: Optional[AuthProviderGroupSupport] = None - idAttribute: Annotated[ - str, - Field( - description="Name of the LDAP attribute, which is used as a unique object identifier (UUID) for objects in LDAP." - ), - ] - import_: Annotated[ - Optional[bool], - Field( - alias="import", - description="If true, the LDAP information will be imported into the EDA (Keycloak) database.", - ), - ] = None - name: Annotated[ - str, Field(description="The name to give to the LDAP provider; must be unique.") - ] - pagination: Annotated[ - Optional[bool], - Field(description="Set to true if the LDAP server supports pagination."), - ] = None - periodicSync: Annotated[ - Optional[bool], - Field( - description="If true, periodic synchronization of new changed or newly created LDAP users to Keycloak will occur." - ), - ] = None - periodicSyncSecs: Annotated[ - Optional[int], - Field( - description="If periodic sync is enabled, this is the period in seconds that synchronization will occur." - ), - ] = None - rdnLDAPAttribute: Annotated[ - str, - Field( - description="Name of the LDAP attribute, which is used as RDN (top attribute) of typical user DN. Usually it's the same as the Username LDAP attribute, however it is not required." - ), - ] - readOnly: Annotated[ - bool, - Field( - description="If false, changes made to LDAP-mapped attribute via EDA will be synced back to the LDAP server. Otherwise, changes are not made in LDAP." - ), - ] - scope: Annotated[ - Optional[Literal["One Level", "Subtree"]], - Field( - description='Must be "One Level" or "Subtree". If "One Level", the search applies only for users in the DNs specified by User DNs. If "Subtree", the search applies to the whole subtree.' - ), - ] = None - timeout: Annotated[ - Optional[int], Field(description="LDAP connection timeout in milliseconds") - ] = None - tls: Annotated[ - Optional[bool], - Field(description="If true, encrypts the connection to LDAP using STARTTLS"), - ] = None - type: Annotated[ - Literal["ldap"], - Field(description='The type of provider. Currently only "ldap" is supported.'), - ] - url: Annotated[str, Field(description="Connection URL to your LDAP server")] - userDN: Annotated[ - str, - Field( - description="Full DN of LDAP tree where your users are. This DN is the parent of LDAP users." - ), - ] - userObjectClasses: Annotated[ - str, - Field( - description="All values of LDAP objectClass attribute for users in LDAP, divided by commas. (e.g. inetOrgPerson, organizationalPerson)." - ), - ] - userSearchFilter: Annotated[ - Optional[str], - Field( - description="Additional LDAP filter for filtering searched users. Leave this empty if you don't need an additional filter. Make sure that it starts with '(' and ends with ')'." - ), - ] = None - usernameAttribute: Annotated[ - str, - Field( - description="Name of the LDAP attribute, which is mapped as EDA username. For many LDAP server vendors it can be 'uid'." - ), - ] - uuid: Annotated[ - Optional[str], - Field( - description="The unique identifier given to the entry when it is created." - ), - ] = None - vendor: Annotated[str, Field(description="LDAP vendor (provider).")] - - -class AuthProviderTestParams(BaseModel): - action: Annotated[ - Optional[Literal["connection", "authentication"]], - Field(description="The test action to take."), - ] = None - auth: Optional[ProviderAuth] = None - timeout: Annotated[ - Optional[int], Field(description="LDAP connection timeout in milliseconds") - ] = None - tls: Annotated[ - Optional[bool], - Field(description="If true, encrypts the connection to LDAP using STARTTLS"), - ] = None - url: Annotated[ - Optional[str], Field(description="Connection URL to your LDAP server") - ] = None - - -class AuthProviders(RootModel[List[AuthProvider]]): - root: List[AuthProvider] - - -class AuthRole(BaseModel): - description: str - name: Annotated[ - str, - Field( - pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" - ), - ] - namespace: Annotated[ - Optional[str], Field(pattern="^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$") - ] = None - resourceRules: Annotated[ - Optional[List[ResourceRule]], - Field(description="Rules for access to resources."), - ] = None - tableRules: Annotated[ - Optional[List[TableRule]], - Field(description="Rules for access to EDB tables, including via EQL."), - ] = None - urlRules: Annotated[ - Optional[List[UrlRule]], - Field(description="Rules for access to APIServer routes."), - ] = None - - -class AuthRoles(RootModel[List[AuthRole]]): - root: List[AuthRole] - - -class AuthUser(BaseModel): - email: Optional[str] = None - enabled: Optional[bool] = None - firstName: Optional[str] = None - groups: Annotated[ - Optional[List[str]], - Field( - description="contains the UUIDs of the groups of which the user is a member." - ), - ] = None - lastName: Optional[str] = None - maxSessions: Optional[int] = None - password: Optional[str] = None - status: Optional[UserStatus] = None - username: Optional[str] = None - uuid: Optional[str] = None - - -class AuthUserGroup(BaseModel): - description: Optional[str] = None - full_users: Annotated[ - Optional[List[AuthUser]], - Field( - alias="full-users", - description="contains the full user definitions of the users who are members of the group, if requested", - ), - ] = None - fullRoles: Annotated[ - Optional[List[AuthRole]], - Field( - description="contains the full role definitions of the Roles and ClusterRoles associated with the group, if requested" - ), - ] = None - isFederated: Annotated[ - Optional[bool], - Field( - description="if true, indicates that the group was imported from a federated LDAP server" - ), - ] = None - name: Optional[str] = None - roles: Annotated[ - Optional[List[str]], - Field( - description='Contains the names of the ClusterRoles and Roles roles associated with the group.\nA Role name has the form "namesspace:rolename", whereas a ClusteRole name is a\nsimple "rolename", without a colon or a namespace.' - ), - ] = None - users: Annotated[ - Optional[List[str]], - Field( - description="contains the usernames of the users who are members of the group" - ), - ] = None - uuid: Optional[str] = None - - -class AuthUserGroups(RootModel[List[AuthUserGroup]]): - root: List[AuthUserGroup] - - -class AuthUsers(RootModel[List[AuthUser]]): - root: List[AuthUser] - - -class CrAnnotation(BaseModel): - cr: Optional[NsCrGvkName] = None - lines: Optional[List[LineSegment]] = None - - -class FlowGetResponse(BaseModel): - error: Annotated[ - Optional[str], - Field(description="If no error is present, the flow completed successfully"), - ] = None - id: Annotated[Optional[int], Field(description="The id of the workflow")] = None - jsonResult: Annotated[ - Optional[str], Field(description="A JSON representation of the result") - ] = None - log: Annotated[Optional[str], Field(description="Log output from the flow")] = None - name: Annotated[Optional[str], Field(description="Name of the workflow")] = None - namespace: Annotated[ - Optional[str], Field(description="The namespace in which the flow ran") - ] = None - parentId: Annotated[ - Optional[int], Field(description="The id of the parent workflow, if any") - ] = None - stages: Annotated[ - Optional[List[FlowStage]], - Field(description="The list of stages of the workflow"), - ] = None - state: Optional[ - Literal[ - "waitingToStart", - "running", - "waitingForInput", - "terminated", - "failed", - "completed", - "subflowWaitingForInput", - ] - ] = None - subflowsWaitingForInput: Annotated[ - Optional[List[int]], - Field(description="The ids of any subflows that are waiting for user input"), - ] = None - type: Annotated[Optional[str], Field(description="The type of workflow")] = None - waitForInputPrompt: Annotated[ - Optional[str], Field(description="Set if the state is waiting for input") - ] = None - - -class GetLabelCompletionRequest(BaseModel): - gvk: Optional[GroupVersionKind] = None - limit: Annotated[ - Optional[int], Field(description="The maximum number of results to return") - ] = None - namespace: Annotated[ - Optional[str], - Field( - description="The namespace of the GVK if the CRD is namespaced\nrequired: true if the GVK is namespaced" - ), - ] = None - value: Annotated[ - str, - Field( - description="A key value string delimited by =. If the Value does not include an =\nit is assumed to be a Key lookup. If there is an =, everything before\nthe = is assumed to be the key and the lookup will be a value lookup" - ), - ] - - -class Health(BaseModel): - mode: Annotated[ - Literal["ACTIVE", "STANDBY"], - Field(description="Indication of the activity of this cluster."), - ] - services: Annotated[ - Optional[Dict[str, HealthServiceStatus]], - Field( - description="Detailed health of the services comprising the EDA cluster. Keyed by the name of the service." - ), - ] = None - status: Annotated[ - Literal["UP", "DEGRADED", "DOWN"], - Field(description="Overall health status of the EDA cluster."), - ] - timestamp: Annotated[ - datetime, Field(description="Time that the health report was generated.") - ] - - -class NodeConfigResponse(BaseModel): - annotations: Annotated[ - Optional[List[CrAnnotation]], - Field(description="The the list of annotations for the node configuration"), - ] = None - running: Annotated[ - Optional[str], Field(description="The current node configuration for the node") - ] = None - - -class Overlay(BaseModel): - endpoint_state: Optional[List[TopoOverlayStateMetadata]] = None - group: Optional[str] = None - link_state: Optional[List[TopoOverlayStateMetadata]] = None - name: Optional[str] = None - node_badge: Optional[List[TopoOverlayBadgeMetadata]] = None - node_state: Optional[List[TopoOverlayStateMetadata]] = None - ui_description: Optional[str] = None - ui_description_key: Optional[str] = None - ui_name: Optional[str] = None - ui_name_key: Optional[str] = None - version: Optional[str] = None - - -class Overlays(RootModel[List[Overlay]]): - root: List[Overlay] - - -class TopoElemMetadata(BaseModel): - attributes: Optional[Dict[str, TopoAttrMetadata]] = None - schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None - subtitle: Optional[str] = None - subtitle_key: Optional[str] = None - - -class TopoEndpoint(BaseModel): - attributes: Optional[Dict[str, Dict[str, Any]]] = None - cr_name: Optional[str] = None - labels: Optional[Dict[str, str]] = None - name: Optional[str] = None - namespace: Optional[str] = None - schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None - ui_name: Optional[str] = None - - -class TopoLink(BaseModel): - attributes: Optional[Dict[str, Dict[str, Any]]] = None - cr_name: Optional[str] = None - endpoint_a: Optional[TopoLinkEndpoint] = None - endpoint_a_details: Optional[TopoEndpoint] = None - endpoint_b: Optional[TopoLinkEndpoint] = None - endpoint_b_details: Optional[TopoEndpoint] = None - key: Optional[str] = None - labels: Optional[Dict[str, str]] = None - name: Optional[str] = None - namespace: Optional[str] = None - schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None - ui_name: Optional[str] = None - - -class TopoNode(BaseModel): - attributes: Optional[Dict[str, Dict[str, Any]]] = None - cr_name: Optional[str] = None - grouping: Optional[TopoNodeGrouping] = None - key: Optional[str] = None - labels: Optional[Dict[str, str]] = None - name: Optional[str] = None - namespace: Optional[str] = None - schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None - ui_name: Optional[str] = None - - -class Topology(BaseModel): - endpoints: Optional[TopoElemMetadata] = None - group: Optional[str] = None - grouping: Optional[TopoSchema] = None - links: Optional[TopoElemMetadata] = None - name: Optional[str] = None - nodes: Optional[TopoElemMetadata] = None - ui_description: Optional[str] = None - ui_description_key: Optional[str] = None - ui_name: Optional[str] = None - ui_name_key: Optional[str] = None - version: Optional[str] = None - - -class TopologyState(BaseModel): - links: Optional[Dict[str, TopoLink]] = None - nodes: Optional[Dict[str, TopoNode]] = None - - -class TopologyStateGroupingBase(BaseModel): - """ - Embed this type inside your topology tier CRD spec to determine the tiers and the - groups of the nodes in the topology. - """ - - groupSelectors: Annotated[ - Optional[List[TopologyStateGroupSelector]], - Field( - description='The set of selectors for assigning nodes to groups\n+eda:ui:title="Group Selectors"' - ), - ] = None - tierSelectors: Annotated[ - Optional[List[TopologyStateTierSelector]], - Field( - description='The set of selectors for assigning nodes to tiers\n+eda:ui:title="Tier Selectors"' - ), - ] = None - uiDescription: Annotated[ - Optional[str], - Field( - description='A description of the topology grouping to expose in the UI\n+eda:ui:title="UI Description"' - ), - ] = None - uiDescriptionKey: Annotated[ - Optional[str], - Field( - description='The translation key for the description of the topology grouping to expose in the UI\n+eda:ui:title="UI Description Key"' - ), - ] = None - uiName: Annotated[ - Optional[str], - Field( - description='The name of the topology grouping to expose in the UI\n+eda:ui:title="UI Name"' - ), - ] = None - uiNameKey: Annotated[ - Optional[str], - Field( - description='The translation key for the name of the topology grouping to expose in the UI\n+eda:ui:title="UI Name Key"' - ), - ] = None - - -class TransactionAppError(BaseModel): - rawError: Optional[str] = None - structuredError: Optional[TransactionStructuredAppError] = None - - -class TransactionIntentResult(BaseModel): - errors: Optional[List[TransactionAppError]] = None - intentName: Optional[NsCrGvkName] = None - outputCrs: Optional[List[NsCrGvkName]] = None - poolAllocation: Optional[List[TransactionPoolAllocation]] = None - script: Optional[TransactionScriptResults] = None - - -class TransactionResultObject(BaseModel): - after: Optional[TransactionResultObjectString] = None - before: Optional[TransactionResultObjectString] = None - dataUnavailable: Annotated[ - Optional[bool], - Field(description="True if there is no data available for the result"), - ] = None - format: Annotated[ - Optional[str], Field(description="The format of the response - Text or YAML") - ] = None - - -class TransactionType(BaseModel): - create: Optional[TransactionValue] = None - delete: Optional[NsCrGvkName] = None - modify: Optional[TransactionValue] = None - patch: Optional[TransactionPatch] = None - replace: Optional[TransactionValue] = None - - -class UserStorageOutDirContent(BaseModel): - directory_path: Annotated[ - str, - Field( - alias="directory-path", - description="path for the directory within the users storage", - ), - ] - entries: Annotated[ - List[UserStorageOutDirEntry], - Field(description="array of entries for the items in the directory"), - ] - - -class WorkflowResult(BaseModel): - errorMessage: Optional[str] = None - resultMessage: Optional[str] = None - state: Optional[WorkflowState] = None - success: Optional[bool] = None - - -class TopoGroupingStateRequest(BaseModel): - name: Optional[str] = None - spec: Optional[TopologyStateGroupingBase] = None - - -class TopoStateRequest(BaseModel): - grouping: Optional[TopoGroupingStateRequest] = None - namespace: Optional[str] = None - overlays: Optional[TopoOverlayStateRequest] = None - - -class Topologies(RootModel[List[Topology]]): - root: List[Topology] - - -class TransactionCr(BaseModel): - type: Optional[TransactionType] = None - - -class TransactionDetails(BaseModel): - changedCrs: Annotated[ - Optional[List[TransactionNsCrGvkNames]], - Field(description="List of changed CRs as part of the transaction"), - ] = None - dryRun: Annotated[ - Optional[bool], Field(description="True if the transaction was not committed") - ] = None - generalErrors: Annotated[ - Optional[List[str]], - Field(description="List of general errors while running the transaction"), - ] = None - inputCrs: Annotated[ - Optional[List[TransactionInputResource]], - Field(description="List of input CRs from the transaction"), - ] = None - intentsRun: Annotated[ - Optional[List[TransactionIntentResult]], - Field(description="List of intents which ran as part of the transaction"), - ] = None - nodesWithConfigChanges: Annotated[ - Optional[List[TransactionNodeResult]], - Field( - description="List of nodes with configuration changes from the transaction" - ), - ] = None - state: Annotated[ - Optional[str], Field(description="The state of the transaction") - ] = None - success: Annotated[ - Optional[bool], Field(description="True if the CR was successfully applied") - ] = None - - -class TransactionExecutionResult(BaseModel): - changedCrs: Annotated[ - Optional[List[TransactionNsCrGvkNames]], - Field(description="List of changed CRs as part of the transaction"), - ] = None - executionSummary: Annotated[ - Optional[str], - Field(description="Information about time taken during processing"), - ] = None - generalErrors: Annotated[ - Optional[List[str]], - Field(description="List of general errors while running the transaction"), - ] = None - intentsRun: Annotated[ - Optional[List[TransactionIntentResult]], - Field(description="List of intents which ran as part of the transaction"), - ] = None - nodesWithConfigChanges: Annotated[ - Optional[List[TransactionNodeResult]], - Field( - description="List of nodes with configuration changes from the transaction" - ), - ] = None - - -class Transaction(BaseModel): - crs: Annotated[ - List[TransactionCr], - Field(description="List of CRs to include in the transaction"), - ] - description: Annotated[ - str, Field(description="Description/commit message for the transaction") - ] - dryRun: Annotated[ - bool, - Field( - description="If true the transaction will not be committed and will run in dry run mode. If false the\ntransaction will be committed" - ), - ] - resultType: Annotated[ - Optional[str], - Field(description="The type of result - errors only, normal, or debug"), - ] = None - retain: Annotated[ - Optional[bool], - Field( - description="retain after results fetched - e.g. after call to get transaction result" - ), - ] = None diff --git a/pydantic_eda/core/v25_8_1-rc1/models.py b/pydantic_eda/core/v25_8_1_rc1/models.py similarity index 100% rename from pydantic_eda/core/v25_8_1-rc1/models.py rename to pydantic_eda/core/v25_8_1_rc1/models.py From f691a51e386e81bfa3593b7e2c87a30b65e37f29 Mon Sep 17 00:00:00 2001 From: hellt Date: Sat, 30 Aug 2025 11:55:24 +0200 Subject: [PATCH 5/5] generated from 25.8.1 GA --- pydantic_eda/apps/aaa/v1alpha1/models.py | 4 +- .../apps/aifabrics/v1alpha1/models.py | 6 +- pydantic_eda/apps/appstore/v1/models.py | 14 +- .../apps/bootstrap/v1alpha1/models.py | 12 +- pydantic_eda/apps/components/v1/models.py | 32 +- pydantic_eda/apps/config/v1alpha1/models.py | 4 +- pydantic_eda/apps/core/v1/models.py | 187 +- .../apps/environment/v1alpha1/models.py | 12 +- pydantic_eda/apps/fabrics/v1alpha1/models.py | 78 +- pydantic_eda/apps/filters/v1alpha1/models.py | 8 +- .../apps/interfaces/v1alpha1/models.py | 24 +- pydantic_eda/apps/oam/v1alpha1/models.py | 107 +- pydantic_eda/apps/os/v1alpha1/models.py | 4 +- pydantic_eda/apps/protocols/v1/models.py | 64 +- pydantic_eda/apps/qos/v1/models.py | 24 +- pydantic_eda/apps/routing/v1alpha1/models.py | 24 +- .../apps/routingpolicies/v1alpha1/models.py | 24 +- pydantic_eda/apps/security/v1alpha1/models.py | 8 +- pydantic_eda/apps/services/v1/models.py | 36 +- pydantic_eda/apps/siteinfo/v1alpha1/models.py | 4 +- pydantic_eda/apps/system/v1alpha1/models.py | 12 +- pydantic_eda/apps/timing/v1alpha1/models.py | 4 +- .../apps/topologies/v1alpha1/models.py | 30 +- pydantic_eda/core/v25_8_1/models.py | 1826 +++++++++++++++++ 24 files changed, 2274 insertions(+), 274 deletions(-) create mode 100644 pydantic_eda/core/v25_8_1/models.py diff --git a/pydantic_eda/apps/aaa/v1alpha1/models.py b/pydantic_eda/apps/aaa/v1alpha1/models.py index f015963..aaa605d 100644 --- a/pydantic_eda/apps/aaa/v1alpha1/models.py +++ b/pydantic_eda/apps/aaa/v1alpha1/models.py @@ -366,8 +366,8 @@ class NodeGroup(BaseModel): NodeGroup is the Schema for the nodegroups API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^aaa\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^NodeGroup$")] metadata: NodeGroupMetadata spec: Annotated[ NodeGroupSpec, diff --git a/pydantic_eda/apps/aifabrics/v1alpha1/models.py b/pydantic_eda/apps/aifabrics/v1alpha1/models.py index 8528809..0ac3d1a 100644 --- a/pydantic_eda/apps/aifabrics/v1alpha1/models.py +++ b/pydantic_eda/apps/aifabrics/v1alpha1/models.py @@ -556,8 +556,10 @@ class Backend(BaseModel): Backend is the Schema for the backends API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^aifabrics\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^Backend$")] metadata: BackendMetadata spec: Annotated[ BackendSpec, diff --git a/pydantic_eda/apps/appstore/v1/models.py b/pydantic_eda/apps/appstore/v1/models.py index 1c203ff..0fa88f6 100644 --- a/pydantic_eda/apps/appstore/v1/models.py +++ b/pydantic_eda/apps/appstore/v1/models.py @@ -227,7 +227,7 @@ class AppInstallerSpecApp(BaseModel): ), ] appSettings: Annotated[ - Optional[Dict[str, Any]], + Optional[Any], Field( description="AppSettings defines a list of variables and their value. Only variables that are customised need to be mentioned.\nIf AppSettings are not again mentioned on upgrade, values will remain as is.", title="App Settings", @@ -559,8 +559,8 @@ class AppInstaller(BaseModel): AppInstaller is the Schema for the appinstallers API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^appstore\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^AppInstaller$")] metadata: AppInstallerMetadata spec: Annotated[AppInstallerSpec, Field(title="Specification")] status: Annotated[Optional[AppInstallerStatus], Field(title="Status")] = None @@ -581,8 +581,8 @@ class Catalog(BaseModel): Catalog is the Schema for the catalogs API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^appstore\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Catalog$")] metadata: CatalogMetadata spec: Annotated[ CatalogSpec, @@ -615,8 +615,8 @@ class Registry(BaseModel): Registry is the Schema for the registries API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^appstore\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Registry$")] metadata: RegistryMetadata spec: Annotated[ RegistrySpec, diff --git a/pydantic_eda/apps/bootstrap/v1alpha1/models.py b/pydantic_eda/apps/bootstrap/v1alpha1/models.py index 2972516..bace339 100644 --- a/pydantic_eda/apps/bootstrap/v1alpha1/models.py +++ b/pydantic_eda/apps/bootstrap/v1alpha1/models.py @@ -371,8 +371,10 @@ class Init(BaseModel): Init is the Schema for the inits API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^bootstrap\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^Init$")] metadata: InitMetadata spec: Annotated[ InitSpec, @@ -404,8 +406,10 @@ class ManagementRouter(BaseModel): ManagementRouter is the Schema for the managementrouters API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^bootstrap\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^ManagementRouter$")] metadata: ManagementRouterMetadata spec: Annotated[ ManagementRouterSpec, diff --git a/pydantic_eda/apps/components/v1/models.py b/pydantic_eda/apps/components/v1/models.py index 4e5eca4..54e6254 100644 --- a/pydantic_eda/apps/components/v1/models.py +++ b/pydantic_eda/apps/components/v1/models.py @@ -1334,8 +1334,8 @@ class Chassis(BaseModel): Chassis is the Schema for the chassis API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^components\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Chassis$")] metadata: ChassisMetadata spec: Annotated[ Optional[Dict[str, Any]], @@ -1368,8 +1368,8 @@ class Component(BaseModel): Component is the Schema for the components API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^components\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Component$")] metadata: ComponentMetadata spec: Annotated[ ComponentSpec, @@ -1402,8 +1402,8 @@ class ControlModule(BaseModel): ControlModule is the Schema for the controlmodules API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^components\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^ControlModule$")] metadata: ControlModuleMetadata spec: Annotated[ Optional[Dict[str, Any]], @@ -1436,8 +1436,8 @@ class FabricModule(BaseModel): FabricModule is the Schema for the fabricmodules API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^components\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^FabricModule$")] metadata: FabricModuleMetadata spec: Annotated[ Optional[Dict[str, Any]], @@ -1470,8 +1470,8 @@ class Fan(BaseModel): Fan is the Schema for the fans API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^components\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Fan$")] metadata: FanMetadata spec: Annotated[ Optional[Dict[str, Any]], @@ -1503,8 +1503,8 @@ class InterfaceModule(BaseModel): InterfaceModule is the Schema for the interfacemodules API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^components\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^InterfaceModule$")] metadata: InterfaceModuleMetadata spec: Annotated[ Optional[Dict[str, Any]], @@ -1537,8 +1537,8 @@ class Monitor(BaseModel): Monitor is the Schema for the monitors API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^components\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Monitor$")] metadata: MonitorMetadata spec: Annotated[ MonitorSpec, @@ -1571,8 +1571,8 @@ class PowerSupply(BaseModel): PowerSupply is the Schema for the powersupplies API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^components\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^PowerSupply$")] metadata: PowerSupplyMetadata spec: Annotated[ PowerSupplySpec, diff --git a/pydantic_eda/apps/config/v1alpha1/models.py b/pydantic_eda/apps/config/v1alpha1/models.py index 16c423c..c13e8a6 100644 --- a/pydantic_eda/apps/config/v1alpha1/models.py +++ b/pydantic_eda/apps/config/v1alpha1/models.py @@ -363,8 +363,8 @@ class Configlet(BaseModel): Configlet is the Schema for the configlets API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^config\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^Configlet$")] metadata: ConfigletMetadata spec: Annotated[ ConfigletSpec, diff --git a/pydantic_eda/apps/core/v1/models.py b/pydantic_eda/apps/core/v1/models.py index 0e272d0..edb93a8 100644 --- a/pydantic_eda/apps/core/v1/models.py +++ b/pydantic_eda/apps/core/v1/models.py @@ -160,6 +160,44 @@ class UIResult(RootModel[str]): root: str +class WorkflowGetInputsRespElem(BaseModel): + ackPrompt: Optional[str] = None + group: str + kind: str + name: str + namespace: Optional[str] = None + schemaPrompt: Optional[Dict[str, Any]] = None + version: str + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowIdentifier(BaseModel): + group: str + kind: str + name: str + namespace: Optional[str] = None + version: str + + +class WorkflowInputDataElem(BaseModel): + ack: Annotated[ + Optional[bool], Field(description="acknowledge or reject the input request") + ] = None + input: Annotated[ + Optional[Dict[str, Any]], + Field(description="provide a json blob to the workflow"), + ] = None + subflow: Optional[WorkflowIdentifier] = None + + class ClusterRoleSpecResourceRuleApiGroup(RootModel[str]): root: Annotated[str, Field(min_length=1)] @@ -1989,6 +2027,38 @@ class UdpProxyDeletedResources(RootModel[List[UdpProxyDeletedResourceEntry]]): UdpProxyMetadata = ClusterRoleMetadata +class WorkflowSpec(BaseModel): + """ + WorkflowSpec defines the desired state of Flow + """ + + input: Annotated[ + Optional[Any], + Field( + description="Input to this flow, adhering to the JSON schema defined in the referenced WorkflowDefinition.", + title="Input", + ), + ] = None + type: Annotated[ + str, + Field(description="Select the WorkflowDefinition to execute.", title="Type"), + ] + + +class WorkflowStatus(BaseModel): + """ + WorkflowStatus defines the observed state of Flow + """ + + output: Annotated[ + Optional[Any], + Field( + description="Output from this flow, adhering to the JSON schema defined in the referenced FlowDefinition", + title="Output", + ), + ] = None + + class WorkflowDefinitionSpecFlowDefinitionResource(BaseModel): """ the resource type to be used for this flow, can only be set if Schema is not set @@ -2072,6 +2142,9 @@ class WorkflowDefinitionDeletedResources( WorkflowDefinitionMetadata = ClusterRoleMetadata +WorkflowMetadata = DeviationActionMetadata + + class AppGroup(BaseModel): apiVersion: Optional[str] = None kind: Optional[str] = None @@ -2156,13 +2229,17 @@ class Topology(BaseModel): version: Optional[str] = None +class WorkflowInputData(RootModel[List[WorkflowInputDataElem]]): + root: List[WorkflowInputDataElem] + + class ClusterRole(BaseModel): """ ClusterRole is the Schema for the clusterroles API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^ClusterRole$")] metadata: ClusterRoleMetadata spec: Annotated[ ClusterRoleSpec, @@ -2194,8 +2271,8 @@ class Deviation(BaseModel): Deviation is the Schema for the deviations API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Deviation$")] metadata: DeviationMetadata spec: Annotated[ DeviationSpec, @@ -2218,8 +2295,8 @@ class DeviationAction(BaseModel): DeviationAction is the Schema for the deviationactions API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^DeviationAction$")] metadata: DeviationActionMetadata spec: Annotated[ DeviationActionSpec, @@ -2262,8 +2339,8 @@ class EdgeInterface(BaseModel): EdgeInterface is the Schema for the edgeinterfaces API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^EdgeInterface$")] metadata: EdgeInterfaceMetadata spec: Annotated[ EdgeInterfaceSpec, @@ -2296,8 +2373,8 @@ class HttpProxy(BaseModel): HttpProxy is the Schema for the httpproxies API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^HttpProxy$")] metadata: HttpProxyMetadata spec: Annotated[ HttpProxySpec, @@ -2330,8 +2407,8 @@ class IPAllocationPool(BaseModel): IPAllocationPool is the Schema for the ipallocationpools API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^IPAllocationPool$")] metadata: IPAllocationPoolMetadata spec: Annotated[ IPAllocationPoolSpec, @@ -2364,8 +2441,8 @@ class IPInSubnetAllocationPool(BaseModel): IPInSubnetAllocationPool is the Schema for the ipinsubnetallocationpools API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^IPInSubnetAllocationPool$")] metadata: IPInSubnetAllocationPoolMetadata spec: Annotated[ IPInSubnetAllocationPoolSpec, @@ -2398,8 +2475,8 @@ class IndexAllocationPool(BaseModel): IndexAllocationPool is the Schema for the indexallocationpools API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^IndexAllocationPool$")] metadata: IndexAllocationPoolMetadata spec: Annotated[ IndexAllocationPoolSpec, @@ -2432,8 +2509,8 @@ class License(BaseModel): License is the Schema for the licenses API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^License$")] metadata: LicenseMetadata spec: Annotated[ LicenseSpec, @@ -2463,8 +2540,8 @@ class Namespace(BaseModel): Namespace is the Schema for the namespaces API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Namespace$")] metadata: NamespaceMetadata spec: Annotated[ NamespaceSpec, @@ -2497,8 +2574,8 @@ class NodeProfile(BaseModel): NodeProfile is the Schema for the nodeprofiles API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^NodeProfile$")] metadata: NodeProfileMetadata spec: Annotated[ NodeProfileSpec, @@ -2525,8 +2602,8 @@ class NodeUser(BaseModel): NodeUser is the Schema for the nodeusers API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^NodeUser$")] metadata: NodeUserMetadata spec: Annotated[ NodeUserSpec, @@ -2556,8 +2633,8 @@ class Role(BaseModel): Role is the Schema for the roles API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Role$")] metadata: RoleMetadata spec: Annotated[ RoleSpec, @@ -2589,8 +2666,8 @@ class SubnetAllocationPool(BaseModel): SubnetAllocationPool is the Schema for the subnetallocationpools API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^SubnetAllocationPool$")] metadata: SubnetAllocationPoolMetadata spec: Annotated[ SubnetAllocationPoolSpec, @@ -2623,8 +2700,8 @@ class TopoBreakout(BaseModel): TopoBreakout is the Schema for the topobreakouts API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^TopoBreakout$")] metadata: TopoBreakoutMetadata spec: Annotated[ TopoBreakoutSpec, @@ -2657,8 +2734,8 @@ class TopoLink(BaseModel): TopoLink is the Schema for the topolinks API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^TopoLink$")] metadata: TopoLinkMetadata spec: Annotated[ TopoLinkSpec, @@ -2691,8 +2768,8 @@ class TopoNode(BaseModel): TopoNode is the Schema for the toponodes API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^TopoNode$")] metadata: TopoNodeMetadata spec: Annotated[ TopoNodeSpec, @@ -2725,8 +2802,8 @@ class UdpProxy(BaseModel): UdpProxy is the Schema for the udpproxies API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^UdpProxy$")] metadata: UdpProxyMetadata spec: Annotated[ UdpProxySpec, @@ -2754,13 +2831,37 @@ class UdpProxyList(BaseModel): kind: str +class Workflow(BaseModel): + """ + Workflow is the Schema for the workflows API + """ + + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Workflow$")] + metadata: WorkflowMetadata + spec: Annotated[ + WorkflowSpec, + Field( + description="WorkflowSpec defines the desired state of Flow", + title="Specification", + ), + ] + status: Annotated[ + Optional[WorkflowStatus], + Field( + description="WorkflowStatus defines the observed state of Flow", + title="Status", + ), + ] = None + + class WorkflowDefinition(BaseModel): """ WorkflowDefinition is the Schema for the workflowdefinitions API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^core\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^WorkflowDefinition$")] metadata: WorkflowDefinitionMetadata spec: Annotated[ WorkflowDefinitionSpec, @@ -2788,6 +2889,16 @@ class WorkflowDefinitionList(BaseModel): kind: str +class WorkflowList(BaseModel): + """ + WorkflowList is a list of workflows + """ + + apiVersion: str + items: Optional[List[Workflow]] = None + kind: str + + class OverlayState(BaseModel): links: Optional[Dict[str, TopoOverlayLink]] = None nodes: Optional[Dict[str, TopoOverlayNode]] = None diff --git a/pydantic_eda/apps/environment/v1alpha1/models.py b/pydantic_eda/apps/environment/v1alpha1/models.py index 901382f..06051eb 100644 --- a/pydantic_eda/apps/environment/v1alpha1/models.py +++ b/pydantic_eda/apps/environment/v1alpha1/models.py @@ -185,8 +185,10 @@ class CliPlugin(BaseModel): CliPlugin is the Schema for the cliplugins API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^environment\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^CliPlugin$")] metadata: CliPluginMetadata spec: Annotated[ CliPluginSpec, @@ -219,8 +221,10 @@ class SetupEnv(BaseModel): SetupEnv is the Schema for the setupenvs API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^environment\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^SetupEnv$")] metadata: SetupEnvMetadata spec: Annotated[ SetupEnvSpec, diff --git a/pydantic_eda/apps/fabrics/v1alpha1/models.py b/pydantic_eda/apps/fabrics/v1alpha1/models.py index 21dbd7a..738e278 100644 --- a/pydantic_eda/apps/fabrics/v1alpha1/models.py +++ b/pydantic_eda/apps/fabrics/v1alpha1/models.py @@ -1242,20 +1242,6 @@ class IslPingSpec(BaseModel): Optional[int], Field(description="Count is the number of pings to send.", title="Count"), ] = 1 - fabricSelectors: Annotated[ - Optional[List[str]], - Field( - description='Fabric Selectors is a list of fabric selectors to execute ISL pings for.\nThis is a list of label expressions, e.g. ["eda.nokia.com/role=leaf", "eda.nokia.com/region=us-west"].', - title="Fabric Selectors", - ), - ] = None - fabrics: Annotated[ - Optional[List[str]], - Field( - description="Fabrics is a list of fabrics to execute ISL pings for.", - title="Fabrics", - ), - ] = None islSelectors: Annotated[ Optional[List[str]], Field( @@ -1280,50 +1266,69 @@ class IslPingSpec(BaseModel): class IslPingStatusDetailDetails(BaseModel): + """ + Details of the ping result, if available. + """ + averageTimeNanoseconds: Annotated[ Optional[int], Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + description="Average time taken for a ping reply.", + title="Average Time (ns)", ), ] = None maxTimeNanoseconds: Annotated[ Optional[int], Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + description="Maximum time taken for a ping reply.", + title="Maximum Time (ns)", ), ] = None minTimeNanoseconds: Annotated[ Optional[int], Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + description="Minimum time taken for a ping reply.", + title="Minimum Time (ns)", ), ] = None - received: Optional[int] = None - sent: Optional[int] = None + received: Annotated[ + int, Field(description="Number of pings received.", title="Received") + ] + sent: Annotated[int, Field(description="Number of pings sent.", title="Sent")] stdDevNanoseconds: Annotated[ Optional[int], Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + description="Standard deviation of time taken for all pings.", + title="Standard Deviation (ns)", ), ] = None totalTimeNanoseconds: Annotated[ Optional[int], - Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." - ), + Field(description="Total time taken for all pings.", title="Total Time (ns)"), ] = None class IslPingStatusDetail(BaseModel): - details: Optional[IslPingStatusDetailDetails] = None - error: Optional[str] = None - name: Optional[str] = None - success: Optional[bool] = None + details: Annotated[ + Optional[IslPingStatusDetailDetails], + Field(description="Details of the ping result, if available.", title="Details"), + ] = None + error: Annotated[ + Optional[str], + Field(description="Error message, if the ping failed.", title="Error"), + ] = None + name: Annotated[ + Optional[str], Field(description="Name of the ping result.", title="Name") + ] = None + success: Annotated[ + bool, + Field(description="Indicates if the ping was successful.", title="Success"), + ] class IslPingStatus(BaseModel): """ - IslPingStatus defines the observed state of IslPing + The result of the ISL ping """ details: Annotated[ @@ -1437,8 +1442,8 @@ class Fabric(BaseModel): Fabric is the Schema for the fabrics API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^fabrics\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^Fabric$")] metadata: FabricMetadata spec: Annotated[ FabricSpec, @@ -1471,8 +1476,8 @@ class ISL(BaseModel): ISL is the Schema for the isls API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^fabrics\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^ISL$")] metadata: ISLMetadata spec: Annotated[ ISLSpec, @@ -1504,8 +1509,8 @@ class IslPing(BaseModel): IslPing is the Schema for the islpings API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^fabrics\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^IslPing$")] metadata: IslPingMetadata spec: Annotated[ IslPingSpec, @@ -1516,10 +1521,7 @@ class IslPing(BaseModel): ] status: Annotated[ Optional[IslPingStatus], - Field( - description="IslPingStatus defines the observed state of IslPing", - title="Status", - ), + Field(description="The result of the ISL ping", title="Status"), ] = None diff --git a/pydantic_eda/apps/filters/v1alpha1/models.py b/pydantic_eda/apps/filters/v1alpha1/models.py index 046535a..26b741c 100644 --- a/pydantic_eda/apps/filters/v1alpha1/models.py +++ b/pydantic_eda/apps/filters/v1alpha1/models.py @@ -1693,8 +1693,8 @@ class ControlPlaneFilter(BaseModel): ControlPlaneFilter is the Schema for the controlplanefilters API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^filters\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^ControlPlaneFilter$")] metadata: ControlPlaneFilterMetadata spec: Annotated[ ControlPlaneFilterSpec, @@ -1727,8 +1727,8 @@ class Filter(BaseModel): Filter is the Schema for the filters API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^filters\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^Filter$")] metadata: FilterMetadata spec: Annotated[ FilterSpec, diff --git a/pydantic_eda/apps/interfaces/v1alpha1/models.py b/pydantic_eda/apps/interfaces/v1alpha1/models.py index 616d698..9a6f2f4 100644 --- a/pydantic_eda/apps/interfaces/v1alpha1/models.py +++ b/pydantic_eda/apps/interfaces/v1alpha1/models.py @@ -913,8 +913,10 @@ class Breakout(BaseModel): Breakout is the Schema for the breakouts API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^interfaces\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^Breakout$")] metadata: BreakoutMetadata spec: Annotated[ BreakoutSpec, @@ -947,8 +949,10 @@ class CheckInterfaces(BaseModel): CheckInterfaces is the Schema for the checkinterfacess API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^interfaces\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^CheckInterfaces$")] metadata: CheckInterfacesMetadata spec: Annotated[ CheckInterfacesSpec, @@ -981,8 +985,10 @@ class Interface(BaseModel): Interface is the Schema for the interfaces API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^interfaces\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^Interface$")] metadata: InterfaceMetadata spec: Annotated[ InterfaceSpec, @@ -1009,8 +1015,10 @@ class InterfaceState(BaseModel): InterfaceState is the Schema for the interfacestates API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^interfaces\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^InterfaceState$")] metadata: InterfaceStateMetadata spec: Annotated[InterfaceStateSpec, Field(title="Specification")] status: Annotated[ diff --git a/pydantic_eda/apps/oam/v1alpha1/models.py b/pydantic_eda/apps/oam/v1alpha1/models.py index e47c0be..277949b 100644 --- a/pydantic_eda/apps/oam/v1alpha1/models.py +++ b/pydantic_eda/apps/oam/v1alpha1/models.py @@ -1167,7 +1167,7 @@ class MirrorMetadata(BaseModel): namespace: str -class NewPingSpec(BaseModel): +class PingSpec(BaseModel): """ Ping allows a ping to be initiated to a specific address on node/set of nodes. """ @@ -1193,14 +1193,14 @@ class NewPingSpec(BaseModel): nodeSelectors: Annotated[ Optional[List[str]], Field( - description="NodeSelectors is a list of node selectors to select nodes to perform pings on.\nThis matches labels on TopoNode resources, including those TopoNodes in the list of nodes that pings will be performed on.\nIf no nodes are specified, and no node selectors are specified, all nodes in the given namespace will be selected.", + description="List of selectors to select nodes to perform pings on.\nThis matches labels on TopoNode resources, including those TopoNodes in the list of nodes that pings will be performed on.\nIf no nodes are specified, and no node selectors are specified, all nodes in the given namespace will be selected.", title="Node Selectors", ), ] = None nodes: Annotated[ Optional[List[str]], Field( - description="Nodes is a list of nodes to perform pings on.\nItems in the list should be the names of the nodes, where each node will have a ping performed on it.\nIf no nodes are specified, and no node selectors are specified, all nodes in the given namespace will be selected.", + description="List of nodes to perform pings from.\nItems in the list should be the names of the nodes, where each node will have a ping performed on it.\nIf no nodes are specified, and no node selectors are specified, all nodes in the given namespace will be selected.", title="Nodes", ), ] = None @@ -1213,56 +1213,82 @@ class NewPingSpec(BaseModel): ] = 5 -class NewPingStatusDetailDetails(BaseModel): +class PingStatusDetailDetails(BaseModel): + """ + Details of the ping result, if available. + """ + averageTimeNanoseconds: Annotated[ Optional[int], Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + description="Average time taken for a ping reply.", + title="Average Time (ns)", ), ] = None maxTimeNanoseconds: Annotated[ Optional[int], Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + description="Maximum time taken for a ping reply.", + title="Maximum Time (ns)", ), ] = None minTimeNanoseconds: Annotated[ Optional[int], Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + description="Minimum time taken for a ping reply.", + title="Minimum Time (ns)", ), ] = None - received: Optional[int] = None - sent: Optional[int] = None + received: Annotated[ + int, Field(description="Number of pings received.", title="Received") + ] + sent: Annotated[int, Field(description="Number of pings sent.", title="Sent")] stdDevNanoseconds: Annotated[ Optional[int], Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." + description="Standard deviation of time taken for all pings.", + title="Standard Deviation (ns)", ), ] = None totalTimeNanoseconds: Annotated[ Optional[int], - Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." - ), + Field(description="Total time taken for all pings.", title="Total Time (ns)"), ] = None -class NewPingStatusDetail(BaseModel): - details: Optional[NewPingStatusDetailDetails] = None - error: Optional[str] = None - networkInstance: Optional[str] = None - node: Optional[str] = None - success: Optional[bool] = None +class PingStatusDetail(BaseModel): + details: Annotated[ + Optional[PingStatusDetailDetails], + Field(description="Details of the ping result, if available.", title="Details"), + ] = None + error: Annotated[ + Optional[str], + Field(description="Error message, if the ping failed.", title="Error"), + ] = None + networkInstance: Annotated[ + Optional[str], + Field( + description="Network instance used to source the ping from.", + title="Network Instance", + ), + ] = None + node: Annotated[ + Optional[str], + Field(description="Node the ping was sourced from.", title="Node"), + ] = None + success: Annotated[ + Optional[bool], + Field(description="Indicates if the ping was successful.", title="Success"), + ] = None -class NewPingStatus(BaseModel): +class PingStatus(BaseModel): """ - NewPingStatus defines the observed state of NewPing + PingStatus defines the observed state of Ping """ details: Annotated[ - Optional[List[NewPingStatusDetail]], + Optional[List[PingStatusDetail]], Field( description="Details contains the results of the pings performed on each node.\nEach entry in the list corresponds to a node that was pinged." ), @@ -1276,7 +1302,7 @@ class NewPingStatus(BaseModel): ] = "Success" -NewPingMetadata = MirrorMetadata +PingMetadata = MirrorMetadata class TechSupportSpec(BaseModel): @@ -1559,8 +1585,8 @@ class Mirror(BaseModel): Mirror is the Schema for the mirrors API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^oam\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^Mirror$")] metadata: MirrorMetadata spec: Annotated[ MirrorSpec, @@ -1588,37 +1614,36 @@ class MirrorList(BaseModel): kind: str -class NewPing(BaseModel): +class Ping(BaseModel): """ - NewPing is the Schema for the newpings API + Ping is the Schema for the pings API """ - apiVersion: str - kind: str - metadata: NewPingMetadata + apiVersion: Annotated[str, Field(pattern="^oam\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^Ping$")] + metadata: PingMetadata spec: Annotated[ - NewPingSpec, + PingSpec, Field( description="Ping allows a ping to be initiated to a specific address on node/set of nodes.", title="Specification", ), ] status: Annotated[ - Optional[NewPingStatus], + Optional[PingStatus], Field( - description="NewPingStatus defines the observed state of NewPing", - title="Status", + description="PingStatus defines the observed state of Ping", title="Status" ), ] = None -class NewPingList(BaseModel): +class PingList(BaseModel): """ - NewPingList is a list of newpings + PingList is a list of pings """ apiVersion: str - items: Optional[List[NewPing]] = None + items: Optional[List[Ping]] = None kind: str @@ -1627,8 +1652,8 @@ class TechSupport(BaseModel): TechSupport is the Schema for the techsupports API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^oam\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^TechSupport$")] metadata: TechSupportMetadata spec: Annotated[ TechSupportSpec, @@ -1661,8 +1686,8 @@ class Threshold(BaseModel): Threshold is the Schema for the thresholds API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^oam\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^Threshold$")] metadata: ThresholdMetadata spec: Annotated[ ThresholdSpec, diff --git a/pydantic_eda/apps/os/v1alpha1/models.py b/pydantic_eda/apps/os/v1alpha1/models.py index bb76091..9c8d81d 100644 --- a/pydantic_eda/apps/os/v1alpha1/models.py +++ b/pydantic_eda/apps/os/v1alpha1/models.py @@ -381,8 +381,8 @@ class DeployImage(BaseModel): DeployImage is the Schema for the deployimages API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^os\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^DeployImage$")] metadata: DeployImageMetadata spec: Annotated[ DeployImageSpec, diff --git a/pydantic_eda/apps/protocols/v1/models.py b/pydantic_eda/apps/protocols/v1/models.py index 7aa78d2..343e9c1 100644 --- a/pydantic_eda/apps/protocols/v1/models.py +++ b/pydantic_eda/apps/protocols/v1/models.py @@ -4105,8 +4105,8 @@ class AggregateRoute(BaseModel): AggregateRoute is the Schema for the aggregateroutes API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^AggregateRoute$")] metadata: AggregateRouteMetadata spec: Annotated[ AggregateRouteSpec, @@ -4139,8 +4139,8 @@ class BGPGroup(BaseModel): BGPGroup is the Schema for the bgpgroups API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^BGPGroup$")] metadata: BGPGroupMetadata spec: Annotated[ BGPGroupSpec, @@ -4173,8 +4173,8 @@ class BGPPeer(BaseModel): BGPPeer is the Schema for the bgppeers API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^BGPPeer$")] metadata: BGPPeerMetadata spec: Annotated[ BGPPeerSpec, @@ -4207,8 +4207,8 @@ class BGPPeerState(BaseModel): BGPPeerState is the Schema for the bgppeerstates API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^BGPPeerState$")] metadata: BGPPeerStateMetadata spec: Annotated[ BGPPeerStateSpec, @@ -4241,8 +4241,8 @@ class CheckDefaultBgpPeers(BaseModel): CheckDefaultBgpPeers is the Schema for the checkdefaultbgppeerss API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^CheckDefaultBgpPeers$")] metadata: CheckDefaultBgpPeersMetadata spec: Annotated[ CheckDefaultBgpPeersSpec, @@ -4275,8 +4275,8 @@ class DefaultAggregateRoute(BaseModel): DefaultAggregateRoute is the Schema for the defaultaggregateroutes API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^DefaultAggregateRoute$")] metadata: DefaultAggregateRouteMetadata spec: Annotated[ DefaultAggregateRouteSpec, @@ -4309,8 +4309,8 @@ class DefaultBGPGroup(BaseModel): DefaultBGPGroup is the Schema for the defaultbgpgroups API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^DefaultBGPGroup$")] metadata: DefaultBGPGroupMetadata spec: Annotated[ DefaultBGPGroupSpec, @@ -4343,8 +4343,8 @@ class DefaultBGPPeer(BaseModel): DefaultBGPPeer is the Schema for the defaultbgppeers API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^DefaultBGPPeer$")] metadata: DefaultBGPPeerMetadata spec: Annotated[ DefaultBGPPeerSpec, @@ -4377,8 +4377,8 @@ class DefaultRouteReflector(BaseModel): DefaultRouteReflector is the Schema for the defaultroutereflectors API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^DefaultRouteReflector$")] metadata: DefaultRouteReflectorMetadata spec: Annotated[ DefaultRouteReflectorSpec, @@ -4401,8 +4401,8 @@ class DefaultRouteReflectorClient(BaseModel): DefaultRouteReflectorClient is the Schema for the defaultroutereflectorclients API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^DefaultRouteReflectorClient$")] metadata: DefaultRouteReflectorClientMetadata spec: Annotated[ DefaultRouteReflectorClientSpec, @@ -4445,8 +4445,8 @@ class DefaultStaticRoute(BaseModel): DefaultStaticRoute is the Schema for the defaultstaticroutes API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^DefaultStaticRoute$")] metadata: DefaultStaticRouteMetadata spec: Annotated[ DefaultStaticRouteSpec, @@ -4479,8 +4479,8 @@ class RouteReflector(BaseModel): RouteReflector is the Schema for the routereflectors API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^RouteReflector$")] metadata: RouteReflectorMetadata spec: Annotated[ RouteReflectorSpec, @@ -4503,8 +4503,8 @@ class RouteReflectorClient(BaseModel): RouteReflectorClient is the Schema for the routereflectorclients API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^RouteReflectorClient$")] metadata: RouteReflectorClientMetadata spec: Annotated[ RouteReflectorClientSpec, @@ -4537,8 +4537,8 @@ class RouteReflectorClientState(BaseModel): RouteReflectorClientState is the Schema for the routereflectorclientstates API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^RouteReflectorClientState$")] metadata: RouteReflectorClientStateMetadata spec: Annotated[ RouteReflectorClientStateSpec, @@ -4581,8 +4581,8 @@ class RouteReflectorState(BaseModel): RouteReflectorState is the Schema for the routereflectorstates API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^RouteReflectorState$")] metadata: RouteReflectorStateMetadata spec: Annotated[ RouteReflectorStateSpec, @@ -4615,8 +4615,8 @@ class StaticRoute(BaseModel): StaticRoute is the Schema for the staticroutes API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^protocols\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^StaticRoute$")] metadata: StaticRouteMetadata spec: Annotated[ StaticRouteSpec, diff --git a/pydantic_eda/apps/qos/v1/models.py b/pydantic_eda/apps/qos/v1/models.py index 84e5e60..3b4b8f5 100644 --- a/pydantic_eda/apps/qos/v1/models.py +++ b/pydantic_eda/apps/qos/v1/models.py @@ -1759,8 +1759,8 @@ class EgressPolicy(BaseModel): EgressPolicy is the Schema for the egresspolicys API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^qos\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^EgressPolicy$")] metadata: EgressPolicyMetadata spec: Annotated[ EgressPolicySpec, @@ -1793,8 +1793,8 @@ class ForwardingClass(BaseModel): ForwardingClass is the Schema for the forwardingclasss API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^qos\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^ForwardingClass$")] metadata: ForwardingClassMetadata spec: Annotated[ Optional[Dict[str, Any]], @@ -1827,8 +1827,8 @@ class IngressPolicy(BaseModel): IngressPolicy is the Schema for the ingresspolicys API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^qos\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^IngressPolicy$")] metadata: IngressPolicyMetadata spec: Annotated[ IngressPolicySpec, @@ -1861,8 +1861,8 @@ class PolicyAttachment(BaseModel): PolicyAttachment is the Schema for the policyattachments API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^qos\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^PolicyAttachment$")] metadata: PolicyAttachmentMetadata spec: Annotated[ PolicyAttachmentSpec, @@ -1895,8 +1895,8 @@ class PolicyDeployment(BaseModel): PolicyDeployment is the Schema for the policydeployments API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^qos\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^PolicyDeployment$")] metadata: PolicyDeploymentMetadata spec: Annotated[ PolicyDeploymentSpec, @@ -1929,8 +1929,8 @@ class Queue(BaseModel): Queue is the Schema for the queues API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^qos\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Queue$")] metadata: QueueMetadata spec: Annotated[ QueueSpec, diff --git a/pydantic_eda/apps/routing/v1alpha1/models.py b/pydantic_eda/apps/routing/v1alpha1/models.py index cd02ebe..f484162 100644 --- a/pydantic_eda/apps/routing/v1alpha1/models.py +++ b/pydantic_eda/apps/routing/v1alpha1/models.py @@ -1171,8 +1171,8 @@ class AttachmentLookup(BaseModel): AttachmentLookup is the Schema for the attachmentlookups API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^routing\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^AttachmentLookup$")] metadata: AttachmentLookupMetadata spec: Annotated[ AttachmentLookupSpec, @@ -1205,8 +1205,8 @@ class DefaultInterface(BaseModel): DefaultInterface is the Schema for the defaultinterfaces API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^routing\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^DefaultInterface$")] metadata: DefaultInterfaceMetadata spec: Annotated[ DefaultInterfaceSpec, @@ -1239,8 +1239,8 @@ class DefaultRouter(BaseModel): DefaultRouter is the Schema for the defaultrouters API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^routing\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^DefaultRouter$")] metadata: DefaultRouterMetadata spec: Annotated[ DefaultRouterSpec, @@ -1273,8 +1273,8 @@ class Drain(BaseModel): Drain is the Schema for the drains API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^routing\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^Drain$")] metadata: DrainMetadata spec: Annotated[ DrainSpec, @@ -1307,8 +1307,8 @@ class RouteLookup(BaseModel): RouteLookup is the Schema for the routelookups API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^routing\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^RouteLookup$")] metadata: RouteLookupMetadata spec: Annotated[ RouteLookupSpec, @@ -1341,8 +1341,8 @@ class SystemInterface(BaseModel): SystemInterface is the Schema for the systeminterfaces API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^routing\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^SystemInterface$")] metadata: SystemInterfaceMetadata spec: Annotated[ SystemInterfaceSpec, diff --git a/pydantic_eda/apps/routingpolicies/v1alpha1/models.py b/pydantic_eda/apps/routingpolicies/v1alpha1/models.py index b95f65f..f62cd38 100644 --- a/pydantic_eda/apps/routingpolicies/v1alpha1/models.py +++ b/pydantic_eda/apps/routingpolicies/v1alpha1/models.py @@ -742,8 +742,10 @@ class ASPathSet(BaseModel): ASPathSet is the Schema for the aspathsets API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^routingpolicies\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^ASPathSet$")] metadata: ASPathSetMetadata spec: Annotated[ ASPathSetSpec, @@ -776,8 +778,10 @@ class CommunitySet(BaseModel): CommunitySet is the Schema for the communitysets API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^routingpolicies\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^CommunitySet$")] metadata: CommunitySetMetadata spec: Annotated[ CommunitySetSpec, @@ -810,8 +814,10 @@ class Policy(BaseModel): Policy is the Schema for the policys API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^routingpolicies\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^Policy$")] metadata: PolicyMetadata spec: Annotated[ PolicySpec, @@ -844,8 +850,10 @@ class PrefixSet(BaseModel): PrefixSet is the Schema for the prefixsets API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^routingpolicies\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^PrefixSet$")] metadata: PrefixSetMetadata spec: Annotated[ PrefixSetSpec, diff --git a/pydantic_eda/apps/security/v1alpha1/models.py b/pydantic_eda/apps/security/v1alpha1/models.py index 6e8324e..9682f81 100644 --- a/pydantic_eda/apps/security/v1alpha1/models.py +++ b/pydantic_eda/apps/security/v1alpha1/models.py @@ -315,8 +315,8 @@ class Keychain(BaseModel): Keychain is the Schema for the keychains API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^security\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^Keychain$")] metadata: KeychainMetadata spec: Annotated[ KeychainSpec, @@ -339,8 +339,8 @@ class KeychainDeployment(BaseModel): KeychainDeployment is the Schema for the keychaindeployments API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^security\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^KeychainDeployment$")] metadata: KeychainDeploymentMetadata spec: Annotated[ KeychainDeploymentSpec, diff --git a/pydantic_eda/apps/services/v1/models.py b/pydantic_eda/apps/services/v1/models.py index c2793b8..b27f983 100644 --- a/pydantic_eda/apps/services/v1/models.py +++ b/pydantic_eda/apps/services/v1/models.py @@ -5482,8 +5482,8 @@ class BridgeDomain(BaseModel): BridgeDomain is the Schema for the bridgedomains API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^services\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^BridgeDomain$")] metadata: BridgeDomainMetadata spec: Annotated[ BridgeDomainSpec, @@ -5516,8 +5516,8 @@ class BridgeInterface(BaseModel): BridgeInterface is the Schema for the bridgeinterfaces API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^services\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^BridgeInterface$")] metadata: BridgeInterfaceMetadata spec: Annotated[ BridgeInterfaceSpec, @@ -5544,8 +5544,8 @@ class DHCPRelay(BaseModel): DHCPRelay is the Schema for the dhcprelays API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^services\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^DHCPRelay$")] metadata: DHCPRelayMetadata spec: Annotated[ DHCPRelaySpec, @@ -5578,8 +5578,8 @@ class EdgePing(BaseModel): EdgePing is the Schema for the edgepings API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^services\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^EdgePing$")] metadata: EdgePingMetadata spec: Annotated[ EdgePingSpec, @@ -5612,8 +5612,8 @@ class IRBInterface(BaseModel): IRBInterface is the Schema for the irbinterfaces API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^services\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^IRBInterface$")] metadata: IRBInterfaceMetadata spec: Annotated[ IRBInterfaceSpec, @@ -5646,8 +5646,8 @@ class RoutedInterface(BaseModel): RoutedInterface is the Schema for the routedinterfaces API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^services\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^RoutedInterface$")] metadata: RoutedInterfaceMetadata spec: Annotated[ RoutedInterfaceSpec, @@ -5680,8 +5680,8 @@ class Router(BaseModel): Router is the Schema for the routers API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^services\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^Router$")] metadata: RouterMetadata spec: Annotated[ RouterSpec, @@ -5714,8 +5714,8 @@ class VLAN(BaseModel): VLAN is the Schema for the vlans API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^services\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^VLAN$")] metadata: VLANMetadata spec: Annotated[ VLANSpec, @@ -5742,8 +5742,8 @@ class VirtualNetwork(BaseModel): VirtualNetwork is the Schema for the virtualnetworks API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^services\\.eda\\.nokia\\.com/v1$")] + kind: Annotated[str, Field(pattern="^VirtualNetwork$")] metadata: VirtualNetworkMetadata spec: Annotated[ VirtualNetworkSpec, diff --git a/pydantic_eda/apps/siteinfo/v1alpha1/models.py b/pydantic_eda/apps/siteinfo/v1alpha1/models.py index 1af862f..7bbc4e4 100644 --- a/pydantic_eda/apps/siteinfo/v1alpha1/models.py +++ b/pydantic_eda/apps/siteinfo/v1alpha1/models.py @@ -321,8 +321,8 @@ class Banner(BaseModel): Banner is the Schema for the banners API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^siteinfo\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^Banner$")] metadata: BannerMetadata spec: Annotated[ BannerSpec, diff --git a/pydantic_eda/apps/system/v1alpha1/models.py b/pydantic_eda/apps/system/v1alpha1/models.py index e444041..e016147 100644 --- a/pydantic_eda/apps/system/v1alpha1/models.py +++ b/pydantic_eda/apps/system/v1alpha1/models.py @@ -652,8 +652,8 @@ class Monitor(BaseModel): Monitor is the Schema for the monitors API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^system\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^Monitor$")] metadata: MonitorMetadata spec: Annotated[ MonitorSpec, @@ -676,8 +676,8 @@ class MonitorAggregateState(BaseModel): MonitorAggregateState is the Schema for the monitoraggregatestates API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^system\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^MonitorAggregateState$")] metadata: MonitorAggregateStateMetadata spec: Annotated[ MonitorAggregateStateSpec, @@ -720,8 +720,8 @@ class MonitorState(BaseModel): MonitorState is the Schema for the monitorstates API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^system\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^MonitorState$")] metadata: MonitorStateMetadata spec: Annotated[ MonitorStateSpec, diff --git a/pydantic_eda/apps/timing/v1alpha1/models.py b/pydantic_eda/apps/timing/v1alpha1/models.py index ae19e04..a7b4861 100644 --- a/pydantic_eda/apps/timing/v1alpha1/models.py +++ b/pydantic_eda/apps/timing/v1alpha1/models.py @@ -395,8 +395,8 @@ class NTPClient(BaseModel): NTPClient is the Schema for the ntpclients API """ - apiVersion: str - kind: str + apiVersion: Annotated[str, Field(pattern="^timing\\.eda\\.nokia\\.com/v1alpha1$")] + kind: Annotated[str, Field(pattern="^NTPClient$")] metadata: NTPClientMetadata spec: Annotated[ NTPClientSpec, diff --git a/pydantic_eda/apps/topologies/v1alpha1/models.py b/pydantic_eda/apps/topologies/v1alpha1/models.py index 21d5ce4..7f0fb77 100644 --- a/pydantic_eda/apps/topologies/v1alpha1/models.py +++ b/pydantic_eda/apps/topologies/v1alpha1/models.py @@ -650,8 +650,10 @@ class Topology(BaseModel): Topology is the Schema for the topologies API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^topologies\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^Topology$")] metadata: TopologyMetadata spec: Annotated[ TopologySpec, @@ -674,8 +676,10 @@ class DeviationOverlay(BaseModel): DeviationOverlay is the Schema for the deviationoverlays API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^topologies\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^DeviationOverlay$")] metadata: DeviationOverlayMetadata spec: Annotated[ DeviationOverlaySpec, @@ -708,8 +712,10 @@ class LldpOverlay(BaseModel): LldpOverlay is the Schema for the lldpoverlays API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^topologies\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^LldpOverlay$")] metadata: LldpOverlayMetadata spec: Annotated[ LldpOverlaySpec, @@ -742,8 +748,10 @@ class TopologyGrouping(BaseModel): TopologyGrouping is the Schema for the topologygroupings API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^topologies\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^TopologyGrouping$")] metadata: TopologyGroupingMetadata spec: Annotated[ TopologyGroupingSpec, @@ -786,8 +794,10 @@ class TrafficRateOverlay(BaseModel): TrafficRateOverlay is the Schema for the trafficrateoverlays API """ - apiVersion: str - kind: str + apiVersion: Annotated[ + str, Field(pattern="^topologies\\.eda\\.nokia\\.com/v1alpha1$") + ] + kind: Annotated[str, Field(pattern="^TrafficRateOverlay$")] metadata: TrafficRateOverlayMetadata spec: Annotated[ TrafficRateOverlaySpec, diff --git a/pydantic_eda/core/v25_8_1/models.py b/pydantic_eda/core/v25_8_1/models.py new file mode 100644 index 0000000..cdabda9 --- /dev/null +++ b/pydantic_eda/core/v25_8_1/models.py @@ -0,0 +1,1826 @@ +# generated by datamodel-codegen: +# filename: core.json + +from __future__ import annotations + +from typing import Annotated, Any, Dict, List, Literal, Optional + +from pydantic import AwareDatetime, BaseModel, Field, RootModel + + +class AlarmData(BaseModel): + """ + The information about a single alarm or alarm history + """ + + acknowledged: Annotated[ + Optional[bool], + Field(description="An indication if the alarm has been acknowledged."), + ] = None + acknowledgedUntil: Annotated[ + Optional[str], + Field(description="Indicates the end time of the acknowledgement."), + ] = None + cleared: Annotated[ + Optional[bool], + Field(description="An indication if the alarm has been cleared."), + ] = None + clusterMember: Annotated[ + Optional[str], + Field(description="The cluster member that generated this alarm."), + ] = None + description: Annotated[ + Optional[str], Field(description="A description for the alarm.") + ] = None + group: Annotated[ + Optional[str], + Field( + description="Indicates the group of the resource the alarm is present on." + ), + ] = None + jsPath: Annotated[ + Optional[str], + Field( + description='a unnormalized jspath relating to the object in the alarm state. For\nexample\n.node{.name=="spine-1-1"}.srl{.version=="24.10.1"}.interface{.name=="ethernet-1-1"}.' + ), + ] = None + kind: Annotated[ + Optional[str], + Field(description="Indicates the kind of resource the alarm is present on."), + ] = None + lastAcknowledged: Annotated[ + Optional[str], Field(description="the time this alarm was last acknowledged.") + ] = None + lastChanged: Annotated[ + Optional[str], + Field( + description="The last time that the alarm was changed; as provided by the raiser of the alarm." + ), + ] = None + lastSuppressed: Annotated[ + Optional[str], Field(description="the time this alarm was last suppressed.") + ] = None + name: Annotated[ + Optional[str], + Field( + description="The unique name for the alarm, e.g. InterfaceDown-spine-1-1-ethernet-1-1." + ), + ] = None + namespace: Annotated[ + Optional[str], Field(description="The namespace of the alarm") + ] = None + occurrences: Annotated[ + Optional[int], + Field( + description="The number of occurrences of this alarm (the number of times it has been raised)." + ), + ] = None + parentAlarms: Annotated[ + Optional[List[str]], + Field( + description="The names of other alarms that are parents of this alarm. This may be used to\nfilter out alarms that are not a root cause." + ), + ] = None + probableCause: Annotated[ + Optional[str], + Field( + description="the probable cause for raising the alarm. This field is optional, and\nshould also be a description indicating the primary probable cause of the\nalarm, which may be enriched with relevant information from this specific\nalarm instance. The complete alarm below contains an example." + ), + ] = None + remedialAction: Annotated[ + Optional[str], + Field( + description="any remedial actions the user could try to resolve/clear the alarm. This\nfield is optional, and may also be enriched with relevant information\nfrom this specific alarm instance. The complete alarm below contains an\nexample." + ), + ] = None + resource: Annotated[ + Optional[str], + Field(description="The name of the resource that this alarm is present on."), + ] = None + severity: Annotated[ + Optional[Literal["warning", "minor", "major", "critical"]], + Field(description="Severity of the alarm"), + ] = None + sourceGroup: Annotated[ + Optional[str], + Field( + description="Indicates indicates the group of the resource that raised this alarm, e.g. interfaces.eda.nokia.com." + ), + ] = None + sourceKind: Annotated[ + Optional[str], + Field( + description="Indicates the Kind of the resource that raised this alarm, e.g. InterfaceState." + ), + ] = None + sourceResource: Annotated[ + Optional[str], + Field( + description="Indicates the the name of the resource that raised this alarm, e.g. spine-1-1-ethernet-1-1." + ), + ] = None + suppressed: Annotated[ + Optional[bool], + Field(description="An indication if the alarm has been suppressed."), + ] = None + suppressedUntil: Annotated[ + Optional[str], Field(description="Indicates the end time of the suppression.") + ] = None + type: Annotated[ + Optional[str], Field(description="A kind for the alarm, e.g. InterfaceDown") + ] = None + + +class AlarmHistoryData(BaseModel): + alarm: Optional[AlarmData] = None + index: Annotated[ + Optional[str], + Field( + description="The index of the history entry within the entries for a single alarm.." + ), + ] = None + + +class AlarmNamespaceAndName(BaseModel): + name: Annotated[Optional[str], Field(description="The name of an alarm")] = None + namespace: Annotated[ + Optional[str], Field(description="The namespace of an alarm") + ] = None + + +class AuthPasswordPolicy(BaseModel): + allowUserName: Annotated[ + Optional[bool], + Field( + description="If true, prevents passwords from being or containing the user name." + ), + ] = None + digits: Annotated[ + Optional[int], + Field( + description="Minimum number of digits required in a password. Can be zero.", + ge=0, + ), + ] = None + forceExpiredPasswordChange: Annotated[ + Optional[int], + Field( + description="The maximum number of days until a password change is enforced.\nA value of zero means no change is required.", + ge=0, + ), + ] = None + hashingAlgorithm: Annotated[ + Optional[Literal["argon2", "pbkdf2-sha512", "pbkdf2-sha256", "pbkdf2"]], + Field( + description="The hashing algorithm to use when hashing stored passwords." + ), + ] = None + length: Annotated[ + Optional[int], + Field(description="Minimum password length. This must be at least 1.", ge=1), + ] = None + lowerCase: Annotated[ + Optional[int], + Field( + description="Minimum number of lower case characters required in a password. Can be zero.", + ge=0, + ), + ] = None + maxFailureWaitSeconds: Annotated[ + Optional[int], + Field( + description="The number of seconds before the users access will be restored, after too many authentication failures.", + ge=0, + ), + ] = None + maxLoginFailure: Annotated[ + Optional[int], + Field( + description="The number of login/authentication failures before a lockout policy takes effect. Zero means no enforcement.", + ge=0, + ), + ] = None + passwordHistory: Annotated[ + Optional[int], + Field( + description="The number of passwords remembered to enforce no re-use of passwords. Zero means no re-use enforcement.", + ge=0, + ), + ] = None + permanentLockout: Annotated[ + Optional[bool], + Field( + description='If true, lockout is permanent and the users access must be re-enabled by an administrator.\nIf false, the users access will be re-enabled after "maxFailureWaitSeconds" seconds.' + ), + ] = None + resetTimeSeconds: Annotated[ + Optional[int], + Field( + description="When lockout is not permanent, the count of authentication failures for a user will be reset\nthis many seconds after the last authentication failure.", + ge=0, + ), + ] = None + specialChars: Annotated[ + Optional[int], + Field( + description="Minimum number of special characters required in a password. Can be zero.", + ge=0, + ), + ] = None + upperCase: Annotated[ + Optional[int], + Field( + description="Minimum number of upper case characters required in a password. Can be zero.", + ge=0, + ), + ] = None + + +class Credentials(BaseModel): + temporary: Annotated[ + Optional[bool], + Field( + description="This is true if the password being set is a temporary password. In this case the user\nis required to change the password after they login using the temporary password." + ), + ] = None + value: Annotated[ + Optional[str], Field(description="The new password for the user.") + ] = None + + +class ErrorIndex(BaseModel): + index: Optional[int] = None + + +class ErrorItem(BaseModel): + error: Optional[Dict[str, Any]] = None + type: Optional[str] = None + + +class ErrorResponse(BaseModel): + """ + Generic error response for REST APIs + """ + + code: Annotated[ + int, Field(description="the numeric HTTP error code for the response.") + ] + details: Annotated[ + Optional[str], Field(description="The optional details of the error response.") + ] = None + dictionary: Annotated[ + Optional[Dict[str, Any]], + Field( + description='Dictionary/map of associated data/information relevant to the error.\nThe error "message" may contain {{name}} escapes that should be substituted\nwith information from this dictionary.' + ), + ] = None + domain: Annotated[ + Optional[str], + Field( + description='The "domain" for the error. If empty, it is an EDA\ncore error. Alternatively it can be an EDA application\n"apiVersion" value (e.g. interfaces.eda.nokia.com/v1alpha1)\nindicating that the error is specific to that application.\nThe domain gives the receiver information that they can use\nto help them interpret the "internal" error code value, or\nto find an internationalization translation for the message.' + ), + ] = None + errors: Annotated[ + Optional[List[ErrorItem]], + Field( + description="Collection of errors in cases where more than one exists. This needs to be\nflexible so we can support multiple formats" + ), + ] = None + index: Optional[ErrorIndex] = None + internal: Annotated[ + Optional[int], + Field( + description="Internal error code in cases where we don't have an array of errors" + ), + ] = None + message: Annotated[ + str, Field(description="The basic text error message for the error response.") + ] + ref: Annotated[ + Optional[str], + Field( + description="Reference to the error source. Should typically be the URI of the request" + ), + ] = None + type: Annotated[ + Optional[str], + Field( + description="URI pointing at a document that describes the error and mitigation steps\nIf there is no document, point to the RFC for the HTTP error code" + ), + ] = None + + +class FlowListEntry(BaseModel): + id: Annotated[Optional[int], Field(description="The id of the workflow")] = None + name: Annotated[Optional[str], Field(description="Name of the workflow")] = None + namespace: Annotated[ + Optional[str], Field(description="The namespace in which the workflow ran") + ] = None + parentId: Annotated[ + Optional[int], Field(description="The id of the parent workflow, if any") + ] = None + state: Optional[ + Literal[ + "waitingToStart", + "running", + "waitingForInput", + "terminated", + "failed", + "completed", + "subflowWaitingForInput", + ] + ] = None + type: Annotated[Optional[str], Field(description="The type of workflow")] = None + + +class FlowListResult(BaseModel): + """ + A list of flows + """ + + flows: Optional[List[FlowListEntry]] = None + + +class FlowStage(BaseModel): + """ + Describes the stage of a workflow + """ + + completed: Annotated[ + Optional[bool], Field(description="True if the stage has completed") + ] = None + hadError: Annotated[ + Optional[bool], + Field(description="True if the stage is complete and there was an error"), + ] = None + name: Annotated[Optional[str], Field(description="Name of the flow stage")] = None + skipped: Annotated[ + Optional[bool], Field(description="True if the stage was skipped") + ] = None + started: Annotated[ + Optional[bool], Field(description="True if the stage has started") + ] = None + subFlowIds: Annotated[ + Optional[List[int]], + Field(description="The ids of flows triggered by the stage"), + ] = None + + +class GroupIDs(RootModel[List[str]]): + root: Annotated[ + List[str], Field(title="A list of user group identifiers (uuid values).") + ] + + +class GroupVersionKind(BaseModel): + group: Annotated[Optional[str], Field(description="Name of the API group")] = None + kind: Annotated[Optional[str], Field(description="The Kind of the resource")] = None + version: Annotated[Optional[str], Field(description="Version of the API group")] = ( + None + ) + + +class GroupVersionResource(BaseModel): + group: Annotated[Optional[str], Field(description="Name of the API group")] = None + resource: Annotated[ + Optional[str], Field(description="The plural name of the resource") + ] = None + version: Annotated[Optional[str], Field(description="Version of the API group")] = ( + None + ) + + +class HealthServiceStatus(BaseModel): + error: Annotated[ + Optional[str], Field(description="Detailed status if the service is not up.") + ] = None + status: Annotated[ + Literal["UP", "DOWN"], + Field(description="Health status of the given service. UP or DOWN."), + ] + + +class Identifier(BaseModel): + group: Optional[str] = None + id: Optional[int] = None + kind: Optional[str] = None + name: Optional[str] = None + namespace: Optional[str] = None + version: Optional[str] = None + + +class K8SPatchOp(BaseModel): + from_: Annotated[Optional[str], Field(alias="from")] = None + op: str + path: str + value: Optional[Dict[str, Any]] = None + x_permissive: Annotated[Optional[bool], Field(alias="x-permissive")] = None + + +class LabelCompletionResponse(BaseModel): + results: Optional[List[str]] = None + + +class LineSegment(BaseModel): + endLine: Optional[int] = None + startLine: Optional[int] = None + + +class Metadata(BaseModel): + annotations: Optional[Dict[str, str]] = None + labels: Optional[Dict[str, str]] = None + name: Annotated[ + str, + Field( + max_length=253, + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + ), + ] + namespace: Optional[str] = None + + +class NamespaceData(BaseModel): + """ + Information about an individual namespace + """ + + description: Annotated[ + Optional[str], Field(description="The description of the namespace") + ] = None + name: Annotated[Optional[str], Field(description="The namespace name")] = None + + +class NamespaceGetResponse(BaseModel): + """ + Body of the non streaming namespace get request + """ + + allNamesapces: Annotated[ + Optional[bool], + Field( + description="If true, the requestor is considered to have permission to access all namespaces" + ), + ] = None + namespaces: Annotated[ + Optional[List[NamespaceData]], Field(description="The list of namespaces") + ] = None + + +class NsCrGvkName(BaseModel): + gvk: Optional[GroupVersionKind] = None + name: Optional[str] = None + namespace: Optional[str] = None + + +class ProviderAuth(BaseModel): + bindCredential: Annotated[ + str, Field(description="Credentials to use when binding to an LDAP provider") + ] + bindDN: Annotated[ + str, Field(description="DN to use when binding to an LDAP provider") + ] + + +class QueryCompletion(BaseModel): + completion: Optional[str] = None + token: Optional[str] = None + + +class QueryCompletionResponse(BaseModel): + """ + The result of a successful query auto-completion request + """ + + completions: Annotated[ + Optional[List[QueryCompletion]], + Field(description="Array of possible auto-completion results."), + ] = None + + +class QueryFieldAnnotation(BaseModel): + end_char: Optional[int] = None + start_char: Optional[int] = None + + +class ResourceRule(BaseModel): + apiGroups: Annotated[ + List[str], + Field( + description='The API groups for the resources controlled by the rule.\nAn API group consists of an apiGroup and a version, e.g. "apigroup/version".\nThe API group can be a wildcard ("*"), in which case it will match any API group.\nIn addition, the version can be a wildcard.' + ), + ] + permissions: Annotated[ + Optional[Literal["none", "read", "readWrite"]], + Field(description="Permissions for resources specified by the rule."), + ] = None + resources: Annotated[ + List[str], + Field( + description='Names for the resources controlled by the rule.\nIt can be a wildcard ("*"), in which case it will match any resource\nin the matching API groups.' + ), + ] + + +class StoreAppInstalledSettings(BaseModel): + appId: Annotated[ + Optional[str], Field(description="The application identifier.") + ] = None + settings: Annotated[ + Optional[Dict[str, Dict[str, Any]]], + Field(description="The settings for the application as a JSON object."), + ] = None + + +class StoreAppVersion(BaseModel): + """ + The information about an application version available from a catalog. + At least one of "semVer" or "commitHash" must/will be defined. + """ + + appId: Annotated[ + Optional[str], Field(description="The identifier for the application") + ] = None + catalog: Annotated[ + Optional[str], + Field(description="The catalog in which this application version was found"), + ] = None + commitHash: Annotated[ + Optional[str], Field(description="The commit hash for the application version.") + ] = None + semVer: Annotated[ + Optional[str], + Field(description="The semantic version for the application version."), + ] = None + + +class StoreAppVersionMetadata(BaseModel): + publishedTime: Annotated[ + Optional[AwareDatetime], + Field( + description="The date and time when the application version was published." + ), + ] = None + + +class StoreAppVersionWithMetadata(BaseModel): + metadata: Optional[StoreAppVersionMetadata] = None + version: Optional[StoreAppVersion] = None + + +class StoreCategoryList(RootModel[List[str]]): + root: List[str] + + +class TableRule(BaseModel): + """ + A role rule controlling access to a EDB table. Note that + there is never write access to EDB. + """ + + path: Annotated[ + str, + Field( + description='EDB path to which this rule applies. It can end in ".*"\nin which case the final portion of the table path can be anything, if the\nprefix matches. It can end in ".**" in which case the table path can be\nanything if the prefix matches.', + min_length=1, + pattern="^\\\\..*", + ), + ] + permissions: Annotated[ + Literal["none", "read"], + Field(description="Permissions for the given EDB path."), + ] + + +class TopoAttrMetadata(BaseModel): + type: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoLinkEndpoint(BaseModel): + endpoint: Optional[str] = None + node: Optional[str] = None + node_key: Optional[str] = None + + +class TopoNodeGrouping(BaseModel): + group: Optional[str] = None + tier: Optional[int] = None + + +class TopoOverlayAttrMetadata(BaseModel): + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + + +class TopoOverlayAttrQuery(BaseModel): + attributes: Optional[Dict[str, TopoOverlayAttrMetadata]] = None + query: Optional[str] = None + + +class TopoOverlayBadgeMetadata(BaseModel): + badge_name: Optional[str] = None + badge_path: Optional[str] = None + color: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + value: Optional[int] = None + + +class TopoOverlayEndpointState(BaseModel): + state: Optional[int] = None + + +TopoOverlayLinkState = TopoOverlayEndpointState + + +class TopoOverlayNodeState(BaseModel): + badges: Optional[List[int]] = None + state: Optional[int] = None + + +class TopoOverlayStateMetadata(BaseModel): + color: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + value: Optional[int] = None + + +class TopoSchema(BaseModel): + group: Optional[str] = None + kind: Optional[str] = None + version: Optional[str] = None + + +class TopologyStateGroupSelector(BaseModel): + group: Annotated[ + Optional[str], + Field( + description='The group to assign to nodes that match the selector.\n+eda:ui:title="Group"' + ), + ] = None + nodeSelector: Annotated[ + Optional[List[str]], + Field( + description='+kubebuilder:validation:Optional\n+eda:ui:title="Node Selector"\n+eda:ui:format="labelselector"\nLabel selector to use to match nodes that should be assigned to this group.' + ), + ] = None + + +class TopologyStateTierSelector(BaseModel): + nodeSelector: Annotated[ + Optional[List[str]], + Field( + description='+kubebuilder:validation:Optional\n+eda:ui:title="Node Selector"\n+eda:ui:format="labelselector"\nLabel selector to use to match nodes that should be assigned to this tier.' + ), + ] = None + tier: Annotated[ + Optional[int], + Field( + description='The tier to assign to nodes that match the selector.\n+eda:ui:title="Tier"' + ), + ] = None + + +class TransactionContent(BaseModel): + apiVersion: Optional[str] = None + kind: Optional[str] = None + metadata: Optional[Metadata] = None + spec: Optional[Dict[str, Any]] = None + + +class TransactionId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A transaction identifier; these are assigned by the system to a posted transaction." + ), + ] = None + + +class TransactionInputResource(BaseModel): + isDelete: Optional[bool] = None + name: Optional[NsCrGvkName] = None + + +class TransactionNodeResult(BaseModel): + """ + The name of a node with changes from a transaction, and a list + of errors that occurred for the node + """ + + errors: Annotated[ + Optional[List[str]], Field(description="Resulting errors for the node") + ] = None + name: Annotated[Optional[str], Field(description="The name of the node")] = None + namespace: Annotated[ + Optional[str], Field(description="The namespace of the node") + ] = None + + +class TransactionNsCrGvkNames(BaseModel): + gvk: Optional[GroupVersionKind] = None + names: Optional[List[str]] = None + namespace: Optional[str] = None + + +class TransactionPatch(BaseModel): + patchOps: List[K8SPatchOp] + target: NsCrGvkName + + +class TransactionResultInputResources(BaseModel): + inputCrs: Annotated[ + Optional[List[TransactionInputResource]], + Field(description="List of input resources from the transaction"), + ] = None + limitedAccess: Annotated[ + Optional[bool], + Field( + description="This field is true if the list returned here is not the complete list of input resources in the transaction because the user does not have read-access to some of them" + ), + ] = None + + +class TransactionResultObjectString(BaseModel): + data: Optional[str] = None + + +class TransactionScriptResults(BaseModel): + executionTime: Optional[int] = None + + +class TransactionState(BaseModel): + state: Annotated[ + Optional[str], Field(description="The state of the transaction") + ] = None + + +class TransactionStructuredAppError(BaseModel): + message: Optional[str] = None + messageKey: Optional[str] = None + values: Optional[Dict[str, Dict[str, Any]]] = None + + +class TransactionSummaryResult(BaseModel): + """ + Summary of the result of a transaction + """ + + commitHash: Annotated[ + Optional[str], Field(description="The git commit hash for the transaction") + ] = None + description: Annotated[ + Optional[str], + Field( + description="The description of the transaction, as posted in the transaction request." + ), + ] = None + details: Annotated[ + Optional[str], + Field( + description="The type of details available for the transaction, as posted in the transaction request." + ), + ] = None + dryRun: Annotated[ + Optional[bool], + Field( + description="If true the transaction was not committed and ran in dry run mode." + ), + ] = None + id: Annotated[Optional[int], Field(description="The transaction identifier")] = None + lastChangeTimestamp: Annotated[ + Optional[str], Field(description="The time that the transaction completed.") + ] = None + state: Annotated[ + Optional[str], Field(description="The state of the transaction.") + ] = None + success: Annotated[ + Optional[bool], Field(description="True if the transaction was successful.") + ] = None + username: Annotated[ + Optional[str], Field(description="The user who posted the transaction.") + ] = None + + +class TransactionSummaryResults(BaseModel): + results: Annotated[ + Optional[List[TransactionSummaryResult]], + Field(description="array of summary-results for transactions"), + ] = None + + +class TransactionValue(BaseModel): + value: Optional[TransactionContent] = None + + +class UrlRule(BaseModel): + path: Annotated[ + str, + Field( + description='The API server URL path to which this rule applies. It can end in "/*"\nin which case the final portion of the URL path can be anything, if the\nprefix matches. It can end in "/**" in which case the URL path can be\nanything if the prefix matches.",', + min_length=1, + pattern="^/.*", + ), + ] + permissions: Annotated[ + Optional[Literal["none", "read", "readWrite"]], + Field(description="The permissions for the API server URL for the rule."), + ] = None + + +class UserStatus(BaseModel): + failedLoginSinceSuccessfulLogin: Optional[int] = None + isFederatedUser: Annotated[ + Optional[bool], + Field(description="True if the user comes from a federated LDAP server"), + ] = None + lastFailedLogin: Optional[str] = None + lastSuccessfulLogin: Optional[str] = None + temporarilyDisabled: Optional[bool] = None + + +class UserStorageInFileContent(BaseModel): + file_content: Annotated[ + str, + Field( + alias="file-content", + description="The desired content of the user-storage file. This will be base64 decoded before storing if the request indicates that the content is base64 encoded.", + ), + ] + + +class UserStorageOutDirEntry(BaseModel): + """ + user-storage directory entry + """ + + modification_time: Annotated[ + Optional[AwareDatetime], + Field( + alias="modification-time", + description="modification type of the item, if a file", + ), + ] = None + name: Annotated[str, Field(description="name of the item within the directory")] + type: Annotated[str, Field(description='type of the item; "file" or "directory"')] + + +class UserStorageOutFileContent(BaseModel): + file_content: Annotated[ + Optional[str], + Field( + alias="file-content", + description="content of the file, will be base64 encoded if the request asked for this", + ), + ] = None + file_deleted: Annotated[ + Optional[bool], + Field( + alias="file-deleted", + description="if present and true, indicates the file has been deleted; used for\nstreamed responses", + ), + ] = None + file_name: Annotated[str, Field(alias="file-name", description="name of the file")] + modification_time: Annotated[ + Optional[AwareDatetime], + Field( + alias="modification-time", + description="UTC modification time of the file, as an RFC 3339 date/time.\nNot valid if file-deleted is true (in a streamed response)", + ), + ] = None + + +class Workflow(BaseModel): + cr: Annotated[ + Dict[str, Dict[str, Any]], + Field(description="Custom resource that defines the workflow to execute"), + ] + description: Annotated[ + str, Field(description="Description message for the workflow") + ] + + +class WorkflowId(BaseModel): + id: Annotated[ + Optional[int], + Field( + description="A workflow identifier; these are assigned by the system to a posted workflow." + ), + ] = None + + +class WorkflowState(BaseModel): + runningState: Optional[str] = None + state: Optional[str] = None + + +class WorkflowStatusSummary(BaseModel): + creationTime: Optional[str] = None + group: Optional[str] = None + id: Optional[int] = None + kind: Optional[str] = None + lastUpdate: Optional[str] = None + name: Optional[str] = None + namespace: Optional[str] = None + parent: Optional[Identifier] = None + rootWorkflow: Optional[Identifier] = None + state: Optional[ + Literal[ + "OK", + "Failed", + "Terminated", + "WaitingForInput", + "Running", + "WaitingToStart", + "SubflowWaitingForInput", + "Completed", + ] + ] = None + username: Optional[str] = None + version: Optional[str] = None + + +class SingleVersionInfo(BaseModel): + builtDate: Annotated[ + Optional[str], Field(description="The build-time for the component.") + ] = None + version: Annotated[ + Optional[str], Field(description="The version string for the component.") + ] = None + + +class VersionInfo(RootModel[Optional[Dict[str, SingleVersionInfo]]]): + root: Optional[Dict[str, SingleVersionInfo]] = None + + +class AuthProviderAuth(BaseModel): + """ + If present, bind to LDAP server with the given credentials. Otherwise do not bind. + """ + + bindCredential: Annotated[ + str, Field(description="Credentials to use when binding to an LDAP provider") + ] + bindDN: Annotated[ + str, Field(description="DN to use when binding to an LDAP provider") + ] + + +class AuthProviderGroupSupport(BaseModel): + """ + Configuration for group import/sync with LDAP. If not present, groups will not synchronized with EDA. + """ + + NameLDAPAttribute: Annotated[ + str, Field(description="The LDAP group name attribute") + ] + filter: Annotated[ + Optional[str], + Field( + description="Further for filtering when retrieving LDAP groups. Ensure starts and ends with parentheses if using." + ), + ] = None + groupLDAPDN: Annotated[ + str, Field(description="The LDAP DN where groups are found.") + ] + memberAttribute: Annotated[ + Optional[str], + Field( + description='The group attribute for a members. Usually "member" or "memberUid".' + ), + ] = None + memberOfAttribute: Annotated[ + Optional[str], + Field( + description='If retrievalStrategy is "memberOf", this is the LDAP user attribute for group memberships.' + ), + ] = None + membershipAttributeType: Annotated[ + Optional[Literal["DN", "UID"]], + Field( + description="How users are identified in a group member entry: either DN or UID." + ), + ] = None + membershipUserAttribute: Annotated[ + Optional[str], + Field( + description="Only required if membershipAttributeType is UID; then it is the user attribute that should match the group member value." + ), + ] = None + objectClasses: Annotated[ + str, + Field( + description="The LDAP object class or classes used for groups. If more than one, they must be comma-separated." + ), + ] + retrievalStrategy: Annotated[ + Optional[Literal["member", "memberOf"]], + Field( + description='The strategy for retrieving groups. Should be "member" to get group membership from the group, or "memberOf" to get group membership from the user.' + ), + ] = None + + +class StoreAppRequirementsGraphItemInstalledAppVersion(BaseModel): + """ + The application version installed in the cluster, if installed. + """ + + appId: Annotated[ + Optional[str], Field(description="The identifier for the application") + ] = None + catalog: Annotated[ + Optional[str], + Field(description="The catalog in which this application version was found"), + ] = None + commitHash: Annotated[ + Optional[str], Field(description="The commit hash for the application version.") + ] = None + semVer: Annotated[ + Optional[str], + Field(description="The semantic version for the application version."), + ] = None + + +class StoreAppRequirementsGraphItemTargetAppVersion(BaseModel): + """ + This graph item instance contains the dependencies for this particular application version. + """ + + appId: Annotated[ + Optional[str], Field(description="The identifier for the application") + ] = None + catalog: Annotated[ + Optional[str], + Field(description="The catalog in which this application version was found"), + ] = None + commitHash: Annotated[ + Optional[str], Field(description="The commit hash for the application version.") + ] = None + semVer: Annotated[ + Optional[str], + Field(description="The semantic version for the application version."), + ] = None + + +class AccessQuery(BaseModel): + gvk: Optional[GroupVersionKind] = None + gvr: Optional[GroupVersionResource] = None + namespace: Annotated[ + Optional[str], + Field( + description="The namespace to check. Empty string (or omit) to check for cluster-wide access" + ), + ] = None + path: Annotated[ + Optional[str], + Field( + description="Target url or table of the access check. Provided when type is table or url" + ), + ] = None + permissions: Annotated[ + Optional[Literal["read", "readWrite"]], + Field(description="The permissions for the requested resource/url/table."), + ] = None + type: Annotated[ + Literal["gvk", "gvr", "url", "table"], + Field(description="The type of rule to check for"), + ] + + +class AccessResult(BaseModel): + access: Annotated[ + Optional[bool], + Field(description="Indicates if the user can access the requested resource"), + ] = None + error: Optional[ErrorResponse] = None + + +class AuthProvider(BaseModel): + auth: Optional[AuthProviderAuth] = None + enabled: Annotated[ + Optional[bool], + Field(description="If true, checking/syncing this LDAP provider is enabled."), + ] = None + groupSupport: Optional[AuthProviderGroupSupport] = None + idAttribute: Annotated[ + str, + Field( + description="Name of the LDAP attribute, which is used as a unique object identifier (UUID) for objects in LDAP." + ), + ] + import_: Annotated[ + Optional[bool], + Field( + alias="import", + description="If true, the LDAP information will be imported into the EDA (Keycloak) database.", + ), + ] = None + name: Annotated[ + str, Field(description="The name to give to the LDAP provider; must be unique.") + ] + pagination: Annotated[ + Optional[bool], + Field(description="Set to true if the LDAP server supports pagination."), + ] = None + periodicSync: Annotated[ + Optional[bool], + Field( + description="If true, periodic synchronization of new changed or newly created LDAP users to Keycloak will occur." + ), + ] = None + periodicSyncSecs: Annotated[ + Optional[int], + Field( + description="If periodic sync is enabled, this is the period in seconds that synchronization will occur." + ), + ] = None + rdnLDAPAttribute: Annotated[ + str, + Field( + description="Name of the LDAP attribute, which is used as RDN (top attribute) of typical user DN. Usually it's the same as the Username LDAP attribute, however it is not required." + ), + ] + readOnly: Annotated[ + bool, + Field( + description="If false, changes made to LDAP-mapped attribute via EDA will be synced back to the LDAP server. Otherwise, changes are not made in LDAP." + ), + ] + scope: Annotated[ + Optional[Literal["One Level", "Subtree"]], + Field( + description='Must be "One Level" or "Subtree". If "One Level", the search applies only for users in the DNs specified by User DNs. If "Subtree", the search applies to the whole subtree.' + ), + ] = None + timeout: Annotated[ + Optional[int], Field(description="LDAP connection timeout in milliseconds") + ] = None + tls: Annotated[ + Optional[bool], + Field(description="If true, encrypts the connection to LDAP using STARTTLS"), + ] = None + type: Annotated[ + Literal["ldap"], + Field(description='The type of provider. Currently only "ldap" is supported.'), + ] + url: Annotated[str, Field(description="Connection URL to your LDAP server")] + userDN: Annotated[ + str, + Field( + description="Full DN of LDAP tree where your users are. This DN is the parent of LDAP users." + ), + ] + userObjectClasses: Annotated[ + str, + Field( + description="All values of LDAP objectClass attribute for users in LDAP, divided by commas. (e.g. inetOrgPerson, organizationalPerson)." + ), + ] + userSearchFilter: Annotated[ + Optional[str], + Field( + description="Additional LDAP filter for filtering searched users. Leave this empty if you don't need an additional filter. Make sure that it starts with '(' and ends with ')'." + ), + ] = None + usernameAttribute: Annotated[ + str, + Field( + description="Name of the LDAP attribute, which is mapped as EDA username. For many LDAP server vendors it can be 'uid'." + ), + ] + uuid: Annotated[ + Optional[str], + Field( + description="The unique identifier given to the entry when it is created." + ), + ] = None + vendor: Annotated[str, Field(description="LDAP vendor (provider).")] + + +class AuthProviderTestParams(BaseModel): + action: Annotated[ + Literal["connection", "authentication"], + Field(description="The test action to take."), + ] + auth: Optional[ProviderAuth] = None + name: Annotated[ + Optional[str], Field(description="The name of the provider to test") + ] = None + timeout: Annotated[ + Optional[int], Field(description="LDAP connection timeout in milliseconds") + ] = None + tls: Annotated[ + Optional[bool], + Field(description="If true, encrypts the connection to LDAP using STARTTLS"), + ] = None + url: Annotated[str, Field(description="Connection URL to your LDAP server")] + + +class AuthProviders(RootModel[List[AuthProvider]]): + root: List[AuthProvider] + + +class AuthRole(BaseModel): + description: str + name: Annotated[ + str, + Field( + pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" + ), + ] + namespace: Annotated[ + Optional[str], Field(pattern="^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$") + ] = None + resourceRules: Annotated[ + Optional[List[ResourceRule]], + Field(description="Rules for access to resources."), + ] = None + tableRules: Annotated[ + Optional[List[TableRule]], + Field(description="Rules for access to EDB tables, including via EQL."), + ] = None + urlRules: Annotated[ + Optional[List[UrlRule]], + Field(description="Rules for access to APIServer routes."), + ] = None + + +class AuthRoles(RootModel[List[AuthRole]]): + root: List[AuthRole] + + +class AuthUser(BaseModel): + email: Optional[str] = None + enabled: Optional[bool] = None + firstName: Optional[str] = None + groups: Annotated[ + Optional[List[str]], + Field( + description="contains the UUIDs of the groups of which the user is a member." + ), + ] = None + lastName: Optional[str] = None + maxSessions: Optional[int] = None + password: Optional[str] = None + status: Optional[UserStatus] = None + username: Optional[str] = None + uuid: Optional[str] = None + + +class AuthUserGroup(BaseModel): + description: Optional[str] = None + full_users: Annotated[ + Optional[List[AuthUser]], + Field( + alias="full-users", + description="contains the full user definitions of the users who are members of the group, if requested", + ), + ] = None + fullRoles: Annotated[ + Optional[List[AuthRole]], + Field( + description="contains the full role definitions of the Roles and ClusterRoles associated with the group, if requested" + ), + ] = None + isFederated: Annotated[ + Optional[bool], + Field( + description="if true, indicates that the group was imported from a federated LDAP server" + ), + ] = None + name: Optional[str] = None + roles: Annotated[ + Optional[List[str]], + Field( + description='Contains the names of the ClusterRoles and Roles roles associated with the group.\nA Role name has the form "namesspace:rolename", whereas a ClusteRole name is a\nsimple "rolename", without a colon or a namespace.' + ), + ] = None + users: Annotated[ + Optional[List[str]], + Field( + description="contains the usernames of the users who are members of the group" + ), + ] = None + uuid: Optional[str] = None + + +class AuthUserGroups(RootModel[List[AuthUserGroup]]): + root: List[AuthUserGroup] + + +class AuthUsers(RootModel[List[AuthUser]]): + root: List[AuthUser] + + +class CheckAccessRequest(RootModel[Optional[Dict[str, AccessQuery]]]): + """ + Body of a checkAccess request. Contains a key and AccessQuery for each resource/url/table to be checked for user access + """ + + root: Optional[Dict[str, AccessQuery]] = None + + +class CheckAccessResponse(RootModel[Optional[Dict[str, AccessResult]]]): + """ + Body of a access check response. Contains an AccessResult for each of the keys provided in the request + """ + + root: Optional[Dict[str, AccessResult]] = None + + +class CrAnnotation(BaseModel): + cr: Optional[NsCrGvkName] = None + lines: Optional[List[LineSegment]] = None + + +class FlowGetResponse(BaseModel): + error: Annotated[ + Optional[str], + Field(description="If no error is present, the flow completed successfully"), + ] = None + id: Annotated[Optional[int], Field(description="The id of the workflow")] = None + jsonResult: Annotated[ + Optional[str], Field(description="A JSON representation of the result") + ] = None + log: Annotated[Optional[str], Field(description="Log output from the flow")] = None + name: Annotated[Optional[str], Field(description="Name of the workflow")] = None + namespace: Annotated[ + Optional[str], Field(description="The namespace in which the flow ran") + ] = None + parentId: Annotated[ + Optional[int], Field(description="The id of the parent workflow, if any") + ] = None + stages: Annotated[ + Optional[List[FlowStage]], + Field(description="The list of stages of the workflow"), + ] = None + state: Optional[ + Literal[ + "waitingToStart", + "running", + "waitingForInput", + "terminated", + "failed", + "completed", + "subflowWaitingForInput", + ] + ] = None + subflowsWaitingForInput: Annotated[ + Optional[List[int]], + Field(description="The ids of any subflows that are waiting for user input"), + ] = None + type: Annotated[Optional[str], Field(description="The type of workflow")] = None + waitForInputPrompt: Annotated[ + Optional[str], Field(description="Set if the state is waiting for input") + ] = None + + +class GetLabelCompletionRequest(BaseModel): + gvk: Optional[GroupVersionKind] = None + limit: Annotated[ + Optional[int], Field(description="The maximum number of results to return") + ] = None + namespace: Annotated[ + Optional[str], + Field( + description="The namespace of the GVK if the CRD is namespaced\nrequired: true if the GVK is namespaced" + ), + ] = None + value: Annotated[ + str, + Field( + description="A key value string delimited by =. If the Value does not include an =\nit is assumed to be a Key lookup. If there is an =, everything before\nthe = is assumed to be the key and the lookup will be a value lookup" + ), + ] + + +class Health(BaseModel): + mode: Annotated[ + Literal["ACTIVE", "STANDBY"], + Field(description="Indication of the activity of this cluster."), + ] + services: Annotated[ + Optional[Dict[str, HealthServiceStatus]], + Field( + description="Detailed health of the services comprising the EDA cluster. Keyed by the name of the service." + ), + ] = None + status: Annotated[ + Literal["UP", "DEGRADED", "DOWN"], + Field(description="Overall health status of the EDA cluster."), + ] + timestamp: Annotated[ + AwareDatetime, Field(description="Time that the health report was generated.") + ] + + +class NodeConfigResponse(BaseModel): + annotations: Annotated[ + Optional[List[CrAnnotation]], + Field(description="The the list of annotations for the node configuration"), + ] = None + running: Annotated[ + Optional[str], Field(description="The current node configuration for the node") + ] = None + + +class Overlay(BaseModel): + endpoint_attr_queries: Optional[List[TopoOverlayAttrQuery]] = None + endpoint_state: Optional[List[TopoOverlayStateMetadata]] = None + endpoint_state_heading: Optional[str] = None + endpoint_state_heading_key: Optional[str] = None + group: Optional[str] = None + link_attr_queries: Optional[List[TopoOverlayAttrQuery]] = None + link_state: Optional[List[TopoOverlayStateMetadata]] = None + link_state_heading: Optional[str] = None + link_state_heading_key: Optional[str] = None + name: Optional[str] = None + node_attr_queries: Optional[List[TopoOverlayAttrQuery]] = None + node_badge: Optional[List[TopoOverlayBadgeMetadata]] = None + node_state: Optional[List[TopoOverlayStateMetadata]] = None + node_state_heading: Optional[str] = None + node_state_heading_key: Optional[str] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class Overlays(RootModel[List[Overlay]]): + root: List[Overlay] + + +class QueryField(BaseModel): + alias: Optional[bool] = None + annotations: Optional[List[QueryFieldAnnotation]] = None + display_name: Optional[str] = None + name: Optional[str] = None + type: Optional[str] = None + + +class QuerySchema(BaseModel): + fields: Optional[List[QueryField]] = None + + +class StoreAppManifest(BaseModel): + manifest: Annotated[ + Optional[Dict[str, Dict[str, Any]]], + Field(description="The application manifest as JSON"), + ] = None + metadata: Optional[StoreAppVersionMetadata] = None + version: Optional[StoreAppVersion] = None + + +class StoreAppRequirementsGraphItem(BaseModel): + appId: Annotated[ + str, + Field( + description="The application identifier to which the 'requires' elements of graph items will refer." + ), + ] + installedAppVersion: Optional[StoreAppRequirementsGraphItemInstalledAppVersion] = ( + None + ) + requires: Annotated[ + Optional[List[str]], + Field( + description="The identifiers for the applications on which this application version depends." + ), + ] = None + targetAppVersion: StoreAppRequirementsGraphItemTargetAppVersion + + +class StoreAppSummary(BaseModel): + appId: Annotated[ + Optional[str], Field(description="Unique ID identifying this application") + ] = None + catalogs: Annotated[ + Optional[List[str]], Field(description="Catalogs where this app was found") + ] = None + categories: Annotated[ + Optional[List[str]], Field(description="Application categories.") + ] = None + description: Annotated[ + Optional[str], + Field( + description="Application description that can be used for user display purposes" + ), + ] = None + infoVersion: Optional[StoreAppVersion] = None + infoVersionMetadata: Optional[StoreAppVersionMetadata] = None + installed: Annotated[ + Optional[bool], Field(description='"true" if the app is installed') + ] = None + installedVersion: Optional[StoreAppVersion] = None + installedVersionMetadata: Optional[StoreAppVersionMetadata] = None + latestVersion: Optional[StoreAppVersion] = None + latestVersionMetadata: Optional[StoreAppVersionMetadata] = None + supportedEndpoints: Annotated[ + Optional[List[str]], Field(description="Application supported endpoints.") + ] = None + title: Annotated[ + Optional[str], + Field( + description="Application title that can be used for user display purposes" + ), + ] = None + upgradable: Annotated[ + Optional[bool], + Field(description='"true" if there is a new version that can be installed'), + ] = None + + +class StoreAppSummaryList(RootModel[List[StoreAppSummary]]): + root: List[StoreAppSummary] + + +class StoreAppVersionList(RootModel[List[StoreAppVersionWithMetadata]]): + root: List[StoreAppVersionWithMetadata] + + +class TopoElemMetadata(BaseModel): + attributes: Optional[Dict[str, TopoAttrMetadata]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + subtitle: Optional[str] = None + subtitle_key: Optional[str] = None + + +class TopoOverlayEndpoint(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayEndpointState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayLink(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + cr_name: Optional[str] = None + endpoint_a: Optional[TopoLinkEndpoint] = None + endpoint_a_details: Optional[TopoOverlayEndpoint] = None + endpoint_b: Optional[TopoLinkEndpoint] = None + endpoint_b_details: Optional[TopoOverlayEndpoint] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayLinkState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class TopoOverlayNode(BaseModel): + attributes: Optional[Dict[str, Dict[str, Any]]] = None + badges: Optional[List[int]] = None + cr_name: Optional[str] = None + grouping: Optional[TopoNodeGrouping] = None + key: Optional[str] = None + labels: Optional[Dict[str, str]] = None + name: Optional[str] = None + namespace: Optional[str] = None + overlays: Optional[Dict[str, TopoOverlayNodeState]] = None + schema_: Annotated[Optional[TopoSchema], Field(alias="schema")] = None + state: Optional[int] = None + ui_name: Optional[str] = None + + +class Topology(BaseModel): + endpoints: Optional[TopoElemMetadata] = None + group: Optional[str] = None + grouping: Optional[TopoSchema] = None + links: Optional[TopoElemMetadata] = None + name: Optional[str] = None + nodes: Optional[TopoElemMetadata] = None + ui_description: Optional[str] = None + ui_description_key: Optional[str] = None + ui_name: Optional[str] = None + ui_name_key: Optional[str] = None + version: Optional[str] = None + + +class TopologyStateGroupingBase(BaseModel): + """ + Embed this type inside your topology tier CRD spec to determine the tiers and the + groups of the nodes in the topology. + """ + + groupSelectors: Annotated[ + Optional[List[TopologyStateGroupSelector]], + Field( + description='The set of selectors for assigning nodes to groups\n+eda:ui:title="Group Selectors"' + ), + ] = None + tierSelectors: Annotated[ + Optional[List[TopologyStateTierSelector]], + Field( + description='The set of selectors for assigning nodes to tiers\n+eda:ui:title="Tier Selectors"' + ), + ] = None + uiDescription: Annotated[ + Optional[str], + Field( + description='A description of the topology grouping to expose in the UI\n+eda:ui:title="UI Description"' + ), + ] = None + uiDescriptionKey: Annotated[ + Optional[str], + Field( + description='The translation key for the description of the topology grouping to expose in the UI\n+eda:ui:title="UI Description Key"' + ), + ] = None + uiName: Annotated[ + Optional[str], + Field( + description='The name of the topology grouping to expose in the UI\n+eda:ui:title="UI Name"' + ), + ] = None + uiNameKey: Annotated[ + Optional[str], + Field( + description='The translation key for the name of the topology grouping to expose in the UI\n+eda:ui:title="UI Name Key"' + ), + ] = None + + +class TransactionAppError(BaseModel): + rawError: Optional[str] = None + structuredError: Optional[TransactionStructuredAppError] = None + + +class TransactionIntentResult(BaseModel): + errors: Optional[List[TransactionAppError]] = None + intentName: Optional[NsCrGvkName] = None + outputCrs: Optional[List[NsCrGvkName]] = None + script: Optional[TransactionScriptResults] = None + + +class TransactionResultObject(BaseModel): + after: Optional[TransactionResultObjectString] = None + before: Optional[TransactionResultObjectString] = None + dataUnavailable: Annotated[ + Optional[bool], + Field(description="True if there is no data available for the result"), + ] = None + format: Annotated[ + Optional[str], Field(description="The format of the response - Text or YAML") + ] = None + + +class TransactionType(BaseModel): + create: Optional[TransactionValue] = None + delete: Optional[NsCrGvkName] = None + modify: Optional[TransactionValue] = None + patch: Optional[TransactionPatch] = None + replace: Optional[TransactionValue] = None + + +class UserStorageOutDirContent(BaseModel): + directory_path: Annotated[ + str, + Field( + alias="directory-path", + description="path for the directory within the users storage", + ), + ] + entries: Annotated[ + List[UserStorageOutDirEntry], + Field(description="array of entries for the items in the directory"), + ] + + +class WorkflowResult(BaseModel): + errorMessage: Optional[str] = None + resultMessage: Optional[str] = None + state: Optional[WorkflowState] = None + success: Optional[bool] = None + + +class OverlayState(BaseModel): + links: Optional[Dict[str, TopoOverlayLink]] = None + nodes: Optional[Dict[str, TopoOverlayNode]] = None + + +class QueryResponse(BaseModel): + """ + The response for a non-streaming query request + """ + + data: Optional[List[Dict[str, Any]]] = None + jsonSchema: Annotated[ + Optional[Dict[str, Dict[str, Any]]], + Field( + description="The JSON schema definition for the query data being returned." + ), + ] = None + schema_: Annotated[Optional[QuerySchema], Field(alias="schema")] = None + + +class StoreAppRequirementsGraph(BaseModel): + graphItems: Annotated[ + Optional[List[StoreAppRequirementsGraphItem]], + Field( + description="The items in the requirements graph resulting from the request. Only present if the state is FINISHED." + ), + ] = None + state: Annotated[ + Optional[Literal["UNKNOWN", "RUNNING", "FINISHED", "FAILED"]], + Field(description="The state of the requirements graph generation request."), + ] = None + + +class TopoGroupingStateRequest(BaseModel): + name: Optional[str] = None + spec: Optional[TopologyStateGroupingBase] = None + + +class TopoStateRequest(BaseModel): + grouping: Optional[TopoGroupingStateRequest] = None + namespace: Optional[str] = None + overlays: Optional[List[str]] = None + + +class Topologies(RootModel[List[Topology]]): + root: List[Topology] + + +class TransactionCr(BaseModel): + type: Optional[TransactionType] = None + + +class TransactionExecutionResult(BaseModel): + changedCrs: Annotated[ + Optional[List[TransactionNsCrGvkNames]], + Field(description="List of changed CRs as part of the transaction"), + ] = None + executionSummary: Annotated[ + Optional[str], + Field(description="Information about time taken during processing"), + ] = None + generalErrors: Annotated[ + Optional[List[str]], + Field(description="List of general errors while running the transaction"), + ] = None + intentsRun: Annotated[ + Optional[List[TransactionIntentResult]], + Field(description="List of intents which ran as part of the transaction"), + ] = None + nodesWithConfigChanges: Annotated[ + Optional[List[TransactionNodeResult]], + Field( + description="List of nodes with configuration changes from the transaction" + ), + ] = None + topologySupported: Annotated[ + Optional[bool], + Field( + description="Whether a topology representation of this transaction is supported" + ), + ] = None + + +class TransactionTopologyResult(BaseModel): + overlayMetadata: Optional[Overlay] = None + topology: Optional[OverlayState] = None + topologyMetadata: Optional[Topology] = None + + +class Transaction(BaseModel): + crs: Annotated[ + List[TransactionCr], + Field(description="List of CRs to include in the transaction"), + ] + description: Annotated[ + str, Field(description="Description/commit message for the transaction") + ] + dryRun: Annotated[ + bool, + Field( + description="If true the transaction will not be committed and will run in dry run mode. If false the\ntransaction will be committed" + ), + ] + resultType: Annotated[ + Optional[str], + Field(description="The type of result - errors only, normal, or debug"), + ] = None + retain: Annotated[ + Optional[bool], + Field( + description="retain after results fetched - e.g. after call to get transaction result" + ), + ] = None