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

Template generator update #371

Merged
merged 7 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
29 changes: 6 additions & 23 deletions vmngclient/api/template_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,32 +559,15 @@ def generate_feature_template_payload(
if field.key in template.device_specific_variables:
value = template.device_specific_variables[field.key]
else:
# Iterate through every possible field, maybe refactor(?)
# Use data_path instead. data_path as tuple
# next(field_value.field_info.extra.get("vmanage_key") == field.key, template.__fields__.values())
for field_name, field_value in template.__fields__.items():
if "vmanage_key" in field_value.field_info.extra: # type: ignore
vmanage_key = field_value.field_info.extra.get("vmanage_key") # type: ignore
if vmanage_key != field.key:
break

value = template.dict(by_alias=True).get(field_name, None)
field_value.field_info.extra.pop("vmanage_key") # type: ignore
if (
field.dataPath == field_value.field_info.extra.get("data_path", []) # type: ignore
and field.key == field_value.alias
):
value = getattr(template, field_name)
break
if value is None:
value = template.dict(by_alias=True).get(field.key, None)

# TODO remove workaround, add specific object
# types like Ignore, Constant, None etc so generator will now
# which object to ommit while generating payload
if template.type == "cisco_vpn_interface" and value is None:
continue

if template.type == "cisco_ospf" and value is None:
continue

if isinstance(value, bool):
value = str(value).lower() # type: ignore
continue

# Merge dictionaries

Expand Down
37 changes: 24 additions & 13 deletions vmngclient/api/templates/feature_template_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, Field, validator
from pydantic.fields import ModelField # type: ignore

from vmngclient.api.templates.device_variable import DeviceVariable
from vmngclient.api.templates.feature_template import FeatureTemplate


class FeatureTemplateOptionType(str, Enum):
Expand Down Expand Up @@ -91,15 +93,22 @@ def payload_scheme(self, value: Any = None, help=None, current_path=None) -> dic

output["vipObjectType"] = self.objectType.value

def nest_value_in_output(value: Any) -> dict:
pointer = rel_output
for path in self.dataPath:
pointer = pointer[path]
pointer[self.key] = value
return rel_output

if isinstance(value, DeviceVariable):
vip_variable = VipVariable(
vipValue="",
vipType=FeatureTemplateOptionType.VARIABLE_NAME,
vipObjectType=self.objectType,
vipVariableName=value.name,
)
return nest_value_in_output(vip_variable.dict(by_alias=True, exclude_none=True))

return {self.key: vip_variable.dict(by_alias=True, exclude_none=True)}
else:
if value:
output["vipType"] = FeatureTemplateOptionType.CONSTANT.value
Expand All @@ -111,19 +120,27 @@ def payload_scheme(self, value: Any = None, help=None, current_path=None) -> dic
for child in self.children: # Child in schema
if current_path is None:
current_path = []
child_payload.update(
child.payload_scheme(
obj[child.key], help=output, current_path=self.dataPath + [self.key]
obj: FeatureTemplate # type: ignore
model_field: ModelField = next(
filter(
lambda f: f.field_info.extra.get("data_path", []) == child.dataPath
and f.alias == child.key,
obj.__fields__.values(),
)
)
obj_value = getattr(obj, model_field.name)
child_payload.update(
child.payload_scheme(obj_value, help=output, current_path=self.dataPath + [self.key])
)
children_output.append(child_payload)
output["vipValue"] = children_output
else:
output["vipValue"] = value
else:
if "default" in self.dataType:
output["vipValue"] = self.dataType["default"] if value is None else value
output["vipType"] = self.defaultOption.value
return {}
# output["vipValue"] = self.dataType["default"] if value is None else value
# output["vipType"] = self.defaultOption.value
else:
output["vipValue"] = []
output["vipType"] = FeatureTemplateOptionType.IGNORE.value
Expand All @@ -135,10 +152,4 @@ def payload_scheme(self, value: Any = None, help=None, current_path=None) -> dic
if self.primaryKeys:
output["vipPrimaryKey"] = self.primaryKeys

pointer = rel_output

for path in self.dataPath:
pointer = pointer[path]

pointer[self.key] = output
return rel_output
return nest_value_in_output(output)
4 changes: 2 additions & 2 deletions vmngclient/api/templates/models/cisco_banner_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class Config:
arbitrary_types_allowed = True
allow_population_by_field_name = True

login_banner: Optional[str] = Field(vmanage_key="login")
motd_banner: Optional[str] = Field(vmanage_key="motd")
login_banner: Optional[str] = Field(alias="login")
motd_banner: Optional[str] = Field(alias="motd")

payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED"
type: ClassVar[str] = "cisco_banner"
4 changes: 2 additions & 2 deletions vmngclient/api/templates/models/cisco_bfd_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ class Config:
arbitrary_types_allowed = True
allow_population_by_field_name = True

multiplier: Optional[int] = DEFAULT_BFD_MULTIPLIER
poll_interval: Optional[int] = Field(DEFAULT_BFD_POLL_INTERVAL, alias="poll-interval")
multiplier: Optional[int] = Field(DEFAULT_BFD_MULTIPLIER, data_path=["app-route"])
poll_interval: Optional[int] = Field(DEFAULT_BFD_POLL_INTERVAL, alias="poll-interval", data_path=["app-route"])
default_dscp: Optional[int] = Field(DEFAULT_BFD_DSCP, alias="default-dscp")
color: Optional[List[Color]]

Expand Down
84 changes: 42 additions & 42 deletions vmngclient/api/templates/models/cisco_bgp_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ class AddressFamily(BaseModel):
ipv6_aggregate_address: Optional[List[Ipv6AggregateAddress]] = Field(alias="ipv6-aggregate-address")
network: Optional[List[Network]]
ipv6_network: Optional[List[Ipv6Network]] = Field(alias="ipv6-network")
paths: Optional[int]
originate: Optional[bool]
name: Optional[str]
filter: Optional[bool]
paths: Optional[int] = Field(data_path=["maximum-paths"])
originate: Optional[bool] = Field(data_path=["default-information"])
policy_name: Optional[str] = Field(data_path=["table-map"], alias="name")
filter: Optional[bool] = Field(data_path=["table-map"])
redistribute: Optional[List[Redistribute]]

class Config:
Expand Down Expand Up @@ -141,10 +141,10 @@ class Config:

class NeighborAddressFamily(BaseModel):
family_type: NeighborFamilyType = Field(alias="family-type")
prefix_num: Optional[int] = Field(alias="prefix-num")
threshold: Optional[int]
restart: Optional[int]
warning_only: Optional[bool] = Field(alias="warning-only")
prefix_num: Optional[int] = Field(data_path=["maximum-prefixes"], alias="prefix-num")
threshold: Optional[int] = Field(data_path=["maximum-prefixes"])
restart: Optional[int] = Field(data_path=["maximum-prefixes"])
warning_only: Optional[bool] = Field(data_path=["maximum-prefixes"], alias="warning-only")
route_policy: Optional[List[RoutePolicy]] = Field(alias="route-policy")

class Config:
Expand All @@ -156,9 +156,9 @@ class Neighbor(BaseModel):
description: Optional[str]
shutdown: Optional[bool]
remote_as: int = Field(alias="remote-as")
keepalive: Optional[int]
holdtime: Optional[int]
if_name: Optional[str] = Field(alias="if-name")
keepalive: Optional[int] = Field(data_path=["timers"])
holdtime: Optional[int] = Field(data_path=["timers"])
if_name: Optional[str] = Field(data_path=["update-source"], alias="if-name")
next_hop_self: Optional[bool] = Field(alias="next-hop-self")
send_community: Optional[bool] = Field(alias="send-community")
send_ext_community: Optional[bool] = Field(alias="send-ext-community")
Expand All @@ -167,7 +167,7 @@ class Neighbor(BaseModel):
send_label: Optional[bool] = Field(alias="send-label")
send_label_explicit: Optional[bool] = Field(alias="send-label-explicit")
as_override: Optional[bool] = Field(alias="as-override")
as_number: Optional[int] = Field(alias="as-number")
as_number: Optional[int] = Field(data_path=["allowas-in"], alias="as-number")
address_family: Optional[List[NeighborAddressFamily]] = Field(alias="address-family")

class Config:
Expand All @@ -193,10 +193,10 @@ class IPv6NeighborFamilyType(str, Enum):

class IPv6NeighborAddressFamily(BaseModel):
family_type: IPv6NeighborFamilyType = Field(alias="family-type")
prefix_num: Optional[int] = Field(0, alias="prefix-num")
threshold: Optional[int]
restart: Optional[int]
warning_only: Optional[bool] = Field(False, alias="warning-only")
prefix_num: Optional[int] = Field(0, data_path=["maximum-prefixes"], alias="prefix-num")
threshold: Optional[int] = Field(data_path=["maximum-prefixes"])
restart: Optional[int] = Field(data_path=["maximum-prefixes"])
warning_only: Optional[bool] = Field(False, data_path=["maximum-prefixes"], alias="warning-only")
route_policy: Optional[List[RoutePolicy]] = Field(alias="route-policy")

class Config:
Expand All @@ -208,9 +208,9 @@ class Ipv6Neighbor(BaseModel):
description: Optional[str]
shutdown: Optional[bool]
remote_as: int = Field(alias="remote-as")
keepalive: Optional[int]
holdtime: Optional[int]
if_name: Optional[str] = Field(alias="if-name")
keepalive: Optional[int] = Field(data_path=["timers"])
holdtime: Optional[int] = Field(data_path=["timers"])
if_name: Optional[str] = Field(data_path=["update-source"], alias="if-name")
next_hop_self: Optional[bool] = Field(False, alias="next-hop-self")
send_community: Optional[bool] = Field(True, alias="send-community")
send_ext_community: Optional[bool] = Field(True, alias="send-ext-community")
Expand All @@ -219,7 +219,7 @@ class Ipv6Neighbor(BaseModel):
send_label: Optional[bool] = Field(False, alias="send-label")
send_label_explicit: Optional[bool] = Field(False, alias="send-label-explicit")
as_override: Optional[bool] = Field(False, alias="as-override")
as_number: Optional[int] = Field(alias="as-number")
as_number: Optional[int] = Field(data_path=["allowas-in"], alias="as-number")
address_family: Optional[List[IPv6NeighborAddressFamily]] = Field(alias="address-family")

class Config:
Expand All @@ -244,32 +244,32 @@ class Config:
arbitrary_types_allowed = True
allow_population_by_field_name = True

as_num: Optional[str] = Field(alias="as-num")
shutdown: Optional[bool]
router_id: Optional[str] = Field(alias="router-id")
propagate_aspath: Optional[bool] = Field(alias="propagate-aspath")
propagate_community: Optional[bool] = Field(alias="propagate-community")
route_target_ipv4: List[RouteTargetIpv4] = Field([], alias="route-target-ipv4")
route_target_ipv6: List[RouteTargetIpv6] = Field([], alias="route-target-ipv6")
mpls_interface: Optional[List[MplsInterface]] = Field(alias="mpls-interface")
external: Optional[int]
internal: Optional[int]
local: Optional[int]
keepalive: Optional[int]
holdtime: Optional[int]
always_compare: Optional[bool] = Field(alias="always-compare")
deterministic: Optional[bool]
missing_as_worst: Optional[bool] = Field(alias="missing-as-worst")
compare_router_id: Optional[bool] = Field(alias="compare-router-id")
multipath_relax: Optional[bool] = Field(alias="multipath-relax")
address_family: Optional[List[AddressFamily]] = Field(alias="address-family")
neighbor: Optional[List[Neighbor]]
ipv6_neighbor: Optional[List[Ipv6Neighbor]] = Field(alias="ipv6-neighbor")
as_num: Optional[str] = Field(data_path=["bgp"], alias="as-num")
shutdown: Optional[bool] = Field(data_path=["bgp"])
router_id: Optional[str] = Field(data_path=["bgp"], alias="router-id")
propagate_aspath: Optional[bool] = Field(data_path=["bgp"], alias="propagate-aspath")
propagate_community: Optional[bool] = Field(data_path=["bgp"], alias="propagate-community")
route_target_ipv4: List[RouteTargetIpv4] = Field([], data_path=["bgp", "target"], alias="route-target-ipv4")
route_target_ipv6: List[RouteTargetIpv6] = Field([], data_path=["bgp", "target"], alias="route-target-ipv6")
mpls_interface: Optional[List[MplsInterface]] = Field(data_path=["bgp"], alias="mpls-interface")
external: Optional[int] = Field(data_path=["bgp", "distance"])
internal: Optional[int] = Field(data_path=["bgp", "distance"])
local: Optional[int] = Field(data_path=["bgp", "distance"])
keepalive: Optional[int] = Field(data_path=["bgp", "timers"])
holdtime: Optional[int] = Field(data_path=["bgp", "timers"])
always_compare: Optional[bool] = Field(data_path=["bgp", "best-path", "med"], alias="always-compare")
deterministic: Optional[bool] = Field(data_path=["bgp", "best-path", "med"])
missing_as_worst: Optional[bool] = Field(data_path=["bgp", "best-path", "med"], alias="missing-as-worst")
compare_router_id: Optional[bool] = Field(data_path=["bgp", "best-path"], alias="compare-router-id")
multipath_relax: Optional[bool] = Field(data_path=["bgp", "best-path", "as-path"], alias="multipath-relax")
address_family: Optional[List[AddressFamily]] = Field(data_path=["bgp"], alias="address-family")
neighbor: Optional[List[Neighbor]] = Field(data_path=["bgp"])
ipv6_neighbor: Optional[List[Ipv6Neighbor]] = Field(data_path=["bgp"], alias="ipv6-neighbor")

payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED"
type: ClassVar[str] = "cisco_bgp"

@validator("shutdown")
@validator("shutdown", "deterministic", "missing_as_worst", "compare_router_id", "multipath_relax")
def cast_to_str(cls, value):
if value is not None:
return str(value).lower()
22 changes: 11 additions & 11 deletions vmngclient/api/templates/models/cisco_logging_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ class AuthType(str, Enum):

class TlsProfile(ConvertBoolToStringModel):
profile: str
version: Optional[Version] = Version.TLSV11
version: Optional[Version] = Field(Version.TLSV11, data_path=["tls-version"])
auth_type: AuthType = Field(alias="auth-type")
ciphersuite_list: Optional[List] = Field(alias="ciphersuite-list")
ciphersuite_list: Optional[List] = Field(data_path=["ciphersuite"], alias="ciphersuite-list")

class Config:
allow_population_by_field_name = True
Expand All @@ -47,9 +47,9 @@ class Server(ConvertBoolToStringModel):
vpn: Optional[int]
source_interface: Optional[str] = Field(alias="source-interface")
priority: Optional[Priority] = Priority.INFORMATION
enable_tls: Optional[bool] = Field(False, alias="enable-tls")
custom_profile: Optional[bool] = Field(False, alias="custom-profile")
profile: Optional[str]
enable_tls: Optional[bool] = Field(False, data_path=["tls"], alias="enable-tls")
custom_profile: Optional[bool] = Field(False, data_path=["tls", "tls-properties"], alias="custom-profile")
profile: Optional[str] = Field(data_path=["tls", "tls-properties"])

class Config:
allow_population_by_field_name = True
Expand All @@ -60,9 +60,9 @@ class Ipv6Server(ConvertBoolToStringModel):
vpn: Optional[int]
source_interface: Optional[str] = Field(alias="source-interface")
priority: Optional[Priority] = Priority.INFORMATION
enable_tls: Optional[bool] = Field(False, alias="enable-tls")
custom_profile: Optional[bool] = Field(False, alias="custom-profile")
profile: Optional[str]
enable_tls: Optional[bool] = Field(False, data_path=["tls"], alias="enable-tls")
custom_profile: Optional[bool] = Field(False, data_path=["tls", "tls-properties"], alias="custom-profile")
profile: Optional[str] = Field(data_path=["tls", "tls-properties"])

class Config:
allow_population_by_field_name = True
Expand All @@ -73,9 +73,9 @@ class Config:
arbitrary_types_allowed = True
allow_population_by_field_name = True

enable: Optional[bool] = True
size: Optional[int] = DEFAULT_LOGGING_SIZE
rotate: Optional[int] = DEFAULT_LOGGING_ROTATE
enable: Optional[bool] = Field(True, data_path=["disk"])
size: Optional[int] = Field(DEFAULT_LOGGING_SIZE, data_path=["disk", "file"])
rotate: Optional[int] = Field(DEFAULT_LOGGING_ROTATE, data_path=["disk", "file"])
tls_profile: List[TlsProfile] = Field(alias="tls-profile")
server: Optional[List[Server]]
ipv6_server: Optional[List[Ipv6Server]] = Field(alias="ipv6-server")
Expand Down
15 changes: 8 additions & 7 deletions vmngclient/api/templates/models/cisco_ntp_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
from pydantic import BaseModel, Field

from vmngclient.api.templates.feature_template import FeatureTemplate
from vmngclient.utils.pydantic_validators import ConvertBoolToStringModel


class Server(BaseModel):
class Server(ConvertBoolToStringModel):
class Config:
allow_population_by_field_name = True

Expand All @@ -26,17 +27,17 @@ class Config:
md5: str


class CiscoNTPModel(FeatureTemplate):
class CiscoNTPModel(FeatureTemplate, ConvertBoolToStringModel):
class Config:
arbitrary_types_allowed = True
allow_population_by_field_name = True

server: List[Server] = Field(default=[])
authentication: List[Authentication] = Field(default=[])
trusted: List[int] = Field(default=[])
enable: Optional[bool] = Field(default=False)
stratum: Optional[int] = Field(default=None)
source: Optional[str] = Field(default=None)
authentication: List[Authentication] = Field(default=[], data_path=["keys"])
trusted: List[int] = Field(default=[], data_path=["keys"])
enable: Optional[bool] = Field(default=False, data_path=["master"])
stratum: Optional[int] = Field(default=None, data_path=["master"])
source: Optional[str] = Field(default=None, data_path=["master"])

payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED"
type: ClassVar[str] = "cisco_ntp"
12 changes: 8 additions & 4 deletions vmngclient/api/templates/models/cisco_omp_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,14 @@ class Config:
shutdown: Optional[bool]
omp_admin_distance_ipv4: Optional[int] = Field(alias="omp-admin-distance-ipv4")
omp_admin_distance_ipv6: Optional[int] = Field(alias="omp-admin-distance-ipv6")
advertisement_interval: Optional[int] = Field(DEFAULT_OMP_ADVERTISEMENT_INTERVAL, alias="advertisement-interval")
graceful_restart_timer: Optional[int] = Field(DEFAULT_OMP_GRACEFUL_RESTART_TIMER, alias="graceful-restart-timer")
eor_timer: Optional[int] = Field(DEFAULT_OMP_EOR_TIMER, alias="eor-timer")
holdtime: Optional[int] = DEFAULT_OMP_HOLDTIME
advertisement_interval: Optional[int] = Field(
DEFAULT_OMP_ADVERTISEMENT_INTERVAL, alias="advertisement-interval", data_path=["timers"]
)
graceful_restart_timer: Optional[int] = Field(
DEFAULT_OMP_GRACEFUL_RESTART_TIMER, alias="graceful-restart-timer", data_path=["timers"]
)
eor_timer: Optional[int] = Field(DEFAULT_OMP_EOR_TIMER, alias="eor-timer", data_path=["timers"])
holdtime: Optional[int] = Field(DEFAULT_OMP_HOLDTIME, data_path=["timers"])
advertise: Optional[List[IPv4Advertise]]
ipv6_advertise: Optional[List[IPv6Advertise]] = Field(alias="ipv6-advertise")
ignore_region_path_length: Optional[bool] = Field(False, alias="ignore-region-path-length")
Expand Down
Loading