class Runner(object):
    def __init__(self, playbook, display, hosts=None, options={}, passwords={}, vault_pass=None):

        self.options = Options()
        for k, v in options.iteritems():
            setattr(self.options, k, v)

        self.display = display
        self.display.verbosity = self.options.verbosity
        # executor has its own verbosity setting
        playbook_executor.verbosity = self.options.verbosity

        # gets data from YAML/JSON files
        self.loader = DataLoader()
        if vault_pass is not None:
            self.loader.set_vault_password(vault_pass)
        elif 'VAULT_PASS' in os.environ:
            self.loader.set_vault_password(os.environ['VAULT_PASS'])

        # all the variables from all the various places
        self.variable_manager = VariableManager()
        if self.options.python_interpreter is not None:
            self.variable_manager.extra_vars = {
                'ansible_python_interpreter': self.options.python_interpreter
            }

        # set inventory, using most of above objects
        self.inventory = Inventory(
            loader=self.loader, variable_manager=self.variable_manager,
            host_list=hosts)

        if len(self.inventory.list_hosts()) == 0:
            self.display.error("Provided hosts list is empty.")
            sys.exit(1)

        self.inventory.subset(self.options.subset)

        if len(self.inventory.list_hosts()) == 0:
            self.display.error("Specified limit does not match any hosts.")
            sys.exit(1)

        self.variable_manager.set_inventory(self.inventory)

        # setup playbook executor, but don't run until run() called
        self.pbex = playbook_executor.PlaybookExecutor(
            playbooks=[playbook],
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=passwords)

    def run(self):
        # run playbook and get stats
        self.pbex.run()
        stats = self.pbex._tqm._stats

        return stats
Exemple #2
0
    def test_leading_range(self):
        i = Inventory(os.path.join(self.test_dir, 'inventory','test_leading_range'))
        hosts = i.list_hosts('test')
        expected_hosts=['1.host','2.host','A.host','B.host']
        assert sorted(hosts) == sorted(expected_hosts)

        hosts2 = i.list_hosts('test2')
        expected_hosts2=['1.host','2.host','3.host']
        assert sorted(hosts2) == sorted(expected_hosts2)
Exemple #3
0
    def test_leading_range(self):
        i = Inventory(os.path.join(self.test_dir, "inventory", "test_leading_range"))
        hosts = i.list_hosts("test")
        expected_hosts = ["1.host", "2.host", "A.host", "B.host"]
        assert sorted(hosts) == sorted(expected_hosts)

        hosts2 = i.list_hosts("test2")
        expected_hosts2 = ["1.host", "2.host", "3.host"]
        assert sorted(hosts2) == sorted(expected_hosts2)
Exemple #4
0
    def pytest_generate_tests(self, metafunc):
        log.debug("pytest_generate_tests() called")

        if 'ansible_host' in metafunc.fixturenames:
            # assert required --ansible-* parameters were used
            self.assert_required_ansible_parameters()
            # TODO: this doesn't support function/cls fixture overrides
            try:
                inventory_manager = Inventory(self.config.getvalue('ansible_inventory'))
            except ansible.errors.AnsibleError, e:
                raise pytest.UsageError(e)
            pattern = self.config.getvalue('ansible_host_pattern')
            metafunc.parametrize("ansible_host", inventory_manager.list_hosts(pattern))
Exemple #5
0
def get_hosts(hostfile, pattern):
    hosts = []
    inventory = Inventory(hostfile)
    hosts = inventory.list_hosts(pattern)
    return hosts
Exemple #6
0
    def run(self):

        super(PlaybookCLI, self).run()

        # Note: slightly wrong, this is written so that implicit localhost
        # Manage passwords
        sshpass = None
        becomepass = None
        vault_pass = None
        passwords = {}

        # 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
            vault_pass = CLI.read_vault_password_file(
                self.options.vault_password_file, loader=loader)
            loader.set_vault_password(vault_pass)
        elif self.options.ask_vault_pass:
            vault_pass = self.ask_vault_passwords()[0]
            loader.set_vault_password(vault_pass)

        # initial error check, to make sure all specified playbooks are accessible
        # before we start running anything through the playbook executor
        for playbook in self.args:
            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)

        # create the variable manager, which will be shared throughout
        # the code, ensuring a consistent view of global variables
        variable_manager = VariableManager()
        variable_manager.extra_vars = load_extra_vars(loader=loader,
                                                      options=self.options)

        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:
            for host in inventory.list_hosts():
                variable_manager.clear_facts(host)

        # create the playbook executor, which manages running the plays via a task queue manager
        pbex = PlaybookExecutor(playbooks=self.args,
                                inventory=inventory,
                                variable_manager=variable_manager,
                                loader=loader,
                                options=self.options,
                                passwords=passwords)

        results = pbex.run()

        if isinstance(results, list):
            for p in results:

                display.display('\nplaybook: %s' % p['playbook'])
                for idx, play in enumerate(p['plays']):
                    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
Exemple #7
0
    def run(self):

        # Note: slightly wrong, this is written so that implicit localhost
        # Manage passwords
        sshpass = None
        becomepass = None
        vault_pass = None
        passwords = {}

        # 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}

        if self.options.vault_password_file:
            # read vault_pass from a file
            vault_pass = read_vault_file(self.options.vault_password_file)
        elif self.options.ask_vault_pass:
            vault_pass = self.ask_vault_passwords(ask_vault_pass=True,
                                                  ask_new_vault_pass=False,
                                                  confirm_new=False)[0]

        loader = DataLoader(vault_password=vault_pass)

        extra_vars = {}
        for extra_vars_opt in self.options.extra_vars:
            extra_vars_opt = to_unicode(extra_vars_opt, errors='strict')
            if extra_vars_opt.startswith(u"@"):
                # Argument is a YAML file (JSON is a subset of YAML)
                data = loader.load_from_file(extra_vars_opt[1:])
            elif extra_vars_opt and extra_vars_opt[0] in u'[{':
                # Arguments as YAML
                data = loader.load(extra_vars_opt)
            else:
                # Arguments as Key-value
                data = parse_kv(extra_vars_opt)
            extra_vars = combine_vars(extra_vars, data)

        # FIXME: this should be moved inside the playbook executor code
        only_tags = self.options.tags.split(",")
        skip_tags = self.options.skip_tags
        if self.options.skip_tags is not None:
            skip_tags = self.options.skip_tags.split(",")

        # initial error check, to make sure all specified playbooks are accessible
        # before we start running anything through the playbook executor
        for playbook in self.args:
            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)

        # create the variable manager, which will be shared throughout
        # the code, ensuring a consistent view of global variables
        variable_manager = VariableManager()
        variable_manager.extra_vars = extra_vars

        # 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
            self.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")

        # create the playbook executor, which manages running the plays via a task queue manager
        pbex = PlaybookExecutor(playbooks=self.args,
                                inventory=inventory,
                                variable_manager=variable_manager,
                                loader=loader,
                                display=self.display,
                                options=self.options,
                                passwords=passwords)

        results = pbex.run()

        if isinstance(results, list):
            for p in results:

                self.display.display('\nplaybook: %s\n' % p['playbook'])
                for play in p['plays']:
                    if self.options.listhosts:
                        self.display.display("\n  %s (%s): host count=%d" %
                                             (play['name'], play['pattern'],
                                              len(play['hosts'])))
                        for host in play['hosts']:
                            self.display.display("    %s" % host)
                    if self.options.listtasks:  #TODO: do we want to display block info?
                        self.display.display("\n  %s" % (play['name']))
                        for task in play['tasks']:
                            self.display.display("    %s" % task)
                    if self.options.listtags:  #TODO: fix once we figure out block handling above
                        self.display.display("\n  %s: tags count=%d" %
                                             (play['name'], len(play['tags'])))
                        for tag in play['tags']:
                            self.display.display("    %s" % tag)
            return 0
        else:
            return results
def listfunction(llist):
    """This function does all the work and lists groups or hosts"""
    llist = llist
    variable_manager = VariableManager()
    loader = DataLoader()
    if not os.path.isfile(inventory_file):
        print "%s is not a file - halting. Consider using the '--inventory $path/to/ansible_inventory file' parameter" % inventory_file
        sys.exit(1)
    else:
        inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=inventory_file)

    groups = inventory.groups
    for group in groups:
        dogroup = inventory.get_group(group)
        if dogroup.child_groups:
            list_of_hosts = dogroup.child_groups
            # we need to quote the items in the list because JSON
            list_of_hosts2 = ','.join("'{0}'".format(x) for x in list_of_hosts)
            list_of_hosts3 = list_of_hosts2.replace('["', '[')
            list_of_hosts4 = list_of_hosts3.replace('"]', ']')
            # the three lists
            dict_groups2[group] = list_of_hosts # used with --single
            dict_groups[group] = [list_of_hosts4] # used with --list and --group
            dict_hosts[group] = inventory.list_hosts(group) # used with --single

## Nested child groups
# To make this work with optionally nested groups (example up top) we need to after the group is populated, look in dict_groups if there are any double-nested groups.
    if chosen_group and single:
        for group in dict_groups2[chosen_group]:
            try:
                dict_groups2[str(group)]
                child_child_groups.append(str(group))
            except KeyError:
                # this group does not have a child group!
                continue


      # here we loop through child_child groups and list the hosts of those groups and then add the last in each group to the dict_single_hosts
    if child_child_groups != []:
        for child in child_child_groups:
            for child_child in dict_groups2[child]:
                child_host = inventory.get_hosts(str(child_child))[-1]
                dict_single_hosts[child_child] = [child_host]

