Skip to content

Commit

Permalink
Merge remote-tracking branch 'integration/main' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
rukapse committed Dec 17, 2024
2 parents 446a197 + 8573416 commit 311bb7e
Show file tree
Hide file tree
Showing 21 changed files with 791 additions and 118 deletions.
21 changes: 21 additions & 0 deletions changelogs/changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1119,3 +1119,24 @@ releases:
- Changes in site_workflow_manager module
- Changes in template_workflow_manager
- Unit test modules added for pnp_workflow_manager module
6.26.0:
release_date: "2024-12-10"
changes:
release_summary: Changes in workflow manager modules
minor_changes:
- Added sample playbook for Device Configs Backup Module
- Changes in dnac.py file
- Bug fixes in accesspoint_workflow_manager module
- Enhancements in device_configs_backup_workflow_manager module to support unzipped backup file after download
- Changes in inventory_workflow_manager module
- Changes in ise_radius_integration_workflow_manager
- Changes in network_compliance_workflow_manager
- Changes in network_settings_workflow_manager
- Bug fixes in sda_fabric_devices_workflow_manager
- Bug fixes in sda_fabric_transits_workflow_manager
- Enhancements in sda_host_port_onboarding_workflow_manager module
- Changes in swim_workflow_manager module
- sda_fabric_devices_workflow_manager - attribute 'delete_fabric_device' was removed
- sda_host_port_onboarding_workflow_manager - attributes 'port_channels', 'fabric_site_name_hierarchy', 'port_assignments', 'wireless_ssids' were added
- sda_host_port_onboarding_workflow_manager - attributes 'port_channel_details', 'port_assignment_details' were removed
- device_configs_backup_workflow_managerr - attribute 'unzip_backup' was added
2 changes: 1 addition & 1 deletion galaxy.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
namespace: cisco
name: dnac
version: 6.25.1
version: 6.26.0
readme: README.md
authors:
- Rafael Campos <[email protected]>
Expand Down
29 changes: 29 additions & 0 deletions plugins/modules/device_credential_workflow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,35 @@
site_name:
- Global/Vietnam/halong/Hanoi
- name: Delete credentials
cisco.dnac.device_credential_workflow_manager:
dnac_host: "{{ dnac_host }}"
dnac_port: "{{ dnac_port }}"
dnac_username: "{{ dnac_username }}"
dnac_password: "{{ dnac_password }}"
dnac_verify: "{{ dnac_verify }}"
dnac_debug: "{{ dnac_debug }}"
dnac_log: True
state: deleted
config_verify: True
config:
- global_credential_details:
cli_credential:
- description: CLI1
username: cli1
snmp_v2c_read:
- description: SNMPv2c Read1 # use this for deletion
snmp_v2c_write:
- description: SNMPv2c Write1 # use this for deletion
snmp_v3:
- description: snmpV31
https_read:
- description: HTTP Read1
username: HTTP_Read1
https_write:
- description: HTTP Write1
username: HTTP_Write1
"""

RETURN = r"""
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/lan_automation_workflow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,12 @@ def extract_lan_automation(self, config):
msg="IP address: {} does not exist in Catalyst Center. Please provide a valid IP address for "
"'lan_automation -> peer_device_management_ip_address'!".format(peer_device_ip), response=[]
)
self.log("Validate peer device management IP address is not the same as primary device IP", "INFO")
if primary_device_ip == peer_device_ip:
self.module.fail_json(
msg="The primary device management IP address '{}' cannot be the same as the peer device IP "
"address '{}'.".format(primary_device_ip, peer_device_ip), response=[]
)
self.log("Peer device management IP address '{}' is valid.".format(peer_device_ip), "DEBUG")
else:
self.log("Peer device IP not provided. Skipping peer device checks.", "INFO")
Expand Down
5 changes: 5 additions & 0 deletions plugins/modules/pnp_workflow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,11 @@ class instance for further use.
self.result['diff'] = self.validated_config
self.result['changed'] = True
return self
elif len(bulk_params.get("failureList")) > 0:
self.msg = "Unable to import below {0} device(s). ".format(
len(bulk_params.get("failureList")))
self.set_operation_result("failed", False, self.msg, "ERROR",
bulk_params).check_return_status()

self.msg = "Bulk import failed"
self.log(self.msg, "CRITICAL")
Expand Down
244 changes: 189 additions & 55 deletions plugins/modules/provision_workflow_manager.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/modules/sda_fabric_devices_workflow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2523,7 +2523,7 @@ def get_device_params(self, fabric_id, network_id, device_details, config_index)
if not borders_settings:
if not have_border_settings:
self.msg = (
"The parameter 'border_settings' is mandatory when the 'device_roles' has 'BORDER_NODE' "
"The parameter 'borders_settings' is mandatory when the 'device_roles' has 'BORDER_NODE' "
"for the device {ip}.".format(ip=device_ip)
)
self.status = "failed"
Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/sda_fabric_sites_zones_workflow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ def get_want(self, config):

