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

Commit

Permalink
Start work on Service models
Browse files Browse the repository at this point in the history
  • Loading branch information
jpkrajewski committed Mar 19, 2024
1 parent efca30a commit 4a0b4f0
Show file tree
Hide file tree
Showing 15 changed files with 289 additions and 153 deletions.
4 changes: 4 additions & 0 deletions catalystwan/api/configuration_groups/parcel.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ class Global(ParcelAttribute, Generic[T]):
)
value: T

def __bool__(self) -> bool:
# if statements use __len__ when __bool__ is not defined
return True

def __len__(self) -> int:
if isinstance(self.value, (str, list)):
return len(self.value)
Expand Down
13 changes: 11 additions & 2 deletions catalystwan/api/feature_profile_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Optional, Protocol, Type, Union, overload
from typing import TYPE_CHECKING, Any, Optional, Protocol, Type, Union, get_args, overload
from uuid import UUID

from pydantic import Json
Expand All @@ -12,6 +12,7 @@
from catalystwan.endpoints.configuration.feature_profile.sdwan.system import SystemFeatureProfile
from catalystwan.models.configuration.feature_profile.sdwan.other import AnyOtherParcel
from catalystwan.models.configuration.feature_profile.sdwan.policy_object.security.url import URLParcel
from catalystwan.models.configuration.feature_profile.sdwan.service import AnyServiceParcel, AnyTopLevelServiceParcel
from catalystwan.typed_list import DataSequence

if TYPE_CHECKING:
Expand Down Expand Up @@ -231,6 +232,14 @@ def delete_profile(self, profile_id: UUID) -> None:
"""
self.endpoint.delete_sdwan_service_feature_profile(profile_id)

def create_parcel(self, profile_id: UUID, payload: AnyServiceParcel) -> ParcelCreationResponse:
"""
Create Service Parcel for selected profile_id based on payload type
"""
if type(payload) in get_args(AnyTopLevelServiceParcel)[0].__args__:
return self.endpoint.create_top_level_service_parcel(profile_id, payload._get_parcel_type(), payload)
return self.endpoint.create_lan_vpn_service_parcel(profile_id, payload)


class SystemFeatureProfileAPI:
"""
Expand Down Expand Up @@ -485,7 +494,7 @@ def create_parcel(self, profile_id: UUID, payload: AnySystemParcel) -> ParcelCre

return self.endpoint.create(profile_id, payload._get_parcel_type(), payload)

