Skip to content
This repository has been archived by the owner on Nov 21, 2024. It is now read-only.

Use ConvertResult for FTs #741

Merged
merged 5 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions catalystwan/models/configuration/config_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,3 +612,6 @@ class ConvertResult(Generic[TO]):
def update_status(self, status: ConvertStatus, message: str):
self.status = status
self.info.append(message)

def get_info(self) -> str:
return "\n".join(self.info)
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# Copyright 2023 Cisco Systems, Inc. and its affiliates
# Copyright 2024 Cisco Systems, Inc. and its affiliates

from typing import List, Union
Expand All @@ -14,6 +13,7 @@
from .management.ethernet import InterfaceEthernetParcel as ManagementInterfaceEthernetParcel
from .t1e1controller import T1E1ControllerParcel
from .vpn import ManagementVpnParcel, TransportVpnParcel
from .wan.interface.cellular import InterfaceCellularParcel
from .wan.interface.ethernet import InterfaceEthernetParcel
from .wan.interface.gre import InterfaceGreParcel
from .wan.interface.ipsec import InterfaceIpsecParcel
Expand All @@ -37,6 +37,7 @@
InterfaceIpsecParcel,
InterfaceEthernetParcel,
InterfaceMultilinkParcel,
InterfaceCellularParcel,
# Add wan interfaces here
],
Field(discriminator="type_"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
from catalystwan.api.configuration_groups.parcel import Global
from catalystwan.models.configuration.feature_profile.sdwan.system import AAAParcel

from .base import FTConverter

class AAATemplateConverter:

class AAAConverter(FTConverter):
supported_template_types = ("cisco_aaa", "cedge_aaa", "aaa")

def create_parcel(self, name: str, description: str, template_values: dict) -> AAAParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
VirtualApplicationType,
)

from .base import FTConverter

class AppqoeTemplateConverter:

class AppqoeConverter(FTConverter):
supported_template_types = ("appqoe",)

def create_parcel(self, name: str, description: str, template_values: dict) -> AppqoeParcel:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from catalystwan.models.configuration.feature_profile.sdwan.system import BannerParcel

from .base import FTConverter

class BannerTemplateConverter:

class BannerConverter(FTConverter):
supported_template_types = ("cisco_banner",)

def create_parcel(self, name: str, description: str, template_values: dict) -> BannerParcel:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
from typing_extensions import Protocol
# Copyright 2024 Cisco Systems, Inc. and its affiliates
from typing import Optional, Tuple

from catalystwan.models.configuration.config_migration import ConvertResult
from catalystwan.models.configuration.feature_profile.parcel import AnyParcel
from catalystwan.utils.config_migration.converters.exceptions import CatalystwanConverterCantConvertException


class FeatureTemplateConverter(Protocol):
def create_parcel(self, name: str, description: str, template_values: dict) -> AnyParcel:
...
class FTConverter:
"""Feature Template Converter base class."""

supported_template_types: Tuple = tuple()

def __init__(self) -> None:
if not self.supported_template_types:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you think about returning the "unsupported" conversion_result instead of raising the exception?

Copy link
Collaborator Author

@jpkrajewski jpkrajewski Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure good idea 👍

raise ValueError("supported_template_types must be defined in the subclass")
self._convert_result = ConvertResult[AnyParcel]()

def create_parcel(self, name: str, description: str, template_values: dict) -> Optional[AnyParcel]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

@jpkrajewski jpkrajewski Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed FTConverter to abstract class and used abstractmethod

"""This function can modify status and info attributes of the conversion process."""
raise NotImplementedError("create_parcel method must be implemented")

def convert(self, name: str, description: str, template_values: dict) -> ConvertResult[AnyParcel]:
"""Converts the template values into a parcel."""
parcel: Optional[AnyParcel] = None
try:
parcel = self.create_parcel(name, description, template_values)
except CatalystwanConverterCantConvertException as e:
self._convert_result.update_status("failed", str(e))

self._convert_result.output = parcel
return self._convert_result
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
from catalystwan.utils.config_migration.converters.feature_template.helpers import create_dict_without_none
from catalystwan.utils.timezone import Timezone

from .base import FTConverter

class SystemToBasicTemplateConverter:

class SystemToBasicConverter(FTConverter):
supported_template_types = ("cisco_system", "system-vsmart", "system-vedge")

def create_parcel(self, name: str, description: str, template_values: dict) -> BasicParcel:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from catalystwan.models.configuration.feature_profile.sdwan.system import BFDParcel

from .base import FTConverter

class BFDTemplateConverter:

class BFDConverter(FTConverter):
supported_template_types = ("cisco_bfd", "bfd-vedge")

def create_parcel(self, name: str, description: str, template_values: dict) -> BFDParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
from catalystwan.utils.config_migration.converters.feature_template.helpers import create_dict_without_none
from catalystwan.utils.config_migration.steps.constants import LAN_BGP, WAN_BGP