##   End of this child of mine

#   make a dict that only has one host per child group
    if chosen_group:
        for host in dict_hosts[chosen_group]:
            groups_for_host = inventory.groups_for_host(str(host))
#           if debug: print "groups_for_host: %s" % groups_for_host

            for group in groups_for_host:
                if group in dict_groups2[chosen_group]:
                #this host is in one of the child groups of the chosen_group
                    if len(dict_single_hosts[chosen_group]) == 0:
                        dict_single_hosts[group] = [host]

#   here we populate dict_single_hosts so that the chosen_group key only has a list of hosts that are in separate child groups
    for group in dict_single_hosts:
        if chosen_group == group:
            continue
        if len(dict_single_hosts[chosen_group]) < (len(dict_single_hosts) - 1):
            # -1 because the chosen_group is also in the same dict
            for host in dict_single_hosts[group]:
              # and we first check if it's already in there, that might have been added by the child_child hosts
                if host not in dict_single_hosts[chosen_group]:
                    dict_single_hosts[chosen_group].append(host)

#   here we quote the entries in dict_of_single_hosts (because JSON)
    if single:
        list_of_single_hosts = dict_single_hosts[chosen_group]
        list_of_single_hosts2 = ','.join("'{0}'".format(x) for x in list_of_single_hosts)
        dict_single_hosts[chosen_group] = []
        dict_single_hosts[chosen_group] = [list_of_single_hosts2]
##  ########

#   Some arguments checking - this could probably be done with argparse settings
    if chosen_group:
        if single:
            return dict_single_hosts[chosen_group]
        else:
            return dict_groups[chosen_group]
    else:
        return dict_groups
Exemple #9
0
    def run(self):

        super(PlaybookCLI, self).run()

        # Note: slightly wrong, this is written so that implicit localhost
        # Manage passwords
        sshpass    = None
        becomepass    = None
        vault_pass = None
        passwords = {}

        # 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 }

        if self.options.vault_password_file:
            # read vault_pass from a file
            vault_pass = CLI.read_vault_password_file(self.options.vault_password_file)
        elif self.options.ask_vault_pass:
            vault_pass = self.ask_vault_passwords(ask_vault_pass=True, ask_new_vault_pass=False, confirm_new=False)[0]

        loader = DataLoader(vault_password=vault_pass)

        # initial error check, to make sure all specified playbooks are accessible
        # before we start running anything through the playbook executor
        for playbook in self.args:
            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)

        # create the variable manager, which will be shared throughout
        # the code, ensuring a consistent view of global variables
        variable_manager = VariableManager()
        variable_manager.extra_vars = load_extra_vars(loader=loader, options=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
            self.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")

        # create the playbook executor, which manages running the plays via a task queue manager
        pbex = PlaybookExecutor(playbooks=self.args, inventory=inventory, variable_manager=variable_manager, loader=loader, display=self.display, options=self.options, passwords=passwords)

        results = pbex.run()

        if isinstance(results, list):
            for p in results:

                self.display.display('\nplaybook: %s' % p['playbook'])
                i = 1
                for play in p['plays']:
                    if play.name:
                        playname = play.name
                    else:
                        playname = '#' + str(i)

                    msg = "\n  PLAY: %s" % (playname)
                    mytags = set()
                    if self.options.listtags and play.tags:
                        mytags = mytags.union(set(play.tags))
                        msg += '    TAGS: [%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

                    self.display.display(msg)

                    if self.options.listtags or self.options.listtasks:
                        taskmsg = '    tasks:'

                        for block in play.compile():
                            if not block.has_tasks():
                                continue

                            j = 1
                            for task in block.block:
                                taskmsg += "\n      %s" % task
                                if self.options.listtags and task.tags:
                                    taskmsg += "    TAGS: [%s]" % ','.join(mytags.union(set(task.tags)))
                                j = j + 1

                        self.display.display(taskmsg)

                    i = i + 1
            return 0
        else:
            return results
Exemple #10
0
 def test_simple_string_ipv4_port(self):
     inventory = Inventory('127.0.0.1:2222,192.168.1.1')
     hosts = inventory.list_hosts()
     self.assertEqual(sorted(hosts), sorted(['127.0.0.1','192.168.1.1']))
Exemple #11
0
 def test_simple_string_fqdn_port(self):
     inventory = Inventory('foo.example.com:2222,bar.example.com')
     hosts = inventory.list_hosts()
     self.assertEqual(sorted(hosts), sorted(['foo.example.com','bar.example.com']))
Exemple #12
0
    def run(self):

        super(PlaybookCLI, self).run()

        # Note: slightly wrong, this is written so that implicit localhost
        # Manage passwords
        sshpass    = None
        becomepass    = None
        vault_pass = None
        passwords = {}

        # 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
            vault_pass = CLI.read_vault_password_file(self.options.vault_password_file, loader=loader)
            loader.set_vault_password(vault_pass)
        elif self.options.ask_vault_pass:
            vault_pass = self.ask_vault_passwords()[0]
            loader.set_vault_password(vault_pass)

        # initial error check, to make sure all specified playbooks are accessible
        # before we start running anything through the playbook executor
        for playbook in self.args:
            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)

        # create the variable manager, which will be shared throughout
        # the code, ensuring a consistent view of global variables
        variable_manager = VariableManager()
        variable_manager.extra_vars = load_extra_vars(loader=loader, options=self.options)

        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")

        # create the playbook executor, which manages running the plays via a task queue manager
        pbex = PlaybookExecutor(playbooks=self.args, inventory=inventory, variable_manager=variable_manager, loader=loader, options=self.options, passwords=passwords)

        results = pbex.run()

        if isinstance(results, list):
            for p in results:

                display.display('\nplaybook: %s' % p['playbook'])
                for idx, play in enumerate(p['plays']):
                    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
Exemple #13
0
def get_hosts(hostfile, pattern):
    hosts = []
    inventory = Inventory(hostfile)
    hosts = inventory.list_hosts(pattern)
    return hosts
Exemple #14
0
class AdHocRunner(object):
    """
    ADHoc接口
    """
    Options = namedtuple("Options", [
        'connection', 'module_path', 'private_key_file', "remote_user",
        'timeout', 'forks', 'become', 'become_method', 'become_user',
        'check', 'extra_vars',
    ]
                         )

    results_callback_class = AdHocResultCallback

    def __init__(self,
                 hosts=C.DEFAULT_HOST_LIST,
                 forks=C.DEFAULT_FORKS,  # 5
                 timeout=C.DEFAULT_TIMEOUT,  # SSH timeout = 10s
                 remote_user=C.DEFAULT_REMOTE_USER,  # root
                 module_path=None,  # dirs of custome modules
                 connection_type="smart",
                 become=None,
                 become_method=None,
                 become_user=None,
                 check=False,
                 passwords=None,
                 extra_vars=None,
                 private_key_file=None,
                 gather_facts='no'):

        self.pattern = ''
        self.variable_manager = VariableManager()
        self.loader = DataLoader()
        self.gather_facts = gather_facts
        self.results_callback = AdHocRunner.results_callback_class()
        self.options = self.Options(
            connection=connection_type,
            timeout=timeout,
            module_path=module_path,
            forks=forks,
            become=become,
            become_method=become_method,
            become_user=become_user,
            check=check,
            remote_user=remote_user,
            extra_vars=extra_vars or [],
            private_key_file=private_key_file,
        )

        self.variable_manager.extra_vars = load_extra_vars(self.loader,
                                                           options=self.options)
        self.variable_manager.options_vars = load_options_vars(self.options)
        self.passwords = passwords or {}
        #self.inventory = JMSInventory(hosts)
        self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=hosts)
        self.variable_manager.set_inventory(self.inventory)
        self.tasks = []
        self.play_source = None
        self.play = None
        self.runner = None

    @staticmethod
    def check_module_args(module_name, module_args=''):
        if module_name in C.MODULE_REQUIRE_ARGS and not module_args:
            err = "No argument passed to '%s' module." % module_name
            print(err)
            return False
        return True

    def run(self, task_tuple, pattern='all', task_name='Ansible Ad-hoc'):
        """
        :param task_tuple:  (('shell', 'ls'), ('ping', ''))
        :param pattern:
        :param task_name:
        :return:
        """
        for module, args in task_tuple:
            if not self.check_module_args(module, args):
                return
            self.tasks.append(
                dict(action=dict(
                    module=module,
                    args=args,
                ))
            )

        self.play_source = dict(
            name=task_name,
            hosts=pattern,
            gather_facts=self.gather_facts,
            tasks=self.tasks
        )

        self.play = Play().load(
            self.play_source,
            variable_manager=self.variable_manager,
            loader=self.loader,
        )

        self.runner = TaskQueueManager(
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=self.passwords,
            stdout_callback=self.results_callback,
        )

        if not self.inventory.list_hosts("all"):
            raise AnsibleError("Inventory is empty.")

        if not self.inventory.list_hosts(self.pattern):
            raise AnsibleError(
                "pattern: %s  dose not match any hosts." % self.pattern)

        try:
            self.runner.run(self.play)
        except Exception as e:
            logger.warning(e)
        else:
            # logger.debug(self.results_callback.result_q)
            return self.results_callback.result_q
        finally:
            if self.runner:
                self.runner.cleanup()
            if self.loader:
                self.loader.cleanup_all_tmp_files()

    def clean_result(self):
        """
        :return: {
            "success": ['hostname',],
            "failed": [('hostname', 'msg'), {}],
        }
        """
        result = {'success': [], 'failed': []}
        for host in self.results_callback.result_q['contacted']:
            result['success'].append(host)

        for host, msgs in self.results_callback.result_q['dark'].items():
            msg = '\n'.join(['{} {}: {}'.format(
                msg.get('module_stdout', ''),
                msg.get('invocation', {}).get('module_name'),
                msg.get('msg', '')) for msg in msgs])
            result['failed'].append((host, msg))
        return result
