def test_variable_manager_task_vars(self): # FIXME: BCS make this work return # pylint: disable=unreachable fake_loader = DictDataLoader({}) mock_task = MagicMock() mock_task._role = None mock_task.loop = None mock_task.get_vars.return_value = dict(foo="bar") mock_task.get_include_params.return_value = dict() mock_all = MagicMock() mock_all.get_vars.return_value = {} mock_all.get_file_vars.return_value = {} mock_host = MagicMock() mock_host.get.name.return_value = 'test01' mock_host.get_vars.return_value = {} mock_host.get_host_vars.return_value = {} mock_inventory = MagicMock() mock_inventory.hosts.get.return_value = mock_host mock_inventory.hosts.get.name.return_value = 'test01' mock_inventory.get_host.return_value = mock_host mock_inventory.groups.__getitem__.return_value = mock_all v = VariableManager(loader=fake_loader, inventory=mock_inventory) self.assertEqual(v.get_vars(task=mock_task, use_cache=False).get("foo"), "bar")
def test_variable_manager_play_vars(self): fake_loader = DictDataLoader({}) mock_play = MagicMock() mock_play.get_vars.return_value = dict(foo="bar") mock_play.get_roles.return_value = [] mock_play.get_vars_files.return_value = [] mock_inventory = MagicMock() v = VariableManager(loader=fake_loader, inventory=mock_inventory) self.assertEqual(v.get_vars(play=mock_play, use_cache=False).get("foo"), "bar")
def test_basic_manager(self): fake_loader = DictDataLoader({}) mock_inventory = MagicMock() v = VariableManager(loader=fake_loader, inventory=mock_inventory) variables = v.get_vars(use_cache=False) # Check var manager expected values, never check: ['omit', 'vars'] # FIXME: add the following ['assible_version', 'assible_playbook_python', 'groups'] for varname, value in (('playbook_dir', os.path.abspath('.')), ): self.assertEqual(variables[varname], value)
def test_variable_manager_role_vars_dependencies(self): ''' Tests vars from role dependencies with duplicate dependencies. ''' mock_inventory = MagicMock() fake_loader = DictDataLoader({ # role common-role '/etc/assible/roles/common-role/tasks/main.yml': """ - debug: msg="{{role_var}}" """, # We do not need allow_duplicates: yes for this role # because eliminating duplicates is done by the execution # strategy, which we do not test here. # role role1 '/etc/assible/roles/role1/vars/main.yml': """ role_var: "role_var_from_role1" """, '/etc/assible/roles/role1/meta/main.yml': """ dependencies: - { role: common-role } """, # role role2 '/etc/assible/roles/role2/vars/main.yml': """ role_var: "role_var_from_role2" """, '/etc/assible/roles/role2/meta/main.yml': """ dependencies: - { role: common-role } """, }) v = VariableManager(loader=fake_loader, inventory=mock_inventory) play1 = Play.load(dict( hosts=['all'], roles=['role1', 'role2'], ), loader=fake_loader, variable_manager=v) # The task defined by common-role exists twice because role1 # and role2 depend on common-role. Check that the tasks see # different values of role_var. blocks = play1.compile() task = blocks[1].block[0] res = v.get_vars(play=play1, task=task) self.assertEqual(res['role_var'], 'role_var_from_role1') task = blocks[2].block[0] res = v.get_vars(play=play1, task=task) self.assertEqual(res['role_var'], 'role_var_from_role2')
def test_variable_manager_options_vars(self): fake_loader = DictDataLoader({}) options_vars = dict(a=1, b=2, c=3) mock_inventory = MagicMock() v = VariableManager(loader=fake_loader, inventory=mock_inventory) # override internal options_vars loading v._extra_vars = options_vars myvars = v.get_vars(use_cache=False) for (key, val) in iteritems(options_vars): self.assertEqual(myvars.get(key), val)
def test_flush_cache(self): cli = PlaybookCLI( args=["assible-playbook", "--flush-cache", "foobar.yml"]) cli.parse() self.assertTrue(context.CLIARGS['flush_cache']) variable_manager = VariableManager() fake_loader = DictDataLoader({'foobar.yml': ""}) inventory = InventoryManager(loader=fake_loader, sources='testhost,') variable_manager.set_host_facts('testhost', {'canary': True}) self.assertTrue('testhost' in variable_manager._fact_cache) cli._flush_cache(inventory, variable_manager) self.assertFalse('testhost' in variable_manager._fact_cache)
def _play_prereqs(): options = context.CLIARGS # all needs loader loader = DataLoader() basedir = options.get('basedir', False) if basedir: loader.set_basedir(basedir) add_all_plugin_dirs(basedir) AssibleCollectionConfig.playbook_paths = basedir default_collection = _get_collection_name_from_path(basedir) if default_collection: display.warning(u'running with default collection {0}'.format( default_collection)) AssibleCollectionConfig.default_collection = default_collection vault_ids = list(options['vault_ids']) default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST vault_ids = default_vault_ids + vault_ids vault_secrets = CLI.setup_vault_secrets( loader, vault_ids=vault_ids, vault_password_files=list(options['vault_password_files']), ask_vault_pass=options['ask_vault_pass'], auto_prompt=False) loader.set_vault_secrets(vault_secrets) # create the inventory, and filter it based on the subset specified (if any) inventory = InventoryManager(loader=loader, sources=options['inventory']) # create the variable manager, which will be shared throughout # the code, ensuring a consistent view of global variables variable_manager = VariableManager( loader=loader, inventory=inventory, version_info=CLI.version_info(gitinfo=False)) return loader, inventory, variable_manager
def test_bad_playbook_files(self): fake_loader = DictDataLoader({ # represents a playbook which is not a list of plays "bad_list.yml": """ foo: bar """, # represents a playbook where a play entry is mis-formatted "bad_entry.yml": """ - - "This should be a mapping..." """, }) vm = VariableManager() self.assertRaises(AssibleParserError, Playbook.load, "bad_list.yml", vm, fake_loader) self.assertRaises(AssibleParserError, Playbook.load, "bad_entry.yml", vm, fake_loader)
def main(): host_list = ['localhost', 'www.example.com', 'www.google.com'] # since the API is constructed for CLI it expects certain options to always be set in the context object context.CLIARGS = ImmutableDict( connection='smart', module_path=['/to/mymodules', '/usr/share/assible'], forks=10, become=None, become_method=None, become_user=None, check=False, diff=False) # required for # https://github.com/assible/assible/blob/devel/lib/assible/inventory/manager.py#L204 sources = ','.join(host_list) if len(host_list) == 1: sources += ',' # initialize needed objects loader = DataLoader( ) # Takes care of finding and reading yaml, json and ini files passwords = dict(vault_pass='******') # Instantiate our ResultsCollectorJSONCallback for handling results as they come in. Assible expects this to be one of its main display outlets results_callback = ResultsCollectorJSONCallback() # create inventory, use path to host config file as source or hosts in a comma separated string inventory = InventoryManager(loader=loader, sources=sources) # variable manager takes care of merging all the different sources to give you a unified view of variables available in each context variable_manager = VariableManager(loader=loader, inventory=inventory) # instantiate task queue manager, which takes care of forking and setting up all objects to iterate over host list and tasks # IMPORTANT: This also adds library dirs paths to the module loader # IMPORTANT: and so it must be initialized before calling `Play.load()`. tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, passwords=passwords, stdout_callback= results_callback, # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout ) # create data structure that represents our play, including tasks, this is basically what our YAML loader does internally. play_source = dict( name="Assible Play", hosts=host_list, gather_facts='no', tasks=[ dict(action=dict(module='shell', args='ls'), register='shell_out'), dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))), dict( action=dict(module='command', args=dict( cmd='/usr/bin/uptime'))), ]) # Create play object, playbook objects use .load instead of init or new methods, # this will also automatically create the task objects from the info provided in play_source play = Play().load(play_source, variable_manager=variable_manager, loader=loader) # Actually run it try: result = tqm.run( play ) # most interesting data for a play is actually sent to the callback's methods finally: # we always need to cleanup child procs and the structures we use to communicate with them tqm.cleanup() if loader: loader.cleanup_all_tmp_files() # Remove assible tmpdir shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) print("UP ***********") for host, result in results_callback.host_ok.items(): print('{0} >>> {1}'.format(host, result._result['stdout'])) print("FAILED *******") for host, result in results_callback.host_failed.items(): print('{0} >>> {1}'.format(host, result._result['msg'])) print("DOWN *********") for host, result in results_callback.host_unreachable.items(): print('{0} >>> {1}'.format(host, result._result['msg']))
def setUp(self): self.loader = DictDataLoader({ '/etc/assible/roles/l1/tasks/main.yml': """ - shell: echo 'hello world from l1' - include_role: name=l2 """, '/etc/assible/roles/l1/tasks/alt.yml': """ - shell: echo 'hello world from l1 alt' - include_role: name=l2 tasks_from=alt defaults_from=alt """, '/etc/assible/roles/l1/defaults/main.yml': """ test_variable: l1-main l1_variable: l1-main """, '/etc/assible/roles/l1/defaults/alt.yml': """ test_variable: l1-alt l1_variable: l1-alt """, '/etc/assible/roles/l2/tasks/main.yml': """ - shell: echo 'hello world from l2' - include_role: name=l3 """, '/etc/assible/roles/l2/tasks/alt.yml': """ - shell: echo 'hello world from l2 alt' - include_role: name=l3 tasks_from=alt defaults_from=alt """, '/etc/assible/roles/l2/defaults/main.yml': """ test_variable: l2-main l2_variable: l2-main """, '/etc/assible/roles/l2/defaults/alt.yml': """ test_variable: l2-alt l2_variable: l2-alt """, '/etc/assible/roles/l3/tasks/main.yml': """ - shell: echo 'hello world from l3' """, '/etc/assible/roles/l3/tasks/alt.yml': """ - shell: echo 'hello world from l3 alt' """, '/etc/assible/roles/l3/defaults/main.yml': """ test_variable: l3-main l3_variable: l3-main """, '/etc/assible/roles/l3/defaults/alt.yml': """ test_variable: l3-alt l3_variable: l3-alt """ }) self.var_manager = VariableManager(loader=self.loader)
class TestIncludeRole(unittest.TestCase): def setUp(self): self.loader = DictDataLoader({ '/etc/assible/roles/l1/tasks/main.yml': """ - shell: echo 'hello world from l1' - include_role: name=l2 """, '/etc/assible/roles/l1/tasks/alt.yml': """ - shell: echo 'hello world from l1 alt' - include_role: name=l2 tasks_from=alt defaults_from=alt """, '/etc/assible/roles/l1/defaults/main.yml': """ test_variable: l1-main l1_variable: l1-main """, '/etc/assible/roles/l1/defaults/alt.yml': """ test_variable: l1-alt l1_variable: l1-alt """, '/etc/assible/roles/l2/tasks/main.yml': """ - shell: echo 'hello world from l2' - include_role: name=l3 """, '/etc/assible/roles/l2/tasks/alt.yml': """ - shell: echo 'hello world from l2 alt' - include_role: name=l3 tasks_from=alt defaults_from=alt """, '/etc/assible/roles/l2/defaults/main.yml': """ test_variable: l2-main l2_variable: l2-main """, '/etc/assible/roles/l2/defaults/alt.yml': """ test_variable: l2-alt l2_variable: l2-alt """, '/etc/assible/roles/l3/tasks/main.yml': """ - shell: echo 'hello world from l3' """, '/etc/assible/roles/l3/tasks/alt.yml': """ - shell: echo 'hello world from l3 alt' """, '/etc/assible/roles/l3/defaults/main.yml': """ test_variable: l3-main l3_variable: l3-main """, '/etc/assible/roles/l3/defaults/alt.yml': """ test_variable: l3-alt l3_variable: l3-alt """ }) self.var_manager = VariableManager(loader=self.loader) def tearDown(self): pass def flatten_tasks(self, tasks): for task in tasks: if isinstance(task, IncludeRole): blocks, handlers = task.get_block_list(loader=self.loader) for block in blocks: for t in self.flatten_tasks(block.block): yield t elif isinstance(task, Task): yield task else: for t in self.flatten_tasks(task.block): yield t def get_tasks_vars(self, play, tasks): for task in self.flatten_tasks(tasks): role = task._role if not role: continue yield (role.get_name(), self.var_manager.get_vars(play=play, task=task)) @patch('assible.playbook.role.definition.unfrackpath', mock_unfrackpath_noop) def test_simple(self): """Test one-level include with default tasks and variables""" play = Play.load(dict(name="test play", hosts=['foo'], gather_facts=False, tasks=[{ 'include_role': 'name=l3' }]), loader=self.loader, variable_manager=self.var_manager) tasks = play.compile() tested = False for role, task_vars in self.get_tasks_vars(play, tasks): tested = True self.assertEqual(task_vars.get('l3_variable'), 'l3-main') self.assertEqual(task_vars.get('test_variable'), 'l3-main') self.assertTrue(tested) @patch('assible.playbook.role.definition.unfrackpath', mock_unfrackpath_noop) def test_simple_alt_files(self): """Test one-level include with alternative tasks and variables""" play = Play.load(dict(name="test play", hosts=['foo'], gather_facts=False, tasks=[{ 'include_role': 'name=l3 tasks_from=alt defaults_from=alt' }]), loader=self.loader, variable_manager=self.var_manager) tasks = play.compile() tested = False for role, task_vars in self.get_tasks_vars(play, tasks): tested = True self.assertEqual(task_vars.get('l3_variable'), 'l3-alt') self.assertEqual(task_vars.get('test_variable'), 'l3-alt') self.assertTrue(tested) @patch('assible.playbook.role.definition.unfrackpath', mock_unfrackpath_noop) def test_nested(self): """ Test nested includes with default tasks and variables. Variables from outer roles should be inherited, but overridden in inner roles. """ play = Play.load(dict(name="test play", hosts=['foo'], gather_facts=False, tasks=[{ 'include_role': 'name=l1' }]), loader=self.loader, variable_manager=self.var_manager) tasks = play.compile() expected_roles = ['l1', 'l2', 'l3'] for role, task_vars in self.get_tasks_vars(play, tasks): expected_roles.remove(role) # Outer-most role must not have variables from inner roles yet if role == 'l1': self.assertEqual(task_vars.get('l1_variable'), 'l1-main') self.assertEqual(task_vars.get('l2_variable'), None) self.assertEqual(task_vars.get('l3_variable'), None) self.assertEqual(task_vars.get('test_variable'), 'l1-main') # Middle role must have variables from outer role, but not inner elif role == 'l2': self.assertEqual(task_vars.get('l1_variable'), 'l1-main') self.assertEqual(task_vars.get('l2_variable'), 'l2-main') self.assertEqual(task_vars.get('l3_variable'), None) self.assertEqual(task_vars.get('test_variable'), 'l2-main') # Inner role must have variables from both outer roles elif role == 'l3': self.assertEqual(task_vars.get('l1_variable'), 'l1-main') self.assertEqual(task_vars.get('l2_variable'), 'l2-main') self.assertEqual(task_vars.get('l3_variable'), 'l3-main') self.assertEqual(task_vars.get('test_variable'), 'l3-main') else: self.fail() self.assertFalse(expected_roles) @patch('assible.playbook.role.definition.unfrackpath', mock_unfrackpath_noop) def test_nested_alt_files(self): """ Test nested includes with alternative tasks and variables. Variables from outer roles should be inherited, but overridden in inner roles. """ play = Play.load(dict(name="test play", hosts=['foo'], gather_facts=False, tasks=[{ 'include_role': 'name=l1 tasks_from=alt defaults_from=alt' }]), loader=self.loader, variable_manager=self.var_manager) tasks = play.compile() expected_roles = ['l1', 'l2', 'l3'] for role, task_vars in self.get_tasks_vars(play, tasks): expected_roles.remove(role) # Outer-most role must not have variables from inner roles yet if role == 'l1': self.assertEqual(task_vars.get('l1_variable'), 'l1-alt') self.assertEqual(task_vars.get('l2_variable'), None) self.assertEqual(task_vars.get('l3_variable'), None) self.assertEqual(task_vars.get('test_variable'), 'l1-alt') # Middle role must have variables from outer role, but not inner elif role == 'l2': self.assertEqual(task_vars.get('l1_variable'), 'l1-alt') self.assertEqual(task_vars.get('l2_variable'), 'l2-alt') self.assertEqual(task_vars.get('l3_variable'), None) self.assertEqual(task_vars.get('test_variable'), 'l2-alt') # Inner role must have variables from both outer roles elif role == 'l3': self.assertEqual(task_vars.get('l1_variable'), 'l1-alt') self.assertEqual(task_vars.get('l2_variable'), 'l2-alt') self.assertEqual(task_vars.get('l3_variable'), 'l3-alt') self.assertEqual(task_vars.get('test_variable'), 'l3-alt') else: self.fail() self.assertFalse(expected_roles)
def test_variable_manager_precedence(self): # FIXME: this needs to be redone as dataloader is not the automatic source of data anymore return # pylint: disable=unreachable ''' Tests complex variations and combinations of get_vars() with different objects to modify the context under which variables are merged. ''' # FIXME: BCS makethiswork # return True mock_inventory = MagicMock() inventory1_filedata = """ [group2:children] group1 [group1] host1 host_var=host_var_from_inventory_host1 [group1:vars] group_var = group_var_from_inventory_group1 [group2:vars] group_var = group_var_from_inventory_group2 """ fake_loader = DictDataLoader({ # inventory1 '/etc/assible/inventory1': inventory1_filedata, # role defaults_only1 '/etc/assible/roles/defaults_only1/defaults/main.yml': """ default_var: "default_var_from_defaults_only1" host_var: "host_var_from_defaults_only1" group_var: "group_var_from_defaults_only1" group_var_all: "group_var_all_from_defaults_only1" extra_var: "extra_var_from_defaults_only1" """, '/etc/assible/roles/defaults_only1/tasks/main.yml': """ - debug: msg="here i am" """, # role defaults_only2 '/etc/assible/roles/defaults_only2/defaults/main.yml': """ default_var: "default_var_from_defaults_only2" host_var: "host_var_from_defaults_only2" group_var: "group_var_from_defaults_only2" group_var_all: "group_var_all_from_defaults_only2" extra_var: "extra_var_from_defaults_only2" """, }) inv1 = InventoryManager(loader=fake_loader, sources=['/etc/assible/inventory1']) v = VariableManager(inventory=mock_inventory, loader=fake_loader) play1 = Play.load(dict( hosts=['all'], roles=['defaults_only1', 'defaults_only2'], ), loader=fake_loader, variable_manager=v) # first we assert that the defaults as viewed as a whole are the merged results # of the defaults from each role, with the last role defined "winning" when # there is a variable naming conflict res = v.get_vars(play=play1) self.assertEqual(res['default_var'], 'default_var_from_defaults_only2') # next, we assert that when vars are viewed from the context of a task within a # role, that task will see its own role defaults before any other role's blocks = play1.compile() task = blocks[1].block[0] res = v.get_vars(play=play1, task=task) self.assertEqual(res['default_var'], 'default_var_from_defaults_only1') # next we assert the precedence of inventory variables v.set_inventory(inv1) h1 = inv1.get_host('host1') res = v.get_vars(play=play1, host=h1) self.assertEqual(res['group_var'], 'group_var_from_inventory_group1') self.assertEqual(res['host_var'], 'host_var_from_inventory_host1') # next we test with group_vars/ files loaded fake_loader.push("/etc/assible/group_vars/all", """ group_var_all: group_var_all_from_group_vars_all """) fake_loader.push("/etc/assible/group_vars/group1", """ group_var: group_var_from_group_vars_group1 """) fake_loader.push("/etc/assible/group_vars/group3", """ # this is a dummy, which should not be used anywhere group_var: group_var_from_group_vars_group3 """) fake_loader.push("/etc/assible/host_vars/host1", """ host_var: host_var_from_host_vars_host1 """) fake_loader.push("group_vars/group1", """ playbook_group_var: playbook_group_var """) fake_loader.push("host_vars/host1", """ playbook_host_var: playbook_host_var """) res = v.get_vars(play=play1, host=h1) # self.assertEqual(res['group_var'], 'group_var_from_group_vars_group1') # self.assertEqual(res['group_var_all'], 'group_var_all_from_group_vars_all') # self.assertEqual(res['playbook_group_var'], 'playbook_group_var') # self.assertEqual(res['host_var'], 'host_var_from_host_vars_host1') # self.assertEqual(res['playbook_host_var'], 'playbook_host_var') # add in the fact cache v._fact_cache['host1'] = dict(fact_cache_var="fact_cache_var_from_fact_cache") res = v.get_vars(play=play1, host=h1) self.assertEqual(res['fact_cache_var'], 'fact_cache_var_from_fact_cache')