def test_inventory_update_injected_content(this_kind, inventory, fake_credential_factory): src_vars = dict(base_source_var='value_of_var') if this_kind in INI_TEST_VARS: src_vars.update(INI_TEST_VARS[this_kind]) extra_kwargs = {} if this_kind in TEST_SOURCE_FIELDS: extra_kwargs.update(TEST_SOURCE_FIELDS[this_kind]) inventory_source = InventorySource.objects.create( inventory=inventory, source=this_kind, source_vars=src_vars, **extra_kwargs ) inventory_source.credentials.add(fake_credential_factory(this_kind)) inventory_update = inventory_source.create_unified_job() task = RunInventoryUpdate() if InventorySource.injectors[this_kind].plugin_name is None: pytest.skip('Use of inventory plugin is not enabled for this source') def substitute_run(envvars=None, **_kw): """This method will replace run_pexpect instead of running, it will read the private data directory contents It will make assertions that the contents are correct If MAKE_INVENTORY_REFERENCE_FILES is set, it will produce reference files """ 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']) env, content = read_content(private_data_dir, envvars, inventory_update) env.pop('ANSIBLE_COLLECTIONS_PATHS', None) # collection paths not relevant to this test base_dir = os.path.join(DATA, 'plugins') if not os.path.exists(base_dir): os.mkdir(base_dir) source_dir = os.path.join(base_dir, this_kind) # this_kind is a global if set_files: create_reference_data(source_dir, env, content) pytest.skip('You set MAKE_INVENTORY_REFERENCE_FILES, so this created files, unset to run actual test.') else: if not os.path.exists(source_dir): raise FileNotFoundError( 'Maybe you never made reference files? ' 'MAKE_INVENTORY_REFERENCE_FILES=true py.test ...\noriginal: {}') files_dir = os.path.join(source_dir, 'files') try: expected_file_list = os.listdir(files_dir) except FileNotFoundError: expected_file_list = [] assert set(expected_file_list) == set(content.keys()), ( 'Inventory update runtime environment does not have expected files' ) for f_name in expected_file_list: with open(os.path.join(files_dir, f_name), 'r') as f: ref_content = f.read() assert ref_content == content[f_name], f_name try: with open(os.path.join(source_dir, 'env.json'), 'r') as f: ref_env_text = f.read() ref_env = json.loads(ref_env_text) except FileNotFoundError: ref_env = {} assert ref_env == env Res = namedtuple('Result', ['status', 'rc']) return Res('successful', 0) # Mock this so that it will not send events to the callback receiver # because doing so in pytest land creates large explosions with mock.patch('awx.main.queue.CallbackQueueDispatcher.dispatch', lambda self, obj: None): # Also do not send websocket status updates with mock.patch.object(UnifiedJob, 'websocket_emit_status', mock.Mock()): with mock.patch.object(task, 'get_ansible_version', return_value='2.13'): # The point of this test is that we replace run with assertions with mock.patch('awx.main.tasks.ansible_runner.interface.run', substitute_run): # so this sets up everything for a run and then yields control over to substitute_run task.run(inventory_update.pk)
def test_inventory_update_injected_content(this_kind, inventory, fake_credential_factory): ExecutionEnvironment.objects.create(name='test EE', managed_by_tower=True) injector = InventorySource.injectors[this_kind] if injector.plugin_name is None: pytest.skip('Use of inventory plugin is not enabled for this source') src_vars = dict(base_source_var='value_of_var') src_vars['plugin'] = injector.get_proper_name() inventory_source = InventorySource.objects.create( inventory=inventory, source=this_kind, source_vars=src_vars, ) inventory_source.credentials.add(fake_credential_factory(this_kind)) inventory_update = inventory_source.create_unified_job() task = RunInventoryUpdate() def substitute_run(awx_receptor_job): """This method will replace run_pexpect instead of running, it will read the private data directory contents It will make assertions that the contents are correct If MAKE_INVENTORY_REFERENCE_FILES is set, it will produce reference files """ envvars = awx_receptor_job.runner_params['envvars'] 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']) env, content = read_content(private_data_dir, envvars, inventory_update) # Assert inventory plugin inventory file is in private_data_dir inventory_filename = InventorySource.injectors[inventory_update.source]().filename assert ( len([True for k in content.keys() if k.endswith(inventory_filename)]) > 0 ), f"'{inventory_filename}' file not found in inventory update runtime files {content.keys()}" env.pop('ANSIBLE_COLLECTIONS_PATHS', None) # collection paths not relevant to this test base_dir = os.path.join(DATA, 'plugins') if not os.path.exists(base_dir): os.mkdir(base_dir) source_dir = os.path.join(base_dir, this_kind) # this_kind is a global if set_files: create_reference_data(source_dir, env, content) pytest.skip('You set MAKE_INVENTORY_REFERENCE_FILES, so this created files, unset to run actual test.') else: source_dir = os.path.join(base_dir, this_kind) # this_kind is a global if not os.path.exists(source_dir): raise FileNotFoundError('Maybe you never made reference files? ' 'MAKE_INVENTORY_REFERENCE_FILES=true py.test ...\noriginal: {}') files_dir = os.path.join(source_dir, 'files') try: expected_file_list = os.listdir(files_dir) except FileNotFoundError: expected_file_list = [] for f_name in expected_file_list: with open(os.path.join(files_dir, f_name), 'r') as f: ref_content = f.read() assert ref_content == content[f_name], f_name try: with open(os.path.join(source_dir, 'env.json'), 'r') as f: ref_env_text = f.read() ref_env = json.loads(ref_env_text) except FileNotFoundError: ref_env = {} assert ref_env == env Res = namedtuple('Result', ['status', 'rc']) return Res('successful', 0) # Mock this so that it will not send events to the callback receiver # because doing so in pytest land creates large explosions with mock.patch('awx.main.queue.CallbackQueueDispatcher.dispatch', lambda self, obj: None): # Also do not send websocket status updates with mock.patch.object(UnifiedJob, 'websocket_emit_status', mock.Mock()): # The point of this test is that we replace run with assertions with mock.patch('awx.main.tasks.AWXReceptorJob.run', substitute_run): # so this sets up everything for a run and then yields control over to substitute_run task.run(inventory_update.pk)