class AnsibleHelper(object): Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become_user', 'become', 'become_method', 'check', 'extra_vars', 'listhosts', 'listtasks', 'listtags', 'syntax', ]) def __init__(self, inventory_file): self.variable_manager = vm = VariableManager() self.loader = DataLoader() self.inventory = Inventory(loader=self.loader, variable_manager=vm, host_list=inventory_file) vm.set_inventory(self.inventory) self.options_args = dict(connection='smart', module_path=None, forks=100, become=None, become_method=None, become_user=None, check=False, listhosts=False, listtasks=False, listtags=False, syntax=False, extra_vars={}) self._run_vars = None def run_playbook(self, playbook): options = self.Options(**self.options_args) vm = self.variable_manager vm.extra_vars = load_extra_vars(loader=self.loader, options=options) pbe = PlaybookExecutor( playbooks=[playbook], inventory=self.inventory, variable_manager=vm, loader=self.loader, options=options, passwords=dict(conn_pass='******'), ) res = pbe.run() self._run_vars = vm.get_vars(self.loader) return res def get_vars(self, *args, **kwargs): self.inventory.get_vars(*args, **kwargs) def get_hosts(self, *args, **kwargs): self.inventory.ger_hosts(*args, **kwargs) def get_groups(self, *args, **kwargs): self.inventory.get_groups(*args, **kwargs) @property def run_vars(self): return self._run_vars
class AnsibleInventory(object): def __init__(self, inventory_generator): """ :type inventory_generator: ops.inventory.generator.InventoryGenerator """ self.inventory_generator = inventory_generator self.generated_path, self.ssh_config_path = inventory_generator.generate( ) # clean up variables cache for tests ansible_vars.VARIABLE_CACHE = dict() ansible_vars.HOSTVARS_CACHE = dict() ansible_inventory.HOSTS_PATTERNS_CACHE = dict() self.variable_manager = VariableManager() loader = DataLoader() self.inventory = Inventory(loader=loader, variable_manager=self.variable_manager, host_list=self.generated_path) self.variable_manager.set_inventory(self.inventory) self.inventory.set_playbook_basedir(self.generated_path) def get_hosts(self, limit): return self.inventory.get_hosts(limit) def get_host(self, host): return self.inventory.get_host(unicode(host)) def get_vars(self, host): return self.inventory.get_vars(unicode(host)) def get_ssh_config(self): return self.ssh_config_path
def find_host_in_inventory(base, host_name): loader = DataLoader() var_manager = VariableManager() host_vars = None host_info = [] for i in get_inventory_files(base): try: inv = Inventory(host_list='%s/%s' %(base, i), loader=loader, variable_manager=var_manager) host_vars = inv.get_vars(host_name) except AnsibleError as err: # print '%s in inventory %s' %(err, i) inv.host_list = None inv.refresh_inventory() continue if host_vars: ssh_host = host_vars.get('ansible_ssh_host', None) ssh_user = host_vars.get('ansible_ssh_user', None) ssh_key = host_vars.get('ansible_ssh_private_key_file', None) ssh_port = host_vars.get('ansible_ssh_port', 22) else: raise Exception('Host %s is not present in any inventory %s' %(host_name, ' '.join(get_inventory_files(base)))) if not ssh_host or not ssh_user: raise Exception('ansible_ssh_host and ansible_ssh_user required.') host_info.append(str('%s@%s' %(ssh_user, ssh_host))) if ssh_key: ssh_key = os.path.expanduser(ssh_key) if not os.path.isabs(ssh_key): ssh_key = os.path.abspath(ssh_key) if os.path.exists(ssh_key): host_info += ['-i', str(ssh_key)] else: print ("SSH key %s doesn't exists please check path." %(ssh_key)) if ssh_port: if not int(ssh_port) == min(max(int(ssh_port), 0), 65535): raise Exception('Incorrect port number given') host_info += ['-p', str(ssh_port)] return host_info
def run(self): # Note: slightly wrong, this is written so that implicit localhost # Manage passwords sshpass = None becomepass = None b_vault_pass = None passwords = {} # initial error check, to make sure all specified playbooks are accessible # before we start running anything through the playbook executor for playbook in self.playbooks: if not os.path.exists(playbook): raise 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 AnsibleError( "the playbook: %s does not appear to be a file" % playbook) # don't deal with privilege escalation or passwords when we don't need to if not self.options.listhosts and not self.options.listtasks and not self.options.listtags and not self.options.syntax: self.normalize_become_options() (sshpass, becomepass) = self.ask_passwords() passwords = {'conn_pass': sshpass, 'become_pass': becomepass} loader = DataLoader() if self.options.vault_password_file: # read vault_pass from a file b_vault_pass = CLI.read_vault_password_file( self.options.vault_password_file, loader=loader) loader.set_vault_password(b_vault_pass) elif self.options.ask_vault_pass: b_vault_pass = self.ask_vault_passwords() loader.set_vault_password(b_vault_pass) elif 'VAULT_PASS' in os.environ: loader.set_vault_password(os.environ['VAULT_PASS']) # create the variable manager, which will be shared throughout # the code, ensuring a consistent view of global variables variable_manager = VariableManager() # Subspace injection option_extra_vars = load_extra_vars(loader=loader, options=self.options) option_extra_vars.update(self.extra_vars) variable_manager.extra_vars = option_extra_vars # End Subspace injection variable_manager.options_vars = load_options_vars(self.options) # create the inventory, and filter it based on the subset specified (if any) inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=self.options.inventory) variable_manager.set_inventory(inventory) # (which is not returned in list_hosts()) is taken into account for # warning if inventory is empty. But it can't be taken into account for # checking if limit doesn't match any hosts. Instead we don't worry about # limit if only implicit localhost was in inventory to start with. # # Fix this when we rewrite inventory by making localhost a real host (and thus show up in list_hosts()) no_hosts = False if len(inventory.list_hosts()) == 0: # Empty inventory display.warning( "provided hosts list is empty, only localhost is available") no_hosts = True inventory.subset(self.options.subset) if len(inventory.list_hosts()) == 0 and no_hosts is False: # Invalid limit raise AnsibleError("Specified --limit does not match any hosts") # flush fact cache if requested if self.options.flush_cache: self._flush_cache(inventory, variable_manager) hosts = inventory.get_hosts() if self.options.subset and not hosts: raise NoValidHosts( "The limit <%s> is not included in the inventory: %s" % (self.options.subset, inventory.host_list)) # create the playbook executor, which manages running the plays via a task queue manager # Subspace injection pbex = PlaybookExecutor(playbooks=self.playbooks, inventory=inventory, variable_manager=variable_manager, loader=loader, options=self.options, passwords=passwords) playbook_map = self._get_playbook_map() pbex._tqm._stats = SubspaceAggregateStats(playbook_map) pbex._tqm.load_callbacks() pbex._tqm.send_callback( 'start_logging', logger=self.options.logger, username=self.extra_vars.get('ATMOUSERNAME', "No-User"), ) for host in inventory._subset: variables = inventory.get_vars(host) self.options.logger.info("Vars found for hostname %s: %s" % (host, variables)) # End Subspace injection results = pbex.run() # Subspace injection stats = pbex._tqm._stats self.stats = stats # Nonpersistent fact cache stores 'register' variables. We would like # to get access to stdout/stderr for specific commands and relay # some of that information back to the end user. self.results = dict(pbex._variable_manager._nonpersistent_fact_cache) # End Subspace injection if isinstance(results, list): for p in results: display.display('\nplaybook: %s' % p['playbook']) for idx, play in enumerate(p['plays']): if play._included_path is not None: loader.set_basedir(play._included_path) else: pb_dir = os.path.realpath( os.path.dirname(p['playbook'])) loader.set_basedir(pb_dir) msg = "\n play #%d (%s): %s" % (idx + 1, ','.join( play.hosts), play.name) mytags = set(play.tags) msg += '\tTAGS: [%s]' % (','.join(mytags)) if self.options.listhosts: playhosts = set(inventory.get_hosts(play.hosts)) msg += "\n pattern: %s\n hosts (%d):" % ( play.hosts, len(playhosts)) for host in playhosts: msg += "\n %s" % host display.display(msg) all_tags = set() if self.options.listtags or self.options.listtasks: taskmsg = '' if self.options.listtasks: taskmsg = ' tasks:\n' def _process_block(b): taskmsg = '' for task in b.block: if isinstance(task, Block): taskmsg += _process_block(task) else: if task.action == 'meta': continue all_tags.update(task.tags) if self.options.listtasks: cur_tags = list( mytags.union(set(task.tags))) cur_tags.sort() if task.name: taskmsg += " %s" % task.get_name( ) else: taskmsg += " %s" % task.action taskmsg += "\tTAGS: [%s]\n" % ', '.join( cur_tags) return taskmsg all_vars = variable_manager.get_vars(loader=loader, play=play) play_context = PlayContext(play=play, options=self.options) for block in play.compile(): block = block.filter_tagged_tasks( play_context, all_vars) if not block.has_tasks(): continue taskmsg += _process_block(block) if self.options.listtags: cur_tags = list(mytags.union(all_tags)) cur_tags.sort() taskmsg += " TASK TAGS: [%s]\n" % ', '.join( cur_tags) display.display(taskmsg) return 0 else: return results
def _main(): global tab_size parser = argparse.ArgumentParser( description="Convert the Ansible inventory from INI to yML format", ) parser.add_argument("-i", dest="inventory_file", help="Inform the Ansible Vault Password", required=True) parser.add_argument( "-d", dest="dest_inventory_path", help= "Destination to save the inventory files (Default will be on $PWD)", required=False) parser.add_argument( "-g", dest="group", help="Filter by specific GROUP", ) parser.add_argument( "-p", dest="vault_password", help="Inform the Ansible Vault Password or file with password", ) parser.add_argument( "-t", dest="tab_size", type=int, help="Number of tab spaces", default=4, ) args = parser.parse_args() tab_size = args.tab_size try: # Ansible: initialize needed objects variable_manager = VariableManager() loader = DataLoader() if args.vault_password: if os.path.isfile(args.vault_password): with open(args.vault_password, "r") as f: args.vault_password = f.readlines()[0].rstrip() f.close() print("** Passing Vault Password: '******'") % (args.vault_password) loader.set_vault_password(args.vault_password) # Ansible: Load inventory inventory = Inventory( loader=loader, variable_manager=variable_manager, host_list=args.inventory_file, ) except Exception as e: print("** ERROR: Missing the '--vault-password'??\n %s\n") % str(e) sys.exit(-1) try: groups = {} if args.group: _group = inventory.get_group(args.group) if not _group: print("** ERROR: No such group '%s' in inventory file '%s', exiting.") % \ (args.group, args.inventory_file) sys.exit(-1) groups[args.group] = _group else: groups = inventory.get_groups() for group in groups: if group == "all": continue # start the file output = "" output += "###################################################################################################\n" output += ("# Converted from '%s[%s]'\n") % (args.inventory_file, group) output += "###################################################################################################\n" output += ("%s:\n") % group group_ref = inventory.get_group(group) # children or hosts? if group_ref.child_groups: output += ident_as_usual(1, "children") for group_name in sorted(group_ref.child_groups): output += ident_as_usual(2, group_name.get_name()) else: group_ips = group_ref.hosts if not group_ips: continue output += "" output += ident_as_usual(1, "hosts") for group_ip in sorted(group_ips): if filter_vars(group_ip): continue output += ident_as_usual(2, group_ip.get_name()) _ip_host_vars = inventory.get_host_vars( group_ip, return_results=True) # group_vars/$group _ip_vars = inventory.get_vars( to_native(group_ip)) # host key1=var1 group_ip_vars = dict(_ip_host_vars.items() + _ip_vars.items()) if not group_ip_vars: continue for k, v in group_ip_vars.items(): if filter_vars(k): continue output += ident_as_the_key(3, k, v) # group_vars/$service output += "\n" output += ident_as_usual(1, "vars") group_vars = inventory.get_group_vars(group_ref, return_results=True) if group_vars: for k, v in sorted(group_vars.items()): if filter_vars(k): continue output += ident_as_the_key(2, k, v) output += "\n" output += ("# End for %s\n") % group if not args.dest_inventory_path: print(output) else: dest = args.dest_inventory_path + "/" + group + ".yml" print("Generating " + dest) try: dest_dir = os.path.dirname(dest) os.makedirs(dest_dir) except OSError as e: if e.errno != errno.EEXIST: raise f = file(dest, "w+") f.write(output) f.close() # Should save the 'group_vars/all' ? src = "group_vars/all" if args.dest_inventory_path and os.path.isfile(src): dest = args.dest_inventory_path + "/" + src print("Copying '%s' to '%s'") % (src, dest) try: dest_dir = os.path.dirname(dest) os.makedirs(dest_dir) except OSError as e: if e.errno != errno.EEXIST: raise shutil.copyfile(src, dest) except Exception as e: print("** ERROR: %s\n") % str(e) traceback.print_exc()