Exemple #15
0
 def test_simple_string_ipv4(self):
     inventory = Inventory("127.0.0.1,192.168.1.1")
     hosts = inventory.list_hosts()
     self.assertEqual(sorted(hosts), sorted(["127.0.0.1", "192.168.1.1"]))
class ResourceBase(object):
    """
    generate inventory

    :param resource: inventory resource, format:
        {
            "hosts" : {
                "host1": {"port": "22", "username": "******", "password": "******"},
                "host2": {"port": "22", "username": "******", "password": "******"},
            },
            "groups": {
                "group1": {"hosts": ["host1", "host2",...], "vars": {'var1':'xxxx', 'var2':'yyy',...} },
                "group2": {"hosts": ["host1", "host2",...], "child": ["group1"], "vars": {'var1':'xxxx', 'var2':'yyy',...} },
            }
        }
    """
    def __init__(self, resource=None):
        host_list = not resource and ANS_CONS.DEFAULT_HOST_LIST or []
        self.loader = DataLoader()
        self.variable_manager = VariableManager()
        self.resource = resource
        self.inventory = Inventory(loader=self.loader,
                                   variable_manager=self.variable_manager,
                                   host_list=host_list)
        #resource and self.gen_inventory()
        self.gen_inventory()

    @staticmethod
    def gen_host(host_name=None, host_vars=None):
        """
        Generate ansible Host object
        :param host_name: <string> ansible inventory hostname
        :param host_vars: <dict> host variables
        :return: Host object
        """
        if host_vars is None:
            host_vars = {}
        ssh_host = host_vars.get('ip', host_name)
        ssh_port = host_vars.get('port', ANS_CONS.DEFAULT_REMOTE_PORT)
        ssh_user = host_vars.get('username')
        ssh_pass = host_vars.get('password')
        ssh_fkey = host_vars.get('ssh_key')
        # init Host
        host = Host(name=host_name, port=ssh_port)
        host.set_variable('ansible_ssh_host', ssh_host)
        # shortcut variables
        ssh_user and host.set_variable('ansible_ssh_user', ssh_user)
        ssh_pass and host.set_variable('ansible_ssh_pass', ssh_pass)
        ssh_fkey and host.set_variable('ansible_private_key_file', ssh_fkey)
        # extra variables
        for key, value in host_vars.items():
            if key not in ['ip', 'port', 'username', 'password', 'ssh_key']:
                host.set_variable(key, value)
        # return Host object
        return host

    @staticmethod
    def gen_group(group_name=None, group_vars=None):
        """
        Generate ansible Group object
        :param group_name: <string> Group Name
        :param group_vars: <dict> Group Variables
        :return: ansible Group object
        """
        if group_vars is None:
            group_vars = {}
        group = Group(name=group_name)
        for key, value in group_vars.items():
            group.set_variable(key, value)
        return group

    def gen_inventory(self):
        """
        :return: None
        """
        # set hosts
        if 'hosts' in self.resource.keys():
            for host, info in self.resource['hosts'].items():
                obj_host = self.gen_host(host, info)
                self.inventory.get_group('all').add_host(obj_host)
        # add group
        if 'groups' in self.resource.keys():
            for group, detail in self.resource['groups'].items():
                obj_group = self.gen_group(group, detail.get('vars', {}))
                for host in detail.get('hosts', []):
                    obj_group.add_host(self.inventory.get_host(host))
                if 'child' in detail.get('child', []):
                    for child in detail.get('child', []):
                        obj_group.add_child_group(
                            self.inventory.get_group(child))
                self.inventory.add_group(obj_group)

    def get_lists(self):
        print("Host: ")
        print("=================")
        for host in self.inventory.list_hosts():
            print(host)
        print("Group: ")
        print("=================")
        for group in self.inventory.list_groups():
            print(group)
    def run(self):

        super(PlaybookCLI, self).run()

        # Note: slightly wrong, this is written so that implicit localhost
        # Manage passwords
        sshpass = None
        becomepass = None
        vault_pass = None
        passwords = {}

        # 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
            vault_pass = CLI.read_vault_password_file(self.options.vault_password_file, loader=loader)
            loader.set_vault_password(vault_pass)
        elif self.options.ask_vault_pass:
            vault_pass = self.ask_vault_passwords(ask_vault_pass=True, ask_new_vault_pass=False, confirm_new=False)[0]
            loader.set_vault_password(vault_pass)

        # initial error check, to make sure all specified playbooks are accessible
        # before we start running anything through the playbook executor
        for playbook in self.args:
            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)

        # create the variable manager, which will be shared throughout
        # the code, ensuring a consistent view of global variables
        variable_manager = VariableManager()
        variable_manager.extra_vars = load_extra_vars(loader=loader, options=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
            self.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")

        # create the playbook executor, which manages running the plays via a task queue manager
        pbex = PlaybookExecutor(
            playbooks=self.args,
            inventory=inventory,
            variable_manager=variable_manager,
            loader=loader,
            display=self.display,
            options=self.options,
            passwords=passwords,
        )

        results = pbex.run()

        if isinstance(results, list):
            for p in results:

                self.display.display("\nplaybook: %s" % p["playbook"])
                i = 1
                for play in p["plays"]:
                    if play.name:
                        playname = play.name
                    else:
                        playname = "#" + str(i)

                    msg = "\n  PLAY: %s" % (playname)
                    mytags = set()
                    if self.options.listtags and play.tags:
                        mytags = mytags.union(set(play.tags))
                        msg += "    TAGS: [%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

                    self.display.display(msg)

                    if self.options.listtags or self.options.listtasks:
                        taskmsg = "    tasks:"

                        for block in play.compile():
                            if not block.has_tasks():
                                continue

                            j = 1
                            for task in block.block:
                                taskmsg += "\n      %s" % task
                                if self.options.listtags and task.tags:
                                    taskmsg += "    TAGS: [%s]" % ",".join(mytags.union(set(task.tags)))
                                j = j + 1

                        self.display.display(taskmsg)

                    i = i + 1
            return 0
        else:
            return results
class Runner(object):
    def __init__(
            self, playbook, options={}, passwords={},
            vault_pass=None):

        display = Display()
        ansible_root = '/opt/emc'
        pb_dir = "{0}/playbooks".format(ansible_root)
        playbook = "{0}/{1}".format(pb_dir, playbook)
        hosts = "{0}/hosts.ini".format(ansible_root)


        # Set options
        self.options = Options()
        for k, v in options.iteritems():
            setattr(self.options, k, v)

        self.options.verbosity = 0
        # Set global verbosity
        self.display = display
        self.display.verbosity = self.options.verbosity
        # Executor has its own verbosity setting
        playbook_executor.verbosity = self.options.verbosity

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        # Set vault password
        if vault_pass is not None:
            self.loader.set_vault_password(vault_pass)
        elif 'VAULT_PASS' in os.environ:
            self.loader.set_vault_password(os.environ['VAULT_PASS'])

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        if self.options.python_interpreter is not None:
            self.variable_manager.extra_vars = {
                'ansible_python_interpreter': self.options.python_interpreter
            }

        # Set inventory, using most of above objects
        self.inventory = Inventory(
            loader=self.loader, variable_manager=self.variable_manager,
            host_list=hosts)

        if len(self.inventory.list_hosts()) == 0:
            # Empty inventory
            self.display.error("Provided hosts list is empty.")
            sys.exit(1)

        self.inventory.subset(self.options.subset)

        if len(self.inventory.list_hosts()) == 0:
            # Invalid limit
            self.display.error("Specified limit does not match any hosts.")
            sys.exit(1)

        self.variable_manager.set_inventory(self.inventory)

        # Setup playbook executor, but don't run until run() called
        self.pbex = playbook_executor.PlaybookExecutor(
            playbooks=[playbook],
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=passwords)

    def run(self):
        # Run Playbook and get stats
        self.pbex.run()
        stats = self.pbex._tqm._stats
        run_success = True
        hosts = sorted(stats.processed.keys())
        for h in hosts:
            t = stats.summarize(h)
            if t['unreachable'] > 0 or t['failures'] > 0:
                run_success = False

        # Do the callback
        # self.pbex._tqm.send_callback(
        #     'record_logs',
        #     success=run_success
        # )

        return run_success
Exemple #19
0
    def run(self):
        ''' use Runner lib to do SSH things '''

        # only thing left should be host pattern
        pattern = self.args[0]

        # ignore connection password cause we are local
        if self.options.connection == "local":
            self.options.ask_pass = False

        sshpass    = None
        becomepass    = None
        vault_pass = None

        self.normalize_become_options()
        (sshpass, becomepass) = self.ask_passwords()
        passwords = { 'conn_pass': sshpass, 'become_pass': becomepass }

        if self.options.vault_password_file:
            # read vault_pass from a file
            vault_pass = read_vault_file(self.options.vault_password_file)
        elif self.options.ask_vault_pass:
            vault_pass = self.ask_vault_passwords(ask_vault_pass=True, ask_new_vault_pass=False, confirm_new=False)[0]

        loader = DataLoader(vault_password=vault_pass)
        variable_manager = VariableManager()

        inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=self.options.inventory)
        variable_manager.set_inventory(inventory)

        hosts = inventory.list_hosts(pattern)
        if len(hosts) == 0:
            self.display.warning("provided hosts list is empty, only localhost is available")

        if self.options.listhosts:
            for host in hosts:
                self.display.display('    %s' % host)
            return 0

        if self.options.module_name in C.MODULE_REQUIRE_ARGS and not self.options.module_args:
            raise AnsibleOptionsError("No argument passed to %s module" % self.options.module_name)

        #TODO: implement async support
        #if self.options.seconds:
        #    callbacks.display("background launch...\n\n", color='cyan')
        #    results, poller = runner.run_async(self.options.seconds)
        #    results = self.poll_while_needed(poller)
        #else:
        #    results = runner.run()

        # create a pseudo-play to execute the specified module via a single task
        play_ds = dict(
            name = "Ansible Ad-Hoc",
            hosts = pattern,
            gather_facts = 'no',
            tasks = [ dict(action=dict(module=self.options.module_name, args=parse_kv(self.options.module_args))), ]
        )

        play = Play().load(play_ds, variable_manager=variable_manager, loader=loader)

        # now create a task queue manager to execute the play
        tqm = None
        try:
            tqm = TaskQueueManager(
                    inventory=inventory,
                    variable_manager=variable_manager,
                    loader=loader,
                    display=self.display,
                    options=self.options,
                    passwords=passwords,
                    stdout_callback='minimal',
                )
            result = tqm.run(play)
        finally:
            if tqm:
                tqm.cleanup()

        return result
