def test_serialize_then_deserialize(self): group = Group('some_group') self.hostA.add_group(group) hostA_data = self.hostA.serialize() hostA_clone = Host() hostA_clone.deserialize(hostA_data) self.assertEqual(self.hostA, hostA_clone)
def test_populates_descendant_hosts(self): A = Group('A') B = Group('B') C = Group('C') h = Host('h') C.add_host(h) A.add_child_group(B) # B is child of A B.add_child_group(C) # C is descendant of A A.add_child_group(B) self.assertEqual(set(h.groups), set([C, B, A])) h2 = Host('h2') C.add_host(h2) self.assertEqual(set(h2.groups), set([C, B, A]))
def _create_implicit_localhost(self, pattern): if self.localhost: new_host = self.localhost else: new_host = Host(pattern) new_host.address = "127.0.0.1" new_host.implicit = True # set localhost defaults py_interp = sys.executable if not py_interp: # sys.executable is not set in some cornercases. see issue #13585 py_interp = '/usr/bin/python' display.warning( 'Unable to determine python interpreter from sys.executable. Using /usr/bin/python default. ' 'You can correct this by setting assible_python_interpreter for localhost' ) new_host.set_variable("assible_python_interpreter", py_interp) new_host.set_variable("assible_connection", 'local') self.localhost = new_host return new_host
class TestHostWithPort(TestHost): assible_port = 8822 def setUp(self): self.hostA = Host(name='a', port=self.assible_port) self.hostB = Host(name='b', port=self.assible_port) def test_get_vars_assible_port(self): host_vars = self.hostA.get_vars() self.assertEqual(host_vars['assible_port'], self.assible_port)
def test_direct_host_ordering(self): """Hosts are returned in order they are added """ group = Group('A') # host names not added in alphabetical order host_name_list = ['z', 'b', 'c', 'a', 'p', 'q'] expected_hosts = [] for host_name in host_name_list: h = Host(host_name) group.add_host(h) expected_hosts.append(h) assert group.get_hosts() == expected_hosts
def test_sub_group_host_ordering(self): """With multiple nested groups, asserts that hosts are returned in deterministic order """ top_group = Group('A') expected_hosts = [] for name in ['z', 'b', 'c', 'a', 'p', 'q']: child = Group('group_{0}'.format(name)) top_group.add_child_group(child) host = Host('host_{0}'.format(name)) child.add_host(host) expected_hosts.append(host) assert top_group.get_hosts() == expected_hosts
def add_host(self, host, group=None, port=None): ''' adds a host to inventory and possibly a group if not there already ''' if host: if not isinstance(host, string_types): raise AssibleError( "Invalid host name supplied, expected a string but got %s for %s" % (type(host), host)) # TODO: add to_safe_host_name g = None if group: if group in self.groups: g = self.groups[group] else: raise AssibleError("Could not find group %s in inventory" % group) if host not in self.hosts: h = Host(host, port) self.hosts[host] = h if self.current_source: # set to 'first source' in which host was encountered self.set_variable(host, 'inventory_file', self.current_source) self.set_variable(host, 'inventory_dir', basedir(self.current_source)) else: self.set_variable(host, 'inventory_file', None) self.set_variable(host, 'inventory_dir', None) display.debug("Added host %s to inventory" % (host)) # set default localhost from inventory to avoid creating an implicit one. Last localhost defined 'wins'. if host in C.LOCALHOST: if self.localhost is None: self.localhost = self.hosts[host] display.vvvv("Set default localhost to %s" % h) else: display.warning( "A duplicate localhost-like entry was found (%s). First found localhost was %s" % (h, self.localhost.name)) else: h = self.hosts[host] if g: g.add_host(h) self._groups_dict_cache = {} display.debug("Added host %s to group %s" % (host, group)) else: raise AssibleError("Invalid empty host name provided: %s" % host) return host
def _get_delegated_vars(self, play, task, existing_variables): # This method has a lot of code copied from ``TaskExecutor._get_loop_items`` # if this is failing, and ``TaskExecutor._get_loop_items`` is not # then more will have to be copied here. # TODO: dedupe code here and with ``TaskExecutor._get_loop_items`` # this may be possible once we move pre-processing pre fork if not hasattr(task, 'loop'): # This "task" is not a Task, so we need to skip it return {}, None # we unfortunately need to template the delegate_to field here, # as we're fetching vars before post_validate has been called on # the task that has been passed in vars_copy = existing_variables.copy() # get search path for this task to pass to lookup plugins vars_copy['assible_search_path'] = task.get_search_path() # ensure basedir is always in (dwim already searches here but we need to display it) if self._loader.get_basedir() not in vars_copy['assible_search_path']: vars_copy['assible_search_path'].append(self._loader.get_basedir()) templar = Templar(loader=self._loader, variables=vars_copy) items = [] has_loop = True if task.loop_with is not None: if task.loop_with in lookup_loader: fail = True if task.loop_with == 'first_found': # first_found loops are special. If the item is undefined then we want to fall through to the next fail = False try: loop_terms = listify_lookup_plugin_terms( terms=task.loop, templar=templar, loader=self._loader, fail_on_undefined=fail, convert_bare=False) if not fail: loop_terms = [ t for t in loop_terms if not templar.is_template(t) ] mylookup = lookup_loader.get(task.loop_with, loader=self._loader, templar=templar) # give lookup task 'context' for subdir (mostly needed for first_found) for subdir in ['template', 'var', 'file']: # TODO: move this to constants? if subdir in task.action: break setattr(mylookup, '_subdir', subdir + 's') items = wrap_var( mylookup.run(terms=loop_terms, variables=vars_copy)) except AssibleTemplateError: # This task will be skipped later due to this, so we just setup # a dummy array for the later code so it doesn't fail items = [None] else: raise AssibleError( "Failed to find the lookup named '%s' in the available lookup plugins" % task.loop_with) elif task.loop is not None: try: items = templar.template(task.loop) except AssibleTemplateError: # This task will be skipped later due to this, so we just setup # a dummy array for the later code so it doesn't fail items = [None] else: has_loop = False items = [None] # since host can change per loop, we keep dict per host name resolved delegated_host_vars = dict() item_var = getattr(task.loop_control, 'loop_var', 'item') cache_items = False for item in items: # update the variables with the item value for templating, in case we need it if item is not None: vars_copy[item_var] = item templar.available_variables = vars_copy delegated_host_name = templar.template(task.delegate_to, fail_on_undefined=False) if delegated_host_name != task.delegate_to: cache_items = True if delegated_host_name is None: raise AssibleError( message="Undefined delegate_to host for task:", obj=task._ds) if not isinstance(delegated_host_name, string_types): raise AssibleError( message= "the field 'delegate_to' has an invalid type (%s), and could not be" " converted to a string type." % type(delegated_host_name), obj=task._ds) if delegated_host_name in delegated_host_vars: # no need to repeat ourselves, as the delegate_to value # does not appear to be tied to the loop item variable continue # now try to find the delegated-to host in inventory, or failing that, # create a new host on the fly so we can fetch variables for it delegated_host = None if self._inventory is not None: delegated_host = self._inventory.get_host(delegated_host_name) # try looking it up based on the address field, and finally # fall back to creating a host on the fly to use for the var lookup if delegated_host is None: for h in self._inventory.get_hosts( ignore_limits=True, ignore_restrictions=True): # check if the address matches, or if both the delegated_to host # and the current host are in the list of localhost aliases if h.address == delegated_host_name: delegated_host = h break else: delegated_host = Host(name=delegated_host_name) else: delegated_host = Host(name=delegated_host_name) # now we go fetch the vars for the delegated-to host and save them in our # master dictionary of variables to be used later in the TaskExecutor/PlayContext delegated_host_vars[delegated_host_name] = self.get_vars( play=play, host=delegated_host, task=task, include_delegate_to=False, include_hostvars=True, ) delegated_host_vars[delegated_host_name][ 'inventory_hostname'] = vars_copy.get('inventory_hostname') _assible_loop_cache = None if has_loop and cache_items: # delegate_to templating produced a change, so we will cache the templated items # in a special private hostvar # this ensures that delegate_to+loop doesn't produce different results than TaskExecutor # which may reprocess the loop _assible_loop_cache = items return delegated_host_vars, _assible_loop_cache
def test_hashability(self): # equality implies the hash values are the same self.assertEqual(hash(self.hostA), hash(Host('a')))
def test_equality(self): self.assertEqual(self.hostA, self.hostA) self.assertNotEqual(self.hostA, self.hostB) self.assertNotEqual(self.hostA, Host('a'))
def setUp(self): self.hostA = Host('a') self.hostB = Host('b')
class TestHost(unittest.TestCase): assible_port = 22 def setUp(self): self.hostA = Host('a') self.hostB = Host('b') def test_equality(self): self.assertEqual(self.hostA, self.hostA) self.assertNotEqual(self.hostA, self.hostB) self.assertNotEqual(self.hostA, Host('a')) def test_hashability(self): # equality implies the hash values are the same self.assertEqual(hash(self.hostA), hash(Host('a'))) def test_get_vars(self): host_vars = self.hostA.get_vars() self.assertIsInstance(host_vars, dict) def test_repr(self): host_repr = repr(self.hostA) self.assertIsInstance(host_repr, string_types) def test_add_group(self): group = Group('some_group') group_len = len(self.hostA.groups) self.hostA.add_group(group) self.assertEqual(len(self.hostA.groups), group_len + 1) def test_get_groups(self): group = Group('some_group') self.hostA.add_group(group) groups = self.hostA.get_groups() self.assertEqual(len(groups), 1) for _group in groups: self.assertIsInstance(_group, Group) def test_equals_none(self): other = None self.hostA == other other == self.hostA self.hostA != other other != self.hostA self.assertNotEqual(self.hostA, other) def test_serialize(self): group = Group('some_group') self.hostA.add_group(group) data = self.hostA.serialize() self.assertIsInstance(data, dict) def test_serialize_then_deserialize(self): group = Group('some_group') self.hostA.add_group(group) hostA_data = self.hostA.serialize() hostA_clone = Host() hostA_clone.deserialize(hostA_data) self.assertEqual(self.hostA, hostA_clone) def test_set_state(self): group = Group('some_group') self.hostA.add_group(group) pickled_hostA = pickle.dumps(self.hostA) hostA_clone = pickle.loads(pickled_hostA) self.assertEqual(self.hostA, hostA_clone)
def setUp(self): self.hostA = Host(name='a', port=self.assible_port) self.hostB = Host(name='b', port=self.assible_port)