From a0090c7c5228ea09bd5de6543a6c6af51e4bb259 Mon Sep 17 00:00:00 2001 From: Sean Date: Tue, 2 Mar 2021 23:55:03 -0600 Subject: [PATCH] update logic --- .../plugins/module_utils/tower_api.py | 42 ++++++++++++++----- .../plugins/modules/tower_credential.py | 31 +++++--------- .../plugins/modules/tower_inventory.py | 34 ++++----------- .../plugins/modules/tower_job_template.py | 27 ++++-------- .../modules/tower_notification_template.py | 33 ++++----------- .../plugins/modules/tower_project.py | 27 ++++-------- .../modules/tower_workflow_job_template.py | 36 ++++------------ 7 files changed, 80 insertions(+), 150 deletions(-) diff --git a/awx_collection/plugins/module_utils/tower_api.py b/awx_collection/plugins/module_utils/tower_api.py index b419ebac68..ce96e492db 100644 --- a/awx_collection/plugins/module_utils/tower_api.py +++ b/awx_collection/plugins/module_utils/tower_api.py @@ -410,26 +410,46 @@ class TowerAPIModule(TowerModule): else: self.fail_json(msg="Failed to associate item {0}".format(response['json'].get('detail', response['json']))) - def copy_item(self, existing_item, name, item_type='unknown'): + def copy_item(self, existing_item, copy_from_name_or_id, new_item_name, endpoint=None, item_type='unknown', copy_lookup_data={}): - if not existing_item: - self.fail_json(msg="Unable to create copy {0} due to missing endpoint".format(item_type)) - item_url = existing_item['related']['copy'] - response = self.post_endpoint(item_url, **{'data': {'name': name}}) + if existing_item is not None: + self.fail_json(msg="A {0} with the name {1} already exists.".format(item_type, new_item_name)) + + # Lookup existing item to copy from + copy_from_lookup = self.get_one(endpoint, name_or_id=copy_from_name_or_id, **{'data': copy_lookup_data}) + + # Fail if the copy_from_lookup is empty + if copy_from_lookup is None: + self.fail_json(msg="A {0} with the name {1} was not able to be found.".format(item_type, copy_from_name_or_id)) + + # Do checks for copy permisions if warrented + if item_type == 'workflow_job_template': + copy_get_check = self.get_endpoint(copy_from_lookup['related']['copy']) + if copy_get_check['status_code'] in [200]: + if (copy_get_check['json']['can_copy'] and copy_get_check['json']['can_copy_without_user_input'] and not + copy_get_check['json']['templates_unable_to_copy'] and not copy_get_check['json']['credentials_unable_to_copy'] and not + copy_get_check['json']['inventories_unable_to_copy']): + # Because checks have passed + self.json_output['copy_checks'] = 'passed' + else: + self.fail_json(msg="Unable to copy {0} {1} error: {2}".format(item_type, copy_from_name_or_id, copy_get_check)) + else: + self.fail_json(msg="Error accessing {0} {1} error: {2} ".format(item_type, copy_from_name_or_id, copy_get_check)) + + response = self.post_endpoint(copy_from_lookup['related']['copy'], **{'data': {'name': new_item_name}}) if response['status_code'] in [201]: self.json_output['id'] = response['json']['id'] self.json_output['changed'] = True - item_url = response['json']['url'] + new_existing_item = response['json'] else: if 'json' in response and '__all__' in response['json']: - self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, name, response['json']['__all__'][0])) + self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, new_item_name, response['json']['__all__'][0])) elif 'json' in response: - self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, name, response['json'])) + self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, new_item_name, response['json'])) else: - self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, name, response['status_code'])) - last_data = response['json'] - return last_data + self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, new_item_name, response['status_code'])) + return new_existing_item def create_if_needed(self, existing_item, new_item, endpoint, on_create=None, auto_exit=True, item_type='unknown', associations=None): diff --git a/awx_collection/plugins/modules/tower_credential.py b/awx_collection/plugins/modules/tower_credential.py index 5002c4e0ed..13cec021ac 100644 --- a/awx_collection/plugins/modules/tower_credential.py +++ b/awx_collection/plugins/modules/tower_credential.py @@ -398,32 +398,21 @@ def main(): lookup_data = { 'credential_type': cred_type_id, } + # Create a copy of lookup data for copying without org. + copy_lookup_data = lookup_data if organization: lookup_data['organization'] = org_id + credential = module.get_one('credentials', name_or_id=name, **{'data': lookup_data}) + # Attempt to look up credential to copy based on the provided name if copy_from: - # Check if credential exists, as API will allow you to create an identical item with the same name in same org, but GUI will not. - credential = module.get_one('credentials', name_or_id=name, **{'data': lookup_data}) - if credential is not None: - module.fail_json(msg="A credential with the name {0} already exists.".format(name)) - else: - # Lookup existing credential. - copy_lookup_data = { - 'credential_type': cred_type_id, - } - copy_from_lookup = module.get_one('credentials', name_or_id=copy_from, **{'data': copy_lookup_data}) - if copy_from_lookup is None: - module.fail_json(msg="A credential with the name {0} was not able to be found.".format(copy_from)) - else: - # Because the initial copy will keep its organization, this can be different then the specified one. - lookup_data['organization'] = copy_from_lookup['organization'] - module.copy_item( - copy_from_lookup, name, - item_type='credential' - ) - - credential = module.get_one('credentials', name_or_id=name, **{'data': lookup_data}) + # a new existing item is formed when copying and is returned. + credential = module.copy_item( + credential, copy_from, name, + endpoint='credentials', item_type='credential', + copy_lookup_data=copy_lookup_data + ) if state == 'absent': # If the state was absent we can let the module delete it if needed, the module will handle exiting from this diff --git a/awx_collection/plugins/modules/tower_inventory.py b/awx_collection/plugins/modules/tower_inventory.py index f3ad98184c..30e77e4195 100644 --- a/awx_collection/plugins/modules/tower_inventory.py +++ b/awx_collection/plugins/modules/tower_inventory.py @@ -126,29 +126,6 @@ def main(): # Attempt to look up the related items the user specified (these will fail the module if not found) org_id = module.resolve_name_to_id('organizations', organization) - # Attempt to look up inventory to copy based on the provided name - if copy_from: - # Check if inventory exists, as API will allow you to create an identical item with the same name in same org, but GUI will not. - inventory = module.get_one('inventories', name_or_id=name, **{ - 'data': { - 'organization': org_id - } - }) - if inventory is not None: - module.fail_json(msg="A inventory with the name {0} already exists.".format(name)) - else: - # Lookup existing inventory. - copy_from_lookup = module.get_one('inventories', name_or_id=copy_from) - if copy_from_lookup is None: - module.fail_json(msg="An inventory with the name {0} was not able to be found.".format(copy_from)) - else: - # Because the initial copy will keep its organization, this can be different then the specified one. - org_id = copy_from_lookup['organization'] - module.copy_item( - copy_from_lookup, name, - item_type='inventory' - ) - # Attempt to look up inventory based on the provided name and org ID inventory = module.get_one('inventories', name_or_id=name, **{ 'data': { @@ -156,13 +133,18 @@ def main(): } }) + # Attempt to look up credential to copy based on the provided name + if copy_from: + # a new existing item is formed when copying and is returned. + inventory = module.copy_item( + inventory, copy_from, name, + endpoint='inventories', item_type='inventory', + ) + if state == 'absent': # If the state was absent we can let the module delete it if needed, the module will handle exiting from this module.delete_if_needed(inventory) - # Reset Org id to push in case copy_from was used. - org_id = module.resolve_name_to_id('organizations', organization) - # Create the data that gets sent for create and update inventory_fields = { 'name': module.get_item_name(inventory) if inventory else name, diff --git a/awx_collection/plugins/modules/tower_job_template.py b/awx_collection/plugins/modules/tower_job_template.py index 47a4820ba5..2ea032f9bc 100644 --- a/awx_collection/plugins/modules/tower_job_template.py +++ b/awx_collection/plugins/modules/tower_job_template.py @@ -437,28 +437,17 @@ def main(): organization_id = module.resolve_name_to_id('organizations', organization) search_fields['organization'] = new_fields['organization'] = organization_id - # Attempt to look up job template to copy based on the provided name - if copy_from: - # Check if job template exists, as API will allow you to create an identical item with the same name in same org, but GUI will not. - job_template = module.get_one('job_templates', name_or_id=name, **{'data': search_fields}) - if job_template is not None: - module.fail_json(msg="A job template with the name {0} already exists.".format(name)) - else: - # Lookup existing job template. - copy_from_lookup = module.get_one('job_templates', name_or_id=copy_from) - if copy_from_lookup is None: - module.fail_json(msg="A job template with the name {0} was not able to be found.".format(copy_from)) - else: - # Because the initial copy will keep its organization, this can be different then the specified one. - search_fields['organization'] = copy_from_lookup['organization'] - module.copy_item( - copy_from_lookup, name, - item_type='job_template' - ) - # Attempt to look up an existing item based on the provided data existing_item = module.get_one('job_templates', name_or_id=name, **{'data': search_fields}) + # Attempt to look up credential to copy based on the provided name + if copy_from: + # a new existing item is formed when copying and is returned. + existing_item = module.copy_item( + existing_item, copy_from, name, + endpoint='job_templates', item_type='job_template', + ) + if state == 'absent': # If the state was absent we can let the module delete it if needed, the module will handle exiting from this module.delete_if_needed(existing_item) diff --git a/awx_collection/plugins/modules/tower_notification_template.py b/awx_collection/plugins/modules/tower_notification_template.py index 63520664ad..912b06bcdd 100644 --- a/awx_collection/plugins/modules/tower_notification_template.py +++ b/awx_collection/plugins/modules/tower_notification_template.py @@ -395,29 +395,6 @@ def main(): if organization: organization_id = module.resolve_name_to_id('organizations', organization) - # Attempt to look up notification template to copy based on the provided name - if copy_from: - # Check if notification template exists, as API will allow you to create an identical item with the same name in same org, but GUI will not. - notification_template = module.get_one('notification_templates', name_or_id=name, **{ - 'data': { - 'organization': organization_id - } - }) - if notification_template is not None: - module.fail_json(msg="A notification template with the name {0} already exists.".format(name)) - else: - # Lookup existing notification template. - copy_from_lookup = module.get_one('notification_templates', name_or_id=copy_from) - if copy_from_lookup is None: - module.fail_json(msg="An notification template with the name {0} was not able to be found.".format(copy_from)) - else: - # Because the initial copy will keep its organization, this can be different then the specified one. - organization_id = copy_from_lookup['organization'] - module.copy_item( - copy_from_lookup, name, - item_type='notification_template' - ) - # Attempt to look up an existing item based on the provided data existing_item = module.get_one('notification_templates', name_or_id=name, **{ 'data': { @@ -425,9 +402,13 @@ def main(): } }) - # Reset Org id to push in case copy_from was used. - if organization: - organization_id = module.resolve_name_to_id('organizations', organization) + # Attempt to look up credential to copy based on the provided name + if copy_from: + # a new existing item is formed when copying and is returned. + existing_item = module.copy_item( + existing_item, copy_from, name, + endpoint='notification_templates', item_type='notification_template', + ) if state == 'absent': # If the state was absent we can let the module delete it if needed, the module will handle exiting from this diff --git a/awx_collection/plugins/modules/tower_project.py b/awx_collection/plugins/modules/tower_project.py index cccc2fec79..f08efb3258 100644 --- a/awx_collection/plugins/modules/tower_project.py +++ b/awx_collection/plugins/modules/tower_project.py @@ -292,28 +292,17 @@ def main(): org_id = module.resolve_name_to_id('organizations', organization) lookup_data['organization'] = org_id - # Attempt to look up project to copy based on the provided name - if copy_from: - # Check if project exists, as API will allow you to create an identical item with the same name in same org, but GUI will not. - project = module.get_one('projects', name_or_id=name, data=lookup_data) - if project is not None: - module.fail_json(msg="A project with the name {0} already exists.".format(name)) - else: - # Lookup existing project. - copy_from_lookup = module.get_one('projects', name_or_id=copy_from) - if copy_from_lookup is None: - module.fail_json(msg="A project with the name {0} was not able to be found.".format(copy_from)) - else: - # Because the initial copy will keep its organization, this can be different then the specified one. - lookup_data['organization'] = copy_from_lookup['organization'] - module.copy_item( - copy_from_lookup, name, - item_type='project' - ) - # Attempt to look up project based on the provided name and org ID project = module.get_one('projects', name_or_id=name, data=lookup_data) + # Attempt to look up credential to copy based on the provided name + if copy_from: + # a new existing item is formed when copying and is returned. + project = module.copy_item( + project, copy_from, name, + endpoint='projects', item_type='project', + ) + if state == 'absent': # If the state was absent we can let the module delete it if needed, the module will handle exiting from this module.delete_if_needed(project) diff --git a/awx_collection/plugins/modules/tower_workflow_job_template.py b/awx_collection/plugins/modules/tower_workflow_job_template.py index fa0c921830..1374b965c0 100644 --- a/awx_collection/plugins/modules/tower_workflow_job_template.py +++ b/awx_collection/plugins/modules/tower_workflow_job_template.py @@ -224,37 +224,17 @@ def main(): organization_id = module.resolve_name_to_id('organizations', organization) search_fields['organization'] = new_fields['organization'] = organization_id - # Attempt to look up workflow job template to copy based on the provided name - if copy_from: - # Check if workflow job template exists, as API will allow you to create an identical item with the same name in same org, but GUI will not. - workflow_job_template = module.get_one('workflow_job_templates', name_or_id=name, data=search_fields) - if workflow_job_template is not None: - module.fail_json(msg="A workflow job template with the name {0} already exists.".format(name)) - else: - # Lookup existing workflow job template. - copy_from_lookup = module.get_one('workflow_job_templates', name_or_id=copy_from) - if copy_from_lookup is None: - module.fail_json(msg="A workflow job template with the name {0} was not able to be found.".format(copy_from)) - else: - workflow_copy_get_check = module.get_endpoint(copy_from_lookup['related']['copy']) - if workflow_copy_get_check['status_code'] in [200]: - if (workflow_copy_get_check['json']['can_copy'] and workflow_copy_get_check['json']['can_copy_without_user_input'] and - not workflow_copy_get_check['json']['templates_unable_to_copy'] and not workflow_copy_get_check['json']['credentials_unable_to_copy'] - and not workflow_copy_get_check['json']['inventories_unable_to_copy']): - # Because the initial copy will keep its organization, this can be different then the specified one. - search_fields['organization'] = copy_from_lookup['organization'] - module.copy_item( - copy_from_lookup, name, - item_type='workflow_job_template' - ) - else: - module.fail_json(msg="Unable to copy workflow {0} error: {1}".format(copy_from, workflow_copy_get_check)) - else: - module.fail_json(msg="Error accessing workflow {0} error: {1} ".format(copy_from, workflow_copy_get_check)) - # Attempt to look up an existing item based on the provided data existing_item = module.get_one('workflow_job_templates', name_or_id=name, **{'data': search_fields}) + # Attempt to look up credential to copy based on the provided name + if copy_from: + # a new existing item is formed when copying and is returned. + existing_item = module.copy_item( + existing_item, copy_from, name, + endpoint='workflow_job_templates', item_type='workflow_job_template', + ) + if state == 'absent': # If the state was absent we can let the module delete it if needed, the module will handle exiting from this module.delete_if_needed(existing_item)