class General(object): def __init__(self): self.cli = PlaybookCLI(sys.argv, callback=CallbackModule) self.cli.parse() def run(self): sshpass = None becomepass = None passwords = {} if not self.cli.options.listhosts and not self.cli.options.listtasks and not self.cli.options.listtags and not self.cli.options.syntax: self.cli.normalize_become_options() (sshpass, becomepass) = self.cli.ask_passwords() passwords = {'conn_pass': sshpass, 'become_pass': becomepass} loader, inventory, variable_manager = self.cli._play_prereqs( self.cli.options) for playbook_path in self.cli.args: pb = Playbook.load(playbook_path, variable_manager=variable_manager, loader=loader) plays = pb.get_plays() for play in plays: tqm = None try: tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=self.cli.options, passwords=passwords, stdout_callback=CallbackModule(), ) tqm.run(play) finally: if tqm is not None: tqm.cleanup()
b_playbook_dirs.append(b_playbook_dir) set_collection_playbook_paths(b_playbook_dirs) playbook_collection = get_collection_name_from_path(b_playbook_dirs[0]) if playbook_collection: display.warning( "running playbook inside collection {0}".format(playbook_collection)) AnsibleCollectionLoader().set_default_collection(playbook_collection) # don't deal with privilege escalation or passwords when we don't need to if not (context.CLIARGS['listhosts'] or context.CLIARGS['listtasks'] or context.CLIARGS['listtags'] or context.CLIARGS['syntax']): (sshpass, becomepass) = pb_cli.ask_passwords() passwords = {'conn_pass': sshpass, 'become_pass': becomepass} # create base objects loader, inventory, variable_manager = pb_cli._play_prereqs() # Fix this when we rewrite inventory by making localhost a real host (and thus show up in list_hosts()) hosts = CLI.get_host_list(inventory, context.CLIARGS['subset']) # flush fact cache if requplaybook_pathested if context.CLIARGS['flush_cache']: pb_cli._flush_cache(inventory, variable_manager) ###################################################################### # Execute the playbook file
def default(self): verbose = self.app.pargs.verbose init(autoreset=True) if len(self.app.pargs.extra_arguments) == 0: self.app.args.print_help() print(Fore.RED + 'Error! You must specify a playbook file to run') sys.exit(1) if str(self.app.pargs.become_method).upper() not in [ 'SUDO', 'SU', 'PBRUN', 'PFEXEC', 'DOAS', 'DZDO', 'KSU', 'RUNAS' ]: print( Fore.RED + 'Error! Become method must be one of sudo, su, pbrun, pfexec, doas, dzdo, ksu or runas.' ) sys.exit(1) #if len(self.app.pargs.extra_arguments) > 0: playbook_path = self.app.pargs.extra_arguments[0] if len( self.app.pargs.extra_arguments) > 0 else "site.yml" if not os.path.isfile(playbook_path): print(Fore.RED + 'Error! The playbook file does not exist') sys.exit(1) inventory_path = self.app.pargs.inventory if not os.path.isfile(inventory_path): print(Fore.RED + 'Error! The inventory file does not exist.') sys.exit(1) # Most of the code from here down is straight copy & paste from ansible source code, # with a few tweaks/hacks to clean up variables that we don't want to emit in the generated # YAML. loader = DataLoader() pb_cli = PlaybookCLI(sys.argv[1:]) pb_cli.parse() # !!!!! WARNING: THESE WILL BE INCLUDED IN THE GENERATED YAML FILE !!!!! (ssh_pass, become_pass) = pb_cli.ask_passwords() passwords = {'conn_pass': ssh_pass, 'become_pass': become_pass} vault_pass = None if self.app.pargs.ask_vault_pass: vault_pass = pb_cli.ask_vault_passwords() else: vault_pass = pb_cli.read_vault_password_file( self.app.pargs.vault_password_file, loader) if vault_pass is not None: loader.set_vault_password(vault_pass) # create the inventory, and filter it based on the subset specified (if any) host_list = self.app.pargs.inventory if self.app.pargs.inventory else constants.DEFAULT_HOST_LIST # FIXME: This should parse any arguments provided via -e or --extra-vars. Currently it seems # to parse the argument value wrongly and returns # '_raw_params': '<last character in variable>'. This prevents the ability to use # --extra-vars when executing plays. variable_manager = VariableManager() options = Options( verbosity=self.app.pargs.verbose, inventory=self.app.pargs.inventory, subset=self.app.pargs.limit, extra_vars=[self.app.pargs.extra_vars], forks=self.app.pargs.forks, ask_vault_pass=self.app.pargs.ask_vault_pass, vault_password_files=self.app.pargs.vault_password_file, tags=self.app.pargs.tags, skip_tags=self.app.pargs.skip_tags, become=self.app.pargs.become, become_method=self.app.pargs.become_method, become_user=self.app.pargs.become_user, become_ask_pass=self.app.pargs.ask_become_pass, ask_pass=self.app.pargs.ask_pass, private_key_file=self.app.pargs.private_key, remote_user=self.app.pargs.user, connection=self.app.pargs.connection, timeout=self.app.pargs.timeout, ssh_common_args=self.app.pargs.ssh_common_args, sftp_extra_args=self.app.pargs.sftp_extra_args, ssh_extra_args=self.app.pargs.ssh_extra_args, scp_extra_args=self.app.pargs.scp_extra_args, flush_cache=self.app.pargs.flush_cache, module_path=self.app.pargs.module_path) inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=host_list) variable_manager.extra_vars = load_extra_vars(loader=loader, options=options) #variable_manager.options_vars = load_options_vars(options) if self.app.pargs.flush_cache: inventory.refresh_inventory() no_hosts = False if len(inventory.list_hosts()) == 0: print( Fore.YELLOW + "Warning! Provided hosts list is empty, only localhost is available." ) no_hosts = True # FIXME: Limit is currently ignored. inventory.subset(self.app.pargs.limit) if len(inventory.list_hosts()) == 0 and no_hosts is False: # Invalid limit print(Fore.RED + "Error! Specified --limit does not match any hosts.") sys.exit(1) play_data = loader.load_from_file(playbook_path) host_list = inventory.get_hosts( pattern=self.app.pargs.limit ) if self.app.pargs.limit else inventory.get_hosts() playbook = Playbook(loader=loader).load( playbook_path, variable_manager=variable_manager, loader=loader) pbex = PlaybookExecutor(playbooks=playbook.get_plays(), inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords) # Ansible variables matching these strings will be excluded from the generated yaml content. ignored_elements = [ 'ansible_playbook_python', 'ansible_version', 'group_names', 'inventory_hostname', 'inventory_hostname_short', 'omit', 'playbook_dir', 'role_names' ] json_data = {} for host in host_list: host_vars = host.get_vars() host_name = host_vars[ 'ansible_host'] if 'ansible_host' in host_vars.keys( ) else host.get_name() for play in playbook.get_plays(): loader.set_vault_password(vault_pass) all_vars = variable_manager.get_vars(loader=loader, play=play, host=host) json_data[host_name] = all_vars['vars'] json_data[host_name]['ansible_groups'] = all_vars[ 'group_names'] json_data[host_name]['ansible_roles'] = all_vars['role_names'] for elem in ignored_elements: del json_data['{}'.format(host)][elem] json_data[host_name][ 'ansible_become_user'] = self.app.pargs.become_user if passwords['become_pass'] is not None: json_data[host_name]['ansible_become_pass'] = passwords[ 'become_pass'] json_data[host_name]['ansible_become'] = self.app.pargs.become json_data[host_name][ 'ansible_become_method'] = self.app.pargs.become_method if self.app.pargs.ssh_extra_args: json_data[host_name][ 'ansible_ssh_extra_args'] = self.app.pargs.ssh_extra_args if self.app.pargs.scp_extra_args: json_data[host_name][ 'ansible_scp_extra_args'] = self.app.pargs.scp_extra_args if self.app.pargs.sftp_extra_args: json_data[host_name][ 'ansible_sftp_extra_args'] = self.app.pargs.sftp_extra_args if self.app.pargs.ssh_common_args: json_data[host_name][ 'ansible_ssh_common_args'] = self.app.pargs.ssh_common_args json_data[host_name][ 'ansible_connection_timeout'] = self.app.pargs.timeout json_data[host_name][ 'ansible_connection_method'] = self.app.pargs.connection if self.app.pargs.private_key: json_data[host_name][ 'ansible_private_key'] = self.app.pargs.private_key json_data[host_name][ 'ansible_ask_pass'] = self.app.pargs.ask_pass if self.app.pargs.limit: json_data[host_name][ 'ansible_limit'] = self.app.pargs.limit # FIXME: Extra vars needs to be processed by Ansible instead of dumping them # here as a "dumb" string. if self.app.pargs.extra_vars: json_data[host_name][ 'ansible_extra_vars'] = self.app.pargs.extra_vars for key, value in json_data[host_name].iteritems(): if type(value) is AnsibleVaultEncryptedUnicode: json_data[host_name][key] = str(value) # Convert the processed python dictionary to a valid json string json_obj = json.dumps(json_data) # Take the json string, and convert it to a valid yaml string yml = YAML(typ="safe", pure=True) yml.default_flow_style = False yml_obj = yml.load(json_obj) if self.app.pargs.output is None: yml.dump(yml_obj, sys.stdout) else: with open(self.app.pargs.output, 'w') as outfile: yml.dump(yml_obj, outfile) print(Fore.GREEN + "Ansible variable dictionary written to {}".format( self.app.pargs.output)) sys.exit(1)