Пример #1
0
    def _load_playbook_from_file(self, path, vars={}):
        '''
        run top level error checking on playbooks and allow them to include other playbooks.
        '''

        playbook_data  = utils.parse_yaml_from_file(path)
        accumulated_plays = []
        play_basedirs = []

        if type(playbook_data) != list:
            raise errors.AnsibleError("parse error: playbooks must be formatted as a YAML list")

        basedir = os.path.dirname(path)
        utils.plugins.push_basedir(basedir)
        for play in playbook_data:
            if type(play) != dict:
                raise errors.AnsibleError("parse error: each play in a playbook must a YAML dictionary (hash), recieved: %s" % play)
            if 'include' in play:
                if len(play.keys()) <= 2:
                    tokens = shlex.split(play['include'])

                    items = ['']
                    for k in play.keys():
                        if not k.startswith("with_"):
                            continue
                        plugin_name = k[5:]
                        if plugin_name not in utils.plugins.lookup_loader:
                            raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name))
                        terms = utils.template_ds(basedir, play[k], vars)
                        items = utils.plugins.lookup_loader.get(plugin_name, basedir=basedir, runner=None).run(terms, inject=vars)
                        break

                    for item in items:
                        incvars = vars.copy()
                        incvars['item'] = item
                        for t in tokens[1:]:
                            (k,v) = t.split("=", 1)
                            incvars[k] = utils.template_ds(basedir, v, incvars)
                        included_path = utils.path_dwim(basedir, tokens[0])
                        (plays, basedirs) = self._load_playbook_from_file(included_path, incvars)
                        for p in plays:
                            if 'vars' not in p:
                                p['vars'] = {}
                            if isinstance(p['vars'], dict):
                                p['vars'].update(incvars)
                            elif isinstance(p['vars'], list):
                                p['vars'].extend([dict(k=v) for k,v in incvars.iteritems()])
                        accumulated_plays.extend(plays)
                        play_basedirs.extend(basedirs)

                else:
                    raise errors.AnsibleError("parse error: playbook includes cannot be used with other directives: %s" % play)
            else:
                accumulated_plays.append(play)
                play_basedirs.append(basedir)

        return (accumulated_plays, play_basedirs)
Пример #2
0
    def _load_tasks(self, tasks, vars={}, additional_conditions=[]):
        ''' handle task and handler include statements '''

        results = []
        if tasks is None:
            # support empty handler files, and the like.
            tasks = []

        for x in tasks:
            task_vars = self.vars.copy()
            task_vars.update(vars)
            if 'include' in x:
                tokens = shlex.split(x['include'])
                items = ['']
                included_additional_conditions = list(additional_conditions)
                for k in x:
                    if k.startswith("with_"):
                        plugin_name = k[5:]
                        if plugin_name not in utils.plugins.lookup_loader:
                            raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name))
                        terms = utils.template_ds(self.basedir, x[k], task_vars)
                        items = utils.plugins.lookup_loader.get(plugin_name, basedir=self.basedir, runner=None).run(terms, inject=task_vars)
                    elif k.startswith("when_"):
                        included_additional_conditions.append(utils.compile_when_to_only_if("%s %s" % (k[5:], x[k])))
                    elif k in ("include", "vars", "only_if"):
                        pass
                    else:
                        raise errors.AnsibleError("parse error: task includes cannot be used with other directives: %s" % k)

                if 'vars' in x:
                    task_vars.update(x['vars'])
                if 'only_if' in x:
                    included_additional_conditions.append(x['only_if'])

                for item in items:
                    mv = task_vars.copy()
                    mv['item'] = item
                    for t in tokens[1:]:
                        (k,v) = t.split("=", 1)
                        mv[k] = utils.template_ds(self.basedir, v, mv)
                    include_file = utils.template(self.basedir, tokens[0], mv)
                    data = utils.parse_yaml_from_file(utils.path_dwim(self.basedir, include_file))
                    results += self._load_tasks(data, mv, included_additional_conditions)
            elif type(x) == dict:
                results.append(Task(self,x,module_vars=task_vars, additional_conditions=additional_conditions))
            else:
                raise Exception("unexpected task type")

        for x in results:
            if self.tags is not None:
                x.tags.extend(self.tags)

        return results