Exemple #20
0
    def run_playbook(self,
                     group,
                     playbook,
                     private_key_file,
                     run_data,
                     become_pas,
                     tags=[]):
        """
        """
        # All the variables from all the various places
        self.variable_manager.extra_vars = run_data
        self.variable_manager.group_vars_files = u'%s/group_vars' % self.inventory
        #print self.variable_manager.get_vars(self.loader)

        # set options
        self.options.tags = tags
        self.options.limit = group
        #self.options.become = True
        #self.options.become_user = u'root'
        #self.options.private_key_file = u'%s/.ssh/id_rsa' % self.inventory

        # Parse hosts
        '''hosts = NamedTemporaryFile(delete=False)
        hosts.write(u'[%s]\n' % group)
        for host in self.get_inventory(group):
            hosts.write(u'%s ansible_ssh_private_key_file=%s ansible_user=root\n' % 
                        (host, self.options.private_key_file))
        hosts.close()
        
        # copy .ssh key in tmp
        os.symlink(u'%s/.ssh' % self.inventory, u'/tmp/.ssh')'''

        # Set inventory, using most of above objects
        #inventory = InventoryManager(self.loader, sources=self.inventory)
        inventory = Inventory(loader=self.loader,
                              variable_manager=self.variable_manager,
                              host_list=self.inventory)
        #logger.warn(inventory.list_groups())
        inventory.subset(group)
        logger.warn(inventory.list_groups())
        logger.warn(inventory.list_hosts(group))
        self.variable_manager.set_inventory(inventory)

        # Setup playbook executor, but don't run until run() called
        self.pbex = playbook_executor.PlaybookExecutor(
            playbooks=[playbook],
            inventory=inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=None)

        # Results of PlaybookExecutor
        self.pbex.run()
        stats = self.pbex._tqm._stats

        # Test if success for record_logs
        run_success = True
        ihosts = sorted(stats.processed.keys())
        for h in ihosts:
            t = stats.summarize(h)
            if t[u'unreachable'] > 0 or t[u'failures'] > 0:
                run_success = False

        # Remove created temporary files
        #os.remove(hosts.name)
        #os.remove(u'/tmp/.ssh')

        return stats
Exemple #21
0
 def test_simple_string_ipv6_port(self):
     inventory = Inventory("[FE80:EF45::12:1]:2222,192.168.1.1")
     hosts = inventory.list_hosts()
     self.assertEqual(sorted(hosts), sorted(["FE80:EF45::12:1", "192.168.1.1"]))
Exemple #22
0
class Runner(object):
    def __init__(self, playbook, hosts='hosts', options={}, passwords={}, vault_pass=None):

        # Set options
        self.options = Options()
        for k, v in options.iteritems():
            setattr(self.options, k, v)

        # Set global verbosity
        self.display = display
        self.display.verbosity = self.options.verbosity

        # Executor has its own verbosity setting
        playbook_executor.verbosity = self.options.verbosity

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        # Set vault password
        if vault_pass is not None:
            self.loader.set_vault_password(vault_pass)
        elif 'VAULT_PASS' in os.environ:
            self.loader.set_vault_password(os.environ['VAULT_PASS'])

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        if self.options.python_interpreter is not None:
            self.variable_manager.extra_vars = {
                'ansible_python_interpreter': self.options.python_interpreter
            }

        # Set inventory, using most of above objects
        self.inventory = Inventory( loader=self.loader, 
                                    variable_manager=self.variable_manager,
                                    host_list=hosts)

        if len(self.inventory.list_hosts()) == 0:
            # Empty inventory
            self.display.error("Provided hosts list is empty.")
            sys.exit(1)

        self.inventory.subset(self.options.subset)

        if len(self.inventory.list_hosts()) == 0:
            # Invalid limit
            self.display.error("Specified limit does not match any hosts.")
            sys.exit(1)

        self.variable_manager.set_inventory(self.inventory)

        # Setup playbook executor, but don't run until run() called
        self.pbex = playbook_executor.PlaybookExecutor(
            playbooks=[playbook],
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=passwords)

    def run(self):
        # Run Playbook and get stats
        self.pbex.run()
        stats = self.pbex._tqm._stats

        return stats
Exemple #23
0
    def run(self):
        ''' use Runner lib to do SSH things '''

        # only thing left should be host pattern
        pattern = self.args[0]

        # ignore connection password cause we are local
        if self.options.connection == "local":
            self.options.ask_pass = False

        sshpass    = None
        becomepass    = None
        vault_pass = None

        self.normalize_become_options()
        (sshpass, becomepass) = self.ask_passwords()
        passwords = { 'conn_pass': sshpass, 'become_pass': becomepass }

        if self.options.vault_password_file:
            # read vault_pass from a file
            vault_pass = read_vault_file(self.options.vault_password_file)
        elif self.options.ask_vault_pass:
            vault_pass = self.ask_vault_passwords(ask_vault_pass=True, ask_new_vault_pass=False, confirm_new=False)[0]

        loader = DataLoader(vault_password=vault_pass)
        variable_manager = VariableManager()

        inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=self.options.inventory)

        hosts = inventory.list_hosts(pattern)
        if len(hosts) == 0:
            self.display.warning("provided hosts list is empty, only localhost is available")

        if self.options.listhosts:
            for host in hosts:
                self.display.display('    %s' % host)
            return 0

        if self.options.module_name in C.MODULE_REQUIRE_ARGS and not self.options.module_args:
            raise AnsibleError("No argument passed to %s module" % self.options.module_name)

        #TODO: implement async support
        #if self.options.seconds:
        #    callbacks.display("background launch...\n\n", color='cyan')
        #    results, poller = runner.run_async(self.options.seconds)
        #    results = self.poll_while_needed(poller)
        #else:
        #    results = runner.run()

        # create a pseudo-play to execute the specified module via a single task
        play_ds = dict(
            name = "Ansible Ad-Hoc",
            hosts = pattern,
            gather_facts = 'no',
            tasks = [ dict(action=dict(module=self.options.module_name, args=parse_kv(self.options.module_args))), ]
        )

        play = Play().load(play_ds, variable_manager=variable_manager, loader=loader)

        # now create a task queue manager to execute the play
        tqm = None
        try:
            tqm = TaskQueueManager(
                    inventory=inventory,
                    variable_manager=variable_manager,
                    loader=loader,
                    display=self.display,
                    options=self.options,
                    passwords=passwords,
                    stdout_callback='minimal',
                )
            result = tqm.run(play)
        finally:
            if tqm:
                tqm.cleanup()

        return result