def update(self, profile_id: UUID, payload: AnySystemParcel, parcel_id: UUID) -> ParcelCreationResponse:
def update_parcel(self, profile_id: UUID, payload: AnySystemParcel, parcel_id: UUID) -> ParcelCreationResponse:
"""
Update System Parcel for selected profile_id based on payload type
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
FeatureProfileCreationResponse,
FeatureProfileInfo,
GetFeatureProfilesPayload,
ParcelCreationResponse,
)
from catalystwan.models.configuration.feature_profile.sdwan.service import (
AnyLanVpnInterfaceParcel,
AnyTopLevelServiceParcel,
)
from catalystwan.models.configuration.feature_profile.sdwan.service.lan.vpn import LanVpnParcel
from catalystwan.typed_list import DataSequence


Expand All @@ -30,6 +36,25 @@ def create_sdwan_service_feature_profile(
...

@versions(supported_versions=(">=20.9"), raises=False)
@delete("/v1/feature-profile/sdwan/service/{profile_id}")
def delete_sdwan_service_feature_profile(self, profile_id: UUID) -> None:
@delete("/v1/feature-profile/sdwan/service/{profile_uuid}")
def delete_sdwan_service_feature_profile(self, profile_uuid: UUID) -> None:
...

@versions(supported_versions=(">=20.9"), raises=False)
@post("/v1/feature-profile/sdwan/service/{profile_uuid}/{parcel_type}")
def create_top_level_service_parcel(
self, profile_uuid: UUID, parcel_type: str, payload: AnyTopLevelServiceParcel
) -> ParcelCreationResponse:
...

@versions(supported_versions=(">=20.9"), raises=False)
@post("/v1/feature-profile/sdwan/service/{profile_uuid}/lan/vpn/")
def create_lan_vpn_service_parcel(self, profile_uuid: UUID, payload: LanVpnParcel) -> ParcelCreationResponse:
...

@versions(supported_versions=(">=20.9"), raises=False)
@post("/v1/feature-profile/sdwan/service/{profile_uuid}/lan/vpn/{vpn_uuid}/interface/{parcel_type}")
def create_lan_vpn_interface_parcel(
self, profile_uuid: UUID, vpn_uuid: UUID, parcel_type: str, payload: AnyLanVpnInterfaceParcel
) -> ParcelCreationResponse:
...
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
LanVpnDhcpServerParcel,
SubnetMask,
)
from catalystwan.models.configuration.feature_profile.sdwan.service.lan.vpn import LanVpnParcel
from catalystwan.session import create_manager_session


Expand All @@ -26,7 +27,6 @@ def setUp(self) -> None:

def test_when_default_values_dhcp_server_parcel_expect_successful_post(self):
# Arrange
url = f"dataservice/v1/feature-profile/sdwan/service/{self.profile_id}/dhcp-server"
dhcp_server_parcel = LanVpnDhcpServerParcel(
parcel_name="DhcpServerDefault",
parcel_description="Dhcp Server Parcel",
Expand All @@ -36,11 +36,23 @@ def test_when_default_values_dhcp_server_parcel_expect_successful_post(self):
),
)
# Act
response = self.session.post(
url=url, data=dhcp_server_parcel.model_dump_json(by_alias=True, exclude_none=True)
) # This will be changed to the actual method
parcel_id = self.session.api.sdwan_feature_profiles.service.create_parcel(
self.profile_id, dhcp_server_parcel
).id
# Assert
assert parcel_id

def test_when_default_values_service_vpn_parcel_expect_successful_post(self):
# Arrange
vpn_parcel = LanVpnParcel(
parcel_name="TestVpnParcel",
parcel_description="Test Vpn Parcel",
vpn_id=Global[int](value=2),
)
# Act
parcel_id = self.session.api.sdwan_feature_profiles.service.create_parcel(self.profile_id, vpn_parcel).id
# Assert
assert response.status_code == 200
assert parcel_id

def tearDown(self) -> None:
self.session.api.sdwan_feature_profiles.service.delete_profile(self.profile_id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,47 @@
from pydantic import Field
from typing_extensions import Annotated

from .appqoe import AppqoeParcel
from .dhcp_server import LanVpnDhcpServerParcel
from .lan.ethernet import InterfaceEthernetData
from .lan.gre import InterfaceGreData
from .lan.ipsec import InterfaceIpsecData
from .lan.svi import InterfaceSviData
from .lan.vpn import LanVpnParcel

AnyTopLevelServiceParcel = Annotated[
Union[
LanVpnDhcpServerParcel,
AppqoeParcel,
# TrackerGroupData,
# WirelessLanData,
# SwitchportData
],
Field(discriminator="type_"),
]

AnyLanVpnInterfaceParcel = Annotated[
Union[
InterfaceEthernetData,
InterfaceGreData,
InterfaceIpsecData,
InterfaceSviData,
],
Field(discriminator="type_"),
]

AnyServiceParcel = Annotated[
Union[LanVpnDhcpServerParcel,], # noqa: E231
Union[AnyTopLevelServiceParcel, LanVpnParcel, AnyLanVpnInterfaceParcel],
Field(discriminator="type_"),
]

__all__ = [
"LanVpnDhcpServerParcel",
"AppqoeParcel",
"LanVpnParcel",
"AnyServiceParcel",
"AnyTopLevelServiceParcel",
"AnyLanVpnInterfaceParcel",
]


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class Appqoe(BaseModel):

class ServiceContext(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
appqoe: List[Appqoe]
appqoe: List[Appqoe] = Field(default_factory=lambda: [Appqoe()])


# Frowarder
Expand Down Expand Up @@ -161,7 +161,9 @@ class ForwarderRole(BaseModel):
service_node_group: List[ForwarderNodeGroup] = Field(
serialization_alias="serviceNodeGroup", validation_alias="serviceNodeGroup"
)
service_context: ServiceContext = Field(serialization_alias="serviceContext", validation_alias="serviceContext")
service_context: ServiceContext = Field(
default_factory=ServiceContext, serialization_alias="serviceContext", validation_alias="serviceContext"
)


# Forwarder and Service
Expand Down Expand Up @@ -248,6 +250,7 @@ class ServiceNodeRole(BaseModel):


class AppqoeParcel(_ParcelBase):
type_: Literal["appqoe"] = Field(default="appqoe", exclude=True)
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)

dreopt: Optional[Union[Global[bool], Default[bool]]] = Field(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from pydantic import BaseModel, ConfigDict, Field

from catalystwan.api.configuration_groups.parcel import Default, Global, Variable
from catalystwan.api.configuration_groups.parcel import Default, Global, Variable, _ParcelBase
from catalystwan.models.configuration.feature_profile.sdwan.service.lan.common import (
Arp,
StaticIPv4Address,
Expand Down Expand Up @@ -281,7 +281,8 @@ class AdvancedAttributes(BaseModel):
)


class InterfaceEthernetData(BaseModel):
class InterfaceEthernetData(_ParcelBase):
type_: Literal["ethernet"] = Field(default="ethernet", exclude=True)
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)

shutdown: Union[Global[bool], Variable, Default[bool]] = Default[bool](value=True)
Expand Down Expand Up @@ -316,12 +317,3 @@ class InterfaceEthernetData(BaseModel):
arp: Optional[List[Arp]] = None
trustsec: Optional[Trustsec] = None
advanced: AdvancedAttributes = AdvancedAttributes()


class InterfaceEthernetCreationPayload(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)

name: str
description: Optional[str] = None
data: InterfaceEthernetData
metadata: Optional[dict] = None
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from pydantic import BaseModel, ConfigDict, Field

from catalystwan.api.configuration_groups.parcel import Default, Global, Variable
from catalystwan.api.configuration_groups.parcel import Default, Global, Variable, _ParcelBase
from catalystwan.models.configuration.feature_profile.sdwan.service.lan.common import (
IkeCiphersuite,
IkeGroup,
Expand Down Expand Up @@ -190,17 +190,9 @@ class AdvancedGre(BaseModel):
application: Optional[Union[Global[TunnelApplication], Variable]] = None


class InterfaceGreData(BaseModel):
class InterfaceGreData(_ParcelBase):
type_: Literal["gre"] = Field(default="gre", exclude=True)
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)

basic: BasicGre
advanced: Optional[AdvancedGre] = None


class InterfaceGreCreationPayload(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)

name: str
description: Optional[str] = None
data: InterfaceGreData
metadata: Optional[dict] = None
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from pydantic import BaseModel, ConfigDict, Field

from catalystwan.api.configuration_groups.parcel import Default, Global, Variable
from catalystwan.api.configuration_groups.parcel import Default, Global, Variable, _ParcelBase
from catalystwan.models.configuration.feature_profile.sdwan.service.lan.common import (
IkeCiphersuite,
IkeGroup,
Expand All @@ -28,7 +28,8 @@ class IpsecAddress(BaseModel):
mask: Union[Variable, Global[str]]


class InterfaceIpsecData(BaseModel):
class InterfaceIpsecData(_ParcelBase):
type_: Literal["ipsec"] = Field(default="ipsec", exclude=True)
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)

interface_name: Union[Global[str], Variable] = Field(serialization_alias="ifName", validation_alias="ifName")
Expand Down Expand Up @@ -128,11 +129,3 @@ class InterfaceIpsecData(BaseModel):
tunnel_route_via: Optional[Union[Global[str], Variable, Default[None]]] = Field(
serialization_alias="tunnelRouteVia", validation_alias="tunnelRouteVia", default=None
)


class InterfaceIpsecCreationPayload(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)

name: str
description: Optional[str] = None
data: InterfaceIpsecData
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Copyright 2024 Cisco Systems, Inc. and its affiliates

from typing import List, Optional, Union
from typing import List, Literal, Optional, Union
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field

from catalystwan.api.configuration_groups.parcel import Default, Global, Variable
from catalystwan.api.configuration_groups.parcel import Default, Global, Variable, _ParcelBase
from catalystwan.models.configuration.feature_profile.sdwan.service.lan.common import (
Arp,
StaticIPv4Address,
Expand Down Expand Up @@ -140,7 +140,8 @@ class AclQos(BaseModel):
)


class InterfaceSviData(BaseModel):
class InterfaceSviData(_ParcelBase):
type_: Literal["svi"] = Field(default="svi", exclude=True)
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)

shutdown: Union[Global[bool], Variable, Default[bool]] = Default[bool](value=True)
Expand All @@ -166,12 +167,3 @@ class InterfaceSviData(BaseModel):
serialization_alias="dhcpClientV6", validation_alias="dhcpClientV6", default=Default[bool](value=False)
)
advanced: AdvancedSviAttributes = AdvancedSviAttributes()


class InterfaceSviCreationPayload(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)

name: str
description: Optional[str] = None
data: InterfaceSviData
metadata: Optional[dict] = None
Loading

0 comments on commit 4a0b4f0

Please sign in to comment.