Пример #3
0
    def _load_tasks(self, ds, keyname):
        ''' handle task and handler include statements '''

        tasks = ds.get(keyname, [])
        results = []
        for x in tasks:
            if 'include' in x:
                task_vars = self.vars.copy()
                tokens = shlex.split(x['include'])
                items = ['']
                for k in x:
                    if not k.startswith("with_"):
                        continue
                    plugin_name = k[5:]
                    if plugin_name not in utils.plugins.lookup_loader:
                        raise errors.AnsibleError(
                            "cannot find lookup plugin named %s for usage in with_%s"
                            % (plugin_name, plugin_name))
                    terms = utils.template_ds(self.basedir, x[k], task_vars)
                    items = utils.plugins.lookup_loader.get(
                        plugin_name, basedir=self.basedir,
                        runner=None).run(terms, inject=task_vars)

                for item in items:
                    mv = task_vars.copy()
                    mv['item'] = item
                    for t in tokens[1:]:
                        (k, v) = t.split("=", 1)
                        mv[k] = utils.template_ds(self.basedir, v, mv)
                    include_file = utils.template(self.basedir, tokens[0], mv)
                    data = utils.parse_yaml_from_file(
                        utils.path_dwim(self.basedir, include_file))
                    for y in data:
                        results.append(Task(self, y, module_vars=mv.copy()))
            elif type(x) == dict:
                task_vars = self.vars.copy()
                results.append(Task(self, x, module_vars=task_vars))
            else:
                raise Exception("unexpected task type")

        for x in results:
            if self.tags is not None:
                x.tags.extend(self.tags)

        return results
Пример #4
0
    def __init__(self, playbook, ds, basedir):
        ''' constructor loads from a play datastructure '''

        for x in ds.keys():
            if not x in Play.VALID_KEYS:
                raise errors.AnsibleError(
                    "%s is not a legal parameter in an Ansible Playbook" % x)

        # TODO: more error handling

        hosts = ds.get('hosts')
        if hosts is None:
            raise errors.AnsibleError('hosts declaration is required')
        elif isinstance(hosts, list):
            hosts = ';'.join(hosts)
        self._ds = ds
        self.playbook = playbook
        self.basedir = basedir
        self.vars = ds.get('vars', {})
        self.vars_files = ds.get('vars_files', [])
        self.vars_prompt = ds.get('vars_prompt', {})
        self.vars = self._get_vars()
        self.hosts = utils.template(basedir, hosts, self.vars)
        self.name = ds.get('name', self.hosts)
        self._tasks = ds.get('tasks', [])
        self._handlers = ds.get('handlers', [])
        self.remote_user = utils.template(
            basedir, ds.get('user', self.playbook.remote_user), self.vars)
        self.remote_port = ds.get('port', self.playbook.remote_port)
        self.sudo = ds.get('sudo', self.playbook.sudo)
        self.sudo_user = utils.template(
            basedir, ds.get('sudo_user', self.playbook.sudo_user), self.vars)
        self.transport = ds.get('connection', self.playbook.transport)
        self.tags = ds.get('tags', None)
        self.gather_facts = ds.get('gather_facts', None)
        self.serial = int(
            utils.template_ds(basedir, ds.get('serial', 0), self.vars))

        if isinstance(self.remote_port, basestring):
            self.remote_port = utils.template(basedir, self.remote_port,
                                              self.vars)

        self._update_vars_files_for_host(None)

        self._tasks = self._load_tasks(self._ds.get('tasks', []))
        self._handlers = self._load_tasks(self._ds.get('handlers', []))

        if self.tags is None:
            self.tags = []
        elif type(self.tags) in [str, unicode]:
            self.tags = [self.tags]
        elif type(self.tags) != list:
            self.tags = []

        if self.sudo_user != 'root':
            self.sudo = True