Exemple #24
0
class ConsoleCLI(CLI, cmd.Cmd):

    modules = []

    def __init__(self, args):

        super(ConsoleCLI, self).__init__(args)

        self.intro = 'Welcome to the ansible console.\nType help or ? to list commands.\n'

        self.groups = []
        self.hosts = []
        self.pattern = None
        self.variable_manager = None
        self.loader = None
        self.passwords = dict()

        self.modules = None
        cmd.Cmd.__init__(self)

    def parse(self):
        self.parser = CLI.base_parser(
            usage='%prog <host-pattern> [options]',
            runas_opts=True,
            inventory_opts=True,
            connect_opts=True,
            check_opts=True,
            vault_opts=True,
            fork_opts=True,
            module_opts=True,
        )

        # options unique to shell
        self.parser.add_option('--step', dest='step', action='store_true',
            help="one-step-at-a-time: confirm each task before running")

        self.parser.set_defaults(cwd='*')
        self.options, self.args = self.parser.parse_args(self.args[1:])

        display.verbosity = self.options.verbosity
        self.validate_conflicts(runas_opts=True, vault_opts=True, fork_opts=True)

        return True

    def get_names(self):
        return dir(self)

    def cmdloop(self):
        try:
            cmd.Cmd.cmdloop(self)
        except KeyboardInterrupt:
            self.do_exit(self)

    def set_prompt(self):
        login_user = self.options.remote_user or getpass.getuser()
        self.selected = self.inventory.list_hosts(self.options.cwd)
        prompt = "%s@%s (%d)[f:%s]" % (login_user, self.options.cwd, len(self.selected), self.options.forks)
        if self.options.become and self.options.become_user in [None, 'root']:
            prompt += "# "
            color = C.COLOR_ERROR
        else:
            prompt += "$ "
            color = C.COLOR_HIGHLIGHT
        self.prompt = stringc(prompt, color)

    def list_modules(self):
        modules = set()
        if self.options.module_path is not None:
            for i in self.options.module_path.split(os.pathsep):
                module_loader.add_directory(i)

        module_paths = module_loader._get_paths()
        for path in module_paths:
            if path is not None:
                modules.update(self._find_modules_in_path(path))
        return modules

    def _find_modules_in_path(self, path):

        if os.path.isdir(path):
            for module in os.listdir(path):
                if module.startswith('.'):
                    continue
                elif os.path.isdir(module):
                    self._find_modules_in_path(module)
                elif module.startswith('__'):
                    continue
                elif any(module.endswith(x) for x in C.BLACKLIST_EXTS):
                    continue
                elif module in C.IGNORE_FILES:
                    continue
                elif module.startswith('_'):
                    fullpath = '/'.join([path,module])
                    if os.path.islink(fullpath):  # avoids aliases
                        continue
                    module = module.replace('_', '', 1)

                module = os.path.splitext(module)[0]  # removes the extension
                yield module

    def default(self, arg, forceshell=False):
        """ actually runs modules """
        if arg.startswith("#"):
            return False

        if not self.options.cwd:
            display.error("No host found")
            return False

        if arg.split()[0] in self.modules:
            module = arg.split()[0]
            module_args = ' '.join(arg.split()[1:])
        else:
            module = 'shell'
            module_args = arg

        if forceshell is True:
            module = 'shell'
            module_args = arg

        self.options.module_name = module

        result = None
        try:
            check_raw = self.options.module_name in ('command', 'shell', 'script', 'raw')
            play_ds = dict(
                name = "Ansible Shell",
                hosts = self.options.cwd,
                gather_facts = 'no',
                tasks = [ dict(action=dict(module=module, args=parse_kv(module_args, check_raw=check_raw)))]
            )
            play = Play().load(play_ds, variable_manager=self.variable_manager, loader=self.loader)
        except Exception as e:
            display.error(u"Unable to build command: %s" % to_text(e))
            return False

        try:
            cb = 'minimal'  # FIXME: make callbacks configurable
            # now create a task queue manager to execute the play
            self._tqm = None
            try:
                self._tqm = TaskQueueManager(
                        inventory=self.inventory,
                        variable_manager=self.variable_manager,
                        loader=self.loader,
                        options=self.options,
                        passwords=self.passwords,
                        stdout_callback=cb,
                        run_additional_callbacks=C.DEFAULT_LOAD_CALLBACK_PLUGINS,
                        run_tree=False,
                    )

                result = self._tqm.run(play)
            finally:
                if self._tqm:
                    self._tqm.cleanup()
                if self.loader:
                    self.loader.cleanup_all_tmp_files()

            if result is None:
                display.error("No hosts found")
                return False
        except KeyboardInterrupt:
            display.error('User interrupted execution')
            return False
        except Exception as e:
            display.error(to_text(e))
            # FIXME: add traceback in very very verbose mode
            return False

    def emptyline(self):
        return

    def do_shell(self, arg):
        """
        You can run shell commands through the shell module.

        eg.:
        shell ps uax | grep java | wc -l
        shell killall python
        shell halt -n

        You can use the ! to force the shell module. eg.:
        !ps aux | grep java | wc -l
        """
        self.default(arg, True)

    def do_forks(self, arg):
        """Set the number of forks"""
        if not arg:
            display.display('Usage: forks <number>')
            return
        self.options.forks = int(arg)
        self.set_prompt()

    do_serial = do_forks

    def do_verbosity(self, arg):
        """Set verbosity level"""
        if not arg:
            display.display('Usage: verbosity <number>')
        else:
            display.verbosity = int(arg)
            display.v('verbosity level set to %s' % arg)

    def do_cd(self, arg):
        """
            Change active host/group. You can use hosts patterns as well eg.:
            cd webservers
            cd webservers:dbservers
            cd webservers:!phoenix
            cd webservers:&staging
            cd webservers:dbservers:&staging:!phoenix
        """
        if not arg:
            self.options.cwd = '*'
        elif arg == '..':
            try:
                self.options.cwd = self.inventory.groups_for_host(self.options.cwd)[1].name
            except Exception:
                self.options.cwd = ''
        elif arg in '/*':
            self.options.cwd = 'all'
        elif self.inventory.get_hosts(arg):
            self.options.cwd = arg
        else:
            display.display("no host matched")

        self.set_prompt()

    def do_list(self, arg):
        """List the hosts in the current group"""
        if arg == 'groups':
            for group in self.groups:
                display.display(group)
        else:
            for host in self.selected:
                display.display(host.name)

    def do_become(self, arg):
        """Toggle whether plays run with become"""
        if arg:
            self.options.become = C.mk_boolean(arg)
            display.v("become changed to %s" % self.options.become)
            self.set_prompt()
        else:
            display.display("Please specify become value, e.g. `become yes`")

    def do_remote_user(self, arg):
        """Given a username, set the remote user plays are run by"""
        if arg:
            self.options.remote_user = arg
            self.set_prompt()
        else:
            display.display("Please specify a remote user, e.g. `remote_user root`")

    def do_become_user(self, arg):
        """Given a username, set the user that plays are run by when using become"""
        if arg:
            self.options.become_user = arg
        else:
            display.display("Please specify a user, e.g. `become_user jenkins`")
            display.v("Current user is %s" % self.options.become_user)
        self.set_prompt()

    def do_become_method(self, arg):
        """Given a become_method, set the privilege escalation method when using become"""
        if arg:
            self.options.become_method = arg
            display.v("become_method changed to %s" % self.options.become_method)
        else:
            display.display("Please specify a become_method, e.g. `become_method su`")

    def do_check(self, arg):
        """Toggle whether plays run with check mode"""
        if arg:
            self.options.check = C.mk_boolean(arg)
            display.v("check mode changed to %s" % self.options.check)
        else:
            display.display("Please specify check mode value, e.g. `check yes`")

    def do_diff(self, arg):
        """Toggle whether plays run with diff"""
        if arg:
            self.options.diff = C.mk_boolean(arg)
            display.v("diff mode changed to %s" % self.options.diff)
        else:
            display.display("Please specify a diff value , e.g. `diff yes`")

    def do_exit(self, args):
        """Exits from the console"""
        sys.stdout.write('\n')
        return -1

    do_EOF = do_exit

    def helpdefault(self, module_name):
        if module_name in self.modules:
            in_path = module_loader.find_plugin(module_name)
            if in_path:
                oc, a, _ = module_docs.get_docstring(in_path)
                if oc:
                    display.display(oc['short_description'])
                    display.display('Parameters:')
                    for opt in oc['options'].keys():
                        display.display('  ' + stringc(opt, C.COLOR_HIGHLIGHT) + ' ' + oc['options'][opt]['description'][0])
                else:
                    display.error('No documentation found for %s.' % module_name)
            else:
                display.error('%s is not a valid command, use ? to list all valid commands.' % module_name)

    def complete_cd(self, text, line, begidx, endidx):
        mline = line.partition(' ')[2]
        offs = len(mline) - len(text)

        if self.options.cwd in ('all','*','\\'):
            completions = self.hosts + self.groups
        else:
            completions = [x.name for x in self.inventory.list_hosts(self.options.cwd)]

        return [to_native(s)[offs:] for s in completions if to_native(s).startswith(to_native(mline))]

    def completedefault(self, text, line, begidx, endidx):
        if line.split()[0] in self.modules:
            mline = line.split(' ')[-1]
            offs = len(mline) - len(text)
            completions = self.module_args(line.split()[0])

            return [s[offs:] + '=' for s in completions if s.startswith(mline)]

    def module_args(self, module_name):
        in_path = module_loader.find_plugin(module_name)
        oc, a, _ = module_docs.get_docstring(in_path)
        return oc['options'].keys()

    def run(self):

        super(ConsoleCLI, self).run()

        sshpass    = None
        becomepass = None
        vault_pass = None

        # hosts
        if len(self.args) != 1:
            self.pattern = 'all'
        else:
            self.pattern = self.args[0]
        self.options.cwd = self.pattern

        # dynamically add modules as commands
        self.modules = self.list_modules()
        for module in self.modules:
            setattr(self, 'do_' + module, lambda arg, module=module: self.default(module + ' ' + arg))
            setattr(self, 'help_' + module, lambda module=module: self.helpdefault(module))

        self.normalize_become_options()
        (sshpass, becomepass) = self.ask_passwords()
        self.passwords = { 'conn_pass': sshpass, 'become_pass': becomepass }

        self.loader = DataLoader()

        if self.options.vault_password_file:
            # read vault_pass from a file
            vault_pass = CLI.read_vault_password_file(self.options.vault_password_file, loader=self.loader)
            self.loader.set_vault_password(vault_pass)
        elif self.options.ask_vault_pass:
            vault_pass = self.ask_vault_passwords()[0]
            self.loader.set_vault_password(vault_pass)

        self.variable_manager = VariableManager()
        self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=self.options.inventory)
        self.variable_manager.set_inventory(self.inventory)

        no_hosts = False
        if len(self.inventory.list_hosts()) == 0:
            # Empty inventory
            no_hosts = True
            display.warning("provided hosts list is empty, only localhost is available")

        self.inventory.subset(self.options.subset)
        hosts = self.inventory.list_hosts(self.pattern)
        if len(hosts) == 0 and not no_hosts:
            raise AnsibleError("Specified hosts and/or --limit does not match any hosts")

        self.groups = self.inventory.list_groups()
        self.hosts = [x.name for x in hosts]

        # This hack is to work around readline issues on a mac:
        #  http://stackoverflow.com/a/7116997/541202
        if 'libedit' in readline.__doc__:
            readline.parse_and_bind("bind ^I rl_complete")
        else:
            readline.parse_and_bind("tab: complete")

        histfile = os.path.join(os.path.expanduser("~"), ".ansible-console_history")
        try:
            readline.read_history_file(histfile)
        except IOError:
            pass

        atexit.register(readline.write_history_file, histfile)
        self.set_prompt()
        self.cmdloop()
