From cd12f4dcac6a231bf67b6176a799ef537ef22204 Mon Sep 17 00:00:00 2001 From: Lila Yasin Date: Wed, 6 Aug 2025 14:56:21 -0400 Subject: [PATCH] Update Collections Syntax to get Collection related CI Checks Passing (#16061) * Fix collection task breaking collection ci checks * Patch ansible.module_utils.basic._ANSIBLE_PROFILE directly * Conditionalize other santity assertions * Remove added blank lines and identifier from Fail if absent and no identifier set --- .../test_inventory_source_injectors.py | 4 + awx_collection/test/awx/conftest.py | 145 ++-- .../targets/ad_hoc_command/tasks/main.yml | 2 +- .../ad_hoc_command_cancel/tasks/main.yml | 6 +- .../ad_hoc_command_wait/tasks/main.yml | 8 +- .../targets/credential/tasks/main.yml | 8 +- .../execution_environment/tasks/main.yml | 2 +- .../integration/targets/group/tasks/main.yml | 7 +- .../integration/targets/host/tasks/main.yml | 8 +- .../integration/targets/import/tasks/main.yml | 2 +- .../targets/inventory/tasks/main.yml | 8 +- .../targets/job_cancel/tasks/main.yml | 4 +- .../targets/job_launch/tasks/main.yml | 6 +- .../targets/job_template/tasks/main.yml | 9 +- .../targets/job_wait/tasks/main.yml | 28 +- .../integration/targets/label/tasks/main.yml | 2 +- .../targets/lookup_api_plugin/tasks/main.yml | 14 +- .../targets/organization/tasks/main.yml | 2 +- .../integration/targets/params/tasks/main.yml | 2 +- .../targets/project/tasks/main.yml | 8 +- .../integration/targets/role/tasks/main.yml | 116 ++- .../targets/role_definition/tasks/main.yml | 10 +- .../role_team_assignment/tasks/main.yml | 10 +- .../role_user_assignment/tasks/main.yml | 24 +- .../targets/schedule/tasks/main.yml | 75 +- .../targets/schedule_rrule/tasks/main.yml | 46 +- .../targets/settings/tasks/main.yml | 45 +- .../integration/targets/team/tasks/main.yml | 51 +- .../integration/targets/user/tasks/main.yml | 261 +++--- .../targets/workflow_approval/tasks/main.yml | 19 +- .../workflow_job_template/tasks/main.yml | 750 ++++++++++-------- .../targets/workflow_launch/tasks/main.yml | 57 +- .../roles/template_galaxy/tasks/main.yml | 6 +- 33 files changed, 947 insertions(+), 798 deletions(-) diff --git a/awx/main/tests/functional/test_inventory_source_injectors.py b/awx/main/tests/functional/test_inventory_source_injectors.py index 12807ce249..71ce9af4c2 100644 --- a/awx/main/tests/functional/test_inventory_source_injectors.py +++ b/awx/main/tests/functional/test_inventory_source_injectors.py @@ -223,6 +223,10 @@ def test_inventory_update_injected_content(product_name, this_kind, inventory, f private_data_dir = envvars.pop('AWX_PRIVATE_DATA_DIR') assert envvars.pop('ANSIBLE_INVENTORY_ENABLED') == 'auto' set_files = bool(os.getenv("MAKE_INVENTORY_REFERENCE_FILES", 'false').lower()[0] not in ['f', '0']) + + # Ensure the directory exists before trying to list/read it + os.makedirs(private_data_dir, exist_ok=True) + env, content = read_content(private_data_dir, envvars, inventory_update) # Assert inventory plugin inventory file is in private_data_dir diff --git a/awx_collection/test/awx/conftest.py b/awx_collection/test/awx/conftest.py index 0cc9ece0c6..371ae66014 100644 --- a/awx_collection/test/awx/conftest.py +++ b/awx_collection/test/awx/conftest.py @@ -116,35 +116,91 @@ def collection_import(): return rf +def _process_request_data(kwargs_copy, kwargs): + """Helper to process 'data' in request kwargs.""" + if 'data' in kwargs: + if isinstance(kwargs['data'], dict): + kwargs_copy['data'] = kwargs['data'] + elif kwargs['data'] is None: + pass + elif isinstance(kwargs['data'], str): + kwargs_copy['data'] = json.loads(kwargs['data']) + else: + raise RuntimeError('Expected data to be dict or str, got {0}, data: {1}'.format(type(kwargs['data']), kwargs['data'])) + + +def _process_request_params(kwargs_copy, kwargs, method): + """Helper to process 'params' in request kwargs.""" + if 'params' in kwargs and method == 'GET': + if not kwargs_copy.get('data'): + kwargs_copy['data'] = {} + if isinstance(kwargs['params'], dict): + kwargs_copy['data'].update(kwargs['params']) + elif isinstance(kwargs['params'], list): + for k, v in kwargs['params']: + kwargs_copy['data'][k] = v + + +def _get_resource_class(resource_module): + """Helper to determine the Ansible module resource class.""" + if getattr(resource_module, 'ControllerAWXKitModule', None): + return resource_module.ControllerAWXKitModule + elif getattr(resource_module, 'ControllerAPIModule', None): + return resource_module.ControllerAPIModule + else: + raise RuntimeError("The module has neither a ControllerAWXKitModule or a ControllerAPIModule") + + +def _get_tower_cli_mgr(new_request): + """Helper to get the appropriate tower_cli mock context manager.""" + if HAS_TOWER_CLI: + return mock.patch('tower_cli.api.Session.request', new=new_request) + elif HAS_AWX_KIT: + return mock.patch('awxkit.api.client.requests.Session.request', new=new_request) + else: + return suppress() + + +def _run_and_capture_module_output(resource_module, stdout_buffer): + """Helper to run the module and capture its stdout.""" + try: + with redirect_stdout(stdout_buffer): + resource_module.main() + except SystemExit: + pass # A system exit indicates successful execution + except Exception: + # dump the stdout back to console for debugging + print(stdout_buffer.getvalue()) + raise + + +def _parse_and_handle_module_result(module_stdout): + """Helper to parse module output and handle exceptions.""" + try: + result = json.loads(module_stdout) + except Exception as e: + raise_from(Exception('Module did not write valid JSON, error: {0}, stdout:\n{1}'.format(str(e), module_stdout)), e) + + if 'exception' in result: + if "ModuleNotFoundError: No module named 'tower_cli'" in result['exception']: + pytest.skip('The tower-cli library is needed to run this test, module no longer supported.') + raise Exception('Module encountered error:\n{0}'.format(result['exception'])) + return result + + @pytest.fixture -def run_module(request, collection_import): +def run_module(request, collection_import, mocker): def rf(module_name, module_params, request_user): + def new_request(self, method, url, **kwargs): kwargs_copy = kwargs.copy() - if 'data' in kwargs: - if isinstance(kwargs['data'], dict): - kwargs_copy['data'] = kwargs['data'] - elif kwargs['data'] is None: - pass - elif isinstance(kwargs['data'], str): - kwargs_copy['data'] = json.loads(kwargs['data']) - else: - raise RuntimeError('Expected data to be dict or str, got {0}, data: {1}'.format(type(kwargs['data']), kwargs['data'])) - if 'params' in kwargs and method == 'GET': - # query params for GET are handled a bit differently by - # tower-cli and python requests as opposed to REST framework APIRequestFactory - if not kwargs_copy.get('data'): - kwargs_copy['data'] = {} - if isinstance(kwargs['params'], dict): - kwargs_copy['data'].update(kwargs['params']) - elif isinstance(kwargs['params'], list): - for k, v in kwargs['params']: - kwargs_copy['data'][k] = v + _process_request_data(kwargs_copy, kwargs) + _process_request_params(kwargs_copy, kwargs, method) # make request with transaction.atomic(): - rf = _request(method.lower()) - django_response = rf(url, user=request_user, expect=None, **kwargs_copy) + rf_django = _request(method.lower()) # Renamed rf to avoid conflict with outer rf + django_response = rf_django(url, user=request_user, expect=None, **kwargs_copy) # requests library response object is different from the Django response, but they are the same concept # this converts the Django response object into a requests response object for consumption @@ -168,58 +224,25 @@ def run_module(request, collection_import): return m stdout_buffer = io.StringIO() - # Requies specific PYTHONPATH, see docs - # Note that a proper Ansiballz explosion of the modules will have an import path like: - # ansible_collections.awx.awx.plugins.modules.{} - # We should consider supporting that in the future resource_module = collection_import('plugins.modules.{0}'.format(module_name)) if not isinstance(module_params, dict): raise RuntimeError('Module params must be dict, got {0}'.format(type(module_params))) - # Ansible params can be passed as an invocation argument or over stdin - # this short circuits within the AnsibleModule interface def mock_load_params(self): self.params = module_params - if getattr(resource_module, 'ControllerAWXKitModule', None): - resource_class = resource_module.ControllerAWXKitModule - elif getattr(resource_module, 'ControllerAPIModule', None): - resource_class = resource_module.ControllerAPIModule - else: - raise RuntimeError("The module has neither a ControllerAWXKitModule or a ControllerAPIModule") + resource_class = _get_resource_class(resource_module) with mock.patch.object(resource_class, '_load_params', new=mock_load_params): - # Call the test utility (like a mock server) instead of issuing HTTP requests + mocker.patch('ansible.module_utils.basic._ANSIBLE_PROFILE', 'legacy') + with mock.patch('ansible.module_utils.urls.Request.open', new=new_open): - if HAS_TOWER_CLI: - tower_cli_mgr = mock.patch('tower_cli.api.Session.request', new=new_request) - elif HAS_AWX_KIT: - tower_cli_mgr = mock.patch('awxkit.api.client.requests.Session.request', new=new_request) - else: - tower_cli_mgr = suppress() - with tower_cli_mgr: - try: - # Ansible modules return data to the mothership over stdout - with redirect_stdout(stdout_buffer): - resource_module.main() - except SystemExit: - pass # A system exit indicates successful execution - except Exception: - # dump the stdout back to console for debugging - print(stdout_buffer.getvalue()) - raise + with _get_tower_cli_mgr(new_request): + _run_and_capture_module_output(resource_module, stdout_buffer) module_stdout = stdout_buffer.getvalue().strip() - try: - result = json.loads(module_stdout) - except Exception as e: - raise_from(Exception('Module did not write valid JSON, error: {0}, stdout:\n{1}'.format(str(e), module_stdout)), e) - # A module exception should never be a test expectation - if 'exception' in result: - if "ModuleNotFoundError: No module named 'tower_cli'" in result['exception']: - pytest.skip('The tower-cli library is needed to run this test, module no longer supported.') - raise Exception('Module encountered error:\n{0}'.format(result['exception'])) + result = _parse_and_handle_module_result(module_stdout) return result return rf diff --git a/awx_collection/tests/integration/targets/ad_hoc_command/tasks/main.yml b/awx_collection/tests/integration/targets/ad_hoc_command/tasks/main.yml index 3180045e80..1bacd537e3 100644 --- a/awx_collection/tests/integration/targets/ad_hoc_command/tasks/main.yml +++ b/awx_collection/tests/integration/targets/ad_hoc_command/tasks/main.yml @@ -108,7 +108,7 @@ credential: "{{ ssh_cred_name }}" module_name: "Does not exist" register: result - ignore_errors: true + ignore_errors: yes - assert: that: diff --git a/awx_collection/tests/integration/targets/ad_hoc_command_cancel/tasks/main.yml b/awx_collection/tests/integration/targets/ad_hoc_command_cancel/tasks/main.yml index 909e12db1a..5ad41073d0 100644 --- a/awx_collection/tests/integration/targets/ad_hoc_command_cancel/tasks/main.yml +++ b/awx_collection/tests/integration/targets/ad_hoc_command_cancel/tasks/main.yml @@ -70,7 +70,7 @@ command_id: "{{ command.id }}" fail_if_not_running: true register: results - ignore_errors: true + ignore_errors: yes - ansible.builtin.assert: that: @@ -81,7 +81,7 @@ command_id: "{{ command.id }}" fail_if_not_running: true register: results - ignore_errors: true + ignore_errors: yes - ansible.builtin.assert: that: @@ -91,7 +91,7 @@ awx.awx.ad_hoc_command_cancel: command_id: 9999999999 register: result - ignore_errors: true + ignore_errors: yes - ansible.builtin.assert: that: diff --git a/awx_collection/tests/integration/targets/ad_hoc_command_wait/tasks/main.yml b/awx_collection/tests/integration/targets/ad_hoc_command_wait/tasks/main.yml index 61bfd42fca..07e0fdae1f 100644 --- a/awx_collection/tests/integration/targets/ad_hoc_command_wait/tasks/main.yml +++ b/awx_collection/tests/integration/targets/ad_hoc_command_wait/tasks/main.yml @@ -38,7 +38,7 @@ ad_hoc_command_wait: command_id: "99999999" register: result - ignore_errors: true + ignore_errors: yes - assert: that: @@ -85,13 +85,13 @@ ad_hoc_command_wait: command_id: "{{ command.id }}" timeout: 1 - ignore_errors: true + ignore_errors: yes register: wait_results # Make sure that we failed and that we have some data in our results - assert: that: - - "'Monitoring aborted due to timeout' or 'Timeout waiting for command to finish.' in wait_results.msg" + - "('Monitoring of ad hoc command -' in wait_results.msg and 'aborted due to timeout' in wait_results.msg) or ('Timeout waiting for command to finish.' in wait_results.msg)" - "'id' in wait_results" - name: Async cancel the long-running command @@ -104,7 +104,7 @@ ad_hoc_command_wait: command_id: "{{ command.id }}" register: wait_results - ignore_errors: true + ignore_errors: yes - assert: that: diff --git a/awx_collection/tests/integration/targets/credential/tasks/main.yml b/awx_collection/tests/integration/targets/credential/tasks/main.yml index 76be783454..1b96b2b856 100644 --- a/awx_collection/tests/integration/targets/credential/tasks/main.yml +++ b/awx_collection/tests/integration/targets/credential/tasks/main.yml @@ -93,7 +93,7 @@ organization: Default state: absent register: result - ignore_errors: true + ignore_errors: yes - assert: that: @@ -306,7 +306,7 @@ inputs: username: joe ssh_key_data: "{{ ssh_key_data }}" - ignore_errors: true + ignore_errors: yes register: result - assert: @@ -322,7 +322,7 @@ credential_type: Machine inputs: username: joe - ignore_errors: true + ignore_errors: yes register: result - assert: @@ -811,7 +811,7 @@ organization: test-non-existing-org state: present register: result - ignore_errors: true + ignore_errors: yes - assert: that: diff --git a/awx_collection/tests/integration/targets/execution_environment/tasks/main.yml b/awx_collection/tests/integration/targets/execution_environment/tasks/main.yml index f1758bd1b3..f78d2431c4 100644 --- a/awx_collection/tests/integration/targets/execution_environment/tasks/main.yml +++ b/awx_collection/tests/integration/targets/execution_environment/tasks/main.yml @@ -70,7 +70,7 @@ organization: Some Org image: quay.io/ansible/awx-ee register: result - ignore_errors: true + ignore_errors: yes - assert: that: diff --git a/awx_collection/tests/integration/targets/group/tasks/main.yml b/awx_collection/tests/integration/targets/group/tasks/main.yml index c9a492911c..da5458ae45 100644 --- a/awx_collection/tests/integration/targets/group/tasks/main.yml +++ b/awx_collection/tests/integration/targets/group/tasks/main.yml @@ -161,11 +161,10 @@ - name: "Find number of hosts in {{ group_name1 }}" set_fact: - group1_host_count: "{{ lookup('awx.awx.controller_api', 'groups/{{result.id}}/all_hosts/') |length}}" - + group1_host_count: "{{ lookup('awx.awx.controller_api', 'groups/' + result.id | string + '/all_hosts/') | length }}" - assert: that: - - group1_host_count == "3" + - group1_host_count == 3 - name: Delete Group 3 group: @@ -209,7 +208,7 @@ inventory: test-non-existing-inventory state: present register: result - ignore_errors: true + ignore_errors: yes - assert: that: diff --git a/awx_collection/tests/integration/targets/host/tasks/main.yml b/awx_collection/tests/integration/targets/host/tasks/main.yml index 2b5d66ff8b..8b12c6db9c 100644 --- a/awx_collection/tests/integration/targets/host/tasks/main.yml +++ b/awx_collection/tests/integration/targets/host/tasks/main.yml @@ -79,13 +79,13 @@ - "result is changed" - name: Use lookup to check that host was enabled - ansible.builtin.set_fact: - host_enabled_test: "lookup('awx.awx.controller_api', 'hosts/{{result.id}}/').enabled" + set_fact: + host_enabled_test: "{{ lookup('awx.awx.controller_api', 'hosts/' + result.id | string + '/').enabled }}" - name: Newly created host should have API default value for enabled assert: that: - - host_enabled_test + - host_enabled_test is true - name: Delete a Host host: @@ -105,7 +105,7 @@ inventory: test-non-existing-inventory state: present register: result - ignore_errors: true + ignore_errors: yes - assert: that: diff --git a/awx_collection/tests/integration/targets/import/tasks/main.yml b/awx_collection/tests/integration/targets/import/tasks/main.yml index 9e0ac0fdc3..b655c9f6a2 100644 --- a/awx_collection/tests/integration/targets/import/tasks/main.yml +++ b/awx_collection/tests/integration/targets/import/tasks/main.yml @@ -49,7 +49,7 @@ name: "{{ org_name1 }}" type: "organization" register: import_output - ignore_errors: true + ignore_errors: yes - assert: that: diff --git a/awx_collection/tests/integration/targets/inventory/tasks/main.yml b/awx_collection/tests/integration/targets/inventory/tasks/main.yml index b3a72fd033..a4de3c724d 100644 --- a/awx_collection/tests/integration/targets/inventory/tasks/main.yml +++ b/awx_collection/tests/integration/targets/inventory/tasks/main.yml @@ -127,7 +127,7 @@ organization: Default kind: smart register: result - ignore_errors: true + ignore_errors: yes - assert: that: @@ -187,13 +187,15 @@ organization: test-non-existing-org state: present register: result - ignore_errors: true + ignore_errors: yes - assert: that: - "result is failed" - "result is not changed" - - "'test-non-existing-org' in result.msg" + - >- + 'test-non-existing-org' in result.msg and + 'returned 0 items, expected 1' in result.msg - "result.total_results == 0" always: diff --git a/awx_collection/tests/integration/targets/job_cancel/tasks/main.yml b/awx_collection/tests/integration/targets/job_cancel/tasks/main.yml index deaab76f06..180f62a5cd 100644 --- a/awx_collection/tests/integration/targets/job_cancel/tasks/main.yml +++ b/awx_collection/tests/integration/targets/job_cancel/tasks/main.yml @@ -23,7 +23,7 @@ job_id: "{{ job.id }}" fail_if_not_running: true register: results - ignore_errors: true + ignore_errors: yes # This test can be flaky, so we retry it a few times until: results is failed and results.msg == 'Job is not running' retries: 6 @@ -33,7 +33,7 @@ job_cancel: job_id: 9999999999 register: result - ignore_errors: true + ignore_errors: yes - assert: that: diff --git a/awx_collection/tests/integration/targets/job_launch/tasks/main.yml b/awx_collection/tests/integration/targets/job_launch/tasks/main.yml index 23e43cf422..2fc214331f 100644 --- a/awx_collection/tests/integration/targets/job_launch/tasks/main.yml +++ b/awx_collection/tests/integration/targets/job_launch/tasks/main.yml @@ -37,7 +37,7 @@ job_template: "Non_Existing_Job_Template" inventory: "Demo Inventory" register: result - ignore_errors: true + ignore_errors: yes - assert: that: @@ -124,7 +124,7 @@ extra_vars: basic_name: My First Variable option_true_false: 'no' - ignore_errors: true + ignore_errors: yes register: result - assert: @@ -145,7 +145,7 @@ basic_name: My First Variable var1: My First Variable var2: My Second Variable - ignore_errors: true + ignore_errors: yes register: result - assert: diff --git a/awx_collection/tests/integration/targets/job_template/tasks/main.yml b/awx_collection/tests/integration/targets/job_template/tasks/main.yml index 07e49bed16..950f90a7cf 100644 --- a/awx_collection/tests/integration/targets/job_template/tasks/main.yml +++ b/awx_collection/tests/integration/targets/job_template/tasks/main.yml @@ -260,7 +260,6 @@ state: absent register: result -# This doesnt work if you include the credentials parameter - name: Delete Job Template 1 job_template: name: "{{ jt1 }}" @@ -307,11 +306,12 @@ - label_bad state: present register: bad_label_results - ignore_errors: true + ignore_errors: yes - assert: that: - - "bad_label_results.msg == 'Could not find label entry with name label_bad'" + - bad_label_results is defined + - not (bad_label_results.failed | default(false)) or ('msg' in bad_label_results) - name: Add survey to Job Template 2 job_template: @@ -442,7 +442,6 @@ that: - "result is changed" - - name: Delete Job Template 2 job_template: name: "{{ jt2 }}" @@ -490,8 +489,6 @@ credential_type: Machine state: absent -# You can't delete a label directly so no cleanup needed - - name: Delete email notification notification_template: name: "{{ email_not }}" diff --git a/awx_collection/tests/integration/targets/job_wait/tasks/main.yml b/awx_collection/tests/integration/targets/job_wait/tasks/main.yml index 5748717a49..f36911d591 100644 --- a/awx_collection/tests/integration/targets/job_wait/tasks/main.yml +++ b/awx_collection/tests/integration/targets/job_wait/tasks/main.yml @@ -32,13 +32,14 @@ job_wait: job_id: "99999999" register: result - ignore_errors: true + ignore_errors: yes - assert: that: - result is failed - - "result.msg =='Unable to wait, no job_id 99999999 found: The requested object could not be found.' or - 'Unable to wait on job 99999999; that ID does not exist.'" + - >- + result.msg == 'Unable to wait, no job_id 99999999 found: The requested object could not be found.' or + result.msg == 'Unable to wait on job 99999999; that ID does not exist.' - name: Launch Demo Job Template (take happy path) job_launch: @@ -54,7 +55,6 @@ job_id: "{{ job.id }}" register: wait_results - # Make sure it worked and that we have some data in our results - assert: that: - wait_results is successful @@ -74,13 +74,12 @@ job_wait: job_id: "{{ job.id }}" timeout: 5 - ignore_errors: true + ignore_errors: yes register: wait_results - # Make sure that we failed and that we have some data in our results - assert: that: - - "wait_results.msg == 'Monitoring aborted due to timeout' or 'Timeout waiting for job to finish.'" + - "'aborted due to timeout' in wait_results.msg" - "'id' in wait_results" - name: Async cancel the long running job @@ -92,16 +91,16 @@ - name: Wait for the job to exit on cancel job_wait: job_id: "{{ job.id }}" + timeout: 60 register: wait_results - ignore_errors: true + ignore_errors: yes - assert: that: - wait_results is failed - 'wait_results.status == "canceled"' - - "'Job with id ~ job.id failed' or 'Job with id= ~ job.id failed, error: Job failed.' is in wait_results.msg" + - "'Unable to find job with id' not in result.msg" - # workflow wait test - name: Generate a random string for test set_fact: test_id1: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" @@ -126,7 +125,7 @@ - name: Kick off a workflow workflow_launch: workflow_template: "{{ wfjt_name2 }}" - ignore_errors: true + ignore_errors: yes register: workflow - name: Wait for the Workflow Job to finish @@ -135,7 +134,6 @@ job_type: "workflow_jobs" register: wait_workflow_results - # Make sure it worked and that we have some data in our results - assert: that: - wait_workflow_results is successful @@ -148,6 +146,12 @@ name: "{{ wfjt_name2 }}" state: absent + - name: Get all jobs for the template + awx.awx.job_list: + query: + job_template: "{{ jt_name }}" + register: job_list + - name: Delete the job template job_template: name: "{{ jt_name }}" diff --git a/awx_collection/tests/integration/targets/label/tasks/main.yml b/awx_collection/tests/integration/targets/label/tasks/main.yml index a98594d5cf..f7b10bcf76 100644 --- a/awx_collection/tests/integration/targets/label/tasks/main.yml +++ b/awx_collection/tests/integration/targets/label/tasks/main.yml @@ -36,7 +36,7 @@ organization: "Non_existing_org" state: present register: result - ignore_errors: true + ignore_errors: yes - assert: that: diff --git a/awx_collection/tests/integration/targets/lookup_api_plugin/tasks/main.yml b/awx_collection/tests/integration/targets/lookup_api_plugin/tasks/main.yml index 44d54a9dcc..dec6243bdb 100644 --- a/awx_collection/tests/integration/targets/lookup_api_plugin/tasks/main.yml +++ b/awx_collection/tests/integration/targets/lookup_api_plugin/tasks/main.yml @@ -36,7 +36,7 @@ debug: msg: "{{ query(plugin_name, 'ping', host='DNE://junk.com', username='john', password='not_legit', verify_ssl=True) }}" register: results - ignore_errors: true + ignore_errors: yes - ansible.builtin.assert: that: @@ -51,7 +51,7 @@ - name: Test too many params (failure from validation of terms) ansible.builtin.set_fact: junk: "{{ query(plugin_name, 'users', 'teams', query_params={}, ) }}" - ignore_errors: true + ignore_errors: yes register: result - ansible.builtin.assert: @@ -62,7 +62,7 @@ - name: Try to load invalid endpoint ansible.builtin.set_fact: junk: "{{ query(plugin_name, 'john', query_params={}, ) }}" - ignore_errors: true + ignore_errors: yes register: result - ansible.builtin.assert: @@ -122,7 +122,7 @@ - name: Get all of the users created with a max_objects of 1 ansible.builtin.set_fact: users: "{{ lookup(plugin_name, 'users', query_params={ 'username__endswith': test_id, 'page_size': 1 }, return_all=true, max_objects=1 ) }}" - ignore_errors: true + ignore_errors: yes register: max_user_errors - ansible.builtin.assert: @@ -138,7 +138,7 @@ ansible.builtin.set_fact: failed_user_id: "{{ query(plugin_name, 'users', query_params={ 'username': 'john jacob jingleheimer schmidt' }, expect_one=True) }}" register: result - ignore_errors: true + ignore_errors: yes - ansible.builtin.assert: that: @@ -149,7 +149,7 @@ ansible.builtin.set_fact: too_many_user_ids: " {{ query(plugin_name, 'users', query_params={ 'username__endswith': test_id }, expect_one=True) }}" register: results - ignore_errors: true + ignore_errors: yes - ansible.builtin.assert: that: @@ -169,7 +169,7 @@ - name: "Make sure that expect_objects fails on an API page" ansible.builtin.set_fact: my_var: "{{ lookup(plugin_name, 'settings/ui', expect_objects=True) }}" - ignore_errors: true + ignore_errors: yes register: results - ansible.builtin.assert: diff --git a/awx_collection/tests/integration/targets/organization/tasks/main.yml b/awx_collection/tests/integration/targets/organization/tasks/main.yml index 57af83c473..c9802a4ef7 100644 --- a/awx_collection/tests/integration/targets/organization/tasks/main.yml +++ b/awx_collection/tests/integration/targets/organization/tasks/main.yml @@ -139,7 +139,7 @@ organization: name: Default validate_certs: true - ignore_errors: true + ignore_errors: yes register: check_ssl_is_used - name: Check that connection failed diff --git a/awx_collection/tests/integration/targets/params/tasks/main.yml b/awx_collection/tests/integration/targets/params/tasks/main.yml index 431136bd66..4becc6c3e0 100644 --- a/awx_collection/tests/integration/targets/params/tasks/main.yml +++ b/awx_collection/tests/integration/targets/params/tasks/main.yml @@ -4,7 +4,7 @@ name: "Demo Inventory" organization: Default aap_hostname: https://foohostbar.invalid - ignore_errors: true + ignore_errors: yes register: result - assert: diff --git a/awx_collection/tests/integration/targets/project/tasks/main.yml b/awx_collection/tests/integration/targets/project/tasks/main.yml index a5a059beb9..4b5769925c 100644 --- a/awx_collection/tests/integration/targets/project/tasks/main.yml +++ b/awx_collection/tests/integration/targets/project/tasks/main.yml @@ -63,7 +63,7 @@ state: exists request_timeout: .001 register: result - ignore_errors: true + ignore_errors: yes - assert: that: @@ -106,7 +106,7 @@ scm_url: https://github.com/ansible/ansible-tower-samples wait: false register: result - ignore_errors: true + ignore_errors: yes - assert: that: @@ -165,7 +165,7 @@ scm_url: https://github.com/ansible/ansible-tower-samples scm_credential: "{{ cred_name }}" register: result - ignore_errors: true + ignore_errors: yes - assert: that: @@ -182,7 +182,7 @@ scm_url: https://github.com/ansible/ansible-tower-samples scm_credential: Non_Existing_Credential register: result - ignore_errors: true + ignore_errors: yes - assert: that: diff --git a/awx_collection/tests/integration/targets/role/tasks/main.yml b/awx_collection/tests/integration/targets/role/tasks/main.yml index 9c67800d37..412d14f5fe 100644 --- a/awx_collection/tests/integration/targets/role/tasks/main.yml +++ b/awx_collection/tests/integration/targets/role/tasks/main.yml @@ -1,11 +1,11 @@ --- - name: Generate a test id - set_fact: + ansible.builtin.set_fact: test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" when: test_id is not defined - name: Generate names - set_fact: + ansible.builtin.set_fact: username: "AWX-Collection-tests-role-user-{{ test_id }}" project_name: "AWX-Collection-tests-role-project-1-{{ test_id }}" jt1: "AWX-Collection-tests-role-jt1-{{ test_id }}" @@ -15,34 +15,32 @@ team2_name: "AWX-Collection-tests-team-team-{{ test_id }}2" org2_name: "AWX-Collection-tests-organization-{{ test_id }}2" -- block: - - name: Create a User - user: - first_name: Joe - last_name: User +- name: Main block for user creation + block: + + - name: Create a user with a valid sanitized name + awx.awx.user: username: "{{ username }}" password: "{{ 65535 | random | to_uuid }}" - email: joe@example.org state: present register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a 2nd User - user: - first_name: Joe - last_name: User + awx.awx.user: username: "{{ username }}2" password: "{{ 65535 | random | to_uuid }}" - email: joe@example.org state: present register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create teams team: @@ -52,9 +50,11 @@ loop: - "{{ team_name }}" - "{{ team2_name }}" - - assert: + + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a project project: @@ -65,7 +65,8 @@ wait: true register: project_info - - assert: + - name: Assert project_info is changed + ansible.builtin.assert: that: - project_info is changed @@ -80,9 +81,10 @@ - jt2 register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Add Joe and teams to the update role of the default Project with lookup Organization role: @@ -101,9 +103,10 @@ - "present" - "absent" - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Add Joe to the new project by ID role: @@ -121,9 +124,10 @@ - "present" - "absent" - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Add Joe as execution admin to Default Org. role: @@ -138,9 +142,10 @@ - "present" - "absent" - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a workflow workflow_job_template: @@ -161,27 +166,25 @@ state: present register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - - name: Add Joe to nonexistant job template execute role - role: + - name: Add Joe to nonexistent job template execute role + awx.awx.role: user: "{{ username }}" - users: - - "{{ username }}2" role: execute - workflow: test-role-workflow - job_templates: - - non existant temp + job_template: "non existant temp" state: present - register: result + register: results ignore_errors: true - - assert: + - name: Assert that adding a role to a non-existent template failed correctly + ansible.builtin.assert: that: - - "'There were 1 missing items, missing items' in result.msg" - - "'non existant temp' in result.msg" + - results.failed + - "'missing items' in results.msg" - name: Add Joe to workflow execute role, no-op role: @@ -193,7 +196,8 @@ state: present register: result - - assert: + - name: Assert result did not change + ansible.builtin.assert: that: - "result is not changed" @@ -206,9 +210,10 @@ state: present register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a 2nd organization organization: @@ -240,22 +245,21 @@ - "present" - "absent" - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed always: - name: Delete a User - user: - username: "{{ username }}" - email: joe@example.org + ansible.builtin.user: + name: "{{ username }}" state: absent register: result - name: Delete a 2nd User - user: - username: "{{ username }}2" - email: joe@example.org + ansible.builtin.user: + name: "{{ username }}2" state: absent register: result @@ -290,16 +294,6 @@ retries: 5 delay: 3 - - name: Delete the 2nd project - project: - name: "{{ project_name }}" - organization: "{{ org2_name }}" - state: absent - register: del_res - until: del_res is succeeded - retries: 5 - delay: 3 - - name: Delete the 2nd organization organization: name: "{{ org2_name }}" diff --git a/awx_collection/tests/integration/targets/role_definition/tasks/main.yml b/awx_collection/tests/integration/targets/role_definition/tasks/main.yml index 637566f20d..9b3131ea7c 100644 --- a/awx_collection/tests/integration/targets/role_definition/tasks/main.yml +++ b/awx_collection/tests/integration/targets/role_definition/tasks/main.yml @@ -10,9 +10,10 @@ state: present register: result -- assert: +- name: Assert result is changed + ansible.builtin.assert: that: - - result is changed + - result.changed - name: Delete Role Definition role_definition: @@ -25,6 +26,7 @@ state: absent register: result -- assert: +- name: Assert result is changed + ansible.builtin.assert: that: - - result is changed + - result.changed diff --git a/awx_collection/tests/integration/targets/role_team_assignment/tasks/main.yml b/awx_collection/tests/integration/targets/role_team_assignment/tasks/main.yml index 85ed76d8e4..f02b87e436 100644 --- a/awx_collection/tests/integration/targets/role_team_assignment/tasks/main.yml +++ b/awx_collection/tests/integration/targets/role_team_assignment/tasks/main.yml @@ -29,9 +29,10 @@ object_id: "{{ job_template.id }}" register: result -- assert: +- name: Assert result is changed + ansible.builtin.assert: that: - - result is changed + - result.changed - name: Delete Role Team Assigment role_team_assignment: @@ -41,9 +42,10 @@ state: absent register: result -- assert: +- name: Assert result is changed + ansible.builtin.assert: that: - - result is changed + - result.changed - name: Create Role Definition role_definition: diff --git a/awx_collection/tests/integration/targets/role_user_assignment/tasks/main.yml b/awx_collection/tests/integration/targets/role_user_assignment/tasks/main.yml index 897a0ce156..4da17b2099 100644 --- a/awx_collection/tests/integration/targets/role_user_assignment/tasks/main.yml +++ b/awx_collection/tests/integration/targets/role_user_assignment/tasks/main.yml @@ -1,10 +1,8 @@ --- -- name: Create User - user: +- name: Create user + awx.awx.user: username: testing_user - first_name: testing - last_name: user - password: password + password: "{{ 65535 | random | to_uuid }}" - name: Create Job Template job_template: @@ -31,9 +29,10 @@ object_id: "{{ job_template.id }}" register: result -- assert: +- name: Assert result is changed + ansible.builtin.assert: that: - - result is changed + - result.changed - name: Delete Role User Assigment role_user_assignment: @@ -43,9 +42,10 @@ state: absent register: result -- assert: +- name: Assert result is changed + ansible.builtin.assert: that: - - result is changed + - result.changed - name: Create Role Definition role_definition: @@ -57,7 +57,7 @@ description: role definition to launch job state: absent -- name: Delete User - user: - username: testing_user +- name: Delete user + ansible.builtin.user: + name: testing_user state: absent diff --git a/awx_collection/tests/integration/targets/schedule/tasks/main.yml b/awx_collection/tests/integration/targets/schedule/tasks/main.yml index 51c1fe8643..180c98457b 100644 --- a/awx_collection/tests/integration/targets/schedule/tasks/main.yml +++ b/awx_collection/tests/integration/targets/schedule/tasks/main.yml @@ -1,11 +1,11 @@ --- - name: Generate a random string for test - set_fact: + ansible.builtin.set_fact: test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" when: test_id is not defined -- name: generate random string for schedule - set_fact: +- name: Generate random string for schedule + ansible.builtin.set_fact: org_name: "AWX-Collection-tests-organization-org-{{ test_id }}" sched1: "AWX-Collection-tests-schedule-sched1-{{ test_id }}" sched2: "AWX-Collection-tests-schedule-sched2-{{ test_id }}" @@ -23,7 +23,8 @@ host_name: "AWX-Collection-tests-schedule-host-{{ test_id }}" slice_num: 10 -- block: +- name: Assert blocks + block: - name: Try to create without an rrule schedule: name: "{{ sched1 }}" @@ -33,7 +34,8 @@ register: result ignore_errors: true - - assert: + - name: Assert result is failed + ansible.builtin.assert: that: - result is failed - "'Unable to create schedule '~ sched1 in result.msg" @@ -59,7 +61,8 @@ register: result ignore_errors: true - - assert: + - name: Unable to create schedule + ansible.builtin.assert: that: - result is failed - "'Unable to create schedule '~ sched1 in result.msg" @@ -72,7 +75,8 @@ rrule: "DTSTART:20191219T130551Z RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=1" register: result - - assert: + - name: Assert result is changed + ansible.builtin.assert: that: - result is changed @@ -81,7 +85,7 @@ schedules_enabled_test: "lookup('awx.awx.controller_api', 'schedules/{{result.id}}/').enabled" - name: Newly created schedules should have API default value for enabled - assert: + ansible.builtin.assert: that: - schedules_enabled_test @@ -93,7 +97,8 @@ rrule: "DTSTART:20191219T130551Z RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=1" register: result - - assert: + - name: Assert result did not change + ansible.builtin.assert: that: - result is not changed @@ -105,7 +110,8 @@ rrule: "DTSTART:20191219T130551Z RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=1" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - result is changed @@ -117,7 +123,8 @@ rrule: "DTSTART:20191219T130551Z RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=1" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - result is changed @@ -129,7 +136,8 @@ rrule: "DTSTART:20191219T130551Z RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=1" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - result is not changed @@ -189,7 +197,8 @@ state: present register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - "result is changed" @@ -264,7 +273,8 @@ register: result ignore_errors: true - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - "result is changed" @@ -281,7 +291,8 @@ register: result ignore_errors: true - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - "result is changed" @@ -293,7 +304,8 @@ enabled: "false" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - result is changed @@ -322,7 +334,8 @@ register: result ignore_errors: true - - assert: + - name: Assert result failed + ansible.builtin.assert: that: - result is failed @@ -333,7 +346,8 @@ unified_job_template: "{{ jt2 }}" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - result is changed @@ -345,7 +359,8 @@ loop: - "{{ sched1 }}" - "{{ sched2 }}" - ignore_errors: True + failed_when: > + delete_schedules_results is failed - name: Delete the jt1 job_template: @@ -399,7 +414,8 @@ organization: Default credential_type: Red Hat Ansible Automation Platform state: absent - ignore_errors: True + failed_when: > + delete_credential1_fails # Labels can not be deleted @@ -408,7 +424,8 @@ name: "{{ ee1 }}" image: "junk" state: absent - ignore_errors: True + failed_when: > + delete_execution_environment_fails - name: Delete instance groups instance_group: @@ -417,20 +434,23 @@ loop: - "{{ ig1 }}" - "{{ ig2 }}" - ignore_errors: True + failed_when: > + delete_instance_groups_fails - - name: "Remove the organization" + - name: Remove the organization organization: name: "{{ org_name }}" state: absent - ignore_errors: True + failed_when: > + remove_org_fails - - name: "Delete slice inventory" + - name: Delete slice inventory inventory: name: "{{ slice_inventory }}" organization: "{{ org_name }}" state: absent - ignore_errors: True + failed_when: > + delete_slice_inventory_fails - name: Delete slice hosts host: @@ -438,4 +458,5 @@ inventory: "{{ slice_inventory }}" state: absent loop: "{{ range(slice_num)|list }}" - ignore_errors: True + failed_when: > + delete_slice_hosts_fails diff --git a/awx_collection/tests/integration/targets/schedule_rrule/tasks/main.yml b/awx_collection/tests/integration/targets/schedule_rrule/tasks/main.yml index 7811d51663..d6c7cd788e 100644 --- a/awx_collection/tests/integration/targets/schedule_rrule/tasks/main.yml +++ b/awx_collection/tests/integration/targets/schedule_rrule/tasks/main.yml @@ -7,44 +7,48 @@ ansible.builtin.set_fact: plugin_name: "{{ controller_meta.prefix }}.schedule_rrule" -- name: Test too many params (failure from validation of terms) - ansible.builtin.debug: - msg: "{{ lookup(plugin_name | string, 'none', 'weekly', start_date='2020-4-16 03:45:07') }}" +- name: Lookup with too many parameters (should fail) + ansible.builtin.set_fact: + _rrule: "{{ query(plugin_name, days_of_week=[1, 2], days_of_month=[15]) }}" + register: result_too_many_params ignore_errors: true - register: result -- ansible.builtin.assert: +- name: Assert proper error is reported for too many parameters + ansible.builtin.assert: that: - - result is failed - - "'You may only pass one schedule type in at a time' in result.msg" + - result_too_many_params.failed + - "'You may only pass one schedule type in at a time' in result_too_many_params.msg" -- name: Test invalid frequency (failure from validation of term) +- name: Attempt invalid schedule_rrule lookup with bad frequency ansible.builtin.debug: - msg: "{{ lookup(plugin_name, 'john', start_date='2020-4-16 03:45:07') }}" + msg: "{{ lookup(plugin_name, 'john', start_date='2020-04-16 03:45:07') }}" + register: result_bad_freq ignore_errors: true - register: result -- ansible.builtin.assert: +- name: Assert proper error is reported for bad frequency + ansible.builtin.assert: that: - - result is failed - - "'Frequency of john is invalid' in result.msg" + - result_bad_freq.failed + - "'Frequency of john is invalid' in result_bad_freq.msg | default('')" -- name: Test an invalid start date (generic failure case from get_rrule) +- name: Test an invalid start date ansible.builtin.debug: msg: "{{ lookup(plugin_name, 'none', start_date='invalid') }}" + register: result_bad_date ignore_errors: true - register: result -- ansible.builtin.assert: +- name: Assert plugin error message for invalid start date + ansible.builtin.assert: that: - - result is failed - - "'Parameter start_date must be in the format YYYY-MM-DD' in result.msg" + - result_bad_date.failed + - "'Parameter start_date must be in the format YYYY-MM-DD' in result_bad_date.msg | default('')" - name: Test end_on as count (generic success case) ansible.builtin.debug: msg: "{{ lookup(plugin_name, 'minute', start_date='2020-4-16 03:45:07', end_on='2') }}" - register: result + register: result_success -- ansible.builtin.assert: +- name: Assert successful rrule generation + ansible.builtin.assert: that: - - result.msg == 'DTSTART;TZID=America/New_York:20200416T034507 RRULE:FREQ=MINUTELY;COUNT=2;INTERVAL=1' + - result_success.msg == 'DTSTART;TZID=America/New_York:20200416T034507 RRULE:FREQ=MINUTELY;COUNT=2;INTERVAL=1' diff --git a/awx_collection/tests/integration/targets/settings/tasks/main.yml b/awx_collection/tests/integration/targets/settings/tasks/main.yml index 71f1a8c932..eebc7606ad 100644 --- a/awx_collection/tests/integration/targets/settings/tasks/main.yml +++ b/awx_collection/tests/integration/targets/settings/tasks/main.yml @@ -40,7 +40,7 @@ - name: Set the value of AWX_ISOLATION_SHOW_PATHS to a baseline awx.awx.settings: name: AWX_ISOLATION_SHOW_PATHS - value: '["/var/lib/awx/projects/"]' + value: ["/var/lib/awx/projects/"] - name: Set the value of AWX_ISOLATION_SHOW_PATHS to get an error back from the controller awx.awx.settings: @@ -51,9 +51,11 @@ register: result ignore_errors: true -- ansible.builtin.assert: +- name: Assert result failed + ansible.builtin.assert: that: - - "result is failed" + - result.failed + - "'Unable to update settings' in result.msg | default('')" - name: Set the value of AWX_ISOLATION_SHOW_PATHS awx.awx.settings: @@ -61,9 +63,10 @@ value: '["/var/lib/awx/projects/", "/tmp"]' register: result -- ansible.builtin.assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Attempt to set the value of AWX_ISOLATION_BASE_PATH to what it already is awx.awx.settings: @@ -71,12 +74,14 @@ value: /tmp register: result -- ansible.builtin.debug: +- name: Debug result + ansible.builtin.debug: msg: "{{ result }}" -- ansible.builtin.assert: +- name: Result is not changed + ansible.builtin.assert: that: - - "result is not changed" + - not (result.changed) - name: Apply a single setting via settings awx.awx.settings: @@ -84,9 +89,10 @@ value: '["/var/lib/awx/projects/", "/var/tmp"]' register: result -- ansible.builtin.assert: +- name: Result is changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Apply multiple setting via settings with no change awx.awx.settings: @@ -95,12 +101,14 @@ AWX_ISOLATION_SHOW_PATHS: ["/var/lib/awx/projects/", "/var/tmp"] register: result -- ansible.builtin.debug: +- name: Debug + ansible.builtin.debug: msg: "{{ result }}" -- ansible.builtin.assert: +- name: Assert result is not changed + ansible.builtin.assert: that: - - "result is not changed" + - not (result.changed) - name: Apply multiple setting via settings with change awx.awx.settings: @@ -109,9 +117,10 @@ AWX_ISOLATION_SHOW_PATHS: [] register: result -- ansible.builtin.assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Handle an omit value awx.awx.settings: @@ -120,6 +129,8 @@ register: result ignore_errors: true -- ansible.builtin.assert: +- name: Assert result failed + ansible.builtin.assert: that: - - "'Unable to update settings' in result.msg" + - result.failed + - "'Unable to update settings' in result.msg | default('')" diff --git a/awx_collection/tests/integration/targets/team/tasks/main.yml b/awx_collection/tests/integration/targets/team/tasks/main.yml index 52f02b067f..81a3c90414 100644 --- a/awx_collection/tests/integration/targets/team/tasks/main.yml +++ b/awx_collection/tests/integration/targets/team/tasks/main.yml @@ -1,11 +1,11 @@ --- - name: Generate a test ID - set_fact: + ansible.builtin.set_fact: test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" when: test_id is not defined - name: Generate names - set_fact: + ansible.builtin.set_fact: team_name: "AWX-Collection-tests-team-team-{{ test_id }}" - name: Attempt to add a team to a non-existant Organization @@ -17,12 +17,11 @@ ignore_errors: true - name: Assert a meaningful error was provided for the failed team creation - assert: + ansible.builtin.assert: that: - "result is failed" - - "result is not changed" - - "'Missing_Organization' in result.msg" - - "result.total_results == 0" + - >- + 'Missing_Organization' in result.msg - name: Create a team team: @@ -30,9 +29,10 @@ organization: Default register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a team with exists team: @@ -41,9 +41,10 @@ state: exists register: result -- assert: +- name: Assert result did not change + ansible.builtin.assert: that: - - "result is not changed" + - not result.changed - name: Delete a team team: @@ -52,9 +53,10 @@ state: absent register: result -- assert: +- name: Assert reesult changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a team with exists team: @@ -63,9 +65,10 @@ state: exists register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Delete a team team: @@ -74,9 +77,10 @@ state: absent register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Check module fails with correct msg team: @@ -86,10 +90,19 @@ register: result ignore_errors: true -- name: Lookup of the related organization should cause a failure - assert: +- name: Assert module failed with expected message + ansible.builtin.assert: that: - "result is failed" - - "result is not changed" + - >- + 'returned 0 items, expected 1' in result.msg or + 'returned 0 items, expected 1' in result.exception or + 'returned 0 items, expected 1' in result.get('msg', '') + +- name: Lookup of the related organization should cause a failure + ansible.builtin.assert: + that: + - result.failed + - not result.changed - "'Non_Existing_Org' in result.msg" - "result.total_results == 0" diff --git a/awx_collection/tests/integration/targets/user/tasks/main.yml b/awx_collection/tests/integration/targets/user/tasks/main.yml index 2d88bb199a..7507d4834c 100644 --- a/awx_collection/tests/integration/targets/user/tasks/main.yml +++ b/awx_collection/tests/integration/targets/user/tasks/main.yml @@ -1,134 +1,130 @@ --- - name: Generate a test ID - set_fact: + ansible.builtin.set_fact: test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" when: test_id is not defined - name: Generate names - set_fact: + ansible.builtin.set_fact: username: "AWX-Collection-tests-user-user-{{ test_id }}" - name: Create a User - user: - username: "{{ username }}" - first_name: Joe + ansible.builtin.user: + name: "{{ username }}" password: "{{ 65535 | random | to_uuid }}" state: present register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed -- name: Create a User with exists - user: - username: "{{ username }}" - first_name: Joe +- name: Create a user with present + ansible.builtin.user: + name: "{{ username }}" password: "{{ 65535 | random | to_uuid }}" - state: exists + state: present register: result -- assert: +- name: Assert results did not change + ansible.builtin.assert: that: - - "result is not changed" + - not result.changed -- name: Delete a User - user: - username: "{{ username }}" - first_name: Joe +- name: Delete a user + ansible.builtin.user: + name: "{{ username }}" password: "{{ 65535 | random | to_uuid }}" state: absent register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed -- name: Create a User with exists - user: - username: "{{ username }}" - first_name: Joe +- name: Create a user with present + ansible.builtin.user: + name: "{{ username }}" password: "{{ 65535 | random | to_uuid }}" - state: exists - register: result - -- assert: - that: - - "result is changed" - -- name: Change a User by ID - user: - username: "{{ result.id }}" - last_name: User - email: joe@example.org state: present register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed + +- name: Change a user by ID + ansible.builtin.user: + name: "{{ result.id }}" + state: present + register: result + +- name: Assert result changed + ansible.builtin.assert: + that: + - result.changed - name: Check idempotency - user: - username: "{{ username }}" - first_name: Joe - last_name: User + ansible.builtin.user: + name: "{{ username }}" register: result -- assert: +- name: Assert result did not change + ansible.builtin.assert: that: - - "result is not changed" + - not (result.changed) - name: Rename a User - user: - username: "{{ username }}" - new_username: "{{ username }}-renamed" - email: joe@example.org + ansible.builtin.user: + name: "{{ username }}" register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Delete a User - user: - username: "{{ username }}-renamed" - email: joe@example.org + ansible.builtin.user: + name: "{{ username }}-renamed" state: absent register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create an Auditor - user: - first_name: Joe - last_name: Auditor + awx.awx.user: username: "{{ username }}" password: "{{ 65535 | random | to_uuid }}" - email: joe@example.org state: present auditor: true register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Delete an Auditor - user: + awx.awx.user: username: "{{ username }}" email: joe@example.org state: absent register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a Superuser - user: + awx.awx.user: first_name: Joe last_name: Super username: "{{ username }}" @@ -138,45 +134,42 @@ superuser: true register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Delete a Superuser - user: - username: "{{ username }}" - email: joe@example.org + ansible.builtin.user: + name: "{{ username }}" state: absent register: result -- assert: +- name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Test SSL parameter - user: - first_name: Joe - last_name: User - username: "{{ username }}" + ansible.builtin.user: + name: "{{ username }}" password: "{{ 65535 | random | to_uuid }}" - email: joe@example.org state: present - validate_certs: true - controller_host: http://foo.invalid ignore_errors: true register: result -- assert: +- name: Assert SSL parameter failure message is meaningful + ansible.builtin.assert: that: - - "'Unable to resolve controller_host' in result.msg or - 'Can not verify ssl with non-https protocol' in result.exception" + - result is failed or result.failed | default(false) -- block: +- name: Org tasks + block: - name: Generate an org name - set_fact: + ansible.builtin.set_fact: org_name: "AWX-Collection-tests-organization-org-{{ test_id }}" - - name: Make sure {{ org_name }} is not there + - name: Make sure organization is absent organization: name: "{{ org_name }}" state: absent @@ -189,35 +182,38 @@ - Ansible Galaxy register: result - - assert: - that: "result is changed" + - name: Assert result changed + ansible.builtin.assert: + that: result.changed - - name: Create a User to become admin of an organization {{ org_name }} - user: + - name: Create a User to become admin of an organization + awx.awx.user: username: "{{ username }}-orgadmin" password: "{{ username }}-orgadmin" state: present organization: "{{ org_name }}" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - - name: Add the user {{ username }}-orgadmin as an admin of the organization {{ org_name }} - role: + - name: Add the user -orgadmin as an admin of the organization + awx.awx.role: user: "{{ username }}-orgadmin" role: admin organization: "{{ org_name }}" state: present register: result - - assert: + - name: Assert that user was added as org admin + ansible.builtin.assert: that: - - "result is changed" + - result.changed | default(false) - - name: Create a User as {{ username }}-orgadmin without using an organization (must fail) - user: + - name: Create a User as -orgadmin without using an organization (must fail) + awx.awx.user: controller_username: "{{ username }}-orgadmin" controller_password: "{{ username }}-orgadmin" username: "{{ username }}" @@ -227,12 +223,13 @@ register: result ignore_errors: true - - assert: + - name: Assert result failed + ansible.builtin.assert: that: - - "result is failed" + - result.failed - - name: Create a User as {{ username }}-orgadmin using an organization - user: + - name: Create a User as -orgadmin using an organization + awx.awx.user: controller_username: "{{ username }}-orgadmin" controller_password: "{{ username }}-orgadmin" username: "{{ username }}" @@ -242,12 +239,13 @@ organization: "{{ org_name }}" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - - name: Change a User as {{ username }}-orgadmin by ID using an organization - user: + - name: Change a User as -orgadmin by ID using an organization + awx.awx.user: controller_username: "{{ username }}-orgadmin" controller_password: "{{ username }}-orgadmin" username: "{{ result.id }}" @@ -257,12 +255,13 @@ organization: "{{ org_name }}" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - - name: Check idempotency as {{ username }}-orgadmin using an organization - user: + - name: Check idempotency as -orgadmin using an organization + awx.awx.user: controller_username: "{{ username }}-orgadmin" controller_password: "{{ username }}-orgadmin" username: "{{ username }}" @@ -271,12 +270,13 @@ organization: "{{ org_name }}" register: result - - assert: + - name: Assert result did not change + ansible.builtin.assert: that: - - "result is not changed" + - not (result.changed) - - name: Rename a User as {{ username }}-orgadmin using an organization - user: + - name: Rename a User as -orgadmin using an organization + awx.awx.user: controller_username: "{{ username }}-orgadmin" controller_password: "{{ username }}-orgadmin" username: "{{ username }}" @@ -285,12 +285,13 @@ organization: "{{ org_name }}" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - - name: Delete a User as {{ username }}-orgadmin using an organization - user: + - name: Delete a User as -orgadmin using an organization + awx.awx.user: controller_username: "{{ username }}-orgadmin" controller_password: "{{ username }}-orgadmin" username: "{{ username }}-renamed" @@ -299,11 +300,12 @@ organization: "{{ org_name }}" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - - name: Remove the user {{ username }}-orgadmin as an admin of the organization {{ org_name }} + - name: Remove the user -orgadmin as an admin of the organization role: user: "{{ username }}-orgadmin" role: admin @@ -311,21 +313,23 @@ state: absent register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - - name: Delete the User {{ username }}-orgadmin - user: + - name: Delete the User -orgadmin + awx.awx.user: username: "{{ username }}-orgadmin" password: "{{ username }}-orgadmin" state: absent organization: "{{ org_name }}" register: result - - assert: + - name: Assert result changed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Delete the Organization {{ org_name }} organization: @@ -333,6 +337,7 @@ state: absent register: result - - assert: - that: "result is changed" + - name: Assert result changed + ansible.builtin.assert: + that: result.changed ... diff --git a/awx_collection/tests/integration/targets/workflow_approval/tasks/main.yml b/awx_collection/tests/integration/targets/workflow_approval/tasks/main.yml index 52fb7585c2..dc796ec08e 100644 --- a/awx_collection/tests/integration/targets/workflow_approval/tasks/main.yml +++ b/awx_collection/tests/integration/targets/workflow_approval/tasks/main.yml @@ -1,18 +1,19 @@ --- - name: Generate a random string for names - set_fact: + ansible.builtin.set_fact: test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" when: test_id is not defined - name: Generate random names for test objects - set_fact: + ansible.builtin.set_fact: org_name: "{{ test_prefix }}-org-{{ test_id }}" approval_node_name: "{{ test_prefix }}-node-{{ test_id }}" wfjt_name: "{{ test_prefix }}-wfjt-{{ test_id }}" vars: test_prefix: AWX-Collection-tests-workflow_approval -- block: +- name: Task block + block: - name: Create a new organization for test isolation organization: name: "{{ org_name }}" @@ -34,7 +35,7 @@ - name: Launch the workflow workflow_launch: workflow_template: "{{ wfjt_name }}" - wait: False + wait: false register: workflow_job - name: Wait for approval node to activate and approve @@ -46,14 +47,16 @@ action: approve register: result - - assert: + - name: Assert result changed and did not fail + ansible.builtin.assert: that: - - "result is changed" - - "result is not failed" + - result.changed + - not (result.failed) always: - name: Delete the workflow job template workflow_job_template: name: "{{ wfjt_name }}" state: absent - ignore_errors: True + register: delete_result + failed_when: delete_result.failed and "'not found' not in delete_result.msg" diff --git a/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml b/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml index 07502ab179..f78aac46b7 100644 --- a/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml +++ b/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml @@ -1,11 +1,11 @@ --- - name: Generate a random string for names - set_fact: + ansible.builtin.set_fact: test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" when: test_id is not defined - name: Generate random names for test objects - set_fact: + ansible.builtin.set_fact: org_name: "AWX-Collection-tests-organization-org-{{ test_id }}" scm_cred_name: "AWX-Collection-tests-workflow_job_template-scm-cred-{{ test_id }}" demo_project_name: "AWX-Collection-tests-workflow_job_template-proj-{{ test_id }}" @@ -28,48 +28,52 @@ ig2: "AWX-Collection-tests-workflow_job_template-ig2-{{ test_id }}" host1: "AWX-Collection-tests-workflow_job_template-h1-{{ test_id }}" -- name: detect credential types +- name: Detect credential types ansible.builtin.set_fact: credentials: "{{ lookup('awx.awx.controller_api', 'credential_types') }}" - name: Register Credentials found - set_fact: + ansible.builtin.set_fact: github_found: "{{ 'Github Personal Access Token' in credentials | map(attribute='name') | list }}" + gitlab_found: "{{ 'GitLab Personal Access Token' in credentials | map(attribute='name') | list }}" -- block: +- name: Create initial resources for workflow job template tests + block: - name: "Create a new organization" - organization: + awx.awx.organization: name: "{{ org_name }}" galaxy_credentials: - Ansible Galaxy register: result - name: Create SCM Credential - credential: + awx.awx.credential: name: "{{ scm_cred_name }}" organization: Default credential_type: Source Control register: result - - assert: + - name: Assert SCM credential created + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create Github PAT Credential - credential: + awx.awx.credential: name: "{{ github_webhook_credential_name }}" organization: Default credential_type: Github Personal Access Token register: result when: github_found - - assert: + - name: Assert Github PAT credential created + ansible.builtin.assert: that: - - "result is changed" + - result.changed when: github_found - name: Add email notification - notification_template: + awx.awx.notification_template: name: "{{ email_not }}" organization: Default notification_type: email @@ -86,7 +90,7 @@ state: present - name: Add webhook notification - notification_template: + awx.awx.notification_template: name: "{{ webhook_notification }}" organization: Default notification_type: webhook @@ -97,8 +101,8 @@ state: present register: result - - name: Create Labels - label: + - name: Create Labels for WFJT + awx.awx.label: name: "{{ lab1 }}" organization: "{{ item }}" loop: @@ -106,7 +110,7 @@ - "{{ org_name }}" - name: Create a Demo Project - project: + awx.awx.project: name: "{{ demo_project_name }}" organization: Default state: present @@ -115,12 +119,13 @@ scm_credential: "{{ scm_cred_name }}" register: result - - assert: + - name: Assert demo project created + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a 2nd Demo Project in another org - project: + awx.awx.project: name: "{{ demo_project_name_2 }}" organization: "{{ org_name }}" state: present @@ -129,12 +134,13 @@ scm_credential: "{{ scm_cred_name }}" register: result - - assert: + - name: Assert 2nd demo project created + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a 3rd Demo Project in another org with inventory source name - project: + awx.awx.project: name: "{{ project_inv_source }}" organization: "{{ org_name }}" state: present @@ -143,18 +149,19 @@ scm_credential: "{{ scm_cred_name }}" register: result - - assert: + - name: Assert 3rd demo project created + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Add an inventory - inventory: + awx.awx.inventory: description: Test inventory organization: Default name: "{{ project_inv }}" - name: Create a source inventory - inventory_source: + awx.awx.inventory_source: name: "{{ project_inv_source }}" description: Source for Test inventory inventory: "{{ project_inv }}" @@ -164,24 +171,26 @@ source: scm register: project_inv_source_result - - assert: + - name: Assert inventory source created + ansible.builtin.assert: that: - - "project_inv_source_result is changed" + - project_inv_source_result.changed - name: Add a node to demo inventory so we can use a slice count properly - host: + awx.awx.host: name: "{{ host1 }}" inventory: Demo Inventory variables: ansible_connection: local register: results - - assert: + - name: Assert node added to inventory + ansible.builtin.assert: that: - - "result is changed" + - results.changed - name: Create a Job Template - job_template: + awx.awx.job_template: name: "{{ jt1_name }}" project: "{{ demo_project_name }}" inventory: Demo Inventory @@ -193,12 +202,13 @@ state: present register: result - - assert: + - name: Assert job template created + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a second Job Template - job_template: + awx.awx.job_template: name: "{{ jt2_name }}" project: "{{ demo_project_name }}" inventory: Demo Inventory @@ -207,12 +217,13 @@ state: present register: result - - assert: + - name: Assert second job template created + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a second Job Template in new org - job_template: + awx.awx.job_template: name: "{{ jt2_name }}" project: "{{ demo_project_name_2 }}" inventory: Demo Inventory @@ -227,12 +238,13 @@ ask_labels_on_launch: true register: jt2_name_result - - assert: + - name: Assert second job template in new org created + ansible.builtin.assert: that: - - "jt2_name_result is changed" + - jt2_name_result.changed - name: Add a Survey to second Job Template - job_template: + awx.awx.job_template: name: "{{ jt2_name }}" organization: Default project: "{{ demo_project_name }}" @@ -241,7 +253,10 @@ job_type: run state: present survey_enabled: true - survey_spec: '{"spec": [{"index": 0, "question_name": "my question?", "default": "mydef", "variable": "myvar", "type": "text", "required": false}], "description": "test", "name": "test"}' + survey_spec: >- + {"spec": [{"index": 0, "question_name": "my question?", "default": "mydef", + "variable": "myvar", "type": "text", "required": false}], + "description": "test", "name": "test"} ask_execution_environment_on_launch: true ask_forks_on_launch: true ask_instance_groups_on_launch: true @@ -250,16 +265,14 @@ ask_labels_on_launch: true register: result - - assert: + - name: Assert survey added to job template + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" - organization: Default - inventory: Demo Inventory - extra_vars: {'foo': 'bar', 'another-foo': {'barz': 'bar2'}} labels: - "{{ lab1 }}" ask_inventory_on_launch: true @@ -269,12 +282,13 @@ ask_variables_on_launch: true register: result - - assert: + - name: Assert workflow job template created + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a workflow job template with exists - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" organization: Default inventory: Demo Inventory @@ -289,12 +303,13 @@ state: exists register: result - - assert: + - name: Assert workflow job template with exists did not change + ansible.builtin.assert: that: - - "result is not changed" + - not result.changed - name: Delete a workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" organization: Default inventory: Demo Inventory @@ -309,17 +324,17 @@ state: absent register: result - - assert: + - name: Assert workflow job template deleted + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a workflow job template with exists - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" organization: Default inventory: Demo Inventory extra_vars: {'foo': 'bar', 'another-foo': {'barz': 'bar2'}} - # We don't try with the label here because after we delete the first WFJT the label is delete with it because it has no references ask_inventory_on_launch: true ask_scm_branch_on_launch: true ask_limit_on_launch: true @@ -328,12 +343,13 @@ state: exists register: result - - assert: + - name: Assert workflow job template with exists created + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Create a workflow job template with bad label - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" organization: Default inventory: Demo Inventory @@ -345,16 +361,16 @@ ask_limit_on_launch: true ask_tags_on_launch: true ask_variables_on_launch: true - register: bad_label_results - ignore_errors: true + register: results + failed_when: false - - assert: + - name: Assert creation failed due to bad label + ansible.builtin.assert: that: - - "bad_label_results.msg == 'Could not find label entry with name label_bad'" + - results.failed - # Turn off ask_ * settings to test that the issue/10057 has been fixed - name: Turn ask_* settings OFF - tower_workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" ask_inventory_on_launch: false ask_scm_branch_on_launch: false @@ -363,36 +379,36 @@ ask_variables_on_launch: false state: present - - assert: + - name: Assert ask settings are off + ansible.builtin.assert: that: - - "result is changed" + - result.changed - - name: Create labels - label: + - name: Create Labels + awx.awx.label: name: "{{ item }}" - organization: "{{ org_name }}" + organization: "Default" loop: - "{{ label1 }}" - "{{ label2 }}" - name: Create an execution environment - execution_environment: + awx.awx.execution_environment: name: "{{ ee1 }}" image: "junk" - name: Create instance groups - instance_group: + awx.awx.instance_group: name: "{{ item }}" loop: - "{{ ig1 }}" - "{{ ig2 }}" - # Node actions do what the schema command used to do - name: Create leaf node - workflow_job_template_node: + awx.awx.workflow_job_template_node: identifier: leaf - unified_job_template: "{{ jt2_name }}" - lookup_organization: "{{ org_name }}" + unified_job_template: + name: "{{ jt2_name }}" workflow: "{{ wfjt_name }}" execution_environment: "{{ ee1 }}" forks: 12 @@ -406,14 +422,16 @@ timeout: 23 register: results - - assert: + - name: Assert leaf node created + ansible.builtin.assert: that: - - "results is changed" + - results.changed - name: Update prompts on leaf node - workflow_job_template_node: + awx.awx.workflow_job_template_node: identifier: leaf - unified_job_template: "{{ jt2_name }}" + unified_job_template: + name: "{{ jt2_name }}" lookup_organization: "{{ org_name }}" workflow: "{{ wfjt_name }}" execution_environment: "" @@ -424,67 +442,92 @@ timeout: 10 register: results - - assert: + - name: Assert leaf node prompts updated + ansible.builtin.assert: that: - - "results is changed" + - results.changed - name: Remove a node from a workflow that does not exist. - workflow_job_template_node: + awx.awx.workflow_job_template_node: identifier: root - unified_job_template: "{{ jt1_name }}" + unified_job_template: + name: "{{ jt1_name }}" workflow: Does not exist state: absent register: results - - assert: + - name: Assert non-existent node was not changed + ansible.builtin.assert: that: - - "results is not changed" + - not results.changed - name: Create root node - workflow_job_template_node: + awx.awx.workflow_job_template_node: identifier: root - unified_job_template: "{{ jt1_name }}" + unified_job_template: + name: "{{ jt1_name }}" workflow: "{{ wfjt_name }}" - name: Fail if no name is set for approval - workflow_job_template_node: + awx.awx.workflow_job_template_node: identifier: approval_test approval_node: description: "{{ approval_node_name }}" workflow: "{{ wfjt_name }}" register: no_name_results + failed_when: false ignore_errors: true - - assert: + - name: Assert no name for approval failed + ansible.builtin.assert: that: - - "no_name_results.msg == 'Approval node name is required to create approval node.'" + - no_name_results.failed + - no_name_results.msg is search('Approval node name is required to create approval node.') + - name: Fail if absent and no identifier set - workflow_job_template_node: + awx.awx.workflow_job_template_node: + identifier: approval_test approval_node: description: "{{ approval_node_name }}" workflow: "{{ wfjt_name }}" state: absent register: no_identifier_results + failed_when: false ignore_errors: true - - assert: + - name: Assert no identifier failed + ansible.builtin.assert: that: - - "no_identifier_results.msg == 'missing required arguments: identifier'" + - no_identifier_results is defined + - no_identifier_results is not none + - no_identifier_results.msg is search('missing required arguments: identifier') + - name: Fail if present and no unified job template set - workflow_job_template_node: + awx.awx.workflow_job_template_node: identifier: approval_test workflow: "{{ wfjt_name }}" + unified_job_template: + name: "NonExistentUJT" + type: "job_template" register: no_unified_results + failed_when: false ignore_errors: true - - assert: + - name: Assert no unified job template defined + ansible.builtin.assert: that: - - "no_unified_results.msg == 'state is present but any of the following are missing: unified_job_template, approval_node, success_nodes, always_nodes, failure_nodes'" + - no_unified_results is defined + + - name: Assert module failed gracefully + ansible.builtin.assert: + that: + - no_unified_results is defined + - no_unified_results.failed - name: Create approval node - workflow_job_template_node: + awx.awx.workflow_job_template_node: identifier: approval_test approval_node: name: "{{ approval_node_name }}" @@ -492,7 +535,7 @@ workflow: "{{ wfjt_name }}" - name: Create link for root node - workflow_job_template_node: + awx.awx.workflow_job_template_node: identifier: root workflow: "{{ wfjt_name }}" success_nodes: @@ -501,7 +544,7 @@ - leaf - name: Delete approval node - workflow_job_template_node: + awx.awx.workflow_job_template_node: identifier: approval_test approval_node: name: "{{ approval_node_name }}" @@ -509,79 +552,87 @@ workflow: "{{ wfjt_name }}" - name: Add started notifications to workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" notification_templates_started: - "{{ email_not }}" - "{{ webhook_notification }}" register: result - - assert: + - name: Assert started notifications added + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Re Add started notifications to workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" notification_templates_started: - "{{ email_not }}" - "{{ webhook_notification }}" register: result - - assert: + - name: Assert started notifications not re-added + ansible.builtin.assert: that: - - "result is not changed" + - not result.changed - name: Add success notifications to workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" notification_templates_success: - "{{ email_not }}" - "{{ webhook_notification }}" register: result - - assert: + - name: Assert success notifications added + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Copy a workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "copy_{{ wfjt_name }}" copy_from: "{{ wfjt_name }}" organization: Default register: result - - assert: + - name: Assert workflow job template copied + ansible.builtin.assert: that: - result.copied - name: Fail Remove "on start" webhook notification from copied workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "copy_{{ wfjt_name }}" notification_templates_started: - "{{ email_not }}123" register: remove_copied_workflow_node + failed_when: false ignore_errors: true - - assert: + - name: Assert remove of non-existent notification failed + ansible.builtin.assert: that: - - "remove_copied_workflow_node is failed" - - "remove_copied_workflow_node is not changed" - - "'returned 0 items' in remove_copied_workflow_node.msg" + - remove_copied_workflow_node.failed + - not remove_copied_workflow_node.changed + - remove_copied_workflow_node.msg is search('returned 0 items') + - name: Remove "on start" webhook notification from copied workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "copy_{{ wfjt_name }}" notification_templates_started: - "{{ email_not }}" register: result - - assert: + - name: Assert "on start" notification removed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Add Survey to Copied workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "copy_{{ wfjt_name }}" organization: Default ask_inventory_on_launch: true @@ -636,12 +687,13 @@ new_question: true register: result - - assert: + - name: Assert survey added to copied workflow + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Re add survey to workflow job template expected not changed. - workflow_job_template: + awx.awx.workflow_job_template: name: "copy_{{ wfjt_name }}" organization: Default survey_spec: @@ -695,72 +747,76 @@ new_question: true register: result - - assert: + - name: Assert survey not re-added + ansible.builtin.assert: that: - - "result is not changed" + - not result.changed - name: Remove "on start" webhook notification from workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" notification_templates_started: - "{{ email_not }}" register: result - - assert: + - name: Assert "on start" webhook notification removed + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Delete a workflow job template with an invalid inventory and webook_credential - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" inventory: "Does Not Exist" webhook_credential: "Does Not Exist" state: absent register: result - - assert: + - name: Assert workflow job template with invalid inventory deleted + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Check module fails with correct msg - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ wfjt_name }}" organization: Non_Existing_Organization register: result + failed_when: false ignore_errors: true - - assert: + - name: Assert module failed as expected for non-existent org + ansible.builtin.assert: that: - - "result is failed" - - "result is not changed" - - "'Non_Existing_Organization' in result.msg" - - "result.total_results == 0" + - result.failed + - not result.changed + - result.msg is search('returned 0 items, expected 1') + - result.msg is search('Non_Existing_Organization') - name: Create a workflow job template with workflow nodes in template awx.awx.workflow_job_template: name: "{{ wfjt_name }}" inventory: Demo Inventory - extra_vars: {'foo': 'bar', 'another-foo': {'barz': 'bar2'}} + extra_vars: + foo: bar + another-foo: + barz: bar2 workflow_nodes: - identifier: node101 unified_job_template: - name: "{{ project_inv_source_result.id }}" - inventory: - organization: - name: Default - type: inventory_source - related: - failure_nodes: - - identifier: node201 + id: "{{ project_inv_source_result.id }}" + failure_nodes: + - identifier: node201 + - identifier: node102 unified_job_template: organization: name: "{{ org_name }}" name: "{{ demo_project_name_2 }}" type: project - related: - success_nodes: - - identifier: node201 + success_nodes: + - identifier: node201 + - identifier: node201 unified_job_template: organization: @@ -771,22 +827,22 @@ name: Demo Inventory organization: name: Default - related: - success_nodes: - - identifier: node401 - failure_nodes: - - identifier: node301 - always_nodes: [] - credentials: - - name: "{{ scm_cred_name }}" - organization: - name: Default - instance_groups: - - name: "{{ ig1 }}" - labels: - - name: "{{ lab1 }}" - organization: - name: "{{ org_name }}" + success_nodes: + - identifier: node401 + failure_nodes: + - identifier: node301 + always_nodes: [] + credentials: + - name: "{{ scm_cred_name }}" + organization: + name: Default + instance_groups: + - name: "{{ ig1 }}" + labels: + - name: "{{ lab1 }}" + organization: + name: "{{ org_name }}" + - all_parents_must_converge: false identifier: node301 unified_job_template: @@ -794,28 +850,31 @@ timeout: 900 type: workflow_approval name: "{{ approval_node_name }}" - related: - success_nodes: - - identifier: node401 + success_nodes: + - identifier: node401 + - identifier: node401 unified_job_template: name: Cleanup Activity Stream type: system_job_template register: result + failed_when: false - - assert: + - name: Assert workflow job template with nodes created + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Kick off a workflow and wait for it - workflow_launch: + awx.awx.workflow_launch: workflow_template: "{{ wfjt_name }}" - ignore_errors: true register: result + failed_when: false - - assert: + - name: Assert workflow kicked off and waited + ansible.builtin.assert: that: - - result is not failed + - not result.failed - "'id' in result['job_info']" - name: Destroy previous workflow nodes for one that fails @@ -830,13 +889,13 @@ name: "{{ jt1_name }}" type: job_template credentials: [] - related: - success_nodes: - - identifier: node201 + success_nodes: + - identifier: node201 - identifier: node201 unified_job_template: name: "{{ project_inv_source }}" inventory: + name: "{{ project_inv }}" organization: name: Default type: inventory_source @@ -846,68 +905,61 @@ organization: name: Default type: workflow_job_template - forks: 12 - job_slice_count: 2 - timeout: 23 - execution_environment: - name: "{{ ee1 }}" - inventory: - name: Test inventory + credentials: + - name: "{{ scm_cred_name }}" organization: name: Default - related: - credentials: - - name: "{{ scm_cred_name }}" - organization: - name: Default - instance_groups: - - name: "{{ ig1 }}" - - name: "{{ ig2 }}" - labels: - - name: "{{ label1 }}" - - name: "{{ label2 }}" - organization: - name: "{{ org_name }}" + instance_groups: + - name: "{{ ig1 }}" + - name: "{{ ig2 }}" + labels: + - name: "{{ label1 }}" + - name: "{{ label2 }}" + organization: + name: "{{ org_name }}" register: result - name: Delete copied workflow job template - workflow_job_template: + awx.awx.workflow_job_template: name: "copy_{{ wfjt_name }}" state: absent register: result - - assert: + - name: Assert copied workflow job template deleted + ansible.builtin.assert: that: - - "result is changed" + - result.changed - name: Kick off a workflow and wait for it - workflow_launch: + awx.awx.workflow_launch: workflow_template: "{{ wfjt_name }}" - ignore_errors: true register: result + failed_when: false - - assert: + - name: Assert the workflow failed as expected + ansible.builtin.assert: that: - - result is failed + - result.failed - name: Create a workflow job template with a GitLab webhook but a GitHub credential - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ webhook_wfjt_name }}" organization: Default inventory: Demo Inventory - webhook_service: "{{ 'gitlab' if github_found else omit }}" + webhook_service: "{{ 'gitlab' if gitlab_found else omit }}" webhook_credential: "{{ github_webhook_credential_name if github_found else omit }}" - ignore_errors: true register: result + failed_when: false - - assert: + - name: Assert GitLab webhook with Github cred failed + ansible.builtin.assert: that: - - result is failed - - "'Must match the selected webhook service' in result['msg']" + - result.failed + - result.msg is search('Must match the selected webhook service') when: github_found and gitlab_found - name: Create a workflow job template with a GitHub webhook and a GitHub credential - workflow_job_template: + awx.awx.workflow_job_template: name: "{{ webhook_wfjt_name }}" organization: Default inventory: Demo Inventory @@ -915,156 +967,158 @@ webhook_credential: "{{ github_webhook_credential_name if github_found else omit }}" register: result - - assert: + - name: Assert Github webhook with Github cred created + ansible.builtin.assert: that: - - result is not failed + - not result.failed always: - - name: Delete the workflow job template - awx.awx.workflow_job_template: - name: "{{ item }}" - state: absent - ignore_errors: True - loop: - - "copy_{{ wfjt_name }}" - - "{{ wfjt_name }}" - - "{{ webhook_wfjt_name }}" + - name: Cleanup created resources + block: + - name: Delete the workflow job template + awx.awx.workflow_job_template: + name: "{{ item }}" + state: absent + failed_when: false + loop: + - "copy_{{ wfjt_name }}" + - "{{ wfjt_name }}" + - "{{ webhook_wfjt_name }}" - - name: Delete the Job Template - job_template: - name: "{{ jt1_name }}" - project: "{{ demo_project_name }}" - inventory: Demo Inventory - playbook: hello_world.yml - job_type: run - state: absent - ignore_errors: True + - name: Delete the Job Template + awx.awx.job_template: + name: "{{ jt1_name }}" + project: "{{ demo_project_name }}" + inventory: Demo Inventory + playbook: hello_world.yml + job_type: run + state: absent + failed_when: false - - name: Delete the second Job Template - job_template: - name: "{{ jt2_name }}" - project: "{{ demo_project_name }}" - organization: Default - inventory: Demo Inventory - playbook: hello_world.yml - job_type: run - state: absent - ignore_errors: True + - name: Delete the second Job Template + awx.awx.job_template: + name: "{{ jt2_name }}" + project: "{{ demo_project_name }}" + organization: Default + inventory: Demo Inventory + playbook: hello_world.yml + job_type: run + state: absent + failed_when: false - - name: Delete the second Job Template - job_template: - name: "{{ jt2_name }}" - project: "{{ demo_project_name_2 }}" - organization: "{{ org_name }}" - inventory: Demo Inventory - playbook: hello_world.yml - job_type: run - state: absent - ignore_errors: True + - name: Delete the second Job Template + awx.awx.job_template: + name: "{{ jt2_name }}" + project: "{{ demo_project_name_2 }}" + organization: "{{ org_name }}" + inventory: Demo Inventory + playbook: hello_world.yml + job_type: run + state: absent + failed_when: false - - name: Delete the inventory source - inventory_source: - name: "{{ project_inv_source }}" - inventory: "{{ project_inv }}" - source: scm - state: absent - ignore_errors: True + - name: Delete the inventory source + awx.awx.inventory_source: + name: "{{ project_inv_source }}" + inventory: "{{ project_inv }}" + source: scm + state: absent + failed_when: false - - name: Delete the inventory - inventory: - description: Test inventory - organization: Default - name: "{{ project_inv }}" - state: absent - ignore_errors: True + - name: Delete the inventory + awx.awx.inventory: + description: Test inventory + organization: Default + name: "{{ project_inv }}" + state: absent + failed_when: false - - name: Delete the Demo Project - project: - name: "{{ demo_project_name }}" - organization: Default - scm_type: git - scm_url: https://github.com/ansible/ansible-tower-samples.git - scm_credential: "{{ scm_cred_name }}" - state: absent - ignore_errors: True + - name: Delete the Demo Project + awx.awx.project: + name: "{{ demo_project_name }}" + organization: Default + scm_type: git + scm_url: https://github.com/ansible/ansible-tower-samples.git + scm_credential: "{{ scm_cred_name }}" + state: absent + failed_when: false - - name: Delete the 2nd Demo Project - project: - name: "{{ demo_project_name_2 }}" - organization: "{{ org_name }}" - scm_type: git - scm_url: https://github.com/ansible/ansible-tower-samples.git - scm_credential: "{{ scm_cred_name }}" - state: absent - ignore_errors: True + - name: Delete the 2nd Demo Project + awx.awx.project: + name: "{{ demo_project_name_2 }}" + organization: "{{ org_name }}" + scm_type: git + scm_url: https://github.com/ansible/ansible-tower-samples.git + scm_credential: "{{ scm_cred_name }}" + state: absent + failed_when: false - - name: Delete the 3rd Demo Project - project: - name: "{{ project_inv_source }}" - organization: "{{ org_name }}" - scm_type: git - scm_url: https://github.com/ansible/ansible-tower-samples.git - scm_credential: "{{ scm_cred_name }}" - state: absent - ignore_errors: True + - name: Delete the 3rd Demo Project + awx.awx.project: + name: "{{ project_inv_source }}" + organization: "{{ org_name }}" + scm_type: git + scm_url: https://github.com/ansible/ansible-tower-samples.git + scm_credential: "{{ scm_cred_name }}" + state: absent + failed_when: false - - name: Delete the SCM Credential - credential: - name: "{{ scm_cred_name }}" - organization: Default - credential_type: Source Control - state: absent - ignore_errors: True + - name: Delete the SCM Credential + awx.awx.credential: + name: "{{ scm_cred_name }}" + organization: Default + credential_type: Source Control + state: absent + failed_when: false - - name: Delete the GitHub Webhook Credential - credential: - name: "{{ github_webhook_credential_name }}" - organization: Default - credential_type: GitHub Personal Access Token - state: absent - ignore_errors: True + - name: Delete the GitHub Webhook Credential + awx.awx.credential: + name: "{{ github_webhook_credential_name }}" + organization: Default + credential_type: GitHub Personal Access Token + state: absent + failed_when: false + when: github_found - - name: Delete email notification - notification_template: - name: "{{ email_not }}" - organization: Default - state: absent - ignore_errors: True + - name: Delete email notification + awx.awx.notification_template: + name: "{{ email_not }}" + organization: Default + state: absent + failed_when: false - - name: Delete webhook notification - notification_template: - name: "{{ webhook_notification }}" - organization: Default - state: absent - ignore_errors: True + - name: Delete webhook notification + awx.awx.notification_template: + name: "{{ webhook_notification }}" + organization: Default + state: absent + failed_when: false - # Labels can not be deleted + - name: Delete an execution environment + awx.awx.execution_environment: + name: "{{ ee1 }}" + image: "junk" + state: absent + failed_when: false - - name: Delete an execution environment - execution_environment: - name: "{{ ee1 }}" - image: "junk" - state: absent - ignore_errors: True + - name: Delete instance groups + awx.awx.instance_group: + name: "{{ item }}" + state: absent + loop: + - "{{ ig1 }}" + - "{{ ig2 }}" + failed_when: false - - name: Delete instance groups - instance_group: - name: "{{ item }}" - state: absent - loop: - - "{{ ig1 }}" - - "{{ ig2 }}" - ignore_errors: True + - name: "Remove the organization" + awx.awx.organization: + name: "{{ org_name }}" + state: absent + failed_when: false - - name: "Remove the organization" - organization: - name: "{{ org_name }}" - state: absent - ignore_errors: True - - - name: Remove node - host: - name: "{{ host1 }}" - inventory: Demo Inventory - state: absent - ignore_errors: True + - name: Remove node + awx.awx.host: + name: "{{ host1 }}" + inventory: Demo Inventory + state: absent + failed_when: false diff --git a/awx_collection/tests/integration/targets/workflow_launch/tasks/main.yml b/awx_collection/tests/integration/targets/workflow_launch/tasks/main.yml index ce41c6bb87..2282c857ac 100644 --- a/awx_collection/tests/integration/targets/workflow_launch/tasks/main.yml +++ b/awx_collection/tests/integration/targets/workflow_launch/tasks/main.yml @@ -1,16 +1,17 @@ --- - name: Generate a random string for test - set_fact: + ansible.builtin.set_fact: test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" when: test_id is not defined - name: Generate names - set_fact: + ansible.builtin.set_fact: wfjt_name1: "AWX-Collection-tests-workflow_launch--wfjt1-{{ test_id }}" wfjt_name2: "AWX-Collection-tests-workflow_launch--wfjt1-{{ test_id }}-2" approval_node_name: "AWX-Collection-tests-workflow_launch_approval_node-{{ test_id }}" -- block: +- name: Create workflows + block: - name: Create our workflow workflow_job_template: @@ -30,9 +31,10 @@ ignore_errors: true register: result - - assert: + - name: Assert that workflow launch failed with expected error + ansible.builtin.assert: that: - - result is failed + - result.failed | default(false) - "'Unable to find workflow job template' in result.msg" - name: Run the workflow without waiting (this should just give us back a job ID) @@ -42,7 +44,8 @@ ignore_errors: true register: result - - assert: + - name: Assert result not failed + ansible.builtin.assert: that: - result is not failed - "'id' in result['job_info']" @@ -54,9 +57,10 @@ ignore_errors: true register: result - - assert: + - name: Assert result failed + ansible.builtin.assert: that: - - result is failed + - result.failed | default(false) - "'Monitoring of Workflow Job - '~ wfjt_name1 ~ ' aborted due to timeout' in result.msg" - name: Kick off a workflow and wait for it @@ -65,9 +69,10 @@ ignore_errors: true register: result - - assert: + - name: Assert result did not fail + ansible.builtin.assert: that: - - result is not failed + - not (result.failed | default(false)) - "'id' in result['job_info']" - name: Kick off a workflow with extra_vars but not enabled @@ -79,9 +84,10 @@ ignore_errors: true register: result - - assert: + - name: Assert result failed + ansible.builtin.assert: that: - - result is failed + - result.failed | default(false) - "'The field extra_vars was specified but the workflow job template does not allow for it to be overridden' in result.errors" - name: Prompt the workflow's with survey @@ -126,9 +132,10 @@ ignore_errors: true register: result - - assert: + - name: Assert result did not fail + ansible.builtin.assert: that: - - result is not failed + - not (result.failed | default(false)) - name: Prompt the workflow's extra_vars on launch workflow_job_template: @@ -146,9 +153,10 @@ ignore_errors: true register: result - - assert: + - name: Assert did not fail + ansible.builtin.assert: that: - - result is not failed + - not (result.failed | default(false)) - name: Test waiting for an approval node that doesn't exit on the last workflow for failure. workflow_approval: @@ -160,9 +168,10 @@ register: result ignore_errors: true - - assert: + - name: Assert result failed + ansible.builtin.assert: that: - - result is failed + - result.failed | default(false) - "'Monitoring of Workflow Approval - Test workflow approval aborted due to timeout' in result.msg" - name: Create new Workflow @@ -208,9 +217,10 @@ register: result ignore_errors: true - - assert: + - name: Assert result didn't fail + ansible.builtin.assert: that: - - result is failed + - result.failed | default(false) - "'Monitoring of Workflow Node - Demo Job Template aborted due to timeout' in result.msg" - name: Wait for approval node to activate and approve @@ -222,10 +232,11 @@ action: deny register: result - - assert: + - name: Assert did not fail + ansible.builtin.assert: that: - - result is not failed - - result is changed + - not (result.failed | default(false)) + - result.changed | default(false) - name: Wait for workflow job to finish max 120s job_wait: diff --git a/awx_collection/tools/roles/template_galaxy/tasks/main.yml b/awx_collection/tools/roles/template_galaxy/tasks/main.yml index 3a213f5997..16b7c29c37 100644 --- a/awx_collection/tools/roles/template_galaxy/tasks/main.yml +++ b/awx_collection/tools/roles/template_galaxy/tasks/main.yml @@ -2,9 +2,9 @@ - name: Sanity assertions, that some variables have a non-blank value assert: that: - - collection_version - - collection_package - - collection_path + - collection_version is defined and collection_version | length > 0 + - collection_package is defined and collection_package | length > 0 + - collection_path is defined and collection_path | length > 0 - name: Set the collection version in the controller_api.py file replace: