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

Service Parcels #533

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
001433a
Start work on Service models
jpkrajewski Mar 19, 2024
782845d
Service VPN passes for the internal vManage
jpkrajewski Mar 20, 2024
3ac2152
Refactor Service VPN converter. Instantiate the converter in the crea…
jpkrajewski Mar 21, 2024
36cb084
Add Interface GRE model. Add unittests. Add integration tests. Change…
jpkrajewski Mar 21, 2024
c74a445
Add SVI Interface model. Add unit tests and integration test for the …
jpkrajewski Mar 22, 2024
d6162d9
Add Ethernet Interface. Add Unit tests. Add integratio tests. Fix VPN…
jpkrajewski Mar 25, 2024
dba2e06
Rename Feature Profile builder file. Use from typing_extensions impor…
jpkrajewski Mar 25, 2024
6a8f62a
Add IPSEC interface model. Add unittests. Add integration tests.
jpkrajewski Mar 26, 2024
3d06526
Add Ethernet interface. Add Builders for other and system profile. Im…
jpkrajewski Mar 26, 2024
98e127b
Fixes
jpkrajewski Mar 27, 2024
415d6b0
Add default=None for Optional fields.
jpkrajewski Mar 27, 2024
54af49e
Add missing imports
jpkrajewski Mar 27, 2024
fef723f
Prepare the rest service parcels for converter
jpkrajewski Mar 27, 2024
db6d6fe
Fix add default=None for optional field
jpkrajewski Mar 27, 2024
60b1ffc
Add OSPF converter
jpkrajewski Mar 27, 2024
a81a5f4
Add OSPF intergration test
jpkrajewski Mar 28, 2024
919e63d
Add OSPFv3IP4 converter.
jpkrajewski Mar 28, 2024
19b9007
Add ospfv3ipv6 converter. add unittest add integration tests
jpkrajewski Mar 29, 2024
88e7cd5
Add ospf model to transform. Add service feature profile in transform…
jpkrajewski Apr 2, 2024
2e73c61
update deprecated github actions (#544)
sbasan Apr 2, 2024
5cdb72f
Remove annotation
jpkrajewski Apr 2, 2024
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
6 changes: 3 additions & 3 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Set Up Poetry
Expand All @@ -20,7 +20,7 @@ jobs:
- name: Build HTML
run: poetry run sphinx-build -M html docs/source docs/build
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: html-docs
path: docs/build/html/
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ jobs:
run: |
curl -fsSL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt-get install -y nodejs
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Set Up Poetry
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ jobs:
run: |
curl -fsSL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt-get install -y nodejs
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Set Up Poetry
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/unittests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ jobs:
run: |
curl -fsSL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt-get install -y nodejs
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Set Up Poetry
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
shell: bash

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Set Up Poetry
Expand Down
2 changes: 2 additions & 0 deletions catalystwan/api/api_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
)
from catalystwan.api.alarms_api import AlarmsAPI
from catalystwan.api.basic_api import DevicesAPI, DeviceStateAPI
from catalystwan.api.builders import BuilderAPI
from catalystwan.api.config_device_inventory_api import ConfigurationDeviceInventoryAPI
from catalystwan.api.config_group_api import ConfigGroupAPI
from catalystwan.api.dashboard_api import DashboardAPI
Expand Down Expand Up @@ -67,3 +68,4 @@ def __init__(self, session: ManagerSession):
self.policy = PolicyAPI(session)
self.sd_routing_feature_profiles = SDRoutingFeatureProfilesAPI(session)
self.sdwan_feature_profiles = SDWANFeatureProfilesAPI(session)
self.builders = BuilderAPI(session)
13 changes: 13 additions & 0 deletions catalystwan/api/builders/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from catalystwan.api.builders.feature_profiles.builder_factory import FeatureProfileBuilderFactory

if TYPE_CHECKING:
from catalystwan.session import ManagerSession


class BuilderAPI:
def __init__(self, session: ManagerSession):
self.feature_profiles = FeatureProfileBuilderFactory(session=session)
42 changes: 42 additions & 0 deletions catalystwan/api/builders/feature_profiles/builder_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from __future__ import annotations