class Runner(object):
    def __init__(
            self, playbook, display, hosts='hosts', options={}, passwords={},
            vault_pass=None):

        # Set options
        self.options = Options()
        for k, v in options.iteritems():
            setattr(self.options, k, v)
        
        # Set global verbosity
        self.display = display
        self.display.verbosity = self.options.verbosity
        # Executor has its own verbosity setting
        playbook_executor.verbosity = self.options.verbosity

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        # Set vault password
        if vault_pass is not None:
            self.loader.set_vault_password(vault_pass)
        elif 'VAULT_PASS' in os.environ:
            self.loader.set_vault_password(os.environ['VAULT_PASS'])

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        if self.options.python_interpreter is not None:
            self.variable_manager.extra_vars = {
                'ansible_python_interpreter': self.options.python_interpreter
            }

        # Set inventory, using most of above objects
        self.inventory = Inventory(
            loader=self.loader, variable_manager=self.variable_manager,
            host_list=hosts)

        if len(self.inventory.list_hosts()) == 0:
            # Empty inventory
            self.display.error("Provided hosts list is empty.")
            sys.exit(1)

        self.inventory.subset(self.options.subset)

        if len(self.inventory.list_hosts()) == 0:
            # Invalid limit
            self.display.error("Specified limit does not match any hosts.")
            sys.exit(1)

        self.variable_manager.set_inventory(self.inventory)
        # import pdb; pdb.set_trace()
        # Setup playbook executor, but don't run until run() called
        self.pbex = playbook_executor.PlaybookExecutor(
            playbooks=[playbook],
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=passwords)

    def run(self):
        # Run Playbook and get stats
        self.pbex.run()
        stats = self.pbex._tqm._stats

        # Test if success for record_logs
        run_success = True
        hosts = sorted(stats.processed.keys())
        for h in hosts:
            t = stats.summarize(h)
            if t['unreachable'] > 0 or t['failures'] > 0:
                run_success = False

        # Dirty hack to send callback to save logs with data we want
        # Note that function "record_logs" is one I created and put into
        # the playbook callback file
        # import pdb; pdb.set_trace()
        self.pbex._tqm.send_callback('record_logs')
        # os.remove(self.hosts.name)
        
        return stats
class Runner(object):
    def __init__(self, playbook, options={}, passwords={}, vault_pass=None):

        display = Display()
        ansible_root = '/opt/emc'
        pb_dir = "{0}/playbooks".format(ansible_root)
        playbook = "{0}/{1}".format(pb_dir, playbook)
        hosts = "{0}/hosts.ini".format(ansible_root)

        # Set options
        self.options = Options()
        for k, v in options.iteritems():
            setattr(self.options, k, v)

        self.options.verbosity = 0
        # Set global verbosity
        self.display = display
        self.display.verbosity = self.options.verbosity
        # Executor has its own verbosity setting
        playbook_executor.verbosity = self.options.verbosity

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        # Set vault password
        if vault_pass is not None:
            self.loader.set_vault_password(vault_pass)
        elif 'VAULT_PASS' in os.environ:
            self.loader.set_vault_password(os.environ['VAULT_PASS'])

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        if self.options.python_interpreter is not None:
            self.variable_manager.extra_vars = {
                'ansible_python_interpreter': self.options.python_interpreter
            }

        # Set inventory, using most of above objects
        self.inventory = Inventory(loader=self.loader,
                                   variable_manager=self.variable_manager,
                                   host_list=hosts)

        if len(self.inventory.list_hosts()) == 0:
            # Empty inventory
            self.display.error("Provided hosts list is empty.")
            sys.exit(1)

        self.inventory.subset(self.options.subset)

        if len(self.inventory.list_hosts()) == 0:
            # Invalid limit
            self.display.error("Specified limit does not match any hosts.")
            sys.exit(1)

        self.variable_manager.set_inventory(self.inventory)

        # Setup playbook executor, but don't run until run() called
        self.pbex = playbook_executor.PlaybookExecutor(
            playbooks=[playbook],
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=passwords)

    def run(self):
        # Run Playbook and get stats
        self.pbex.run()
        stats = self.pbex._tqm._stats
        run_success = True
        hosts = sorted(stats.processed.keys())
        for h in hosts:
            t = stats.summarize(h)
            if t['unreachable'] > 0 or t['failures'] > 0:
                run_success = False

        # Do the callback
        # self.pbex._tqm.send_callback(
        #     'record_logs',
        #     success=run_success
        # )

        return run_success
Exemple #27
0
 def test_simple_string_ipv6_port(self):
     inventory = Inventory('[FE80:EF45::12:1]:2222,192.168.1.1')
     hosts = inventory.list_hosts()
     self.assertEqual(sorted(hosts), sorted(['FE80:EF45::12:1','192.168.1.1']))
Exemple #28
0
 def test_combined_range(self):
     i = Inventory(os.path.join(self.test_dir, "inventory", "test_combined_range"))
     hosts = i.list_hosts("test")
     expected_hosts = ["host1A", "host2A", "host1B", "host2B"]
     assert sorted(hosts) == sorted(expected_hosts)
Exemple #29
0
 def test_combined_range(self):
     i = Inventory(os.path.join(self.test_dir, 'inventory','test_combined_range'))
     hosts = i.list_hosts('test')
     expected_hosts=['host1A','host2A','host1B','host2B']
     assert sorted(hosts) == sorted(expected_hosts)
Exemple #30
0
    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
Exemple #31
0
    def run(self):
        ''' use Runner lib to do SSH things '''

        super(AdHocCLI, self).run()


        # only thing left should be host pattern
        pattern = self.args[0]

        # ignore connection password cause we are local
        if self.options.connection == "local":
            self.options.ask_pass = False

        sshpass    = None
        becomepass    = None
        vault_pass = None

        self.normalize_become_options()
        (sshpass, becomepass) = self.ask_passwords()
        passwords = { 'conn_pass': sshpass, 'become_pass': becomepass }

        if self.options.vault_password_file:
            # read vault_pass from a file
            vault_pass = CLI.read_vault_password_file(self.options.vault_password_file)
        elif self.options.ask_vault_pass:
            vault_pass = self.ask_vault_passwords(ask_vault_pass=True, ask_new_vault_pass=False, confirm_new=False)[0]

        loader = DataLoader(vault_password=vault_pass)
        variable_manager = VariableManager()
        variable_manager.extra_vars = load_extra_vars(loader=loader, options=self.options)

        inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=self.options.inventory)
        variable_manager.set_inventory(inventory)

        hosts = inventory.list_hosts(pattern)
        if len(hosts) == 0:
            self.display.warning("provided hosts list is empty, only localhost is available")

        if self.options.listhosts:
            self.display.display('  hosts (%d):' % len(hosts))
            for host in hosts:
                self.display.display('    %s' % host)
            return 0

        if self.options.module_name in C.MODULE_REQUIRE_ARGS and not self.options.module_args:
            err = "No argument passed to %s module" % self.options.module_name
            if pattern.endswith(".yml"):
                err = err + ' (did you mean to run ansible-playbook?)'
            raise AnsibleOptionsError(err)

        #TODO: implement async support
        #if self.options.seconds:
        #    callbacks.display("background launch...\n\n", color='cyan')
        #    results, poller = runner.run_async(self.options.seconds)
        #    results = self.poll_while_needed(poller)
        #else:
        #    results = runner.run()

        # create a pseudo-play to execute the specified module via a single task
        play_ds = self._play_ds(pattern)
        play = Play().load(play_ds, variable_manager=variable_manager, loader=loader)

        if self.options.one_line:
            cb = 'oneline'
        else:
            cb = 'minimal'

        # now create a task queue manager to execute the play
        self._tqm = None
        try:
            self._tqm = TaskQueueManager(
                    inventory=inventory,
                    variable_manager=variable_manager,
                    loader=loader,
                    display=self.display,
                    options=self.options,
                    passwords=passwords,
                    stdout_callback=cb,
                )
            result = self._tqm.run(play)
        finally:
            if self._tqm:
                self._tqm.cleanup()

        return result
Exemple #32
0
 def test_simple_string_ipv6_port(self):
     inventory = Inventory('[FE80:EF45::12:1]:2222,192.168.1.1')
     hosts = inventory.list_hosts()
     self.assertEqual(sorted(hosts),
                      sorted(['FE80:EF45::12:1', '192.168.1.1']))
Exemple #33
0
class ConsoleCLI(CLI, cmd.Cmd):

    modules = []

    def __init__(self, args):

        super(ConsoleCLI, self).__init__(args)

        self.intro = 'Welcome to the ansible console.\nType help or ? to list commands.\n'

        self.groups = []
        self.hosts = []
        self.pattern = None
        self.variable_manager = None
        self.loader = None
        self.passwords = dict()

        self.modules = None
        cmd.Cmd.__init__(self)

    def parse(self):
        self.parser = CLI.base_parser(
            usage='%prog <host-pattern> [options]',
            runas_opts=True,
            inventory_opts=True,
            connect_opts=True,
            check_opts=True,
            vault_opts=True,
            fork_opts=True,
            module_opts=True,
        )

        # options unique to shell
        self.parser.add_option(
            '--step',
            dest='step',
            action='store_true',
            help="one-step-at-a-time: confirm each task before running")

        self.parser.set_defaults(cwd='*')

        super(AdHocCLI, self).parse()

        display.verbosity = self.options.verbosity
        self.validate_conflicts(runas_opts=True,
                                vault_opts=True,
                                fork_opts=True)

    def get_names(self):
        return dir(self)

    def cmdloop(self):
        try:
            cmd.Cmd.cmdloop(self)
        except KeyboardInterrupt:
            self.do_exit(self)

    def set_prompt(self):
        login_user = self.options.remote_user or getpass.getuser()
        self.selected = self.inventory.list_hosts(self.options.cwd)
        prompt = "%s@%s (%d)[f:%s]" % (login_user, self.options.cwd,
                                       len(self.selected), self.options.forks)
        if self.options.become and self.options.become_user in [None, 'root']:
            prompt += "# "
            color = C.COLOR_ERROR
        else:
            prompt += "$ "
            color = C.COLOR_HIGHLIGHT
        self.prompt = stringc(prompt, color)

    def list_modules(self):
        modules = set()
        if self.options.module_path is not None:
            for i in self.options.module_path.split(os.pathsep):
                module_loader.add_directory(i)

        module_paths = module_loader._get_paths()
        for path in module_paths:
            if path is not None:
                modules.update(self._find_modules_in_path(path))
        return modules

    def _find_modules_in_path(self, path):

        if os.path.isdir(path):
            for module in os.listdir(path):
                if module.startswith('.'):
                    continue
                elif os.path.isdir(module):
                    self._find_modules_in_path(module)
                elif module.startswith('__'):
                    continue
                elif any(module.endswith(x) for x in C.BLACKLIST_EXTS):
                    continue
                elif module in C.IGNORE_FILES:
                    continue
                elif module.startswith('_'):
                    fullpath = '/'.join([path, module])
                    if os.path.islink(fullpath):  # avoids aliases
                        continue
                    module = module.replace('_', '', 1)

                module = os.path.splitext(module)[0]  # removes the extension
                yield module

    def default(self, arg, forceshell=False):
        """ actually runs modules """
        if arg.startswith("#"):
            return False

        if not self.options.cwd:
            display.error("No host found")
            return False

        if arg.split()[0] in self.modules:
            module = arg.split()[0]
            module_args = ' '.join(arg.split()[1:])
        else:
            module = 'shell'
            module_args = arg

        if forceshell is True:
            module = 'shell'
            module_args = arg

        self.options.module_name = module

        result = None
        try:
            check_raw = self.options.module_name in ('command', 'shell',
                                                     'script', 'raw')
            play_ds = dict(
                name="Ansible Shell",
                hosts=self.options.cwd,
                gather_facts='no',
                tasks=[
                    dict(action=dict(module=module,
                                     args=parse_kv(module_args,
                                                   check_raw=check_raw)))
                ])
            play = Play().load(play_ds,
                               variable_manager=self.variable_manager,
                               loader=self.loader)
        except Exception as e:
            display.error(u"Unable to build command: %s" % to_text(e))
            return False

        try:
            cb = 'minimal'  # FIXME: make callbacks configurable
            # now create a task queue manager to execute the play
            self._tqm = None
            try:
                self._tqm = TaskQueueManager(
                    inventory=self.inventory,
                    variable_manager=self.variable_manager,
                    loader=self.loader,
                    options=self.options,
                    passwords=self.passwords,
                    stdout_callback=cb,
                    run_additional_callbacks=C.DEFAULT_LOAD_CALLBACK_PLUGINS,
                    run_tree=False,
                )

                result = self._tqm.run(play)
            finally:
                if self._tqm:
                    self._tqm.cleanup()
                if self.loader:
                    self.loader.cleanup_all_tmp_files()

            if result is None:
                display.error("No hosts found")
                return False
        except KeyboardInterrupt:
            display.error('User interrupted execution')
            return False
        except Exception as e:
            display.error(to_text(e))
            # FIXME: add traceback in very very verbose mode
            return False

    def emptyline(self):
        return

    def do_shell(self, arg):
        """
        You can run shell commands through the shell module.

        eg.:
        shell ps uax | grep java | wc -l
        shell killall python
        shell halt -n

        You can use the ! to force the shell module. eg.:
        !ps aux | grep java | wc -l
        """
        self.default(arg, True)

    def do_forks(self, arg):
        """Set the number of forks"""
        if not arg:
            display.display('Usage: forks <number>')
            return
        self.options.forks = int(arg)
        self.set_prompt()

    do_serial = do_forks

    def do_verbosity(self, arg):
        """Set verbosity level"""
        if not arg:
            display.display('Usage: verbosity <number>')
        else:
            display.verbosity = int(arg)
            display.v('verbosity level set to %s' % arg)

    def do_cd(self, arg):
        """
            Change active host/group. You can use hosts patterns as well eg.:
            cd webservers
            cd webservers:dbservers
            cd webservers:!phoenix
            cd webservers:&staging
            cd webservers:dbservers:&staging:!phoenix
        """
        if not arg:
            self.options.cwd = '*'
        elif arg == '..':
            try:
                self.options.cwd = self.inventory.groups_for_host(
                    self.options.cwd)[1].name
            except Exception:
                self.options.cwd = ''
        elif arg in '/*':
            self.options.cwd = 'all'
        elif self.inventory.get_hosts(arg):
            self.options.cwd = arg
        else:
            display.display("no host matched")

        self.set_prompt()

    def do_list(self, arg):
        """List the hosts in the current group"""
        if arg == 'groups':
            for group in self.groups:
                display.display(group)
        else:
            for host in self.selected:
                display.display(host.name)

    def do_become(self, arg):
        """Toggle whether plays run with become"""
        if arg:
            self.options.become = C.mk_boolean(arg)
            display.v("become changed to %s" % self.options.become)
            self.set_prompt()
        else:
            display.display("Please specify become value, e.g. `become yes`")

    def do_remote_user(self, arg):
        """Given a username, set the remote user plays are run by"""
        if arg:
            self.options.remote_user = arg
            self.set_prompt()
        else:
            display.display(
                "Please specify a remote user, e.g. `remote_user root`")

    def do_become_user(self, arg):
        """Given a username, set the user that plays are run by when using become"""
        if arg:
            self.options.become_user = arg
        else:
            display.display(
                "Please specify a user, e.g. `become_user jenkins`")
            display.v("Current user is %s" % self.options.become_user)
        self.set_prompt()

    def do_become_method(self, arg):
        """Given a become_method, set the privilege escalation method when using become"""
        if arg:
            self.options.become_method = arg
            display.v("become_method changed to %s" %
                      self.options.become_method)
        else:
            display.display(
                "Please specify a become_method, e.g. `become_method su`")

    def do_check(self, arg):
        """Toggle whether plays run with check mode"""
        if arg:
            self.options.check = C.mk_boolean(arg)
            display.v("check mode changed to %s" % self.options.check)
        else:
            display.display(
                "Please specify check mode value, e.g. `check yes`")

    def do_diff(self, arg):
        """Toggle whether plays run with diff"""
        if arg:
            self.options.diff = C.mk_boolean(arg)
            display.v("diff mode changed to %s" % self.options.diff)
        else:
            display.display("Please specify a diff value , e.g. `diff yes`")

    def do_exit(self, args):
        """Exits from the console"""
        sys.stdout.write('\n')
        return -1

    do_EOF = do_exit

    def helpdefault(self, module_name):
        if module_name in self.modules:
            in_path = module_loader.find_plugin(module_name)
            if in_path:
                oc, a, _ = module_docs.get_docstring(in_path)
                if oc:
                    display.display(oc['short_description'])
                    display.display('Parameters:')
                    for opt in oc['options'].keys():
                        display.display('  ' +
                                        stringc(opt, C.COLOR_HIGHLIGHT) + ' ' +
                                        oc['options'][opt]['description'][0])
                else:
                    display.error('No documentation found for %s.' %
                                  module_name)
            else:
                display.error(
                    '%s is not a valid command, use ? to list all valid commands.'
                    % module_name)

    def complete_cd(self, text, line, begidx, endidx):
        mline = line.partition(' ')[2]
        offs = len(mline) - len(text)

        if self.options.cwd in ('all', '*', '\\'):
            completions = self.hosts + self.groups
        else:
            completions = [
                x.name for x in self.inventory.list_hosts(self.options.cwd)
            ]

        return [
            to_native(s)[offs:] for s in completions
            if to_native(s).startswith(to_native(mline))
        ]

    def completedefault(self, text, line, begidx, endidx):
        if line.split()[0] in self.modules:
            mline = line.split(' ')[-1]
            offs = len(mline) - len(text)
            completions = self.module_args(line.split()[0])

            return [s[offs:] + '=' for s in completions if s.startswith(mline)]

    def module_args(self, module_name):
        in_path = module_loader.find_plugin(module_name)
        oc, a, _ = module_docs.get_docstring(in_path)
        return oc['options'].keys()

    def run(self):

        super(ConsoleCLI, self).run()

        sshpass = None
        becomepass = None
        vault_pass = None

        # hosts
        if len(self.args) != 1:
            self.pattern = 'all'
        else:
            self.pattern = self.args[0]
        self.options.cwd = self.pattern

        # dynamically add modules as commands
        self.modules = self.list_modules()
        for module in self.modules:
            setattr(
                self,
                'do_' + module,
                lambda arg, module=module: self.default(module + ' ' + arg))
            setattr(self,
                    'help_' + module,
                    lambda module=module: self.helpdefault(module))

        self.normalize_become_options()
        (sshpass, becomepass) = self.ask_passwords()
        self.passwords = {'conn_pass': sshpass, 'become_pass': becomepass}

        self.loader = DataLoader()

        if self.options.vault_password_file:
            # read vault_pass from a file
            vault_pass = CLI.read_vault_password_file(
                self.options.vault_password_file, loader=self.loader)
            self.loader.set_vault_password(vault_pass)
        elif self.options.ask_vault_pass:
            vault_pass = self.ask_vault_passwords()[0]
            self.loader.set_vault_password(vault_pass)

        self.variable_manager = VariableManager()
        self.inventory = Inventory(loader=self.loader,
                                   variable_manager=self.variable_manager,
                                   host_list=self.options.inventory)
        self.variable_manager.set_inventory(self.inventory)

        no_hosts = False
        if len(self.inventory.list_hosts()) == 0:
            # Empty inventory
            no_hosts = True
            display.warning(
                "provided hosts list is empty, only localhost is available")

        self.inventory.subset(self.options.subset)
        hosts = self.inventory.list_hosts(self.pattern)
        if len(hosts) == 0 and not no_hosts:
            raise AnsibleError(
                "Specified hosts and/or --limit does not match any hosts")

        self.groups = self.inventory.list_groups()
        self.hosts = [x.name for x in hosts]

        # This hack is to work around readline issues on a mac:
        #  http://stackoverflow.com/a/7116997/541202
        if 'libedit' in readline.__doc__:
            readline.parse_and_bind("bind ^I rl_complete")
        else:
            readline.parse_and_bind("tab: complete")

        histfile = os.path.join(os.path.expanduser("~"),
                                ".ansible-console_history")
        try:
            readline.read_history_file(histfile)
        except IOError:
            pass

        atexit.register(readline.write_history_file, histfile)
        self.set_prompt()
        self.cmdloop()
