diff --git a/catalystwan/api/configuration_groups/parcel.py b/catalystwan/api/configuration_groups/parcel.py index c49f8e67e..4490f4bdb 100644 --- a/catalystwan/api/configuration_groups/parcel.py +++ b/catalystwan/api/configuration_groups/parcel.py @@ -16,7 +16,7 @@ class _ParcelBase(BaseModel): model_config = ConfigDict( - extra="allow", arbitrary_types_allowed=True, populate_by_name=True, json_schema_mode_override="validation" + extra="allow", arbitrary_types_allowed=True, populate_by_name=True, # json_schema_mode_override="validation" ) parcel_name: str = Field( min_length=1, diff --git a/catalystwan/models/configuration/config_migration.py b/catalystwan/models/configuration/config_migration.py index 3b45d5d73..36cf8673f 100644 --- a/catalystwan/models/configuration/config_migration.py +++ b/catalystwan/models/configuration/config_migration.py @@ -1,11 +1,13 @@ -from typing import List +from typing import List, Union from pydantic import BaseModel, ConfigDict, Field +from typing_extensions import Annotated from catalystwan.api.template_api import DeviceTemplateInformation, FeatureTemplateInformation from catalystwan.endpoints.configuration_group import ConfigGroup from catalystwan.models.configuration.feature_profile.common import FeatureProfileCreationPayload from catalystwan.models.configuration.feature_profile.sdwan.policy_object import AnyPolicyObjectParcel +from catalystwan.models.configuration.feature_profile.sdwan.system import AnySystemParcel from catalystwan.models.policy import ( AnyPolicyDefinition, AnyPolicyList, @@ -14,6 +16,14 @@ SecurityPolicy, ) +AnyParcel = Annotated[ + Union[ + AnySystemParcel, + AnyPolicyObjectParcel, + ], + Field(discriminator="type_"), +] + class UX1Policies(BaseModel): model_config = ConfigDict(populate_by_name=True) @@ -58,6 +68,6 @@ class UX2Config(BaseModel): feature_profiles: List[FeatureProfileCreationPayload] = Field( default=[], serialization_alias="featureProfiles", validation_alias="featureProfiles" ) - profile_parcels: List[AnyPolicyObjectParcel] = Field( + profile_parcels: List[AnyParcel] = Field( default=[], serialization_alias="profileParcels", validation_alias="profileParcels" ) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/url.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/url.py index 2a641e1ce..69ca9163c 100644 --- a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/url.py +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/url.py @@ -19,12 +19,14 @@ def add_url(self, pattern: str): class URLAllowParcel(BaseURLParcel): + type_: Literal["security-urllist"] = Field(default="security-urllist", exclude=True) parcel_type: Literal["urlallowed"] = Field( default="urlallowed", validation_alias="type", serialization_alias="type" ) class URLBlockParcel(BaseURLParcel): + type_: Literal["security-urllist"] = Field(default="security-urllist", exclude=True) parcel_type: Literal["urlblocked"] = Field( default="urlblocked", validation_alias="type", serialization_alias="type" ) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/system/aaa.py b/catalystwan/models/configuration/feature_profile/sdwan/system/aaa.py index c18dd2b80..21b4afdc2 100644 --- a/catalystwan/models/configuration/feature_profile/sdwan/system/aaa.py +++ b/catalystwan/models/configuration/feature_profile/sdwan/system/aaa.py @@ -1,5 +1,5 @@ from ipaddress import IPv4Address, IPv6Address -from typing import List, Optional, Union +from typing import List, Literal, Optional, Union from pydantic import AliasPath, BaseModel, ConfigDict, Field @@ -269,6 +269,7 @@ class AuthorizationRuleItem(BaseModel): class AAA(_ParcelBase): + type_: Literal["aaa"] = Field(default="aaa", exclude=True) authentication_group: Union[DefaultGlobalBool, Variable, Global[bool], Default[bool]] = Field( default=as_default(False), validation_alias=AliasPath("data", "authenticationGroup"), diff --git a/catalystwan/models/configuration/feature_profile/sdwan/system/bfd.py b/catalystwan/models/configuration/feature_profile/sdwan/system/bfd.py index 574a4ed53..123e9ccff 100644 --- a/catalystwan/models/configuration/feature_profile/sdwan/system/bfd.py +++ b/catalystwan/models/configuration/feature_profile/sdwan/system/bfd.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Union +from typing import List, Literal, Optional, Union from pydantic import AliasPath, BaseModel, ConfigDict, Field @@ -30,6 +30,7 @@ class Color(BaseModel): class BFD(_ParcelBase): + type_: Literal["bfd"] = Field(default="bfd", exclude=True) model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) multiplier: Optional[Global[int]] = Field( diff --git a/catalystwan/workflows/config_migration.py b/catalystwan/workflows/config_migration.py index 6e9b4ecbb..3ae015ed3 100644 --- a/catalystwan/workflows/config_migration.py +++ b/catalystwan/workflows/config_migration.py @@ -8,6 +8,8 @@ logger = logging.getLogger(__name__) +SUPPORTED_TEMPLATE_TYPES = ["cedge_aaa", "cedge_aaa"] + def log_progress(task: str, completed: int, total: int) -> None: logger.info(f"{task} {completed}/{total}") @@ -15,7 +17,9 @@ def log_progress(task: str, completed: int, total: int) -> None: def transform(ux1: UX1Config) -> UX2Config: ux2 = UX2Config() - ux2.profile_parcels.extend([create_parcel_from_template(ft) for ft in ux1.templates.features]) + for ft in ux1.templates.features: + if ft.template_type in SUPPORTED_TEMPLATE_TYPES: + ux2.profile_parcels.append(create_parcel_from_template(ft)) # Policy Lists for policy_list in ux1.policies.policy_lists: if (parcel := policy_list.to_policy_object_parcel()) is not None: