diff --git a/.flake8 b/.flake8 index 551ba6507..dae21715f 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,7 @@ [flake8] -per-file-ignores = catalystwan/models/policy/__init__.py: F401 +per-file-ignores = + catalystwan/models/policy/__init__.py: F401 + catalystwan/models/configuration/feature_profile/sdwan/policy_object/__init__.py: F401 max-line-length = 120 inline-quotes = double # https://black.readthedocs.io/en/stable/faq.html#why-are-flake8-s-e203-and-w503-violated diff --git a/ENDPOINTS.md b/ENDPOINTS.md index 04a8dc02f..71034d411 100644 --- a/ENDPOINTS.md +++ b/ENDPOINTS.md @@ -1,4 +1,6 @@ -**THIS FILE IS AUTO-GENERATED DO NOT EDIT** +**THIS FILE WAS AUTO-GENERATED DO NOT EDIT** + +Generated for: catalystwan-0.30.0 All URIs are relative to */dataservice* HTTP request | Supported Versions | Method | Payload Type | Return Type | Tenancy Mode @@ -159,267 +161,267 @@ GET /template/policy/definition/zonebasedfw||[**ConfigurationPolicyZoneBasedFire GET /template/policy/definition/zonebasedfw/{id}||[**ConfigurationPolicyZoneBasedFirewallDefinition.get_policy_definition**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/definition/zone_based_firewall.py#L46)||[**ZoneBasedFWPolicyGetResponse**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/definition/zone_based_firewall.py#L21)| POST /template/policy/definition/zonebasedfw/preview||[**ConfigurationPolicyZoneBasedFirewallDefinition.preview_policy_definition**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/definition/zone_based_firewall.py#L50)|[**ZoneBasedFWPolicy**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/definitions/zone_based_firewall.py#L191)|[**PolicyDefinitionPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_definition.py#L1113)| GET /template/policy/definition/zonebasedfw/preview/{id}||[**ConfigurationPolicyZoneBasedFirewallDefinition.preview_policy_definition_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/definition/zone_based_firewall.py#L54)||[**PolicyDefinitionPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_definition.py#L1113)| -POST /template/policy/list/app||[**ConfigurationPolicyApplicationList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L25)|[**AppList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L130)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/app||[**ConfigurationPolicyApplicationList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L25)|[**AppList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L129)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/app/{id}||[**ConfigurationPolicyApplicationList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L29)||None| DELETE /template/policy/list/app||[**ConfigurationPolicyApplicationList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L33)||None| PUT /template/policy/list/app/{id}||[**ConfigurationPolicyApplicationList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L37)|[**AppListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L16)|None| GET /template/policy/list/app/{id}||[**ConfigurationPolicyApplicationList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L41)||[**AppListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L20)| GET /template/policy/list/app||[**ConfigurationPolicyApplicationList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L45)||DataSequence[[**AppListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L20)]| GET /template/policy/list/app/filtered||[**ConfigurationPolicyApplicationList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L49)||DataSequence[[**AppListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L20)]| -POST /template/policy/list/app/preview||[**ConfigurationPolicyApplicationList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L53)|[**AppList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L130)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/app/preview||[**ConfigurationPolicyApplicationList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L53)|[**AppList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L129)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/app/preview/{id}||[**ConfigurationPolicyApplicationList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/appprobe||[**ConfigurationPolicyAppProbeClassList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L25)|[**AppProbeClassList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L225)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/appprobe||[**ConfigurationPolicyAppProbeClassList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L25)|[**AppProbeClassList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L224)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/appprobe/{id}||[**ConfigurationPolicyAppProbeClassList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L29)||None| DELETE /template/policy/list/appprobe||[**ConfigurationPolicyAppProbeClassList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L33)||None| PUT /template/policy/list/appprobe/{id}||[**ConfigurationPolicyAppProbeClassList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L37)|[**AppProbeClassListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L16)|None| GET /template/policy/list/appprobe/{id}||[**ConfigurationPolicyAppProbeClassList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L41)||[**AppProbeClassListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L20)| GET /template/policy/list/appprobe||[**ConfigurationPolicyAppProbeClassList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L45)||DataSequence[[**AppProbeClassListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L20)]| GET /template/policy/list/appprobe/filtered||[**ConfigurationPolicyAppProbeClassList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L49)||DataSequence[[**AppProbeClassListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L20)]| -POST /template/policy/list/appprobe/preview||[**ConfigurationPolicyAppProbeClassList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L53)|[**AppProbeClassList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L225)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/appprobe/preview||[**ConfigurationPolicyAppProbeClassList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L53)|[**AppProbeClassList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L224)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/appprobe/preview/{id}||[**ConfigurationPolicyAppProbeClassList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/app_probe.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/aspath||[**ConfigurationPolicyASPathList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L25)|[**ASPathList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L205)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/aspath||[**ConfigurationPolicyASPathList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L25)|[**ASPathList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L204)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/aspath/{id}||[**ConfigurationPolicyASPathList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L29)||None| DELETE /template/policy/list/aspath||[**ConfigurationPolicyASPathList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L33)||None| PUT /template/policy/list/aspath/{id}||[**ConfigurationPolicyASPathList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L37)|[**ASPathListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L16)|None| GET /template/policy/list/aspath/{id}||[**ConfigurationPolicyASPathList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L41)||[**ASPathListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L20)| GET /template/policy/list/aspath||[**ConfigurationPolicyASPathList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L45)||DataSequence[[**ASPathListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L20)]| GET /template/policy/list/aspath/filtered||[**ConfigurationPolicyASPathList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L49)||DataSequence[[**ASPathListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L20)]| -POST /template/policy/list/aspath/preview||[**ConfigurationPolicyASPathList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L53)|[**ASPathList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L205)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/aspath/preview||[**ConfigurationPolicyASPathList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L53)|[**ASPathList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L204)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/aspath/preview/{id}||[**ConfigurationPolicyASPathList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/as_path.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/class||[**ConfigurationPolicyForwardingClassList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L25)|[**ClassMapList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L210)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/class||[**ConfigurationPolicyForwardingClassList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L25)|[**ClassMapList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L209)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/class/{id}||[**ConfigurationPolicyForwardingClassList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L29)||None| DELETE /template/policy/list/class||[**ConfigurationPolicyForwardingClassList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L33)||None| PUT /template/policy/list/class/{id}||[**ConfigurationPolicyForwardingClassList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L37)|[**ClassMapListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L16)|None| GET /template/policy/list/class/{id}||[**ConfigurationPolicyForwardingClassList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L41)||[**ClassMapListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L20)| GET /template/policy/list/class||[**ConfigurationPolicyForwardingClassList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L45)||DataSequence[[**ClassMapListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L20)]| GET /template/policy/list/class/filtered||[**ConfigurationPolicyForwardingClassList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L49)||DataSequence[[**ClassMapListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L20)]| -POST /template/policy/list/class/preview||[**ConfigurationPolicyForwardingClassList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L53)|[**ClassMapList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L210)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/class/preview||[**ConfigurationPolicyForwardingClassList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L53)|[**ClassMapList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L209)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/class/preview/{id}||[**ConfigurationPolicyForwardingClassList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/class_map.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/color||[**ConfigurationPolicyColorList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L25)|[**ColorList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L141)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/color||[**ConfigurationPolicyColorList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L25)|[**ColorList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L140)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/color/{id}||[**ConfigurationPolicyColorList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L29)||None| DELETE /template/policy/list/color||[**ConfigurationPolicyColorList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L33)||None| PUT /template/policy/list/color/{id}||[**ConfigurationPolicyColorList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L37)|[**ColorListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L16)|None| GET /template/policy/list/color/{id}||[**ConfigurationPolicyColorList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L41)||[**ColorListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L20)| GET /template/policy/list/color||[**ConfigurationPolicyColorList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L45)||DataSequence[[**ColorListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L20)]| GET /template/policy/list/color/filtered||[**ConfigurationPolicyColorList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L49)||DataSequence[[**ColorListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L20)]| -POST /template/policy/list/color/preview||[**ConfigurationPolicyColorList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L53)|[**ColorList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L141)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/color/preview||[**ConfigurationPolicyColorList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L53)|[**ColorList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L140)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/color/preview/{id}||[**ConfigurationPolicyColorList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/color.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/community||[**ConfigurationPolicyCommunityList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L25)|[**CommunityList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L187)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/community||[**ConfigurationPolicyCommunityList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L25)|[**CommunityList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L186)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/community/{id}||[**ConfigurationPolicyCommunityList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L29)||None| DELETE /template/policy/list/community||[**ConfigurationPolicyCommunityList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L33)||None| PUT /template/policy/list/community/{id}||[**ConfigurationPolicyCommunityList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L37)|[**CommunityListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L16)|None| GET /template/policy/list/community/{id}||[**ConfigurationPolicyCommunityList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L41)||[**CommunityListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L20)| GET /template/policy/list/community||[**ConfigurationPolicyCommunityList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L45)||DataSequence[[**CommunityListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L20)]| GET /template/policy/list/community/filtered||[**ConfigurationPolicyCommunityList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L49)||DataSequence[[**CommunityListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L20)]| -POST /template/policy/list/community/preview||[**ConfigurationPolicyCommunityList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L53)|[**CommunityList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L187)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/community/preview||[**ConfigurationPolicyCommunityList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L53)|[**CommunityList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L186)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/community/preview/{id}||[**ConfigurationPolicyCommunityList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/community.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/dataipv6prefix||[**ConfigurationPolicyDataIPv6PrefixList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L25)|[**DataIPv6PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L149)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/dataipv6prefix||[**ConfigurationPolicyDataIPv6PrefixList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L25)|[**DataIPv6PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L148)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/dataipv6prefix/{id}||[**ConfigurationPolicyDataIPv6PrefixList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L29)||None| DELETE /template/policy/list/dataipv6prefix||[**ConfigurationPolicyDataIPv6PrefixList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L33)||None| PUT /template/policy/list/dataipv6prefix/{id}||[**ConfigurationPolicyDataIPv6PrefixList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L37)|[**DataIPv6PrefixListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L16)|None| GET /template/policy/list/dataipv6prefix/{id}||[**ConfigurationPolicyDataIPv6PrefixList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L41)||[**DataIPv6PrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L20)| GET /template/policy/list/dataipv6prefix||[**ConfigurationPolicyDataIPv6PrefixList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L45)||DataSequence[[**DataIPv6PrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L20)]| GET /template/policy/list/dataipv6prefix/filtered||[**ConfigurationPolicyDataIPv6PrefixList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L49)||DataSequence[[**DataIPv6PrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L20)]| -POST /template/policy/list/dataipv6prefix/preview||[**ConfigurationPolicyDataIPv6PrefixList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L53)|[**DataIPv6PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L149)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/dataipv6prefix/preview||[**ConfigurationPolicyDataIPv6PrefixList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L53)|[**DataIPv6PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L148)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/dataipv6prefix/preview/{id}||[**ConfigurationPolicyDataIPv6PrefixList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_ipv6_prefix.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/dataprefix||[**ConfigurationPolicyDataPrefixList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L25)|[**DataPrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L60)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/dataprefix||[**ConfigurationPolicyDataPrefixList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L25)|[**DataPrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L59)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/dataprefix/{id}||[**ConfigurationPolicyDataPrefixList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L29)||None| DELETE /template/policy/list/dataprefix||[**ConfigurationPolicyDataPrefixList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L33)||None| PUT /template/policy/list/dataprefix/{id}||[**ConfigurationPolicyDataPrefixList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L37)|[**DataPrefixListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L16)|None| GET /template/policy/list/dataprefix/{id}||[**ConfigurationPolicyDataPrefixList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L41)||[**DataPrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L20)| GET /template/policy/list/dataprefix||[**ConfigurationPolicyDataPrefixList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L45)||DataSequence[[**DataPrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L20)]| GET /template/policy/list/dataprefix/filtered||[**ConfigurationPolicyDataPrefixList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L49)||DataSequence[[**DataPrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L20)]| -POST /template/policy/list/dataprefix/preview||[**ConfigurationPolicyDataPrefixList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L53)|[**DataPrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L60)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/dataprefix/preview||[**ConfigurationPolicyDataPrefixList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L53)|[**DataPrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L59)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/dataprefix/preview/{id}||[**ConfigurationPolicyDataPrefixList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/data_prefix.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/expandedcommunity||[**ConfigurationPolicyExpandedCommunityList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L25)|[**ExpandedCommunityList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L191)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/expandedcommunity||[**ConfigurationPolicyExpandedCommunityList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L25)|[**ExpandedCommunityList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L190)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/expandedcommunity/{id}||[**ConfigurationPolicyExpandedCommunityList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L29)||None| DELETE /template/policy/list/expandedcommunity||[**ConfigurationPolicyExpandedCommunityList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L33)||None| PUT /template/policy/list/expandedcommunity/{id}||[**ConfigurationPolicyExpandedCommunityList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L37)|[**ExpandedCommunityListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L16)|None| GET /template/policy/list/expandedcommunity/{id}||[**ConfigurationPolicyExpandedCommunityList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L41)||[**ExpandedCommunityListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L20)| GET /template/policy/list/expandedcommunity||[**ConfigurationPolicyExpandedCommunityList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L45)||DataSequence[[**ExpandedCommunityListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L20)]| GET /template/policy/list/expandedcommunity/filtered||[**ConfigurationPolicyExpandedCommunityList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L49)||DataSequence[[**ExpandedCommunityListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L20)]| -POST /template/policy/list/expandedcommunity/preview||[**ConfigurationPolicyExpandedCommunityList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L53)|[**ExpandedCommunityList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L191)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/expandedcommunity/preview||[**ConfigurationPolicyExpandedCommunityList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L53)|[**ExpandedCommunityList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L190)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/expandedcommunity/preview/{id}||[**ConfigurationPolicyExpandedCommunityList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/expanded_community.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/fqdn||[**ConfigurationPolicyFQDNList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L25)|[**FQDNList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L105)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/fqdn||[**ConfigurationPolicyFQDNList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L25)|[**FQDNList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L104)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/fqdn/{id}||[**ConfigurationPolicyFQDNList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L29)||None| DELETE /template/policy/list/fqdn||[**ConfigurationPolicyFQDNList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L33)||None| PUT /template/policy/list/fqdn/{id}||[**ConfigurationPolicyFQDNList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L37)|[**FQDNListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L16)|None| GET /template/policy/list/fqdn/{id}||[**ConfigurationPolicyFQDNList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L41)||[**FQDNListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L20)| GET /template/policy/list/fqdn||[**ConfigurationPolicyFQDNList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L45)||DataSequence[[**FQDNListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L20)]| GET /template/policy/list/fqdn/filtered||[**ConfigurationPolicyFQDNList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L49)||DataSequence[[**FQDNListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L20)]| -POST /template/policy/list/fqdn/preview||[**ConfigurationPolicyFQDNList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L53)|[**FQDNList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L105)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/fqdn/preview||[**ConfigurationPolicyFQDNList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L53)|[**FQDNList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L104)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/fqdn/preview/{id}||[**ConfigurationPolicyFQDNList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/fqdn.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/geolocation||[**ConfigurationPolicyGeoLocationList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L25)|[**GeoLocationList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L110)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/geolocation||[**ConfigurationPolicyGeoLocationList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L25)|[**GeoLocationList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L109)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/geolocation/{id}||[**ConfigurationPolicyGeoLocationList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L29)||None| DELETE /template/policy/list/geolocation||[**ConfigurationPolicyGeoLocationList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L33)||None| PUT /template/policy/list/geolocation/{id}||[**ConfigurationPolicyGeoLocationList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L37)|[**GeoLocationListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L16)|None| GET /template/policy/list/geolocation/{id}||[**ConfigurationPolicyGeoLocationList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L41)||[**GeoLocationListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L20)| GET /template/policy/list/geolocation||[**ConfigurationPolicyGeoLocationList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L45)||DataSequence[[**GeoLocationListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L20)]| GET /template/policy/list/geolocation/filtered||[**ConfigurationPolicyGeoLocationList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L49)||DataSequence[[**GeoLocationListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L20)]| -POST /template/policy/list/geolocation/preview||[**ConfigurationPolicyGeoLocationList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L53)|[**GeoLocationList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L110)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/geolocation/preview||[**ConfigurationPolicyGeoLocationList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L53)|[**GeoLocationList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L109)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/geolocation/preview/{id}||[**ConfigurationPolicyGeoLocationList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/geo_location.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/ipssignature||[**ConfigurationPolicyIPSSignatureList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L25)|[**IPSSignatureList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L162)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/ipssignature||[**ConfigurationPolicyIPSSignatureList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L25)|[**IPSSignatureList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L161)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/ipssignature/{id}||[**ConfigurationPolicyIPSSignatureList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L29)||None| DELETE /template/policy/list/ipssignature||[**ConfigurationPolicyIPSSignatureList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L33)||None| PUT /template/policy/list/ipssignature/{id}||[**ConfigurationPolicyIPSSignatureList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L37)|[**IPSSignatureListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L16)|None| GET /template/policy/list/ipssignature/{id}||[**ConfigurationPolicyIPSSignatureList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L41)||[**IPSSignatureListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L20)| GET /template/policy/list/ipssignature||[**ConfigurationPolicyIPSSignatureList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L45)||DataSequence[[**IPSSignatureListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L20)]| GET /template/policy/list/ipssignature/filtered||[**ConfigurationPolicyIPSSignatureList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L49)||DataSequence[[**IPSSignatureListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L20)]| -POST /template/policy/list/ipssignature/preview||[**ConfigurationPolicyIPSSignatureList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L53)|[**IPSSignatureList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L162)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/ipssignature/preview||[**ConfigurationPolicyIPSSignatureList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L53)|[**IPSSignatureList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L161)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/ipssignature/preview/{id}||[**ConfigurationPolicyIPSSignatureList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ips_signature.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/ipv6prefix||[**ConfigurationPolicyIPv6PrefixList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L25)|[**IPv6PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L316)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/ipv6prefix||[**ConfigurationPolicyIPv6PrefixList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L25)|[**IPv6PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L315)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/ipv6prefix/{id}||[**ConfigurationPolicyIPv6PrefixList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L29)||None| DELETE /template/policy/list/ipv6prefix||[**ConfigurationPolicyIPv6PrefixList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L33)||None| PUT /template/policy/list/ipv6prefix/{id}||[**ConfigurationPolicyIPv6PrefixList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L37)|[**IPv6PrefixListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L16)|None| GET /template/policy/list/ipv6prefix/{id}||[**ConfigurationPolicyIPv6PrefixList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L41)||[**IPv6PrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L20)| GET /template/policy/list/ipv6prefix||[**ConfigurationPolicyIPv6PrefixList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L45)||DataSequence[[**IPv6PrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L20)]| GET /template/policy/list/ipv6prefix/filtered||[**ConfigurationPolicyIPv6PrefixList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L49)||DataSequence[[**IPv6PrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L20)]| -POST /template/policy/list/ipv6prefix/preview||[**ConfigurationPolicyIPv6PrefixList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L53)|[**IPv6PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L316)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/ipv6prefix/preview||[**ConfigurationPolicyIPv6PrefixList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L53)|[**IPv6PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L315)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/ipv6prefix/preview/{id}||[**ConfigurationPolicyIPv6PrefixList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/ipv6_prefix.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/localapp||[**ConfigurationPolicyLocalAppList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L25)|[**LocalAppList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L125)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/localapp||[**ConfigurationPolicyLocalAppList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L25)|[**LocalAppList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L124)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/localapp/{id}||[**ConfigurationPolicyLocalAppList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L29)||None| DELETE /template/policy/list/localapp||[**ConfigurationPolicyLocalAppList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L33)||None| PUT /template/policy/list/localapp/{id}||[**ConfigurationPolicyLocalAppList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L37)|[**LocalAppListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L16)|None| GET /template/policy/list/localapp/{id}||[**ConfigurationPolicyLocalAppList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L41)||[**LocalAppListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L20)| GET /template/policy/list/localapp||[**ConfigurationPolicyLocalAppList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L45)||DataSequence[[**LocalAppListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L20)]| GET /template/policy/list/localapp/filtered||[**ConfigurationPolicyLocalAppList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L49)||DataSequence[[**LocalAppListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L20)]| -POST /template/policy/list/localapp/preview||[**ConfigurationPolicyLocalAppList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L53)|[**LocalAppList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L125)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/localapp/preview||[**ConfigurationPolicyLocalAppList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L53)|[**LocalAppList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L124)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/localapp/preview/{id}||[**ConfigurationPolicyLocalAppList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_app.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/localdomain||[**ConfigurationPolicyLocalDomainList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L25)|[**LocalDomainList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L157)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/localdomain||[**ConfigurationPolicyLocalDomainList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L25)|[**LocalDomainList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L156)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/localdomain/{id}||[**ConfigurationPolicyLocalDomainList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L29)||None| DELETE /template/policy/list/localdomain||[**ConfigurationPolicyLocalDomainList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L33)||None| PUT /template/policy/list/localdomain/{id}||[**ConfigurationPolicyLocalDomainList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L37)|[**LocalDomainListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L16)|None| GET /template/policy/list/localdomain/{id}||[**ConfigurationPolicyLocalDomainList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L41)||[**LocalDomainListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L20)| GET /template/policy/list/localdomain||[**ConfigurationPolicyLocalDomainList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L45)||DataSequence[[**LocalDomainListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L20)]| GET /template/policy/list/localdomain/filtered||[**ConfigurationPolicyLocalDomainList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L49)||DataSequence[[**LocalDomainListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L20)]| -POST /template/policy/list/localdomain/preview||[**ConfigurationPolicyLocalDomainList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L53)|[**LocalDomainList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L157)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/localdomain/preview||[**ConfigurationPolicyLocalDomainList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L53)|[**LocalDomainList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L156)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/localdomain/preview/{id}||[**ConfigurationPolicyLocalDomainList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/local_domain.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/mirror||[**ConfigurationPolicyMirrorList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L25)|[**MirrorList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L220)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/mirror||[**ConfigurationPolicyMirrorList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L25)|[**MirrorList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L219)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/mirror/{id}||[**ConfigurationPolicyMirrorList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L29)||None| DELETE /template/policy/list/mirror||[**ConfigurationPolicyMirrorList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L33)||None| PUT /template/policy/list/mirror/{id}||[**ConfigurationPolicyMirrorList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L37)|[**MirrorListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L16)|None| GET /template/policy/list/mirror/{id}||[**ConfigurationPolicyMirrorList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L41)||[**MirrorListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L20)| GET /template/policy/list/mirror||[**ConfigurationPolicyMirrorList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L45)||DataSequence[[**MirrorListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L20)]| GET /template/policy/list/mirror/filtered||[**ConfigurationPolicyMirrorList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L49)||DataSequence[[**MirrorListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L20)]| -POST /template/policy/list/mirror/preview||[**ConfigurationPolicyMirrorList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L53)|[**MirrorList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L220)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/mirror/preview||[**ConfigurationPolicyMirrorList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L53)|[**MirrorList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L219)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/mirror/preview/{id}||[**ConfigurationPolicyMirrorList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/mirror.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/policer||[**ConfigurationPolicyPolicerClassList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L25)|[**PolicerList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L195)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/policer||[**ConfigurationPolicyPolicerClassList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L25)|[**PolicerList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L194)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/policer/{id}||[**ConfigurationPolicyPolicerClassList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L29)||None| DELETE /template/policy/list/policer||[**ConfigurationPolicyPolicerClassList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L33)||None| PUT /template/policy/list/policer/{id}||[**ConfigurationPolicyPolicerClassList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L37)|[**PolicerListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L16)|None| GET /template/policy/list/policer/{id}||[**ConfigurationPolicyPolicerClassList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L41)||[**PolicerListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L20)| GET /template/policy/list/policer||[**ConfigurationPolicyPolicerClassList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L45)||DataSequence[[**PolicerListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L20)]| GET /template/policy/list/policer/filtered||[**ConfigurationPolicyPolicerClassList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L49)||DataSequence[[**PolicerListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L20)]| -POST /template/policy/list/policer/preview||[**ConfigurationPolicyPolicerClassList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L53)|[**PolicerList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L195)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/policer/preview||[**ConfigurationPolicyPolicerClassList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L53)|[**PolicerList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L194)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/policer/preview/{id}||[**ConfigurationPolicyPolicerClassList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/policer.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/port||[**ConfigurationPolicyPortList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L25)|[**PortList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L115)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/port||[**ConfigurationPolicyPortList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L25)|[**PortList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L114)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/port/{id}||[**ConfigurationPolicyPortList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L29)||None| DELETE /template/policy/list/port||[**ConfigurationPolicyPortList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L33)||None| PUT /template/policy/list/port/{id}||[**ConfigurationPolicyPortList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L37)|[**PortListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L16)|None| GET /template/policy/list/port/{id}||[**ConfigurationPolicyPortList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L41)||[**PortListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L20)| GET /template/policy/list/port||[**ConfigurationPolicyPortList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L45)||DataSequence[[**PortListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L20)]| GET /template/policy/list/port/filtered||[**ConfigurationPolicyPortList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L49)||DataSequence[[**PortListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L20)]| -POST /template/policy/list/port/preview||[**ConfigurationPolicyPortList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L53)|[**PortList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L115)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/port/preview||[**ConfigurationPolicyPortList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L53)|[**PortList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L114)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/port/preview/{id}||[**ConfigurationPolicyPortList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/port.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/preferredcolorgroup||[**ConfigurationPreferredColorGroupList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L25)|[**PreferredColorGroupList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L279)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/preferredcolorgroup||[**ConfigurationPreferredColorGroupList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L25)|[**PreferredColorGroupList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L278)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/preferredcolorgroup/{id}||[**ConfigurationPreferredColorGroupList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L29)||None| DELETE /template/policy/list/preferredcolorgroup||[**ConfigurationPreferredColorGroupList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L33)||None| PUT /template/policy/list/preferredcolorgroup/{id}||[**ConfigurationPreferredColorGroupList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L37)|[**PreferredColorGroupListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L16)|None| GET /template/policy/list/preferredcolorgroup/{id}||[**ConfigurationPreferredColorGroupList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L41)||[**PreferredColorGroupListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L20)| GET /template/policy/list/preferredcolorgroup||[**ConfigurationPreferredColorGroupList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L45)||DataSequence[[**PreferredColorGroupListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L20)]| GET /template/policy/list/preferredcolorgroup/filtered||[**ConfigurationPreferredColorGroupList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L49)||DataSequence[[**PreferredColorGroupListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L20)]| -POST /template/policy/list/preferredcolorgroup/preview||[**ConfigurationPreferredColorGroupList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L53)|[**PreferredColorGroupList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L279)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/preferredcolorgroup/preview||[**ConfigurationPreferredColorGroupList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L53)|[**PreferredColorGroupList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L278)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/preferredcolorgroup/preview/{id}||[**ConfigurationPreferredColorGroupList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/preferred_color_group.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/prefix||[**ConfigurationPolicyPrefixList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L25)|[**PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L306)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/prefix||[**ConfigurationPolicyPrefixList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L25)|[**PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L305)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/prefix/{id}||[**ConfigurationPolicyPrefixList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L29)||None| DELETE /template/policy/list/prefix||[**ConfigurationPolicyPrefixList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L33)||None| PUT /template/policy/list/prefix/{id}||[**ConfigurationPolicyPrefixList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L37)|[**PrefixListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L16)|None| GET /template/policy/list/prefix/{id}||[**ConfigurationPolicyPrefixList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L41)||[**PrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L20)| GET /template/policy/list/prefix||[**ConfigurationPolicyPrefixList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L45)||DataSequence[[**PrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L20)]| GET /template/policy/list/prefix/filtered||[**ConfigurationPolicyPrefixList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L49)||DataSequence[[**PrefixListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L20)]| -POST /template/policy/list/prefix/preview||[**ConfigurationPolicyPrefixList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L53)|[**PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L306)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/prefix/preview||[**ConfigurationPolicyPrefixList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L53)|[**PrefixList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L305)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/prefix/preview/{id}||[**ConfigurationPolicyPrefixList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/prefix.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/protocolname||[**ConfigurationPolicyProtocolNameList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L25)|[**ProtocolNameList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L120)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/protocolname||[**ConfigurationPolicyProtocolNameList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L25)|[**ProtocolNameList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L119)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/protocolname/{id}||[**ConfigurationPolicyProtocolNameList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L29)||None| DELETE /template/policy/list/protocolname||[**ConfigurationPolicyProtocolNameList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L33)||None| PUT /template/policy/list/protocolname/{id}||[**ConfigurationPolicyProtocolNameList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L37)|[**ProtocolNameListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L16)|None| GET /template/policy/list/protocolname/{id}||[**ConfigurationPolicyProtocolNameList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L41)||[**ProtocolNameListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L20)| GET /template/policy/list/protocolname||[**ConfigurationPolicyProtocolNameList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L45)||DataSequence[[**ProtocolNameListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L20)]| GET /template/policy/list/protocolname/filtered||[**ConfigurationPolicyProtocolNameList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L49)||DataSequence[[**ProtocolNameListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L20)]| -POST /template/policy/list/protocolname/preview||[**ConfigurationPolicyProtocolNameList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L53)|[**ProtocolNameList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L120)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/protocolname/preview||[**ConfigurationPolicyProtocolNameList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L53)|[**ProtocolNameList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L119)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/protocolname/preview/{id}||[**ConfigurationPolicyProtocolNameList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/protocol_name.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/region||[**ConfigurationPolicyRegionList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L19)|[**RegionList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L321)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/region||[**ConfigurationPolicyRegionList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L19)|[**RegionList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L320)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/region/{id}||[**ConfigurationPolicyRegionList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L23)||None| DELETE /template/policy/list/region||[**ConfigurationPolicyRegionList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L27)||None| PUT /template/policy/list/region/{id}||[**ConfigurationPolicyRegionList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L31)|[**RegionListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L10)|None| GET /template/policy/list/region/{id}||[**ConfigurationPolicyRegionList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L35)||[**RegionListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L14)| GET /template/policy/list/region||[**ConfigurationPolicyRegionList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L39)||DataSequence[[**RegionListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L14)]| GET /template/policy/list/region/filtered||[**ConfigurationPolicyRegionList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L43)||DataSequence[[**RegionListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L14)]| -POST /template/policy/list/region/preview||[**ConfigurationPolicyRegionList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L47)|[**RegionList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L321)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/region/preview||[**ConfigurationPolicyRegionList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L47)|[**RegionList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L320)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/region/preview/{id}||[**ConfigurationPolicyRegionList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/region.py#L51)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/site/defaultsite||[**ConfigurationPolicySiteList.create_default_site_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L25)|[**SiteList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L68)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| -POST /template/policy/list/site||[**ConfigurationPolicySiteList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L29)|[**SiteList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L68)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/site/defaultsite||[**ConfigurationPolicySiteList.create_default_site_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L25)|[**SiteList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L67)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/site||[**ConfigurationPolicySiteList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L29)|[**SiteList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L67)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/site/{id}||[**ConfigurationPolicySiteList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L33)||None| DELETE /template/policy/list/site||[**ConfigurationPolicySiteList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L37)||None| PUT /template/policy/list/site/{id}||[**ConfigurationPolicySiteList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L41)|[**SiteListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L16)|None| GET /template/policy/list/site/{id}||[**ConfigurationPolicySiteList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L45)||[**SiteListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L20)| GET /template/policy/list/site||[**ConfigurationPolicySiteList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L49)||DataSequence[[**SiteListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L20)]| GET /template/policy/list/site/filtered||[**ConfigurationPolicySiteList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L53)||DataSequence[[**SiteListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L20)]| -POST /template/policy/list/site/preview||[**ConfigurationPolicySiteList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L57)|[**SiteList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L68)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/site/preview||[**ConfigurationPolicySiteList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L57)|[**SiteList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L67)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/site/preview/{id}||[**ConfigurationPolicySiteList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/site.py#L61)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/sla||[**ConfigurationPolicySLAClassList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L25)|[**SLAClassList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L236)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/sla||[**ConfigurationPolicySLAClassList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L25)|[**SLAClassList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L235)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/sla/{id}||[**ConfigurationPolicySLAClassList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L29)||None| DELETE /template/policy/list/sla||[**ConfigurationPolicySLAClassList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L33)||None| PUT /template/policy/list/sla/{id}||[**ConfigurationPolicySLAClassList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L37)|[**SLAClassListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L16)|None| GET /template/policy/list/sla/{id}||[**ConfigurationPolicySLAClassList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L41)||[**SLAClassListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L20)| GET /template/policy/list/sla||[**ConfigurationPolicySLAClassList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L45)||DataSequence[[**SLAClassListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L20)]| GET /template/policy/list/sla/filtered||[**ConfigurationPolicySLAClassList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L49)||DataSequence[[**SLAClassListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L20)]| -POST /template/policy/list/sla/preview||[**ConfigurationPolicySLAClassList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L53)|[**SLAClassList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L236)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/sla/preview||[**ConfigurationPolicySLAClassList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L53)|[**SLAClassList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L235)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/sla/preview/{id}||[**ConfigurationPolicySLAClassList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/sla.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/tloc||[**ConfigurationPolicyTLOCList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L25)|[**TLOCList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L268)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/tloc||[**ConfigurationPolicyTLOCList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L25)|[**TLOCList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L267)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/tloc/{id}||[**ConfigurationPolicyTLOCList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L29)||None| DELETE /template/policy/list/tloc||[**ConfigurationPolicyTLOCList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L33)||None| PUT /template/policy/list/tloc/{id}||[**ConfigurationPolicyTLOCList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L37)|[**TLOCListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L16)|None| GET /template/policy/list/tloc/{id}||[**ConfigurationPolicyTLOCList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L41)||[**TLOCListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L20)| GET /template/policy/list/tloc||[**ConfigurationPolicyTLOCList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L45)||DataSequence[[**TLOCListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L20)]| GET /template/policy/list/tloc/filtered||[**ConfigurationPolicyTLOCList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L49)||DataSequence[[**TLOCListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L20)]| -POST /template/policy/list/tloc/preview||[**ConfigurationPolicyTLOCList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L53)|[**TLOCList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L268)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/tloc/preview||[**ConfigurationPolicyTLOCList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L53)|[**TLOCList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L267)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/tloc/preview/{id}||[**ConfigurationPolicyTLOCList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/tloc.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/urlblacklist||[**ConfigurationPolicyURLBlackList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L25)|[**URLBlackList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L172)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/urlblacklist||[**ConfigurationPolicyURLBlackList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L25)|[**URLBlackList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L171)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/urlblacklist/{id}||[**ConfigurationPolicyURLBlackList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L29)||None| DELETE /template/policy/list/urlblacklist||[**ConfigurationPolicyURLBlackList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L33)||None| PUT /template/policy/list/urlblacklist/{id}||[**ConfigurationPolicyURLBlackList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L37)|[**URLBlackListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L16)|None| GET /template/policy/list/urlblacklist/{id}||[**ConfigurationPolicyURLBlackList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L41)||[**URLBlackListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L20)| GET /template/policy/list/urlblacklist||[**ConfigurationPolicyURLBlackList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L45)||DataSequence[[**URLBlackListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L20)]| GET /template/policy/list/urlblacklist/filtered||[**ConfigurationPolicyURLBlackList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L49)||DataSequence[[**URLBlackListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L20)]| -POST /template/policy/list/urlblacklist/preview||[**ConfigurationPolicyURLBlackList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L53)|[**URLBlackList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L172)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/urlblacklist/preview||[**ConfigurationPolicyURLBlackList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L53)|[**URLBlackList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L171)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/urlblacklist/preview/{id}||[**ConfigurationPolicyURLBlackList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_black_list.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/urlwhitelist||[**ConfigurationPolicyURLWhiteList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L25)|[**URLWhiteList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L167)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/urlwhitelist||[**ConfigurationPolicyURLWhiteList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L25)|[**URLWhiteList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L166)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/urlwhitelist/{id}||[**ConfigurationPolicyURLWhiteList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L29)||None| DELETE /template/policy/list/urlwhitelist||[**ConfigurationPolicyURLWhiteList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L33)||None| PUT /template/policy/list/urlwhitelist/{id}||[**ConfigurationPolicyURLWhiteList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L37)|[**URLWhiteListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L16)|None| GET /template/policy/list/urlwhitelist/{id}||[**ConfigurationPolicyURLWhiteList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L41)||[**URLWhiteListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L20)| GET /template/policy/list/urlwhitelist||[**ConfigurationPolicyURLWhiteList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L45)||DataSequence[[**URLWhiteListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L20)]| GET /template/policy/list/urlwhitelist/filtered||[**ConfigurationPolicyURLWhiteList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L49)||DataSequence[[**URLWhiteListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L20)]| -POST /template/policy/list/urlwhitelist/preview||[**ConfigurationPolicyURLWhiteList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L53)|[**URLWhiteList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L167)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/urlwhitelist/preview||[**ConfigurationPolicyURLWhiteList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L53)|[**URLWhiteList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L166)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/urlwhitelist/preview/{id}||[**ConfigurationPolicyURLWhiteList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/url_white_list.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/vpn||[**ConfigurationPolicyVPNList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L27)|[**VPNList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L81)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/vpn||[**ConfigurationPolicyVPNList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L27)|[**VPNList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L80)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/vpn/{id}||[**ConfigurationPolicyVPNList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L31)||None| DELETE /template/policy/list/vpn||[**ConfigurationPolicyVPNList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L35)||None| PUT /template/policy/list/vpn/{id}||[**ConfigurationPolicyVPNList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L39)|[**VPNListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L18)|None| GET /template/policy/list/vpn/{id}||[**ConfigurationPolicyVPNList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L43)||[**VPNListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L22)| GET /template/policy/list/vpn||[**ConfigurationPolicyVPNList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L47)||DataSequence[[**VPNListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L22)]| GET /template/policy/list/vpn/filtered||[**ConfigurationPolicyVPNList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L51)||DataSequence[[**VPNListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L22)]| -POST /template/policy/list/vpn/preview||[**ConfigurationPolicyVPNList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L55)|[**VPNList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L81)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/vpn/preview||[**ConfigurationPolicyVPNList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L55)|[**VPNList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L80)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/vpn/preview/{id}||[**ConfigurationPolicyVPNList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/vpn.py#L59)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| -POST /template/policy/list/zone||[**ConfigurationPolicyZoneList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L25)|[**ZoneList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L94)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| +POST /template/policy/list/zone||[**ConfigurationPolicyZoneList.create_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L25)|[**ZoneList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L93)|[**PolicyListId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L15)| DELETE /template/policy/list/zone/{id}||[**ConfigurationPolicyZoneList.delete_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L29)||None| DELETE /template/policy/list/zone||[**ConfigurationPolicyZoneList.delete_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L33)||None| PUT /template/policy/list/zone/{id}||[**ConfigurationPolicyZoneList.edit_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L37)|[**ZoneListEditPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L16)|None| GET /template/policy/list/zone/{id}||[**ConfigurationPolicyZoneList.get_lists_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L41)||[**ZoneListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L20)| GET /template/policy/list/zone||[**ConfigurationPolicyZoneList.get_policy_lists**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L45)||DataSequence[[**ZoneListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L20)]| GET /template/policy/list/zone/filtered||[**ConfigurationPolicyZoneList.get_policy_lists_with_info_tag**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L49)||DataSequence[[**ZoneListInfo**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L20)]| -POST /template/policy/list/zone/preview||[**ConfigurationPolicyZoneList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L53)|[**ZoneList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L94)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| +POST /template/policy/list/zone/preview||[**ConfigurationPolicyZoneList.preview_policy_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L53)|[**ZoneList**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/lists.py#L93)|[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| GET /template/policy/list/zone/preview/{id}||[**ConfigurationPolicyZoneList.preview_policy_list_by_id**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/list/zone.py#L57)||[**PolicyListPreview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/policy_list.py#L29)| POST /template/policy/security||[**ConfigurationSecurityTemplatePolicy.create_security_template**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/security_template.py#L15)|[**SecurityPolicy**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/security.py#L102), [**UnifiedSecurityPolicy**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/models/policy/security.py#L137)|None| DELETE /template/policy/security/{id}||[**ConfigurationSecurityTemplatePolicy.delete_security_template**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration/policy/security_template.py#L19)|None|None| @@ -455,13 +457,13 @@ GET /device/action/software/images||[**ConfigurationSoftwareActions.get_list_of_ GET /device/action/status/{task_id}||[**ConfigurationDashboardStatus.find_status**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_dashboard_status.py#L89)||[**TaskData**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_dashboard_status.py#L76)| GET /device/action/status/tasks||[**ConfigurationDashboardStatus.find_running_tasks**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_dashboard_status.py#L93)||[**TasksData**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_dashboard_status.py#L84)| GET /device/action/ztp/upgrade/setting||[**ConfigurationDeviceActions.get_ztp_upgrade_config_setting**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_actions.py#L74)||DataSequence[[**ZTPUpgradeSettings**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_actions.py#L10)]| -POST /system/device/{device_uuid}/unlock|>=20.9|[**ConfigurationDeviceInventory.unlock**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L196)|[**DeviceUnlockPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L19)|[**DeviceUnlockResponse**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L24)| -POST /system/device||[**ConfigurationDeviceInventory.create_device**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L201)|[**DeviceCreationPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L33)|None| -DELETE /system/device/{uuid}||[**ConfigurationDeviceInventory.delete_device**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L205)||[**DeviceDeletionResponse**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L45)| -GET /system/device/{device_category}||[**ConfigurationDeviceInventory.get_device_details**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L212)||DataSequence[[**DeviceDetailsResponse**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L58)]| -POST /system/device/smartaccount/sync||[**ConfigurationDeviceInventory.sync_devices_from_smart_account**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L218)|[**SmartAccountSyncParams**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L145)|[**ProcessId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L153)| -POST /system/device/fileupload||[**ConfigurationDeviceInventory.upload_wan_edge_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L222)|[**SerialFilePayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L157)|[**UploadSerialFileResponse**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L185)| -GET /system/device/bootstrap/device/{uuid}||[**ConfigurationDeviceInventory.generate_bootstrap_configuration**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L226)||[**BoostrapConfiguration**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L179)| +POST /system/device/{device_uuid}/unlock|>=20.9|[**ConfigurationDeviceInventory.unlock**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L271)|[**DeviceUnlockPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L18)|[**DeviceUnlockResponse**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L23)| +POST /system/device||[**ConfigurationDeviceInventory.create_device**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L276)|[**DeviceCreationPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L30)|None| +DELETE /system/device/{uuid}||[**ConfigurationDeviceInventory.delete_device**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L280)||[**DeviceDeletionResponse**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L42)| +GET /system/device/{device_category}||[**ConfigurationDeviceInventory.get_device_details**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L287)||DataSequence[[**DeviceDetailsResponse**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L55)]| +POST /system/device/smartaccount/sync||[**ConfigurationDeviceInventory.sync_devices_from_smart_account**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L293)|[**SmartAccountSyncParams**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L208)|[**ProcessId**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L216)| +POST /system/device/fileupload||[**ConfigurationDeviceInventory.upload_wan_edge_list**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L297)|[**SerialFilePayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L220)|[**UploadSerialFileResponse**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L252)| +GET /system/device/bootstrap/device/{uuid}||[**ConfigurationDeviceInventory.generate_bootstrap_configuration**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L301)||[**BoostrapConfiguration**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_inventory.py#L244)| POST /template/device/config/config/||[**ConfigurationDeviceTemplate.get_device_configuration_preview**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_template.py#L19)|[**FeatureToCLIPayload**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_device_template.py#L10)|str|PROVIDER GET /v1/feature-profile/sdwan/system/aaa/schema|>=20.9|[**ConfigurationFeatureProfile.get_sdwan_system_aaa_parcel_schema**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_feature_profile.py#L39)||None| GET /v1/feature-profile/sdwan/transport/cellular-controller/schema|>=20.9|[**ConfigurationFeatureProfile.get_sdwan_transport_cellular_controller_parcel_schema**](https://github.com/CiscoDevNet/catalystwan/blob/main/catalystwan/endpoints/configuration_feature_profile.py#L44)||None| diff --git a/README.md b/README.md index 733e33923..e13143b6c 100644 --- a/README.md +++ b/README.md @@ -121,11 +121,11 @@ critical_alarms = session.api.alarms.get(from_time=n).filter(severity=Severity.C session.api.users.get() # Create user -new_user = User(userName="new_user", password="new_user", group=["netadmin"], description="new user") +new_user = User(username="new_user", password="new_user", group=["netadmin"], description="new user") session.api.users.create(new_user) # Update user data -new_user_update = UserUpdateRequest(userName="new_user", group=["netadmin", "netops"], locale="en_US", description="updated-new_user-description", resGroupName="global") +new_user_update = UserUpdateRequest(username="new_user", group=["netadmin", "netops"], locale="en_US", description="updated-new_user-description") session.api.users.update(new_user_update) # Update user password @@ -324,14 +324,14 @@ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) ## Catching Exceptions ```python try: - session.api.users.delete_user("XYZ") -except vManageBadRequestError as error: - # Process an error. - logger.error(error.info.details) - -# message = 'Delete users request failed' -# details = 'No user with name XYZ was found' -# code = 'USER0006' + session.api.users.delete("bogus-user-name") +except ManagerHTTPError as error: + # Process an error. + print(error.response.status_code) + print(error.info.code) + print(error.info.message) + print(error.info.details) + ``` ## [Supported API endpoints](https://github.com/CiscoDevNet/catalystwan/blob/main/ENDPOINTS.md) diff --git a/catalystwan/abstractions.py b/catalystwan/abstractions.py new file mode 100644 index 000000000..7dd6d3c6b --- /dev/null +++ b/catalystwan/abstractions.py @@ -0,0 +1,52 @@ +from typing import Optional, Protocol, Type, TypeVar + +from packaging.version import Version # type: ignore + +from catalystwan.typed_list import DataSequence +from catalystwan.utils.session_type import SessionType + +T = TypeVar("T") + + +class APIEndpointClientResponse(Protocol): + """ + Interface to response object. Fits "requests.Response" + but set of methods is minimal to allow easy migration to another client if needed + """ + + @property + def text(self) -> str: + ... + + @property + def content(self) -> bytes: + ... + + def dataobj(self, cls: Type[T], sourcekey: Optional[str]) -> T: + ... + + def dataseq(self, cls: Type[T], sourcekey: Optional[str]) -> DataSequence[T]: + ... + + def json(self) -> dict: + ... + + +class APIEndpointClient(Protocol): + """ + Interface to client object. + We only need a 'request' function and few vmanage session properties obtained from server. + Matched to fit "requests.Session" but migration to other client is possible. + At his point not very clean as injection of custom kwargs is possible (and sometimes used) + """ + + def request(self, method: str, url: str, **kwargs) -> APIEndpointClientResponse: + ... + + @property + def api_version(self) -> Optional[Version]: + ... + + @property + def session_type(self) -> Optional[SessionType]: + ... diff --git a/catalystwan/api/admin_tech_api.py b/catalystwan/api/admin_tech_api.py index 3a1072b7a..16fa1f4c1 100644 --- a/catalystwan/api/admin_tech_api.py +++ b/catalystwan/api/admin_tech_api.py @@ -12,7 +12,7 @@ from requests.exceptions import HTTPError from catalystwan.dataclasses import AdminTech, DeviceAdminTech -from catalystwan.exceptions import ManagerError +from catalystwan.exceptions import CatalystwanException from catalystwan.utils.creation_tools import create_dataclass if TYPE_CHECKING: @@ -21,15 +21,15 @@ logger = logging.getLogger(__name__) -class GenerateAdminTechLogError(ManagerError): +class GenerateAdminTechLogError(CatalystwanException): pass -class DownloadAdminTechLogError(ManagerError): +class DownloadAdminTechLogError(CatalystwanException): pass -class RequestTokenIdNotFound(ManagerError): +class RequestTokenIdNotFound(CatalystwanException): pass diff --git a/catalystwan/api/administration.py b/catalystwan/api/administration.py index 9fad65a18..4a7076c42 100644 --- a/catalystwan/api/administration.py +++ b/catalystwan/api/administration.py @@ -31,7 +31,7 @@ UserRole, UserUpdateRequest, ) -from catalystwan.exceptions import CatalystwanDeprecationWarning, InvalidOperationError +from catalystwan.exceptions import CatalystwanDeprecationWarning, CatalystwanException from catalystwan.typed_list import DataSequence from catalystwan.utils.creation_tools import asdict, create_dataclass @@ -393,7 +393,7 @@ def update(self, payload: Union[Organization, Certificate, Password, Vbond]) -> elif isinstance(payload, Vbond): response = self.__update_vbond(json_payload) else: - raise InvalidOperationError(f"Not supported payload type: {type(payload).__name__}") + raise CatalystwanException(f"Not supported payload type: {type(payload).__name__}") return True if response.status_code == HTTPStatus.OK else False diff --git a/catalystwan/api/basic_api.py b/catalystwan/api/basic_api.py index b94e86e63..39da0506b 100644 --- a/catalystwan/api/basic_api.py +++ b/catalystwan/api/basic_api.py @@ -9,7 +9,7 @@ from catalystwan.dataclasses import BfdSessionData, Connection, Device, WanInterface from catalystwan.endpoints.real_time_monitoring.reboot_history import RebootEntry -from catalystwan.exceptions import InvalidOperationError +from catalystwan.exceptions import CatalystwanException from catalystwan.typed_list import DataSequence from catalystwan.utils.creation_tools import create_dataclass from catalystwan.utils.operation_status import OperationStatus @@ -128,7 +128,7 @@ def wait_for_state(): if response.get("id"): action_id = response["id"] else: - raise InvalidOperationError("Failed to push edges list certificates") + raise CatalystwanException("Failed to push edges list certificates") return True if wait_for_state() else False diff --git a/catalystwan/api/config_device_inventory_api.py b/catalystwan/api/config_device_inventory_api.py index 5ca722d8a..cf6d6fd5d 100644 --- a/catalystwan/api/config_device_inventory_api.py +++ b/catalystwan/api/config_device_inventory_api.py @@ -29,11 +29,11 @@ def unlock(self, device_uuid: str, device_type: str, device_details: list) -> Ta devices = [] for device_detail in device_details: unlock_device_detail = UnlockDeviceDetail( - deviceId=device_detail["deviceId"], deviceIP=device_detail["deviceIP"] + device_id=device_detail["deviceId"], device_ip=device_detail["deviceIP"] ) devices.append(unlock_device_detail) - payload = DeviceUnlockPayload(deviceType=device_type, devices=devices) + payload = DeviceUnlockPayload(device_type=device_type, devices=devices) task_id = self.endpoint.unlock(device_uuid=device_uuid, payload=payload).parentTaskId return Task(self.session, task_id=task_id) @@ -41,7 +41,7 @@ def unlock(self, device_uuid: str, device_type: str, device_details: list) -> Ta def generate_bootstrap_cfg( self, device_uuid: UUID, - configtype: ConfigType = ConfigType.CLOUDINIT, + configtype: ConfigType = "cloudinit", incl_def_root_cert: bool = False, version: str = "v1", ) -> BoostrapConfigurationDetails: diff --git a/catalystwan/api/feature_profile_api.py b/catalystwan/api/feature_profile_api.py index 820cd4e79..abdf84871 100644 --- a/catalystwan/api/feature_profile_api.py +++ b/catalystwan/api/feature_profile_api.py @@ -1,21 +1,56 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Protocol +from typing import TYPE_CHECKING, Any, Protocol, Type, Union, overload +from uuid import UUID + +from catalystwan.typed_list import DataSequence if TYPE_CHECKING: from catalystwan.session import ManagerSession from catalystwan.api.parcel_api import SDRoutingFullConfigParcelAPI +from catalystwan.endpoints.configuration.feature_profile.sdwan.policy_object import PolicyObjectFeatureProfile from catalystwan.endpoints.configuration_feature_profile import SDRoutingConfigurationFeatureProfile from catalystwan.models.configuration.feature_profile.common import ( FeatureProfileCreationPayload, FeatureProfileCreationResponse, + Parcel, + ParcelCreationResponse, +) +from catalystwan.models.configuration.feature_profile.sdwan.policy_object import ( + POLICY_OBJECT_PAYLOAD_ENDPOINT_MAPPING, + AnyPolicyObjectParcel, + ApplicationListParcel, + AppProbeParcel, + ColorParcel, + DataPrefixParcel, + ExpandedCommunityParcel, + FowardingClassParcel, + FQDNDomainParcel, + GeoLocationListParcel, + IPSSignatureParcel, + IPv6DataPrefixParcel, + IPv6PrefixListParcel, + LocalDomainParcel, + PolicierParcel, + PreferredColorGroupParcel, + PrefixListParcel, + ProtocolListParcel, + SecurityApplicationListParcel, + SecurityDataPrefixParcel, + SecurityPortParcel, + SecurityZoneListParcel, + StandardCommunityParcel, + TlocParcel, + URLAllowParcel, + URLBlockParcel, ) class SDRoutingFeatureProfilesAPI: def __init__(self, session: ManagerSession): self.cli = SDRoutingCLIFeatureProfileAPI(session=session) + self.policy_object = PolicyObjectFeatureProfileAPI(session=session) class FeatureProfileAPI(Protocol): @@ -66,3 +101,379 @@ def delete(self, fp_id: str) -> None: Deletes CLI feature-profile """ self.endpoint.delete_cli_feature_profile(cli_fp_id=fp_id) + + +class PolicyObjectFeatureProfileAPI: + """ + SDWAN Feature Profile Policy Object APIs + """ + + def __init__(self, session: ManagerSession): + self.session = session + self.endpoint = PolicyObjectFeatureProfile(session) + + @overload + def get(self, profile_id: UUID, parcel_type: Type[ApplicationListParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[AppProbeParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[ColorParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[DataPrefixParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[ExpandedCommunityParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[FowardingClassParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[FQDNDomainParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[GeoLocationListParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[IPSSignatureParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[IPv6DataPrefixParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[IPv6PrefixListParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[LocalDomainParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[PolicierParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[PreferredColorGroupParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[PrefixListParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[ProtocolListParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[SecurityApplicationListParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[SecurityDataPrefixParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[SecurityPortParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[SecurityZoneListParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[StandardCommunityParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[TlocParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[URLAllowParcel]) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[URLBlockParcel]) -> DataSequence[Parcel[Any]]: + ... + + # get by id + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[ApplicationListParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[AppProbeParcel], parcel_id: UUID) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[ColorParcel], parcel_id: UUID) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[DataPrefixParcel], parcel_id: UUID) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[ExpandedCommunityParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[FowardingClassParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[FQDNDomainParcel], parcel_id: UUID) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[GeoLocationListParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[IPSSignatureParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[IPv6DataPrefixParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[IPv6PrefixListParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[LocalDomainParcel], parcel_id: UUID) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[PolicierParcel], parcel_id: UUID) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[PreferredColorGroupParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[PrefixListParcel], parcel_id: UUID) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[ProtocolListParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[SecurityApplicationListParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[SecurityDataPrefixParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[SecurityPortParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[SecurityZoneListParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get( + self, profile_id: UUID, parcel_type: Type[StandardCommunityParcel], parcel_id: UUID + ) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[TlocParcel], parcel_id: UUID) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[URLAllowParcel], parcel_id: UUID) -> DataSequence[Parcel[Any]]: + ... + + @overload + def get(self, profile_id: UUID, parcel_type: Type[URLBlockParcel], parcel_id: UUID) -> DataSequence[Parcel[Any]]: + ... + + def get( + self, + profile_id: UUID, + parcel_type: Type[AnyPolicyObjectParcel], + parcel_id: Union[UUID, None] = None, + ) -> DataSequence[Parcel[Any]]: + """ + Get all Policy Objects for selected profile_id and selected type or get one Policy Object given parcel id + """ + + policy_object_list_type = POLICY_OBJECT_PAYLOAD_ENDPOINT_MAPPING[parcel_type] + if not parcel_id: + return self.endpoint.get_all(profile_id=profile_id, policy_object_list_type=policy_object_list_type) + parcel = self.endpoint.get_by_id( + profile_id=profile_id, policy_object_list_type=policy_object_list_type, list_object_id=parcel_id + ) + return DataSequence(Parcel, [parcel]) + + def create(self, profile_id: UUID, payload: AnyPolicyObjectParcel) -> ParcelCreationResponse: + """ + Create Policy Object for selected profile_id based on payload type + """ + + policy_object_list_type = POLICY_OBJECT_PAYLOAD_ENDPOINT_MAPPING[type(payload)] + return self.endpoint.create( + profile_id=profile_id, policy_object_list_type=policy_object_list_type, payload=payload + ) + + def update(self, profile_id: UUID, payload: AnyPolicyObjectParcel, list_object_id: UUID): + """ + Update Policy Object for selected profile_id based on payload type + """ + + policy_type = POLICY_OBJECT_PAYLOAD_ENDPOINT_MAPPING[type(payload)] + return self.endpoint.update( + profile_id=profile_id, policy_object_list_type=policy_type, list_object_id=list_object_id, payload=payload + ) + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[ApplicationListParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[AppProbeParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[ColorParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[DataPrefixParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[ExpandedCommunityParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[FowardingClassParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[FQDNDomainParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[GeoLocationListParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[IPSSignatureParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[IPv6DataPrefixParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[IPv6PrefixListParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[LocalDomainParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[PolicierParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[PreferredColorGroupParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[PrefixListParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[ProtocolListParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[SecurityApplicationListParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[SecurityDataPrefixParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[SecurityPortParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[SecurityZoneListParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[StandardCommunityParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[TlocParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[URLAllowParcel], list_object_id: UUID) -> None: + ... + + @overload + def delete(self, profile_id: UUID, parcel_type: Type[URLBlockParcel], list_object_id: UUID) -> None: + ... + + def delete(self, profile_id: UUID, parcel_type: Type[AnyPolicyObjectParcel], list_object_id: UUID) -> None: + """ + Delete Policy Object for selected profile_id based on payload type + """ + + policy_object_list_type = POLICY_OBJECT_PAYLOAD_ENDPOINT_MAPPING[parcel_type] + return self.endpoint.delete( + profile_id=profile_id, policy_object_list_type=policy_object_list_type, list_object_id=list_object_id + ) diff --git a/catalystwan/api/mtt_aaa_api.py b/catalystwan/api/mtt_aaa_api.py index 6dd6778f5..e196fecd8 100644 --- a/catalystwan/api/mtt_aaa_api.py +++ b/catalystwan/api/mtt_aaa_api.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING from catalystwan.dataclasses import TenantAAA, TenantRadiusServer, TenantTacacsServer -from catalystwan.exceptions import ManagerError +from catalystwan.exceptions import CatalystwanException from catalystwan.utils.creation_tools import asdict, create_dataclass if TYPE_CHECKING: @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) -class AAAConfigNotPresent(ManagerError): +class AAAConfigNotPresent(CatalystwanException): pass diff --git a/catalystwan/api/template_api.py b/catalystwan/api/template_api.py index 1255a0c5d..4fa20e0ea 100644 --- a/catalystwan/api/template_api.py +++ b/catalystwan/api/template_api.py @@ -42,6 +42,7 @@ from catalystwan.typed_list import DataSequence from catalystwan.utils.device_model import DeviceModel from catalystwan.utils.dict import merge +from catalystwan.utils.pydantic_field import get_extra_field from catalystwan.utils.template_type import TemplateType if TYPE_CHECKING: @@ -381,7 +382,7 @@ def _edit_feature_template(self, template: FeatureTemplate, data: FeatureTemplat if self.is_created_by_generator(template): debug = False schema = self.get_feature_template_schema(template, debug) - payload = self.generate_feature_template_payload(template, schema, debug).dict(by_alias=True) + payload = self.generate_feature_template_payload(template, schema, debug).model_dump(by_alias=True) else: payload = json.loads(template.generate_payload(self.session)) @@ -540,7 +541,7 @@ def create_by_generator(self, template: FeatureTemplate, debug: bool) -> str: payload = self.generate_feature_template_payload(template, schema, debug) endpoint = "/dataservice/template/feature" - response = self.session.post(endpoint, json=payload.dict(by_alias=True, exclude_none=True)) + response = self.session.post(endpoint, json=payload.model_dump(by_alias=True, exclude_none=True)) return response.json()["templateId"] @@ -565,12 +566,14 @@ def generate_feature_template_payload( if field.key in template.device_specific_variables: value = template.device_specific_variables[field.key] else: - for field_name, field_value in template.__fields__.items(): - if field.dataPath == field_value.field_info.extra.get("data_path", []) and ( # type: ignore - field.key == field_value.alias - or field.key == field_value.field_info.extra.get("vmanage_key") # type: ignore + for field_name, field_value in template.model_fields.items(): + data_path = get_extra_field(field_value, "data_path", default=[]) + vmanage_key = get_extra_field(field_value, "vmanage_key") + if field.dataPath == data_path and ( # type: ignore + (field.key == field_value.alias or field.key == field_name) + or field.key == vmanage_key # type: ignore ): - priority_order = field_value.field_info.extra.get("priority_order") # type: ignore + priority_order = get_extra_field(field_value, "priority_order") # type: ignore value = getattr(template, field_name) break if value is None: @@ -581,7 +584,7 @@ def generate_feature_template_payload( if debug: with open(f"payload_{template.type}.json", "w") as f: - f.write(json.dumps(payload.dict(by_alias=True), indent=4)) + f.write(json.dumps(payload.model_dump(by_alias=True), indent=4)) return payload diff --git a/catalystwan/api/templates/device_template/device_template.py b/catalystwan/api/templates/device_template/device_template.py index 811f716e9..fe13b7c10 100644 --- a/catalystwan/api/templates/device_template/device_template.py +++ b/catalystwan/api/templates/device_template/device_template.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Final, List from jinja2 import DebugUndefined, Environment, FileSystemLoader, meta # type: ignore -from pydantic.v1 import BaseModel, Field, validator +from pydantic import BaseModel, ConfigDict, Field, field_validator from catalystwan.utils.device_model import DeviceModel @@ -16,8 +16,7 @@ class GeneralTemplate(BaseModel): - class Config: - arbitrary_types_allowed = True + model_config = ConfigDict(arbitrary_types_allowed=True) name: str = "" subTemplates: List[GeneralTemplate] = [] @@ -59,7 +58,7 @@ def generate_payload(self) -> str: undefined=DebugUndefined, ) template = env.get_template(self.payload_path.name) - output = template.render(self.dict()) + output = template.render(self.model_dump()) ast = env.parse(output) if meta.find_undeclared_variables(ast): @@ -67,7 +66,8 @@ def generate_payload(self) -> str: raise Exception("There are undeclared variables.") return output - @validator("general_templates", pre=True) + @field_validator("general_templates", mode="before") + @classmethod def parse_templates(cls, value): output = [] for template in value: @@ -85,9 +85,7 @@ def get(self, name: str, session: ManagerSession) -> DeviceTemplate: resp = session.get(f"dataservice/template/device/object/{device_template.id}").json() return DeviceTemplate(**resp) - class Config: - allow_population_by_field_name = True - use_enum_values = True + model_config = ConfigDict(populate_by_name=True, use_enum_values=True) class DeviceSpecificValue(BaseModel): diff --git a/catalystwan/api/templates/device_variable.py b/catalystwan/api/templates/device_variable.py index 915b32428..c37b2e456 100644 --- a/catalystwan/api/templates/device_variable.py +++ b/catalystwan/api/templates/device_variable.py @@ -1,4 +1,4 @@ -from pydantic.v1 import BaseModel +from pydantic import BaseModel class DeviceVariable(BaseModel): diff --git a/catalystwan/api/templates/feature_template.py b/catalystwan/api/templates/feature_template.py index bb78fe4e6..357f919eb 100644 --- a/catalystwan/api/templates/feature_template.py +++ b/catalystwan/api/templates/feature_template.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Dict, List, cast from jinja2 import DebugUndefined, Environment, FileSystemLoader, meta # type: ignore -from pydantic.v1 import BaseModel, root_validator +from pydantic import BaseModel, model_validator from catalystwan.api.templates.device_variable import DeviceVariable from catalystwan.utils.device_model import DeviceModel @@ -29,7 +29,7 @@ def generate_payload(self, session: ManagerSession) -> str: undefined=DebugUndefined, ) template = env.get_template(self.payload_path.name) - output = template.render(self.dict()) + output = template.render(self.model_dump()) ast = env.parse(output) if meta.find_undeclared_variables(ast): @@ -49,7 +49,8 @@ def payload_path(self) -> Path: def type(self) -> str: raise NotImplementedError() - @root_validator(pre=True) + @model_validator(mode="before") + @classmethod def remove_device_variables(cls, values): if "device_specific_variables" not in values: values["device_specific_variables"] = {} @@ -59,7 +60,7 @@ def remove_device_variables(cls, values): for key, value in values.items(): if isinstance(value, DeviceVariable): to_delete[key] = value - field_key = cls.__fields__[key].field_info.extra.get("vmanage_key", cls.__fields__[key].alias) + field_key = cls.model_fields[key].json_schema_extra.get("vmanage_key", cls.model_fields[key].alias) values["device_specific_variables"][field_key] = DeviceVariable(name=value.name) for var in to_delete: diff --git a/catalystwan/api/templates/feature_template_field.py b/catalystwan/api/templates/feature_template_field.py index ce34989a9..f7f813b71 100644 --- a/catalystwan/api/templates/feature_template_field.py +++ b/catalystwan/api/templates/feature_template_field.py @@ -3,12 +3,12 @@ from enum import Enum from typing import Any, Dict, List, Optional -from pydantic.v1 import BaseModel, Field, validator -from pydantic.v1.fields import ModelField # type: ignore +from pydantic import BaseModel, Field, field_validator from catalystwan.api.templates.device_variable import DeviceVariable from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.dict import merge +from catalystwan.utils.pydantic_field import get_extra_field class FeatureTemplateOptionType(str, Enum): @@ -73,7 +73,8 @@ class FeatureTemplateField(BaseModel): primaryKeys: List[str] = [] children: List[FeatureTemplateField] = [] - @validator("dataType", pre=True) + @field_validator("dataType", mode="before") + @classmethod def convert_data_type_to_dict(cls, value): if isinstance(value, str): return {"type": value} @@ -110,30 +111,34 @@ def nest_value_in_output(value: Any) -> dict: vipObjectType=self.objectType, vipVariableName=value.name, ) - return nest_value_in_output(vip_variable.dict(by_alias=True, exclude_none=True)) + return nest_value_in_output(vip_variable.model_dump(by_alias=True, exclude_none=True)) else: if value is not None: output["vipType"] = vip_type or FeatureTemplateOptionType.CONSTANT.value if self.children: children_output = [] - for obj in value: # obj is User, atomic value. Loop every child child_payload: dict = {} for child in self.children: # Child in schema if current_path is None: current_path = [] obj: FeatureTemplate # type: ignore - model_field: ModelField = next( + model_tuple = next( filter( - lambda f: f.field_info.extra.get("data_path", []) == child.dataPath - and (f.alias == child.key or f.field_info.extra.get("vmanage_key") == child.key), - obj.__fields__.values(), + lambda f: get_extra_field(f[1], "data_path", []) == child.dataPath + and ( + f[1].alias == child.key + or get_extra_field(f[1], "vmanage_key") == child.key + or f[0] == child.key + ), + obj.model_fields.items(), ) ) - obj_value = getattr(obj, model_field.name) - po = model_field.field_info.extra.get("priority_order") - vip_type = model_field.field_info.extra.get("vip_type") + model_field = model_tuple[1] + obj_value = getattr(obj, model_tuple[0]) + po = get_extra_field(model_field, "priority_order") + vip_type = get_extra_field(model_field, "vip_type") merge( child_payload, child.payload_scheme( diff --git a/catalystwan/api/templates/feature_template_payload.py b/catalystwan/api/templates/feature_template_payload.py index 2697aa731..7cdc27174 100644 --- a/catalystwan/api/templates/feature_template_payload.py +++ b/catalystwan/api/templates/feature_template_payload.py @@ -1,11 +1,10 @@ from typing import Any, List -from pydantic.v1 import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field class FeatureTemplatePayload(BaseModel): - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) name: str = Field(alias="templateName") description: str = Field(alias="templateDescription") diff --git a/catalystwan/api/templates/models/cisco_aaa_model.py b/catalystwan/api/templates/models/cisco_aaa_model.py index ee54f55cf..a325cc4ba 100644 --- a/catalystwan/api/templates/models/cisco_aaa_model.py +++ b/catalystwan/api/templates/models/cisco_aaa_model.py @@ -2,42 +2,39 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate class User(BaseModel): name: str - password: Optional[str] - secret: Optional[str] - privilege: Optional[str] - pubkey_chain: List[str] = Field(default=[], vmanage_key="pubkey-chain", vip_type="ignore") + password: Optional[str] = None + secret: Optional[str] = None + privilege: Optional[str] = None + pubkey_chain: List[str] = Field(default=[], json_schema_extra={"vmanage_key": "pubkey-chain", "vip_type": "ignore"}) class RadiusServer(BaseModel): - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) address: str - auth_port: int = Field(vmanage_key="auth-port", default=1812) - acct_port: int = Field(vmanage_key="acct-port", default=1813) + auth_port: int = Field(default=1812, json_schema_extra={"vmanage_key": "auth-port"}) + acct_port: int = Field(default=1813, json_schema_extra={"vmanage_key": "acct-port"}) timeout: int = Field(default=5) retransmit: int = 3 key: str - secret_key: Optional[str] = Field(vmanage_key="secret-key", default=None) - key_enum: Optional[str] = Field(vmanage_key="key-enum", default=None) - key_type: Optional[str] = Field(vmanage_key="key-type", default=None) + secret_key: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "secret-key"}) + key_enum: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "key-enum"}) + key_type: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "key-type"}) class RadiusGroup(BaseModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) - group_name: str = Field(vmanage_key="group-name") - vpn: Optional[int] - source_interface: Optional[str] = Field(vmanage_key="source-interface") + group_name: str = Field(json_schema_extra={"vmanage_key": "group-name"}) + vpn: Optional[int] = None + source_interface: Optional[str] = Field(json_schema_extra={"vmanage_key": "source-interface"}) server: List[RadiusServer] = [] @@ -48,40 +45,38 @@ class DomainStripping(str, Enum): class TacacsServer(BaseModel): - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) address: str port: int = 49 timeout: int = Field(default=5) key: str - secret_key: Optional[str] = Field(vmanage_key="secret-key", default=None) - key_enum: Optional[str] = Field(vmanage_key="key-enum", default=None) + secret_key: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "secret-key"}) + key_enum: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "key-enum"}) class TacacsGroup(BaseModel): - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) - group_name: str = Field(vmanage_key="group-name") + group_name: str = Field(json_schema_extra={"vmanage_key": "group-name"}) vpn: int = 0 - source_interface: Optional[str] = Field(vmanage_key="source-interface", default=None) + source_interface: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "source-interface"}) server: List[TacacsServer] = [] class CiscoAAAModel(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) - user: Optional[List[User]] - authentication_group: bool = Field(vmanage_key="authentication_group", default=False) + user: Optional[List[User]] = None + authentication_group: bool = Field(default=False, json_schema_extra={"vmanage_key": "authentication_group"}) accounting_group: bool = True radius: Optional[List[RadiusGroup]] = None - domain_stripping: Optional[DomainStripping] = Field(vmanage_key="domain-stripping", default=None) + domain_stripping: Optional[DomainStripping] = Field( + default=None, json_schema_extra={"vmanage_key": "domain-stripping"} + ) port: int = 1700 tacacs: Optional[List[TacacsGroup]] = None - server_auth_order: str = Field(vmanage_key="server-auth-order", default="local") + server_auth_order: str = Field(default="local", json_schema_extra={"vmanage_key": "server-auth-order"}) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cedge_aaa" diff --git a/catalystwan/api/templates/models/cisco_banner_model.py b/catalystwan/api/templates/models/cisco_banner_model.py index 4bc2ac398..4060c633b 100644 --- a/catalystwan/api/templates/models/cisco_banner_model.py +++ b/catalystwan/api/templates/models/cisco_banner_model.py @@ -1,18 +1,16 @@ from pathlib import Path from typing import ClassVar, Optional -from pydantic.v1 import Field +from pydantic import ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate class CiscoBannerModel(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) - login_banner: Optional[str] = Field(vmanage_key="login") - motd_banner: Optional[str] = Field(vmanage_key="motd") + login_banner: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "login"}) + motd_banner: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "motd"}) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_banner" diff --git a/catalystwan/api/templates/models/cisco_bfd_model.py b/catalystwan/api/templates/models/cisco_bfd_model.py index bd150c8af..837871240 100644 --- a/catalystwan/api/templates/models/cisco_bfd_model.py +++ b/catalystwan/api/templates/models/cisco_bfd_model.py @@ -2,7 +2,7 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import Field +from pydantic import ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.pydantic_validators import ConvertBoolToStringModel @@ -41,26 +41,24 @@ class ColorType(str, Enum): class Color(ConvertBoolToStringModel): color: ColorType - hello_interval: Optional[int] = Field(DEFAULT_BFD_HELLO_INTERVAL, vmanage_key="hello-interval") + hello_interval: Optional[int] = Field( + DEFAULT_BFD_HELLO_INTERVAL, json_schema_extra={"vmanage_key": "hello-interval"} + ) multiplier: Optional[int] = DEFAULT_BFD_COLOR_MULTIPLIER - pmtu_discovery: Optional[bool] = Field(True, vmanage_key="pmtu-discovery") + pmtu_discovery: Optional[bool] = Field(True, json_schema_extra={"vmanage_key": "pmtu-discovery"}) dscp: Optional[int] = DEFAULT_BFD_DSCP - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class CiscoBFDModel(FeatureTemplate, ConvertBoolToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) - multiplier: Optional[int] = Field(DEFAULT_BFD_MULTIPLIER, data_path=["app-route"]) + multiplier: Optional[int] = Field(DEFAULT_BFD_MULTIPLIER, json_schema_extra={"data_path": ["app-route"]}) poll_interval: Optional[int] = Field( - DEFAULT_BFD_POLL_INTERVAL, vmanage_key="poll-interval", data_path=["app-route"] + DEFAULT_BFD_POLL_INTERVAL, json_schema_extra={"vmanage_key": "poll-interval", "data_path": ["app-route"]} ) - default_dscp: Optional[int] = Field(DEFAULT_BFD_DSCP, vmanage_key="default-dscp") - color: Optional[List[Color]] + default_dscp: Optional[int] = Field(DEFAULT_BFD_DSCP, json_schema_extra={"vmanage_key": "default-dscp"}) + color: Optional[List[Color]] = None payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_bfd" diff --git a/catalystwan/api/templates/models/cisco_bgp_model.py b/catalystwan/api/templates/models/cisco_bgp_model.py index 8621f0f7e..9f40b651a 100644 --- a/catalystwan/api/templates/models/cisco_bgp_model.py +++ b/catalystwan/api/templates/models/cisco_bgp_model.py @@ -2,48 +2,38 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import BaseModel, Field, validator +from pydantic import BaseModel, ConfigDict, Field, field_validator from catalystwan.api.templates.feature_template import FeatureTemplate class Export(BaseModel): - asn_ip: str = Field(vmanage_key="asn-ip") - - class Config: - allow_population_by_field_name = True + asn_ip: str = Field(json_schema_extra={"vmanage_key": "asn-ip"}) + model_config = ConfigDict(populate_by_name=True) class Import(BaseModel): - asn_ip: str = Field(vmanage_key="asn-ip") - - class Config: - allow_population_by_field_name = True + asn_ip: str = Field(json_schema_extra={"vmanage_key": "asn-ip"}) + model_config = ConfigDict(populate_by_name=True) class RouteTargetIpv4(BaseModel): - vpn_id: int = Field(vmanage_key="vpn-id") + vpn_id: int = Field(json_schema_extra={"vmanage_key": "vpn-id"}) export: List[Export] - import_: List[Import] = Field(vmanage_key="import") - - class Config: - allow_population_by_field_name = True + import_: List[Import] = Field(json_schema_extra={"vmanage_key": "import"}) + model_config = ConfigDict(populate_by_name=True) class RouteTargetIpv6(BaseModel): - vpn_id: int = Field(vmanage_key="vpn-id") + vpn_id: int = Field(json_schema_extra={"vmanage_key": "vpn-id"}) export: List[Export] - import_: List[Import] = Field(vmanage_key="import") - - class Config: - allow_population_by_field_name = True + import_: List[Import] = Field(json_schema_extra={"vmanage_key": "import"}) + model_config = ConfigDict(populate_by_name=True) class MplsInterface(BaseModel): - if_name: Optional[str] = Field(vmanage_key="if-name") - - class Config: - allow_population_by_field_name = True + if_name: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "if-name"}) + model_config = ConfigDict(populate_by_name=True) class AddressFamilyType(str, Enum): @@ -52,13 +42,12 @@ class AddressFamilyType(str, Enum): class AggregateAddress(BaseModel): prefix: str - as_set: Optional[bool] = Field(vmanage_key="as-set") - summary_only: Optional[bool] = Field(vmanage_key="summary-only") + as_set: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "as-set"}) + summary_only: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "summary-only"}) + model_config = ConfigDict(populate_by_name=True) - class Config: - allow_population_by_field_name = True - - @validator("as_set", "summary_only") + @field_validator("as_set", "summary_only") + @classmethod def cast_to_str(cls, value): if value is not None: return str(value).lower() @@ -66,11 +55,9 @@ def cast_to_str(cls, value): class Ipv6AggregateAddress(BaseModel): prefix: str - as_set: Optional[bool] = Field(False, vmanage_key="as-set") - summary_only: Optional[bool] = Field(False, vmanage_key="summary-only") - - class Config: - allow_population_by_field_name = True + as_set: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "as-set"}) + summary_only: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "summary-only"}) + model_config = ConfigDict(populate_by_name=True) class Network(BaseModel): @@ -93,28 +80,31 @@ class Protocol(str, Enum): class Redistribute(BaseModel): protocol: Protocol - route_policy: Optional[str] = Field(vmanage_key="route-policy") - - class Config: - allow_population_by_field_name = True + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + model_config = ConfigDict(populate_by_name=True) class AddressFamily(BaseModel): - family_type: AddressFamilyType = Field(vmanage_key="family-type") - aggregate_address: Optional[List[AggregateAddress]] = Field(vmanage_key="aggregate-address") - ipv6_aggregate_address: Optional[List[Ipv6AggregateAddress]] = Field(vmanage_key="ipv6-aggregate-address") - network: Optional[List[Network]] - ipv6_network: Optional[List[Ipv6Network]] = Field(vmanage_key="ipv6-network") - 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"], vmanage_key="name") - filter: Optional[bool] = Field(data_path=["table-map"]) - redistribute: Optional[List[Redistribute]] - - class Config: - allow_population_by_field_name = True - - @validator("originate", "filter") + family_type: AddressFamilyType = Field(json_schema_extra={"vmanage_key": "family-type"}) + aggregate_address: Optional[List[AggregateAddress]] = Field( + default=None, json_schema_extra={"vmanage_key": "aggregate-address"} + ) + ipv6_aggregate_address: Optional[List[Ipv6AggregateAddress]] = Field( + default=None, json_schema_extra={"vmanage_key": "ipv6-aggregate-address"} + ) + network: Optional[List[Network]] = None + ipv6_network: Optional[List[Ipv6Network]] = Field(default=None, json_schema_extra={"vmanage_key": "ipv6-network"}) + paths: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["maximum-paths"]}) + originate: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["default-information"]}) + policy_name: Optional[str] = Field( + default=None, json_schema_extra={"data_path": ["table-map"], "vmanage_key": "name"} + ) + filter: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["table-map"]}) + redistribute: Optional[List[Redistribute]] = None + model_config = ConfigDict(populate_by_name=True) + + @field_validator("originate", "filter") + @classmethod def cast_to_str(cls, value): if value is not None: return str(value).lower() @@ -133,47 +123,51 @@ class Direction(str, Enum): class RoutePolicy(BaseModel): direction: Direction - pol_name: str = Field(vmanage_key="pol-name") - - class Config: - allow_population_by_field_name = True + pol_name: str = Field(json_schema_extra={"vmanage_key": "pol-name"}) + model_config = ConfigDict(populate_by_name=True) class NeighborAddressFamily(BaseModel): - family_type: NeighborFamilyType = Field(vmanage_key="family-type") - prefix_num: Optional[int] = Field(data_path=["maximum-prefixes"], vmanage_key="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"], vmanage_key="warning-only") - route_policy: Optional[List[RoutePolicy]] = Field(vmanage_key="route-policy") - - class Config: - allow_population_by_field_name = True + family_type: NeighborFamilyType = Field(json_schema_extra={"vmanage_key": "family-type"}) + prefix_num: Optional[int] = Field( + default=None, json_schema_extra={"data_path": ["maximum-prefixes"], "vmanage_key": "prefix-num"} + ) + threshold: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["maximum-prefixes"]}) + restart: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["maximum-prefixes"]}) + warning_only: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["maximum-prefixes"], "vmanage_key": "warning-only"} + ) + route_policy: Optional[List[RoutePolicy]] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + model_config = ConfigDict(populate_by_name=True) class Neighbor(BaseModel): address: str - description: Optional[str] - shutdown: Optional[bool] - remote_as: int = Field(vmanage_key="remote-as") - keepalive: Optional[int] = Field(data_path=["timers"]) - holdtime: Optional[int] = Field(data_path=["timers"]) - if_name: Optional[str] = Field(data_path=["update-source"], vmanage_key="if-name") - next_hop_self: Optional[bool] = Field(vmanage_key="next-hop-self") - send_community: Optional[bool] = Field(vmanage_key="send-community") - send_ext_community: Optional[bool] = Field(vmanage_key="send-ext-community") - ebgp_multihop: Optional[int] = Field(vmanage_key="ebgp-multihop") - password: Optional[str] - send_label: Optional[bool] = Field(vmanage_key="send-label") - send_label_explicit: Optional[bool] = Field(vmanage_key="send-label-explicit") - as_override: Optional[bool] = Field(vmanage_key="as-override") - as_number: Optional[int] = Field(data_path=["allowas-in"], vmanage_key="as-number") - address_family: Optional[List[NeighborAddressFamily]] = Field(vmanage_key="address-family") - - class Config: - allow_population_by_field_name = True - - @validator( + description: Optional[str] = None + shutdown: Optional[bool] = None + remote_as: int = Field(json_schema_extra={"vmanage_key": "remote-as"}) + keepalive: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["timers"]}) + holdtime: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["timers"]}) + if_name: Optional[str] = Field( + default=None, json_schema_extra={"data_path": ["update-source"], "vmanage_key": "if-name"} + ) + next_hop_self: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "next-hop-self"}) + send_community: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "send-community"}) + send_ext_community: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "send-ext-community"}) + ebgp_multihop: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "ebgp-multihop"}) + password: Optional[str] = None + send_label: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "send-label"}) + send_label_explicit: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "send-label-explicit"}) + as_override: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "as-override"}) + as_number: Optional[int] = Field( + default=None, json_schema_extra={"data_path": ["allowas-in"], "vmanage_key": "as-number"} + ) + address_family: Optional[List[NeighborAddressFamily]] = Field( + default=None, json_schema_extra={"vmanage_key": "address-family"} + ) + model_config = ConfigDict(populate_by_name=True) + + @field_validator( "shutdown", "next_hop_self", "send_community", @@ -182,6 +176,7 @@ class Config: "send_label_explicit", "as_override", ) + @classmethod def cast_to_str(cls, value): if value is not None: return str(value).lower() @@ -192,40 +187,46 @@ class IPv6NeighborFamilyType(str, Enum): class IPv6NeighborAddressFamily(BaseModel): - family_type: IPv6NeighborFamilyType = Field(vmanage_key="family-type") - prefix_num: Optional[int] = Field(0, data_path=["maximum-prefixes"], vmanage_key="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"], vmanage_key="warning-only") - route_policy: Optional[List[RoutePolicy]] = Field(vmanage_key="route-policy") - - class Config: - allow_population_by_field_name = True + family_type: IPv6NeighborFamilyType = Field(json_schema_extra={"vmanage_key": "family-type"}) + prefix_num: Optional[int] = Field( + 0, json_schema_extra={"data_path": ["maximum-prefixes"], "vmanage_key": "prefix-num"} + ) + threshold: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["maximum-prefixes"]}) + restart: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["maximum-prefixes"]}) + warning_only: Optional[bool] = Field( + False, json_schema_extra={"data_path": ["maximum-prefixes"], "vmanage_key": "warning-only"} + ) + route_policy: Optional[List[RoutePolicy]] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + model_config = ConfigDict(populate_by_name=True) class Ipv6Neighbor(BaseModel): address: str - description: Optional[str] - shutdown: Optional[bool] - remote_as: int = Field(vmanage_key="remote-as") - keepalive: Optional[int] = Field(data_path=["timers"]) - holdtime: Optional[int] = Field(data_path=["timers"]) - if_name: Optional[str] = Field(data_path=["update-source"], vmanage_key="if-name") - next_hop_self: Optional[bool] = Field(False, vmanage_key="next-hop-self") - send_community: Optional[bool] = Field(True, vmanage_key="send-community") - send_ext_community: Optional[bool] = Field(True, vmanage_key="send-ext-community") - ebgp_multihop: Optional[int] = Field(1, vmanage_key="ebgp-multihop") - password: Optional[str] - send_label: Optional[bool] = Field(False, vmanage_key="send-label") - send_label_explicit: Optional[bool] = Field(False, vmanage_key="send-label-explicit") - as_override: Optional[bool] = Field(False, vmanage_key="as-override") - as_number: Optional[int] = Field(data_path=["allowas-in"], vmanage_key="as-number") - address_family: Optional[List[IPv6NeighborAddressFamily]] = Field(vmanage_key="address-family") - - class Config: - allow_population_by_field_name = True - - @validator( + description: Optional[str] = None + shutdown: Optional[bool] = None + remote_as: int = Field(default=None, json_schema_extra={"vmanage_key": "remote-as"}) + keepalive: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["timers"]}) + holdtime: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["timers"]}) + if_name: Optional[str] = Field( + default=None, json_schema_extra={"data_path": ["update-source"], "vmanage_key": "if-name"} + ) + next_hop_self: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "next-hop-self"}) + send_community: Optional[bool] = Field(True, json_schema_extra={"vmanage_key": "send-community"}) + send_ext_community: Optional[bool] = Field(True, json_schema_extra={"vmanage_key": "send-ext-community"}) + ebgp_multihop: Optional[int] = Field(1, json_schema_extra={"vmanage_key": "ebgp-multihop"}) + password: Optional[str] = None + send_label: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "send-label"}) + send_label_explicit: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "send-label-explicit"}) + as_override: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "as-override"}) + as_number: Optional[int] = Field( + default=None, json_schema_extra={"data_path": ["allowas-in"], "vmanage_key": "as-number"} + ) + address_family: Optional[List[IPv6NeighborAddressFamily]] = Field( + default=None, json_schema_extra={"vmanage_key": "address-family"} + ) + model_config = ConfigDict(populate_by_name=True) + + @field_validator( "shutdown", "next_hop_self", "send_community", @@ -234,42 +235,64 @@ class Config: "send_label_explicit", "as_override", ) + @classmethod def cast_to_str(cls, value): if value is not None: return str(value).lower() class CiscoBGPModel(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True - - as_num: Optional[str] = Field(data_path=["bgp"], vmanage_key="as-num") - shutdown: Optional[bool] = Field(data_path=["bgp"]) - router_id: Optional[str] = Field(data_path=["bgp"], vmanage_key="router-id") - propagate_aspath: Optional[bool] = Field(data_path=["bgp"], vmanage_key="propagate-aspath") - propagate_community: Optional[bool] = Field(data_path=["bgp"], vmanage_key="propagate-community") - route_target_ipv4: List[RouteTargetIpv4] = Field([], data_path=["bgp", "target"], vmanage_key="route-target-ipv4") - route_target_ipv6: List[RouteTargetIpv6] = Field([], data_path=["bgp", "target"], vmanage_key="route-target-ipv6") - mpls_interface: Optional[List[MplsInterface]] = Field(data_path=["bgp"], vmanage_key="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"], vmanage_key="always-compare") - deterministic: Optional[bool] = Field(data_path=["bgp", "best-path", "med"]) - missing_as_worst: Optional[bool] = Field(data_path=["bgp", "best-path", "med"], vmanage_key="missing-as-worst") - compare_router_id: Optional[bool] = Field(data_path=["bgp", "best-path"], vmanage_key="compare-router-id") - multipath_relax: Optional[bool] = Field(data_path=["bgp", "best-path", "as-path"], vmanage_key="multipath-relax") - address_family: Optional[List[AddressFamily]] = Field(data_path=["bgp"], vmanage_key="address-family") - neighbor: Optional[List[Neighbor]] = Field(data_path=["bgp"]) - ipv6_neighbor: Optional[List[Ipv6Neighbor]] = Field(data_path=["bgp"], vmanage_key="ipv6-neighbor") + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) + + as_num: Optional[str] = Field(default=None, json_schema_extra={"data_path": ["bgp"], "vmanage_key": "as-num"}) + shutdown: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["bgp"]}) + router_id: Optional[str] = Field(default=None, json_schema_extra={"data_path": ["bgp"], "vmanage_key": "router-id"}) + propagate_aspath: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["bgp"], "vmanage_key": "propagate-aspath"} + ) + propagate_community: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["bgp"], "vmanage_key": "propagate-community"} + ) + route_target_ipv4: List[RouteTargetIpv4] = Field( + [], json_schema_extra={"data_path": ["bgp", "target"], "vmanage_key": "route-target-ipv4"} + ) + route_target_ipv6: List[RouteTargetIpv6] = Field( + [], json_schema_extra={"data_path": ["bgp", "target"], "vmanage_key": "route-target-ipv6"} + ) + mpls_interface: Optional[List[MplsInterface]] = Field( + default=None, json_schema_extra={"data_path": ["bgp"], "vmanage_key": "mpls-interface"} + ) + external: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["bgp", "distance"]}) + internal: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["bgp", "distance"]}) + local: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["bgp", "distance"]}) + keepalive: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["bgp", "timers"]}) + holdtime: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["bgp", "timers"]}) + always_compare: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["bgp", "best-path", "med"], "vmanage_key": "always-compare"} + ) + deterministic: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["bgp", "best-path", "med"]}) + missing_as_worst: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["bgp", "best-path", "med"], "vmanage_key": "missing-as-worst"} + ) + compare_router_id: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["bgp", "best-path"], "vmanage_key": "compare-router-id"} + ) + multipath_relax: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["bgp", "best-path", "as-path"], "vmanage_key": "multipath-relax"} + ) + address_family: Optional[List[AddressFamily]] = Field( + default=None, json_schema_extra={"data_path": ["bgp"], "vmanage_key": "address-family"} + ) + neighbor: Optional[List[Neighbor]] = Field(default=None, json_schema_extra={"data_path": ["bgp"]}) + ipv6_neighbor: Optional[List[Ipv6Neighbor]] = Field( + default=None, json_schema_extra={"data_path": ["bgp"], "vmanage_key": "ipv6-neighbor"} + ) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_bgp" - @validator("shutdown", "deterministic", "missing_as_worst", "compare_router_id", "multipath_relax") + @field_validator("shutdown", "deterministic", "missing_as_worst", "compare_router_id", "multipath_relax") + @classmethod def cast_to_str(cls, value): if value is not None: return str(value).lower() diff --git a/catalystwan/api/templates/models/cisco_logging_model.py b/catalystwan/api/templates/models/cisco_logging_model.py index 59f748116..2fc95acde 100644 --- a/catalystwan/api/templates/models/cisco_logging_model.py +++ b/catalystwan/api/templates/models/cisco_logging_model.py @@ -2,7 +2,7 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import Field +from pydantic import ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.pydantic_validators import ConvertBoolToStringModel @@ -20,12 +20,12 @@ class AuthType(str, Enum): class TlsProfile(ConvertBoolToStringModel): profile: str - version: Optional[Version] = Field(Version.TLSV11, data_path=["tls-version"]) - auth_type: AuthType = Field(vmanage_key="auth-type") - ciphersuite_list: Optional[List] = Field(data_path=["ciphersuite"], vmanage_key="ciphersuite-list") - - class Config: - allow_population_by_field_name = True + version: Optional[Version] = Field(Version.TLSV11, json_schema_extra={"data_path": ["tls-version"]}) + auth_type: AuthType = Field(json_schema_extra={"vmanage_key": "auth-type"}) + ciphersuite_list: Optional[List] = Field( + default=None, json_schema_extra={"data_path": ["ciphersuite"], "vmanage_key": "ciphersuite-list"} + ) + model_config = ConfigDict(populate_by_name=True) class Priority(str, Enum): @@ -41,41 +41,39 @@ class Priority(str, Enum): class Server(ConvertBoolToStringModel): name: str - vpn: Optional[int] - source_interface: Optional[str] = Field(vmanage_key="source-interface") + vpn: Optional[int] = None + source_interface: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "source-interface"}) priority: Optional[Priority] = Priority.INFORMATION - enable_tls: Optional[bool] = Field(False, data_path=["tls"], vmanage_key="enable-tls") - custom_profile: Optional[bool] = Field(False, data_path=["tls", "tls-properties"], vmanage_key="custom-profile") - profile: Optional[str] = Field(data_path=["tls", "tls-properties"]) - - class Config: - allow_population_by_field_name = True + enable_tls: Optional[bool] = Field(False, json_schema_extra={"data_path": ["tls"], "vmanage_key": "enable-tls"}) + custom_profile: Optional[bool] = Field( + False, json_schema_extra={"data_path": ["tls", "tls-properties"], "vmanage_key": "custom-profile"} + ) + profile: Optional[str] = Field(default=None, json_schema_extra={"data_path": ["tls", "tls-properties"]}) + model_config = ConfigDict(populate_by_name=True) class Ipv6Server(ConvertBoolToStringModel): name: str - vpn: Optional[int] - source_interface: Optional[str] = Field(vmanage_key="source-interface") + vpn: Optional[int] = None + source_interface: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "source-interface"}) priority: Optional[Priority] = Priority.INFORMATION - enable_tls: Optional[bool] = Field(False, data_path=["tls"], vmanage_key="enable-tls") - custom_profile: Optional[bool] = Field(False, data_path=["tls", "tls-properties"], vmanage_key="custom-profile") - profile: Optional[str] = Field(data_path=["tls", "tls-properties"]) - - class Config: - allow_population_by_field_name = True + enable_tls: Optional[bool] = Field(False, json_schema_extra={"data_path": ["tls"], "vmanage_key": "enable-tls"}) + custom_profile: Optional[bool] = Field( + False, json_schema_extra={"data_path": ["tls", "tls-properties"], "vmanage_key": "custom-profile"} + ) + profile: Optional[str] = Field(default=None, json_schema_extra={"data_path": ["tls", "tls-properties"]}) + model_config = ConfigDict(populate_by_name=True) class CiscoLoggingModel(FeatureTemplate, ConvertBoolToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True - - enable: Optional[bool] = Field(data_path=["disk"]) - size: Optional[int] = Field(data_path=["disk", "file"]) - rotate: Optional[int] = Field(data_path=["disk", "file"]) - tls_profile: Optional[List[TlsProfile]] = Field(vmanage_key="tls-profile") - server: Optional[List[Server]] - ipv6_server: Optional[List[Ipv6Server]] = Field(vmanage_key="ipv6-server") + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) + + enable: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["disk"]}) + size: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["disk", "file"]}) + rotate: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["disk", "file"]}) + tls_profile: Optional[List[TlsProfile]] = Field(default=None, json_schema_extra={"vmanage_key": "tls-profile"}) + server: Optional[List[Server]] = None + ipv6_server: Optional[List[Ipv6Server]] = Field(default=None, json_schema_extra={"vmanage_key": "ipv6-server"}) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_logging" diff --git a/catalystwan/api/templates/models/cisco_ntp_model.py b/catalystwan/api/templates/models/cisco_ntp_model.py index 49bdc79a5..d26605691 100644 --- a/catalystwan/api/templates/models/cisco_ntp_model.py +++ b/catalystwan/api/templates/models/cisco_ntp_model.py @@ -1,43 +1,39 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.pydantic_validators import ConvertBoolToStringModel class Server(ConvertBoolToStringModel): - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) name: str - key: Optional[int] - vpn: Optional[int] - version: Optional[int] - source_interface: Optional[str] = Field(vmanage_key="source-interface", default=None) - prefer: Optional[bool] + key: Optional[int] = None + vpn: Optional[int] = None + version: Optional[int] = None + source_interface: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "source-interface"}) + prefer: Optional[bool] = None class Authentication(BaseModel): - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) number: int md5: str class CiscoNTPModel(FeatureTemplate, ConvertBoolToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) server: List[Server] = Field(default=[]) - authentication: Optional[List[Authentication]] = Field(data_path=["keys"]) - trusted: Optional[List[int]] = Field(data_path=["keys"]) - enable: Optional[bool] = Field(data_path=["master"]) - stratum: Optional[int] = Field(data_path=["master"]) - source: Optional[str] = Field(data_path=["master"]) + authentication: Optional[List[Authentication]] = Field(default=None, json_schema_extra={"data_path": ["keys"]}) + trusted: Optional[List[int]] = Field(default=None, json_schema_extra={"data_path": ["keys"]}) + enable: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["master"]}) + stratum: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["master"]}) + source: Optional[str] = Field(default=None, json_schema_extra={"data_path": ["master"]}) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_ntp" diff --git a/catalystwan/api/templates/models/cisco_omp_model.py b/catalystwan/api/templates/models/cisco_omp_model.py index b29b67c77..5f1cbb719 100644 --- a/catalystwan/api/templates/models/cisco_omp_model.py +++ b/catalystwan/api/templates/models/cisco_omp_model.py @@ -2,7 +2,7 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.pydantic_validators import ConvertBoolToStringModel @@ -65,31 +65,45 @@ class SiteTypes(str, Enum): class CiscoOMPModel(FeatureTemplate, ConvertBoolToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True - - graceful_restart: Optional[bool] = Field(True, vmanage_key="graceful-restart") - overlay_as: Optional[int] = Field(vmanage_key="overlay-as") - send_path_limit: Optional[int] = Field(DEFAULT_OMP_SENDPATH_LIMIT, vmanage_key="send-path-limit") - ecmp_limit: Optional[int] = Field(DEFAULT_OMP_ECMP_LIMIT, vmanage_key="ecmp-limit") + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) + + graceful_restart: Optional[bool] = Field(True, json_schema_extra={"vmanage_key": "graceful-restart"}) + overlay_as: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "overlay-as"}) + send_path_limit: Optional[int] = Field( + DEFAULT_OMP_SENDPATH_LIMIT, json_schema_extra={"vmanage_key": "send-path-limit"} + ) + ecmp_limit: Optional[int] = Field(DEFAULT_OMP_ECMP_LIMIT, json_schema_extra={"vmanage_key": "ecmp-limit"}) shutdown: Optional[bool] - omp_admin_distance_ipv4: Optional[int] = Field(vmanage_key="omp-admin-distance-ipv4") - omp_admin_distance_ipv6: Optional[int] = Field(vmanage_key="omp-admin-distance-ipv6") + omp_admin_distance_ipv4: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "omp-admin-distance-ipv4"} + ) + omp_admin_distance_ipv6: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "omp-admin-distance-ipv6"} + ) advertisement_interval: Optional[int] = Field( - DEFAULT_OMP_ADVERTISEMENT_INTERVAL, vmanage_key="advertisement-interval", data_path=["timers"] + DEFAULT_OMP_ADVERTISEMENT_INTERVAL, + json_schema_extra={"vmanage_key": "advertisement-interval", "data_path": ["timers"]}, ) graceful_restart_timer: Optional[int] = Field( - DEFAULT_OMP_GRACEFUL_RESTART_TIMER, vmanage_key="graceful-restart-timer", data_path=["timers"] + DEFAULT_OMP_GRACEFUL_RESTART_TIMER, + json_schema_extra={"vmanage_key": "graceful-restart-timer", "data_path": ["timers"]}, + ) + eor_timer: Optional[int] = Field( + DEFAULT_OMP_EOR_TIMER, json_schema_extra={"vmanage_key": "eor-timer", "data_path": ["timers"]} + ) + holdtime: Optional[int] = Field(DEFAULT_OMP_HOLDTIME, json_schema_extra={"data_path": ["timers"]}) + advertise: Optional[List[IPv4Advertise]] = None + ipv6_advertise: Optional[List[IPv6Advertise]] = Field( + default=None, json_schema_extra={"vmanage_key": "ipv6-advertise"} + ) + ignore_region_path_length: Optional[bool] = Field( + False, json_schema_extra={"vmanage_key": "ignore-region-path-length"} + ) + transport_gateway: Optional[TransportGateway] = Field( + default=None, json_schema_extra={"vmanage_key": "transport-gateway"} ) - eor_timer: Optional[int] = Field(DEFAULT_OMP_EOR_TIMER, vmanage_key="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(vmanage_key="ipv6-advertise") - ignore_region_path_length: Optional[bool] = Field(False, vmanage_key="ignore-region-path-length") - transport_gateway: Optional[TransportGateway] = Field(vmanage_key="transport-gateway") - site_types: Optional[List[SiteTypes]] = Field(vmanage_key="site-types") - auto_translate: Optional[bool] = Field(False, vmanage_key="auto-translate") + site_types: Optional[List[SiteTypes]] = Field(default=None, json_schema_extra={"vmanage_key": "site-types"}) + auto_translate: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "auto-translate"}) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_omp" diff --git a/catalystwan/api/templates/models/cisco_ospf.py b/catalystwan/api/templates/models/cisco_ospf.py index 8855376b0..d20f3ad47 100644 --- a/catalystwan/api/templates/models/cisco_ospf.py +++ b/catalystwan/api/templates/models/cisco_ospf.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import Field +from pydantic import ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.pydantic_validators import ConvertBoolToStringModel, ConvertIPToStringModel @@ -37,11 +37,9 @@ class Protocol(str, Enum): class Redistribute(ConvertBoolToStringModel): protocol: Protocol - route_policy: Optional[str] = Field(vmanage_key="route-policy") + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) dia: Optional[bool] = True - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class AdType(str, Enum): @@ -50,11 +48,9 @@ class AdType(str, Enum): class RouterLsa(ConvertBoolToStringModel): - ad_type: AdType = Field(vmanage_key="ad-type") + ad_type: AdType = Field(json_schema_extra={"vmanage_key": "ad-type"}) time: int - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class Direction(str, Enum): @@ -63,10 +59,8 @@ class Direction(str, Enum): class RoutePolicy(ConvertBoolToStringModel): direction: Direction - pol_name: str = Field(vmanage_key="pol-name") - - class Config: - allow_population_by_field_name = True + pol_name: str = Field(json_schema_extra={"vmanage_key": "pol-name"}) + model_config = ConfigDict(populate_by_name=True) class Network(str, Enum): @@ -84,71 +78,89 @@ class Type(str, Enum): class Interface(ConvertBoolToStringModel): name: str - hello_interval: Optional[int] = Field(DEFAULT_OSPF_DEAD_INTERVAL, vmanage_key="hello-interval") - dead_interval: Optional[int] = Field(DEFAULT_OSPF_DEAD_INTERVAL, vmanage_key="dead-interval") - retransmit_interval: Optional[int] = Field(DEFAULT_OSPF_RETRANSMIT_INTERVAL, vmanage_key="retransmit-interval") - cost: Optional[int] + hello_interval: Optional[int] = Field( + DEFAULT_OSPF_DEAD_INTERVAL, json_schema_extra={"vmanage_key": "hello-interval"} + ) + dead_interval: Optional[int] = Field(DEFAULT_OSPF_DEAD_INTERVAL, json_schema_extra={"vmanage_key": "dead-interval"}) + retransmit_interval: Optional[int] = Field( + DEFAULT_OSPF_RETRANSMIT_INTERVAL, json_schema_extra={"vmanage_key": "retransmit-interval"} + ) + cost: Optional[int] = None priority: Optional[int] = DEFAULT_OSPF_INTERFACE_PRIORITY network: Optional[Network] = Network.BROADCAST - passive_interface: Optional[bool] = Field(False, vmanage_key="passive-interface") - type: Optional[Type] = Field(data_path=["authentication"]) + passive_interface: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "passive-interface"}) + type: Optional[Type] = Field(default=None, json_schema_extra={"data_path": ["authentication"]}) message_digest_key: Optional[int] = Field( - vmanage_key="message-digest-key", data_path=["authentication", "message-digest"] + default=None, + json_schema_extra={"vmanage_key": "message-digest-key", "data_path": ["authentication", "message-digest"]}, ) - md5: Optional[str] = Field(data_path=["authentication", "message-digest"]) - - class Config: - allow_population_by_field_name = True + md5: Optional[str] = Field(default=None, json_schema_extra={"data_path": ["authentication", "message-digest"]}) + model_config = ConfigDict(populate_by_name=True) class Range(ConvertBoolToStringModel, ConvertIPToStringModel): address: ipaddress.IPv4Interface - cost: Optional[int] - no_advertise: Optional[bool] = Field(False, vmanage_key="no-advertise") - - class Config: - allow_population_by_field_name = True + cost: Optional[int] = None + no_advertise: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "no-advertise"}) + model_config = ConfigDict(populate_by_name=True) class Area(ConvertBoolToStringModel): - a_num: int = Field(vmanage_key="a-num") - stub: Optional[bool] = Field(vmanage_key="no-summary", data_path=["stub"]) - nssa: Optional[bool] = Field(vmanage_key="no-summary", data_path=["nssa"]) - interface: Optional[List[Interface]] - range: Optional[List[Range]] - - class Config: - allow_population_by_field_name = True + a_num: int = Field(json_schema_extra={"vmanage_key": "a-num"}) + stub: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "no-summary", "data_path": ["stub"]}) + nssa: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "no-summary", "data_path": ["nssa"]}) + interface: Optional[List[Interface]] = None + range: Optional[List[Range]] = None + model_config = ConfigDict(populate_by_name=True) class CiscoOSPFModel(FeatureTemplate, ConvertBoolToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) - router_id: Optional[str] = Field(vmanage_key="router-id", data_path=["ospf"]) + router_id: Optional[str] = Field( + default=None, json_schema_extra={"vmanage_key": "router-id", "data_path": ["ospf"]} + ) reference_bandwidth: Optional[int] = Field( - DEFAULT_OSPF_REFERENCE_BANDWIDTH, data_path=["ospf", "auto-cost"], vmanage_key="reference-bandwidth" + DEFAULT_OSPF_REFERENCE_BANDWIDTH, + json_schema_extra={"data_path": ["ospf", "auto-cost"], "vmanage_key": "reference-bandwidth"}, + ) + rfc1583: Optional[bool] = Field(True, json_schema_extra={"data_path": ["ospf", "compatible"]}) + originate: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["ospf", "default-information"]}) + always: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["ospf", "default-information", "originate"]} + ) + metric: Optional[int] = Field( + default=None, json_schema_extra={"data_path": ["ospf", "default-information", "originate"]} ) - rfc1583: Optional[bool] = Field(True, data_path=["ospf", "compatible"]) - originate: Optional[bool] = Field(data_path=["ospf", "default-information"]) - always: Optional[bool] = Field(data_path=["ospf", "default-information", "originate"]) - metric: Optional[int] = Field(data_path=["ospf", "default-information", "originate"]) metric_type: Optional[MetricType] = Field( - vmanage_key="metric-type", data_path=["ospf", "default-information", "originate"] + default=None, + json_schema_extra={"vmanage_key": "metric-type", "data_path": ["ospf", "default-information", "originate"]}, + ) + external: Optional[int] = Field(DEFAULT_OSPF_EXTERNAL, json_schema_extra={"data_path": ["ospf", "distance"]}) + inter_area: Optional[int] = Field( + DEFAULT_OSPF_INTER_AREA, json_schema_extra={"data_path": ["ospf", "distance"], "vmanage_key": "inter-area"} + ) + intra_area: Optional[int] = Field( + DEFAULT_OSPF_INTRA_AREA, json_schema_extra={"data_path": ["ospf", "distance"], "vmanage_key": "intra-area"} ) - external: Optional[int] = Field(DEFAULT_OSPF_EXTERNAL, data_path=["ospf", "distance"]) - inter_area: Optional[int] = Field(DEFAULT_OSPF_INTER_AREA, data_path=["ospf", "distance"], vmanage_key="inter-area") - intra_area: Optional[int] = Field(DEFAULT_OSPF_INTRA_AREA, data_path=["ospf", "distance"], vmanage_key="intra-area") - delay: Optional[int] = Field(DEFAULT_OSPF_DELAY, data_path=["ospf", "timers", "spf"]) + delay: Optional[int] = Field(DEFAULT_OSPF_DELAY, json_schema_extra={"data_path": ["ospf", "timers", "spf"]}) initial_hold: Optional[int] = Field( - DEFAULT_OSPF_INITIAL_HOLD, vmanage_key="initial-hold", data_path=["ospf", "timers", "spf"] + DEFAULT_OSPF_INITIAL_HOLD, + json_schema_extra={"vmanage_key": "initial-hold", "data_path": ["ospf", "timers", "spf"]}, + ) + max_hold: Optional[int] = Field( + DEFAULT_OSPF_MAX_HOLD, json_schema_extra={"vmanage_key": "max-hold", "data_path": ["ospf", "timers", "spf"]} + ) + redistribute: Optional[List[Redistribute]] = Field( + default=None, json_schema_extra={"vmanage_key": "redistribute", "data_path": ["ospf"]} + ) + router_lsa: Optional[List[RouterLsa]] = Field( + default=None, json_schema_extra={"vmanage_key": "router-lsa", "data_path": ["ospf", "max-metric"]} + ) + route_policy: Optional[List[RoutePolicy]] = Field( + default=None, json_schema_extra={"vmanage_key": "route-policy", "data_path": ["ospf"]} ) - max_hold: Optional[int] = Field(DEFAULT_OSPF_MAX_HOLD, vmanage_key="max-hold", data_path=["ospf", "timers", "spf"]) - redistribute: Optional[List[Redistribute]] = Field(vmanage_key="redistribute", data_path=["ospf"]) - router_lsa: Optional[List[RouterLsa]] = Field(vmanage_key="router-lsa", data_path=["ospf", "max-metric"]) - route_policy: Optional[List[RoutePolicy]] = Field(vmanage_key="route-policy", data_path=["ospf"]) - area: Optional[List[Area]] = Field(vmanage_key="area", data_path=["ospf"]) + area: Optional[List[Area]] = Field(default=None, json_schema_extra={"vmanage_key": "area", "data_path": ["ospf"]}) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_ospf" diff --git a/catalystwan/api/templates/models/cisco_ospfv3.py b/catalystwan/api/templates/models/cisco_ospfv3.py index 0a85533d1..14b515dbc 100644 --- a/catalystwan/api/templates/models/cisco_ospfv3.py +++ b/catalystwan/api/templates/models/cisco_ospfv3.py @@ -3,6 +3,7 @@ from pathlib import Path from typing import ClassVar, List, Optional +from pydantic import ConfigDict from pydantic.v1 import BaseModel, Field from catalystwan.api.templates.feature_template import FeatureTemplate @@ -27,11 +28,9 @@ class Protocol(str, Enum): class Redistribute(ConvertBoolToStringModel): protocol: Protocol - route_policy: Optional[str] = Field(vmanage_key="route-policy") + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) dia: Optional[bool] = True - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class AdType(str, Enum): @@ -39,11 +38,9 @@ class AdType(str, Enum): class RouterLsa(BaseModel): - ad_type: AdType = Field(vmanage_key="ad-type") + ad_type: AdType = Field(json_schema_extra={"vmanage_key": "ad-type"}) time: int - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class Translate(str, Enum): @@ -64,257 +61,307 @@ class Type(str, Enum): class Interface(BaseModel): name: str - hello_interval: Optional[int] = Field(10, vmanage_key="hello-interval") - dead_interval: Optional[int] = Field(40, vmanage_key="dead-interval") - retransmit_interval: Optional[int] = Field(5, vmanage_key="retransmit-interval") - cost: Optional[int] + hello_interval: Optional[int] = Field(10, json_schema_extra={"vmanage_key": "hello-interval"}) + dead_interval: Optional[int] = Field(40, json_schema_extra={"vmanage_key": "dead-interval"}) + retransmit_interval: Optional[int] = Field(5, json_schema_extra={"vmanage_key": "retransmit-interval"}) + cost: Optional[int] = None network: Optional[Network] = Network.BROADCAST - passive_interface: Optional[bool] = Field(False, vmanage_key="passive-interface") - type: Type = Field(data_path=["authentication"]) - authentication_key: str = Field(vmanage_key="authentication-key", data_path=["authentication"]) - spi: Optional[int] = Field(data_path=["authentication", "ipsec"]) - - class Config: - allow_population_by_field_name = True + passive_interface: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "passive-interface"}) + type: Type = Field(json_schema_extra={"data_path": ["authentication"]}) + authentication_key: str = Field( + json_schema_extra={"vmanage_key": "authentication-key", "data_path": ["authentication"]} + ) + spi: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["authentication", "ipsec"]}) + model_config = ConfigDict(populate_by_name=True) class Range(BaseModel): address: ipaddress.IPv4Interface - cost: Optional[int] - no_advertise: Optional[bool] = Field(False, vmanage_key="no-advertise") - - class Config: - allow_population_by_field_name = True + cost: Optional[int] = None + no_advertise: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "no-advertise"}) + model_config = ConfigDict(populate_by_name=True) class Area(ConvertBoolToStringModel): - a_num: int = Field(vmanage_key="a-num") - stub: Optional[bool] = Field(vmanage_key="no-summary", data_path=["stub"]) - nssa: Optional[bool] = Field(vmanage_key="no-summary", data_path=["nssa"]) - translate: Optional[Translate] = Field(data_path=["nssa"]) - normal: Optional[bool] - interface: Optional[List[Interface]] - range: Optional[List[Range]] - - class Config: - allow_population_by_field_name = True + a_num: int = Field(json_schema_extra={"vmanage_key": "a-num"}) + stub: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "no-summary", "data_path": ["stub"]}) + nssa: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "no-summary", "data_path": ["nssa"]}) + translate: Optional[Translate] = Field(default=None, json_schema_extra={"data_path": ["nssa"]}) + normal: Optional[bool] = None + interface: Optional[List[Interface]] = None + range: Optional[List[Range]] = None + model_config = ConfigDict(populate_by_name=True) class RedistributeV6(BaseModel): protocol: Protocol - route_policy: Optional[str] = Field(vmanage_key="route-policy") - - class Config: - allow_population_by_field_name = True + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + model_config = ConfigDict(populate_by_name=True) class InterfaceV6(BaseModel): name: str - hello_interval: Optional[int] = Field(10, vmanage_key="hello-interval") - dead_interval: Optional[int] = Field(40, vmanage_key="dead-interval") - retransmit_interval: Optional[int] = Field(5, vmanage_key="retransmit-interval") - cost: Optional[int] + hello_interval: Optional[int] = Field(10, json_schema_extra={"vmanage_key": "hello-interval"}) + dead_interval: Optional[int] = Field(40, json_schema_extra={"vmanage_key": "dead-interval"}) + retransmit_interval: Optional[int] = Field(5, json_schema_extra={"vmanage_key": "retransmit-interval"}) + cost: Optional[int] = None network: Optional[Network] = Network.BROADCAST - passive_interface: Optional[bool] = Field(False, vmanage_key="passive-interface") - type: Type = Field(data_path=["authentication"]) - authentication_key: str = Field(vmanage_key="authentication-key", data_path=["authentication"]) - spi: Optional[int] = Field(data_path=["authentication", "ipsec"]) - - class Config: - allow_population_by_field_name = True + passive_interface: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "passive-interface"}) + type: Type = Field(json_schema_extra={"data_path": ["authentication"]}) + authentication_key: str = Field( + json_schema_extra={"vmanage_key": "authentication-key", "data_path": ["authentication"]} + ) + spi: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["authentication", "ipsec"]}) + model_config = ConfigDict(populate_by_name=True) class RangeV6(BaseModel): address: ipaddress.IPv6Interface - cost: Optional[int] - no_advertise: Optional[bool] = Field(False, vmanage_key="no-advertise") - - class Config: - allow_population_by_field_name = True + cost: Optional[int] = None + no_advertise: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "no-advertise"}) + model_config = ConfigDict(populate_by_name=True) class AreaV6(ConvertBoolToStringModel): - a_num: int = Field(vmanage_key="a-num") - stub: Optional[bool] = Field(vmanage_key="no-summary", data_path=["stub"]) - nssa: Optional[bool] = Field(vmanage_key="no-summary", data_path=["nssa"]) - translate: Optional[Translate] = Field(data_path=["nssa"]) - normal: Optional[bool] - interface: Optional[List[InterfaceV6]] - range: Optional[List[RangeV6]] - - class Config: - allow_population_by_field_name = True + a_num: int = Field(json_schema_extra={"vmanage_key": "a-num"}) + stub: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "no-summary", "data_path": ["stub"]}) + nssa: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "no-summary", "data_path": ["nssa"]}) + translate: Optional[Translate] = Field(default=None, json_schema_extra={"data_path": ["nssa"]}) + normal: Optional[bool] = None + interface: Optional[List[InterfaceV6]] = None + range: Optional[List[RangeV6]] = None + model_config = ConfigDict(populate_by_name=True) class CiscoOspfv3Model(FeatureTemplate, ConvertIPToStringModel, ConvertBoolToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) router_id_v4: Optional[ipaddress.IPv4Address] = Field( - vmanage_key="router-id", data_path=["ospfv3", "address-family", "ipv4"] + default=None, json_schema_extra={"vmanage_key": "router-id", "data_path": ["ospfv3", "address-family", "ipv4"]} ) reference_bandwidth_v4: Optional[int] = Field( 100, - vmanage_key="reference-bandwidth", - data_path=["ospfv3", "address-family", "ipv4", "auto-cost"], + json_schema_extra={ + "vmanage_key": "reference-bandwidth", + "data_path": ["ospfv3", "address-family", "ipv4", "auto-cost"], + }, ) rfc1583_v4: Optional[bool] = Field( - True, vmanage_key="rfc1583", data_path=["ospfv3", "address-family", "ipv4", "compatible"] + True, + json_schema_extra={"vmanage_key": "rfc1583", "data_path": ["ospfv3", "address-family", "ipv4", "compatible"]}, ) originate_v4: Optional[bool] = Field( - vmanage_key="originate", data_path=["ospfv3", "address-family", "ipv4", "default-information"] + default=None, + json_schema_extra={ + "vmanage_key": "originate", + "data_path": ["ospfv3", "address-family", "ipv4", "default-information"], + }, ) always_v4: Optional[bool] = Field( - vmanage_key="always", - data_path=[ - "ospfv3", - "address-family", - "ipv4", - "default-information", - "originate", - ], + default=None, + json_schema_extra={ + "vmanage_key": "always", + "data_path": ["ospfv3", "address-family", "ipv4", "default-information", "originate"], + }, ) metric_v4: Optional[int] = Field( - vmanage_key="metric", - data_path=[ - "ospfv3", - "address-family", - "ipv4", - "default-information", - "originate", - ], + default=None, + json_schema_extra={ + "vmanage_key": "metric", + "data_path": ["ospfv3", "address-family", "ipv4", "default-information", "originate"], + }, ) metric_type_v4: Optional[MetricType] = Field( - vmanage_key="metric-type", - data_path=[ - "ospfv3", - "address-family", - "ipv4", - "default-information", - "originate", - ], + default=None, + json_schema_extra={ + "vmanage_key": "metric-type", + "data_path": ["ospfv3", "address-family", "ipv4", "default-information", "originate"], + }, ) external_v4: Optional[int] = Field( - 110, vmanage_key="external", data_path=["ospfv3", "address-family", "ipv4", "distance-ipv4", "ospf"] + 110, + json_schema_extra={ + "vmanage_key": "external", + "data_path": ["ospfv3", "address-family", "ipv4", "distance-ipv4", "ospf"], + }, ) inter_area_v4: Optional[int] = Field( 110, - vmanage_key="inter-area", - data_path=["ospfv3", "address-family", "ipv4", "distance-ipv4", "ospf"], + json_schema_extra={ + "vmanage_key": "inter-area", + "data_path": ["ospfv3", "address-family", "ipv4", "distance-ipv4", "ospf"], + }, ) intra_area_v4: Optional[int] = Field( 110, - vmanage_key="intra-area", - data_path=["ospfv3", "address-family", "ipv4", "distance-ipv4", "ospf"], + json_schema_extra={ + "vmanage_key": "intra-area", + "data_path": ["ospfv3", "address-family", "ipv4", "distance-ipv4", "ospf"], + }, ) delay_v4: Optional[int] = Field( - 200, vmanage_key="delay", data_path=["ospfv3", "address-family", "ipv4", "timers", "throttle", "spf"] + 200, + json_schema_extra={ + "vmanage_key": "delay", + "data_path": ["ospfv3", "address-family", "ipv4", "timers", "throttle", "spf"], + }, ) initial_hold_v4: Optional[int] = Field( 1000, - vmanage_key="initial-hold", - data_path=["ospfv3", "address-family", "ipv4", "timers", "throttle", "spf"], + json_schema_extra={ + "vmanage_key": "initial-hold", + "data_path": ["ospfv3", "address-family", "ipv4", "timers", "throttle", "spf"], + }, ) max_hold_v4: Optional[int] = Field( 10000, - vmanage_key="max-hold", - data_path=["ospfv3", "address-family", "ipv4", "timers", "throttle", "spf"], + json_schema_extra={ + "vmanage_key": "max-hold", + "data_path": ["ospfv3", "address-family", "ipv4", "timers", "throttle", "spf"], + }, ) distance_v4: Optional[int] = Field( - 110, vmanage_key="distance", data_path=["ospfv3", "address-family", "ipv4", "distance-ipv4"] + 110, + json_schema_extra={ + "vmanage_key": "distance", + "data_path": ["ospfv3", "address-family", "ipv4", "distance-ipv4"], + }, + ) + name_v4: Optional[str] = Field( + default=None, + json_schema_extra={"vmanage_key": "name", "data_path": ["ospfv3", "address-family", "ipv4", "table-map"]}, + ) + filter_v4: Optional[bool] = Field( + default=None, + json_schema_extra={"vmanage_key": "filter", "data_path": ["ospfv3", "address-family", "ipv4", "table-map"]}, ) - name_v4: Optional[str] = Field(vmanage_key="name", data_path=["ospfv3", "address-family", "ipv4", "table-map"]) - filter_v4: Optional[bool] = Field(vmanage_key="filter", data_path=["ospfv3", "address-family", "ipv4", "table-map"]) redistribute_v4: Optional[List[Redistribute]] = Field( - vmanage_key="redistribute", data_path=["ospfv3", "address-family", "ipv4"] + default=None, + json_schema_extra={"vmanage_key": "redistribute", "data_path": ["ospfv3", "address-family", "ipv4"]}, ) router_lsa_v4: Optional[List[RouterLsa]] = Field( - vmanage_key="router-lsa", data_path=["ospfv3", "address-family", "ipv4", "max-metric"] + default=None, + json_schema_extra={ + "vmanage_key": "router-lsa", + "data_path": ["ospfv3", "address-family", "ipv4", "max-metric"], + }, + ) + area_v4: Optional[List[Area]] = Field( + default=None, json_schema_extra={"vmanage_key": "area", "data_path": ["ospfv3", "address-family", "ipv4"]} ) - area_v4: Optional[List[Area]] = Field(vmanage_key="area", data_path=["ospfv3", "address-family", "ipv4"]) router_id_v6: Optional[ipaddress.IPv4Address] = Field( - vmanage_key="router-id", data_path=["ospfv3", "address-family", "ipv6"] + default=None, json_schema_extra={"vmanage_key": "router-id", "data_path": ["ospfv3", "address-family", "ipv6"]} ) reference_bandwidth_v6: Optional[int] = Field( 100, - vmanage_key="reference-bandwidth", - data_path=["ospfv3", "address-family", "ipv6", "auto-cost"], + json_schema_extra={ + "vmanage_key": "reference-bandwidth", + "data_path": ["ospfv3", "address-family", "ipv6", "auto-cost"], + }, ) rfc1583_v6: Optional[bool] = Field( - True, vmanage_key="rfc1583", data_path=["ospfv3", "address-family", "ipv6", "compatible"] + True, + json_schema_extra={"vmanage_key": "rfc1583", "data_path": ["ospfv3", "address-family", "ipv6", "compatible"]}, ) originate_v6: Optional[bool] = Field( - vmanage_key="originate", data_path=["ospfv3", "address-family", "ipv6", "default-information"] + default=None, + json_schema_extra={ + "vmanage_key": "originate", + "data_path": ["ospfv3", "address-family", "ipv6", "default-information"], + }, ) always_v6: Optional[bool] = Field( - vmanage_key="always", - data_path=[ - "ospfv3", - "address-family", - "ipv6", - "default-information", - "originate", - ], + default=None, + json_schema_extra={ + "vmanage_key": "always", + "data_path": ["ospfv3", "address-family", "ipv6", "default-information", "originate"], + }, ) metric_v6: Optional[int] = Field( - vmanage_key="metric", - data_path=[ - "ospfv3", - "address-family", - "ipv6", - "default-information", - "originate", - ], + default=None, + json_schema_extra={ + "vmanage_key": "metric", + "data_path": ["ospfv3", "address-family", "ipv6", "default-information", "originate"], + }, ) metric_type_v6: Optional[MetricType] = Field( - vmanage_key="metric-type", - data_path=[ - "ospfv3", - "address-family", - "ipv6", - "default-information", - "originate", - ], + default=None, + json_schema_extra={ + "vmanage_key": "metric-type", + "data_path": ["ospfv3", "address-family", "ipv6", "default-information", "originate"], + }, ) external_v6: Optional[int] = Field( - 110, vmanage_key="external", data_path=["ospfv3", "address-family", "ipv6", "distance-ipv6", "ospf"] + 110, + json_schema_extra={ + "vmanage_key": "external", + "data_path": ["ospfv3", "address-family", "ipv6", "distance-ipv6", "ospf"], + }, ) inter_area_v6: Optional[int] = Field( 110, - vmanage_key="inter-area", - data_path=["ospfv3", "address-family", "ipv6", "distance-ipv6", "ospf"], + json_schema_extra={ + "vmanage_key": "inter-area", + "data_path": ["ospfv3", "address-family", "ipv6", "distance-ipv6", "ospf"], + }, ) intra_area_v6: Optional[int] = Field( 110, - vmanage_key="intra-area", - data_path=["ospfv3", "address-family", "ipv6", "distance-ipv6", "ospf"], + json_schema_extra={ + "vmanage_key": "intra-area", + "data_path": ["ospfv3", "address-family", "ipv6", "distance-ipv6", "ospf"], + }, ) delay_v6: Optional[int] = Field( - 200, vmanage_key="delay", data_path=["ospfv3", "address-family", "ipv6", "timers", "throttle", "spf"] + 200, + json_schema_extra={ + "vmanage_key": "delay", + "data_path": ["ospfv3", "address-family", "ipv6", "timers", "throttle", "spf"], + }, ) initial_hold_v6: Optional[int] = Field( 1000, - vmanage_key="initial-hold", - data_path=["ospfv3", "address-family", "ipv6", "timers", "throttle", "spf"], + json_schema_extra={ + "vmanage_key": "initial-hold", + "data_path": ["ospfv3", "address-family", "ipv6", "timers", "throttle", "spf"], + }, ) max_hold_v6: Optional[int] = Field( 10000, - vmanage_key="max-hold", - data_path=["ospfv3", "address-family", "ipv6", "timers", "throttle", "spf"], + json_schema_extra={ + "vmanage_key": "max-hold", + "data_path": ["ospfv3", "address-family", "ipv6", "timers", "throttle", "spf"], + }, ) distance_v6: Optional[int] = Field( - 110, vmanage_key="distance", data_path=["ospfv3", "address-family", "ipv6", "distance-ipv6"] + 110, + json_schema_extra={ + "vmanage_key": "distance", + "data_path": ["ospfv3", "address-family", "ipv6", "distance-ipv6"], + }, + ) + name_v6: Optional[str] = Field( + default=None, + json_schema_extra={"vmanage_key": "name", "data_path": ["ospfv3", "address-family", "ipv6", "table-map"]}, + ) + filter_v6: Optional[bool] = Field( + default=None, + json_schema_extra={"vmanage_key": "filter", "data_path": ["ospfv3", "address-family", "ipv6", "table-map"]}, ) - name_v6: Optional[str] = Field(vmanage_key="name", data_path=["ospfv3", "address-family", "ipv6", "table-map"]) - filter_v6: Optional[bool] = Field(vmanage_key="filter", data_path=["ospfv3", "address-family", "ipv6", "table-map"]) redistribute_v6: Optional[List[RedistributeV6]] = Field( - vmanage_key="redistribute", data_path=["ospfv3", "address-family", "ipv6"] + default=None, + json_schema_extra={"vmanage_key": "redistribute", "data_path": ["ospfv3", "address-family", "ipv6"]}, ) router_lsa_v6: Optional[List[RouterLsa]] = Field( - vmanage_key="router-lsa", data_path=["ospfv3", "address-family", "ipv6", "max-metric"] + default=None, + json_schema_extra={ + "vmanage_key": "router-lsa", + "data_path": ["ospfv3", "address-family", "ipv6", "max-metric"], + }, + ) + area_v6: Optional[List[AreaV6]] = Field( + default=None, json_schema_extra={"vmanage_key": "area", "data_path": ["ospfv3", "address-family", "ipv6"]} ) - area_v6: Optional[List[AreaV6]] = Field(vmanage_key="area", data_path=["ospfv3", "address-family", "ipv6"]) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_ospfv3" diff --git a/catalystwan/api/templates/models/cisco_secure_internet_gateway.py b/catalystwan/api/templates/models/cisco_secure_internet_gateway.py index c9c0b858b..6eb7ac0c1 100644 --- a/catalystwan/api/templates/models/cisco_secure_internet_gateway.py +++ b/catalystwan/api/templates/models/cisco_secure_internet_gateway.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.pydantic_validators import ConvertIPToStringModel @@ -74,44 +74,56 @@ class PerfectForwardSecrecy(str, Enum): class Interface(ConvertIPToStringModel): - if_name: str = Field(vmanage_key="if-name") + if_name: str = Field(json_schema_extra={"vmanage_key": "if-name"}) auto: bool shutdown: bool - description: Optional[str] + description: Optional[str] = None unnumbered: bool = True - address: Optional[ipaddress.IPv4Interface] - tunnel_source: ipaddress.IPv4Address = Field(vmanage_key="tunnel-source") - tunnel_source_interface: str = Field(vmanage_key="tunnel-source-interface") - tunnel_route_via: str = Field(vmanage_key="tunnel-route-via") - tunnel_destination: str = Field(vmanage_key="tunnel-destination") + address: Optional[ipaddress.IPv4Interface] = None + tunnel_source: ipaddress.IPv4Address = Field(json_schema_extra={"vmanage_key": "tunnel-source"}) + tunnel_source_interface: str = Field(json_schema_extra={"vmanage_key": "tunnel-source-interface"}) + tunnel_route_via: str = Field(json_schema_extra={"vmanage_key": "tunnel-route-via"}) + tunnel_destination: str = Field(json_schema_extra={"vmanage_key": "tunnel-destination"}) application: Application = Application.SIG - tunnel_set: TunnelSet = Field(TunnelSet.SECURE_INTERNET_GATEWAY_UMBRELLA, vmanage_key="tunnel-set") - tunnel_dc_preference: TunnelDcPreference = Field(TunnelDcPreference.PRIMARY_DC, vmanage_key="tunnel-dc-preference") - tcp_mss_adjust: Optional[int] = Field(vmanage_key="tcp-mss-adjust") + tunnel_set: TunnelSet = Field( + TunnelSet.SECURE_INTERNET_GATEWAY_UMBRELLA, json_schema_extra={"vmanage_key": "tunnel-set"} + ) + tunnel_dc_preference: TunnelDcPreference = Field( + TunnelDcPreference.PRIMARY_DC, json_schema_extra={"vmanage_key": "tunnel-dc-preference"} + ) + tcp_mss_adjust: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "tcp-mss-adjust"}) mtu: int = DEFAULT_INTERFACE_MTU - dpd_interval: Optional[int] = Field(DEFAULT_INTERFACE_DPD_INTERVAL, vmanage_key="dpd-interval") - dpd_retries: Optional[int] = Field(DEFAULT_INTERFACE_DPD_RETRIES, vmanage_key="dpd-retries") - ike_version: int = Field(DEFAULT_INTERFACE_IKE_VERSION, vmanage_key="ike-version") - pre_shared_secret: Optional[str] = Field(vmanage_key="pre-shared-secret") - ike_rekey_interval: Optional[int] = Field(DEFAULT_INTERFACE_IKE_REKEY_INTERVAL, vmanage_key="ike-rekey-interval") - ike_ciphersuite: Optional[IkeCiphersuite] = Field(IkeCiphersuite.AES256_CBC_SHA1, vmanage_key="ike-ciphersuite") - ike_group: IkeGroup = Field(IkeGroup.FOURTEEN, vmanage_key="ike-group") - pre_shared_key_dynamic: bool = Field(True, vmanage_key="pre-shared-key-dynamic") - ike_local_id: Optional[str] = Field(vmanage_key="ike-local-id") - ike_remote_id: Optional[str] = Field(vmanage_key="ike-remote-id") + dpd_interval: Optional[int] = Field( + DEFAULT_INTERFACE_DPD_INTERVAL, json_schema_extra={"vmanage_key": "dpd-interval"} + ) + dpd_retries: Optional[int] = Field(DEFAULT_INTERFACE_DPD_RETRIES, json_schema_extra={"vmanage_key": "dpd-retries"}) + ike_version: int = Field(DEFAULT_INTERFACE_IKE_VERSION, json_schema_extra={"vmanage_key": "ike-version"}) + pre_shared_secret: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "pre-shared-secret"}) + ike_rekey_interval: Optional[int] = Field( + DEFAULT_INTERFACE_IKE_REKEY_INTERVAL, json_schema_extra={"vmanage_key": "ike-rekey-interval"} + ) + ike_ciphersuite: Optional[IkeCiphersuite] = Field( + IkeCiphersuite.AES256_CBC_SHA1, json_schema_extra={"vmanage_key": "ike-ciphersuite"} + ) + ike_group: IkeGroup = Field(IkeGroup.FOURTEEN, json_schema_extra={"vmanage_key": "ike-group"}) + pre_shared_key_dynamic: bool = Field(True, json_schema_extra={"vmanage_key": "pre-shared-key-dynamic"}) + ike_local_id: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "ike-local-id"}) + ike_remote_id: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "ike-remote-id"}) ipsec_rekey_interval: Optional[int] = Field( - DEFAULT_INTERFACE_IPSEC_REKEY_INTERVAL, vmanage_key="ipsec-rekey-interval" + DEFAULT_INTERFACE_IPSEC_REKEY_INTERVAL, json_schema_extra={"vmanage_key": "ipsec-rekey-interval"} + ) + ipsec_replay_window: Optional[int] = Field( + DEFAULT_INTERFACE_IPSEC_REPLAY_WINDOW, json_schema_extra={"vmanage_key": "ipsec-replay-window"} + ) + ipsec_ciphersuite: IpsecCiphersuite = Field( + IpsecCiphersuite.AES256_GCM, json_schema_extra={"vmanage_key": "ipsec-ciphersuite"} ) - ipsec_replay_window: Optional[int] = Field(DEFAULT_INTERFACE_IPSEC_REPLAY_WINDOW, vmanage_key="ipsec-replay-window") - ipsec_ciphersuite: IpsecCiphersuite = Field(IpsecCiphersuite.AES256_GCM, vmanage_key="ipsec-ciphersuite") perfect_forward_secrecy: PerfectForwardSecrecy = Field( - PerfectForwardSecrecy.NONE, vmanage_key="perfect-forward-secrecy" + PerfectForwardSecrecy.NONE, json_schema_extra={"vmanage_key": "perfect-forward-secrecy"} ) - tracker: Optional[bool] - track_enable: Optional[bool] = Field(True, vmanage_key="track-enable") - - class Config: - allow_population_by_field_name = True + tracker: Optional[bool] = None + track_enable: Optional[bool] = Field(True, json_schema_extra={"vmanage_key": "track-enable"}) + model_config = ConfigDict(populate_by_name=True) class SvcType(str, Enum): @@ -119,17 +131,15 @@ class SvcType(str, Enum): class InterfacePair(BaseModel): - active_interface: str = Field(vmanage_key="active-interface") + active_interface: str = Field(json_schema_extra={"vmanage_key": "active-interface"}) active_interface_weight: int = Field( - DEFAULT_INTERFACE_PAIR_ACTIVE_INTERFACE_WEIGHT, vmanage_key="active-interface-weight" + DEFAULT_INTERFACE_PAIR_ACTIVE_INTERFACE_WEIGHT, json_schema_extra={"vmanage_key": "active-interface-weight"} ) - backup_interface: Optional[str] = Field("None", vmanage_key="backup-interface") + backup_interface: Optional[str] = Field("None", json_schema_extra={"vmanage_key": "backup-interface"}) backup_interface_weight: int = Field( - DEFAULT_INTERFACE_PAIR_BACKUP_INTERFACE_WEIGHT, vmanage_key="backup-interface-weight" + DEFAULT_INTERFACE_PAIR_BACKUP_INTERFACE_WEIGHT, json_schema_extra={"vmanage_key": "backup-interface-weight"} ) - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class DisplayTimeUnit(str, Enum): @@ -145,30 +155,36 @@ class RefreshTimeUnit(str, Enum): class Service(BaseModel): - svc_type: SvcType = Field(SvcType.SIG, vmanage_key="svc-type") - interface_pair: List[InterfacePair] = Field(vmanage_key="interface-pair") - auth_required: Optional[bool] = Field(False, vmanage_key="auth-required") - xff_forward_enabled: Optional[bool] = Field(False, vmanage_key="xff-forward-enabled") - ofw_enabled: Optional[bool] = Field(False, vmanage_key="ofw-enabled") - ips_control: Optional[bool] = Field(False, vmanage_key="ips-control") - caution_enabled: Optional[bool] = Field(False, vmanage_key="caution-enabled") - primary_data_center: Optional[str] = Field("Auto", vmanage_key="primary-data-center") - secondary_data_center: Optional[str] = Field("Auto", vmanage_key="secondary-data-center") - ip: Optional[bool] - idle_time: Optional[int] = Field(DEFAULT_SERVICE_IDLE_TIME, vmanage_key="idle-time") - display_time_unit: Optional[DisplayTimeUnit] = Field(DisplayTimeUnit.MINUTE, vmanage_key="display-time-unit") - ip_enforced_for_known_browsers: Optional[bool] = Field(False, vmanage_key="ip-enforced-for-known-browsers") - refresh_time: Optional[int] = Field(DEFAULT_SERVICE_REFRESH_TIME, vmanage_key="refresh-time") - refresh_time_unit: Optional[RefreshTimeUnit] = Field(RefreshTimeUnit.MINUTE, vmanage_key="refresh-time-unit") + svc_type: SvcType = Field(SvcType.SIG, json_schema_extra={"vmanage_key": "svc-type"}) + interface_pair: List[InterfacePair] = Field(json_schema_extra={"vmanage_key": "interface-pair"}) + auth_required: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "auth-required"}) + xff_forward_enabled: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "xff-forward-enabled"}) + ofw_enabled: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "ofw-enabled"}) + ips_control: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "ips-control"}) + caution_enabled: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "caution-enabled"}) + primary_data_center: Optional[str] = Field("Auto", json_schema_extra={"vmanage_key": "primary-data-center"}) + secondary_data_center: Optional[str] = Field("Auto", json_schema_extra={"vmanage_key": "secondary-data-center"}) + ip: Optional[bool] = None + idle_time: Optional[int] = Field(DEFAULT_SERVICE_IDLE_TIME, json_schema_extra={"vmanage_key": "idle-time"}) + display_time_unit: Optional[DisplayTimeUnit] = Field( + DisplayTimeUnit.MINUTE, json_schema_extra={"vmanage_key": "display-time-unit"} + ) + ip_enforced_for_known_browsers: Optional[bool] = Field( + False, json_schema_extra={"vmanage_key": "ip-enforced-for-known-browsers"} + ) + refresh_time: Optional[int] = Field(DEFAULT_SERVICE_REFRESH_TIME, json_schema_extra={"vmanage_key": "refresh-time"}) + refresh_time_unit: Optional[RefreshTimeUnit] = Field( + RefreshTimeUnit.MINUTE, json_schema_extra={"vmanage_key": "refresh-time-unit"} + ) enabled: Optional[bool] - block_internet_until_accepted: Optional[bool] = Field(False, vmanage_key="block-internet-until-accepted") - force_ssl_inspection: Optional[bool] = Field(False, vmanage_key="force-ssl-inspection") + block_internet_until_accepted: Optional[bool] = Field( + False, json_schema_extra={"vmanage_key": "block-internet-until-accepted"} + ) + force_ssl_inspection: Optional[bool] = Field(False, json_schema_extra={"vmanage_key": "force-ssl-inspection"}) timeout: Optional[int] - data_center_primary: Optional[str] = Field("Auto", vmanage_key="data-center-primary") - data_center_secondary: Optional[str] = Field("Auto", vmanage_key="data-center-secondary") - - class Config: - allow_population_by_field_name = True + data_center_primary: Optional[str] = Field("Auto", json_schema_extra={"vmanage_key": "data-center-primary"}) + data_center_secondary: Optional[str] = Field("Auto", json_schema_extra={"vmanage_key": "data-center-secondary"}) + model_config = ConfigDict(populate_by_name=True) class TrackerType(str, Enum): @@ -177,26 +193,22 @@ class TrackerType(str, Enum): class Tracker(BaseModel): name: str - endpoint_api_url: str = Field(vmanage_key="endpoint-api-url") + endpoint_api_url: str = Field(json_schema_extra={"vmanage_key": "endpoint-api-url"}) threshold: Optional[int] = DEFAULT_TRACKER_THRESHOLD interval: Optional[int] = DEFAULT_TRACKER_INTERVAL multiplier: Optional[int] = DEFAULT_TRACKER_MULTIPLIER - tracker_type: TrackerType = Field(vmanage_key="tracker-type") - - class Config: - allow_population_by_field_name = True + tracker_type: TrackerType = Field(json_schema_extra={"vmanage_key": "tracker-type"}) + model_config = ConfigDict(populate_by_name=True) class CiscoSecureInternetGatewayModel(FeatureTemplate, ConvertIPToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) - vpn_id: int = Field(DEFAULT_SIG_VPN_ID, vmanage_key="vpn-id") + vpn_id: int = Field(DEFAULT_SIG_VPN_ID, json_schema_extra={"vmanage_key": "vpn-id"}) interface: List[Interface] service: List[Service] - tracker_src_ip: ipaddress.IPv4Interface = Field(vmanage_key="tracker-src-ip") - tracker: Optional[List[Tracker]] + tracker_src_ip: ipaddress.IPv4Interface = Field(json_schema_extra={"vmanage_key": "tracker-src-ip"}) + tracker: Optional[List[Tracker]] = None payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_secure_internet_gateway" diff --git a/catalystwan/api/templates/models/cisco_snmp_model.py b/catalystwan/api/templates/models/cisco_snmp_model.py index c67285b49..743c07a50 100644 --- a/catalystwan/api/templates/models/cisco_snmp_model.py +++ b/catalystwan/api/templates/models/cisco_snmp_model.py @@ -2,7 +2,7 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.pydantic_validators import ConvertBoolToStringModel @@ -10,12 +10,12 @@ class Oid(ConvertBoolToStringModel): id: str - exclude: Optional[bool] + exclude: Optional[bool] = None class View(BaseModel): name: str - oid: Optional[List[Oid]] + oid: Optional[List[Oid]] = None class Authorization(str, Enum): @@ -36,11 +36,9 @@ class SecurityLevel(str, Enum): class Group(BaseModel): name: str - security_level: SecurityLevel = Field(vmanage_key="security-level") + security_level: SecurityLevel = Field(json_schema_extra={"vmanage_key": "security-level"}) view: str - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class Auth(str, Enum): @@ -54,41 +52,35 @@ class Priv(str, Enum): class User(BaseModel): name: str - auth: Optional[Auth] - auth_password: Optional[str] = Field(vmanage_key="auth-password") - priv: Optional[Priv] - priv_password: Optional[str] = Field(vmanage_key="priv-password") + auth: Optional[Auth] = None + auth_password: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "auth-password"}) + priv: Optional[Priv] = None + priv_password: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "priv-password"}) group: str - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class Target(BaseModel): - vpn_id: int = Field(vmanage_key="vpn-id") + vpn_id: int = Field(json_schema_extra={"vmanage_key": "vpn-id"}) ip: str port: int - community_name: str = Field(vmanage_key="community-name") - user: Optional[str] - source_interface: str = Field(vmanage_key="source-interface") - - class Config: - allow_population_by_field_name = True + community_name: str = Field(default=None, json_schema_extra={"vmanage_key": "community-name"}) + user: Optional[str] = None + source_interface: str = Field(default=None, json_schema_extra={"vmanage_key": "source-interface"}) + model_config = ConfigDict(populate_by_name=True) class CiscoSNMPModel(FeatureTemplate, ConvertBoolToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) shutdown: Optional[bool] = True - contact: Optional[str] - location: Optional[str] - view: Optional[List[View]] - community: Optional[List[Community]] - group: Optional[List[Group]] - user: Optional[List[User]] - target: Optional[List[Target]] = Field(data_path=["trap"]) + contact: Optional[str] = None + location: Optional[str] = None + view: Optional[List[View]] = None + community: Optional[List[Community]] = None + group: Optional[List[Group]] = None + user: Optional[List[User]] = None + target: Optional[List[Target]] = Field(default=None, json_schema_extra={"data_path": ["trap"]}) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_snmp" diff --git a/catalystwan/api/templates/models/cisco_system.py b/catalystwan/api/templates/models/cisco_system.py index c9316b363..eaebe5f25 100644 --- a/catalystwan/api/templates/models/cisco_system.py +++ b/catalystwan/api/templates/models/cisco_system.py @@ -2,7 +2,7 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from catalystwan.api.templates.device_variable import DeviceVariable from catalystwan.api.templates.feature_template import FeatureTemplate @@ -52,21 +52,21 @@ class Type(str, Enum): class Tracker(BaseModel): name: str - endpoint_ip: str = Field(vmanage_key="endpoint-ip") - endpoint_ip_transport_port: str = Field(vmanage_key="endpoint-ip", data_path=["endpoint-ip-transport-port"]) - protocol: Protocol = Field(data_path=["endpoint-ip-transport-port"]) - port: int = Field(data_path=["endpoint-ip-transport-port"]) - endpoint_dns_name: str = Field(vmanage_key="endpoint-dns-name") - endpoint_api_url: str = Field(vmanage_key="endpoint-api-url") + endpoint_ip: str = Field(json_schema_extra={"vmanage_key": "endpoint-ip"}) + endpoint_ip_transport_port: str = Field( + json_schema_extra={"vmanage_key": "endpoint-ip", "data_path": ["endpoint-ip-transport-port"]} + ) + protocol: Protocol = Field(json_schema_extra={"data_path": ["endpoint-ip-transport-port"]}) + port: int = Field(json_schema_extra={"data_path": ["endpoint-ip-transport-port"]}) + endpoint_dns_name: str = Field(json_schema_extra={"vmanage_key": "endpoint-dns-name"}) + endpoint_api_url: str = Field(json_schema_extra={"vmanage_key": "endpoint-api-url"}) elements: List[str] boolean: Optional[Boolean] = Boolean.OR threshold: Optional[int] = 300 interval: Optional[int] = 60 multiplier: Optional[int] = 3 type: Optional[Type] = Type.INTERFACE - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class Object(BaseModel): @@ -74,7 +74,7 @@ class Object(BaseModel): class ObjectTrack(BaseModel): - object_number: int = Field(vmanage_key="object-number") + object_number: int = Field(json_schema_extra={"vmanage_key": "object-number"}) interface: str sig: str ip: str @@ -82,9 +82,7 @@ class ObjectTrack(BaseModel): vpn: int object: List[Object] boolean: Boolean - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class Role(str, Enum): @@ -93,11 +91,11 @@ class Role(str, Enum): class AffinityPerVrf(BaseModel): - affinity_group_number: Optional[int] = Field(vmanage_key="affinity-group-number") - vrf_range: Optional[str] = Field(vmanage_key="vrf-range") - - class Config: - allow_population_by_field_name = True + affinity_group_number: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "affinity-group-number"} + ) + vrf_range: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "vrf-range"}) + model_config = ConfigDict(populate_by_name=True) class EnableMrfMigration(str, Enum): @@ -106,11 +104,11 @@ class EnableMrfMigration(str, Enum): class Vrf(BaseModel): - vrf_id: int = Field(vmanage_key="vrf-id") - gateway_preference: Optional[List[int]] = Field(vmanage_key="gateway-preference") - - class Config: - allow_population_by_field_name = True + vrf_id: int = Field(json_schema_extra={"vmanage_key": "vrf-id"}) + gateway_preference: Optional[List[int]] = Field( + default=None, json_schema_extra={"vmanage_key": "gateway-preference"} + ) + model_config = ConfigDict(populate_by_name=True) class Epfr(str, Enum): @@ -121,58 +119,87 @@ class Epfr(str, Enum): class CiscoSystemModel(FeatureTemplate, ConvertBoolToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True - - timezone: Optional[Timezone] = Field(data_path=["clock"]) - hostname: str = Field( - default=DeviceVariable(name="system_host_name"), vmanage_key="host-name", validate_default=True - ) - location: Optional[str] - latitude: Optional[float] = Field(data_path=["gps-location"]) - longitude: Optional[float] = Field(data_path=["gps-location"]) - range: Optional[int] = Field(100, data_path=["gps-location", "geo-fencing"]) - enable_fencing: Optional[bool] = Field(data_path=["gps-location", "geo-fencing"], vmanage_key="enable") + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) + + timezone: Optional[Timezone] = Field(default=None, json_schema_extra={"data_path": ["clock"]}) + hostname: DeviceVariable = Field( + default=DeviceVariable(name="system_host_name"), + validate_default=True, + json_schema_extra={"vmanage_key": "host-name"}, + ) + location: Optional[str] = None + latitude: Optional[float] = Field(default=None, json_schema_extra={"data_path": ["gps-location"]}) + longitude: Optional[float] = Field(default=None, json_schema_extra={"data_path": ["gps-location"]}) + range: Optional[int] = Field(100, json_schema_extra={"data_path": ["gps-location", "geo-fencing"]}) + enable_fencing: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["gps-location", "geo-fencing"], "vmanage_key": "enable"} + ) mobile_number: Optional[List[MobileNumber]] = Field( - vmanage_key="mobile-number", data_path=["gps-location", "geo-fencing", "sms"] - ) - enable_sms: Optional[bool] = Field(False, data_path=["gps-location", "geo-fencing", "sms"], vmanage_key="enable") - device_groups: Optional[List[str]] = Field(vmanage_key="device-groups") - controller_group_list: Optional[List[int]] = Field(vmanage_key="controller-group-list") - system_ip: DeviceVariable = Field(default=DeviceVariable(name="system_system_ip"), vmanage_key="system-ip") - overlay_id: Optional[int] = Field(vmanage_key="overlay-id") - site_id: int = Field(default=DeviceVariable(name="system_site_id"), vmanage_key="site-id") - site_type: Optional[List[SiteType]] = Field(vmanage_key="site-type") - port_offset: Optional[int] = Field(vmanage_key="port-offset") - port_hop: Optional[bool] = Field(vmanage_key="port-hop") - control_session_pps: Optional[int] = Field(vmanage_key="control-session-pps") - track_transport: Optional[bool] = Field(vmanage_key="track-transport") - track_interface_tag: Optional[int] = Field(vmanage_key="track-interface-tag") - console_baud_rate: Optional[ConsoleBaudRate] = Field(vmanage_key="console-baud-rate") - max_omp_sessions: Optional[int] = Field(vmanage_key="max-omp-sessions") - multi_tenant: Optional[bool] = Field(vmanage_key="multi-tenant") - track_default_gateway: Optional[bool] = Field(vmanage_key="track-default-gateway") - admin_tech_on_failure: Optional[bool] = Field(vmanage_key="admin-tech-on-failure") - enable_tunnel: Optional[bool] = Field(vmanage_key="enable", data_path=["on-demand"]) - idle_timeout: Optional[int] = Field(vmanage_key="idle-timeout") - on_demand_idle_timeout_min: Optional[int] = Field(vmanage_key="idle-timeout", data_path=["on-demand"]) - tracker: Optional[List[Tracker]] - object_track: Optional[List[ObjectTrack]] = Field(vmanage_key="object-track") - region_id: Optional[int] = Field(vmanage_key="region-id") - secondary_region: Optional[int] = Field(vmanage_key="secondary-region") - role: Optional[Role] - affinity_group_number: Optional[int] = Field(vmanage_key="affinity-group-number", data_path=["affinity-group"]) - preference: Optional[List[int]] = Field(data_path=["affinity-group"]) - preference_auto: Optional[bool] = Field(vmanage_key="preference-auto") - affinity_per_vrf: Optional[List[AffinityPerVrf]] = Field(vmanage_key="affinity-per-vrf") - transport_gateway: Optional[bool] = Field(vmanage_key="transport-gateway") - enable_mrf_migration: Optional[EnableMrfMigration] = Field(vmanage_key="enable-mrf-migration") - migration_bgp_community: Optional[int] = Field(vmanage_key="migration-bgp-community") - enable_management_region: Optional[bool] = Field(vmanage_key="enable-management-region") - vrf: Optional[List[Vrf]] - management_gateway: Optional[bool] = Field(vmanage_key="management-gateway") - epfr: Optional[Epfr] + default=None, + json_schema_extra={"vmanage_key": "mobile-number", "data_path": ["gps-location", "geo-fencing", "sms"]}, + ) + enable_sms: Optional[bool] = Field( + False, json_schema_extra={"data_path": ["gps-location", "geo-fencing", "sms"], "vmanage_key": "enable"} + ) + device_groups: Optional[List[str]] = Field(default=None, json_schema_extra={"vmanage_key": "device-groups"}) + controller_group_list: Optional[List[int]] = Field( + default=None, json_schema_extra={"vmanage_key": "controller-group-list"} + ) + system_ip: DeviceVariable = Field( + default=DeviceVariable(name="system_system_ip"), json_schema_extra={"vmanage_key": "system-ip"} + ) + overlay_id: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "overlay-id"}) + site_id: int = Field(default=DeviceVariable(name="system_site_id"), json_schema_extra={"vmanage_key": "site-id"}) + site_type: Optional[List[SiteType]] = Field(default=None, json_schema_extra={"vmanage_key": "site-type"}) + port_offset: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "port-offset"}) + port_hop: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "port-hop"}) + control_session_pps: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "control-session-pps"}) + track_transport: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "track-transport"}) + track_interface_tag: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "track-interface-tag"}) + console_baud_rate: Optional[ConsoleBaudRate] = Field( + default=None, json_schema_extra={"vmanage_key": "console-baud-rate"} + ) + max_omp_sessions: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "max-omp-sessions"}) + multi_tenant: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "multi-tenant"}) + track_default_gateway: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "track-default-gateway"} + ) + admin_tech_on_failure: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "admin-tech-on-failure"} + ) + enable_tunnel: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "enable", "data_path": ["on-demand"]} + ) + idle_timeout: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "idle-timeout"}) + on_demand_idle_timeout_min: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "idle-timeout", "data_path": ["on-demand"]} + ) + tracker: Optional[List[Tracker]] = None + object_track: Optional[List[ObjectTrack]] = Field(default=None, json_schema_extra={"vmanage_key": "object-track"}) + region_id: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "region-id"}) + secondary_region: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "secondary-region"}) + role: Optional[Role] = None + affinity_group_number: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "affinity-group-number", "data_path": ["affinity-group"]} + ) + preference: Optional[List[int]] = Field(default=None, json_schema_extra={"data_path": ["affinity-group"]}) + preference_auto: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "preference-auto"}) + affinity_per_vrf: Optional[List[AffinityPerVrf]] = Field( + default=None, json_schema_extra={"vmanage_key": "affinity-per-vrf"} + ) + transport_gateway: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "transport-gateway"}) + enable_mrf_migration: Optional[EnableMrfMigration] = Field( + default=None, json_schema_extra={"vmanage_key": "enable-mrf-migration"} + ) + migration_bgp_community: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "migration-bgp-community"} + ) + enable_management_region: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "enable-management-region"} + ) + vrf: Optional[List[Vrf]] = None + management_gateway: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "management-gateway"}) + epfr: Optional[Epfr] = None payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_system" diff --git a/catalystwan/api/templates/models/cisco_vpn_interface_model.py b/catalystwan/api/templates/models/cisco_vpn_interface_model.py index f7d83ba58..93dc208c4 100644 --- a/catalystwan/api/templates/models/cisco_vpn_interface_model.py +++ b/catalystwan/api/templates/models/cisco_vpn_interface_model.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import Field +from pydantic import ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.pydantic_validators import ConvertBoolToStringModel, ConvertIPToStringModel @@ -21,11 +21,11 @@ class SecondaryIPv4Address(ConvertBoolToStringModel, ConvertIPToStringModel): - address: Optional[ipaddress.IPv4Interface] + address: Optional[ipaddress.IPv4Interface] = None class SecondaryIPv6Address(ConvertBoolToStringModel, ConvertIPToStringModel): - address: Optional[ipaddress.IPv6Interface] + address: Optional[ipaddress.IPv6Interface] = None class Direction(str, Enum): @@ -35,15 +35,13 @@ class Direction(str, Enum): class AccessList(ConvertBoolToStringModel): direction: Direction - acl_name: str = Field(vmanage_key="acl-name") - - class Config: - allow_population_by_field_name = True + acl_name: str = Field(json_schema_extra={"vmanage_key": "acl-name"}) + model_config = ConfigDict(populate_by_name=True) class DhcpHelperV6(ConvertBoolToStringModel, ConvertIPToStringModel): address: ipaddress.IPv6Address - vpn: Optional[int] + vpn: Optional[int] = None class NatChoice(str, Enum): @@ -53,12 +51,10 @@ class NatChoice(str, Enum): class StaticNat66(ConvertBoolToStringModel, ConvertIPToStringModel): - source_prefix: ipaddress.IPv6Interface = Field(vmanage_key="source-prefix") - translated_source_prefix: str = Field(vmanage_key="translated-source-prefix") - source_vpn_id: int = Field(DEFAULT_STATIC_NAT64_SOURCE_VPN_ID, vmanage_key="source-vpn-id") - - class Config: - allow_population_by_field_name = True + source_prefix: ipaddress.IPv6Interface = Field(json_schema_extra={"vmanage_key": "source-prefix"}) + translated_source_prefix: str = Field(json_schema_extra={"vmanage_key": "translated-source-prefix"}) + source_vpn_id: int = Field(DEFAULT_STATIC_NAT64_SOURCE_VPN_ID, json_schema_extra={"vmanage_key": "source-vpn-id"}) + model_config = ConfigDict(populate_by_name=True) class StaticNatDirection(str, Enum): @@ -67,13 +63,13 @@ class StaticNatDirection(str, Enum): class Static(ConvertBoolToStringModel, ConvertIPToStringModel): - source_ip: ipaddress.IPv4Address = Field(vmanage_key="source-ip") - translate_ip: ipaddress.IPv4Address = Field(vmanage_key="translate-ip") - static_nat_direction: StaticNatDirection = Field(StaticNatDirection.INSIDE, vmanage_key="static-nat-direction") - source_vpn: int = Field(DEFAULT_STATIC_NAT_SOURCE_VPN_ID, vmanage_key="source-vpn") - - class Config: - allow_population_by_field_name = True + source_ip: ipaddress.IPv4Address = Field(json_schema_extra={"vmanage_key": "source-ip"}) + translate_ip: ipaddress.IPv4Address = Field(json_schema_extra={"vmanage_key": "translate-ip"}) + static_nat_direction: StaticNatDirection = Field( + StaticNatDirection.INSIDE, json_schema_extra={"vmanage_key": "static-nat-direction"} + ) + source_vpn: int = Field(DEFAULT_STATIC_NAT_SOURCE_VPN_ID, json_schema_extra={"vmanage_key": "source-vpn"}) + model_config = ConfigDict(populate_by_name=True) class Proto(str, Enum): @@ -82,16 +78,18 @@ class Proto(str, Enum): class StaticPortForward(ConvertBoolToStringModel, ConvertIPToStringModel): - source_ip: ipaddress.IPv4Address = Field(vmanage_key="source-ip") - translate_ip: ipaddress.IPv4Address = Field(vmanage_key="translate-ip") - static_nat_direction: StaticNatDirection = Field(StaticNatDirection.INSIDE, vmanage_key="static-nat-direction") - source_port: int = Field(DEFAULT_STATIC_PORT_FORWARD_SOURCE_PORT, vmanage_key="source-port") - translate_port: int = Field(DEFAULT_STATIC_PORT_FORWARD_TRANSLATE_PORT, vmanage_key="translate-port") + source_ip: ipaddress.IPv4Address = Field(json_schema_extra={"vmanage_key": "source-ip"}) + translate_ip: ipaddress.IPv4Address = Field(json_schema_extra={"vmanage_key": "translate-ip"}) + static_nat_direction: StaticNatDirection = Field( + StaticNatDirection.INSIDE, json_schema_extra={"vmanage_key": "static-nat-direction"} + ) + source_port: int = Field(DEFAULT_STATIC_PORT_FORWARD_SOURCE_PORT, json_schema_extra={"vmanage_key": "source-port"}) + translate_port: int = Field( + DEFAULT_STATIC_PORT_FORWARD_TRANSLATE_PORT, json_schema_extra={"vmanage_key": "translate-port"} + ) proto: Proto - source_vpn: int = Field(DEFAULT_STATIC_PORT_FORWARD_SOURCE_VPN, vmanage_key="source-vpn") - - class Config: - allow_population_by_field_name = True + source_vpn: int = Field(DEFAULT_STATIC_PORT_FORWARD_SOURCE_VPN, json_schema_extra={"vmanage_key": "source-vpn"}) + model_config = ConfigDict(populate_by_name=True) class CoreRegion(str, Enum): @@ -112,7 +110,7 @@ class Encap(str, Enum): class Encapsulation(ConvertBoolToStringModel): encap: Encap - preference: Optional[int] + preference: Optional[int] = None weight: int = DEFAULT_ENCAPSULATION_WEIGHT @@ -194,183 +192,252 @@ class TrackAction(str, Enum): class TrackingObject(ConvertBoolToStringModel): name: int - track_action: TrackAction = Field(TrackAction.DECREMENT, vmanage_key="track-action") + track_action: TrackAction = Field(TrackAction.DECREMENT, json_schema_extra={"vmanage_key": "track-action"}) decrement: int - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class Vrrp(ConvertBoolToStringModel, ConvertIPToStringModel): - grp_id: int = Field(vmanage_key="grp-id") + grp_id: int = Field(json_schema_extra={"vmanage_key": "grp-id"}) priority: int = DEFAULT_VRRP_PRIORITY timer: int = DEFAULT_VRRP_TIMER - track_omp: bool = Field(False, vmanage_key="track-omp") - track_prefix_list: Optional[str] = Field(vmanage_key="track-prefix-list") - address: Optional[ipaddress.IPv4Address] = Field(data_path=["ipv4"], vmanage_key="address") - ipv4_secondary: Optional[List[Ipv4Secondary]] = Field(vmanage_key="ipv4-secondary") - tloc_change_pref: bool = Field(False, vmanage_key="tloc-change-pref") + track_omp: bool = Field(False, json_schema_extra={"vmanage_key": "track-omp"}) + track_prefix_list: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "track-prefix-list"}) + address: Optional[ipaddress.IPv4Address] = Field( + default=None, json_schema_extra={"data_path": ["ipv4"], "vmanage_key": "address"} + ) + ipv4_secondary: Optional[List[Ipv4Secondary]] = Field( + default=None, json_schema_extra={"vmanage_key": "ipv4-secondary"} + ) + tloc_change_pref: bool = Field(False, json_schema_extra={"vmanage_key": "tloc-change-pref"}) value: int - tracking_object: Optional[List[TrackingObject]] = Field(vmanage_key="tracking-object") - - class Config: - allow_population_by_field_name = True + tracking_object: Optional[List[TrackingObject]] = Field( + default=None, json_schema_extra={"vmanage_key": "tracking-object"} + ) + model_config = ConfigDict(populate_by_name=True) class Ipv6(ConvertBoolToStringModel, ConvertIPToStringModel): - ipv6_link_local: ipaddress.IPv6Address = Field(vmanage_key="ipv6-link-local") - prefix: Optional[ipaddress.IPv6Interface] - - class Config: - allow_population_by_field_name = True + ipv6_link_local: ipaddress.IPv6Address = Field(json_schema_extra={"vmanage_key": "ipv6-link-local"}) + prefix: Optional[ipaddress.IPv6Interface] = None + model_config = ConfigDict(populate_by_name=True) class Ipv6Vrrp(ConvertBoolToStringModel): - grp_id: int = Field(vmanage_key="grp-id") + grp_id: int = Field(json_schema_extra={"vmanage_key": "grp-id"}) priority: int = DEFAULT_IPV6_VRRP_PRIORITY timer: int = DEFAULT_IPV6_VRRP_TIMER - track_omp: bool = Field(False, vmanage_key="track-omp") - track_prefix_list: Optional[str] = Field(vmanage_key="track-prefix-list") - ipv6: Optional[List[Ipv6]] - - class Config: - allow_population_by_field_name = True + track_omp: bool = Field(False, json_schema_extra={"vmanage_key": "track-omp"}) + track_prefix_list: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "track-prefix-list"}) + ipv6: Optional[List[Ipv6]] = None + model_config = ConfigDict(populate_by_name=True) class CiscoVpnInterfaceModel(FeatureTemplate, ConvertBoolToStringModel, ConvertIPToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True - - if_name: str = Field(vmanage_key="if-name") - interface_description: Optional[str] = Field(vmanage_key="description") - poe: Optional[bool] - ipv4_address: Optional[str] = Field(data_path=["ip"], vmanage_key="address") + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) + + if_name: str = Field(json_schema_extra={"vmanage_key": "if-name"}) + interface_description: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "description"}) + poe: Optional[bool] = None + ipv4_address: Optional[str] = Field(default=None, json_schema_extra={"data_path": ["ip"], "vmanage_key": "address"}) secondary_ipv4_address: Optional[List[SecondaryIPv4Address]] = Field( - data_path=["ip"], vmanage_key="secondary-address" + default=None, json_schema_extra={"data_path": ["ip"], "vmanage_key": "secondary-address"} + ) + dhcp_ipv4_client: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "dhcp-client"}) + dhcp_distance: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "dhcp-distance"}) + ipv6_address: Optional[ipaddress.IPv6Interface] = Field( + default=None, json_schema_extra={"data_path": ["ipv6"], "vmanage_key": "address"} ) - dhcp_ipv4_client: Optional[bool] = Field(vmanage_key="dhcp-client") - dhcp_distance: Optional[int] = Field(vmanage_key="dhcp-distance") - ipv6_address: Optional[ipaddress.IPv6Interface] = Field(data_path=["ipv6"], vmanage_key="address") - dhcp_ipv6_client: Optional[bool] = Field(vmanage_key="dhcp-client") + dhcp_ipv6_client: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "dhcp-client"}) secondary_ipv6_address: Optional[List[SecondaryIPv6Address]] = Field( - data_path=["ipv6"], vmanage_key="secondary-address" - ) - access_list_ipv4: Optional[List[AccessList]] = Field(vmanage_key="access-list") - dhcp_helper: Optional[List[ipaddress.IPv4Address]] = Field(vmanage_key="dhcp-helper") - dhcp_helper_v6: Optional[List[DhcpHelperV6]] = Field(vmanage_key="dhcp-helper-v6") - tracker: Optional[List[str]] - auto_bandwidth_detect: Optional[bool] = Field(vmanage_key="auto-bandwidth-detect") - iperf_server: Optional[ipaddress.IPv4Address] = Field(vmanage_key="iperf-server") - nat: Optional[bool] - nat_choice: Optional[NatChoice] = Field(vmanage_key="nat-choice") - udp_timeout: Optional[int] = Field(vmanage_key="udp-timeout") - tcp_timeout: Optional[int] = Field(vmanage_key="tcp-timeout") - nat_range_start: Optional[ipaddress.IPv4Address] = Field(vmanage_key="range-start") - nat_range_end: Optional[ipaddress.IPv4Address] = Field(vmanage_key="range-end") - overload: Optional[bool] - loopback_interface: Optional[str] = Field(vmanage_key="loopback-interface") - prefix_length: Optional[int] = Field(vmanage_key="prefix-length") - enable: Optional[bool] - nat64: Optional[bool] - nat66: Optional[bool] - static_nat66: Optional[List[StaticNat66]] = Field(vmanage_key="static-nat66") - static: Optional[List[Static]] = Field(data_path=["nat"], vmanage_key="static") - static_port_forward: Optional[List[StaticPortForward]] = Field(vmanage_key="static-port-forward") - enable_core_region: Optional[bool] = Field(vmanage_key="enable-core-region") - core_region: Optional[CoreRegion] = Field(vmanage_key="core-region") - secondary_region: Optional[SecondaryRegion] = Field(vmanage_key="secondary-region") + default=None, json_schema_extra={"data_path": ["ipv6"], "vmanage_key": "secondary-address"} + ) + access_list_ipv4: Optional[List[AccessList]] = Field(default=None, json_schema_extra={"vmanage_key": "access-list"}) + dhcp_helper: Optional[List[ipaddress.IPv4Address]] = Field( + default=None, json_schema_extra={"vmanage_key": "dhcp-helper"} + ) + dhcp_helper_v6: Optional[List[DhcpHelperV6]] = Field( + default=None, json_schema_extra={"vmanage_key": "dhcp-helper-v6"} + ) + tracker: Optional[List[str]] = None + auto_bandwidth_detect: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "auto-bandwidth-detect"} + ) + iperf_server: Optional[ipaddress.IPv4Address] = Field( + default=None, json_schema_extra={"vmanage_key": "iperf-server"} + ) + nat: Optional[bool] = None + nat_choice: Optional[NatChoice] = Field(default=None, json_schema_extra={"vmanage_key": "nat-choice"}) + udp_timeout: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "udp-timeout"}) + tcp_timeout: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "tcp-timeout"}) + nat_range_start: Optional[ipaddress.IPv4Address] = Field( + default=None, json_schema_extra={"vmanage_key": "range-start"} + ) + nat_range_end: Optional[ipaddress.IPv4Address] = Field(default=None, json_schema_extra={"vmanage_key": "range-end"}) + overload: Optional[bool] = None + loopback_interface: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "loopback-interface"}) + prefix_length: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "prefix-length"}) + enable: Optional[bool] = None + nat64: Optional[bool] = None + nat66: Optional[bool] = None + static_nat66: Optional[List[StaticNat66]] = Field(default=None, json_schema_extra={"vmanage_key": "static-nat66"}) + static: Optional[List[Static]] = Field( + default=None, json_schema_extra={"data_path": ["nat"], "vmanage_key": "static"} + ) + static_port_forward: Optional[List[StaticPortForward]] = Field( + default=None, json_schema_extra={"vmanage_key": "static-port-forward"} + ) + enable_core_region: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "enable-core-region"}) + core_region: Optional[CoreRegion] = Field(default=None, json_schema_extra={"vmanage_key": "core-region"}) + secondary_region: Optional[SecondaryRegion] = Field( + default=None, json_schema_extra={"vmanage_key": "secondary-region"} + ) tloc_encapsulation: Optional[List[Encapsulation]] = Field( - vmanage_key="encapsulation", data_path=["tunnel-interface"] - ) - border: Optional[bool] = Field(data_path=["tunnel-interface"]) - per_tunnel_qos: Optional[bool] = Field(vmanage_key="per-tunnel-qos") - per_tunnel_qos_aggregator: Optional[bool] = Field(vmanage_key="per-tunnel-qos-aggregator") - mode: Optional[Mode] - tunnels_bandwidth: Optional[int] = Field(vmanage_key="tunnels-bandwidth") - group: Optional[List[int]] = Field(data_path=["tunnel-interface"]) - value: Optional[Value] = Field(data_path=["tunnel-interface", "color"]) + default=None, json_schema_extra={"vmanage_key": "encapsulation", "data_path": ["tunnel-interface"]} + ) + border: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface"]}) + per_tunnel_qos: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "per-tunnel-qos"}) + per_tunnel_qos_aggregator: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "per-tunnel-qos-aggregator"} + ) + mode: Optional[Mode] = None + tunnels_bandwidth: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "tunnels-bandwidth"}) + group: Optional[List[int]] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface"]}) + value: Optional[Value] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "color"]}) max_control_connections: Optional[int] = Field( - vmanage_key="max-control-connections", data_path=["tunnel-interface"] + default=None, json_schema_extra={"vmanage_key": "max-control-connections", "data_path": ["tunnel-interface"]} + ) + control_connections: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "control-connections", "data_path": ["tunnel-interface"]} + ) + vbond_as_stun_server: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "vbond-as-stun-server", "data_path": ["tunnel-interface"]} ) - control_connections: Optional[bool] = Field(vmanage_key="control-connections", data_path=["tunnel-interface"]) - vbond_as_stun_server: Optional[bool] = Field(vmanage_key="vbond-as-stun-server", data_path=["tunnel-interface"]) exclude_controller_group_list: Optional[List[int]] = Field( - vmanage_key="exclude-controller-group-list", data_path=["tunnel-interface"] + default=None, + json_schema_extra={"vmanage_key": "exclude-controller-group-list", "data_path": ["tunnel-interface"]}, ) vmanage_connection_preference: Optional[int] = Field( - vmanage_key="vmanage-connection-preference", data_path=["tunnel-interface"] + default=None, + json_schema_extra={"vmanage_key": "vmanage-connection-preference", "data_path": ["tunnel-interface"]}, ) - port_hop: Optional[bool] = Field(vmanage_key="port-hop", data_path=["tunnel-interface"]) - restrict: Optional[bool] = Field(data_path=["tunnel-interface", "color"]) + port_hop: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "port-hop", "data_path": ["tunnel-interface"]} + ) + restrict: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "color"]}) dst_ip: Optional[ipaddress.IPv4Address] = Field( - vmanage_key="dst-ip", data_path=["tunnel-interface", "tloc-extension-gre-to"] - ) - carrier: Optional[Carrier] = Field(data_path=["tunnel-interface"]) - nat_refresh_interval: Optional[int] = Field(vmanage_key="nat-refresh-interval", data_path=["tunnel-interface"]) - hello_interval: Optional[int] = Field(vmanage_key="hello-interval", data_path=["tunnel-interface"]) - hello_tolerance: Optional[int] = Field(vmanage_key="hello-tolerance", data_path=["tunnel-interface"]) - bind: Optional[str] = Field(data_path=["tunnel-interface"]) - last_resort_circuit: Optional[bool] = Field(vmanage_key="last-resort-circuit", data_path=["tunnel-interface"]) - low_bandwidth_link: Optional[bool] = Field(vmanage_key="low-bandwidth-link", data_path=["tunnel-interface"]) - tunnel_tcp_mss_adjust: Optional[int] = Field(vmanage_key="tunnel-tcp-mss-adjust", data_path=["tunnel-interface"]) - clear_dont_fragment: Optional[bool] = Field(vmanage_key="clear-dont-fragment", data_path=["tunnel-interface"]) - propagate_sgt: Optional[bool] = Field(data_path=["tunnel-interface"], vmanage_key="propagate-sgt") - network_broadcast: Optional[bool] = Field(vmanage_key="network-broadcast", data_path=["tunnel-interface"]) - all: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - bgp: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - dhcp: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - dns: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - icmp: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - sshd: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - netconf: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - ntp: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - ospf: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - stun: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - snmp: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - https: Optional[bool] = Field(data_path=["tunnel-interface", "allow-service"]) - media_type: Optional[MediaType] = Field(vmanage_key="media-type") - intrf_mtu: Optional[int] = Field(vmanage_key="intrf-mtu") - mtu: Optional[int] - tcp_mss_adjust: Optional[int] = Field(vmanage_key="tcp-mss-adjust") - tloc_extension: Optional[str] = Field(vmanage_key="tloc-extension") - load_interval: Optional[int] = Field(vmanage_key="load-interval") - src_ip: Optional[ipaddress.IPv4Address] = Field(vmanage_key="src-ip", data_path=["tloc-extension-gre-from"]) - xconnect: Optional[str] = Field(data_path=["tloc-extension-gre-from"]) - mac_address: Optional[str] = Field(vmanage_key="mac-address") - speed: Optional[Speed] - duplex: Optional[Duplex] + default=None, + json_schema_extra={"vmanage_key": "dst-ip", "data_path": ["tunnel-interface", "tloc-extension-gre-to"]}, + ) + carrier: Optional[Carrier] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface"]}) + nat_refresh_interval: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "nat-refresh-interval", "data_path": ["tunnel-interface"]} + ) + hello_interval: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "hello-interval", "data_path": ["tunnel-interface"]} + ) + hello_tolerance: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "hello-tolerance", "data_path": ["tunnel-interface"]} + ) + bind: Optional[str] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface"]}) + last_resort_circuit: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "last-resort-circuit", "data_path": ["tunnel-interface"]} + ) + low_bandwidth_link: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "low-bandwidth-link", "data_path": ["tunnel-interface"]} + ) + tunnel_tcp_mss_adjust: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "tunnel-tcp-mss-adjust", "data_path": ["tunnel-interface"]} + ) + clear_dont_fragment: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "clear-dont-fragment", "data_path": ["tunnel-interface"]} + ) + propagate_sgt: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["tunnel-interface"], "vmanage_key": "propagate-sgt"} + ) + network_broadcast: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "network-broadcast", "data_path": ["tunnel-interface"]} + ) + all: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + bgp: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + dhcp: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + dns: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + icmp: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + sshd: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + netconf: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]} + ) + ntp: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + ospf: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + stun: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + snmp: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + https: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["tunnel-interface", "allow-service"]}) + media_type: Optional[MediaType] = Field(default=None, json_schema_extra={"vmanage_key": "media-type"}) + intrf_mtu: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "intrf-mtu"}) + mtu: Optional[int] = None + tcp_mss_adjust: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "tcp-mss-adjust"}) + tloc_extension: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "tloc-extension"}) + load_interval: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "load-interval"}) + src_ip: Optional[ipaddress.IPv4Address] = Field( + default=None, json_schema_extra={"vmanage_key": "src-ip", "data_path": ["tloc-extension-gre-from"]} + ) + xconnect: Optional[str] = Field(default=None, json_schema_extra={"data_path": ["tloc-extension-gre-from"]}) + mac_address: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "mac-address"}) + speed: Optional[Speed] = None + duplex: Optional[Duplex] = None shutdown: Optional[bool] = False - arp_timeout: Optional[int] = Field(vmanage_key="arp-timeout") - autonegotiate: Optional[bool] - ip_directed_broadcast: Optional[bool] = Field(vmanage_key="ip-directed-broadcast") - icmp_redirect_disable: Optional[bool] = Field(vmanage_key="icmp-redirect-disable") - qos_adaptive: Optional[bool] = Field(vmanage_key="qos-adaptive") - period: Optional[int] = Field(data_path=["qos-adaptive"]) - bandwidth_down: Optional[int] = Field(vmanage_key="bandwidth-down", data_path=["qos-adaptive", "downstream"]) - dmin: Optional[int] = Field(data_path=["qos-adaptive", "downstream", "range"]) - dmax: Optional[int] = Field(data_path=["qos-adaptive", "downstream", "range"]) - bandwidth_up: Optional[int] = Field(vmanage_key="bandwidth-up", data_path=["qos-adaptive", "upstream"]) - umin: Optional[int] = Field(data_path=["qos-adaptive", "upstream", "range"]) - umax: Optional[int] = Field(data_path=["qos-adaptive", "upstream", "range"]) - shaping_rate: Optional[int] = Field(vmanage_key="shaping-rate") - qos_map: Optional[str] = Field(vmanage_key="qos-map") - qos_map_vpn: Optional[str] = Field(vmanage_key="qos-map-vpn") - service_provider: Optional[str] = Field(vmanage_key="service-provider") - bandwidth_upstream: Optional[int] = Field(vmanage_key="bandwidth-upstream") - bandwidth_downstream: Optional[int] = Field(vmanage_key="bandwidth-downstream") - block_non_source_ip: Optional[bool] = Field(vmanage_key="block-non-source-ip") - rule_name: Optional[str] = Field(vmanage_key="rule-name", data_path=["rewrite-rule"]) - access_list_ipv6: Optional[List[AccessList]] = Field(data_path=["ipv6"], vmanage_key="access-list") - ip: Optional[List[Ip]] = Field(data_path=["arp"]) - vrrp: Optional[List[Vrrp]] = Field(vmanage_key="vrrp") - ipv6_vrrp: Optional[List[Ipv6Vrrp]] = Field(vmanage_key="ipv6-vrrp") - enable_sgt_propagation: Optional[bool] = Field(data_path=["trustsec", "propagate"], vmanage_key="sgt") - security_group_tag: Optional[int] = Field(data_path=["trustsec", "static"], vmanage_key="sgt") - trusted: Optional[bool] = Field(data_path=["trustsec", "static"]) - enable_sgt_authorization_and_forwarding: Optional[bool] = Field(data_path=["trustsec"], vmanage_key="enable") - enable_sgt_enforcement: Optional[bool] = Field(data_path=["trustsec", "enforcement"], vmanage_key="enable") - enforcement_sgt: Optional[int] = Field(data_path=["trustsec", "enforcement"], vmanage_key="sgt") + arp_timeout: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "arp-timeout"}) + autonegotiate: Optional[bool] = None + ip_directed_broadcast: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "ip-directed-broadcast"} + ) + icmp_redirect_disable: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "icmp-redirect-disable"} + ) + qos_adaptive: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "qos-adaptive"}) + period: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["qos-adaptive"]}) + bandwidth_down: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "bandwidth-down", "data_path": ["qos-adaptive", "downstream"]} + ) + dmin: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["qos-adaptive", "downstream", "range"]}) + dmax: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["qos-adaptive", "downstream", "range"]}) + bandwidth_up: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "bandwidth-up", "data_path": ["qos-adaptive", "upstream"]} + ) + umin: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["qos-adaptive", "upstream", "range"]}) + umax: Optional[int] = Field(default=None, json_schema_extra={"data_path": ["qos-adaptive", "upstream", "range"]}) + shaping_rate: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "shaping-rate"}) + qos_map: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "qos-map"}) + qos_map_vpn: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "qos-map-vpn"}) + service_provider: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "service-provider"}) + bandwidth_upstream: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "bandwidth-upstream"}) + bandwidth_downstream: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "bandwidth-downstream"}) + block_non_source_ip: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "block-non-source-ip"}) + rule_name: Optional[str] = Field( + default=None, json_schema_extra={"vmanage_key": "rule-name", "data_path": ["rewrite-rule"]} + ) + access_list_ipv6: Optional[List[AccessList]] = Field( + default=None, json_schema_extra={"data_path": ["ipv6"], "vmanage_key": "access-list"} + ) + ip: Optional[List[Ip]] = Field(default=None, json_schema_extra={"data_path": ["arp"]}) + vrrp: Optional[List[Vrrp]] = Field(default=None, json_schema_extra={"vmanage_key": "vrrp"}) + ipv6_vrrp: Optional[List[Ipv6Vrrp]] = Field(default=None, json_schema_extra={"vmanage_key": "ipv6-vrrp"}) + enable_sgt_propagation: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["trustsec", "propagate"], "vmanage_key": "sgt"} + ) + security_group_tag: Optional[int] = Field( + default=None, json_schema_extra={"data_path": ["trustsec", "static"], "vmanage_key": "sgt"} + ) + trusted: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["trustsec", "static"]}) + enable_sgt_authorization_and_forwarding: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["trustsec"], "vmanage_key": "enable"} + ) + enable_sgt_enforcement: Optional[bool] = Field( + default=None, json_schema_extra={"data_path": ["trustsec", "enforcement"], "vmanage_key": "enable"} + ) + enforcement_sgt: Optional[int] = Field( + default=None, json_schema_extra={"data_path": ["trustsec", "enforcement"], "vmanage_key": "sgt"} + ) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_vpn_interface" diff --git a/catalystwan/api/templates/models/cisco_vpn_model.py b/catalystwan/api/templates/models/cisco_vpn_model.py index 013276620..6320bcb69 100644 --- a/catalystwan/api/templates/models/cisco_vpn_model.py +++ b/catalystwan/api/templates/models/cisco_vpn_model.py @@ -2,7 +2,7 @@ from pathlib import Path from typing import ClassVar, List, Optional -from pydantic.v1 import BaseModel, Field, validator +from pydantic import BaseModel, ConfigDict, Field, field_validator from catalystwan.api.templates.feature_template import FeatureTemplate @@ -13,19 +13,15 @@ class Role(str, Enum): class Dns(BaseModel): - dns_addr: str = Field(vmanage_key="dns-addr") + dns_addr: str = Field(json_schema_extra={"vmanage_key": "dns-addr"}) role: Role = Role.PRIMARY - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class DnsIpv6(BaseModel): - dns_addr: str = Field(vmanage_key="dns-addr") + dns_addr: str = Field(json_schema_extra={"vmanage_key": "dns-addr"}) role: Optional[Role] = Role.PRIMARY - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class Host(BaseModel): @@ -46,15 +42,14 @@ class SvcType(str, Enum): class Service(BaseModel): - svc_type: SvcType = Field(vmanage_key="svc-type") + svc_type: SvcType = Field(json_schema_extra={"vmanage_key": "svc-type"}) address: List[str] interface: str - track_enable: bool = Field(True, vmanage_key="track-enable") - - class Config: - allow_population_by_field_name = True + track_enable: bool = Field(True, json_schema_extra={"vmanage_key": "track-enable"}) + model_config = ConfigDict(populate_by_name=True) - @validator("track_enable") + @field_validator("track_enable") + @classmethod def convert_to_string(cls, value): return str(value).lower() @@ -82,15 +77,17 @@ class NextHopWithTrack(BaseModel): class Routev4(BaseModel): prefix: str - 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] + next_hop: Optional[List[NextHop]] = Field( + default=None, json_schema_extra={"vmanage_key": "next-hop", "priority_order": ["address", "distance"]} + ) + next_hop_with_track: Optional[List[NextHopWithTrack]] = Field( + default=None, json_schema_extra={"vmanage_key": "next-hop-with-track"} + ) + null0: Optional[bool] = None distance: Optional[int] = None - vpn: Optional[int] - dhcp: Optional[bool] - - class Config: - allow_population_by_field_name = True + vpn: Optional[int] = None + dhcp: Optional[bool] = None + model_config = ConfigDict(populate_by_name=True) class NextHopv6(BaseModel): @@ -105,25 +102,23 @@ class Nat(str, Enum): class Routev6(BaseModel): prefix: str - next_hop: Optional[List[NextHopv6]] = Field(vmanage_key="next-hop") - null0: Optional[bool] - vpn: Optional[int] - nat: Optional[Nat] - - class Config: - allow_population_by_field_name = True + next_hop: Optional[List[NextHopv6]] = Field(default=None, json_schema_extra={"vmanage_key": "next-hop"}) + null0: Optional[bool] = None + vpn: Optional[int] = None + nat: Optional[Nat] = None + model_config = ConfigDict(populate_by_name=True) class GreRoute(BaseModel): prefix: str vpn: int - interface: Optional[List[str]] + interface: Optional[List[str]] = None class IpsecRoute(BaseModel): prefix: str vpn: int - interface: Optional[List[str]] + interface: Optional[List[str]] = None class AdvertiseProtocol(str, Enum): @@ -149,22 +144,20 @@ class Region(str, Enum): class PrefixList(BaseModel): - prefix_entry: str = Field(vmanage_key="prefix-entry") - aggregate_only: Optional[bool] = Field(vmanage_key="aggregate-only") + prefix_entry: str = Field(json_schema_extra={"vmanage_key": "prefix-entry"}) + aggregate_only: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "aggregate-only"}) region: Optional[Region] - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class Advertise(BaseModel): protocol: AdvertiseProtocol - route_policy: Optional[str] = Field(vmanage_key="route-policy") - protocol_sub_type: Optional[List[AdvertiseProtocolSubType]] = Field(vmanage_key="protocol-sub-type") - prefix_list: Optional[List[PrefixList]] = Field(vmanage_key="prefix-list") - - class Config: - allow_population_by_field_name = True + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + protocol_sub_type: Optional[List[AdvertiseProtocolSubType]] = Field( + default=None, json_schema_extra={"vmanage_key": "protocol-sub-type"} + ) + prefix_list: Optional[List[PrefixList]] = Field(default=None, json_schema_extra={"vmanage_key": "prefix-list"}) + model_config = ConfigDict(populate_by_name=True) class Ipv6AdvertiseProtocol(str, Enum): @@ -182,12 +175,12 @@ class Ipv6AdvertiseProtocolSubType(str, Enum): class Ipv6Advertise(BaseModel): protocol: Ipv6AdvertiseProtocol - route_policy: Optional[str] = Field(vmanage_key="route-policy") - protocol_sub_type: Optional[List[Ipv6AdvertiseProtocolSubType]] = Field(vmanage_key="protocol-sub-type") - prefix_list: Optional[List[PrefixList]] = Field(vmanage_key="prefix-list") - - class Config: - allow_population_by_field_name = True + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + protocol_sub_type: Optional[List[Ipv6AdvertiseProtocolSubType]] = Field( + default=None, json_schema_extra={"vmanage_key": "protocol-sub-type"} + ) + prefix_list: Optional[List[PrefixList]] = Field(default=None, json_schema_extra={"vmanage_key": "prefix-list"}) + model_config = ConfigDict(populate_by_name=True) class LeakFromGlobalProtocol(str, Enum): @@ -201,15 +194,13 @@ class LeakFromGlobalProtocol(str, Enum): class Pool(BaseModel): name: str - start_address: str = Field(vmanage_key="start-address") - end_address: str = Field(vmanage_key="end-address") - overload: Optional[bool] + start_address: str = Field(json_schema_extra={"vmanage_key": "start-address"}) + end_address: str = Field(json_schema_extra={"vmanage_key": "end-address"}) + overload: Optional[bool] = None leak_from_global: bool leak_from_global_protocol: LeakFromGlobalProtocol leak_to_global: bool - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class Direction(str, Enum): @@ -224,15 +215,13 @@ class Overload(str, Enum): class Natpool(BaseModel): name: int - prefix_length: int = Field(vmanage_key="prefix-length") - range_start: str = Field(vmanage_key="range-start") - range_end: str = Field(vmanage_key="range-end") + prefix_length: int = Field(json_schema_extra={"vmanage_key": "prefix-length"}) + range_start: str = Field(json_schema_extra={"vmanage_key": "range-start"}) + range_end: str = Field(json_schema_extra={"vmanage_key": "range-end"}) overload: Overload = Overload.TRUE direction: Direction - tracker_id: Optional[int] = Field(vmanage_key="tracker-id") - - class Config: - allow_population_by_field_name = True + tracker_id: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "tracker-id"}) + model_config = ConfigDict(populate_by_name=True) class StaticNatDirection(str, Enum): @@ -241,25 +230,21 @@ class StaticNatDirection(str, Enum): class Static(BaseModel): - pool_name: Optional[int] = Field(vmanage_key="pool-name") - source_ip: str = Field(vmanage_key="source-ip") - translate_ip: str = Field(vmanage_key="translate-ip") - static_nat_direction: StaticNatDirection = Field(vmanage_key="static-nat-direction") - tracker_id: Optional[int] = Field(vmanage_key="tracker-id") - - class Config: - allow_population_by_field_name = True + pool_name: Optional[int] = Field(json_schema_extra={"vmanage_key": "pool-name"}) + source_ip: str = Field(json_schema_extra={"vmanage_key": "source-ip"}) + translate_ip: str = Field(json_schema_extra={"vmanage_key": "translate-ip"}) + static_nat_direction: StaticNatDirection = Field(json_schema_extra={"vmanage_key": "static-nat-direction"}) + tracker_id: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "tracker-id"}) + model_config = ConfigDict(populate_by_name=True) class SubnetStatic(BaseModel): - source_ip_subnet: str = Field(vmanage_key="source-ip-subnet") - translate_ip_subnet: str = Field(vmanage_key="translate-ip-subnet") - prefix_length: int = Field(vmanage_key="prefix-length") - static_nat_direction: StaticNatDirection = Field(vmanage_key="static-nat-direction") - tracker_id: Optional[int] = Field(vmanage_key="tracker-id") - - class Config: - allow_population_by_field_name = True + source_ip_subnet: str = Field(json_schema_extra={"vmanage_key": "source-ip-subnet"}) + translate_ip_subnet: str = Field(json_schema_extra={"vmanage_key": "translate-ip-subnet"}) + prefix_length: int = Field(json_schema_extra={"vmanage_key": "prefix-length"}) + static_nat_direction: StaticNatDirection = Field(json_schema_extra={"vmanage_key": "static-nat-direction"}) + tracker_id: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "tracker-id"}) + model_config = ConfigDict(populate_by_name=True) class Proto(str, Enum): @@ -268,15 +253,13 @@ class Proto(str, Enum): class PortForward(BaseModel): - pool_name: Optional[int] = Field(vmanage_key="pool-name") - source_port: int = Field(vmanage_key="source-port") - translate_port: int = Field(vmanage_key="translate-port") - source_ip: str = Field(vmanage_key="source-ip") - translate_ip: str = Field(vmanage_key="translate-ip") + pool_name: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "pool-name"}) + source_port: int = Field(json_schema_extra={"vmanage_key": "source-port"}) + translate_port: int = Field(json_schema_extra={"vmanage_key": "translate-port"}) + source_ip: str = Field(json_schema_extra={"vmanage_key": "source-ip"}) + translate_ip: str = Field(json_schema_extra={"vmanage_key": "translate-ip"}) proto: Proto - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class RouteImportProtocol(str, Enum): @@ -298,20 +281,16 @@ class RouteImportRedistributeProtocol(str, Enum): class RouteImportRedistribute(BaseModel): protocol: RouteImportRedistributeProtocol - route_policy: Optional[str] = Field(vmanage_key="route-policy") - - class Config: - allow_population_by_field_name = True + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + model_config = ConfigDict(populate_by_name=True) class RouteImport(BaseModel): protocol: RouteImportProtocol - protocol_sub_type: List[RouteImportProtocolSubType] = Field(vmanage_key="protocol-sub-type") - route_policy: Optional[str] = Field(vmanage_key="route-policy") - redistribute: Optional[List[RouteImportRedistribute]] - - class Config: - allow_population_by_field_name = True + protocol_sub_type: List[RouteImportProtocolSubType] = Field(json_schema_extra={"vmanage_key": "protocol-sub-type"}) + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + redistribute: Optional[List[RouteImportRedistribute]] = None + model_config = ConfigDict(populate_by_name=True) class RouteImportFromProtocol(str, Enum): @@ -334,21 +313,19 @@ class RouteImportFromRedistributeProtocol(str, Enum): class RouteImportFromRedistribute(BaseModel): protocol: RouteImportFromRedistributeProtocol - route_policy: Optional[str] = Field(vmanage_key="route-policy") - - class Config: - allow_population_by_field_name = True + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + model_config = ConfigDict(populate_by_name=True) class RouteImportFrom(BaseModel): - source_vpn: int = Field(vmanage_key="source-vpn") + source_vpn: int = Field(json_schema_extra={"vmanage_key": "source-vpn"}) protocol: RouteImportFromProtocol - protocol_sub_type: List[RouteImportFromProtocolSubType] = Field(vmanage_key="protocol-sub-type") - route_policy: Optional[str] = Field(vmanage_key="route-policy") - redistribute: Optional[List[RouteImportFromRedistribute]] - - class Config: - allow_population_by_field_name = True + protocol_sub_type: List[RouteImportFromProtocolSubType] = Field( + json_schema_extra={"vmanage_key": "protocol-sub-type"} + ) + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + redistribute: Optional[List[RouteImportFromRedistribute]] = None + model_config = ConfigDict(populate_by_name=True) class RouteExportProtocol(str, Enum): @@ -370,55 +347,74 @@ class RouteExportRedistributeProtocol(str, Enum): class RouteExportRedistribute(BaseModel): protocol: RouteExportRedistributeProtocol - route_policy: Optional[str] = Field(vmanage_key="route-policy") - - class Config: - allow_population_by_field_name = True + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) + model_config = ConfigDict(populate_by_name=True) class RouteExport(BaseModel): protocol: RouteExportProtocol - protocol_sub_type: List[RouteExportProtocolSubType] = Field(vmanage_key="protocol-sub-type") - route_policy: Optional[str] = Field(vmanage_key="route-policy") + protocol_sub_type: List[RouteExportProtocolSubType] = Field(json_schema_extra={"vmanage_key": "protocol-sub-type"}) + route_policy: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "route-policy"}) redistribute: Optional[List[RouteExportRedistribute]] - - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) class CiscoVPNModel(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True - - vpn_id: int = Field(vmanage_key="vpn-id", default=0) - vpn_name: Optional[str] = Field(vmanage_key="name") - tenant_vpn_id: Optional[int] = Field(vmanage_key="tenant-vpn-id") - org_name: Optional[str] = Field(vmanage_key="org-name") - omp_admin_distance_ipv4: Optional[int] = Field(vmanage_key="omp-admin-distance-ipv4") - omp_admin_distance_ipv6: Optional[int] = Field(vmanage_key="omp-admin-distance-ipv6") - 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]] = Field(priority_order=["hostname", "ip"]) - service: Optional[List[Service]] - service_route: Optional[List[ServiceRoute]] = Field(data_path=["ip"], vmanage_key="service-route") + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) + + vpn_id: int = Field(default=0, json_schema_extra={"vmanage_key": "vpn-id"}) + vpn_name: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "name"}) + tenant_vpn_id: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "tenant-vpn-id"}) + org_name: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "org-name"}) + omp_admin_distance_ipv4: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "omp-admin-distance-ipv4"} + ) + omp_admin_distance_ipv6: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "omp-admin-distance-ipv6"} + ) + dns: Optional[List[Dns]] = None + dns_ipv6: Optional[List[DnsIpv6]] = Field(default=None, json_schema_extra={"vmanage_key": "dns-ipv6"}) + layer4: Optional[bool] = Field(default=None, json_schema_extra={"data_path": ["ecmp-hash-key"]}) + host: Optional[List[Host]] = Field(default=None, json_schema_extra={"priority_order": ["hostname", "ip"]}) + service: Optional[List[Service]] = None + service_route: Optional[List[ServiceRoute]] = Field( + default=None, json_schema_extra={"data_path": ["ip"], "vmanage_key": "service-route"} + ) route_v4: Optional[List[Routev4]] = Field( - data_path=["ip"], vmanage_key="route", priority_order=["prefix", "next-hop", "next-hop-with-track"] + default=None, + json_schema_extra={ + "data_path": ["ip"], + "vmanage_key": "route", + "priority_order": ["prefix", "next-hop", "next-hop-with-track"], + }, + ) + route_v6: Optional[List[Routev6]] = Field( + default=None, json_schema_extra={"data_path": ["ipv6"], "vmanage_key": "route"} + ) + gre_route: Optional[List[GreRoute]] = Field( + default=None, json_schema_extra={"data_path": ["ip"], "vmanage_key": "gre-route"} + ) + ipsec_route: Optional[List[IpsecRoute]] = Field( + default=None, json_schema_extra={"data_path": ["ip"], "vmanage_key": "ipsec-route"} + ) + advertise: Optional[List[Advertise]] = Field(default=None, json_schema_extra={"data_path": ["omp"]}) + ipv6_advertise: Optional[List[Ipv6Advertise]] = Field( + default=None, json_schema_extra={"data_path": ["omp"], "vmanage_key": "ipv6-advertise"} + ) + pool: Optional[List[Pool]] = Field(default=None, json_schema_extra={"data_path": ["nat64", "v4"]}) + natpool: Optional[List[Natpool]] = Field(default=None, json_schema_extra={"data_path": ["nat"]}) + static: Optional[List[Static]] = Field(default=None, json_schema_extra={"data_path": ["nat"]}) + subnet_static: Optional[List[SubnetStatic]] = Field( + default=None, json_schema_extra={"data_path": ["nat"], "vmanage_key": "subnet-static"} + ) + port_forward: Optional[List[PortForward]] = Field( + default=None, json_schema_extra={"data_path": ["nat"], "vmanage_key": "port-forward"} + ) + route_import: Optional[List[RouteImport]] = Field(default=None, json_schema_extra={"vmanage_key": "route-import"}) + route_import_from: Optional[List[RouteImportFrom]] = Field( + default=None, json_schema_extra={"vmanage_key": "route-import-from"} ) - 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") - advertise: Optional[List[Advertise]] = Field(data_path=["omp"]) - ipv6_advertise: Optional[List[Ipv6Advertise]] = Field(data_path=["omp"], vmanage_key="ipv6-advertise") - pool: Optional[List[Pool]] = Field(data_path=["nat64", "v4"]) - natpool: Optional[List[Natpool]] = Field(data_path=["nat"]) - static: Optional[List[Static]] = Field(data_path=["nat"]) - subnet_static: Optional[List[SubnetStatic]] = Field(data_path=["nat"], vmanage_key="subnet-static") - port_forward: Optional[List[PortForward]] = Field(data_path=["nat"], vmanage_key="port-forward") - route_import: Optional[List[RouteImport]] = Field(vmanage_key="route-import") - route_import_from: Optional[List[RouteImportFrom]] = Field(vmanage_key="route-import-from") - route_export: Optional[List[RouteExport]] = Field(vmanage_key="route-export") + route_export: Optional[List[RouteExport]] = Field(default=None, json_schema_extra={"vmanage_key": "route-export"}) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "cisco_vpn" diff --git a/catalystwan/api/templates/models/cli_template.py b/catalystwan/api/templates/models/cli_template.py index d0deddf6d..f8211b9dc 100644 --- a/catalystwan/api/templates/models/cli_template.py +++ b/catalystwan/api/templates/models/cli_template.py @@ -1,13 +1,13 @@ from pathlib import Path from typing import ClassVar +from pydantic import ConfigDict + from catalystwan.api.templates.feature_template import FeatureTemplate class CliTemplateModel(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) config: str diff --git a/catalystwan/api/templates/models/omp_vsmart_model.py b/catalystwan/api/templates/models/omp_vsmart_model.py index 6bdaecd35..5daa2edcc 100644 --- a/catalystwan/api/templates/models/omp_vsmart_model.py +++ b/catalystwan/api/templates/models/omp_vsmart_model.py @@ -1,30 +1,34 @@ from pathlib import Path from typing import ClassVar, Optional -from pydantic.v1 import Field +from pydantic import ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.pydantic_validators import ConvertBoolToStringModel class OMPvSmart(FeatureTemplate, ConvertBoolToStringModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) - graceful_restart: Optional[bool] = Field(default=None, vmanage_key="graceful-restart") - send_path_limit: Optional[int] = Field(default=None, vmanage_key="send-path-limit") - send_backup_paths: Optional[bool] = Field(default=None, vmanage_key="send-backup-paths") - discard_rejected: Optional[bool] = Field(default=None, vmanage_key="discard-rejected") - shutdown: Optional[bool] = Field(default=None, vmanage_key="shutdown") + graceful_restart: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "graceful-restart"}) + send_path_limit: Optional[int] = Field(default=None, json_schema_extra={"vmanage_key": "send-path-limit"}) + send_backup_paths: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "send-backup-paths"}) + discard_rejected: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "discard-rejected"}) + shutdown: Optional[bool] = Field(default=None, json_schema_extra={"vmanage_key": "shutdown"}) graceful_restart_timer: Optional[int] = Field( - default=None, vmanage_key="graceful-restart-timer", data_path=["timers"] + default=None, json_schema_extra={"vmanage_key": "graceful-restart-timer", "data_path": ["timers"]} + ) + eor_timer: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "eor-timer", "data_path": ["timers"]} + ) + holdtime: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "holdtime", "data_path": ["timers"]} + ) + affinity_group_preference: Optional[bool] = Field( + default=None, json_schema_extra={"vmanage_key": "affinity-group-preference"} ) - eor_timer: Optional[int] = Field(default=None, vmanage_key="eor-timer", data_path=["timers"]) - holdtime: Optional[int] = Field(default=None, vmanage_key="holdtime", data_path=["timers"]) - affinity_group_preference: Optional[bool] = Field(default=None, vmanage_key="affinity-group-preference") advertisement_interval: Optional[int] = Field( - default=None, vmanage_key="advertisement-interval", data_path=["timers"] + default=None, json_schema_extra={"vmanage_key": "advertisement-interval", "data_path": ["timers"]} ) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" diff --git a/catalystwan/api/templates/models/security_vsmart_model.py b/catalystwan/api/templates/models/security_vsmart_model.py index a01281295..0af675d38 100644 --- a/catalystwan/api/templates/models/security_vsmart_model.py +++ b/catalystwan/api/templates/models/security_vsmart_model.py @@ -2,7 +2,7 @@ from pathlib import Path from typing import ClassVar, Optional -from pydantic.v1 import Field +from pydantic import ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate @@ -13,11 +13,11 @@ class Protocol(str, Enum): class SecurityvSmart(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) - protocol: Optional[Protocol] = Field(default=None, data_path=["control"]) - tls_port: Optional[int] = Field(default=None, vmanage_key="tls-port", data_path=["control"]) + protocol: Optional[Protocol] = Field(default=None, json_schema_extra={"data_path": ["control"]}) + tls_port: Optional[int] = Field( + default=None, json_schema_extra={"vmanage_key": "tls-port", "data_path": ["control"]} + ) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "security-vsmart" diff --git a/catalystwan/api/templates/models/system_vsmart_model.py b/catalystwan/api/templates/models/system_vsmart_model.py index 204d0d196..bd1231704 100644 --- a/catalystwan/api/templates/models/system_vsmart_model.py +++ b/catalystwan/api/templates/models/system_vsmart_model.py @@ -1,37 +1,43 @@ from pathlib import Path from typing import ClassVar, Optional -from pydantic.v1 import Field +from pydantic import ConfigDict, Field from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.utils.timezone import Timezone class SystemVsmart(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) - timezone: Optional[Timezone] = Field(default=None, converter=Timezone) - idle_timeout: Optional[int] = Field(default=None, vmanage_key="idle-timeout", ge=0, le=300) - admin_tech_on_failure: Optional[bool] = Field(default=True, vmanage_key="admin-tech-on-failure") - iptables_enable: Optional[bool] = Field(default=True, vmanage_key="iptables-enable") - track_default_gateway: Optional[bool] = Field(default=True, vmanage_key="track-default-gateway") - dns_cache_timeout: Optional[int] = Field(default=2, vmanage_key="dns-cache-timeout", ge=1, le=30) - track_transport: Optional[bool] = Field(default=True, vmanage_key="track-transport") - controller_group_id: Optional[int] = Field(default=0, vmanage_key="controller-group-id", ge=0, le=100) - control_session_pps: Optional[int] = Field(default=300, vmanage_key="control-session-pps") - port_hop: Optional[bool] = Field(default=True, vmanage_key="port-hop") - port_offset: Optional[int] = Field(default=0, vmanage_key="port-offset", ge=0, le=20) - overlay_id: Optional[int] = Field(default=1, vmanage_key="overlay-id", ge=1, le=4294967295) - site_id: Optional[int] = Field(default=1, vmanage_key="site-id", ge=1, le=4294967295) - system_ip: Optional[str] = Field(default=None, vmanage_key="system-ip") - device_groups: Optional[str] = Field(default=None, vmanage_key="device-groups") - longitude: Optional[int] = Field(ge=-180, le=180) - latitude: Optional[int] = Field(ge=-90, le=90) - system_tunnel_mtu: Optional[str] = Field(default=1024, vmanage_key="system-tunnel-mtu") - location: Optional[str] - host_name: Optional[str] = Field(default=None, vmanage_key="host-name") + timezone: Optional[Timezone] = Field(default=None) + idle_timeout: Optional[int] = Field(default=None, ge=0, le=300, json_schema_extra={"vmanage_key": "idle-timeout"}) + admin_tech_on_failure: Optional[bool] = Field( + default=True, json_schema_extra={"vmanage_key": "admin-tech-on-failure"} + ) + iptables_enable: Optional[bool] = Field(default=True, json_schema_extra={"vmanage_key": "iptables-enable"}) + track_default_gateway: Optional[bool] = Field( + default=True, json_schema_extra={"vmanage_key": "track-default-gateway"} + ) + dns_cache_timeout: Optional[int] = Field( + default=2, ge=1, le=30, json_schema_extra={"vmanage_key": "dns-cache-timeout"} + ) + track_transport: Optional[bool] = Field(default=True, json_schema_extra={"vmanage_key": "track-transport"}) + controller_group_id: Optional[int] = Field( + default=0, ge=0, le=100, json_schema_extra={"vmanage_key": "controller-group-id"} + ) + control_session_pps: Optional[int] = Field(default=300, json_schema_extra={"vmanage_key": "control-session-pps"}) + port_hop: Optional[bool] = Field(default=True, json_schema_extra={"vmanage_key": "port-hop"}) + port_offset: Optional[int] = Field(default=0, ge=0, le=20, json_schema_extra={"vmanage_key": "port-offset"}) + overlay_id: Optional[int] = Field(default=1, ge=1, le=4294967295, json_schema_extra={"vmanage_key": "overlay-id"}) + site_id: Optional[int] = Field(default=1, ge=1, le=4294967295, json_schema_extra={"vmanage_key": "site-id"}) + system_ip: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "system-ip"}) + device_groups: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "device-groups"}) + longitude: Optional[int] = Field(default=None, ge=-180, le=180) + latitude: Optional[int] = Field(default=None, ge=-90, le=90) + system_tunnel_mtu: Optional[str] = Field(default=1024, json_schema_extra={"vmanage_key": "system-tunnel-mtu"}) + location: Optional[str] = None + host_name: Optional[str] = Field(default=None, json_schema_extra={"vmanage_key": "host-name"}) payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "system-vsmart" diff --git a/catalystwan/api/templates/payloads/aaa/aaa_model.py b/catalystwan/api/templates/payloads/aaa/aaa_model.py index d6cbb1ff5..bcd54a007 100644 --- a/catalystwan/api/templates/payloads/aaa/aaa_model.py +++ b/catalystwan/api/templates/payloads/aaa/aaa_model.py @@ -5,6 +5,7 @@ from typing import ClassVar, List, Optional from attr import define, field # type: ignore +from pydantic import ConfigDict from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.dataclasses import User @@ -64,8 +65,7 @@ class AuthTask: class AAAModel(FeatureTemplate): - class Config: - arbitrary_types_allowed = True + model_config = ConfigDict(arbitrary_types_allowed=True) payload_path: ClassVar[Path] = Path(__file__).parent / "feature" / "aaa.json.j2" type: ClassVar[str] = "aaa" # AAA diff --git a/catalystwan/api/templates/payloads/cisco_vpn/cisco_vpn_model.py b/catalystwan/api/templates/payloads/cisco_vpn/cisco_vpn_model.py index 1a88f5535..b0c8bb40a 100644 --- a/catalystwan/api/templates/payloads/cisco_vpn/cisco_vpn_model.py +++ b/catalystwan/api/templates/payloads/cisco_vpn/cisco_vpn_model.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, ClassVar, List, Optional from attr import define, field # type: ignore -from pydantic.v1 import validator +from pydantic import ConfigDict, field_validator from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.api.templates.payloads.aaa.aaa_model import VpnType @@ -59,18 +59,19 @@ class IPv6Route: class CiscoVPNModel(FeatureTemplate): type: ClassVar[str] = "cisco_vpn" # Cisco VPN payload_path: ClassVar[Path] = Path(__file__).parent / "feature/cisco_vpn.json.j2" - tenant_vpn: Optional[int] - tenant_org_name: Optional[str] + tenant_vpn: Optional[int] = None + tenant_org_name: Optional[str] = None vpn_id: int dns: Optional[DNS] = None mapping: List[Mapping] = [] ipv4route: List[IPv4Route] = [] ipv6route: List[IPv6Route] = [] - @validator("vpn_id") - def check_id(cls, v, values): + @field_validator("vpn_id") + @classmethod + def check_id(cls, v: int): if v not in [VpnType.VPN_TRANSPORT.value, VpnType.VPN_MANAGMENT.value]: - if "tenant_org_name" not in values: + if cls.tenant_org_name is None: raise ValueError("Must enter the name of the organization.") return v @@ -86,5 +87,4 @@ def generate_payload(self, session: ManagerSession) -> str: self.generate_vpn_id(session=session) return super().generate_payload(session) - class Config: - arbitrary_types_allowed = True + model_config = ConfigDict(arbitrary_types_allowed=True) diff --git a/catalystwan/api/templates/payloads/tenant/tenant_model.py b/catalystwan/api/templates/payloads/tenant/tenant_model.py index 2510088bf..862ad8bdc 100644 --- a/catalystwan/api/templates/payloads/tenant/tenant_model.py +++ b/catalystwan/api/templates/payloads/tenant/tenant_model.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import TYPE_CHECKING, ClassVar, List, Optional -from pydantic.v1 import BaseModel +from pydantic import BaseModel, ConfigDict from catalystwan.api.templates.feature_template import FeatureTemplate from catalystwan.endpoints.monitoring_device_details import Tier as TierInfo @@ -23,8 +23,7 @@ class Tenant(BaseModel): class TenantModel(FeatureTemplate): - class Config: - arbitrary_types_allowed = True + model_config = ConfigDict(arbitrary_types_allowed=True) type: ClassVar[str] = "tenant" # Tenant payload_path: ClassVar[Path] = Path(__file__).parent / "tenant.json.j2" diff --git a/catalystwan/endpoints/__init__.py b/catalystwan/endpoints/__init__.py index 7d9e5e214..a4e1da9a4 100644 --- a/catalystwan/endpoints/__init__.py +++ b/catalystwan/endpoints/__init__.py @@ -43,13 +43,13 @@ Final, Iterable, List, + Literal, Mapping, Optional, Protocol, Sequence, Set, Tuple, - Type, TypeVar, Union, runtime_checkable, @@ -62,6 +62,7 @@ from pydantic.v1 import BaseModel as BaseModelV1 from typing_extensions import Annotated, get_args, get_origin +from catalystwan.abstractions import APIEndpointClient, APIEndpointClientResponse from catalystwan.exceptions import APIEndpointError, APIRequestPayloadTypeError, APIVersionError, APIViewError from catalystwan.typed_list import DataSequence from catalystwan.utils.session_type import SessionType @@ -153,50 +154,6 @@ def dict_values_to_str(field_names: Set[str], kwargs: Dict[str, Any]) -> Dict[st return result -class APIEndpointClientResponse(Protocol): - """ - Interface to response object. Fits "requests.Response" - but set of methods is minimal to allow easy migration to another client if needed - """ - - @property - def text(self) -> str: - ... - - @property - def content(self) -> bytes: - ... - - def dataobj(self, cls: Type[T], sourcekey: Optional[str]) -> T: - ... - - def dataseq(self, cls: Type[T], sourcekey: Optional[str]) -> DataSequence[T]: - ... - - def json(self) -> dict: - ... - - -class APIEndpointClient(Protocol): - """ - Interface to client object. - We only need a 'request' function and few vmanage session properties obtained from server. - Matched to fit "requests.Session" but migration to other client is possible. - At his point not very clean as injection of custom kwargs is possible (and sometimes used) - """ - - def request(self, method: str, url: str, **kwargs) -> APIEndpointClientResponse: - ... - - @property - def api_version(self) -> Optional[Version]: - ... - - @property - def session_type(self) -> Optional[SessionType]: - ... - - class APIEndpoints: """ Class to be used as base for all API endpoints. @@ -538,8 +495,19 @@ def check_params(self): raise APIEndpointError(f"Missing parameters: {missing} to format url: {self.url}") for parameter in [parameters.get(name) for name in self.url_field_names]: + # Check if 'params' is type of str, UUID or LIteral if not (isclass(parameter.annotation) and issubclass(parameter.annotation, (str, UUID))): - raise APIEndpointError(f"Parameter {parameter} used for url formatting must be 'str' sub-type or UUID") + if not get_origin(parameter.annotation) == Literal: + raise APIEndpointError( + f"Parameter {parameter} used for url formatting must be 'str', UUID or Literal sub-type" + ) + + elif p_args := get_args(parameter.annotation): + # Check if all 'params' Literal values are str + if not all((isinstance(arg, str) for arg in p_args)): + raise APIEndpointError( + f"Literal values for parameter {parameter} used for url formatting must be 'str'" + ) no_purpose_params = { parameters.get(name) for name in general_purpose_arg_names.difference(self.url_field_names) diff --git a/catalystwan/endpoints/configuration/feature_profile/sdwan/policy_object.py b/catalystwan/endpoints/configuration/feature_profile/sdwan/policy_object.py new file mode 100644 index 000000000..31f7aa587 --- /dev/null +++ b/catalystwan/endpoints/configuration/feature_profile/sdwan/policy_object.py @@ -0,0 +1,80 @@ +# mypy: disable-error-code="empty-body" +from uuid import UUID + +from catalystwan.endpoints import APIEndpoints, delete, get, post, put, versions +from catalystwan.models.configuration.feature_profile.common import Parcel, ParcelCreationResponse +from catalystwan.models.configuration.feature_profile.sdwan.policy_object import AnyPolicyObjectParcel +from catalystwan.typed_list import DataSequence + + +class PolicyObjectFeatureProfile(APIEndpoints): + @versions(supported_versions=(">=20.13"), raises=False) + @post("/v1/feature-profile/sdwan/policy-object/{profile_id}/{policy_object_list_type}") + def create( + self, profile_id: UUID, policy_object_list_type: str, payload: AnyPolicyObjectParcel + ) -> ParcelCreationResponse: + ... + + # @versions(supported_versions=(">=20.13"), raises=False) + # @post("/v1/feature-profile/sdwan/policy-object/{policy_object_id}/unified/{security_object_list_type}") + # def create_security_profile_parcel(self, policy_object_id: UUID, security_object_list_type: str): + # ... + + @versions(supported_versions=(">=20.13"), raises=False) + @delete("/v1/feature-profile/sdwan/policy-object/{profile_id}/{policy_object_list_type}/{list_object_id}") + def delete(self, profile_id: UUID, policy_object_list_type: str, list_object_id: UUID) -> None: + ... + + # @versions(supported_versions=(">=20.13"), raises=False) + # @delete( + # "/v1/feature-profile/sdwan/policy-object/{policy_object_id}/unified/{security_object_list_type}/{security_profile_parcel_id}" + # ) + # def delete_security_profile_parcel1( + # self, policy_object_id: UUID, security_object_list_type: str, security_profile_parcel_id: UUID + # ): + # ... + + @versions(supported_versions=(">=20.13"), raises=False) + @put("/v1/feature-profile/sdwan/policy-object/{profile_id}/{policy_object_list_type}/{list_object_id}") + def update( + self, profile_id: UUID, policy_object_list_type: str, list_object_id: UUID, payload: AnyPolicyObjectParcel + ) -> ParcelCreationResponse: + ... + + # @versions(supported_versions=(">=20.13"), raises=False) + # @put( + # "/v1/feature-profile/sdwan/policy-object/{policy_object_id}/unified/{security_object_list_type}/{security_profile_parcel_id}" + # ) + # def edit_security_profile_parcel1( + # self, policy_object_id: UUID, security_object_list_type: str, security_profile_parcel_id: UUID + # ): + # ... + + @versions(supported_versions=(">=20.13"), raises=False) + @get("/v1/feature-profile/sdwan/policy-object/{profile_id}/{policy_object_list_type}/{list_object_id}") + def get_by_id(self, profile_id: UUID, policy_object_list_type: str, list_object_id: UUID) -> Parcel: + ... + + @versions(supported_versions=(">=20.13"), raises=False) + @get("/v1/feature-profile/sdwan/policy-object/{profile_id}/{policy_object_list_type}", resp_json_key="data") + def get_all(self, profile_id: UUID, policy_object_list_type: str) -> DataSequence[Parcel]: + ... + + # @versions(supported_versions=(">=20.13"), raises=False) + # @get("/v1/feature-profile/sdwan/policy-object/{policy_object_list_type}/schema") + # def get_sdwan_policy_object_data_prefix_parcel_schema_by_schema_type(self, policy_object_list_type: str): + # ... + + # @versions(supported_versions=(">=20.13"), raises=False) + # @get("/v1/feature-profile/sdwan/policy-object/{policy_object_id}/unified/{security_object_list_type}") + # def get_security_profile_parcel(self, policy_object_id: UUID, security_object_list_type: str): + # ... + + # @versions(supported_versions=(">=20.13"), raises=False) + # @get( + # "/v1/feature-profile/sdwan/policy-object/{policy_object_id}/unified/{security_object_list_type}/{security_profile_parcel_id}" + # ) + # def get_security_profile_parcel_by_parcel_id( + # self, policy_object_id: UUID, security_object_list_type: str, security_profile_parcel_id: UUID + # ): + # ... diff --git a/catalystwan/endpoints/configuration_device_inventory.py b/catalystwan/endpoints/configuration_device_inventory.py index 5e684e10c..b78c4fd60 100644 --- a/catalystwan/endpoints/configuration_device_inventory.py +++ b/catalystwan/endpoints/configuration_device_inventory.py @@ -1,7 +1,6 @@ # mypy: disable-error-code="empty-body" -from enum import Enum from pathlib import Path -from typing import List, Optional, Union +from typing import List, Literal, Optional, Union from uuid import UUID from pydantic import BaseModel, ConfigDict, Field @@ -12,12 +11,12 @@ class UnlockDeviceDetail(BaseModel): - device_id: str = Field(alias="deviceId") - device_ip: str = Field(alias="deviceIP") + device_id: str = Field(validation_alias="deviceId", serialization_alias="deviceId") + device_ip: str = Field(validation_alias="deviceIP", serialization_alias="deviceIP") class DeviceUnlockPayload(BaseModel): - device_type: str = Field(alias="deviceType") + device_type: str = Field(validation_alias="deviceType", serialization_alias="deviceType") devices: List[UnlockDeviceDetail] @@ -25,9 +24,7 @@ class DeviceUnlockResponse(BaseModel): parentTaskId: str -class Protocol(str, Enum): - DTLS = "DTLS" - TLS = "TLS" +Protocol = Literal["DTLS", "TLS"] class DeviceCreationPayload(BaseModel): @@ -38,108 +35,174 @@ class DeviceCreationPayload(BaseModel): password: str personality: Personality port: Optional[str] = Field(default=None) - protocol: Protocol = Protocol.DTLS + protocol: Protocol = Field(default="DTLS") username: str class DeviceDeletionResponse(BaseModel): model_config = ConfigDict(populate_by_name=True) - local_delete_from_db: Optional[bool] = Field(default=None, alias="localDeleteFromDB") + local_delete_from_db: Optional[bool] = Field( + default=None, validation_alias="localDeleteFromDB", serialization_alias="localDeleteFromDB" + ) id: Optional[str] = Field(default=None) status: Optional[str] = Field(default=None) -class DeviceCategory(str, Enum): - CONTROLLERS = "controllers" - VEDGES = "vedges" +DeviceCategory = Literal["controllers", "vedges"] class DeviceDetailsResponse(BaseModel): # Field "model_sku" has conflict with protected namespace "model_" model_config = ConfigDict(populate_by_name=True, protected_namespaces=()) - device_type: Optional[str] = Field(default=None, alias="deviceType") - serial_number: Optional[str] = Field(default=None, alias="serialNumber") + device_type: Optional[str] = Field(default=None, validation_alias="deviceType", serialization_alias="deviceType") + serial_number: Optional[str] = Field( + default=None, validation_alias="serialNumber", serialization_alias="serialNumber" + ) uuid: Optional[str] = None - management_system_ip: Optional[str] = Field(default=None, alias="managementSystemIP") - chasis_number: Optional[str] = Field(default=None, alias="chasisNumber") - config_operation_mode: Optional[str] = Field(default=None, alias="configOperationMode") - device_model: Optional[str] = Field(default=None, alias="deviceModel") - device_state: Optional[str] = Field(default=None, alias="deviceState") + management_system_ip: Optional[str] = Field( + default=None, validation_alias="managementSystemIP", serialization_alias="managementSystemIP" + ) + chasis_number: Optional[str] = Field( + default=None, validation_alias="chasisNumber", serialization_alias="chasisNumber" + ) + config_operation_mode: Optional[str] = Field( + default=None, validation_alias="configOperationMode", serialization_alias="configOperationMode" + ) + device_model: Optional[str] = Field(default=None, validation_alias="deviceModel", serialization_alias="deviceModel") + device_state: Optional[str] = Field(default=None, validation_alias="deviceState", serialization_alias="deviceState") validity: Optional[str] = None - platform_family: Optional[str] = Field(default=None, alias="platformFamily") + platform_family: Optional[str] = Field( + default=None, validation_alias="platformFamily", serialization_alias="platformFamily" + ) username: Optional[str] = None - device_csr: Optional[str] = Field(default=None, alias="deviceCSR") - device_csr_common_name: Optional[str] = Field(default=None, alias="deviceCSRCommonName") - root_cert_hash: Optional[str] = Field(default=None, alias="rootCertHash") - csr: Optional[str] = Field(default=None, alias="CSR") - csr_detail: Optional[str] = Field(default=None, alias="CSRDetail") + device_csr: Optional[str] = Field(default=None, validation_alias="deviceCSR", serialization_alias="deviceCSR") + device_csr_common_name: Optional[str] = Field( + default=None, validation_alias="deviceCSRCommonName", serialization_alias="deviceCSRCommonName" + ) + root_cert_hash: Optional[str] = Field( + default=None, validation_alias="rootCertHash", serialization_alias="rootCertHash" + ) + csr: Optional[str] = Field(default=None, validation_alias="CSR", serialization_alias="CSR") + csr_detail: Optional[str] = Field(default=None, validation_alias="CSRDetail", serialization_alias="CSRDetail") state: Optional[str] = None - global_state: Optional[str] = Field(default=None, alias="globalState") + global_state: Optional[str] = Field(default=None, validation_alias="globalState", serialization_alias="globalState") valid: Optional[str] = None - request_token_id: Optional[str] = Field(default=None, alias="requestTokenID") - expiration_date: Optional[str] = Field(default=None, alias="expirationDate") - expiration_date_long: Optional[int] = Field(default=None, alias="expirationDateLong") - device_ip: Optional[str] = Field(default=None, alias="deviceIP") + request_token_id: Optional[str] = Field( + default=None, validation_alias="requestTokenID", serialization_alias="requestTokenID" + ) + expiration_date: Optional[str] = Field( + default=None, validation_alias="expirationDate", serialization_alias="expirationDate" + ) + expiration_date_long: Optional[int] = Field( + default=None, validation_alias="expirationDateLong", serialization_alias="expirationDateLong" + ) + device_ip: Optional[str] = Field(default=None, validation_alias="deviceIP", serialization_alias="deviceIP") activity: Optional[List[str]] = None - state_vedge_list: Optional[str] = Field(default=None, alias="state_vedgeList") - cert_install_status: Optional[str] = Field(default=None, alias="certInstallStatus") + state_vedge_list: Optional[str] = Field( + default=None, validation_alias="state_vedgeList", serialization_alias="state_vedgeList" + ) + cert_install_status: Optional[str] = Field( + default=None, validation_alias="certInstallStatus", serialization_alias="certInstallStatus" + ) org: Optional[str] = None personality: Optional[str] = None - expiration_status: Optional[str] = Field(default=None, alias="expirationStatus") - life_cycle_required: Optional[bool] = Field(default=None, alias="lifeCycleRequired") - hardware_cert_serial_number: Optional[str] = Field(default=None, alias="hardwareCertSerialNumber") - subject_serial_number: Optional[str] = Field(default=None, alias="subjectSerialNumber") - resource_group: Optional[str] = Field(default=None, alias="resourceGroup") + expiration_status: Optional[str] = Field( + default=None, validation_alias="expirationStatus", serialization_alias="expirationStatus" + ) + life_cycle_required: Optional[bool] = Field( + default=None, validation_alias="lifeCycleRequired", serialization_alias="lifeCycleRequired" + ) + hardware_cert_serial_number: Optional[str] = Field( + default=None, validation_alias="hardwareCertSerialNumber", serialization_alias="hardwareCertSerialNumber" + ) + subject_serial_number: Optional[str] = Field( + default=None, validation_alias="subjectSerialNumber", serialization_alias="subjectSerialNumber" + ) + resource_group: Optional[str] = Field( + default=None, validation_alias="resourceGroup", serialization_alias="resourceGroup" + ) id: Optional[str] = None tags: Optional[List[str]] = None - draft_mode: Optional[str] = Field(default=None, alias="draftMode") + draft_mode: Optional[str] = Field(default=None, validation_alias="draftMode", serialization_alias="draftMode") solution: Optional[str] = None - device_lock: Optional[str] = Field(default=None, alias="device-lock") - managed_by: Optional[str] = Field(default=None, alias="managed-by") - configured_site_id: Optional[str] = Field(default=None, alias="configuredSiteId") - ncs_device_name: Optional[str] = Field(default=None, alias="ncsDeviceName") - config_status_message: Optional[str] = Field(default=None, alias="configStatusMessage") - template_apply_log: Optional[List[str]] = Field(default=None, alias="templateApplyLog") - template_status: Optional[str] = Field(default=None, alias="templateStatus") - config_status_message_details: Optional[str] = Field(default=None, alias="configStatusMessageDetails") - device_enterprise_certificate: Optional[str] = Field(default=None, alias="deviceEnterpriseCertificate") - service_personality: Optional[str] = Field(default=None, alias="servicePersonality") - upload_source: Optional[str] = Field(default=None, alias="uploadSource") - time_remaining_for_expiration: Optional[int] = Field(default=None, alias="timeRemainingForExpiration") - domain_id: Optional[str] = Field(default=None, alias="domain-id") - local_system_ip: Optional[str] = Field(default=None, alias="local-system-ip") - system_ip: Optional[str] = Field(default=None, alias="system-ip") + device_lock: Optional[str] = Field(default=None, validation_alias="device-lock", serialization_alias="device-lock") + managed_by: Optional[str] = Field(default=None, validation_alias="managed-by", serialization_alias="managed-by") + configured_site_id: Optional[str] = Field( + default=None, validation_alias="configuredSiteId", serialization_alias="configuredSiteId" + ) + ncs_device_name: Optional[str] = Field( + default=None, validation_alias="ncsDeviceName", serialization_alias="ncsDeviceName" + ) + config_status_message: Optional[str] = Field( + default=None, validation_alias="configStatusMessage", serialization_alias="configStatusMessage" + ) + template_apply_log: Optional[List[str]] = Field( + default=None, validation_alias="templateApplyLog", serialization_alias="templateApplyLog" + ) + template_status: Optional[str] = Field( + default=None, validation_alias="templateStatus", serialization_alias="templateStatus" + ) + config_status_message_details: Optional[str] = Field( + default=None, validation_alias="configStatusMessageDetails", serialization_alias="configStatusMessageDetails" + ) + device_enterprise_certificate: Optional[str] = Field( + default=None, validation_alias="deviceEnterpriseCertificate", serialization_alias="deviceEnterpriseCertificate" + ) + service_personality: Optional[str] = Field( + default=None, validation_alias="servicePersonality", serialization_alias="servicePersonality" + ) + upload_source: Optional[str] = Field( + default=None, validation_alias="uploadSource", serialization_alias="uploadSource" + ) + time_remaining_for_expiration: Optional[int] = Field( + default=None, validation_alias="timeRemainingForExpiration", serialization_alias="timeRemainingForExpiration" + ) + domain_id: Optional[str] = Field(default=None, validation_alias="domain-id", serialization_alias="domain-id") + local_system_ip: Optional[str] = Field( + default=None, validation_alias="local-system-ip", serialization_alias="ocal-system-ip" + ) + system_ip: Optional[str] = Field(default=None, validation_alias="system-ip", serialization_alias="system-ip") model_sku: Optional[str] = Field(default=None) - site_id: Optional[str] = Field(default=None, alias="site-id") - host_name: Optional[str] = Field(default=None, alias="host-name") - sp_organization_name: Optional[str] = Field(default=None, alias="sp-organization-name") + site_id: Optional[str] = Field(default=None, validation_alias="site-id", serialization_alias="site-id") + host_name: Optional[str] = Field(default=None, validation_alias="host-name", serialization_alias="host-name") + sp_organization_name: Optional[str] = Field( + default=None, validation_alias="sp-organization-name", serialization_alias="sp-organization-name" + ) version: Optional[str] = Field(default=None) vbond: Optional[str] = Field(default=None) - vmanage_system_ip: Optional[str] = Field(default=None, alias="vmanage-system-ip") - vmanage_connection_state: Optional[str] = Field(default=None, alias="vmanageConnectionState") - last_updated: Optional[int] = Field(default=None, alias="lastupdated") + vmanage_system_ip: Optional[str] = Field( + default=None, validation_alias="vmanage-system-ip", serialization_alias="vmanage-system-ip" + ) + vmanage_connection_state: Optional[str] = Field( + default=None, validation_alias="vmanageConnectionState", serialization_alias="vmanageConnectionState" + ) + last_updated: Optional[int] = Field(default=None, validation_alias="lastupdated", serialization_alias="lastupdated") reachability: Optional[str] = Field(default=None) - uptime_date: Optional[int] = Field(default=None, alias="uptime-date") - default_version: Optional[str] = Field(default=None, alias="defaultVersion") - organization_name: Optional[str] = Field(default=None, alias="organization-name") - available_versions: Optional[List[str]] = Field(default=None, alias="availableVersions") - site_name: Optional[str] = Field(default=None, alias="site-name") + uptime_date: Optional[int] = Field(default=None, validation_alias="uptime-date", serialization_alias="uptime-date") + default_version: Optional[str] = Field( + default=None, validation_alias="defaultVersion", serialization_alias="defaultVersion" + ) + organization_name: Optional[str] = Field( + default=None, validation_alias="organization-name", serialization_alias="organization-name" + ) + available_versions: Optional[List[str]] = Field( + default=None, validation_alias="availableVersions", serialization_alias="availableVersions" + ) + site_name: Optional[str] = Field(default=None, validation_alias="site-name", serialization_alias="site-name") class DeviceDetailsQueryParams(BaseModel): model: Optional[str] = None state: Optional[List[str]] = None uuid: Optional[List[str]] = None - device_ip: Optional[List[str]] = Field(default=None, serialization_alias="deviceIP") + device_ip: Optional[List[str]] = Field(default=None, validation_alias="deviceIP", serialization_alias="deviceIP") validity: Optional[List[str]] = None family: Optional[str] = None -class Validity(str, Enum): - VALID = "valid" - INVALID = "invalid" +Validity = Literal["valid", "invalid"] class SmartAccountSyncParams(BaseModel): @@ -147,15 +210,15 @@ class SmartAccountSyncParams(BaseModel): password: str username: str - validity_string: str = Validity.INVALID + validity_string: Validity = Field(default="valid") class ProcessId(BaseModel): - process_id: str = Field(alias="processId") + process_id: str = Field(validation_alias="processId", serialization_alias="processId") class SerialFilePayload(CustomPayloadType): - def __init__(self, image_path: str, validity: Validity = Validity.INVALID): + def __init__(self, image_path: str, validity: Validity = "valid"): self.image_path = image_path self.validity = validity self.data = open(self.image_path, "rb") @@ -165,31 +228,43 @@ def prepared(self) -> PreparedPayload: return PreparedPayload(files={"file": (Path(self.data.name).name, self.data)}, data=self.fields) -class ConfigType(str, Enum): - CLOUDINIT = "cloudinit" - ENCODEDSTRING = "encodedstring" +ConfigType = Literal["cloudinit", "encodedstring"] class GenerateBoostrapConfigurationQueryParams(BaseModel): - configtype: Optional[ConfigType] = Field(default=ConfigType.CLOUDINIT) - incl_def_root_cert: Optional[bool] = Field(default=False) + model_config = ConfigDict(populate_by_name=True) + + configtype: Optional[ConfigType] = Field(default="cloudinit") + incl_def_root_cert: Optional[bool] = Field( + default=False, validation_alias="inclDefRootCert", serialization_alias="inclDefRootCert" + ) version: Optional[str] = Field(default="v1") class BoostrapConfiguration(BaseModel): model_config = ConfigDict(populate_by_name=True) - bootstrap_config: Optional[str] = Field(default=None, alias="bootstrapConfig") + bootstrap_config: Optional[str] = Field( + default=None, validation_alias="bootstrapConfig", serialization_alias="bootstrapConfig" + ) class UploadSerialFileResponse(BaseModel): model_config = ConfigDict(populate_by_name=True) - vedge_list_upload_msg: Optional[str] = Field(default=None, alias="vedgeListUploadMsg") - vedge_list_upload_status: Optional[str] = Field(default=None, alias="vedgeListUploadStatus") + vedge_list_upload_msg: Optional[str] = Field( + default=None, validation_alias="vedgeListUploadMsg", serialization_alias="vedgeListUploadMsg" + ) + vedge_list_upload_status: Optional[str] = Field( + default=None, validation_alias="vedgeListUploadStatus", serialization_alias="vedgeListUploadStatus" + ) id: Optional[str] = None - vedge_list_status_code: Optional[str] = Field(default=None, alias="vedgeListStatusCode") - activity_list: Optional[Union[List, str]] = Field(default=None, alias="activityList") + vedge_list_status_code: Optional[str] = Field( + default=None, validation_alias="vedgeListStatusCode", serialization_alias="vedgeListStatusCode" + ) + activity_list: Optional[Union[List, str]] = Field( + default=None, validation_alias="activityList", serialization_alias="activityList" + ) class ConfigurationDeviceInventory(APIEndpoints): diff --git a/catalystwan/endpoints/configuration_feature_profile.py b/catalystwan/endpoints/configuration_feature_profile.py index 9fa372ef6..f5ce2edd2 100644 --- a/catalystwan/endpoints/configuration_feature_profile.py +++ b/catalystwan/endpoints/configuration_feature_profile.py @@ -96,6 +96,11 @@ def create_cellular_controller_profile_parcel_for_transport( ) -> ParcelId: ... + @versions(supported_versions=(">=20.9"), raises=False) + @get("/v1/feature-profile/sdwan") + def get_sdwan_feature_profiles(self) -> DataSequence[FeatureProfileInfo]: + ... + class SDRoutingConfigurationFeatureProfile(APIEndpoints): @versions(supported_versions=(">=20.13"), raises=False) diff --git a/catalystwan/exceptions.py b/catalystwan/exceptions.py index 21cf314dc..117944934 100644 --- a/catalystwan/exceptions.py +++ b/catalystwan/exceptions.py @@ -1,18 +1,51 @@ -class ManagerError(Exception): - """Superclass of all catalystwan exception types.""" +from typing import Any, Optional, Union +from pydantic import BaseModel +from requests import HTTPError, RequestException -class InvalidOperationError(ManagerError): + +class ManagerErrorInfo(BaseModel): + message: Union[str, None] + details: Union[str, None] + code: Union[str, None] + + +class CatalystwanException(Exception): + """Superclass of all catalystwan SDK exception types.""" + + +class ManagerRequestException(RequestException, CatalystwanException): + """Exception raised when there is ambigous problem during sending of request to Manager""" + + def __init__(self, *args, **kwargs): + """Initialize RequestException with `request` and `response` objects.""" + super().__init__(*args, **kwargs) + + +class ManagerHTTPError(HTTPError, ManagerRequestException): + def __init__(self, *, error_info: Optional[ManagerErrorInfo], request: Any, response: Any): + """Initialize RequestException with `error_info`, `request` and `response` objects.""" + self.info = error_info + super().__init__(request=request, response=response) + + +class DefaultPasswordError(CatalystwanException): + """Default password for SDWAN Manager user was detected and needs to be changed.""" + + pass + + +class InvalidOperationError(CatalystwanException): """The exception that is thrown when a method call is invalid for the object's current state.""" pass -class RetrieveIntervalOutOfRange(ManagerError): +class RetrieveIntervalOutOfRange(CatalystwanException): pass -class VersionDeclarationError(ManagerError): +class VersionDeclarationError(CatalystwanException): """ The exception that is thrown in one of two below cases. @@ -23,107 +56,107 @@ class VersionDeclarationError(ManagerError): pass -class ImageNotInRepositoryError(ManagerError): +class ImageNotInRepositoryError(CatalystwanException): """The exception that is thrown, if image is not in vManage images Repository""" pass -class TemplateNotFoundError(ManagerError): +class TemplateNotFoundError(CatalystwanException): """Used when a template item is not found.""" def __init__(self, template): self.message = f"No such template: '{template}'" -class AttachedError(ManagerError): +class AttachedError(CatalystwanException): """Used when delete attached template.""" def __init__(self, template): self.message = f"Template: {template} is attached to device." -class TemplateTypeError(ManagerError): +class TemplateTypeError(CatalystwanException): """Used when wrong type template.""" def __init__(self, name): self.message = f"Template: {name} - wrong template type." -class AlreadyExistsError(ManagerError): +class AlreadyExistsError(CatalystwanException): """Raised when an entity that we attempted to create already exists.""" pass -class APIVersionError(ManagerError): +class APIVersionError(CatalystwanException): """Raised when API is unsupported in running vManage version.""" def __init__(self, item, supported, current): self.message = f"vManage is running: {current} but {item} only supported in API version: {supported}" -class APIViewError(ManagerError): +class APIViewError(CatalystwanException): """Raised when API is not allowed for given session type / view.""" def __init__(self, item, allowed, current): self.message = f"Current view is: {current} but {item} only allowed for views: {allowed}" -class APIRequestPayloadTypeError(ManagerError): +class APIRequestPayloadTypeError(CatalystwanException): """Raised when unsupported payload type is passed to vManage request.""" def __init__(self, item): self.message = f"Unsupported payload type: {type(item)} for vManage request" -class EmptyTaskResponseError(ManagerError): +class EmptyTaskResponseError(CatalystwanException): """Raised if task is registred by vManage, but reponse content is empty""" pass -class TaskNotRegisteredError(ManagerError): +class TaskNotRegisteredError(CatalystwanException): """Raised if task_id is generated, but it's not registere in vManage""" pass -class TaskValidationError(ManagerError): +class TaskValidationError(CatalystwanException): """Raised if task has not been validated""" pass -class MultiplePersonalityError(ManagerError): +class MultiplePersonalityError(CatalystwanException): """Raised if Device DataSequnce contains devices with multiples personalities""" -class SessionNotCreatedError(ManagerError): +class SessionNotCreatedError(CatalystwanException): """Raised when vManage session cannot be created""" pass -class TenantSubdomainNotFound(ManagerError): +class TenantSubdomainNotFound(CatalystwanException): """Raised when given subdomain does not exist""" pass -class APIEndpointError(Exception): +class APIEndpointError(CatalystwanException): """Raised when there is a problem with endpoint definition""" pass -class TenantMigrationExportFileNotFound(ManagerError): +class TenantMigrationExportFileNotFound(CatalystwanException): """Raised when client cannot find exported file name in export task result""" pass -class TenantMigrationPreconditionsError(ManagerError): +class TenantMigrationPreconditionsError(CatalystwanException): """Raised when preconditions for tenant migration fail""" pass diff --git a/catalystwan/models/configuration/feature_profile/common.py b/catalystwan/models/configuration/feature_profile/common.py index 346df4258..bcc302aea 100644 --- a/catalystwan/models/configuration/feature_profile/common.py +++ b/catalystwan/models/configuration/feature_profile/common.py @@ -1,11 +1,11 @@ from datetime import datetime from enum import Enum from typing import Generic, List, Literal, Optional, TypeVar, Union +from uuid import UUID from pydantic import BaseModel, ConfigDict, Field from catalystwan.api.configuration_groups.parcel import Default, Global, Variable, as_global -from catalystwan.models.common import UUID from catalystwan.models.configuration.common import Solution T = TypeVar("T") @@ -20,10 +20,13 @@ class ProfileType(str, Enum): SYSTEM = "system" CLI = "cli" SERVICE = "service" + APPLICATION_PRIORITY = "application-priority" + POLICY_OBJECT = "policy-object" + EMBEDDED_SECURITY = "embedded-security" class FeatureProfileInfo(BaseModel): - profile_id: str = Field(alias="profileId") + profile_id: UUID = Field(alias="profileId") profile_name: str = Field(alias="profileName") solution: Solution profile_type: ProfileType = Field(alias="profileType") @@ -70,9 +73,9 @@ class FeatureProfileCreationResponse(BaseModel): class ParcelCreationResponse(BaseModel): - model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) + model_config = ConfigDict(populate_by_name=True) - id: UUID = Field(alias="parcelId") + id: UUID = Field(serialization_alias="parcelId", validation_alias="parcelId") class ParcelType(str, Enum): @@ -93,6 +96,31 @@ class ParcelType(str, Enum): ROUTING_OSPFV3_IPV6 = "routing/ospfv3/ipv6" WIRELESSLAN = "wirelesslan" SWITCHPORT = "switchport" + APP_PROBE = "app-probe" + APPLICATION_LIST = "app-list" + COLOR = "color" + DATA_PREFIX = "data-prefix" + EXPANDED_COMMUNITY = "expanded-community" + FOWARDING_CLASS = "class" + IPV6_DATA_PREFIX = "data-ipv6-prefix" + IPV6_PREFIX_LIST = "ipv6-prefix" + PREFIX_LIST = "prefix" + POLICIER = "policer" + PREFERRED_COLOR_GROUP = "preferred-color-group" + SLA_CLASS = "sla-class" + TLOC = "tloc" + STANDARD_COMMUNITY = "standard-community" + LOCAL_DOMAIN = "security-localdomain" + FQDN_DOMAIN = "security-fqdn" + IPS_SIGNATURE = "security-ipssignature" + URL_ALLOW = "security-urllist" + URL_BLOCK = "security-urllist" + SECURITY_PORT = "security-port" + PROTOCOL_LIST = "security-protocolname" + GEO_LOCATION_LIST = "security-geolocation" + SECURITY_ZONE_LIST = "security-zone" + SECURITY_APPLICATION_LIST = "security-localapp" + SECURITY_DATA_PREFIX = "security-data-ip-prefix" class Parcel(BaseModel, Generic[T]): diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/__init__.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/__init__.py new file mode 100644 index 000000000..a2a32939f --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/__init__.py @@ -0,0 +1,119 @@ +from typing import Dict, Mapping, Union + +from pydantic import Field +from typing_extensions import Annotated + +from .policy.app_probe import AppProbeEntry as AppProbeEntry +from .policy.app_probe import AppProbeMapItem as AppProbeMapItem +from .policy.app_probe import AppProbeParcel as AppProbeParcel +from .policy.application_list import ApplicationFamilyListEntry as ApplicationFamilyListEntry +from .policy.application_list import ApplicationListEntry as ApplicationListEntry +from .policy.application_list import ApplicationListParcel +from .policy.color_list import ColorEntry as ColorEntry +from .policy.color_list import ColorParcel as ColorParcel +from .policy.data_prefix import DataPrefixEntry as DataPrefixEntry +from .policy.data_prefix import DataPrefixParcel as DataPrefixParcel +from .policy.expanded_community_list import ExpandedCommunityParcel as ExpandedCommunityParcel +from .policy.fowarding_class import FowardingClassParcel as FowardingClassParcel +from .policy.fowarding_class import FowardingClassQueueEntry as FowardingClassQueueEntry +from .policy.ipv6_data_prefix import IPv6DataPrefixEntry as IPv6DataPrefixEntry +from .policy.ipv6_data_prefix import IPv6DataPrefixParcel as IPv6DataPrefixParcel +from .policy.ipv6_prefix_list import IPv6PrefixListEntry as IPv6PrefixListEntry +from .policy.ipv6_prefix_list import IPv6PrefixListParcel as IPv6PrefixListParcel +from .policy.policier import PolicierEntry as PolicierEntry +from .policy.policier import PolicierParcel as PolicierParcel +from .policy.prefered_group_color import Preference as Preference +from .policy.prefered_group_color import PreferredColorGroupEntry as PreferredColorGroupEntry +from .policy.prefered_group_color import PreferredColorGroupParcel as PreferredColorGroupParcel +from .policy.prefix_list import PrefixListEntry as PrefixListEntry +from .policy.prefix_list import PrefixListParcel as PrefixListParcel +from .policy.sla_class import FallbackBestTunnel as FallbackBestTunnel +from .policy.sla_class import SLAAppProbeClass as SLAAppProbeClass +from .policy.sla_class import SLAClassCriteriaEnum as SLAClassCriteriaEnum +from .policy.sla_class import SLAClassListEntry as SLAClassListEntry +from .policy.sla_class import SLAClassParcel as SLAClassParcel +from .policy.standard_community import StandardCommunityEntry as StandardCommunityEntry +from .policy.standard_community import StandardCommunityParcel as StandardCommunityParcel +from .policy.tloc_list import TlocEntry as TlocEntry +from .policy.tloc_list import TlocParcel as TlocParcel +from .security.application_list import SecurityApplicationFamilyListEntry as SecurityApplicationFamilyListEntry +from .security.application_list import SecurityApplicationListEntry as SecurityApplicationListEntry +from .security.application_list import SecurityApplicationListParcel as SecurityApplicationListParcel +from .security.data_prefix import SecurityDataPrefixEntry as SecurityDataPrefixEntry +from .security.data_prefix import SecurityDataPrefixParcel as SecurityDataPrefixParcel +from .security.fqdn import FQDNDomainParcel as FQDNDomainParcel +from .security.fqdn import FQDNListEntry as FQDNListEntry +from .security.geolocation_list import GeoLocationListEntry as GeoLocationListEntry +from .security.geolocation_list import GeoLocationListParcel as GeoLocationListParcel +from .security.ips_signature import IPSSignatureListEntry as IPSSignatureListEntry +from .security.ips_signature import IPSSignatureParcel as IPSSignatureParcel +from .security.local_domain import LocalDomainListEntry as LocalDomainListEntry +from .security.local_domain import LocalDomainParcel as LocalDomainParcel +from .security.protocol_list import ProtocolListEntry as ProtocolListEntry +from .security.protocol_list import ProtocolListParcel as ProtocolListParcel +from .security.security_port import SecurityPortListEntry as SecurityPortListEntry +from .security.security_port import SecurityPortParcel as SecurityPortParcel +from .security.url import BaseURLListEntry as BaseURLListEntry +from .security.url import URLAllowParcel as URLAllowParcel +from .security.url import URLBlockParcel as URLBlockParcel +from .security.zone import SecurityZoneListEntry as SecurityZoneListEntry +from .security.zone import SecurityZoneListParcel as SecurityZoneListParcel + +AnyPolicyObjectParcel = Annotated[ + Union[ + AppProbeParcel, + ApplicationListParcel, + ColorParcel, + DataPrefixParcel, + ExpandedCommunityParcel, + FowardingClassParcel, + IPv6DataPrefixParcel, + IPv6PrefixListParcel, + PrefixListParcel, + PolicierParcel, + PreferredColorGroupParcel, + SLAClassParcel, + TlocParcel, + StandardCommunityParcel, + LocalDomainParcel, + FQDNDomainParcel, + IPSSignatureParcel, + URLAllowParcel, + URLBlockParcel, + SecurityPortParcel, + ProtocolListParcel, + GeoLocationListParcel, + SecurityZoneListParcel, + SecurityApplicationListParcel, + SecurityDataPrefixParcel, + ], + Field(discriminator="type"), +] + +POLICY_OBJECT_PAYLOAD_ENDPOINT_MAPPING: Mapping[type, str] = { + AppProbeParcel: "app-probe", + ApplicationListParcel: "app-list", + ColorParcel: "color", + DataPrefixParcel: "data-prefix", + ExpandedCommunityParcel: "expanded-community", + FowardingClassParcel: "class", + IPv6DataPrefixParcel: "data-ipv6-prefix", + IPv6PrefixListParcel: "ipv6-prefix", + PrefixListParcel: "prefix", + PolicierParcel: "policer", + PreferredColorGroupParcel: "preferred-color-group", + SLAClassParcel: "sla-class", + TlocParcel: "tloc", + StandardCommunityParcel: "standard-community", + LocalDomainParcel: "security-localdomain", + FQDNDomainParcel: "security-fqdn", + IPSSignatureParcel: "security-ipssignature", + URLAllowParcel: "security-urllist", + URLBlockParcel: "security-urllist", + SecurityPortParcel: "security-port", + ProtocolListParcel: "security-protocolname", + GeoLocationListParcel: "security-geolocation", + SecurityZoneListParcel: "security-zone", + SecurityApplicationListParcel: "security-localapp", + SecurityDataPrefixParcel: "security-data-ip-prefix", +} diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/app_probe.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/app_probe.py new file mode 100644 index 000000000..46e723788 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/app_probe.py @@ -0,0 +1,40 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field, field_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global +from catalystwan.models.common import TLOCColorEnum + + +class AppProbeMapItem(BaseModel): + color: Global[TLOCColorEnum] + dscp: Global[int] + + @field_validator("dscp") + @classmethod + def check_rate(cls, dscp: Global): + assert 0 <= int(dscp.value) <= 63 + return dscp + + +class AppProbeEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + map: List[AppProbeMapItem] = Field(default=[]) + forwarding_class_name: Global[str] = Field( + serialization_alias="forwardingClass", validation_alias="forwardingClass" + ) + + +class AppProbeParcel(_ParcelBase): + entries: List[AppProbeEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_fowarding_class(self, forwarding_class_name: str): + self.entries.append( + AppProbeEntry( + forwarding_class_name=as_global(forwarding_class_name), + ) + ) + + def add_map(self, color: TLOCColorEnum, dscp: int): + entry = self.entries[0] + entry.map.append(AppProbeMapItem(color=as_global(color), dscp=as_global(dscp))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/application_list.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/application_list.py new file mode 100644 index 000000000..eeda66374 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/application_list.py @@ -0,0 +1,27 @@ +from typing import List, Union + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class ApplicationListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + app_list: Global[str] = Field(serialization_alias="app", validation_alias="app") + + +class ApplicationFamilyListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + app_list_family: Global[str] = Field(serialization_alias="appFamily", validation_alias="appFamily") + + +class ApplicationListParcel(_ParcelBase): + entries: List[Union[ApplicationListEntry, ApplicationFamilyListEntry]] = Field( + default=[], validation_alias=AliasPath("data", "entries") + ) + + def add_application(self, application: str): + self.entries.append(ApplicationListEntry(app_list=as_global(application))) + + def add_application_family(self, application_family: str): + self.entries.append(ApplicationFamilyListEntry(app_list_family=as_global(application_family))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/color_list.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/color_list.py new file mode 100644 index 000000000..bb7541af9 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/color_list.py @@ -0,0 +1,17 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global +from catalystwan.models.common import TLOCColorEnum + + +class ColorEntry(BaseModel): + color: Global[TLOCColorEnum] + + +class ColorParcel(_ParcelBase): + entries: List[ColorEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_color(self, color: TLOCColorEnum): + self.entries.append(ColorEntry(color=as_global(color))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/data_prefix.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/data_prefix.py new file mode 100644 index 000000000..b4d7721f7 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/data_prefix.py @@ -0,0 +1,24 @@ +from ipaddress import IPv4Address, IPv4Network +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class DataPrefixEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + ipv4_address: Global[IPv4Address] = Field(serialization_alias="ipv4Address", validation_alias="ipv4Address") + ipv4_prefix_length: Global[int] = Field(serialization_alias="ipv4PrefixLength", validation_alias="ipv4PrefixLength") + + +class DataPrefixParcel(_ParcelBase): + entries: List[DataPrefixEntry] = Field(default_factory=list, validation_alias=AliasPath("data", "entries")) + + def add_data_prefix(self, ipv4_network: IPv4Network): + self.entries.append( + DataPrefixEntry( + ipv4_address=as_global(ipv4_network.network_address), + ipv4_prefix_length=as_global(ipv4_network.prefixlen), + ) + ) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/expanded_community_list.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/expanded_community_list.py new file mode 100644 index 000000000..7ceedd0da --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/expanded_community_list.py @@ -0,0 +1,21 @@ +from pydantic import AliasPath, ConfigDict, Field, field_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class ExpandedCommunityParcel(_ParcelBase): + model_config = ConfigDict(populate_by_name=True) + expandedCommunityList: Global[list] = Field( + default=as_global([]), + serialization_alias="expandedCommunityList", + validation_alias=AliasPath("data", "expandedCommunityList"), + ) + + def add_community(self, expanded_community: str): + self.expandedCommunityList.value.append(expanded_community) + + @field_validator("expandedCommunityList") + @classmethod + def check_rate(cls, expanded_community_list: Global): + assert all([isinstance(ec, str) for ec in expanded_community_list.value]) + return expanded_community_list diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/fowarding_class.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/fowarding_class.py new file mode 100644 index 000000000..769072b39 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/fowarding_class.py @@ -0,0 +1,22 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, Field, field_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class FowardingClassQueueEntry(BaseModel): + queue: Global[str] + + @field_validator("queue") + @classmethod + def check_burst(cls, queue: Global): + assert 0 <= int(queue.value) <= 7 + return queue + + +class FowardingClassParcel(_ParcelBase): + entries: List[FowardingClassQueueEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_queue(self, queue: int): + self.entries.append(FowardingClassQueueEntry(queue=as_global(str(queue)))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/ipv6_data_prefix.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/ipv6_data_prefix.py new file mode 100644 index 000000000..4e6c58603 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/ipv6_data_prefix.py @@ -0,0 +1,24 @@ +from ipaddress import IPv6Address, IPv6Network +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class IPv6DataPrefixEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + ipv6_address: Global[IPv6Address] = Field(serialization_alias="ipv6Address", validation_alias="ipv6Address") + ipv6_prefix_length: Global[int] = Field(serialization_alias="ipv6PrefixLength", validation_alias="ipv6PrefixLength") + + +class IPv6DataPrefixParcel(_ParcelBase): + entries: List[IPv6DataPrefixEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_prefix(self, ipv6_network: IPv6Network): + self.entries.append( + IPv6DataPrefixEntry( + ipv6_address=as_global(ipv6_network.network_address), + ipv6_prefix_length=as_global(ipv6_network.prefixlen), + ) + ) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/ipv6_prefix_list.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/ipv6_prefix_list.py new file mode 100644 index 000000000..f80c0687b --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/ipv6_prefix_list.py @@ -0,0 +1,24 @@ +from ipaddress import IPv6Address, IPv6Network +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class IPv6PrefixListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + ipv6_address: Global[IPv6Address] = Field(serialization_alias="ipv6Address", validation_alias="ipv6Address") + ipv6_prefix_length: Global[int] = Field(serialization_alias="ipv6PrefixLength", validation_alias="ipv6PrefixLength") + + +class IPv6PrefixListParcel(_ParcelBase): + entries: List[IPv6PrefixListEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_prefix(self, ipv6_network: IPv6Network): + self.entries.append( + IPv6PrefixListEntry( + ipv6_address=as_global(ipv6_network.network_address), + ipv6_prefix_length=as_global(ipv6_network.prefixlen), + ) + ) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/policier.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/policier.py new file mode 100644 index 000000000..d38e26459 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/policier.py @@ -0,0 +1,38 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field, field_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global +from catalystwan.models.policy.lists_entries import PolicerExceedActionEnum + + +class PolicierEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + burst: Global[int] + exceed: Global[PolicerExceedActionEnum] + rate: Global[int] + + @field_validator("burst") + @classmethod + def check_burst(cls, burst_str: Global): + assert 15000 <= burst_str.value <= 10_000_000 + return burst_str + + @field_validator("rate") + @classmethod + def check_rate(cls, rate_str: Global): + assert 8 <= rate_str.value <= 100_000_000_000 + return rate_str + + +class PolicierParcel(_ParcelBase): + entries: List[PolicierEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_entry(self, burst: int, exceed: PolicerExceedActionEnum, rate: int): + self.entries.append( + PolicierEntry( + burst=as_global(burst), + exceed=as_global(exceed), + rate=as_global(rate), + ) + ) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/prefered_group_color.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/prefered_group_color.py new file mode 100644 index 000000000..c05769f22 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/prefered_group_color.py @@ -0,0 +1,63 @@ +from typing import List, Optional + +from pydantic import AliasPath, BaseModel, ConfigDict, Field, model_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global +from catalystwan.models.common import TLOCColorEnum +from catalystwan.models.policy.lists_entries import PathPreferenceEnum + + +class Preference(BaseModel): + model_config = ConfigDict(populate_by_name=True) + color_preference: Global[list] = Field( # [TLOCColorEnum] + serialization_alias="colorPreference", validation_alias="colorPreference" + ) + path_preference: Global[PathPreferenceEnum] = Field( + serialization_alias="pathPreference", validation_alias="pathPreference" + ) + + +class PreferredColorGroupEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + primary_preference: Preference = Field( + serialization_alias="primaryPreference", validation_alias="primaryPreference" + ) + secondary_preference: Optional[Preference] = Field( + None, serialization_alias="secondaryPreference", validation_alias="secondaryPreference" + ) + tertiary_preference: Optional[Preference] = Field( + None, serialization_alias="tertiaryPreference", validation_alias="tertiaryPreference" + ) + + @model_validator(mode="after") + def check_passwords_match(self) -> "PreferredColorGroupEntry": + if not self.secondary_preference and self.tertiary_preference: + raise ValueError("Preference Entry has to have a secondary prefrence when assigning tertiary preference.") + return self + + +class PreferredColorGroupParcel(_ParcelBase): + entries: List[PreferredColorGroupEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_primary(self, color_preference: List[TLOCColorEnum], path_preference: PathPreferenceEnum): + self.entries.append( + PreferredColorGroupEntry( + primary_preference=Preference( + color_preference=as_global(color_preference), path_preference=as_global(path_preference) + ), + secondary_preference=None, + tertiary_preference=None, + ) + ) + + def add_secondary(self, color_preference: List[TLOCColorEnum], path_preference: PathPreferenceEnum): + preferred_color = self.entries[0] + preferred_color.secondary_preference = Preference( + color_preference=as_global(color_preference), path_preference=as_global(path_preference) + ) + + def add_tertiary(self, color_preference: List[TLOCColorEnum], path_preference: PathPreferenceEnum): + preferred_color = self.entries[0] + preferred_color.tertiary_preference = Preference( + color_preference=as_global(color_preference), path_preference=as_global(path_preference) + ) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/prefix_list.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/prefix_list.py new file mode 100644 index 000000000..3c74105a6 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/prefix_list.py @@ -0,0 +1,24 @@ +from ipaddress import IPv4Address, IPv4Network +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class PrefixListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + ipv4_address: Global[IPv4Address] = Field(serialization_alias="ipv4Address", validation_alias="ipv4Address") + ipv4_prefix_length: Global[int] = Field(serialization_alias="ipv4PrefixLength", validation_alias="ipv4PrefixLength") + + +class PrefixListParcel(_ParcelBase): + entries: List[PrefixListEntry] = Field(default_factory=list, validation_alias=AliasPath("data", "entries")) + + def add_prefix(self, ipv4_network: IPv4Network): + self.entries.append( + PrefixListEntry( + ipv4_address=as_global(ipv4_network.network_address), + ipv4_prefix_length=as_global(ipv4_network.prefixlen), + ) + ) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/sla_class.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/sla_class.py new file mode 100644 index 000000000..2e8af6bfe --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/sla_class.py @@ -0,0 +1,151 @@ +from enum import Enum +from typing import List, Optional, Union +from uuid import UUID + +from pydantic import AliasPath, BaseModel, ConfigDict, Field, field_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class SLAClassCriteriaEnum(str, Enum): + LOSS = "loss" + LATENCY = "latency" + JITTER = "jitter" + LOSS_LATENCY = "loss-latency" + LOSS_JITTER = "loss-jitter" + LATENCY_LOSS = "latency-loss" + LATENCY_JITTER = "latency-jitter" + JITTER_LATENCY = "jitter-latency" + JITTER_LOSS = "jitter-loss" + LOSS_LATENCY_JITTER = "loss-latency-jitter" + LOSS_JITTER_LATENCY = "loss-jitter-latency" + LATENCY_LOSS_JITTER = "latency-loss-jitter" + LATENCY_JITTER_LOSS = "latency-jitter-loss" + JITTER_LATENCY_LOSS = "jitter-latency-loss" + JITTER_LOSS_LATENCY = "jitter-loss-latency" + + +class SLAAppProbeClass(BaseModel): + model_config = ConfigDict(populate_by_name=True) + + ref_id: Global[UUID] = Field(serialization_alias="refId", validation_alias="refId") + + +class FallbackBestTunnel(BaseModel): + model_config = ConfigDict(populate_by_name=True) + + criteria: Global[SLAClassCriteriaEnum] + jitter_variance: Optional[Global[int]] = Field( + default=None, + serialization_alias="jitterVariance", + validation_alias="jitterVariance", + description="jitter variance in ms", + ) + latency_variance: Optional[Global[int]] = Field( + default=None, + serialization_alias="latencyVariance", + validation_alias="latencyVariance", + description="latency variance in ms", + ) + loss_variance: Optional[Global[int]] = Field( + default=None, + serialization_alias="lossVariance", + validation_alias="lossVariance", + description="loss variance as percentage", + ) + + def add_criterias( + self, jitter_variance: Union[int, None], latency_variance: Union[int, None], loss_variance: Union[int, None] + ): + expected_criterias = [] + if jitter_variance: + self.jitter_variance = Global(value=jitter_variance) + expected_criterias.append("jitter") + if latency_variance: + self.latency_variance = Global(value=latency_variance) + expected_criterias.append("latency") + if loss_variance: + self.loss_variance = Global(value=loss_variance) + expected_criterias.append("loss") + for e in expected_criterias: + if e not in self.criteria.value: + raise ValueError(f"Criteria {e} is not in configured criteraias {self.criteria.value}") + + @field_validator("latency_variance") + @classmethod + def check_latency(cls, latency: Global): + assert 1 <= latency.value <= 1000 + return latency + + @field_validator("loss_variance") + @classmethod + def check_loss(cls, loss: Global): + assert 0 <= loss.value <= 100 + return loss + + @field_validator("jitter_variance") + @classmethod + def check_jitter(cls, jitter: Global): + assert 1 <= jitter.value <= 1000 + return jitter + + +class SLAClassListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + + latency: Optional[Global[int]] = None + loss: Optional[Global[int]] = None + jitter: Optional[Global[int]] = None + app_probe_class: Optional[SLAAppProbeClass] = Field( + validation_alias="appProbeClass", serialization_alias="appProbeClass" + ) + fallback_best_tunnel: Optional[FallbackBestTunnel] = Field( + default=None, validation_alias="fallbackBestTunnel", serialization_alias="fallbackBestTunnel" + ) + + @field_validator("latency") + @classmethod + def check_latency(cls, latency: Global): + assert 1 <= latency.value <= 1000 + return latency + + @field_validator("loss") + @classmethod + def check_loss(cls, loss: Global): + assert 0 <= loss.value <= 100 + return loss + + @field_validator("jitter") + @classmethod + def check_jitter(cls, jitter: Global): + assert 1 <= jitter.value <= 1000 + return jitter + + +class SLAClassParcel(_ParcelBase): + entries: List[SLAClassListEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_entry(self, app_probe_class_id: UUID, loss: Optional[int], jitter: Optional[int], latency: Optional[int]): + self.entries.append( + SLAClassListEntry( + app_probe_class=SLAAppProbeClass(ref_id=as_global(app_probe_class_id)), + loss=as_global(loss), + jitter=as_global(jitter), + latency=as_global(latency), + ) + ) + + def add_fallback( + self, + criteria: SLAClassCriteriaEnum, + jitter_variance: Optional[int], + latency_variance: Optional[int], + loss_variance: Optional[int], + ): + fallback = FallbackBestTunnel( + criteria=as_global(criteria), + jitter_variance=as_global(jitter_variance), + latency_variance=as_global(latency_variance), + loss_variance=as_global(loss_variance), + ) + self.entries[0].fallback_best_tunnel = fallback diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/standard_community.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/standard_community.py new file mode 100644 index 000000000..ce87f6de3 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/standard_community.py @@ -0,0 +1,20 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global +from catalystwan.models.common import WellKnownBGPCommunitiesEnum + + +class StandardCommunityEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + standard_community: Global[WellKnownBGPCommunitiesEnum] = Field( + serialization_alias="standardCommunity", validation_alias="standardCommunity" + ) + + +class StandardCommunityParcel(_ParcelBase): + entries: List[StandardCommunityEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_community(self, standard_community: WellKnownBGPCommunitiesEnum): + self.entries.append(StandardCommunityEntry(standard_community=as_global(standard_community))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/tloc_list.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/tloc_list.py new file mode 100644 index 000000000..935445e77 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/policy/tloc_list.py @@ -0,0 +1,41 @@ +from ipaddress import IPv4Address +from typing import List, Optional + +from pydantic import AliasPath, BaseModel, ConfigDict, Field, field_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global +from catalystwan.models.common import TLOCColorEnum +from catalystwan.models.policy.lists_entries import EncapEnum + + +class TlocEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + tloc: Global[IPv4Address] + color: Global[TLOCColorEnum] + encapsulation: Global[EncapEnum] = Field(serialization_alias="encap", validation_alias="encap") + preference: Optional[Global[str]] = None + + @field_validator("preference") + @classmethod + def ensure_correct_preference_value(cls, v: Global): + if not v: + return v + if not (0 <= int(v.value) < 4_294_967_295): + raise ValueError('"preference" not in range 0 - 4 294 967 295 (2 ** 32 - 1)') + return v + + +class TlocParcel(_ParcelBase): + entries: List[TlocEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_entry( + self, tloc: IPv4Address, color: TLOCColorEnum, encapsulation: EncapEnum, preference: Optional[str] = None + ): + self.entries.append( + TlocEntry( + tloc=as_global(tloc), + color=as_global(color), + encapsulation=as_global(encapsulation), + preference=as_global(preference), + ) + ) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/application_list.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/application_list.py new file mode 100644 index 000000000..50d808d4f --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/application_list.py @@ -0,0 +1,27 @@ +from typing import List, Union + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class SecurityApplicationListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + app_list: Global[str] = Field(serialization_alias="app", validation_alias="app") + + +class SecurityApplicationFamilyListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + app_list_family: Global[str] = Field(serialization_alias="appFamily", validation_alias="appFamily") + + +class SecurityApplicationListParcel(_ParcelBase): + entries: List[Union[SecurityApplicationFamilyListEntry, SecurityApplicationListEntry]] = Field( + default=[], validation_alias=AliasPath("data", "entries") + ) + + def add_application(self, application: str): + self.entries.append(SecurityApplicationListEntry(app_list=as_global(application))) + + def add_application_family(self, application_family: str): + self.entries.append(SecurityApplicationFamilyListEntry(app_list_family=as_global(application_family))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/data_prefix.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/data_prefix.py new file mode 100644 index 000000000..263a77758 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/data_prefix.py @@ -0,0 +1,18 @@ +from ipaddress import IPv4Network +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class SecurityDataPrefixEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + ip_prefix: Global[IPv4Network] = Field(serialization_alias="ipPrefix", validation_alias="ipPrefix") + + +class SecurityDataPrefixParcel(_ParcelBase): + entries: List[SecurityDataPrefixEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_prefix(self, ip_prefix: IPv4Network): + self.entries.append(SecurityDataPrefixEntry(ip_prefix=as_global(ip_prefix))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/fqdn.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/fqdn.py new file mode 100644 index 000000000..e80dbe170 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/fqdn.py @@ -0,0 +1,20 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class FQDNListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + pattern: Global[str] = Field( + description="Ex: cisco.com, .*cisco.com, .*.cisco.com. Should not start with '*' or '+'" + ) + + +class FQDNDomainParcel(_ParcelBase): + entries: List[FQDNListEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def from_fqdns(self, fqdns: List[str]): + for fqdn in fqdns: + self.entries.append(FQDNListEntry(pattern=as_global(fqdn))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/geolocation_list.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/geolocation_list.py new file mode 100644 index 000000000..d2e3ce69b --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/geolocation_list.py @@ -0,0 +1,28 @@ +from typing import List, Optional + +from pydantic import AliasPath, BaseModel, Field, model_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global +from catalystwan.models.common import check_fields_exclusive + + +class GeoLocationListEntry(BaseModel): + country: Optional[Global[str]] = Field(default=None, description="ISO-3166 alpha-3 country code eg: FRA") + continent: Optional[Global[str]] = Field( + default=None, description="One of 2-letter continent codes: AF, NA, OC, AN, AS, EU, SA" + ) + + @model_validator(mode="after") + def check_country_xor_continent(self): + check_fields_exclusive(self.__dict__, {"country", "continent"}, True) + return self + + +class GeoLocationListParcel(_ParcelBase): + entries: List[GeoLocationListEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_country(self, country: str): + self.entries.append(GeoLocationListEntry(country=as_global(country))) + + def add_continent(self, continent: str): + self.entries.append(GeoLocationListEntry(continent=as_global(continent))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/ips_signature.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/ips_signature.py new file mode 100644 index 000000000..4c8f821ca --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/ips_signature.py @@ -0,0 +1,40 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field, field_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class IPSSignatureListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + generator_id: Global[str] = Field( + serialization_alias="generatorId", validation_alias="generatorId", description="Range 0 to 4294967295" + ) + signature_id: Global[str] = Field( + serialization_alias="signatureId", validation_alias="signatureId", description="Range 0 to 4294967295" + ) + + @field_validator("generator_id") + @classmethod + def check_generator_id(cls, generator_id: Global): + assert 0 <= int(generator_id.value) <= 4294967295 + return generator_id + + @field_validator("signature_id") + @classmethod + def check_signature_id(cls, signature_id: Global): + assert 0 <= int(signature_id.value) <= 4294967295 + return signature_id + + +class IPSSignatureParcel(_ParcelBase): + entries: List[IPSSignatureListEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_signature(self, signature: str): + generator_id, signature_id = signature.split(":") + self.entries.append( + IPSSignatureListEntry( + generator_id=as_global(generator_id), + signature_id=as_global(signature_id), + ) + ) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/local_domain.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/local_domain.py new file mode 100644 index 000000000..92e63f4e8 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/local_domain.py @@ -0,0 +1,20 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class LocalDomainListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + name_server: Global[str] = Field( + serialization_alias="nameServer", validation_alias="nameServer", description="Ex: cisco.com, *.cisco.com" + ) + + +class LocalDomainParcel(_ParcelBase): + entries: List[LocalDomainListEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def from_local_domains(self, domains: List[str]): + for domain in domains: + self.entries.append(LocalDomainListEntry(name_server=as_global(domain))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/protocol_list.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/protocol_list.py new file mode 100644 index 000000000..fcff212d2 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/protocol_list.py @@ -0,0 +1,17 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class ProtocolListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + protocol: Global[str] = Field(serialization_alias="protocolName", validation_alias="protocolName") + + +class ProtocolListParcel(_ParcelBase): + entries: List[ProtocolListEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_protocol(self, protocol: str): + self.entries.append(ProtocolListEntry(protocol=as_global(protocol))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/security_port.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/security_port.py new file mode 100644 index 000000000..dd7b00914 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/security_port.py @@ -0,0 +1,33 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field, field_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class SecurityPortListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + port: Global[str] = Field(description="Ex: 1 or 1-10 by range. Range 0 to 65530") + + @field_validator("port") + @classmethod + def check_port(cls, port: Global[str]): + value = port.value + if value.count("-") == 0: + assert 0 <= int(value) <= 65530 + return port + + start_port, end_port = value.split("-") + start = int(start_port) + end = int(end_port) + assert 0 <= start <= 65530 + assert 0 <= end <= 65530 + assert start < end + return port + + +class SecurityPortParcel(_ParcelBase): + entries: List[SecurityPortListEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_port(self, port: str): + self.entries.append(SecurityPortListEntry(port=as_global(port))) diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/url.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/url.py new file mode 100644 index 000000000..a42a4d561 --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/url.py @@ -0,0 +1,25 @@ +from typing import List + +from pydantic import AliasPath, BaseModel, ConfigDict, Field + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global + + +class BaseURLListEntry(BaseModel): + model_config = ConfigDict(populate_by_name=True) + pattern: Global[str] + + +class BaseURLParcel(_ParcelBase): + entries: List[BaseURLListEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_url(self, pattern: str): + self.entries.append(BaseURLListEntry(pattern=as_global(pattern))) + + +class URLAllowParcel(BaseURLParcel): + parcel_type: str = Field(default="urlallowed", validation_alias="type", serialization_alias="type") + + +class URLBlockParcel(BaseURLParcel): + parcel_type: str = Field(default="urlblocked", validation_alias="type", serialization_alias="type") diff --git a/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/zone.py b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/zone.py new file mode 100644 index 000000000..e9955119d --- /dev/null +++ b/catalystwan/models/configuration/feature_profile/sdwan/policy_object/security/zone.py @@ -0,0 +1,40 @@ +from typing import List, Optional + +from pydantic import AliasPath, BaseModel, Field, field_validator, model_validator + +from catalystwan.api.configuration_groups.parcel import Global, _ParcelBase, as_global +from catalystwan.models.common import InterfaceTypeEnum, check_fields_exclusive + + +class SecurityZoneListEntry(BaseModel): + vpn: Optional[Global[str]] = Field(default=None, description="0-65530 single number") + interface: Optional[Global[InterfaceTypeEnum]] = None + + @field_validator("vpn") + @classmethod + def check_vpn_range(cls, vpn: Global[str]): + assert 0 <= int(vpn.value) <= 65530 + return vpn + + @model_validator(mode="after") + def check_vpn_xor_interface(self): + check_fields_exclusive(self.__dict__, {"vpn", "interface"}, True) + return self + + +class SecurityZoneListParcel(_ParcelBase): + entries: List[SecurityZoneListEntry] = Field(default=[], validation_alias=AliasPath("data", "entries")) + + def add_interface(self, interface: InterfaceTypeEnum): + self.entries.append( + SecurityZoneListEntry( + interface=as_global(interface), + ) + ) + + def add_vpn(self, vpn: str): + self.entries.append( + SecurityZoneListEntry( + vpn=as_global(vpn), + ) + ) diff --git a/catalystwan/response.py b/catalystwan/response.py index 0846db4e0..c125c3453 100644 --- a/catalystwan/response.py +++ b/catalystwan/response.py @@ -11,7 +11,8 @@ from requests.exceptions import JSONDecodeError from catalystwan import with_proc_info_header -from catalystwan.endpoints import APIEndpointClientResponse +from catalystwan.abstractions import APIEndpointClientResponse +from catalystwan.exceptions import ManagerErrorInfo from catalystwan.typed_list import DataSequence from catalystwan.utils.creation_tools import create_dataclass @@ -20,12 +21,6 @@ SENSITIVE_URL_PATHS = ["/dataservice/settings/configuration/smartaccountcredentials"] -class ErrorInfo(BaseModelV2): - message: Union[str, None] - details: Union[str, None] - code: Union[str, None] - - def response_debug(response: Optional[Response], request: Union[Request, PreparedRequest, None]) -> str: """Returns human readable string containing Request-Response contents (helpful for debugging). @@ -212,17 +207,17 @@ def dataobj(self, cls: Type[T], sourcekey: Optional[str] = "data") -> T: return cls.model_validate(data) # type: ignore return create_dataclass(cls, data) - def get_error_info(self) -> ErrorInfo: + def get_error_info(self) -> ManagerErrorInfo: """Returns error information from JSON payload""" if self.payload.error is None: - return ErrorInfo( + return ManagerErrorInfo( message=None, details=None, code=None, ) - return ErrorInfo(**self.payload.error) + return ManagerErrorInfo(**self.payload.error) def with_vmanage_response(method: Callable[[Any], Response]) -> Callable[[Any], ManagerResponse]: diff --git a/catalystwan/session.py b/catalystwan/session.py index 72f9bbd7c..7d0a2a6db 100644 --- a/catalystwan/session.py +++ b/catalystwan/session.py @@ -18,9 +18,15 @@ from catalystwan.endpoints import APIEndpointClient from catalystwan.endpoints.client import AboutInfo, ServerInfo from catalystwan.endpoints.endpoints_container import APIEndpointContainter -from catalystwan.exceptions import InvalidOperationError, ManagerError, SessionNotCreatedError, TenantSubdomainNotFound +from catalystwan.exceptions import ( + DefaultPasswordError, + ManagerHTTPError, + ManagerRequestException, + SessionNotCreatedError, + TenantSubdomainNotFound, +) from catalystwan.models.tenant import Tenant -from catalystwan.response import ErrorInfo, ManagerResponse, response_history_debug +from catalystwan.response import ManagerResponse, response_history_debug from catalystwan.utils.session_type import SessionType from catalystwan.version import NullVersion, parse_api_version from catalystwan.vmanage_auth import vManageAuth @@ -29,24 +35,6 @@ USER_AGENT = f"{__package__}/{metadata.version(__package__)}" -class vManageBadResponseError(ManagerError): - """Indicates that vManage returned error HTTP status code other than 400.""" - - def __init__(self, error_info: Optional[ErrorInfo], response: ManagerResponse): - self.response = response - self.info = error_info - super().__init__(error_info) - - -class vManageBadRequestError(vManageBadResponseError): - """Indicates that vManage returned HTTP status code 400. - - A 400 Bad Request response status code indicates that the server - could not understand the request due to invalid syntax, - malformed request message, or missing request parameters. - """ - - class UserMode(str, Enum): PROVIDER = "provider" TENANT = "tenant" @@ -114,7 +102,7 @@ def create_manager_session( try: server_info = session.server() - except InvalidOperationError: + except DefaultPasswordError: server_info = ServerInfo.parse_obj({}) session.server_name = server_info.server @@ -218,7 +206,7 @@ def request(self, method, url, *args, **kwargs) -> ManagerResponse: except RequestException as exception: self.logger.debug(self.response_trace(exception.response, exception.request)) self.logger.error(exception) - raise + raise ManagerRequestException(request=exception.request, response=exception.response) if self.enable_relogin and self.__is_jsession_updated(response): self.logger.warning("Logging to session again. Reason: JSESSIONID cookie updated by response") @@ -226,19 +214,14 @@ def request(self, method, url, *args, **kwargs) -> ManagerResponse: return self.request(method, url, *args, **kwargs) if response.request.url and "passwordReset.html" in response.request.url: - raise InvalidOperationError("Password must be changed to use this session.") + raise DefaultPasswordError("Password must be changed to use this session.") try: response.raise_for_status() except HTTPError as error: - self.logger.debug(error) + self.logger.error(error) error_info = response.get_error_info() - if response.status_code == 403: - self.logger.info(f"User {self.username} is unauthorized for method {method} {full_url}") - if response.status_code == 400: - raise vManageBadRequestError(error_info, response) - else: - raise vManageBadResponseError(error_info, response) + raise ManagerHTTPError(error_info=error_info, request=error.request, response=error.response) return response def get_full_url(self, url_path: str) -> str: diff --git a/catalystwan/tests/templates/models/cisco_vpn.py b/catalystwan/tests/templates/models/cisco_vpn.py index eda2bd9b8..a9cf7cd16 100644 --- a/catalystwan/tests/templates/models/cisco_vpn.py +++ b/catalystwan/tests/templates/models/cisco_vpn.py @@ -18,6 +18,7 @@ Nat, Natpool, NextHop, + NextHopv6, Overload, Pool, PortForward, @@ -64,7 +65,7 @@ omp_admin_distance_ipv4=10, omp_admin_distance_ipv6=100, route_v4=[Routev4(prefix="prefixv4", next_hop=[NextHop(address="1.1.1.1")])], - route_v6=[Routev6(prefix="prefixv6", next_hop=[NextHop(address="2.2.2.2")], nat=Nat.NAT64)], + route_v6=[Routev6(prefix="prefixv6", next_hop=[NextHopv6(address="2.2.2.2")], nat=Nat.NAT64)], dns=[Dns(dns_addr="1.1.1.1"), Dns(dns_addr="2.2.2.2", role=Role.SECONDARY)], dns_ipv6=[DnsIpv6(dns_addr="30a8:b25e:3db5:fe9f:231f:7478:4181:9234")], host=[Host(hostname="test_hostname", ip=["1.1.1.1"])], diff --git a/catalystwan/tests/templates/test_generate_payload.py b/catalystwan/tests/templates/test_generate_payload.py index 9843f8eae..81172af7e 100644 --- a/catalystwan/tests/templates/test_generate_payload.py +++ b/catalystwan/tests/templates/test_generate_payload.py @@ -7,7 +7,7 @@ from unittest.mock import patch from parameterized import parameterized -from pydantic.v1 import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from catalystwan.api.template_api import TemplatesAPI from catalystwan.api.templates.feature_template import FeatureTemplate @@ -15,9 +15,7 @@ class MockedFeatureTemplate(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) template_name: str = "test" template_description: str = "test" @@ -28,9 +26,7 @@ class Config: class MockedFeatureTemplateAlias(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) template_name: str = "test" template_description: str = "test" @@ -41,27 +37,22 @@ class Config: class RSA(BaseModel): - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) key: str = Field(alias="key-string") - key_type: str = Field(alias="key-type", data_path=["type", "RSA"]) + key_type: str = Field(alias="key-type", json_schema_extra={"data_path": ["type", "RSA"]}) class User(BaseModel): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) name: str - password: str = Field(data_path=["list"]) + password: str = Field(json_schema_extra={"data_path": ["list"]}) pubkey_chain: List[RSA] = Field(default=[], alias="pubkey-chain") class MockedFeatureTemplateChildren(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) template_name: str = "test" template_description: str = "test" @@ -72,16 +63,14 @@ class Config: class DataPathFeatureTemplate(FeatureTemplate): - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True + model_config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True) template_name: str = "test" template_description: str = "test" payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" type: ClassVar[str] = "test_type" - as_num: str = Field(alias="as-num", data_path=["authentication", "dot1x", "default"]) + as_num: str = Field(alias="as-num", json_schema_extra={"data_path": ["authentication", "dot1x", "default"]}) mocked_feature_template_children_1 = MockedFeatureTemplateChildren( @@ -132,7 +121,7 @@ def test_get( mocked_template = MockedFeatureTemplate() # Act - a = templates_api.generate_feature_template_payload(mocked_template, schema).dict( + a = templates_api.generate_feature_template_payload(mocked_template, schema).model_dump( by_alias=True, exclude_none=True )["templateDefinition"] print(json.dumps(a)) diff --git a/catalystwan/tests/templates/test_serialize_model.py b/catalystwan/tests/templates/test_serialize_model.py index dba9bd6d2..e8822af39 100644 --- a/catalystwan/tests/templates/test_serialize_model.py +++ b/catalystwan/tests/templates/test_serialize_model.py @@ -43,7 +43,7 @@ def test_generate_feature_template_payload_definition( self.maxDiff = 10000 self.assertDictEqual( definition["templateDefinition"], - feature_template_payload.dict(by_alias=True)["templateDefinition"], + feature_template_payload.model_dump(by_alias=True)["templateDefinition"], ) diff --git a/catalystwan/tests/test_administration.py b/catalystwan/tests/test_administration.py index 602bf38b6..21bac8066 100644 --- a/catalystwan/tests/test_administration.py +++ b/catalystwan/tests/test_administration.py @@ -34,7 +34,7 @@ UserRole, UserUpdateRequest, ) -from catalystwan.exceptions import InvalidOperationError +from catalystwan.exceptions import CatalystwanException from catalystwan.utils.certificate_status import ValidityPeriod from catalystwan.utils.creation_tools import create_dataclass @@ -450,7 +450,7 @@ def answer(): AdministrationSettingsAPI(mock_session).update(random_dataclass) # Assert - self.assertRaises(InvalidOperationError, answer) + self.assertRaises(CatalystwanException, answer) @patch("catalystwan.session.ManagerSession") @patch("requests.Response") diff --git a/catalystwan/tests/test_devices_api.py b/catalystwan/tests/test_devices_api.py index 08590156f..11b46396a 100644 --- a/catalystwan/tests/test_devices_api.py +++ b/catalystwan/tests/test_devices_api.py @@ -10,7 +10,7 @@ from catalystwan.endpoints.endpoints_container import APIEndpointContainter from catalystwan.endpoints.monitoring_device_details import DeviceData from catalystwan.endpoints.real_time_monitoring.reboot_history import RebootEntry -from catalystwan.exceptions import InvalidOperationError +from catalystwan.exceptions import CatalystwanException from catalystwan.response import ManagerResponse from catalystwan.typed_list import DataSequence from catalystwan.utils.creation_tools import create_dataclass @@ -326,7 +326,7 @@ def answer(): return DevicesAPI(mock_session).send_certificate_state_to_controllers() # Assert - self.assertRaises(InvalidOperationError, answer) + self.assertRaises(CatalystwanException, answer) @parameterized.expand([["vm200", 0], ["vm129", 1], ["vm128", 2], ["vm1", 3]]) @patch("catalystwan.response.ManagerResponse") diff --git a/catalystwan/tests/test_endpoints.py b/catalystwan/tests/test_endpoints.py index ef4265e7f..b2715e463 100644 --- a/catalystwan/tests/test_endpoints.py +++ b/catalystwan/tests/test_endpoints.py @@ -858,6 +858,29 @@ class TestAPI(APIEndpoints): def get_data(self, fruit_type: FruitEnum) -> None: # type: ignore [empty-body] ... + def test_request_decorator_format_url_with_literal(self): + FruitType = Literal["banana", "orange", "apple"] + + class TestAPI(APIEndpoints): + @request("GET", "/v1/data/{fruit_type}") + def get_data(self, fruit_type: FruitType, payload: str) -> None: # type: ignore [empty-body] + ... + + api = TestAPI(self.session_mock) + # Act + api.get_data("banana", "not a fruit") + # Assert + self.session_mock.request.assert_called_once_with("GET", self.base_path + "/v1/data/banana", data="not a fruit") + + def test_request_decorator_raises_when_format_url_with_literal_is_not_str_subtype(self): + with self.assertRaises(APIEndpointError): + FruitType = Literal[1, 2, 3] + + class TestAPI(APIEndpoints): + @request("POST", "/v1/data/{fruit_type}") + def get_data(self, fruit_type: FruitType) -> None: # type: ignore [empty-body] + ... + def test_request_decorator_accept_union_of_models(self): class TestAPI(APIEndpoints): @request("GET", "/v1/data") diff --git a/catalystwan/tests/test_response.py b/catalystwan/tests/test_response.py index f814c95a6..b54f5eaad 100644 --- a/catalystwan/tests/test_response.py +++ b/catalystwan/tests/test_response.py @@ -10,7 +10,7 @@ from pydantic.v1 import Field as FieldV1 from catalystwan.dataclasses import DataclassBase -from catalystwan.response import ErrorInfo, ManagerResponse +from catalystwan.response import ManagerErrorInfo, ManagerResponse from catalystwan.typed_list import DataSequence @@ -161,7 +161,7 @@ def test_get_error(self, empty_error: bool, json: Any): self.response_mock.json.return_value = json vmng_response = ManagerResponse(self.response_mock) error_info = vmng_response.get_error_info() - assert isinstance(error_info, ErrorInfo) + assert isinstance(error_info, ManagerErrorInfo) if empty_error: assert error_info.message is None assert error_info.details is None diff --git a/catalystwan/tests/test_session.py b/catalystwan/tests/test_session.py index fe14afa84..b9c6447ad 100644 --- a/catalystwan/tests/test_session.py +++ b/catalystwan/tests/test_session.py @@ -4,7 +4,9 @@ import pytest # type: ignore from parameterized import parameterized # type: ignore +from requests import HTTPError, Request, RequestException, Response +from catalystwan.exceptions import CatalystwanException, ManagerHTTPError, ManagerRequestException from catalystwan.session import ManagerSession @@ -13,7 +15,7 @@ class TestSession(unittest.TestCase): def setUp(self): self.url = "example.com" self.username = "admin" - self.password = "admin_password" + self.password = "admin_password" # pragma: allowlist secret def test_session_str(self): # Arrange, Act @@ -120,5 +122,39 @@ def test_check_vmanage_server_no_port(self, mock_requests): self.assertEqual(answer, True) +class TestSessionExceptions(unittest.TestCase): + def setUp(self): + self.session = ManagerSession(url="domain.com", username="user", password="<>") + response = Response() + response.json = lambda: { + "error": { + "message": "Delete users request failed", + "details": "No user with name XYZ was found", + "code": "USER0006", + } + } + response.status_code = 500 + response.request = Request(method="GET", url="/v1/data") + self.response = response + + @parameterized.expand( + [ + (RequestException(), [CatalystwanException, ManagerRequestException, RequestException]), + (HTTPError(), [CatalystwanException, ManagerHTTPError, ManagerRequestException, RequestException]), + ] + ) + @patch("requests.sessions.Session.request") + def test_session_request_exceptions(self, lib_exception, sdk_exceptions, mock_request_base): + # Arrange + if isinstance(lib_exception, HTTPError): + mock_request_base.return_value = self.response + else: + mock_request_base.side_effect = lib_exception + for sdk_exception in sdk_exceptions: + # Act / Assert + with self.assertRaises(sdk_exception): + self.session.request(self.response.request.method, self.response.request.url) + + if __name__ == "__main__": unittest.main() diff --git a/catalystwan/utils/pydantic_field.py b/catalystwan/utils/pydantic_field.py new file mode 100644 index 000000000..c0bacb6ac --- /dev/null +++ b/catalystwan/utils/pydantic_field.py @@ -0,0 +1,10 @@ +from typing import Any, Optional + +from pydantic.fields import FieldInfo + + +def get_extra_field(field_info: FieldInfo, key: str, default: Optional[Any] = None) -> Any: + try: + return field_info.json_schema_extra.get(key, default) # type: ignore + except AttributeError: + return default diff --git a/catalystwan/utils/pydantic_validators.py b/catalystwan/utils/pydantic_validators.py index c69772392..c8f5accaf 100644 --- a/catalystwan/utils/pydantic_validators.py +++ b/catalystwan/utils/pydantic_validators.py @@ -1,24 +1,26 @@ import ipaddress from typing import Any -from pydantic.v1 import BaseModel, root_validator +from pydantic import BaseModel, model_validator class ConvertBoolToStringModel(BaseModel): - @root_validator # type: ignore - def convert_bool_to_string_validator(cls, values): - for key, value in values.items(): + @model_validator(mode="after") + def convert_bool_to_string_validator(self): + for key in self.model_fields.keys(): + value = getattr(self, key) if isinstance(value, bool): - values[key] = str(value).lower() - return values + setattr(self, key, str(value).lower()) + return self class ConvertIPToStringModel(BaseModel): - @root_validator # type: ignore - def convert_ip_to_string_validator(cls, values): - for key, value in values.items(): - values[key] = convert_ip_to_string(value) - return values + @model_validator(mode="after") + def convert_ip_to_string_validator(self): + for key in self.model_fields.keys(): + value = getattr(self, key) + setattr(self, key, convert_ip_to_string(value)) + return self def convert_ip_to_string(values: Any): diff --git a/catalystwan/vmanage_auth.py b/catalystwan/vmanage_auth.py index e9da3ea14..2d4100fd2 100644 --- a/catalystwan/vmanage_auth.py +++ b/catalystwan/vmanage_auth.py @@ -8,10 +8,10 @@ from requests.cookies import RequestsCookieJar from catalystwan import with_proc_info_header -from catalystwan.exceptions import ManagerError +from catalystwan.exceptions import CatalystwanException -class UnauthorizedAccessError(ManagerError): +class UnauthorizedAccessError(CatalystwanException): """Exception raised for wrong username/password or when user not authorized to access vManage. Attributes: diff --git a/endpoints-md.py b/endpoints-md.py index 5282bd5c3..64cd581b9 100644 --- a/endpoints-md.py +++ b/endpoints-md.py @@ -2,6 +2,7 @@ from __future__ import annotations from dataclasses import dataclass +from importlib import metadata from inspect import getsourcefile, getsourcelines from os import environ from pathlib import Path, PurePath @@ -10,6 +11,7 @@ from packaging.specifiers import SpecifierSet # type: ignore +from catalystwan import __package__ from catalystwan.endpoints import BASE_PATH, APIEndpointRequestMeta, TypeSpecifier, request, versions, view from catalystwan.utils.session_type import SessionType # type: ignore @@ -206,5 +208,6 @@ def md(self) -> str: ) if environ.get("catalystwan_export_endpoints") is not None: with open("ENDPOINTS.md", "w") as f: - f.write("**THIS FILE IS AUTO-GENERATED DO NOT EDIT**\n\n") + f.write("**THIS FILE WAS AUTO-GENERATED DO NOT EDIT**\n\n") + f.write(f"Generated for: {__package__}-{metadata.version(__package__)}\n\n") f.write(endpoint_registry.md()) diff --git a/examples/parcel_configuration_guide.py b/examples/parcel_configuration_guide.py new file mode 100644 index 000000000..a66bfb264 --- /dev/null +++ b/examples/parcel_configuration_guide.py @@ -0,0 +1,330 @@ +import logging +import sys +from dataclasses import dataclass +from ipaddress import IPv4Address, IPv4Network, IPv6Network +from typing import Any, List, Optional, Tuple +from uuid import UUID + +from catalystwan.api.feature_profile_api import PolicyObjectFeatureProfileAPI +from catalystwan.endpoints.configuration_feature_profile import ConfigurationFeatureProfile +from catalystwan.models.common import InterfaceTypeEnum, TLOCColorEnum, WellKnownBGPCommunitiesEnum +from catalystwan.models.configuration.feature_profile.common import ParcelCreationResponse +from catalystwan.models.configuration.feature_profile.sdwan.policy_object import ( + ApplicationListParcel, + AppProbeParcel, + ColorParcel, + DataPrefixParcel, + ExpandedCommunityParcel, + FowardingClassParcel, + FQDNDomainParcel, + GeoLocationListParcel, + IPSSignatureParcel, + IPv6DataPrefixParcel, + IPv6PrefixListParcel, + LocalDomainParcel, + PolicierParcel, + PreferredColorGroupParcel, + PrefixListParcel, + ProtocolListParcel, + SecurityApplicationListParcel, + SecurityDataPrefixParcel, + SecurityPortParcel, + SecurityZoneListParcel, + SLAClassCriteriaEnum, + SLAClassParcel, + StandardCommunityParcel, + TlocParcel, + URLAllowParcel, + URLBlockParcel, +) +from catalystwan.models.policy.lists_entries import EncapEnum, PathPreferenceEnum, PolicerExceedActionEnum + +logger = logging.getLogger(__name__) + +PROFILE_NAME = "Default_Policy_Object_Profile" + + +@dataclass +class CmdArguments: + url: str + port: int + user: str + password: str + device_template: Optional[str] = None + + +def configure_groups_of_interest(profile_id: UUID, api: PolicyObjectFeatureProfileAPI): + """ + This function creates various policy objects such as + FQDN, + Local Domain, + IPS Signature, + Allowed URL, + Blocked URL, + Security Port, + Geolocation, + Security Zone, + Security Application List, + Security Data Prefix, + Protocol, + Color, + Data Prefix, + IPv6 Data Prefix, + Application Family, + Preferred Color Group, + Policier, + Fowarding Class, + Tloc, + Standard Community, + Expanded Community, + App Probe, and + SLA Class. + + Args: + profile (FeatureProfileInfo): The feature profile to which the policy objects are to be added. + api (PolicyObjectFeatureProfileAPI): The API object used to create and delete the policy objects. + + Returns: + None: This function does not return any additional values. + """ + items: List[Any] = [] + items_ids: List[Tuple[ParcelCreationResponse, Any]] = [] + + # Security Groups + + # Create FQDN parcel and add FQDNs + fqdn = FQDNDomainParcel(parcel_name="FQDNDomainParcelExmaple") + fqdn.from_fqdns(["www.cisco.com", "www.aws.com", "www.youtube.com"]) + + # Create Local Domain parcel and add Local Domains + local_domain = LocalDomainParcel(parcel_name="LocalDomainParcelExample") + local_domain.from_local_domains(["www.google.com", "www.ciscodevnet.com"]) + + # Create IPS Signature parcel and add signatures + ips_signature = IPSSignatureParcel(parcel_name="IPSSignatureParcelExample") + ips_signature.add_signature("30:1000") + ips_signature.add_signature("60:3000") + + # Create Allowed URL parcel and add URLs + url_allowed = URLAllowParcel(parcel_name="URLAllowParcelExample") + url_allowed.add_url("https://www.cisco.com/") + url_allowed.add_url("https://www.test.com/") + + # Create Blocked URL parcel and add URLs + url_blocked = URLBlockParcel(parcel_name="URLBlockParcelExample") + url_blocked.add_url("https://www.example.com/") + + # Create security port parcel and add ports + security_port = SecurityPortParcel(parcel_name="SecurityPortParcelExmaple") + security_port.add_port("10") + security_port.add_port("50-100") + security_port.add_port("400-999") + + # Create Geolocation parcel and add geolocations + geolocation = GeoLocationListParcel(parcel_name="GeoLocationListParcelExample") + geolocation.add_continent("AF") + geolocation.add_country("BVT") + geolocation.add_country("ATA") + + # Create Security Zone parcel and add interfaces + security_zone = SecurityZoneListParcel(parcel_name="SecurityZoneListParcel") + security_zone.add_interface(InterfaceTypeEnum.ETHERNET) + security_zone.add_interface(InterfaceTypeEnum.TUNNEL) + + # Create Application parcel and add applications + security_application_list = SecurityApplicationListParcel(parcel_name="SecurityApplListParcelExample") + security_application_list.add_application("msn-messenger-ft") + security_application_list.add_application("aol-messenger") + security_application_list.add_application_family("app-fam-2") + + # Create Security data prefix parcel and add data prefixes + security_data_prefix_parcel = SecurityDataPrefixParcel(parcel_name="SecurityDataPrefixExample") + security_data_prefix_parcel.add_prefix(IPv4Network("10.0.0.0/16")) + security_data_prefix_parcel.add_prefix(IPv4Network("30.0.0.0/16")) + security_data_prefix_parcel.add_prefix(IPv4Network("50.0.0.0/16")) + security_data_prefix_parcel.add_prefix(IPv4Network("60.0.0.0/16")) + + # Create Protocol parcel and add protocols + protocol_list = ProtocolListParcel(parcel_name="ProtocolListParcelExample") + protocol_list.add_protocol("ldap") + protocol_list.add_protocol("kerberos") + protocol_list.add_protocol("cifs") + + # Policy Groups + + # Create Color parcel and add colors + color_parcel = ColorParcel(parcel_name="ColorParcelExample") + color_parcel.add_color(TLOCColorEnum.BIZ_INTERNET) + color_parcel.add_color(TLOCColorEnum.METRO_ETHERNET) + color_parcel.add_color(TLOCColorEnum.PUBLIC_INTERNET) + + # Create Data prefix parcel and add data prefixes + data_prefix_parcel = DataPrefixParcel(parcel_name="DataPrefixExample") + data_prefix_parcel.add_data_prefix(IPv4Network("10.0.0.0/16")) + data_prefix_parcel.add_data_prefix(IPv4Network("50.0.0.0/32")) + + # Create Prefix parcel and add prefixes + prefix_list_parcel = PrefixListParcel(parcel_name="PrefixListExample") + prefix_list_parcel.add_prefix(IPv4Network("10.0.0.0/16")) + prefix_list_parcel.add_prefix(IPv4Network("50.0.0.0/32")) + + # Create IPv6 data prefix parcel and add IPv6 prefixes + ipv6_data_prefix = IPv6DataPrefixParcel(parcel_name="IPv6DataPrefixExample") + ipv6_data_prefix.add_prefix(IPv6Network("2000:0:0:0::/128")) + ipv6_data_prefix.add_prefix(IPv6Network("2001:0:0:0::/128")) + ipv6_data_prefix.add_prefix(IPv6Network("2002:0:0:0::/128")) + + # Create IPv6 prefix parcel and add IPv6 prefixes + ipv6_prefix_list = IPv6PrefixListParcel(parcel_name="IPv6PrefixListExample") + ipv6_prefix_list.add_prefix(IPv6Network("2000:0:0:0::/64")) + ipv6_prefix_list.add_prefix(IPv6Network("2001:0:0:0::/64")) + ipv6_prefix_list.add_prefix(IPv6Network("2002:0:0:0::/64")) + + # Create Application family parcel and add application families + application_list_parcel = ApplicationListParcel(parcel_name="AppListExample") + application_list_parcel.add_application_family("app-fam-2") + application_list_parcel.add_application_family("sugarcrm") + + # Create Preferred color parcel and add preferred colors + preferred_group_color = PreferredColorGroupParcel(parcel_name="PreferredColorGroupParcelExmaple") + preferred_group_color.add_primary( + color_preference=[TLOCColorEnum.BIZ_INTERNET, TLOCColorEnum.MPLS], + path_preference=PathPreferenceEnum.DIRECT_PATH, + ) + preferred_group_color.add_secondary( + color_preference=[TLOCColorEnum.BRONZE, TLOCColorEnum.SILVER], path_preference=PathPreferenceEnum.DIRECT_PATH + ) + preferred_group_color.add_tertiary( + color_preference=[TLOCColorEnum.METRO_ETHERNET], path_preference=PathPreferenceEnum.MULTI_HOP_PATH + ) + + # Create Policier parcel and add policiers + policier = PolicierParcel(parcel_name="PolicierParcelExmaple") + policier.add_entry(burst=17000, exceed=PolicerExceedActionEnum.DROP, rate=1000) + + # Create Fowarding Class parcel and add fowarding classes + fowarding_class = FowardingClassParcel(parcel_name="FowardingClassParcelExmaple") + fowarding_class.add_queue(4) + + # Create Tloc Parcel and add tlocs + tloc_list = TlocParcel(parcel_name="TlocParcelExample") + tloc_list.add_entry( + tloc=IPv4Address("40.0.0.0"), color=TLOCColorEnum.PRIVATE3, encapsulation=EncapEnum.GRE, preference="1000" + ) + tloc_list.add_entry( + tloc=IPv4Address("50.0.0.0"), color=TLOCColorEnum.CUSTOM1, encapsulation=EncapEnum.GRE, preference="10000" + ) + + # Create Standard Community Parcel and add standard communities + standard_community = StandardCommunityParcel(parcel_name="StandardCommunityParcelExample") + standard_community.add_community(WellKnownBGPCommunitiesEnum.INTERNET) + standard_community.add_community(WellKnownBGPCommunitiesEnum.LOCAL_AS) + standard_community.add_community(WellKnownBGPCommunitiesEnum.NO_ADVERTISE) + + # Create Expanded Community Parcel and add expanded communities + expanded_community = ExpandedCommunityParcel(parcel_name="ExpandedCommunityParcel") + expanded_community.add_community("CommunityList1") + expanded_community.add_community("CommunityList2") + expanded_community.add_community("CommunityList3") + + # Create App Probe Parcel and add app probes + app_probe = AppProbeParcel(parcel_name="AppProbeParcelExample") + app_probe.add_fowarding_class("FowardingClassParcelExmaple") + app_probe.add_map(color=TLOCColorEnum.CUSTOM1, dscp=33) + app_probe.add_map(color=TLOCColorEnum.BLUE, dscp=40) + app_probe.add_map(color=TLOCColorEnum.PUBLIC_INTERNET, dscp=43) + + items.append(fqdn) + items.append(local_domain) + items.append(ips_signature) + items.append(url_allowed) + items.append(url_blocked) + items.append(security_port) + items.append(geolocation) + items.append(security_zone) + items.append(security_application_list) + items.append(security_data_prefix_parcel) + items.append(protocol_list) + items.append(color_parcel) + items.append(data_prefix_parcel) + items.append(ipv6_data_prefix) + items.append(application_list_parcel) + items.append(prefix_list_parcel) + items.append(ipv6_prefix_list) + items.append(preferred_group_color) + items.append(policier) + items.append(fowarding_class) + items.append(tloc_list) + items.append(standard_community) + items.append(expanded_community) + items.append(app_probe) + + for item in items: + print(item.model_dump_json(by_alias=True, indent=4)) + + for item in items: + items_ids.append((api.create(profile_id, item), item.__class__)) + + _id, _ = items_ids[-1] + + sla = SLAClassParcel(parcel_name="SLAClassParcelExample") + sla.add_entry(app_probe_class_id=_id.id, jitter=20, latency=50, loss=100) + sla.add_fallback( + criteria=SLAClassCriteriaEnum.JITTER_LATENCY_LOSS, latency_variance=10, jitter_variance=10, loss_variance=10 + ) + + items_ids.append((api.create(profile_id, sla), sla.__class__)) + + input("Press enter to delete...") + + for _id, item_type in reversed(items_ids): + api.delete(profile_id, item_type, _id.id) + + +def retrive_groups_of_interest(profile_id: UUID, api: PolicyObjectFeatureProfileAPI): + print(api.get(profile_id, ApplicationListParcel)) # Get all Application List Parcels + + +def run_demo(args: CmdArguments): + """ + Runs a demo of the Catalyst WAN API. + + Args: + args (CmdArguments): The command line arguments. + + Returns: + None: This function does not return any additional values. + """ + from catalystwan.session import create_manager_session + + with create_manager_session( + url=args.url, port=args.port, username=args.user, password=args.password, logger=logger + ) as session: + api = PolicyObjectFeatureProfileAPI(session) + profile_id = ( + ConfigurationFeatureProfile(session) + .get_sdwan_feature_profiles() + .filter(profile_name=PROFILE_NAME) + .single_or_default() + ).profile_id + configure_groups_of_interest(profile_id, api) + retrive_groups_of_interest(profile_id, api) + + +def load_arguments() -> CmdArguments: + """ + Load the command line arguments for the script. + + Returns: + CmdArguments: The command line arguments. + """ + url = sys.argv[1] + port = sys.argv[2] + user = sys.argv[3] + password = sys.argv[4] + return CmdArguments(url, int(port), user, password) + + +if __name__ == "__main__": + arguments = load_arguments() + run_demo(arguments) diff --git a/examples/policies_configuration_guide.py b/examples/policies_configuration_guide.py index a99c1e327..3ec8dea33 100644 --- a/examples/policies_configuration_guide.py +++ b/examples/policies_configuration_guide.py @@ -25,10 +25,9 @@ from uuid import UUID from pydantic import ValidationError -from requests import RequestException from catalystwan.api.policy_api import PolicyAPI -from catalystwan.exceptions import ManagerError +from catalystwan.exceptions import CatalystwanException from catalystwan.models.common import TLOCColorEnum, WellKnownBGPCommunitiesEnum from catalystwan.models.policy import ( AppList, @@ -443,7 +442,7 @@ def run_demo(args: CmdArguments): ConfigItem(CentralizedPolicy, centralized_policy.policy_name, centralized_policy_id) ) - except (ManagerError, ValidationError, RequestException) as e: + except (CatalystwanException, ValidationError) as e: logger.exception(e) """Cleanup""" diff --git a/examples/policy_forwarding_qos.py b/examples/policy_forwarding_qos.py index 6661f54f8..ca6023495 100644 --- a/examples/policy_forwarding_qos.py +++ b/examples/policy_forwarding_qos.py @@ -38,7 +38,7 @@ class CmdArguments: def run_demo(args: CmdArguments): - from catalystwan.exceptions import ManagerError + from catalystwan.exceptions import CatalystwanException from catalystwan.session import create_manager_session with create_manager_session(url=args.url, port=args.port, username=args.user, password=args.password) as session: @@ -210,7 +210,7 @@ def run_demo(args: CmdArguments): device_template = DeviceTemplate.get(args.device_template, session) device_template.policy_id = str(pol_dict["My-Localized-Policy"]) session.api.templates.edit(device_template) - except ManagerError: + except CatalystwanException: logger.warning("Failed to attach My-Localized-Policy to Device Template") """ V. Define Centralized Traffic Data QoS Policy to Classify Traffic into Proper Queue @@ -282,7 +282,7 @@ def run_demo(args: CmdArguments): try: policy_activate_task = api.centralized.activate(pol_dict["My-Centralized-Policy"]) policy_activate_task.wait_for_completed() - except ManagerError: + except CatalystwanException: logger.warning("My-Centralized-Policy activation failed! are vSmarts in Manager mode?") """End of procedure, below is user prompt to check created policies and delete everything afterwards"""