Пример #5
0
    def __init__(self, playbook, ds, basedir):
        ''' constructor loads from a play datastructure '''

        for x in ds.keys():
            if not x in Play.VALID_KEYS:
                raise errors.AnsibleError("%s is not a legal parameter in an Ansible Playbook" % x)

        # TODO: more error handling

        hosts = ds.get('hosts')
        if hosts is None:
            raise errors.AnsibleError('hosts declaration is required')
        elif isinstance(hosts, list):
            hosts = ';'.join(hosts)
        self._ds          = ds
        self.playbook     = playbook
        self.basedir      = basedir
        self.vars         = ds.get('vars', {})
        self.vars_files   = ds.get('vars_files', [])
        self.vars_prompt  = ds.get('vars_prompt', {})
        self.vars         = self._get_vars()
        self.hosts        = utils.template(basedir, hosts, self.vars)
        self.name         = ds.get('name', self.hosts)
        self._tasks       = ds.get('tasks', [])
        self._handlers    = ds.get('handlers', [])
        self.remote_user  = utils.template(basedir, ds.get('user', self.playbook.remote_user), self.vars)
        self.remote_port  = ds.get('port', self.playbook.remote_port)
        self.sudo         = ds.get('sudo', self.playbook.sudo)
        self.sudo_user    = utils.template(basedir, ds.get('sudo_user', self.playbook.sudo_user), self.vars)
        self.transport    = ds.get('connection', self.playbook.transport)
        self.tags         = ds.get('tags', None)
        self.gather_facts = ds.get('gather_facts', None)
        self.serial       = int(utils.template_ds(basedir, ds.get('serial', 0), self.vars))

        if isinstance(self.remote_port, basestring):
            self.remote_port = utils.template(basedir, self.remote_port, self.vars)

        self._update_vars_files_for_host(None)

        self._tasks      = self._load_tasks(self._ds.get('tasks', []))
        self._handlers   = self._load_tasks(self._ds.get('handlers', []))

        if self.tags is None:
            self.tags = []
        elif type(self.tags) in [ str, unicode ]:
            self.tags = [ self.tags ]
        elif type(self.tags) != list:
            self.tags = []

        if self.sudo_user != 'root':
            self.sudo = True
Пример #6
0
    def _executor_internal(self, host):
        ''' executes any module one or more times '''

        host_variables = self.inventory.get_variables(host)
        if self.transport in ['paramiko', 'ssh']:
            port = host_variables.get('ansible_ssh_port', self.remote_port)
            if port is None:
                port = C.DEFAULT_REMOTE_PORT
        else:
            # fireball, local, etc
            port = self.remote_port

        inject = {}
        inject.update(host_variables)
        inject.update(self.module_vars)
        inject.update(self.setup_cache[host])
        inject['hostvars'] = HostVars(self.setup_cache, self.inventory)
        inject['group_names'] = host_variables.get('group_names', [])
        inject['groups'] = self.inventory.groups_list()

        # allow with_foo to work in playbooks...
        items = None
        items_plugin = self.module_vars.get('items_lookup_plugin', None)
        if items_plugin is not None and items_plugin in utils.plugins.lookup_loader:
            items_terms = self.module_vars.get('items_lookup_terms', '')
            items_terms = utils.template_ds(self.basedir, items_terms, inject)
            items = utils.plugins.lookup_loader.get(items_plugin,
                                                    runner=self,
                                                    basedir=self.basedir).run(
                                                        items_terms,
                                                        inject=inject)
            if type(items) != list:
                raise errors.AnsibleError(
                    "lookup plugins have to return a list: %r" % items)

            if len(items) and self.module_name in ['apt', 'yum']:
                # hack for apt and soon yum, with_items maps back into a single module call
                inject['item'] = ",".join(items)
                items = None

        # logic to decide how to run things depends on whether with_items is used

        if items is None:
            return self._executor_internal_inner(host, self.module_name,
                                                 self.module_args, inject,
                                                 port)
        elif len(items) > 0:
            # executing using with_items, so make multiple calls
            # TODO: refactor
            aggregrate = {}
            all_comm_ok = True
            all_changed = False
            all_failed = False
            results = []
            for x in items:
                inject['item'] = x
                result = self._executor_internal_inner(host, self.module_name,
                                                       self.module_args,
                                                       inject, port)
                results.append(result.result)
                if result.comm_ok == False:
                    all_comm_ok = False
                    all_failed = True
                    break
                for x in results:
                    if x.get('changed') == True:
                        all_changed = True
                    if (x.get('failed') == True) or (('rc' in x) and
                                                     (x['rc'] != 0)):
                        all_failed = True
                        break
            msg = 'All items completed'
            if all_failed:
                msg = "One or more items failed."
            rd_result = dict(failed=all_failed,
                             changed=all_changed,
                             results=results,
                             msg=msg)
            if not all_failed:
                del rd_result['failed']
            return ReturnData(host=host, comm_ok=all_comm_ok, result=rd_result)
        else:
            self.callbacks.on_skipped(host, None)
            return ReturnData(host=host,
                              comm_ok=True,
                              result=dict(skipped=True))
