Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(cv_facts_v3): raise errors when svcaccount/user is not authorized #677

Merged
merged 13 commits into from
Nov 20, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,12 @@ def module_action(self, change: dict, name: str = None, state: str = "show", cha
MODULE_LOGGER.debug("Successfully deleted: %s", change_id)
changed = True
except Exception as e:
self.__ansible.fail_json(msg="{0}".format(e))
if "Forbidden" in str(e):
message = "Failed to delete Change Control. User is unauthorized!"
else:
message = str(e)
logging.error(message)
self.__ansible.fail_json(msg="{0}".format(message))

return changed, {'remove': []}, warnings

Expand Down Expand Up @@ -704,7 +709,12 @@ def module_action(self, change: dict, name: str = None, state: str = "show", cha
data = cc_structure['key']

except Exception as e:
self.__ansible.fail_json(msg="{0}".format(e))
if "Forbidden" in str(e):
message = "Failed to create Change Control. User is unauthorized!"
else:
message = str(e)
logging.error(message)
self.__ansible.fail_json(msg="{0}".format(message))

elif state in ['approve', 'unapprove', 'execute', 'schedule', 'approve_and_execute', 'schedule_and_approve'] and self.__check_mode is False:
MODULE_LOGGER.debug("Change control state: %s", state)
Expand Down Expand Up @@ -764,9 +774,14 @@ def module_action(self, change: dict, name: str = None, state: str = "show", cha
e = "Change control {0} id not found".format(cc_id)
self.__ansible.fail_json(msg="{0}".format(e))
return changed, {"approve": change_id}, warnings
except CvpRequestError:
except CvpRequestError as e:
# Skip this - covers the case where an approved CC is approved again
pass
if "Forbidden" in str(e):
message = "Failed to approve Change Control. User is unauthorized!"
self.__ansible.fail_json(msg="{0}".format(message))
logging.error(str(message))
else:
pass
except Exception as e:
self.__ansible.fail_json(msg="{0}".format(e))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from ansible_collections.arista.cvp.plugins.module_utils.tools_schema import validate_json_schema
from ansible_collections.arista.cvp.plugins.module_utils.resources.exceptions import AnsibleCVPApiError, AnsibleCVPNotFoundError, CVPRessource
try:
from cvprac.cvp_client_errors import CvpClientError, CvpApiError
from cvprac.cvp_client_errors import CvpClientError, CvpApiError, CvpRequestError
HAS_CVPRAC = True
except ImportError:
HAS_CVPRAC = False
Expand Down Expand Up @@ -356,6 +356,13 @@ def __configlet_add(self, container: dict, configlets: list, save_topology: bool
container=container,
create_task=save_topology
)
except CvpRequestError as e:
if "Forbidden" in str(e):
message = "Error configuring configlets. User is unauthorized!"
else:
message = "Error configuring configlets " + str(configlets) + " to container " + str(container) + ". Exception: " + str(e)
MODULE_LOGGER.error(message)
self.__ansible.fail_json(msg=message)
except CvpApiError as e:
message = "Error configuring configlets " + str(configlets) + " to container " + str(container) + ". Exception: " + str(e)
MODULE_LOGGER.error(message)
Expand Down Expand Up @@ -425,6 +432,13 @@ def __configlet_del(self, container: dict, configlets: list, save_topology: bool
container=container,
create_task=save_topology
)
except CvpRequestError as e:
if "Forbidden" in str(e):
message = "Error removing configlets. User is unauthorized!"
else:
message = "Error removing configlets " + str(configlets) + " to container " + str(container) + ". Exception: " + str(e)
MODULE_LOGGER.error(message)
self.__ansible.fail_json(msg=message)
except CvpApiError as e:
message = "Error removing configlets " + str(configlets) + " from container " + str(container) + ". Exception: " + str(e)
MODULE_LOGGER.error(message)
Expand Down Expand Up @@ -507,6 +521,13 @@ def __image_bundle_add(self, container: dict, image_bundle: str):
container[Api.generic.NAME],
'container'
)
except CvpRequestError as e:
if "Forbidden" in str(e):
message = "Error applying bundle to container. User is unauthorized!"
else:
message = "Error applying bundle to container " + str(container[Api.generic.NAME]) + ". Exception: " + str(e)
MODULE_LOGGER.error(message)
self.__ansible.fail_json(msg=message)
except CvpApiError as catch_error:
MODULE_LOGGER.error('Error applying bundle to device: %s', str(catch_error))
self.__ansible.fail_json(msg='Error applying bundle to container' + container[Api.generic.NAME] + ': ' + catch_error)
Expand Down Expand Up @@ -567,6 +588,13 @@ def __image_bundle_del(self, container: dict):
container[Api.generic.NAME],
'container'
)
except CvpRequestError as e:
if "Forbidden" in str(e):
message = "Error removing bundle from container. User is unauthorized!"
else:
message = "Error removing bundle from container " + str(container[Api.generic.NAME]) + ". Exception: " + str(e)
MODULE_LOGGER.error(message)
self.__ansible.fail_json(msg=message)
except CvpApiError as catch_error:
MODULE_LOGGER.error('Error removing bundle from container: %s', str(catch_error))
self.__ansible.fail_json(msg='Error removing bundle from container: ' + container[Api.generic.NAME] + ': ' + catch_error)
Expand Down Expand Up @@ -839,6 +867,13 @@ def create_container(self, container: str, parent: str):
try:
resp = self.__cvp_client.api.add_container(
container_name=container, parent_key=parent_id, parent_name=parent)
except CvpRequestError as e:
if "Forbidden" in str(e):
message = "Error creating container. User is unauthorized!"
else:
message = "Error creating container " + str(container) + ". Exception: " + str(e)
MODULE_LOGGER.error(message)
self.__ansible.fail_json(msg=message)
except CvpApiError as e:
# Add Ansible error management
message = "Error creating container " + str(container) + " on CV. Exception: " + str(e)
Expand Down Expand Up @@ -915,6 +950,13 @@ def delete_container(self, container: str, parent: str):
try:
resp = self.__cvp_client.api.delete_container(
container_name=container, container_key=container_id, parent_key=parent_id, parent_name=parent)
except CvpRequestError as e:
if "Forbidden" in str(e):
message = "Error deleting container. User is unauthorized!"
else:
message = "Error deleting container " + str(container) + ". Exception: " + str(e)
MODULE_LOGGER.error(message)
self.__ansible.fail_json(msg=message)
except CvpApiError as e:
# Add Ansible error management
message = "Error deleting container " + str(container) + " on CV. Exception: " + str(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,10 @@ def move_device(self, user_inventory: DeviceInventory):
error_message = f"Error to move device {device.fqdn} to container {device.container}"
MODULE_LOGGER.error(error_message)
self.__ansible.fail_json(msg=error_message)
except CvpRequestError:
error_message = f"Move device {device.fqdn} to container {device.container} failed. User is unauthorized!"
MODULE_LOGGER.error(error_message)
self.__ansible.fail_json(msg=error_message)
else:
if resp and resp['data']['status'] == 'success':
result_data.changed = True
Expand Down Expand Up @@ -1696,6 +1700,13 @@ def apply_bundle(self, user_inventory: DeviceInventory):
self.__ansible.fail_json(
msg=f"Error applying bundle to device {device.fqdn}: {str(catch_error)}"
)
except CvpRequestError as catch_error:
MODULE_LOGGER.error(
"Error applying bundle to device: %s", str(catch_error)
)
self.__ansible.fail_json(
msg=f"Error applying bundle to device {device.fqdn}: {str(catch_error)}"
)
else:
if resp and resp["data"]["status"] == "success":
result_data.changed = True
Expand Down Expand Up @@ -1924,6 +1935,10 @@ def apply_configlets(self, user_inventory: DeviceInventory):
self.__ansible.fail_json(
msg="Error applying configlets to device"
)
except CvpRequestError:
message = "Failed to apply configlets to device. User is unauthorized!"
MODULE_LOGGER.error(message)
self.__ansible.fail_json(msg=message)
else:
if resp["data"]["status"] == "success":
result_data.changed = True
Expand Down Expand Up @@ -2014,6 +2029,11 @@ def detach_configlets(self, user_inventory: DeviceInventory):
self.__ansible.fail_json(
msg=f"Error detaching configlets from device {device.fqdn}: {catch_error}"
)
except CvpRequestError:
MODULE_LOGGER.error("Error detaching configlets to device. User is unauthorized!")
self.__ansible.fail_json(
msg="Error detaching configlets to device. User is unauthorized!"
)
else:
if resp["data"]["status"] == "success":
result_data.changed = True
Expand Down Expand Up @@ -2213,6 +2233,10 @@ def delete_device(self, user_inventory: DeviceInventory):
self.__ansible.fail_json(
msg="Error removing device from provisioning"
)
except CvpRequestError:
message = "Failed to remove device from provisioning. User is unauthorized!"
MODULE_LOGGER.error(message)
self.__ansible.fail_json(msg=message)
else:
if resp["result"] == "success":
result_data.changed = True
Expand Down Expand Up @@ -2251,8 +2275,11 @@ def decommission_device(self, user_inventory: DeviceInventory):
except CvpApiError:
MODULE_LOGGER.error("Error decommissioning device")
self.__ansible.fail_json(msg="Error decommissioning device")
except CvpRequestError:
request_err_msg = f"Device with {device_id} does not exist or is not registered to decommission"
except CvpRequestError as e:
if "403 Forbidden" in e.msg:
request_err_msg = f"Failed to decommission device {device_id}. User is unauthorized!"
else:
request_err_msg = f"Device with {device_id} does not exist or is not registered to decommission"
MODULE_LOGGER.error(request_err_msg)
self.__ansible.fail_json(msg=request_err_msg)
else:
Expand Down Expand Up @@ -2315,6 +2342,10 @@ def reset_device(self, user_inventory: DeviceInventory):
except CvpApiError:
MODULE_LOGGER.error("Error resetting device")
self.__ansible.fail_json(msg="Error resetting device")
except CvpRequestError:
message = "Failed to reset device. Users is unauthorized!"
MODULE_LOGGER.error(message)
self.__ansible.fail_json(msg=message)
else:
if resp and resp["data"]["status"] == "success":
result_data.changed = True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ def __fact_devices(self, filter: str = '.*', verbose: str = 'short'):
cv_devices = self.__cv_client.api.get_inventory()
except CvpApiError as error_msg:
MODULE_LOGGER.error('Error when collecting devices facts: %s', str(error_msg))
raise error_msg
MODULE_LOGGER.info('Extract device data using filter %s', str(filter))
facts_builder = CvFactResource()
for device in cv_devices:
Expand All @@ -614,6 +615,7 @@ def __fact_containers(self, filter: str = '.*'):
cv_containers = self.__cv_client.api.get_containers()
except CvpApiError as error_msg:
MODULE_LOGGER.error('Error when collecting containers facts: %s', str(error_msg))
raise error_msg
facts_builder = CvFactResource()
for container in cv_containers['data']:
if container[Api.generic.NAME] != 'Tenant':
Expand All @@ -637,7 +639,11 @@ def __fact_configlets(self, filter: str = '.*', configlets_per_call: int = 10):
configlets_per_call : int, optional
Number of configlets to retrieve per API call, by default 10
"""
max_range_calc = self.__cv_client.api.get_configlets(start=0, end=1)['total'] + 1
try:
max_range_calc = self.__cv_client.api.get_configlets(start=0, end=1)['total'] + 1
except CvpApiError as error_msg:
MODULE_LOGGER.error('Error when collecting configlets facts: %s', str(error_msg))
raise error_msg
futures_list = []
results = []
with ThreadPoolExecutor(max_workers=self._max_worker) as executor:
Expand Down Expand Up @@ -678,6 +684,7 @@ def __fact_images(self, filter: str = '.*'):
cv_images = self.__cv_client.api.get_images()
except CvpApiError as error_msg:
MODULE_LOGGER.error('Error when collecting images facts: %s', str(error_msg))
raise error_msg

facts_builder = CvFactResource()
for image in cv_images['data']:
Expand Down Expand Up @@ -710,18 +717,21 @@ def __fact_tasks(self, filter: str = '.*', verbose: str = 'short'):
cv_tasks = cv_tasks['data']
except CvpApiError as error_msg:
MODULE_LOGGER.error('Error when collecting task facts: %s', str(error_msg))
raise error_msg
elif isinstance(filter, str):
# filter by task status
try:
cv_tasks = self.__cv_client.api.get_tasks_by_status(filter)
except CvpApiError as error_msg:
MODULE_LOGGER.error('Error when collecting %s task facts: %s', filter, str(error_msg))
raise error_msg
elif isinstance(filter, int):
# filter by task_id
try:
cv_tasks = self.__cv_client.api.get_task_by_id(filter)
except CvpApiError as error_msg:
MODULE_LOGGER.error('Error when collecting %s task facts: %s', filter, str(error_msg))
raise error_msg

for task in cv_tasks:
MODULE_LOGGER.debug('Got following information for task: %s', str(task))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,11 @@ def tasker(self, tags: list, mode: string, auto_create: bool = True):
workspace_id = workspace_name_id

workspace_name = workspace_name_id
self.__cv_client.api.workspace_config(workspace_id, workspace_name)
try:
self.__cv_client.api.workspace_config(workspace_id, workspace_name)
except CvpRequestError:
MODULE_LOGGER.info('Workspace creation failed. User is unauthorized!')
self.__ansible.fail_json(msg='Workspace creation failed. User is unauthorized!')

# create tags and assign tags
for per_device in tags:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,15 @@ def tasker(self, taskIds_list: list, state: str = 'executed'):
api_result = CvApiResult(action_name='task_' + str(task_id))
if self.is_actionable(task_data=self.__get_task_data(task_id)):
if self.__ansible.check_mode is False:
self.__cv_client.api.add_note_to_task(task_id, "Executed by Ansible")
try:
self.__cv_client.api.add_note_to_task(task_id, "Executed by Ansible")
except CvpRequestError as e:
if "Forbidden" in str(e):
message = "Error while adding note and executing task. User is unauthorized!"
else:
message = "Error while adding note to task: {0}".format(str(e))
logging.error(message)
self.__ansible.fail_json(msg=message)
if state == "executed":
api_result.add_entry(self.execute_task(task_id))
api_result.changed = True
Expand Down
7 changes: 5 additions & 2 deletions ansible_collections/arista/cvp/plugins/modules/cv_facts_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,11 @@ def main():

# Instantiate ansible results
facts_collector = CvFactsTools(cv_connection=cv_client)
facts = facts_collector.facts(scope=ansible_module.params['facts'], regex_filter=ansible_module.params['regexp_filter'],
verbose=ansible_module.params['verbose'])
try:
facts = facts_collector.facts(scope=ansible_module.params['facts'], regex_filter=ansible_module.params['regexp_filter'],
verbose=ansible_module.params['verbose'])
except CvpClientError as e:
ansible_module.fail_json(msg=str(e))
result = dict(changed=False, data=facts, failed=False)

# Implement logic
Expand Down
Loading