示例#1
0
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)
示例#2
0
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)