from typing import TYPE_CHECKING, Callable, Mapping, Union

from catalystwan.api.builders.feature_profiles.other import OtherFeatureProfileBuilder
from catalystwan.api.builders.feature_profiles.service import ServiceFeatureProfileBuilder
from catalystwan.api.builders.feature_profiles.system import SystemFeatureProfileBuilder
from catalystwan.exceptions import CatalystwanException
from catalystwan.models.configuration.feature_profile.common import ProfileType

if TYPE_CHECKING:
from catalystwan.session import ManagerSession

FeatureProfileBuilder = Union[ServiceFeatureProfileBuilder, SystemFeatureProfileBuilder, OtherFeatureProfileBuilder]

BUILDER_MAPPING: Mapping[ProfileType, Callable] = {
"service": ServiceFeatureProfileBuilder,
"system": SystemFeatureProfileBuilder,
"other": OtherFeatureProfileBuilder,
}


class FeatureProfileBuilderFactory:
def __init__(self, session: ManagerSession):
self.session = session

def create_builder(self, profile_type: ProfileType) -> FeatureProfileBuilder:
"""
Creates a builder for the specified feature profile.

Args:
feature_profile_name (str): The name of the feature profile.

Returns:
FeatureProfileBuilder: The builder for the specified feature profile.

Raises:
CatalystwanException: If the feature profile is not found or has an unsupported type.
"""
if profile_type not in BUILDER_MAPPING:
raise CatalystwanException(f"Unsupported builder for type {profile_type}")
return BUILDER_MAPPING[profile_type](self.session)
69 changes: 69 additions & 0 deletions catalystwan/api/builders/feature_profiles/other.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from __future__ import annotations

from typing import TYPE_CHECKING, List
from uuid import UUID

from catalystwan.api.feature_profile_api import OtherFeatureProfileAPI
from catalystwan.endpoints.configuration.feature_profile.sdwan.other import OtherFeatureProfile
from catalystwan.models.configuration.feature_profile.common import FeatureProfileCreationPayload
from catalystwan.models.configuration.feature_profile.sdwan.other import AnyOtherParcel

if TYPE_CHECKING:
from catalystwan.session import ManagerSession


class OtherFeatureProfileBuilder:
"""
A class for building Other feature profiles.
"""

def __init__(self, session: ManagerSession) -> None:
"""
Initialize a new instance of the Service class.

Args:
session (ManagerSession): The ManagerSession object used for API communication.
profile_uuid (UUID): The UUID of the profile.
"""
self._profile: FeatureProfileCreationPayload
self._api = OtherFeatureProfileAPI(session)
self._endpoints = OtherFeatureProfile(session)
self._independent_items: List[AnyOtherParcel] = []

def add_profile_name_and_description(self, feature_profile: FeatureProfileCreationPayload) -> None:
"""
Adds a name and description to the feature profile.

Args:
name (str): The name of the feature profile.
description (str): The description of the feature profile.

Returns:
None
"""
self._profile = feature_profile

def add_parcel(self, parcel: AnyOtherParcel) -> None:
"""
Adds a parcel to the feature profile.

Args:
parcel (AnySystemParcel): The parcel to add.

Returns:
None
"""
self._independent_items.append(parcel)

def build(self) -> UUID:
"""
Builds the feature profile.

Returns:
UUID: The UUID of the created feature profile.
"""

profile_uuid = self._endpoints.create_sdwan_other_feature_profile(self._profile).id
for parcel in self._independent_items:
self._api.create_parcel(profile_uuid, parcel)
return profile_uuid
130 changes: 130 additions & 0 deletions catalystwan/api/builders/feature_profiles/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
from __future__ import annotations

import logging
from collections import defaultdict
from typing import TYPE_CHECKING, Dict, List, Union
from uuid import UUID, uuid4

from pydantic import Field
from typing_extensions import Annotated

