Example #1
0
    def get_inherited_vars(self, dep_chain=[]):
        inherited_vars = dict()

        for parent in dep_chain:
            inherited_vars = combine_vars(inherited_vars, parent._role_vars)
            inherited_vars = combine_vars(inherited_vars, parent._role_params)
        return inherited_vars
Example #2
0
 def get_default_vars(self):
     # FIXME: get these from dependent roles too
     default_vars = dict()
     for dep in self.get_all_dependencies():
         default_vars = combine_vars(default_vars, dep.get_default_vars())
     default_vars = combine_vars(default_vars, self._default_vars)
     return default_vars
Example #3
0
 def get_inherited_vars(self):
     inherited_vars = dict()
     for parent in self._parents:
         inherited_vars = combine_vars(inherited_vars, parent.get_inherited_vars())
         inherited_vars = combine_vars(inherited_vars, parent._role_vars)
         inherited_vars = combine_vars(inherited_vars, parent._role_params)
     return inherited_vars
Example #4
0
 def get_role_params(self, dep_chain=[]):
     params = {}
     if dep_chain:
         for parent in dep_chain:
             params = combine_vars(params, parent._role_params)
     params = combine_vars(params, self._role_params)
     return params
Example #5
0
    def _get_host_variables(self, hostname, vault_password=None):

        host = self.get_host(hostname)
        if host is None:
            raise errors.AnsibleError("host not found: %s" % hostname)

        vars = {}

        # plugin.run retrieves all vars (also from groups) for host
        vars_results = [ plugin.run(host, vault_password=vault_password) for plugin in self._vars_plugins if hasattr(plugin, 'run')]
        for updated in vars_results:
            if updated is not None:
                # FIXME: combine_vars
                vars = combine_vars(vars, updated)

        # plugin.get_host_vars retrieves just vars for specific host
        vars_results = [ plugin.get_host_vars(host, vault_password=vault_password) for plugin in self._vars_plugins if hasattr(plugin, 'get_host_vars')]
        for updated in vars_results:
            if updated is not None:
                # FIXME: combine_vars
                vars = combine_vars(vars, updated)

        # still need to check InventoryParser per host vars
        # which actually means InventoryScript per host,
        # which is not performant
        if self.parser is not None:
            # FIXME: combine_vars
            vars = combine_vars(vars, self.parser.get_host_variables(host))

        # Read host_vars/ files
        # FIXME: combine_vars
        vars = combine_vars(vars, self.get_host_vars(host))

        return vars
Example #6
0
def boilerplate_module(modfile, args, interpreter, check, destfile):
    """ simulate what ansible does with new style modules """

    loader = DataLoader()

    complex_args = {}
    if args.startswith("@"):
        # Argument is a YAML file (JSON is a subset of YAML)
        complex_args = utils_vars.combine_vars(complex_args,
                                               loader.load_from_file(args[1:]))
        args = ''
    elif args.startswith("{"):
        # Argument is a YAML document (not a file)
        complex_args = utils_vars.combine_vars(complex_args, loader.load(args))
        args = ''

    if args:
        parsed_args = parse_kv(args)
        complex_args = utils_vars.combine_vars(complex_args, parsed_args)

    task_vars = {}
    if interpreter:
        if '=' not in interpreter:
            print("interpreter must by in the form of \
                   ansible_python_interpreter=/usr/bin/python")
            sys.exit(1)
        interpreter_type, interpreter_path = interpreter.split('=')
        if not interpreter_type.startswith('ansible_'):
            interpreter_type = 'ansible_%s' % interpreter_type
        if not interpreter_type.endswith('_interpreter'):
            interpreter_type = '%s_interpreter' % interpreter_type
        task_vars[interpreter_type] = interpreter_path

    if check:
        complex_args['_ansible_check_mode'] = True

    modname = os.path.basename(modfile)
    modname = os.path.splitext(modname)[0]
    (module_data, module_style, shebang) = module_common.modify_module(
        modname,
        modfile,
        complex_args,
        task_vars=task_vars
    )

    if module_style == 'new' \
       and 'ZIPLOADER_WRAPPER = True' in module_data:
        module_style = 'ziploader'

    modfile2_path = os.path.expanduser(destfile)
    print("* including generated source,\
           if any, saving to: %s" % modfile2_path)
    if module_style not in ('ziploader', 'old'):
        print("* this may offset any line numbers in tracebacks/debuggers!")
    modfile2 = open(modfile2_path, 'w')
    modfile2.write(module_data)
    modfile2.close()
    modfile = modfile2_path

    return (modfile2_path, modname, module_style)
Example #7
0
    def _load_vars(self, attr, ds):
        '''
        Vars in a play can be specified either as a dictionary directly, or
        as a list of dictionaries. If the later, this method will turn the
        list into a single dictionary.
        '''

        def _validate_variable_keys(ds):
            for key in ds:
                if not isidentifier(key):
                    raise TypeError("'%s' is not a valid variable name" % key)

        try:
            if isinstance(ds, dict):
                _validate_variable_keys(ds)
                return combine_vars(self.vars, ds)
            elif isinstance(ds, list):
                all_vars = self.vars
                for item in ds:
                    if not isinstance(item, dict):
                        raise ValueError
                    _validate_variable_keys(item)
                    all_vars = combine_vars(all_vars, item)
                return all_vars
            elif ds is None:
                return {}
            else:
                raise ValueError
        except ValueError as e:
            raise AnsibleParserError("Vars in a %s must be specified as a dictionary, or a list of dictionaries" % self.__class__.__name__,
                                     obj=ds, orig_exc=e)
        except TypeError as e:
            raise AnsibleParserError("Invalid variable name in vars specified for %s: %s" % (self.__class__.__name__, e), obj=ds, orig_exc=e)
Example #8
0
 def get_default_vars(self, dep_chain=[]):
     default_vars = dict()
     for dep in self.get_all_dependencies():
         default_vars = combine_vars(default_vars, dep.get_default_vars())
     if dep_chain:
         for parent in dep_chain:
             default_vars = combine_vars(default_vars, parent._default_vars)
     default_vars = combine_vars(default_vars, self._default_vars)
     return default_vars
Example #9
0
    def get_role_params(self, dep_chain=None):
        dep_chain = [] if dep_chain is None else dep_chain

        params = {}
        if dep_chain:
            for parent in dep_chain:
                params = combine_vars(params, parent._role_params)
        params = combine_vars(params, self._role_params)
        return params
Example #10
0
    def get_vars(self, dep_chain=[]):
        all_vars = self.get_inherited_vars(dep_chain)

        for dep in self.get_all_dependencies():
            all_vars = combine_vars(all_vars, dep.get_vars())

        all_vars = combine_vars(all_vars, self._role_vars)
        all_vars = combine_vars(all_vars, self._role_params)

        return all_vars