from .base import FTConverter

logger = logging.getLogger(__name__)


class BgpRoutingTemplateConverter:
class BgpRoutingConverter(FTConverter):
supported_template_types = (WAN_BGP, LAN_BGP)

def create_parcel(self, name: str, description: str, template_values: dict) -> RoutingBgpParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
)
from catalystwan.utils.config_migration.converters.exceptions import CatalystwanConverterCantConvertException

from .base import FTConverter

class CellularControllerTemplateConverter:

class CellularControllerConverter(FTConverter):
supported_template_types = ("cellular-cedge-controller",)

def create_parcel(self, name: str, description: str, template_values: dict) -> CellularControllerParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
)
from catalystwan.utils.config_migration.converters.exceptions import CatalystwanConverterCantConvertException

from .base import FTConverter

logger = logging.getLogger(__name__)


class CellularProfileTemplateConverter:
class CellularProfileConverter(FTConverter):
supported_template_types = ("cellular-cedge-profile",)

def create_parcel(self, name: str, description: str, template_values: dict) -> CellularProfileParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
from catalystwan.models.configuration.feature_profile.sdwan.cli.config import ConfigParcel
from catalystwan.utils.config_migration.converters.exceptions import CatalystwanConverterCantConvertException

from .base import FTConverter

class CliTemplateConverter:

class CliConverter(FTConverter):
supported_template_types = ("cli-template",)

def create_parcel(self, name: str, description: str, template_values: dict) -> ConfigParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
from catalystwan.utils.config_migration.converters.exceptions import CatalystwanConverterCantConvertException
from catalystwan.utils.config_migration.converters.feature_template.helpers import create_dict_without_none

from .base import FTConverter

logger = logging.getLogger(__name__)


class DhcpTemplateConverter:
class DhcpConverter(FTConverter):
supported_template_types = ("dhcp", "cisco_dhcp_server", "dhcp-server")

variable_address_pool = "{{dhcp_1_addressPool_networkAddress}}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
TableMap,
)

from .base import FTConverter

class EigrpTemplateConverter:

class EigrpConverter(FTConverter):
supported_template_types = ("eigrp",)

delete_keys = ("as_num",)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
from catalystwan.utils.config_migration.converters.utils import parse_interface_name
from catalystwan.utils.config_migration.steps.constants import MANAGEMENT_VPN_ETHERNET

from .base import FTConverter

class ManagementInterfaceEthernetTemplateConverter:

class ManagementInterfaceEthernetConverter(FTConverter):
supported_template_types = (MANAGEMENT_VPN_ETHERNET,)

def create_parcel(self, name: str, description: str, template_values: dict) -> InterfaceEthernetParcel:
Expand All @@ -37,7 +39,7 @@ def create_parcel(self, name: str, description: str, template_values: dict) -> I
parcel_name=name,
parcel_description=description,
advanced=self.parse_advanced(data),
interface_name=parse_interface_name(data),
interface_name=parse_interface_name(self, data),
interface_description=data.get("description", Default[None](value=None)),
intf_ip_address=self.parse_ipv4_address(data),
shutdown=data.get("shutdown"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from catalystwan.models.configuration.feature_profile.sdwan.system import GlobalParcel

from .base import FTConverter

class GlobalTemplateConverter:

class GlobalConverter(FTConverter):
supported_template_types = ("cedge_global",)

def create_parcel(self, name: str, description: str, template_values: dict) -> GlobalParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
from catalystwan.models.configuration.feature_profile.sdwan.transport.gps import GpsMode, GpsParcel
from catalystwan.utils.config_migration.converters.feature_template.helpers import create_dict_without_none

from .base import FTConverter

class GpsTemplateConverter:

class GpsConverter(FTConverter):
supported_template_types = ("cellular-cedge-gps-controller",)

def create_parcel(self, name: str, description: str, template_values: dict) -> GpsParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@
Trustsec,
VrrpIPv4,
)
from catalystwan.utils.config_migration.converters.feature_template.base import FTConverter
from catalystwan.utils.config_migration.converters.utils import parse_interface_name
from catalystwan.utils.config_migration.steps.constants import LAN_VPN_ETHERNET


class LanInterfaceEthernetTemplateConverter:
class LanInterfaceEthernetConverter(FTConverter):
supported_template_types = (LAN_VPN_ETHERNET,)

