Skip to content

Commit

Permalink
Merge pull request #162 from cisco-en-programmability/develop
Browse files Browse the repository at this point in the history
Develop v6.13.2
  • Loading branch information
fmunozmiranda authored Apr 3, 2024
2 parents e3b0c1c + 73e92a2 commit 234fb71
Show file tree
Hide file tree
Showing 25 changed files with 386 additions and 102 deletions.
9 changes: 9 additions & 0 deletions changelogs/changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -849,3 +849,12 @@ releases:
- Added attributes 'dnac_api_task_timeout' and 'dnac_task_poll_interval' in intent and workflow_manager modules.
- inventory_workflow_manager - Added attributes 'add_user_defined_field', 'update_interface_details', 'export_device_list' and 'admin_status'
- inventory_workflow_manager - Removed attributes 'provision_wireless_device', 'reprovision_wired_device'
6.13.2:
release_date: "2024-04-03"
changes:
release_summary: Enhancements in discovery, site, swim and inventory workflow manager modules.
minor_changes:
- Added the op_modifies=True when calling SDK APIs in the workflow manager modules.
- Added a method to validate IP addresses.
- Fixed a minor issue in the site workflow manager module.
- Updating galaxy.yml ansible.utils dependencies.
4 changes: 2 additions & 2 deletions galaxy.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
namespace: cisco
name: dnac
version: 6.13.1
version: 6.13.2
readme: README.md
authors:
- Rafael Campos <rcampos@altus.cr>
Expand All @@ -27,7 +27,7 @@ tags:
- networking
- sdn
dependencies:
ansible.utils: ">=2.0.0,<4.0"
ansible.utils: ">=2.0.0,<5.0"
repository: https://github.com/cisco-en-programmability/dnacenter-ansible
documentation: https://cisco-en-programmability.github.io/dnacenter-ansible/
homepage: https://github.com/cisco-en-programmability/dnacenter-ansible
Expand Down
4 changes: 2 additions & 2 deletions playbooks/PnP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
template_name: "Ansible_PNP_Switch"
image_name: cat9k_iosxe_npe.17.03.07.SPA.bin
project_name: Onboarding Configuration
template_details:
template_params:
hostname: SJC-Switch-1
interface: TwoGigabitEthernet1/0/2
device_info:
Expand Down Expand Up @@ -108,4 +108,4 @@
- device_info:
- serial_number: QD2425L8M7 #Will get deleted
- serial_number: FTC2320E0HA #Doesn't exist in the inventory
- serial_number: FKC2310E0HB #Doesn't exist in the inventory
- serial_number: FKC2310E0HB #Doesn't exist in the inventory
2 changes: 1 addition & 1 deletion playbooks/PnP_Workflow_Manager_Playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
template_name: "Ansible_PNP_Switch"
image_name: cat9k_iosxe_npe.17.03.07.SPA.bin
project_name: Onboarding Configuration
template_details:
template_params:
hostname: SJC-Switch-1
interface: TwoGigabitEthernet1/0/2
device_info:
Expand Down
10 changes: 5 additions & 5 deletions playbooks/device_provision_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@
dnac_port: "{{ dnac_port }}"
dnac_version: "{{ dnac_version }}"
dnac_debug: "{{ dnac_debug }}"

tasks:
- name: Provision a wired device to a site
cisco.dnac.workflow_manager:
cisco.dnac.provision_workflow_manager:
<<: *dnac_login
dnac_log: True
state: merged
config_verify: True
config:
- site_name_hierarchy: Global/USA/San Francisco/BGL_18
management_ip_address: 204.1.1.1
management_ip_address: 204.1.2.2


- name: Unprovision a wired device from a site
cisco.dnac.workflow_manager:
cisco.dnac.provision_workflow_manager:
<<: *dnac_login
dnac_log: True
state: deleted
config:
- management_ip_address: 204.1.1.1
- management_ip_address: 204.1.2.2
14 changes: 14 additions & 0 deletions playbooks/template_workflow_manager.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
dnac_verify: "{{ dnac_verify }}"
dnac_debug: "{{ dnac_debug }}"
dnac_log: true
dnac_log_level: "{{ dnac_debug }}"
dnac_log_append: true
dnac_log_file_path: "{{ dnac_log_file_path }}"
validate_response_schema: false
state: "merged"
config_verify: true
#ignore_errors: true #Enable this to continue execution even the task fails
Expand All @@ -28,6 +32,16 @@
software_variant: "{{ item.variant }}"
device_types:
- product_family: "{{ item.family }}"
export:
project:
- Ansible_project
- Sample Velocity Templates
template:
- project_name: Onboarding Configuration
template_name: AP_Onboarding
import:
project: "{{ item.import_project }}"
# template: "{{ item.import_template }}"
register: template_result
with_items: '{{ template_details }}'
tags:
Expand Down
25 changes: 25 additions & 0 deletions plugins/module_utils/dnac.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
# import datetime
import inspect
import re
import socket