Exemple #34
0
 def test_simple_string_fqdn_port(self):
     inventory = Inventory('foo.example.com:2222,bar.example.com')
     hosts = inventory.list_hosts()
     self.assertEqual(sorted(hosts),
                      sorted(['foo.example.com', 'bar.example.com']))
Exemple #35
0
def list_tags():
    # ansible playbook specific opts
    # parser.add_argument('--list-tasks', dest='listtasks', action='store_true',
    #                   help="list all tasks that would be executed")
    # parser.add_argument('--list-tags', dest='listtags', action='store_true',
    #                   help="list all available tags")
    # parser.add_argument('--step', dest='step', action='store_true',
    #                   help="one-step-at-a-time: confirm each task before running")
    # parser.add_argument('--start-at-task', dest='start_at_task',
    #                   help="start the playbook at the task matching this name")
    #
    # parser.add_argument('--inventory_file', help='Inventory Filename', required=True)
    # parser.add_argument('--playbook_path', help='Inventory Filename', required=True)

    parser = CLI.base_parser(
        usage="%prog playbook.yml",
        connect_opts=True,
        meta_opts=True,
        runas_opts=True,
        subset_opts=True,
        check_opts=True,
        inventory_opts=True,
        runtask_opts=True,
        vault_opts=True,
        fork_opts=True,
        module_opts=True,
    )

    # ansible playbook specific opts
    parser.add_option('--list-tasks',
                      dest='listtasks',
                      action='store_true',
                      help="list all tasks that would be executed")
    parser.add_option('--list-tags',
                      dest='listtags',
                      action='store_true',
                      help="list all available tags")
    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_task',
                      help="start the playbook at the task matching this name")

    options, args = parser.parse_args(args[1:])

    # options = parser.parse_args()

    inventory_path = options.inventory_file
    playbook_path = options.playbook_path

    if not os.path.exists(playbook_path):
        print('[ERROR] The playbook does not exist')
        sys.exit(1)

    loader = DataLoader()

    # initial error check, to make sure all specified playbooks are accessible
    # before we start running anything through the playbook executor
    # for playbook in playbooks:
    #     if not os.path.exists(playbook):
    #         raise Exception("the playbook: %s could not be found" % playbook)
    #     if not (os.path.isfile(playbook) or stat.S_ISFIFO(os.stat(playbook).st_mode)):
    #         raise Exception("the playbook: %s does not appear to be a file" % playbook)

    # create the variable manager, which will be shared throughout
    # the code, ensuring a consistent view of global variables
    variable_manager = VariableManager()
    # variable_manager.extra_vars = load_extra_vars(loader=loader, options=options)

    # variable_manager.options_vars = load_options_vars(options)

    # create the inventory, and filter it based on the subset specified (if any)
    inventory = Inventory(loader=loader,
                          variable_manager=variable_manager,
                          host_list=inventory_path)
    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
        print("provided hosts list is empty, only localhost is available")
        no_hosts = True
    # inventory.subset(options.subset)
    if len(inventory.list_hosts()) == 0 and no_hosts is False:
        # Invalid limit
        raise Exception("Specified --limit does not match any hosts")

    # flush fact cache if requested
    # if options.flush_cache:
    #     for host in inventory.list_hosts():
    #         variable_manager.clear_facts(host)

    passwords = {}

    # create the playbook executor, which manages running the plays via a task queue manager
    pbex = PlaybookExecutor(playbooks=[playbook_path],
                            inventory=inventory,
                            variable_manager=variable_manager,
                            loader=loader,
                            options=options,
                            passwords=passwords)

    results = pbex.run()

    if isinstance(results, list):
        for p in results:

            print('\nplaybook: %s' % p['playbook'])
            for idx, play in enumerate(p['plays']):
                msg = "\n  play #%d (%s): %s" % (idx + 1, ','.join(
                    play.hosts), play.name)
                mytags = set(play.tags)
                msg += '\tTAGS: [%s]' % (','.join(mytags))

                if 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

                print(msg)

                all_tags = set()
                if options.listtags or options.listtasks:
                    taskmsg = ''
                    if 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 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=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 options.listtags:
                        cur_tags = list(mytags.union(all_tags))
                        cur_tags.sort()
                        taskmsg += "      TASK TAGS: [%s]\n" % ', '.join(
                            cur_tags)

                    print(taskmsg)
Exemple #36
0
 def test_combined_range(self):
     i = Inventory(
         os.path.join(self.test_dir, 'inventory', 'test_combined_range'))
     hosts = i.list_hosts('test')
     expected_hosts = ['host1A', 'host2A', 'host1B', 'host2B']
     assert sorted(hosts) == sorted(expected_hosts)
Exemple #37
0
 def test_simple_string_ipv4(self):
     inventory = Inventory('127.0.0.1,192.168.1.1')
     hosts = inventory.list_hosts()
     self.assertEqual(sorted(hosts), sorted(['127.0.0.1', '192.168.1.1']))
Exemple #38
0
    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)