def _parse(self, data): all = Group("all") ungrouped = Group("ungrouped") all.add_child_group(ungrouped) self.groups = dict(all=all, ungrouped=ungrouped) yaml = utils.parse_yaml(data) for item in yaml: if type(item) in [str, unicode]: host = self._make_host(item) ungrouped.add_host(host) elif type(item) == dict and "host" in item: host = self._make_host(item["host"]) vars = item.get("vars", {}) if type(vars) == list: varlist, vars = vars, {} for subitem in varlist: vars.update(subitem) for (k, v) in vars.items(): host.set_variable(k, v) elif type(item) == dict and "group" in item: group = Group(item["group"]) for subresult in item.get("hosts", []): if type(subresult) in [str, unicode]: host = self._make_host(subresult) group.add_host(host) elif type(subresult) == dict: host = self._make_host(subresult["host"]) vars = subresult.get("vars", {}) if type(vars) == list: for subitem in vars: for (k, v) in subitem.items(): host.set_variable(k, v) elif type(vars) == dict: for (k, v) in subresult.get("vars", {}).items(): host.set_variable(k, v) else: raise errors.AnsibleError("unexpected type for variable") group.add_host(host) vars = item.get("vars", {}) if type(vars) == dict: for (k, v) in item.get("vars", {}).items(): group.set_variable(k, v) elif type(vars) == list: for subitem in vars: if type(subitem) != dict: raise errors.AnsibleError("expected a dictionary") for (k, v) in subitem.items(): group.set_variable(k, v) self.groups[group.name] = group all.add_child_group(group)
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): args = {} if complex_args: args.update(complex_args) args.update(utils.parse_kv(module_args)) path = args.get("path") if not path: raise errors.AnsibleError('"path" is a required argument') gpg_path = args.get("gpg", "gpg") gpg = subprocess.Popen([gpg_path, "-q", "-d", path], stdout=subprocess.PIPE) stdout, _stderr = gpg.communicate() if gpg.returncode != 0: raise errors.AnsibleError("error calling gpg") try: gpg_vars = utils.parse_yaml(stdout) except yaml.YAMLError, ex: utils.process_yaml_error(ex, stdout, path)
def _include_handlers(self, play, handler, dirname, new_handlers): ''' load handlers from external files ''' path = utils.path_dwim(dirname, handler['include']) inject_vars = self._get_vars(play, dirname) included = utils.template_from_file(path, inject_vars) included = utils.parse_yaml(included) for x in included: new_handlers.append(x)
def boilerplate_module(modfile, args, interpreter, check): """ simulate what ansible does with new style modules """ #module_fh = open(modfile) #module_data = module_fh.read() #module_fh.close() replacer = module_common.ModuleReplacer() #included_boilerplate = module_data.find(module_common.REPLACER) != -1 or module_data.find("import ansible.module_utils") != -1 complex_args = {} if args.startswith("@"): # Argument is a YAML file (JSON is a subset of YAML) complex_args = utils.combine_vars(complex_args, utils.parse_yaml_from_file(args[1:])) args = '' elif args.startswith("{"): # Argument is a YAML document (not a file) complex_args = utils.combine_vars(complex_args, utils.parse_yaml(args)) args = '' inject = {} 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 inject[interpreter_type] = interpreter_path if check: complex_args['CHECKMODE'] = True (module_data, module_style, shebang) = replacer.modify_module(modfile, complex_args, args, inject) modfile2_path = os.path.expanduser("~/.ansible_module_generated") print "* including generated source, if any, saving to: %s" % modfile2_path 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, module_style)
def _include_tasks(self, play, task, dirname, new_tasks): ''' load tasks included from external files. ''' # include: some.yml a=2 b=3 c=4 include_tokens = task['include'].split() path = utils.path_dwim(dirname, include_tokens[0]) inject_vars = self._get_vars(play, dirname) for i,x in enumerate(include_tokens): if x.find("=") != -1: (k,v) = x.split("=") inject_vars[k] = v included = utils.template_from_file(path, inject_vars) included = utils.parse_yaml(included) for x in included: new_tasks.append(x)
def parse_extra_vars(extras, vault_pass=None): inject_ansible_paths() from ansible import utils extra_vars = {} for extra_vars_opt in extras: if extra_vars_opt.startswith("@"): # Argument is a YAML file (JSON is a subset of YAML) kw = {} if vault_pass: kw['vault_password'] = vault_pass extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml_from_file(extra_vars_opt[1:]), **kw) elif extra_vars_opt and extra_vars_opt[0] in '[{': # Arguments as YAML extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml(extra_vars_opt)) else: # Arguments as Key-value extra_vars = utils.combine_vars(extra_vars, utils.parse_kv(extra_vars_opt)) return extra_vars
def _include_tasks(self, play, task, dirname, new_tasks): ''' load tasks included from external files. ''' # include: some.yml a=2 b=3 c=4 include_tokens = task['include'].split() path = utils.path_dwim(dirname, include_tokens[0]) play_vars = self._get_vars(play, dirname) include_vars = {} for i, x in enumerate(include_tokens): if x.find("=") != -1: (k, v) = x.split("=") include_vars[k] = v inject_vars = play_vars.copy() inject_vars.update(include_vars) included = utils.template_from_file(path, inject_vars) included = utils.parse_yaml(included) for x in included: if len(include_vars): x["vars"] = include_vars new_tasks.append(x)
def init(self): """ To instantiate a new environment, we create a set of inventory files for that environment. See individual playbooks for more info. """ # additional options which need to be processed with the init command for extra_vars_opt in self.options.extra_vars: self.extra_vars = utils.combine_vars(self.extra_vars, utils.parse_yaml(extra_vars_opt)) # basic string checking to prevent failures later in playbook if not re.match('^[a-zA-z]{1}[a-zA-Z0-9-]*', self.options.env_name): raise ValidationError( 'The environment name must match the following\ regexp: "[a-zA-z]{1}[a-zA-Z0-9-]*" ') # check to make sure this inventory does not already exist if (os.path.isdir((config['env_path'] + self.options.env_name)) and not self.options.force): raise ValidationError( 'There is already an environment with name "%s". Use -f, --force to \ update the inventory variables for this environment. ' % self.options.env_name) # check that this is one of the working regions if self.extra_vars['region'] not in config['regions']: raise ValidationError( 'Only the following regions are possible when using this tool due to \ availability of the ECS-optimized images used to run the Docker app: {}'.format( config['regions'])) # TODO: validate images, eip and cloudformation limits? playbooks = ['init.yml'] playbook_context = PlaybookExecution( playbooks, config, self.proj_inventory_path, self.options, self.extra_vars) playbook_context.run() return {'playbook_results': playbook_context, 'env': self}
return _load_vars_from_path(target, results) # directory if stat.S_ISDIR(pathstat.st_mode): # support organizing variables across multiple files in a directory return True, _load_vars_from_folder(path, results, vault_password=vault_password) # regular file elif stat.S_ISREG(pathstat.st_mode): gpg = subprocess.Popen(['gpg', "--batch", "-q", "-d", path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, _stderr = gpg.communicate() if gpg.returncode != 0: raise errors.AnsibleError("error calling gpg") data = utils.parse_yaml(stdout) if type(data) != dict: raise errors.AnsibleError( "%s must be stored as a dictionary/hash" % path) # combine vars overrides by default but can be configured to do a # hash merge in settings results = utils.combine_vars(results, data) return True, results # something else? could be a fifo, socket, device, etc. else: raise errors.AnsibleError("Expected a variable file or directory " "but found a non-file object at path %s" % (path, ))
def _parse(self, data): all = Group('all') ungrouped = Group('ungrouped') all.add_child_group(ungrouped) self.groups = dict(all=all, ungrouped=ungrouped) grouped_hosts = [] yaml = utils.parse_yaml(data) # first add all groups for item in yaml: if type(item) == dict and 'group' in item: group = Group(item['group']) for subresult in item.get('hosts',[]): if type(subresult) in [ str, unicode ]: host = self._make_host(subresult) group.add_host(host) grouped_hosts.append(host) elif type(subresult) == dict: host = self._make_host(subresult['host']) vars = subresult.get('vars',{}) if type(vars) == list: for subitem in vars: for (k,v) in subitem.items(): host.set_variable(k,v) elif type(vars) == dict: for (k,v) in subresult.get('vars',{}).items(): host.set_variable(k,v) else: raise errors.AnsibleError("unexpected type for variable") group.add_host(host) grouped_hosts.append(host) vars = item.get('vars',{}) if type(vars) == dict: for (k,v) in item.get('vars',{}).items(): group.set_variable(k,v) elif type(vars) == list: for subitem in vars: if type(subitem) != dict: raise errors.AnsibleError("expected a dictionary") for (k,v) in subitem.items(): group.set_variable(k,v) self.groups[group.name] = group all.add_child_group(group) # add host definitions for item in yaml: if type(item) in [ str, unicode ]: host = self._make_host(item) if host not in grouped_hosts: ungrouped.add_host(host) elif type(item) == dict and 'host' in item: host = self._make_host(item['host']) vars = item.get('vars', {}) if type(vars)==list: varlist, vars = vars, {} for subitem in varlist: vars.update(subitem) for (k,v) in vars.items(): host.set_variable(k,v) if host not in grouped_hosts: ungrouped.add_host(host)
def deploy(args): # create parser for CLI options parser = utils.base_parser( constants=C, usage = "%prog playbook.yml", connect_opts=True, runas_opts=True, subset_opts=True, check_opts=True, diff_opts=True ) parser.add_option('-e', '--extra-vars', dest="extra_vars", action="append", help="set additional variables as key=value or YAML/JSON", default=[]) options, args = parser.parse_args(args) if len(args) == 0: parser.print_help(file=sys.stderr) return 1 inventory = ansible.inventory.Inventory(options.inventory) inventory.subset(options.subset) print "number of hosts: %s" % str(len(inventory.list_hosts())) if len(inventory.list_hosts()) == 0: raise errors.AnsibleError("provided hosts list is empty") sshpass = None sudopass = None su_pass = None vault_pass = None options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS if options.connection == "local": options.ask_pass = False options.ask_sudo_pass = options.ask_sudo_pass or C.DEFAULT_ASK_SUDO_PASS (sshpass, sudopass, su_pass, vault_pass) = \ utils.ask_passwords(ask_pass=options.ask_pass, ask_sudo_pass=options.ask_sudo_pass, ask_su_pass=options.ask_su_pass, ask_vault_pass=options.ask_vault_pass) options.sudo_user = options.sudo_user or C.DEFAULT_SUDO_USER options.su_user = options.su_user or C.DEFAULT_SU_USER extra_vars={} for extra_vars_opt in options.extra_vars: if extra_vars_opt.startswith("@"): # Argument is a YAML file (JSON is a subset of YAML) extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml_from_file(extra_vars_opt[1:])) elif extra_vars_opt and extra_vars_opt[0] in '[{': # Arguments as YAML extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml(extra_vars_opt)) else: # Arguments as Key-value extra_vars = utils.combine_vars(extra_vars, utils.parse_kv(extra_vars_opt)) playbook = underwear.__path__[0] + '/django-stack.yml' inventory.set_playbook_basedir(os.path.dirname(playbook)) stats = callbacks.AggregateStats() playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY) if not os.path.exists(playbook): raise errors.AnsibleError("the playbook: %s could not be found" % \ playbook) if not (os.path.isfile(playbook) or \ stat.S_ISFIFO(os.stat(playbook).st_mode)): raise errors.AnsibleError( \ "the playbook: %s does not appear to be a file" % playbook) pb = ansible.playbook.PlayBook( playbook=playbook, module_path=options.module_path, inventory=inventory, forks=options.forks, remote_user=options.remote_user, remote_pass=sshpass, callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats, timeout=options.timeout, transport=options.connection, sudo=options.sudo, sudo_user=options.sudo_user, sudo_pass=sudopass, extra_vars=extra_vars, private_key_file=options.private_key_file, only_tags=['all',], skip_tags=None, check=options.check, diff=options.diff ) failed_hosts = [] unreachable_hosts = [] try: pb.run() hosts = sorted(pb.stats.processed.keys()) print hosts display(callbacks.banner("PLAY RECAP")) playbook_cb.on_stats(pb.stats) for h in hosts: t = pb.stats.summarize(h) if t['failures'] > 0: failed_hosts.append(h) if t['unreachable'] > 0: unreachable_hosts.append(h) retries = failed_hosts + unreachable_hosts if len(retries) > 0: filename = pb.generate_retry_inventory(retries) if filename: display(" to retry, use: --limit @%s\n" % filename) for h in hosts: t = pb.stats.summarize(h) display("%s : %s %s %s %s" % ( hostcolor(h, t), colorize('ok', t['ok'], 'green'), colorize('changed', t['changed'], 'yellow'), colorize('unreachable', t['unreachable'], 'red'), colorize('failed', t['failures'], 'red')), screen_only=True ) display("%s : %s %s %s %s" % ( hostcolor(h, t, False), colorize('ok', t['ok'], None), colorize('changed', t['changed'], None), colorize('unreachable', t['unreachable'], None), colorize('failed', t['failures'], None)), log_only=True ) print "" if len(failed_hosts) > 0: return 2 if len(unreachable_hosts) > 0: return 3 except errors.AnsibleError, e: display("ERROR: %s" % e, color='red') return 1
def deploy(args): # create parser for CLI options parser = utils.base_parser(constants=C, usage="%prog playbook.yml", connect_opts=True, runas_opts=True, subset_opts=True, check_opts=True, diff_opts=True) parser.add_option( '-e', '--extra-vars', dest="extra_vars", action="append", help="set additional variables as key=value or YAML/JSON", default=[]) options, args = parser.parse_args(args) if len(args) == 0: parser.print_help(file=sys.stderr) return 1 inventory = ansible.inventory.Inventory(options.inventory) inventory.subset(options.subset) print "number of hosts: %s" % str(len(inventory.list_hosts())) if len(inventory.list_hosts()) == 0: raise errors.AnsibleError("provided hosts list is empty") sshpass = None sudopass = None su_pass = None vault_pass = None options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS if options.connection == "local": options.ask_pass = False options.ask_sudo_pass = options.ask_sudo_pass or C.DEFAULT_ASK_SUDO_PASS (sshpass, sudopass, su_pass, vault_pass) = \ utils.ask_passwords(ask_pass=options.ask_pass, ask_sudo_pass=options.ask_sudo_pass, ask_su_pass=options.ask_su_pass, ask_vault_pass=options.ask_vault_pass) options.sudo_user = options.sudo_user or C.DEFAULT_SUDO_USER options.su_user = options.su_user or C.DEFAULT_SU_USER extra_vars = {} for extra_vars_opt in options.extra_vars: if extra_vars_opt.startswith("@"): # Argument is a YAML file (JSON is a subset of YAML) extra_vars = utils.combine_vars( extra_vars, utils.parse_yaml_from_file(extra_vars_opt[1:])) elif extra_vars_opt and extra_vars_opt[0] in '[{': # Arguments as YAML extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml(extra_vars_opt)) else: # Arguments as Key-value extra_vars = utils.combine_vars(extra_vars, utils.parse_kv(extra_vars_opt)) playbook = underwear.__path__[0] + '/django-stack.yml' inventory.set_playbook_basedir(os.path.dirname(playbook)) stats = callbacks.AggregateStats() playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY) if not os.path.exists(playbook): raise errors.AnsibleError("the playbook: %s could not be found" % \ playbook) if not (os.path.isfile(playbook) or \ stat.S_ISFIFO(os.stat(playbook).st_mode)): raise errors.AnsibleError( \ "the playbook: %s does not appear to be a file" % playbook) pb = ansible.playbook.PlayBook(playbook=playbook, module_path=options.module_path, inventory=inventory, forks=options.forks, remote_user=options.remote_user, remote_pass=sshpass, callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats, timeout=options.timeout, transport=options.connection, sudo=options.sudo, sudo_user=options.sudo_user, sudo_pass=sudopass, extra_vars=extra_vars, private_key_file=options.private_key_file, only_tags=[ 'all', ], skip_tags=None, check=options.check, diff=options.diff) failed_hosts = [] unreachable_hosts = [] try: pb.run() hosts = sorted(pb.stats.processed.keys()) print hosts display(callbacks.banner("PLAY RECAP")) playbook_cb.on_stats(pb.stats) for h in hosts: t = pb.stats.summarize(h) if t['failures'] > 0: failed_hosts.append(h) if t['unreachable'] > 0: unreachable_hosts.append(h) retries = failed_hosts + unreachable_hosts if len(retries) > 0: filename = pb.generate_retry_inventory(retries) if filename: display(" to retry, use: --limit @%s\n" % filename) for h in hosts: t = pb.stats.summarize(h) display("%s : %s %s %s %s" % (hostcolor(h, t), colorize('ok', t['ok'], 'green'), colorize('changed', t['changed'], 'yellow'), colorize('unreachable', t['unreachable'], 'red'), colorize('failed', t['failures'], 'red')), screen_only=True) display("%s : %s %s %s %s" % (hostcolor(h, t, False), colorize('ok', t['ok'], None), colorize('changed', t['changed'], None), colorize('unreachable', t['unreachable'], None), colorize('failed', t['failures'], None)), log_only=True) print "" if len(failed_hosts) > 0: return 2 if len(unreachable_hosts) > 0: return 3 except errors.AnsibleError, e: display("ERROR: %s" % e, color='red') return 1
tmp_vault_pass=f.read().strip() f.close() except (OSError, IOError), e: raise errors.AnsibleError("Could not read %s: %s" % (this_path, e)) if not options.ask_vault_pass: vault_pass = tmp_vault_pass extra_vars = {} for extra_vars_opt in options.extra_vars: if extra_vars_opt.startswith("@"): # Argument is a YAML file (JSON is a subset of YAML) extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml_from_file(extra_vars_opt[1:], vault_password=vault_pass)) elif extra_vars_opt and extra_vars_opt[0] in '[{': # Arguments as YAML extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml(extra_vars_opt)) else: # Arguments as Key-value extra_vars = utils.combine_vars(extra_vars, utils.parse_kv(extra_vars_opt)) only_tags = options.tags.split(",") skip_tags = options.skip_tags if options.skip_tags is not None: skip_tags = options.skip_tags.split(",") for playbook in args: if not os.path.exists(playbook): raise errors.AnsibleError("the playbook: %s could not be found" % playbook) if not (os.path.isfile(playbook) or stat.S_ISFIFO(os.stat(playbook).st_mode)): raise errors.AnsibleError("the playbook: %s does not appear to be a file" % playbook)
def __call__(self, argv, help): import ansible.playbook import ansible.constants as C from ansible import errors from ansible import callbacks from mr.awsome.ansible.inventory import Inventory from ansible import utils from ansible.color import ANSIBLE_COLOR, stringc parser = utils.base_parser( constants=C, connect_opts=True, runas_opts=True, subset_opts=True, check_opts=True, diff_opts=True, usage='aws playbook playbook.yml' ) parser.remove_option('-i') parser.remove_option('-k') parser.add_option('-e', '--extra-vars', dest="extra_vars", action="append", help="set additional variables as key=value or YAML/JSON", default=[]) parser.add_option('-t', '--tags', dest='tags', default='all', help="only run plays and tasks tagged with these values") parser.add_option('--skip-tags', dest='skip_tags', help="only run plays and tasks whose tags do not match these values") parser.add_option('--syntax-check', dest='syntax', action='store_true', help="perform a syntax check on the playbook, but do not execute it") parser.add_option('--list-tasks', dest='listtasks', action='store_true', help="list all tasks that would be executed") parser.add_option('--step', dest='step', action='store_true', help="one-step-at-a-time: confirm each task before running") parser.add_option('--start-at-task', dest='start_at', help="start the playbook at the task matching this name") options, args = parser.parse_args(argv) cbs = callbacks.CliRunnerCallbacks() cbs.options = options if len(args) == 0: parser.print_help(file=sys.stderr) sys.exit(1) def colorize(lead, num, color): """ Print 'lead' = 'num' in 'color' """ if num != 0 and ANSIBLE_COLOR and color is not None: return "%s%s%-15s" % (stringc(lead, color), stringc("=", color), stringc(str(num), color)) else: return "%s=%-4s" % (lead, str(num)) def hostcolor(host, stats, color=True): if ANSIBLE_COLOR and color: if stats['failures'] != 0 or stats['unreachable'] != 0: return "%-37s" % stringc(host, 'red') elif stats['changed'] != 0: return "%-37s" % stringc(host, 'yellow') else: return "%-37s" % stringc(host, 'green') return "%-26s" % host try: patch_connect(self.aws) inventory = Inventory(self.aws) sudopass = None if not options.listhosts and not options.syntax and not options.listtasks: options.ask_sudo_pass = options.ask_sudo_pass or C.DEFAULT_ASK_SUDO_PASS sudopass = utils.ask_passwords(ask_sudo_pass=options.ask_sudo_pass) if options.sudo_user or options.ask_sudo_pass: options.sudo = True options.sudo_user = options.sudo_user or C.DEFAULT_SUDO_USER extra_vars = {} for extra_vars_opt in options.extra_vars: if extra_vars_opt.startswith("@"): # Argument is a YAML file (JSON is a subset of YAML) extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml_from_file(extra_vars_opt[1:])) elif extra_vars_opt and extra_vars_opt[0] in '[{': # Arguments as YAML extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml(extra_vars_opt)) else: # Arguments as Key-value extra_vars = utils.combine_vars(extra_vars, utils.parse_kv(extra_vars_opt)) only_tags = options.tags.split(",") skip_tags = options.skip_tags if options.skip_tags is not None: skip_tags = options.skip_tags.split(",") for playbook in args: if not os.path.exists(playbook): raise errors.AnsibleError("the playbook: %s could not be found" % playbook) # run all playbooks specified on the command line for playbook in args: # let inventory know which playbooks are using so it can know the basedirs inventory.set_playbook_basedir(os.path.dirname(playbook)) stats = callbacks.AggregateStats() playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) if options.step: playbook_cb.step = options.step if options.start_at: playbook_cb.start_at = options.start_at runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY) pb = ansible.playbook.PlayBook( playbook=playbook, module_path=options.module_path, inventory=inventory, forks=options.forks, remote_user=options.remote_user, callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats, timeout=options.timeout, transport=options.connection, sudo=options.sudo, sudo_user=options.sudo_user, sudo_pass=sudopass, extra_vars=extra_vars, private_key_file=options.private_key_file, only_tags=only_tags, skip_tags=skip_tags, check=options.check, diff=options.diff ) if options.listhosts or options.listtasks or options.syntax: print '' print 'playbook: %s' % playbook print '' playnum = 0 for (play_ds, play_basedir) in zip(pb.playbook, pb.play_basedirs): playnum += 1 play = ansible.playbook.Play(pb, play_ds, play_basedir) label = play.name if options.listhosts: hosts = pb.inventory.list_hosts(play.hosts) print ' play #%d (%s): host count=%d' % (playnum, label, len(hosts)) for host in hosts: print ' %s' % host if options.listtasks: matched_tags, unmatched_tags = play.compare_tags(pb.only_tags) # Remove skipped tasks matched_tags = matched_tags - set(pb.skip_tags) unmatched_tags.discard('all') unknown_tags = ((set(pb.only_tags) | set(pb.skip_tags)) - (matched_tags | unmatched_tags)) if unknown_tags: continue print ' play #%d (%s):' % (playnum, label) for task in play.tasks(): if (set(task.tags).intersection(pb.only_tags) and not set(task.tags).intersection(pb.skip_tags)): if getattr(task, 'name', None) is not None: # meta tasks have no names print ' %s' % task.name print '' continue if options.syntax: # if we've not exited by now then we are fine. print 'Playbook Syntax is fine' sys.exit(0) failed_hosts = [] unreachable_hosts = [] pb.run() hosts = sorted(pb.stats.processed.keys()) callbacks.display(callbacks.banner("PLAY RECAP")) playbook_cb.on_stats(pb.stats) for h in hosts: t = pb.stats.summarize(h) if t['failures'] > 0: failed_hosts.append(h) if t['unreachable'] > 0: unreachable_hosts.append(h) retries = failed_hosts + unreachable_hosts if len(retries) > 0: filename = pb.generate_retry_inventory(retries) if filename: callbacks.display(" to retry, use: --limit @%s\n" % filename) for h in hosts: t = pb.stats.summarize(h) callbacks.display("%s : %s %s %s %s" % ( hostcolor(h, t), colorize('ok', t['ok'], 'green'), colorize('changed', t['changed'], 'yellow'), colorize('unreachable', t['unreachable'], 'red'), colorize('failed', t['failures'], 'red')), screen_only=True ) callbacks.display("%s : %s %s %s %s" % ( hostcolor(h, t, False), colorize('ok', t['ok'], None), colorize('changed', t['changed'], None), colorize('unreachable', t['unreachable'], None), colorize('failed', t['failures'], None)), log_only=True ) print "" if len(failed_hosts) > 0: sys.exit(2) if len(unreachable_hosts) > 0: sys.exit(3) except errors.AnsibleError, e: callbacks.display("ERROR: %s" % e, color='red', stderr=True) sys.exit(1)