Example #11
0
 def plugins_by_groups():
     '''
         merges all plugin sources by group,
         This should be used instead, NOT in combination with the other groups_plugins* functions
     '''
     data = {}
     for group in host_groups:
         data[group] = combine_vars(data[group], _plugins_inventory(group))
         data[group] = combine_vars(data[group], _plugins_play(group))
     return data
Example #12
0
    def parse_inventory(self, host_list):

        if isinstance(host_list, basestring):
            if "," in host_list:
                host_list = host_list.split(",")
                host_list = [h for h in host_list if h and h.strip()]

        if host_list is None:
            self.parser = None
        elif isinstance(host_list, list):
            self.parser = None
            all = Group("all")
            self.groups = [all]
            ipv6_re = re.compile("\[([a-f:A-F0-9]*[%[0-z]+]?)\](?::(\d+))?")
            for x in host_list:
                m = ipv6_re.match(x)
                if m:
                    all.add_host(Host(m.groups()[0], m.groups()[1]))
                else:
                    if ":" in x:
                        tokens = x.rsplit(":", 1)
                        # if there is ':' in the address, then this is an ipv6
                        if ":" in tokens[0]:
                            all.add_host(Host(x))
                        else:
                            all.add_host(Host(tokens[0], tokens[1]))
                    else:
                        all.add_host(Host(x))
        elif self._loader.path_exists(host_list):
            # TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
            if self._loader.is_directory(host_list):
                # Ensure basedir is inside the directory
                host_list = os.path.join(self.host_list, "")
                self.parser = InventoryDirectory(loader=self._loader, filename=host_list)
            else:
                self.parser = get_file_parser(host_list, self._loader)
                vars_loader.add_directory(self.basedir(), with_subdir=True)

            if self.parser:
                self.groups = self.parser.groups.values()
            else:
                # should never happen, but JIC
                raise AnsibleError("Unable to parse %s as an inventory source" % host_list)

        self._vars_plugins = [x for x in vars_loader.all(self)]

        # FIXME: shouldn't be required, since the group/host vars file
        #        management will be done in VariableManager
        # get group vars from group_vars/ files and vars plugins
        for group in self.groups:
            group.vars = combine_vars(group.vars, self.get_group_variables(group.name))

        # get host vars from host_vars/ files and vars plugins
        for host in self.get_hosts():
            host.vars = combine_vars(host.vars, self.get_host_variables(host.name))