delete_keys = (
Expand Down Expand Up @@ -113,7 +114,7 @@ def prepare_parcel_values(self, name: str, description: str, values: dict) -> di
return {"parcel_name": name, "parcel_description": description, **values}

def configure_interface_name(self, values: dict) -> None:
values["interface_name"] = parse_interface_name(values)
values["interface_name"] = parse_interface_name(self, values)

def configure_ethernet_description(self, values: dict) -> None:
values["ethernet_description"] = values.get("description")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
TunnelSourceIPv6,
)
from catalystwan.utils.config_migration.converters.exceptions import CatalystwanConverterCantConvertException
from catalystwan.utils.config_migration.converters.feature_template.base import FTConverter
from catalystwan.utils.config_migration.steps.constants import LAN_VPN_GRE


class LanInterfaceGreTemplateConverter:
class LanInterfaceGreConverter(FTConverter):
supported_template_types = (LAN_VPN_GRE,)

def create_parcel(self, name: str, description: str, template_values: dict) -> InterfaceGreParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
from catalystwan.models.configuration.feature_profile.common import AddressWithMask, TunnelApplication
from catalystwan.models.configuration.feature_profile.sdwan.service.lan.ipsec import InterfaceIpsecParcel
from catalystwan.utils.config_migration.converters.exceptions import CatalystwanConverterCantConvertException
from catalystwan.utils.config_migration.converters.feature_template.base import FTConverter
from catalystwan.utils.config_migration.steps.constants import LAN_VPN_IPSEC


class LanInterfaceIpsecTemplateConverter:
class LanInterfaceIpsecConverter(FTConverter):
supported_template_types = (LAN_VPN_IPSEC,)

# Default Values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
MultilinkNimList,
)
from catalystwan.models.configuration.feature_profile.sdwan.service.lan.multilink import InterfaceMultilinkParcel
from catalystwan.utils.config_migration.converters.feature_template.base import FTConverter
from catalystwan.utils.config_migration.converters.feature_template.model_definition_normalizer import (
flatten_datapaths,
normalize_to_model_definition,
)
from catalystwan.utils.config_migration.steps.constants import LAN_VPN_MULTILINK


class LanMultilinkTemplateConverter:
class LanMultilinkConverter(FTConverter):
supported_template_types = (LAN_VPN_MULTILINK,)

def create_parcel(self, name: str, description: str, template_values: dict) -> InterfaceMultilinkParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
VrrpIPv4,
VrrpIPv4SecondaryAddress,
)
from catalystwan.utils.config_migration.converters.feature_template.base import FTConverter
from catalystwan.utils.config_migration.steps.constants import LAN_VPN_SVI


class InterfaceSviTemplateConverter:
class InterfaceSviConverter(FTConverter):
"""
A class for converting template values into a InterfaceSviParcel object.
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
from catalystwan.models.configuration.feature_profile.sdwan.system import LoggingParcel
from catalystwan.models.configuration.feature_profile.sdwan.system.logging_parcel import CypherSuite

from .base import FTConverter

class LoggingTemplateConverter:

class LoggingConverter(FTConverter):
supported_template_types = ("cisco_logging", "logging")

def create_parcel(self, name: str, description: str, template_values: dict) -> LoggingParcel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
StaticRpAddress,
)

from .base import FTConverter

class MulticastToMulticastTemplateConverter:

class MulticastToMulticastConverter(FTConverter):
"""This is corner case.
Multicast Parcel is not a direct conversion from template.
It is a combination of multiple templates.
Expand Down Expand Up @@ -67,7 +69,7 @@ def get_example_payload(self):
}


class PimToMulticastTemplateConverter:
class PimToMulticastConverter(FTConverter):
"""This is corner case.
Multicast Parcel is not a direct conversion from template.
It is a combination of multiple templates.
Expand Down Expand Up @@ -245,7 +247,7 @@ def get_example_payload(self):
}


class IgmpToMulticastTemplateConverter:
class IgmpToMulticastConverter(FTConverter):
"""This is corner case.
Multicast Parcel is not a direct conversion from template.
It is a combination of multiple templates.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright 2024 Cisco Systems, Inc. and its affiliates
import logging
from ipaddress import AddressValueError, IPv4Address, IPv4Interface, IPv6Address, IPv6Interface
from typing import List, Optional, Union, get_args

Expand Down Expand Up @@ -103,6 +104,8 @@
Variable,
]

logger = logging.getLogger(__name__)


def to_snake_case(s: str) -> str:
"""Converts a string from kebab-case to snake_case."""
Expand All @@ -111,7 +114,10 @@ def to_snake_case(s: str) -> str:

def cast_value_to_global(value: Union[DeviceVariable, str, int, List[str], List[int]]) -> CastedTypes:
if isinstance(value, DeviceVariable):
return as_variable(value=convert_varname(value.name))
converted_name = convert_varname(value.name)
if converted_name != value.name:
logger.info(f"Converted variable name: {value.name} -> {converted_name}")
return as_variable(value=converted_name)
if isinstance(value, list):
value_type = Global[List[int]] if isinstance(value[0], int) else Global[List[str]]
return value_type(value=value) # type: ignore
Expand Down
Loading