Пример #7
0
    def _load_tasks(self, tasks, vars={}, additional_conditions=[]):
        ''' handle task and handler include statements '''

        results = []
        if tasks is None:
            # support empty handler files, and the like.
            tasks = []

        for x in tasks:
            task_vars = self.vars.copy()
            task_vars.update(vars)
            if 'include' in x:
                tokens = shlex.split(x['include'])
                items = ['']
                included_additional_conditions = list(additional_conditions)
                for k in x:
                    if k.startswith("with_"):
                        plugin_name = k[5:]
                        if plugin_name not in utils.plugins.lookup_loader:
                            raise errors.AnsibleError(
                                "cannot find lookup plugin named %s for usage in with_%s"
                                % (plugin_name, plugin_name))
                        terms = utils.template_ds(self.basedir, x[k],
                                                  task_vars)
                        items = utils.plugins.lookup_loader.get(
                            plugin_name, basedir=self.basedir,
                            runner=None).run(terms, inject=task_vars)
                    elif k.startswith("when_"):
                        included_additional_conditions.append(
                            utils.compile_when_to_only_if("%s %s" %
                                                          (k[5:], x[k])))
                    elif k in ("include", "vars", "only_if"):
                        pass
                    else:
                        raise errors.AnsibleError(
                            "parse error: task includes cannot be used with other directives: %s"
                            % k)

                if 'vars' in x:
                    task_vars.update(x['vars'])
                if 'only_if' in x:
                    included_additional_conditions.append(x['only_if'])

                for item in items:
                    mv = task_vars.copy()
                    mv['item'] = item
                    for t in tokens[1:]:
                        (k, v) = t.split("=", 1)
                        mv[k] = utils.template_ds(self.basedir, v, mv)
                    include_file = utils.template(self.basedir, tokens[0], mv)
                    data = utils.parse_yaml_from_file(
                        utils.path_dwim(self.basedir, include_file))
                    results += self._load_tasks(
                        data, mv, included_additional_conditions)
            elif type(x) == dict:
                results.append(
                    Task(self,
                         x,
                         module_vars=task_vars,
                         additional_conditions=additional_conditions))
            else:
                raise Exception("unexpected task type")

        for x in results:
            if self.tags is not None:
                x.tags.extend(self.tags)

        return results