Example #13
0
    def parse_inventory(self, host_list):

        if isinstance(host_list, string_types):
            if "," in host_list:
                host_list = host_list.split(",")
                host_list = [ h for h in host_list if h and h.strip() ]

        self.parser = None

        # Always create the 'all' and 'ungrouped' groups, even if host_list is
        # empty: in this case we will subsequently an the implicit 'localhost' to it.

        ungrouped = Group('ungrouped')
        all = Group('all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)

        if host_list is None:
            pass
        elif isinstance(host_list, list):
            for h in host_list:
                try:
                    (host, port) = parse_address(h, allow_ranges=False)
                except AnsibleError as e:
                    display.vvv("Unable to parse address from hostname, leaving unchanged: %s" % to_unicode(e))
                    host = h
                    port = None
                all.add_host(Host(host, port))
        elif self._loader.path_exists(host_list):
            #TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
            if self.is_directory(host_list):
                # Ensure basedir is inside the directory
                host_list = os.path.join(self.host_list, "")
                self.parser = InventoryDirectory(loader=self._loader, groups=self.groups, filename=host_list)
            else:
                self.parser = get_file_parser(host_list, self.groups, self._loader)
                vars_loader.add_directory(self.basedir(), with_subdir=True)

            if not self.parser:
                # should never happen, but JIC
                raise AnsibleError("Unable to parse %s as an inventory source" % host_list)
        else:
            display.warning("Host file not found: %s" % to_unicode(host_list))

        self._vars_plugins = [ x for x in vars_loader.all(self) ]

        # set group vars from group_vars/ files and vars plugins
        for g in self.groups:
            group = self.groups[g]
            group.vars = combine_vars(group.vars, self.get_group_variables(group.name))

        # set host vars from host_vars/ files and vars plugins
        for host in self.get_hosts():
            host.vars = combine_vars(host.vars, self.get_host_variables(host.name))
Example #14
0
    def get_vars(self):

        results = {}
        groups = self.get_groups()
        for group in sorted(groups, key=lambda g: g.depth):
            results = combine_vars(results, group.get_vars())
        results = combine_vars(results, self.vars)
        results['inventory_hostname'] = self.name
        results['inventory_hostname_short'] = self.name.split('.')[0]
        results['group_names'] = sorted([ g.name for g in groups if g.name != 'all'])
        return results
    def get_vars(self, dep_chain=[], include_params=True):
        all_vars = self.get_inherited_vars(dep_chain)

        for dep in self.get_all_dependencies():
            all_vars = combine_vars(all_vars, dep.get_vars(include_params=include_params))

        all_vars = combine_vars(all_vars, self._role_vars)
        if include_params:
            all_vars = combine_vars(all_vars, self.get_role_params(dep_chain=dep_chain))

        return all_vars
Example #16
0
    def _get_hostgroup_vars(self, host=None, group=None, new_pb_basedir=False, return_results=False):
        """
        Loads variables from group_vars/<groupname> and host_vars/<hostname> in directories parallel
        to the inventory base directory or in the same directory as the playbook.  Variables in the playbook
        dir will win over the inventory dir if files are in both.
        """

        results = {}
        scan_pass = 0
        _basedir = self._basedir
        _playbook_basedir = self._playbook_basedir

        # look in both the inventory base directory and the playbook base directory
        # unless we do an update for a new playbook base dir
        if not new_pb_basedir and _playbook_basedir:
            basedirs = [_basedir, _playbook_basedir]
        else:
            basedirs = [_basedir]

        for basedir in basedirs:
            # this can happen from particular API usages, particularly if not run
            # from /usr/bin/ansible-playbook
            if basedir in ('', None):
                basedir = './'

            scan_pass = scan_pass + 1

            # it's not an eror if the directory does not exist, keep moving
            if not os.path.exists(basedir):
                continue

            # save work of second scan if the directories are the same
            if _basedir == _playbook_basedir and scan_pass != 1:
                continue

            # Before trying to load vars from file, check that the directory contains relvant file names
            if host is None and any(map(lambda ext: group.name + ext in self._group_vars_files, C.YAML_FILENAME_EXTENSIONS)):
                # load vars in dir/group_vars/name_of_group
                base_path = to_text(os.path.abspath(os.path.join(to_bytes(basedir), b"group_vars/" + to_bytes(group.name))), errors='surrogate_or_strict')
                host_results = self._variable_manager.add_group_vars_file(base_path, self._loader)
                if return_results:
                    results = combine_vars(results, host_results)
            elif group is None and any(map(lambda ext: host.name + ext in self._host_vars_files, C.YAML_FILENAME_EXTENSIONS)):
                # same for hostvars in dir/host_vars/name_of_host
                base_path = to_text(os.path.abspath(os.path.join(to_bytes(basedir), b"host_vars/" + to_bytes(host.name))), errors='surrogate_or_strict')
                group_results = self._variable_manager.add_host_vars_file(base_path, self._loader)
                if return_results:
                    results = combine_vars(results, group_results)

        # all done, results is a dictionary of variables for this particular host.
        return results
Example #17
0
    def parse_inventory(self, host_list):

        if isinstance(host_list, string_types):
            if "," in host_list:
                host_list = host_list.split(",")
                host_list = [ h for h in host_list if h and h.strip() ]

        self.parser = None

        # Always create the 'all' and 'ungrouped' groups, even if host_list is
        # empty: in this case we will subsequently an the implicit 'localhost' to it.

        ungrouped = Group(name='ungrouped')
        all = Group('all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)

        if host_list is None:
            pass
        elif isinstance(host_list, list):
            for h in host_list:
                (host, port) = parse_address(h, allow_ranges=False)
                all.add_host(Host(host, port))
        elif self._loader.path_exists(host_list):
            #TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
            if self._loader.is_directory(host_list):
                # Ensure basedir is inside the directory
                host_list = os.path.join(self.host_list, "")
                self.parser = InventoryDirectory(loader=self._loader, groups=self.groups, filename=host_list)
            else:
                self.parser = get_file_parser(host_list, self.groups, self._loader)
                vars_loader.add_directory(self.basedir(), with_subdir=True)

            if not self.parser:
                # should never happen, but JIC
                raise AnsibleError("Unable to parse %s as an inventory source" % host_list)

        self._vars_plugins = [ x for x in vars_loader.all(self) ]

        # FIXME: shouldn't be required, since the group/host vars file
        #        management will be done in VariableManager
        # get group vars from group_vars/ files and vars plugins
        for group in self.groups.values():
            group.vars = combine_vars(group.vars, self.get_group_variables(group.name))

        # get host vars from host_vars/ files and vars plugins
        for host in self.get_hosts():
            host.vars = combine_vars(host.vars, self.get_host_variables(host.name))
Example #18
0
    def load_inventory_files(self, inventory_files, host_list=None):
        temp_vars = self._variable_manager.get_vars(loader=self._loader)
        templar = Templar(loader=self._loader, variables=temp_vars)

        all_inventory = AbleMapping()
        try:
            for inventory_file in inventory_files:
                inventory_file = templar.template(inventory_file)
                try:
                    data = InventoryYaml.prepare_data(self._loader.load_from_file(inventory_file))
                    if data is not None:
                        if self._directory is None:
                            self._directory = os.path.dirname(inventory_file)
                        all_inventory = combine_vars(all_inventory, data)
                    break
                except AbleFileNotFound as e:
                    # we continue on loader failures
                    continue
                except AbleParserError as e:
                    raise
            else:
                raise AbleFileNotFound("vars file %s was not found" % inventory_files)
        except (UndefinedError, AbleUndefinedVariable):
                # we do not have a full context here, and the missing variable could be
                # because of that, so just show a warning and continue
                display.vvv("skipping inventory_file '%s' due to an undefined variable" % inventory_files)

        return all_inventory
Example #19
0
 def _load_role_yaml(self, subdir, main=None, allow_dir=False):
     file_path = os.path.join(self._role_path, subdir)
     if self._loader.path_exists(file_path) and self._loader.is_directory(file_path):
         # Valid extensions and ordering for roles is hard-coded to maintain
         # role portability
         extensions = ['.yml', '.yaml', '.json']
         # If no <main> is specified by the user, look for files with
         # extensions before bare name. Otherwise, look for bare name first.
         if main is None:
             _main = 'main'
             extensions.append('')
         else:
             _main = main
             extensions.insert(0, '')
         found_files = self._loader.find_vars_files(file_path, _main, extensions, allow_dir)
         if found_files:
             data = {}
             for found in found_files:
                 new_data = self._loader.load_from_file(found)
                 if new_data and allow_dir:
                     data = combine_vars(data, new_data)
                 else:
                     data = new_data
                 return data
         elif main is not None:
             raise AnsibleParserError("Could not find specified file in role: %s/%s" % (subdir, main))
     return None
Example #20
0
    def get_magic_vars(self):
        results = {}
        results['inventory_hostname'] = self.name
        results['inventory_hostname_short'] = self.name.split('.')[0]
        results['group_names'] = sorted([g.name for g in self.get_groups() if g.name != 'all'])

        return combine_vars(self.vars, results)
Example #21
0
    def set_host_overrides(self, host):
        self._host = host

        host_vars = combine_vars(host.get_group_vars(), host.get_vars())
        self._nspawn_cmd = host_vars.get('nspawn_command', 'systemd-nspawn')
        self._nspawn_args = shlex.split(host_vars.get('nspawn_extra_args', ''))
        self._nspawn_sudo = boolean(host_vars.get('nspawn_sudo', 'false'))
Example #22
0
 def _get_plugin_vars(plugin, path, entities):
     data = {}
     try:
         data = plugin.get_vars(self.loader, path, entity)
     except AttributeError:
         try:
             if isinstance(entity, Host):
                 data = combine_vars(data, plugin.get_host_vars(entity.name))
             else:
                 data = combine_vars(data, plugin.get_group_vars(entity.name))
         except AttributeError:
             if hasattr(plugin, 'run'):
                 raise AnsibleError("Cannot use v1 type vars plugin %s from %s" % (plugin._load_name, plugin._original_path))
             else:
                 raise AnsibleError("Invalid vars plugin %s from %s" % (plugin._load_name, plugin._original_path))
     return data
Example #23
0
def get_group_vars(groups):

    results = {}
    for group in sort_groups(groups):
        results = combine_vars(results, group.get_vars())

    return results
Example #24
0
    def _set_connection_options(self, variables, templar):

        # Keep the pre-delegate values for these keys
        PRESERVE_ORIG = ('inventory_hostname',)

        # create copy with delegation built in
        final_vars = combine_vars(variables, variables.get('ansible_delegated_vars', dict()).get(self._task.delegate_to, dict()))

        # grab list of usable vars for this plugin
        option_vars = C.config.get_plugin_vars('connection', self._connection._load_name)

        # create dict of 'templated vars'
        options = {'_extras': {}}
        for k in option_vars:
            if k in PRESERVE_ORIG:
                options[k] = templar.template(variables[k])
            elif k in final_vars:
                options[k] = templar.template(final_vars[k])

        # add extras if plugin supports them
        if getattr(self._connection, 'allow_extras', False):
            for k in final_vars:
                if k.startswith('ansible_%s_' % self._connection._load_name) and k not in options:
                    options['_extras'][k] = templar.template(final_vars[k])

        # set options with 'templated vars' specific to this plugin
        self._connection.set_options(var_options=options)
        self._set_shell_options(final_vars, templar)
Example #25
0
    def _get_hostgroup_vars(self, host=None, group=None, new_pb_basedir=False):
        """
        Loads variables from group_vars/<groupname> and host_vars/<hostname> in directories parallel
        to the inventory base directory or in the same directory as the playbook.  Variables in the playbook
        dir will win over the inventory dir if files are in both.
        """

        results = {}
        scan_pass = 0
        _basedir = self.basedir()

        # look in both the inventory base directory and the playbook base directory
        # unless we do an update for a new playbook base dir
        if not new_pb_basedir:
            basedirs = [_basedir, self._playbook_basedir]
        else:
            basedirs = [self._playbook_basedir]

        for basedir in basedirs:
            # this can happen from particular API usages, particularly if not run
            # from /usr/bin/ansible-playbook
            if basedir in ('', None):
                basedir = './'

            scan_pass = scan_pass + 1

            # it's not an eror if the directory does not exist, keep moving
            if not os.path.exists(basedir):
                continue

            # save work of second scan if the directories are the same
            if _basedir == self._playbook_basedir and scan_pass != 1:
                continue

            if group and host is None:
                # load vars in dir/group_vars/name_of_group
                base_path = to_unicode(os.path.abspath(os.path.join(to_bytes(basedir), b"group_vars/" + to_bytes(group.name))), errors='strict')
                results = combine_vars(results, self._variable_manager.add_group_vars_file(base_path, self._loader))
            elif host and group is None:
                # same for hostvars in dir/host_vars/name_of_host
                base_path = to_unicode(os.path.abspath(os.path.join(to_bytes(basedir), b"host_vars/" + to_bytes(host.name))), errors='strict')
                results = combine_vars(results, self._variable_manager.add_host_vars_file(base_path, self._loader))

        # all done, results is a dictionary of variables for this particular host.
        return results
Example #26
0
    def get_inherited_vars(self, dep_chain=None):
        dep_chain = [] if dep_chain is None else dep_chain

        inherited_vars = dict()

        if dep_chain:
            for parent in dep_chain:
                inherited_vars = combine_vars(inherited_vars, parent._role_vars)
        return inherited_vars
Example #27
0
    def _get_group_variables(self, groupname, vault_password=None):

        group = self.get_group(groupname)
        if group is None:
            raise Exception("group not found: %s" % groupname)

        vars = {}

        # plugin.get_group_vars retrieves just vars for specific group
        vars_results = [ plugin.get_group_vars(group, vault_password=vault_password) for plugin in self._vars_plugins if hasattr(plugin, 'get_group_vars')]
        for updated in vars_results:
            if updated is not None:
                vars = combine_vars(vars, updated)

        # Read group_vars/ files
        vars = combine_vars(vars, self.get_group_vars(group))

        return vars
Example #28
0
 def set_playbook_basedir(self, dir):
     """
     sets the base directory of the playbook so inventory can use it as a
     basedir for host_ and group_vars, and other things.
     """
     # Only update things if dir is a different playbook basedir
     if dir != self._playbook_basedir:
         self._playbook_basedir = dir
         # get group vars from group_vars/ files
         for group in self.groups:
             # FIXME: combine_vars
             group.vars = combine_vars(group.vars, self.get_group_vars(group, new_pb_basedir=True))
         # get host vars from host_vars/ files
         for host in self.get_hosts():
             # FIXME: combine_vars
             host.vars = combine_vars(host.vars, self.get_host_vars(host, new_pb_basedir=True))
         # invalidate cache
         self._vars_per_host = {}
         self._vars_per_group = {}
Example #29
0
    def test_improper_args(self):
        with mock.patch("ansible.constants.DEFAULT_HASH_BEHAVIOUR", "replace"):
            with self.assertRaises(AnsibleError):
                combine_vars([1, 2, 3], dict(a=1))
            with self.assertRaises(AnsibleError):
                combine_vars(dict(a=1), [1, 2, 3])

        with mock.patch("ansible.constants.DEFAULT_HASH_BEHAVIOUR", "merge"):
            with self.assertRaises(AnsibleError):
                combine_vars([1, 2, 3], dict(a=1))
            with self.assertRaises(AnsibleError):
                combine_vars(dict(a=1), [1, 2, 3])
Example #30
0
 def set_host_variable(self, host, varname, value):
     '''
     Sets a value in the vars_cache for a host.
     '''
     host_name = host.get_name()
     if host_name not in self._vars_cache:
         self._vars_cache[host_name] = dict()
     if varname in self._vars_cache[host_name]:
         self._vars_cache[host_name][varname] = combine_vars(self._vars_cache[host_name][varname], value)
     else:
         self._vars_cache[host_name][varname] = value
Example #31
0
 def set_host_variable(self, host, varname, value):
     '''
     Sets a value in the vars_cache for a host.
     '''
     host_name = host.get_name()
     if host_name not in self._vars_cache:
         self._vars_cache[host_name] = dict()
     if varname in self._vars_cache[host_name] and isinstance(
             self._vars_cache[host_name][varname],
             MutableMapping) and isinstance(value, MutableMapping):
         self._vars_cache[host_name] = combine_vars(
             self._vars_cache[host_name], {varname: value})
     else:
         self._vars_cache[host_name][varname] = value
Example #32
0
    def _get_host_variables(self, host):

        if context.CLIARGS['export']:
            hostvars = host.get_vars()

            # FIXME: add switch to skip vars plugins
            # add vars plugin info
            for inventory_dir in self.inventory._sources:
                hostvars = combine_vars(
                    hostvars, self.get_plugin_vars(inventory_dir, host))
        else:
            hostvars = self.vm.get_vars(host=host, include_hostvars=False)

        return hostvars
Example #33
0
    def _get_host_variables(self, hostname, vault_password=None):

        host = self.get_host(hostname)
        if host is None:
            raise AnsibleError("host not found: %s" % hostname)

        vars = {}

        # plugin.run retrieves all vars (also from groups) for host
        vars_results = [
            plugin.run(host, vault_password=vault_password)
            for plugin in self._vars_plugins if hasattr(plugin, 'run')
        ]
        for updated in vars_results:
            if updated is not None:
                vars = combine_vars(vars, updated)

        # plugin.get_host_vars retrieves just vars for specific host
        vars_results = [
            plugin.get_host_vars(host, vault_password=vault_password)
            for plugin in self._vars_plugins
            if hasattr(plugin, 'get_host_vars')
        ]
        for updated in vars_results:
            if updated is not None:
                vars = combine_vars(vars, updated)

        # still need to check InventoryParser per host vars
        # which actually means InventoryScript per host,
        # which is not performant
        if self.parser is not None:
            vars = combine_vars(vars, self.parser.get_host_variables(host))

        # Read host_vars/ files
        vars = combine_vars(vars, self.get_host_vars(host))

        return vars
Example #34
0
    def parse_sources(self, cache=False):
        ''' iterate over inventory sources and parse each one to populate it'''

        parsed = False
        # allow for multiple inventory parsing
        for source in self._sources:

            if source:
                if ',' not in source:
                    source = unfrackpath(source, follow=False)
                parse = self.parse_source(source, cache=cache)
                if parse and not parsed:
                    parsed = True

        if parsed:
            # do post processing
            self._inventory.reconcile_inventory()
        else:
            if C.INVENTORY_UNPARSED_IS_FAILED:
                raise AnsibleError(
                    "No inventory was parsed, please check your configuration and options."
                )
            else:
                display.warning(
                    "No inventory was parsed, only implicit localhost is available"
                )

        for group in self.groups.values():
            group.vars = combine_vars(
                group.vars,
                get_vars_from_inventory_sources(self._loader, self._sources,
                                                [group], 'inventory'))
        for host in self.hosts.values():
            host.vars = combine_vars(
                host.vars,
                get_vars_from_inventory_sources(self._loader, self._sources,
                                                [host], 'inventory'))
Example #35
0
    def parse(self, inventory, loader, path, cache=False):
        ''' parses the inventory file '''

        super(InventoryModule, self).parse(inventory, loader, path, cache=True)

        try:
            data = self.loader.load_from_file(path)
        except Exception as e:
            raise AnsibleParserError("Unable to parse %s: %s" %
                                     (to_native(path), to_native(e)))

        if not data:
            raise AnsibleParserError("%s is empty" % (to_native(path)))
        elif data.get('plugin') != self.NAME:
            raise AnsibleParserError(
                "%s is not a constructed groups config file, plugin entry must be 'constructed'"
                % (to_native(path)))

        strict = data.get('strict', False)
        try:
            # Go over hosts (less var copies)
            for host in inventory.hosts:

                # get available variables to templar
                hostvars = inventory.hosts[host].get_vars()
                if host in inventory.cache:  # adds facts if cache is active
                    hostvars = combine_vars(hostvars, inventory.cache[host])

                # create composite vars
                self._set_composite_vars(data.get('compose'),
                                         hostvars,
                                         host,
                                         strict=strict)

                # constructed groups based on conditionals
                self._add_host_to_composed_groups(data.get('groups'),
                                                  hostvars,
                                                  host,
                                                  strict=strict)

                # constructed groups based variable values
                self._add_host_to_keyed_groups(data.get('keyed_groups'),
                                               hostvars,
                                               host,
                                               strict=strict)

        except Exception as e:
            raise AnsibleParserError("failed to parse %s: %s " %
                                     (to_native(path), to_native(e)))
Example #36
0
    def parse(self, inventory, loader, path, cache=True):

        super(InventoryModule, self).parse(inventory, loader, path)
        self._read_config_data(path)
        self._connect_to_libvirt()
        self.inventory.add_group('libvirt')

        strict = self.get_option('strict')

        for dom in self._lv.listAllDomains():
            host = dom.name()
            LOG.info('inspecting %s', host)

            if not self.get_option('include_inactive') and \
                    dom.state() != libvirt.VIR_DOMAIN_RUNNING:
                LOG.info('skipping %s (not running)', host)
                continue

            self.inventory.add_host(host)
            self.inventory.add_child('libvirt', host)

            address = self._lookup_dom_address(host, dom)
            if address is None:
                LOG.warning('failed to find address for %s', host)
            else:
                self.inventory.set_variable(host, 'ansible_host', address)

            self._set_libvirt_vars(host, dom)

            hostvars = combine_vars(
                get_group_vars(inventory.hosts[host].get_groups()),
                inventory.hosts[host].get_vars())

            # create composite vars
            self._set_composite_vars(self.get_option('compose'),
                                     hostvars,
                                     host,
                                     strict=strict)
            # constructed groups based on conditionals
            self._add_host_to_composed_groups(self.get_option('groups'),
                                              hostvars,
                                              host,
                                              strict=strict)

            # constructed groups based variable values
            self._add_host_to_keyed_groups(self.get_option('keyed_groups'),
                                           hostvars,
                                           host,
                                           strict=strict)
Example #37
0
    def _get_host_variables(self, host):

        if context.CLIARGS['export']:
            # only get vars defined directly host
            hostvars = host.get_vars()

            # Always load vars plugins
            hostvars = combine_vars(
                hostvars,
                get_vars_from_inventory_sources(self.loader,
                                                self.inventory._sources,
                                                [host], 'all'))
            if context.CLIARGS['basedir']:
                hostvars = combine_vars(
                    hostvars,
                    get_vars_from_path(self.loader, context.CLIARGS['basedir'],
                                       [host], 'all'))
        else:
            # get all vars flattened by host, but skip magic hostvars
            hostvars = self.vm.get_vars(host=host,
                                        include_hostvars=False,
                                        stage='all')

        return self._remove_internal(hostvars)
Example #38
0
    def _get_group_variables(self, groupname, vault_password=None):

        group = self.get_group(groupname)
        if group is None:
            raise Exception("group not found: %s" % groupname)

        vars = {}

        # plugin.get_group_vars retrieves just vars for specific group
        vars_results = [
            plugin.get_group_vars(group, vault_password=vault_password)
            for plugin in self._vars_plugins
            if hasattr(plugin, 'get_group_vars')
        ]
        for updated in vars_results:
            if updated is not None:
                # FIXME: combine_vars
                vars = combine_vars(vars, updated)

        # Read group_vars/ files
        # FIXME: combine_vars
        vars = combine_vars(vars, self.get_group_vars(group))

        return vars
Example #39
0
    def _compose(self, template, variables):
        ''' helper method for plugins to compose variables for Ansible based on jinja2 expression and inventory vars'''
        t = self.templar

        try:
            use_extra = self.get_option('use_extra_vars')
        except Exception:
            use_extra = False

        if use_extra:
            t.available_variables = combine_vars(variables, self._vars)
        else:
            t.available_variables = variables

        return t.template('%s%s%s' % (t.environment.variable_start_string, template, t.environment.variable_end_string), disable_lookups=True)
 def set_playbook_basedir(self, dir_name):
     """
     sets the base directory of the playbook so inventory can use it as a
     basedir for host_ and group_vars, and other things.
     """
     # Only update things if dir is a different playbook basedir
     if dir_name != self._playbook_basedir:
         self._playbook_basedir = dir_name
         # get group vars from group_vars/ files
         # FIXME: excluding the new_pb_basedir directory may result in group_vars
         #        files loading more than they should, however with the file caching
         #        we do this shouldn't be too much of an issue. Still, this should
         #        be fixed at some point to allow a "first load" to touch all of the
         #        directories, then later runs only touch the new basedir specified
         for group in self.groups:
             #group.vars = combine_vars(group.vars, self.get_group_vars(group, new_pb_basedir=True))
             group.vars = combine_vars(group.vars, self.get_group_vars(group))
         # get host vars from host_vars/ files
         for host in self.get_hosts():
             #host.vars = combine_vars(host.vars, self.get_host_vars(host, new_pb_basedir=True))
             host.vars = combine_vars(host.vars, self.get_host_vars(host))
         # invalidate cache
         self._vars_per_host = {}
         self._vars_per_group = {}
Example #41
0
    def _get_group_variables(self, group):

        # get info from inventory source
        res = group.get_vars()

        res = combine_vars(
            res,
            get_vars_from_inventory_sources(self.loader,
                                            self.inventory._sources, [group],
                                            'inventory'))

        if group.priority != 1:
            res['ansible_group_priority'] = group.priority

        return self._remove_internal(res)
    def _get_host_variables(self, host):

        if context.CLIARGS['export']:
            # only get vars defined directly host
            hostvars = host.get_vars()

            # FIXME: add switch to skip vars plugins, add vars plugin info
            for inventory_dir in self.inventory._sources:
                hostvars = combine_vars(
                    hostvars, self.get_plugin_vars(inventory_dir, host))
        else:
            # get all vars flattened by host, but skip magic hostvars
            hostvars = self.vm.get_vars(host=host, include_hostvars=False)

        return self._remove_internal(hostvars)
Example #43
0
    def _load_role_yaml(self, subdir, main=None, allow_dir=False):
        '''
        Find and load role YAML files and return data found.
        :param subdir: subdir of role to search (vars, files, tasks, handlers, defaults)
        :type subdir: string
        :param main: filename to match, will default to 'main.<ext>' if not provided.
        :type main: string
        :param allow_dir: If true we combine results of multiple matching files found.
                          If false, highlander rules. Only for vars(dicts) and not tasks(lists).
        :type allow_dir: bool

        :returns: data from the matched file(s), type can be dict or list depending on vars or tasks.
        '''
        data = None
        file_path = os.path.join(self._role_path, subdir)
        if self._loader.path_exists(file_path) and self._loader.is_directory(file_path):
            # Valid extensions and ordering for roles is hard-coded to maintain portability
            extensions = ['.yml', '.yaml', '.json']  # same as default for YAML_FILENAME_EXTENSIONS

            # look for files w/o extensions before/after bare name depending on it being set or not
            # keep 'main' as original to figure out errors if no files found
            if main is None:
                _main = 'main'
                extensions.append('')
            else:
                _main = main
                extensions.insert(0, '')

            # not really 'find_vars_files' but find_files_with_extensions_default_to_yaml_filename_extensions
            found_files = self._loader.find_vars_files(file_path, _main, extensions, allow_dir)
            if found_files:
                for found in found_files:
                    new_data = self._loader.load_from_file(found)
                    if new_data:
                        if data is not None and isinstance(new_data, Mapping):
                            data = combine_vars(data, new_data)
                        else:
                            data = new_data

                        # found data so no need to continue unless we want to merge
                        if not allow_dir:
                            break

            elif main is not None:
                # this won't trigger with default only when <subdir>_from is specified
                raise AnsibleParserError("Could not find specified file in role: %s/%s" % (subdir, main))

        return data
Example #44
0
    def _load_inventory_file(self, path, loader):
        '''
        helper function, which loads the file and gets the
        basename of the file without the extension
        '''

        if loader.is_directory(path):
            data = dict()

            try:
                names = loader.list_directory(path)
            except os.error as err:
                raise AnsibleError("This folder cannot be listed: %s: %s." % (path, err.strerror))

            # evaluate files in a stable order rather than whatever
            # order the filesystem lists them.
            names.sort()

            # do not parse hidden files or dirs, e.g. .svn/
            paths = [os.path.join(path, name) for name in names if not name.startswith('.')]
            for p in paths:
                results = self._load_inventory_file(path=p, loader=loader)
                if results is not None:
                    data = combine_vars(data, results)

        else:
            file_name, ext = os.path.splitext(path)
            data = None
            if not ext or ext not in C.YAML_FILENAME_EXTENSIONS:
                for test_ext in C.YAML_FILENAME_EXTENSIONS:
                    new_path = path + test_ext
                    if loader.path_exists(new_path):
                        data = loader.load_from_file(new_path)
                        break
            else:
                if loader.path_exists(path):
                    data = loader.load_from_file(path)

        rval = AnsibleInventoryVarsData()
        rval.path = path

        if data is not None:
            if not isinstance(data, dict):
                raise AnsibleError("Problem parsing file '%s': line %d, column %d" % data.ansible_pos)
            else:
                rval.update(data)

        return rval
    def get_vars(self, loader, path, entities):
        super(VarsModule, self).get_vars(loader, path, entities)
        out_vars = {}
        cache = self.become_pass_cache
        for entity in entities:

            if entity not in cache:
                cache[entity] = self.get_password(entity)

            password = cache[entity]

            if password is not None:
                out_vars = combine_vars(out_vars,
                                        {'ansible_become_pass': password})

        return out_vars
            def _plugins_inventory(entities):
                ''' merges all entities by inventory source '''
                data = {}
                for inventory_dir in self._inventory._sources:
                    if ',' in inventory_dir:  # skip host lists
                        continue
                    elif not os.path.isdir(
                            inventory_dir
                    ):  # always pass 'inventory directory'
                        inventory_dir = os.path.dirname(inventory_dir)

                    for plugin in vars_loader.all():
                        data = combine_vars(
                            data,
                            _get_plugin_vars(plugin, inventory_dir, entities))
                return data
Example #47
0
    def _get_host_variables(self, host):

        if self.options.export:
            hostvars = host.get_vars()

            # FIXME: add switch to skip vars plugins
            # add vars plugin info
            for inventory_dir in self.inventory._sources:
                hostvars = combine_vars(hostvars, self.get_plugin_vars(inventory_dir, host))
        else:
            if self._new_api:
                hostvars = self.vm.get_vars(host=host, include_hostvars=False)
            else:
                hostvars = self.vm.get_vars(self.loader, host=host, include_hostvars=False)

        return hostvars
Example #48
0
    def _add_host_to_keyed_groups(self, keys, variables, host, strict=False):
        ''' helper to create groups for plugins based on variable values and add the corresponding hosts to it'''
        if keys and isinstance(keys, list):
            for keyed in keys:
                if keyed and isinstance(keyed, dict):

                    variables = combine_vars(variables, self.inventory.get_host(host).get_vars())
                    try:
                        key = self._compose(keyed.get('key'), variables)
                    except Exception as e:
                        if strict:
                            raise AnsibleParserError("Could not generate group for host %s from %s entry: %s" % (host, keyed.get('key'), to_native(e)))
                        continue

                    if key:
                        prefix = keyed.get('prefix', '')
                        sep = keyed.get('separator', '_')
                        raw_parent_name = keyed.get('parent_group', None)

                        new_raw_group_names = []
                        if isinstance(key, string_types):
                            new_raw_group_names.append(key)
                        elif isinstance(key, list):
                            for name in key:
                                new_raw_group_names.append(name)
                        elif isinstance(key, Mapping):
                            for (gname, gval) in key.items():
                                name = '%s%s%s' % (gname, sep, gval)
                                new_raw_group_names.append(name)
                        else:
                            raise AnsibleParserError("Invalid group name format, expected a string or a list of them or dictionary, got: %s" % type(key))

                        for bare_name in new_raw_group_names:
                            gname = to_safe_group_name('%s%s%s' % (prefix, sep, bare_name))
                            self.inventory.add_group(gname)
                            self.inventory.add_child(gname, host)

                            if raw_parent_name:
                                parent_name = to_safe_group_name(raw_parent_name)
                                self.inventory.add_group(parent_name)
                                self.inventory.add_child(parent_name, gname)

                    else:
                        if strict:
                            raise AnsibleParserError("No key or key resulted empty, invalid entry")
                else:
                    raise AnsibleParserError("Invalid keyed group entry, it must be a dictionary: %s " % keyed)
Example #49
0
    def set_host_overrides(self, host):
        '''
        Override WinRM-specific options from host variables.
        '''
        host_vars = combine_vars(host.get_group_vars(), host.get_vars())

        self._winrm_host = self._play_context.remote_addr
        self._winrm_port = int(self._play_context.port or 5986)
        self._winrm_scheme = host_vars.get(
            'ansible_winrm_scheme',
            'http' if self._winrm_port == 5985 else 'https')
        self._winrm_path = host_vars.get('ansible_winrm_path', '/wsman')
        self._winrm_user = self._play_context.remote_user
        self._winrm_pass = self._play_context.password

        if '@' in self._winrm_user:
            self._winrm_realm = self._winrm_user.split('@',
                                                       1)[1].strip() or None
        else:
            self._winrm_realm = None
        self._winrm_realm = host_vars.get('ansible_winrm_realm',
                                          self._winrm_realm) or None

        transport_selector = 'ssl' if self._winrm_scheme == 'https' else 'plaintext'

        if HAVE_KERBEROS and ('@' in self._winrm_user or self._winrm_realm):
            self._winrm_transport = 'kerberos,%s' % transport_selector
        else:
            self._winrm_transport = transport_selector
        self._winrm_transport = host_vars.get('ansible_winrm_transport',
                                              self._winrm_transport)
        if isinstance(self._winrm_transport, basestring):
            self._winrm_transport = [
                x.strip() for x in self._winrm_transport.split(',')
                if x.strip()
            ]

        self._winrm_kwargs = dict(username=self._winrm_user,
                                  password=self._winrm_pass,
                                  realm=self._winrm_realm)
        argspec = inspect.getargspec(Protocol.__init__)
        for arg in argspec.args:
            if arg in ('self', 'endpoint', 'transport', 'username', 'password',
                       'realm'):
                continue
            if 'ansible_winrm_%s' % arg in host_vars:
                self._winrm_kwargs[arg] = host_vars['ansible_winrm_%s' % arg]
Example #50
0
    def reconcile_inventory(self):
        ''' Ensure inventory basic rules, run after updates '''

        display.debug('Reconcile groups and hosts in inventory.')
        self.current_source = None

        group_names = set()
        # set group vars from group_vars/ files and vars plugins
        for g in self.groups:
            group = self.groups[g]
            group_names.add(group.name)

            # ensure all groups inherit from 'all'
            if group.name != 'all' and not group.get_ancestors():
                self.add_child('all', group.name)

        host_names = set()
        # get host vars from host_vars/ files and vars plugins
        for host in self.hosts.values():
            host_names.add(host.name)

            mygroups = host.get_groups()

            if self.groups['ungrouped'] in mygroups:
                # clear ungrouped of any incorrectly stored by parser
                if set(mygroups).difference(
                        set([self.groups['all'], self.groups['ungrouped']])):
                    self.groups['ungrouped'].remove_host(host)

            elif not host.implicit:
                # add ungrouped hosts to ungrouped, except implicit
                length = len(mygroups)
                if length == 0 or (length == 1
                                   and self.groups['all'] in mygroups):
                    self.add_child('ungrouped', host.name)

            # special case for implicit hosts
            if host.implicit:
                host.vars = combine_vars(self.groups['all'].get_vars(),
                                         host.vars)

        # warn if overloading identifier as both group and host
        for conflict in group_names.intersection(host_names):
            display.warning("Found both group and host with same name: %s" %
                            conflict)

        self._groups_dict_cache = {}
Example #51
0
def get_vars_from_inventory_sources(loader, sources, entities, stage):

    data = {}
    for path in sources:

        if path is None:
            continue
        if ',' in path and not os.path.exists(path):  # skip host lists
            continue
        elif not os.path.isdir(to_bytes(path)):
            # always pass the directory of the inventory source file
            path = os.path.dirname(path)

        data = combine_vars(data,
                            get_vars_from_path(loader, path, entities, stage))

    return data
Example #52
0
    def get_vars(self, loader, path, entities, cache=True):
        ''' parses the inventory file '''

        if not isinstance(entities, list):
            entities = [entities]

        super(VarsModule, self).get_vars(loader, path, entities)

        data = {}
        for entity in entities:
            if isinstance(entity, Host):
                subdir = 'host_vars'
            elif isinstance(entity, Group):
                subdir = 'group_vars'
            else:
                raise AnsibleParserError("Supplied entity must be Host or Group, got %s instead" % (type(entity)))

            # avoid 'chroot' type inventory hostnames /path/to/chroot
            if not entity.name.startswith(os.path.sep):
                try:
                    found_files = []
                    # load vars
                    opath = os.path.realpath(os.path.join(self._basedir, subdir))
                    key = '%s.%s' % (entity.name, opath)
                    if cache and key in FOUND:
                        found_files = FOUND[key]
                    else:
                        b_opath = to_bytes(opath)
                        # no need to do much if path does not exist for basedir
                        if os.path.exists(b_opath):
                            if os.path.isdir(b_opath):
                                self._display.debug("\tprocessing dir %s" % opath)
                                found_files = self._find_vars_files(opath, entity.name)
                                FOUND[key] = found_files
                            else:
                                self._display.warning("Found %s that is not a directory, skipping: %s" % (subdir, opath))

                    for found in found_files:
                        new_data = loader.load_from_file(found, cache=True, unsafe=True)
                        if new_data:  # ignore empty files
                            data = combine_vars(data, new_data)

                except Exception as e:
                    raise AnsibleParserError(to_native(e))
        return data
Example #53
0
    def _plugins_inventory(self, entities):
        import os
        from ansible.plugins.loader import vars_loader
        from ansible.utils.vars import combine_vars
        ''' merges all entities by inventory source '''
        data = {}
        for inventory_dir in self.variable_manager._inventory._sources:
            if ',' in inventory_dir:  # skip host lists
                continue
            elif not os.path.isdir(
                    inventory_dir):  # always pass 'inventory directory'
                inventory_dir = os.path.dirname(inventory_dir)

            for plugin in vars_loader.all():
                data = combine_vars(
                    data, self._get_plugin_vars(plugin, inventory_dir,
                                                entities))
        return data
Example #54
0
    def get_vars(self, loader, path, entities):
        ''' parses the inventory file '''

        if not isinstance(entities, list):
            entities = [entities]

        super(VarsModule, self).get_vars(loader, path, entities)

        data = {}
        for entity in entities:
            if isinstance(entity, Host):
                subdir = 'host_vars'
            elif isinstance(entity, Group):
                subdir = 'group_vars'
            else:
                raise AnsibleParserError(
                    "Supplied entity must be Host or Group, got %s instead" %
                    (type(entity)))

            try:
                # load vars
                opath = os.path.realpath(os.path.join(self._basedir, subdir))
                b_opath = to_bytes(opath)
                # no need to do much if path does not exist for basedir
                if os.path.exists(b_opath):
                    if os.path.isdir(b_opath):
                        self._display.debug("\tprocessing dir %s" % opath)
                        for found in self._find_vars_files(opath, entity.name):
                            self._display.debug("READING %s" % found)
                            new_data = loader.load_from_file(found,
                                                             cache=True,
                                                             unsafe=True)
                            if new_data:  # ignore empty files
                                data = combine_vars(data, new_data)
                    else:
                        self._display.warning(
                            "Found %s that is not a directory, skipping: %s" %
                            (subdir, opath))

            except Exception as e:
                raise AnsibleParserError(to_text(e))
        return data
Example #55
0
    def _add_host_to_composed_groups(self, groups, variables, host, strict=False):
        ''' helper to create complex groups for plugins based on jinja2 conditionals, hosts that meet the conditional are added to group'''
        # process each 'group entry'
        if groups and isinstance(groups, dict):
            variables = combine_vars(variables, self.inventory.get_host(host).get_vars())
            self.templar.set_available_variables(variables)
            for group_name in groups:
                conditional = "{%% if %s %%} True {%% else %%} False {%% endif %%}" % groups[group_name]
                try:
                    result = boolean(self.templar.template(conditional))
                except Exception as e:
                    if strict:
                        raise AnsibleParserError("Could not add host %s to group %s: %s" % (host, group_name, to_native(e)))
                    continue

                if result:
                    # ensure group exists
                    self.inventory.add_group(group_name)
                    # add host to group
                    self.inventory.add_child(group_name, host)
Example #56
0
    def _get_persistent_connection_options(self, connection, variables,
                                           templar):
        final_vars = combine_vars(
            variables,
            variables.get('ansible_delegated_vars',
                          dict()).get(self._task.delegate_to, dict()))

        option_vars = C.config.get_plugin_vars('connection',
                                               connection._load_name)
        for plugin in connection._sub_plugins:
            if plugin['type'] != 'external':
                option_vars.extend(
                    C.config.get_plugin_vars(plugin['type'], plugin['name']))

        options = {}
        for k in option_vars:
            if k in final_vars:
                options[k] = templar.template(final_vars[k])

        return options
Example #57
0
    def parse(self, inventory, loader, path):
        ''' parses the inventory file '''

        super(InventoryModule, self).parse(inventory, loader, path)

        try:
            data = self.loader.load_from_file(path)
        except Exception as e:
            raise AnsibleParserError("Unable to parse %s: %s" %
                                     (to_native(path), to_native(e)))

        if not data or data.get('plugin') != self.NAME:
            raise AnsibleParserError(
                "%s is empty or not a constructed groups config file" %
                (to_native(path)))

        try:
            templar = Templar(loader=loader)

            # Go over hosts (less var copies)
            for host in inventory.hosts:

                # get available variables to templar
                hostvars = host.get_vars()
                if host.name in inventory.cache:  # adds facts if cache is active
                    hostvars = combine_vars(hostvars,
                                            inventory.cache[host.name])
                templar.set_available_variables(hostvars)

                # process each 'group entry'
                for group_name, expression in data.get('groups', {}):
                    conditional = u"{%% if %s %%} True {%% else %%} False {%% endif %%}" % expression
                    result = templar.template(conditional)
                    if result and bool(result):
                        # ensure group exists
                        inventory.add_group(group_name)
                        # add host to group
                        inventory.add_child(group_name, host.name)
        except Exception as e:
            raise AnsibleParserError("failed to parse %s: %s " %
                                     (to_native(path), to_native(e)))
Example #58
0
    def _merge_hosts(self,host, newhost):
        """ Merge all of instance newhost into host """

        # name
        if host.name != newhost.name:
            raise AnsibleError("Cannot merge host %s with %s" % (host.name, newhost.name))

        # group membership relation
        for newgroup in newhost.groups:
            # dict with existing groups:
            hostgroups = dict([(g.name, g) for g in host.groups])
            # check if new group is already known as a group
            if newgroup.name not in hostgroups:
                if newgroup.name not in self.groups:
                    # group does not exist yet in self, import him
                    self.groups[newgroup.name] = newgroup
                # group now exists but doesn't have host yet
                self.groups[newgroup.name].add_host(host)

        # variables
        host.vars = combine_vars(host.vars, newhost.vars)
Example #59
0
    def get_vars(self, loader, path, entities):
        """Entry point called from Ansible to get vars."""

        if self.vault_addr is None:
            debug("VAULT_ADDR isnt set, skipping hashivault_vars plugin")
            return {}

        debug("get_vars **********************************")
        if not isinstance(entities, list):
            entities = [entities]
        debug("lookup entities:", entities)

        super(VarsModule, self).get_vars(loader, path, entities)

        data = {}
        for entity in entities:
            data = combine_vars(data, entity.vars)
            data = self._get_vars(data, entity)

        debug("get_vars: ", data)
        return data
Example #60
0
def get_vars_from_path(loader, path, entities, stage):

    data = {}

    vars_plugin_list = list(vars_loader.all())
    for plugin_name in C.VARIABLE_PLUGINS_ENABLED:
        if AnsibleCollectionRef.is_valid_fqcr(plugin_name):
            vars_plugin = vars_loader.get(plugin_name)
            if vars_plugin is None:
                # Error if there's no play directory or the name is wrong?
                continue
            if vars_plugin not in vars_plugin_list:
                vars_plugin_list.append(vars_plugin)

    for plugin in vars_plugin_list:
        if plugin._load_name not in C.VARIABLE_PLUGINS_ENABLED and getattr(
                plugin, 'REQUIRES_WHITELIST', False):
            # 2.x plugins shipped with ansible should require enabling, older or non shipped should load automatically
            continue

        has_stage = hasattr(plugin,
                            'get_option') and plugin.has_option('stage')

        # if a plugin-specific setting has not been provided, use the global setting
        # older/non shipped plugins that don't support the plugin-specific setting should also use the global setting
        use_global = (has_stage
                      and plugin.get_option('stage') is None) or not has_stage

        if use_global:
            if C.RUN_VARS_PLUGINS == 'demand' and stage == 'inventory':
                continue
            elif C.RUN_VARS_PLUGINS == 'start' and stage == 'task':
                continue
        elif has_stage and plugin.get_option('stage') not in ('all', stage):
            continue

        data = combine_vars(data,
                            get_plugin_vars(loader, plugin, path, entities))

    return data