class DnacBase():
Expand Down Expand Up @@ -485,6 +486,30 @@ def update_site_type_key(self, config):

return new_config

def is_valid_ipv4(self, ip_address):
"""
Validates an IPv4 address.
Parameters:
ip_address - String denoting the IPv4 address passed.
Returns:
bool - Returns true if the passed IP address value is correct or it returns
false if it is incorrect
"""

try:
socket.inet_aton(ip_address)
octets = ip_address.split('.')
if len(octets) != 4:
return False
for octet in octets:
if not 0 <= int(octet) <= 255:
return False
return True
except socket.error:
return False


def is_list_complex(x):
return isinstance(x[0], dict) or isinstance(x[0], list)
Expand Down
5 changes: 5 additions & 0 deletions plugins/modules/device_credential_intent.py
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,7 @@ def get_site_id(self, site_name):
response = self.dnac._exec(
family="sites",
function='get_site',
op_modifies=True,
params={"name": site_name},
)
self.log("Received API response from 'get_site': {0}".format(response), "DEBUG")
Expand Down Expand Up @@ -2209,6 +2210,7 @@ def create_device_credentials(self):
response = self.dnac._exec(
family="discovery",
function='create_global_credentials_v2',
op_modifies=True,
params=credential_params,
)
self.log("Received API response from 'create_global_credentials_v2': {0}"
Expand Down Expand Up @@ -2273,6 +2275,7 @@ def update_device_credentials(self):
response = self.dnac._exec(
family="discovery",
function='update_global_credentials_v2',
op_modifies=True,
params=credential_params,
)
self.log("Received API response for 'update_global_credentials_v2': {0}"
Expand Down Expand Up @@ -2328,6 +2331,7 @@ def assign_credentials_to_site(self):
response = self.dnac._exec(
family="network_settings",
function='assign_device_credential_to_site_v2',
op_modifies=True,
params=credential_params,
)
self.log("Received API response for 'assign_device_credential_to_site_v2': {0}"
Expand Down Expand Up @@ -2414,6 +2418,7 @@ def delete_device_credential(self, config):
response = self.dnac._exec(
family="discovery",
function="delete_global_credential_v2",
op_modifies=True,
params={"id": _id},
)
self.log("Received API response for 'delete_global_credential_v2': {0}"
Expand Down
5 changes: 5 additions & 0 deletions plugins/modules/device_credential_workflow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,7 @@ def get_site_id(self, site_name):
response = self.dnac._exec(
family="sites",
function='get_site',
op_modifies=True,
params={"name": site_name},
)
self.log("Received API response from 'get_site': {0}".format(response), "DEBUG")
Expand Down Expand Up @@ -2208,6 +2209,7 @@ def create_device_credentials(self):
response = self.dnac._exec(
family="discovery",
function='create_global_credentials_v2',
op_modifies=True,
params=credential_params,
)
self.log("Received API response from 'create_global_credentials_v2': {0}"
Expand Down Expand Up @@ -2272,6 +2274,7 @@ def update_device_credentials(self):
response = self.dnac._exec(
family="discovery",
function='update_global_credentials_v2',
op_modifies=True,
params=credential_params,
)
self.log("Received API response for 'update_global_credentials_v2': {0}"
Expand Down Expand Up @@ -2327,6 +2330,7 @@ def assign_credentials_to_site(self):
response = self.dnac._exec(
family="network_settings",
function='assign_device_credential_to_site_v2',
op_modifies=True,
params=credential_params,
)
self.log("Received API response for 'assign_device_credential_to_site_v2': {0}"
Expand Down Expand Up @@ -2413,6 +2417,7 @@ def delete_device_credential(self, config):
response = self.dnac._exec(
family="discovery",
function="delete_global_credential_v2",
op_modifies=True,
params={"id": _id},
)
self.log("Received API response for 'delete_global_credential_v2': {0}"
Expand Down
51 changes: 48 additions & 3 deletions plugins/modules/discovery_intent.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,43 @@ def validate_input(self, state=None):
self.status = "success"
return self

def validate_ip4_address_list(self):
"""
Validates each ip adress paased in the IP_address_list passed by the user before preprocessing it
"""

ip_address_list = self.validated_config[0].get('ip_address_list')
for ip in ip_address_list:
if '/' in ip:
ip = ip.split("/")[0]
if '-' in ip:
if len(ip.split('-')) == 2:
ip1, ip2 = ip.split('-')
if self.is_valid_ipv4(ip1) is False:
msg = "IP address {0} is not valid".format(ip1)
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)
if self.is_valid_ipv4(ip2) is False:
msg = "IP address {0} is not valid".format(ip2)
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)
ip1_parts = list(map(int, ip1.split('.')))
ip2_parts = list(map(int, ip2.split('.')))
for part in range(4):
if ip1_parts[part] > ip2_parts[part]:
msg = "Incorrect range passed: {0}. Please pass correct IP address range".format(ip)
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)
else:
msg = "Provided range '{0}' is incorrect. IP address range should have only upper and lower limit values".format(ip)
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)
if self.is_valid_ipv4(ip) is False and '-' not in ip:
msg = "IP address {0} is not valid".format(ip)
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)
self.log("All the IP addresses passed are correct", "INFO")

def get_creds_ids_list(self):
"""
Retrieve the list of credentials IDs associated with class instance.
Expand Down Expand Up @@ -934,6 +971,7 @@ def get_ccc_global_credentials_v2_info(self):
family="discovery",
function='get_all_global_credentials_v2',
params=self.validated_config[0].get('headers'),
op_modifies=True
)
response = response.get('response')
self.log("The Global credentials response from 'get all global credentials v2' API is {0}".format(str(response)), "DEBUG")
Expand Down Expand Up @@ -1288,6 +1326,7 @@ def get_task_status(self, task_id=None):
family="task",
function='get_task_by_id',
params=params,
op_modifies=True,
)
response = response.response
self.log("Task status for the task id {0} is {1}".format(str(task_id), str(response)), "INFO")
Expand Down Expand Up @@ -1336,7 +1375,8 @@ def lookup_discovery_by_range_via_name(self):
response_part = self.dnac_apply['exec'](
family="discovery",
function='get_discoveries_by_range',
params=params
params=params,
op_modifies=True,
)
response["response"].extend(response_part["response"])
else:
Expand All @@ -1349,7 +1389,8 @@ def lookup_discovery_by_range_via_name(self):
response = self.dnac_apply['exec'](
family="discovery",
function='get_discoveries_by_range',
params=params
params=params,
op_modifies=True,
)
self.log("Response of the get discoveries via range API is {0}".format(str(response)), "DEBUG")

Expand Down Expand Up @@ -1425,6 +1466,7 @@ def get_discovery_device_info(self, discovery_id=None, task_id=None):
family="discovery",
function='get_discovered_network_devices_by_discovery_id',
params=params,
op_modifies=True,
)
devices = response.response

Expand Down Expand Up @@ -1495,6 +1537,7 @@ def delete_exist_discovery(self, params):
family="discovery",
function="delete_discovery_by_id",
params=params,
op_modifies=True,
)

self.log("Response collected from API 'delete_discovery_by_id': {0}".format(str(response)), "DEBUG")
Expand All @@ -1513,6 +1556,7 @@ def get_diff_merged(self):
- self: The instance of the class with updated attributes.
"""

self.validate_ip4_address_list()
devices_list_info = self.get_devices_list_info()
ip_address_list = self.preprocess_device_discovery(devices_list_info)
exist_discovery = self.get_exist_discovery()
Expand Down Expand Up @@ -1611,7 +1655,8 @@ def verify_diff_merged(self, config):
response = self.dnac_apply['exec'](
family="discovery",
function='get_discovery_by_id',
params=params
params=params,
op_modifies=True,
)
discovery_name = config.get('discovery_name')
if response:
Expand Down
Loading

0 comments on commit 234fb71

Please sign in to comment.