Пример #8
0
    def _load_playbook_from_file(self, path, vars={}):
        '''
        run top level error checking on playbooks and allow them to include other playbooks.
        '''

        playbook_data  = utils.parse_yaml_from_file(path)
        accumulated_plays = []
        play_basedirs = []

        if type(playbook_data) != list:
            raise errors.AnsibleError("parse error: playbooks must be formatted as a YAML list")

        basedir = os.path.dirname(path) or '.'
        utils.plugins.push_basedir(basedir)
        for play in playbook_data:
            if type(play) != dict:
                raise errors.AnsibleError("parse error: each play in a playbook must a YAML dictionary (hash), recieved: %s" % play)
            if 'include' in play:
                tokens = shlex.split(play['include'])

                items = ['']
                for k in play.keys():
                    if not k.startswith("with_"):
                        # These are the keys allowed to be mixed with playbook includes
                        if k in ("include", "vars"):
                            continue
                        else:
                            raise errors.AnsibleError("parse error: playbook includes cannot be used with other directives: %s" % play)
                    plugin_name = k[5:]
                    if plugin_name not in utils.plugins.lookup_loader:
                        raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name))
                    terms = utils.template_ds(basedir, play[k], vars)
                    items = utils.plugins.lookup_loader.get(plugin_name, basedir=basedir, runner=None).run(terms, inject=vars)

                for item in items:
                    incvars = vars.copy()
                    incvars['item'] = item
                    if 'vars' in play:
                        if isinstance(play['vars'], dict):
                            incvars.update(play['vars'])
                        elif isinstance(play['vars'], list):
                            for v in play['vars']:
                                incvars.update(v)
                    for t in tokens[1:]:
                        (k,v) = t.split("=", 1)
                        incvars[k] = utils.template_ds(basedir, v, incvars)
                    included_path = utils.path_dwim(basedir, tokens[0])
                    (plays, basedirs) = self._load_playbook_from_file(included_path, incvars)
                    for p in plays:
                        if 'vars' not in p:
                            p['vars'] = {}
                        if isinstance(p['vars'], dict):
                            p['vars'].update(incvars)
                        elif isinstance(p['vars'], list):
                            p['vars'].extend([dict(k=v) for k,v in incvars.iteritems()])
                    accumulated_plays.extend(plays)
                    play_basedirs.extend(basedirs)
            else:
                accumulated_plays.append(play)
                play_basedirs.append(basedir)

        return (accumulated_plays, play_basedirs)
Пример #9
0
    def _executor_internal(self, host):
        ''' executes any module one or more times '''

        host_variables = self.inventory.get_variables(host)
        if self.transport in [ 'paramiko', 'ssh' ]:
            port = host_variables.get('ansible_ssh_port', self.remote_port)
            if port is None:
                port = C.DEFAULT_REMOTE_PORT
        else:
            # fireball, local, etc
            port = self.remote_port

        inject = {}
        inject.update(host_variables)
        inject.update(self.module_vars)
        inject.update(self.setup_cache[host])
        inject['hostvars'] = HostVars(self.setup_cache, self.inventory)
        inject['group_names'] = host_variables.get('group_names', [])
        inject['groups'] = self.inventory.groups_list()

        # allow with_foo to work in playbooks...
        items = None
        items_plugin = self.module_vars.get('items_lookup_plugin', None)
        if items_plugin is not None and items_plugin in utils.plugins.lookup_loader:
            items_terms = self.module_vars.get('items_lookup_terms', '')
            items_terms = utils.template_ds(self.basedir, items_terms, inject)
            items = utils.plugins.lookup_loader.get(items_plugin, runner=self, basedir=self.basedir).run(items_terms, inject=inject)
            if type(items) != list:
                raise errors.AnsibleError("lookup plugins have to return a list: %r" % items)

            if len(items) and self.module_name in [ 'apt', 'yum' ]:
                # hack for apt and soon yum, with_items maps back into a single module call
                inject['item'] = ",".join(items)
                items = None

        # logic to decide how to run things depends on whether with_items is used

        if items is None:
            return self._executor_internal_inner(host, self.module_name, self.module_args, inject, port)
        elif len(items) > 0:
            # executing using with_items, so make multiple calls
            # TODO: refactor
            aggregrate = {}
            all_comm_ok = True
            all_changed = False
            all_failed = False
            results = []
            for x in items:
                inject['item'] = x
                result = self._executor_internal_inner(host, self.module_name, self.module_args, inject, port)
                results.append(result.result)
                if result.comm_ok == False:
                    all_comm_ok = False
                    all_failed = True
                    break
                for x in results:
                    if x.get('changed') == True:
                        all_changed = True
                    if (x.get('failed') == True) or (('rc' in x) and (x['rc'] != 0)):
                        all_failed = True
                        break
            msg = 'All items completed'
            if all_failed:
                msg = "One or more items failed."
            rd_result = dict(failed=all_failed, changed=all_changed, results=results, msg=msg)
            if not all_failed:
                del rd_result['failed']
            return ReturnData(host=host, comm_ok=all_comm_ok, result=rd_result)
        else:
            self.callbacks.on_skipped(host, None)
            return ReturnData(host=host, comm_ok=True, result=dict(skipped=True))