from catalystwan.api.feature_profile_api import ServiceFeatureProfileAPI
from catalystwan.endpoints.configuration.feature_profile.sdwan.service import ServiceFeatureProfile
from catalystwan.models.configuration.feature_profile.common import FeatureProfileCreationPayload
from catalystwan.models.configuration.feature_profile.sdwan.service import (
AppqoeParcel,
InterfaceEthernetParcel,
InterfaceGreParcel,
InterfaceIpsecParcel,
InterfaceSviParcel,
LanVpnDhcpServerParcel,
LanVpnParcel,
)

if TYPE_CHECKING:
from catalystwan.session import ManagerSession

logger = logging.getLogger(__name__)

IndependedParcels = Annotated[Union[AppqoeParcel, LanVpnDhcpServerParcel], Field(discriminator="type_")]
DependedInterfaceParcels = Annotated[
Union[InterfaceGreParcel, InterfaceSviParcel, InterfaceEthernetParcel, InterfaceIpsecParcel],
Field(discriminator="type_"),
]


class ServiceFeatureProfileBuilder:
"""
A class for building service feature profiles.
"""

def __init__(self, session: ManagerSession):
"""
Initialize a new instance of the Service class.

Args:
session (ManagerSession): The ManagerSession object used for API communication.
profile_uuid (UUID): The UUID of the profile.
"""
self._profile: FeatureProfileCreationPayload
self._api = ServiceFeatureProfileAPI(session)
self._endpoints = ServiceFeatureProfile(session)
self._independent_items: List[IndependedParcels] = []
self._independent_items_vpns: Dict[UUID, LanVpnParcel] = {}
self._depended_items_on_vpns: Dict[UUID, List[DependedInterfaceParcels]] = defaultdict(list)

def add_profile_name_and_description(self, feature_profile: FeatureProfileCreationPayload) -> None:
"""
Adds a name and description to the feature profile.

Args:
name (str): The name of the feature profile.
description (str): The description of the feature profile.

Returns:
None
"""
self._profile = feature_profile

def add_parcel(self, parcel: IndependedParcels) -> None:
"""
Adds an independent parcel to the builder.

Args:
parcel (IndependedParcels): The independent parcel to add.

Returns:
None
"""
self._independent_items.append(parcel)

def add_parcel_vpn(self, parcel: LanVpnParcel) -> UUID:
"""
Adds a VPN parcel to the builder.

Args:
parcel (LanVpnParcel): The VPN parcel to add.

Returns:
UUID: The UUID tag of the added VPN parcel.
"""
vpn_tag = uuid4()
logger.debug(f"Adding VPN parcel {parcel.parcel_name} with tag {vpn_tag}")
self._independent_items_vpns[vpn_tag] = parcel
return vpn_tag

def add_parcel_vpn_interface(self, vpn_tag: UUID, parcel: DependedInterfaceParcels) -> None:
"""
Adds an interface parcel dependent on a VPN to the builder.

Args:
vpn_tag (UUID): The UUID of the VPN.
parcel (DependedInterfaceParcels): The interface parcel to add.

Returns:
None
"""
logger.debug(f"Adding interface parcel {parcel.parcel_name} to VPN {vpn_tag}")
self._depended_items_on_vpns[vpn_tag].append(parcel)

def build(self) -> UUID:
"""
Builds the feature profile by creating parcels for independent items,
VPNs, and interface parcels dependent on VPNs.

Returns:
Service feature profile UUID
"""
profile_uuid = self._endpoints.create_sdwan_service_feature_profile(self._profile).id

for parcel in self._independent_items:
self._api.create_parcel(profile_uuid, parcel)

for vpn_tag, vpn_parcel in self._independent_items_vpns.items():
vpn_uuid = self._api.create_parcel(profile_uuid, vpn_parcel).id

for interface_parcel in self._depended_items_on_vpns[vpn_tag]:
logger.debug(f"Creating interface parcel {interface_parcel.parcel_name} to VPN {vpn_tag}")
self._api.create_parcel(profile_uuid, interface_parcel, vpn_uuid)

return profile_uuid
Loading
Loading