if not site_name:
self.msg = (
"Required parameter 'site_name' is missing. It must be provided in the playbook for fabric site/zone "
"Required parameter 'site_name_hierarchy' is missing. It must be provided in the playbook for fabric site/zone "
"operations in Cisco Catalyst Center."
)
self.set_operation_result("failed", False, self.msg, "ERROR").check_return_status()
Expand Down
88 changes: 43 additions & 45 deletions plugins/modules/swim_workflow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -937,62 +937,60 @@ def get_device_uuids(self, site_name, device_family, device_role, device_series_
for item_dict in item['response']:
site_response_list.append(item_dict)
else:
try:
response = self.dnac._exec(
family="site_design",
function='get_site_assigned_network_devices',
op_modifies=True,
params={"site_id": site_id},
)
self.log("Received API response from 'get_site_assigned_network_devices': {0}".format(str(response)), "DEBUG")
response = response.get('response')
site_names = site_name + ".*"
get_site_names = self.get_site(site_names)
self.log("Fetched site names: {0}".format(str(get_site_names)), "DEBUG")

site_info = {}

for item in get_site_names['response']:
if 'nameHierarchy' in item and 'id' in item:
site_info[item['nameHierarchy']] = item['id']

for site_name, site_id in site_info.items():
try:
response = self.dnac._exec(
family="site_design",
function='get_site_assigned_network_devices',
params={"site_id": site_id},
)
self.log("Received API response from 'get_site_assigned_network_devices': {0}".format(str(response)), "DEBUG")
devices = response.get('response')
if not devices:
self.log("No devices found for site - '{0}'.". format(site_name), "WARNING")
continue

if not response:
self.log("No devices found for site '{0}'.". format(site_name), "WARNING")
for device_id in devices:
device_id_list.append(device_id.get("deviceId"))

except Exception as e:
self.log("Unable to fetch the device(s) associated to the site '{0}' due to '{1}'".format(site_name, str(e)), "WARNING")
return device_uuid_list
except Exception as e:
self.log("Unable to fetch the device(s) associated to the site '{0}' due to '{1}'".format(site_name, str(e)), "WARNING")
return device_uuid_list

for device_id in response:
device_id_list.append(device_id.get("deviceId"))
for device_id in device_id_list:
self.log("Processing device_id: {0}".format(device_id))
try:
device_list_response = self.dnac._exec(
family="devices",
function="get_device_list",
params={"id": device_id},
)

try:
device_params = {}
offset = 0
limit = self.get_device_details_limit()
initial_exec = False
self.log("Received API response from 'get_device_list': {0}".format(str(device_list_response)), "DEBUG")

while True:
if initial_exec:
device_params["limit"] = limit
device_params["offset"] = offset * limit
device_list_response = self.dnac._exec(
family="devices",
function='get_device_list',
params=device_params
)
else:
initial_exec = True
device_list_response = self.dnac._exec(
family="devices",
function='get_device_list',
op_modifies=True
)
offset = offset + 1
self.log("Received API response from 'device_list_response': {0}".format(str(device_list_response)), "DEBUG")
device_response = device_list_response.get('response')
device_response = device_list_response.get("response")
if not device_response:
break
self.log("No device data found for device_id: {0}".format(device_id), "INFO")
continue

for device in device_response:
if device.get("instanceUuid") in device_id_list:
if device_family is None or device.get("family") == device_family:
site_response_list.append(device)

except Exception as e:
self.log("Unable to fetch the device(s) associated to the site '{0}' due to '{1}'".format(site_name, str(e)), "WARNING")
return device_uuid_list
except Exception as e:
self.log("Unable to fetch devices for site '{0}' due to: {1}".format(site_name, str(e)), "WARNING")
return device_uuid_list

self.device_ips = []
for item in site_response_list:
Expand Down Expand Up @@ -1034,7 +1032,7 @@ def get_device_uuids(self, site_name, device_family, device_role, device_series_
offset = offset + 1
device_response = device_list_response.get('response')

if not response or not device_response:
if not device_response:
self.log("Failed to retrieve devices associated with the site '{0}' due to empty API response.".format(site_name), "INFO")
break

Expand Down
10 changes: 4 additions & 6 deletions plugins/modules/template_workflow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -844,8 +844,7 @@
device_details:
description: Details specific to devices where the template will be deployed, including lists of device IPs, hostnames,
serial numbers, or MAC addresses.
type: list
elements: dict
type: dict
suboptions:
device_ips:
description: A list of IP addresses of the devices where the template will be deployed.
Expand Down Expand Up @@ -1078,7 +1077,7 @@
- param_name: "vlan_name"
param_value: "testvlan31"
device_details:
- device_ips: ["10.1.2.1", "10.2.3.4"]
device_ips: ["10.1.2.1", "10.2.3.4"]
- name: Delete the given project or template from the Cisco Catalyst Center
cisco.dnac.template_workflow_manager:
Expand Down Expand Up @@ -1270,8 +1269,7 @@ def validate_input(self):
'param_value': {'type': 'str'},
},
'device_details': {
'type': 'list',
'elements': 'dict',
'type': 'dict',
'device_ips': {'type': 'list', 'elements': 'str'},
'device_hostnames': {'type': 'list', 'elements': 'str'},
'serial_numbers': {'type': 'list', 'elements': 'str'},
Expand Down Expand Up @@ -2420,7 +2418,7 @@ def get_export_template_values(self, export_values):

all_project_details = self.dnac._exec(
family="configuration_templates",
function='get_projects_details'
function='get_projects_details_v2'
)
all_project_details = all_project_details.get("response")
for values in export_values:
Expand Down
26 changes: 17 additions & 9 deletions plugins/modules/user_role_workflow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,7 @@ def __init__(self, module):
self.created_user, self.updated_user, self.no_update_user = [], [], []
self.created_role, self.updated_role, self.no_update_role = [], [], []
self.deleted_user, self.deleted_role = [], []
self.no_deleted_user, self.no_deleted_role = [], []

def validate_input_yml(self, user_role_details):
"""
Expand Down Expand Up @@ -3009,9 +3010,7 @@ def get_diff_deleted(self, config):
self.status = "failed"
return self

self.msg = "Please provide a valid role_name for role deletion"
self.log(self.msg, "ERROR")
self.status = "failed"
self.no_deleted_role.append(self.want.get("role_name"))
return self

if "username" in config or "email" in config:
Expand Down Expand Up @@ -3044,12 +3043,7 @@ def get_diff_deleted(self, config):
else:
user_identifier = self.want.get("email")

self.msg = (
"The specified user '{0}' does not exist in Cisco Catalyst Center. "
"Please provide a valid 'username' or 'email' for user deletion.".format(user_identifier)
)
self.log(self.msg, "ERROR")
self.status = "failed"
self.no_deleted_user.append(self.want.get("username"))
return self

def delete_user(self, user_params):
Expand Down Expand Up @@ -3326,6 +3320,20 @@ def update_user_role_profile_messages(self):
delete_role_msg = "Role(s) '{0}' deleted successfully from the Cisco Catalyst Center.".format("', '".join(self.deleted_role))
result_msg_list.append(delete_role_msg)

if self.no_deleted_user:
no_delete_user_msg = (
"The specified user '{0}' does not exist in Cisco Catalyst Center. "
"Please provide a valid 'username' or 'email' for user deletion.".format("', '".join(self.no_deleted_user))
)
no_update_list.append(no_delete_user_msg)

if self.no_deleted_role:
no_delete_role_msg = (
"The specified role '{0}' does not exist in Cisco Catalyst Center. "
"Please provide a valid 'role_name' for user deletion.".format("', '".join(self.no_deleted_role))
)
no_update_list.append(no_delete_role_msg)

if result_msg_list and no_update_list:
self.result["changed"] = True
self.msg = "{0} {1}".format(" ".join(result_msg_list), " ".join(no_update_list))
Expand Down
2 changes: 2 additions & 0 deletions tests/integration/ccc_template_management/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
testcase: "*"
1 change: 1 addition & 0 deletions tests/integration/ccc_template_management/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dependencies: []
34 changes: 34 additions & 0 deletions tests/integration/ccc_template_management/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
- name: collect ccc test cases
find:
paths: "{{ role_path }}/tests"
patterns: "{{ testcase }}.yml"
connection: local
register: ccc_cases
tags: sanity

- debug:
msg: "CCC Cases: {{ ccc_cases }}"

- set_fact:
test_cases:
files: "{{ ccc_cases.files }}"
tags: sanity

- debug:
msg: "Test Cases: {{ test_cases }}"

- name: set test_items
set_fact:
test_items: "{{ test_cases.files | map(attribute='path') | list }}"
tags: sanity

- debug:
msg: "Test Items: {{ test_items }}"

- name: run test cases (connection=httpapi)
include_tasks: "{{ test_case_to_run }}"
loop: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run
tags: sanity
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[
{
"name": "test_template",
"tags": [],
"author": "admin",
"deviceTypes": [
{
"productFamily": "Switches and Hubs"
}
],
"softwareType": "IOS",
"softwareVariant": "XE",
"templateContent": "hostname cat9k-1\\n",
"templateParams": [],
"rollbackTemplateParams": [],
"composite": false,
"containingTemplates": [],
"language": "VELOCITY",
"promotedTemplateContent": "hostname cat9k-1\\n",
"promotedTemplateParams": [],
"customParamsOrder": false,
"createTime": 1719914895959,
"lastUpdateTime": 1719914895959,
"latestVersionTime": 1719914896486,
"validationErrors": {
"templateErrors": [],
"rollbackTemplateErrors": [],
"templateId": "10a9a332-44f8-419e-8274-45ad74a38e9b",
"templateVersion": null
},
"noOfConflicts": 0,
"projectAssociated": true,
"documentDatabase": false
}
]
Loading

0 comments on commit 311bb7e

Please sign in to comment.