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

Commit

Permalink
Fix Device Template (#382)
Browse files Browse the repository at this point in the history
* fix jinja file

* Fix payload schema for value==0

* fix cisco aaa model

* Fix Device Template attach

* fix serialize templates

* fix generate payload

* bump minor

* add default value

* remove duplicated logging errors
  • Loading branch information
kagrski authored Oct 16, 2023
1 parent b39c5bb commit d392c05
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 154 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "vmngclient"
version = "0.15.1"
version = "0.16.0"
description = "vManage SDK for Python"
authors = ["kagorski <[email protected]>"]
readme = "README.md"
Expand Down
15 changes: 4 additions & 11 deletions vmngclient/api/template_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from typing import TYPE_CHECKING, Any, Optional, Type, overload

from ciscoconfparse import CiscoConfParse # type: ignore
from requests.exceptions import HTTPError

from vmngclient.api.task_status_api import Task
from vmngclient.api.templates.cli_template import CLITemplate
Expand Down Expand Up @@ -211,10 +210,6 @@ def _attach_cli(self, name: str, device: Device, is_edited: bool = False) -> boo
except TemplateNotFoundError:
logger.error(f"Error, Template with name {name} not found on {device}.")
return False
except HTTPError as error:
error_details = json.loads(error.response.text)
logger.error(f"Error in config: {error_details['error']['details']}.")
return False
payload = {
"deviceTemplateList": [
{
Expand Down Expand Up @@ -564,7 +559,7 @@ def generate_feature_template_payload(
# "name"
for i, field in enumerate(fr_template_fields):
value = None

priority_order = None
# TODO How to discover Device specific variable
if field.key in template.device_specific_variables:
value = template.device_specific_variables[field.key]
Expand All @@ -574,6 +569,7 @@ def generate_feature_template_payload(
field.key == field_value.alias
or field.key == field_value.field_info.extra.get("vmanage_key") # type: ignore
):
priority_order = field_value.field_info.extra.get("priority_order") # type: ignore
value = getattr(template, field_name)
break
if value is None:
Expand All @@ -597,7 +593,8 @@ def merge(a, b, path=None):
a[key] = b[key]
return a

payload.definition = merge(payload.definition, field.payload_scheme(value))
# print(field.payload_scheme(value))
payload.definition = merge(payload.definition, field.payload_scheme(value, priority_order=priority_order))

if debug:
with open(f"payload_{template.type}.json", "w") as f:
Expand Down Expand Up @@ -674,10 +671,6 @@ def edit_before_push(self, name: str, device: Device) -> bool:
except TemplateNotFoundError:
logger.error(f"Error, Template with name {name} not found on {device}.")
return False
except HTTPError as error:
error_details = json.loads(error.response.text)
logger.error(f"Error in config: {error_details['error']['details']}.")
return False
payload = {
"templateId": template_id,
"deviceIds": [device.uuid],
Expand Down
9 changes: 6 additions & 3 deletions vmngclient/api/templates/cli_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,12 @@ def update(self, session: vManageSession, id: str, config: CiscoConfParse) -> bo
try:
session.put(url=endpoint, json=payload)
except HTTPError as error:
response = json.loads(error.response.text)["error"]
logger.error(f'Response message: {response["message"]}')
logger.error(f'Response details: {response["details"]}')
if error.response:
response = json.loads(error.response.text)["error"]
logger.error(f'Response message: {response["message"]}')
logger.error(f'Response details: {response["details"]}')
else:
logger.error("Response is None.")
return False
logger.info(f"Template with name: {self.template_name} - updated.")
return True
Expand Down
13 changes: 10 additions & 3 deletions vmngclient/api/templates/feature_template_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def data_path(self, output):
return output

# value must be JSON serializable, return JSON serializable dict
def payload_scheme(self, value: Any = None, help=None, current_path=None) -> dict:
def payload_scheme(self, value: Any = None, help=None, current_path=None, priority_order=None) -> dict:
output: dict = {}
rel_output: dict = {}
rel_output.update(get_path_dict([self.dataPath]))
Expand All @@ -110,7 +110,7 @@ def nest_value_in_output(value: Any) -> dict:
return nest_value_in_output(vip_variable.dict(by_alias=True, exclude_none=True))

else:
if value:
if value is not None:
output["vipType"] = FeatureTemplateOptionType.CONSTANT.value
if self.children:
children_output = []
Expand All @@ -129,14 +129,21 @@ def nest_value_in_output(value: Any) -> dict:
)
)
obj_value = getattr(obj, model_field.name)
po = model_field.field_info.extra.get("priority_order")
child_payload.update(
child.payload_scheme(obj_value, help=output, current_path=self.dataPath + [self.key])
child.payload_scheme(
obj_value, help=output, current_path=self.dataPath + [self.key], priority_order=po
)
)
if priority_order:
child_payload.update({"priority-order": priority_order})
children_output.append(child_payload)
output["vipValue"] = children_output
else:
output["vipValue"] = value
else:
if value is None:
return {}
if "default" in self.dataType:
return {}
# output["vipValue"] = self.dataType["default"] if value is None else value
Expand Down
6 changes: 3 additions & 3 deletions vmngclient/api/templates/models/cisco_aaa_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class User(BaseModel):
password: str
secret: str
privilege: Optional[str]
pubkey_chain: List[str] = Field(default=[], vmanage_key="pubkey-chain")
pubkey_chain: Optional[List[str]] = Field(default=None, vmanage_key="pubkey-chain")


class RadiusServer(BaseModel):
Expand Down Expand Up @@ -77,10 +77,10 @@ class Config:
user: List[User] = []
authentication_group: bool = Field(vmanage_key="authentication_group", default=False)
accounting_group: bool = True
radius: List[RadiusGroup] = []
radius: Optional[List[RadiusGroup]] = None
domain_stripping: Optional[DomainStripping] = Field(vmanage_key="domain-stripping", default=None)
port: int = 1700
tacacs: List[TacacsGroup] = []
tacacs: Optional[List[TacacsGroup]] = None
server_auth_order: str = Field(vmanage_key="server-auth-order", default="local")

payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED"
Expand Down
19 changes: 14 additions & 5 deletions vmngclient/api/templates/models/cisco_vpn_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ class NextHopWithTrack(BaseModel):

class Routev4(BaseModel):
prefix: str
next_hop: Optional[List[NextHop]] = Field(vmanage_key="next-hop")
next_hop_with_track: Optional[List[NextHopWithTrack]] = Field(vmanage_key="next-hop-with-track")
next_hop: Optional[List[NextHop]] = Field(vmanage_key="next-hop", priority_order=["address", "distance"])
next_hop_with_track: Optional[List[NextHopWithTrack]] = Field(default=None, vmanage_key="next-hop-with-track")
null0: Optional[bool]
distance: Optional[int] = 1
distance: Optional[int] = None
vpn: Optional[int]
dhcp: Optional[bool]

Expand Down Expand Up @@ -400,10 +400,12 @@ class Config:
dns: Optional[List[Dns]]
dns_ipv6: Optional[List[DnsIpv6]] = Field(vmanage_key="dns-ipv6")
layer4: Optional[bool] = Field(data_path=["ecmp-hash-key"])
host: Optional[List[Host]]
host: Optional[List[Host]] = Field(priority_order=["hostname", "ip"])
service: Optional[List[Service]]
service_route: Optional[List[ServiceRoute]] = Field(data_path=["ip"], vmanage_key="service-route")
route_v4: Optional[List[Routev4]] = Field(data_path=["ip"], vmanage_key="route")
route_v4: Optional[List[Routev4]] = Field(
data_path=["ip"], vmanage_key="route", priority_order=["next-hop", "next-hop-with-track", "prefix"]
)
route_v6: Optional[List[Routev6]] = Field(data_path=["ipv6"], vmanage_key="route")
gre_route: Optional[List[GreRoute]] = Field(data_path=["ip"], vmanage_key="gre-route")
ipsec_route: Optional[List[IpsecRoute]] = Field(data_path=["ip"], vmanage_key="ipsec-route")
Expand All @@ -420,3 +422,10 @@ class Config:

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

def generate_vpn_id(self, session):
if self.vpn_id not in [0, 512]:
payload = {"resourcePoolDataType": "vpn", "tenantId": self.org_name, "tenantVpn": self.vpn_id}
url = "/dataservice/resourcepool/resource/vpn"
response = session.put(url=url, json=payload).json()
self.vpn_id = response["deviceVpn"]
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@
],
"factoryDefault": false,
"templateMinVersion": "15.0.0",
"templateDefinition": {}
"templateDefinition": {
"vpn-id": {
"vipObjectType": "object",
"vipType": "constant",
"vipValue": 0
}
}
}
39 changes: 19 additions & 20 deletions vmngclient/tests/templates/definitions/basic/children_nested.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
{
"user": {
"vipObjectType": "tree",
"vipPrimaryKey": [
"name"
],
"vipType": "constant",
"vipValue": [
{
"name": {
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "user1"
},
"list": {
"password": {
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "pass"
}
},
"name": {
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "user1"
},
"pubkey-chain": {
"vipObjectType": "tree",
"vipPrimaryKey": [
"key-string"
],
"vipType": "constant",
"vipValue": [
{
Expand All @@ -42,32 +36,37 @@
}
}
}
],
"vipPrimaryKey": [
"key-string"
]
}
},
{
"name": {
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "user2"
},
"list": {
"password": {
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "pass"
}
},
"name": {
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "user2"
},
"pubkey-chain": {
"vipObjectType": "tree",
"vipType": "constant",
"vipValue": [],
"vipPrimaryKey": [
"key-string"
],
"vipType": "ignore",
"vipValue": [
]
}
}
],
"vipPrimaryKey": [
"name"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
},
"pubkey-chain": {
"vipObjectType": "tree",
"vipType": "constant",
"vipValue": [],
"vipType": "ignore",
"vipPrimaryKey": [
"key-string"
]
Expand Down
36 changes: 5 additions & 31 deletions vmngclient/tests/templates/definitions/complex_aaa.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,6 @@
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "1"
},
"pubkey-chain": {
"vipObjectType": "tree",
"vipValue": [],
"vipType": "ignore",
"vipPrimaryKey": [
"key-string"
]
}
},
{
Expand All @@ -65,14 +57,6 @@
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "15"
},
"pubkey-chain": {
"vipObjectType": "tree",
"vipValue": [],
"vipType": "ignore",
"vipPrimaryKey": [
"key-string"
]
}
}
],
Expand Down Expand Up @@ -139,11 +123,6 @@
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "secret_key"
},
"key-enum": {
"vipObjectType": "object",
"vipValue": [],
"vipType": "ignore"
}
}
],
Expand Down Expand Up @@ -207,11 +186,6 @@
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "secret_key2"
},
"key-enum": {
"vipObjectType": "object",
"vipValue": [],
"vipType": "ignore"
}
}
],
Expand All @@ -235,6 +209,11 @@
"vipType": "constant",
"vipValue": "group1"
},
"vpn": {
"vipObjectType": "object",
"vipType": "constant",
"vipValue": 0
},
"source-interface": {
"vipObjectType": "object",
"vipType": "constant",
Expand Down Expand Up @@ -269,11 +248,6 @@
"vipObjectType": "object",
"vipType": "constant",
"vipValue": "secret_key"
},
"key-enum": {
"vipObjectType": "object",
"vipValue": [],
"vipType": "ignore"
}
}
],
Expand Down
Loading

0 comments on commit d392c05

Please sign in to comment.