コード例 #1
0
class TestDataLoaderWithVault(unittest.TestCase):

    def setUp(self):
        self._loader = DataLoader()
        self._loader.set_vault_password('ansible')

    def tearDown(self):
        pass

    @patch.multiple(DataLoader, path_exists=lambda s, x: True, is_file=lambda s, x: True)
    def test_parse_from_vault_1_1_file(self):
        vaulted_data = """$ANSIBLE_VAULT;1.1;AES256
33343734386261666161626433386662623039356366656637303939306563376130623138626165
6436333766346533353463636566313332623130383662340a393835656134633665333861393331
37666233346464636263636530626332623035633135363732623332313534306438393366323966
3135306561356164310a343937653834643433343734653137383339323330626437313562306630
3035
"""
        if PY3:
            builtins_name = 'builtins'
        else:
            builtins_name = '__builtin__'

        with patch(builtins_name + '.open', mock_open(read_data=vaulted_data.encode('utf-8'))):
            output = self._loader.load_from_file('dummy_vault.txt')
            self.assertEqual(output, dict(foo='bar'))
コード例 #2
0
class TestDataLoaderWithVault(unittest.TestCase):

    def setUp(self):
        self._loader = DataLoader()
        self._loader.set_vault_password('ansible')

    def tearDown(self):
        pass

    @patch.multiple(DataLoader, path_exists=lambda s, x: True, is_file=lambda s, x: True)
    def test_parse_from_vault_1_1_file(self):
        vaulted_data = """$ANSIBLE_VAULT;1.1;AES256
33343734386261666161626433386662623039356366656637303939306563376130623138626165
6436333766346533353463636566313332623130383662340a393835656134633665333861393331
37666233346464636263636530626332623035633135363732623332313534306438393366323966
3135306561356164310a343937653834643433343734653137383339323330626437313562306630
3035
"""
        if PY3:
            builtins_name = 'builtins'
        else:
            builtins_name = '__builtin__'

        with patch(builtins_name + '.open', mock_open(read_data=vaulted_data.encode('utf-8'))):
            output = self._loader.load_from_file('dummy_vault.txt')
            self.assertEqual(output, dict(foo='bar'))
コード例 #3
0
ファイル: __init__.py プロジェクト: nmatsu/rs
    def _play_prereqs(options):

        # all needs loader
        loader = DataLoader()

        # vault
        b_vault_pass = None
        if options.vault_password_file:
            # read vault_pass from a file
            b_vault_pass = CLI.read_vault_password_file(
                options.vault_password_file, loader=loader)
        elif options.ask_vault_pass:
            b_vault_pass = CLI.ask_vault_passwords()

        if b_vault_pass is not None:
            loader.set_vault_password(b_vault_pass)

        # create the inventory, and filter it based on the subset specified (if any)
        inventory = InventoryManager(loader=loader, sources=options.inventory)

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

        # load vars from cli options
        variable_manager.extra_vars = load_extra_vars(loader=loader,
                                                      options=options)
        variable_manager.options_vars = load_options_vars(
            options, CLI.version_info(gitinfo=False))

        return loader, inventory, variable_manager
コード例 #4
0
def create_ansible_objects(inventory_file, extra_vars, forks=50):
    """Create the default ansible objects needed to run a playbook.

    :param inventory_file: The path to the inventory file
    :param extra_vars: The dictionary containing
           the collection status of the optional products.
    :param forks: number of forks to run with, default of 50
    :returns: tuple of (options, variable_manager, loader, inventory)
    """
    named_options = namedtuple('Options', [
        'connection', 'module_path', 'forks', 'become', 'become_method',
        'become_user', 'check'
    ])
    options = named_options(connection='ssh',
                            module_path=C.DEFAULT_MODULE_PATH,
                            forks=forks,
                            become=False,
                            become_method='sudo',
                            become_user='******',
                            check=False)

    variable_manager = VariableManager()
    loader = DataLoader()
    loader.set_vault_password(settings.SECRET_KEY)

    # create inventory and extra vars and pass to var manager
    inventory = Inventory(loader=loader,
                          variable_manager=variable_manager,
                          host_list=inventory_file)
    variable_manager.extra_vars = extra_vars
    variable_manager.set_inventory(inventory)

    return options, variable_manager, loader, inventory
コード例 #5
0
    def get_play_prereqs_2(self, options):
        loader = DataLoader()

        if self.vault_pass:
            loader.set_vault_password(self.vault_pass)

        variable_manager = VariableManager()
        variable_manager.extra_vars = self.extra_vars
        variable_manager.options_vars = {
            'ansible_version': self.version_info(ansible_version)
        }

        # Add this to avoid the Ansible bug:  no host vars as host is not in inventory
        # In version 2.0.1 it must be fixed
        ansible.inventory.HOSTS_PATTERNS_CACHE = {}

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

        if self.host:
            inventory.subset(self.host)
        # let inventory know which playbooks are using so it can know the
        # basedirs
        inventory.set_playbook_basedir(os.path.dirname(self.playbook_file))

        return loader, inventory, variable_manager
コード例 #6
0
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
コード例 #7
0
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
コード例 #8
0
ファイル: cli.py プロジェクト: arokem/myria-ec2-ansible
class Runner(object):

    def __init__(self, hostnames, playbook, private_key_file, run_data, become_pass=None,
                 verbosity=0, callback=None, subset_pattern=None):

        self.hostnames = hostnames

        self.playbook = os.path.join(playbooks_dir, playbook)
        self.run_data = run_data

        self.options = Options(subset=subset_pattern, private_key_file=private_key_file, verbosity=verbosity)

        self.display = Display()
        self.display.verbosity = verbosity
        playbook_executor.verbosity = verbosity

        passwords = {'become_pass': None}

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        self.loader.set_vault_password(os.environ.get('VAULT_PASS'))

        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars = self.run_data

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

        self.pbex = playbook_executor.PlaybookExecutor(
            playbooks=[self.playbook],
            inventory=self.inventory,
            variable_manager=self.variable_manager,
            loader=self.loader,
            options=self.options,
            passwords=passwords)

        if callback:
            self.pbex._tqm._stdout_callback = callback

    def run(self):
        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

        return run_success
コード例 #9
0
ファイル: ndmtk.py プロジェクト: yijxiang/ndmtk
 def _load_auth_secrets(self, hosts=[], secrets=[]):
     for _safe, _lockpick in secrets:
         try:
             _safe_loader = DataLoader();
             _safe_lockpick = CLI.read_vault_password_file(_lockpick, loader=_safe_loader);
             _safe_loader.set_vault_password(_safe_lockpick);
             _safe_contents = _safe_loader.load_from_file(_safe);
             if 'credentials' not in _safe_contents:
                 return dict();
             #display.display(pprint.pformat(_safe_contents, indent=4), color='green');
             return _safe_contents['credentials'];
         except Exception as e:
             display.display('[ERROR] ' + str(e), color='red');
     return dict();
コード例 #10
0
    def get_host_vars(self, host, vault_password=None):
        """ Get host specific variables. """
        resulting_host_vars = {}
        var_files = []

        for host_var_folder in self.host_vars_folders:
            var_files.extend(vars_files_loading(host_var_folder, host.name))

        _dataloader = DataLoader()
        _dataloader.set_vault_password(vault_password)
        for filename in var_files:
            display.vvvvv("Hostname {}: Loading var file {}".format(
                host.name, filename))
            data = _dataloader.load_from_file(filename)
            if data is not None:
                resulting_host_vars = merge_hash(resulting_host_vars, data)
        return resulting_host_vars
コード例 #11
0
ファイル: AnsibleAPI.py プロジェクト: cpatte7372/mumsyansible
def role_vars():
    parser.add_argument(
        '--playbook_path',
        help='Test Playbook path for role - usually role/tests/test.yml',
        required=True)
    parser.add_argument(
        '--vault_password_file',
        help='Vault password file - usually role/tests/test.yml')
    args = parser.parse_args()

    variable_manager = VariableManager()
    loader = DataLoader()

    if args.vault_password_file:
        # read vault_pass from a file
        vault_pass = CLI.read_vault_password_file(args.vault_password_file,
                                                  loader=loader)
        loader.set_vault_password(vault_pass)

    playbook_path = args.playbook_path

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

    pb = Playbook.load(playbook_path,
                       variable_manager=variable_manager,
                       loader=loader)
    plays = pb.get_plays()

    if len(plays) == 0:
        print('[ERROR] No plays in playbook')
        sys.exit(1)

    first_play = plays[0]
    if first_play._included_path is not None:
        loader.set_basedir(first_play._included_path)
    else:
        loader.set_basedir(pb._basedir)

    result = dict()
    for role in first_play.roles:
        result.update(role.get_default_vars())
        result.update(role.get_vars())

    print(json.dumps(result))
コード例 #12
0
    def get_group_vars(self, group, vault_password=None):
        """ Get group specific variables. """

        resulting_group_vars = {}
        var_files = []

        for grp_var_folder in self.grp_vars_folders:
            var_files.extend(vars_files_loading(grp_var_folder, group.name))

        _dataloader = DataLoader()
        _dataloader.set_vault_password(vault_password)
        for filename in var_files:
            display.vvvvv("Group {}: Loading var file {}".format(
                group.name, filename))
            data = _dataloader.load_from_file(filename)
            if data is not None:
                resulting_group_vars = merge_hash(resulting_group_vars, data)
        return resulting_group_vars
コード例 #13
0
class FrecklesRunner(object):

    def __init__(self, playbook, become_pass, verbosity=0):

        self.options = Options()
        self.options.verbosity = verbosity

        self.display = Display()
        self.display.verbosity = self.options.verbosity
        playbook_executor.verbosity = self.options.verbosity

        passwords = {'become_pass': become_pass}

        self.loader = DataLoader()
        self.loader.set_vault_password(os.environ['VAULT_PASS'])

        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars = self.run_data
コード例 #14
0
 def __init__(self, inventory, ask_vault_pass, vault_password_files, vault_ids):
     if vault_ids or len(vault_password_files) > 1:
         raise NotImplementedError
     from ansible.cli import CLI
     super(Inventory20, self).__init__()
     loader = DataLoader()
     if ask_vault_pass:
         self.vault_pass = CLI.ask_vault_passwords()
     elif vault_password_files:
         self.vault_pass = CLI.read_vault_password_file(vault_password_files[0], loader)
     if self.vault_pass is not None:
         loader.set_vault_password(self.vault_pass)
     self.variable_manager = VariableManager()
     try:
         self.inventory = ansible.inventory.Inventory(loader=loader,
                                                      variable_manager=self.variable_manager,
                                                      host_list=inventory)
     except ansible.errors.AnsibleError:
         raise NoVaultSecretFound
     self.variable_manager.set_inventory(self.inventory)
コード例 #15
0
    def get_play_prereqs_2(self, options):
        loader = DataLoader()

        if self.vault_pass:
            loader.set_vault_password(self.vault_pass)

        variable_manager = VariableManager()
        variable_manager.extra_vars = self.extra_vars
        variable_manager.options_vars = {
            'ansible_version': self.version_info(ansible_version)
        }

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

        # let inventory know which playbooks are using so it can know the
        # basedirs
        inventory.set_playbook_basedir(os.path.dirname(self.playbook_file))

        return loader, inventory, variable_manager
コード例 #16
0
 def __init__(self, inventory, ask_vault_pass, vault_password_files,
              vault_ids):
     if vault_ids or len(vault_password_files) > 1:
         raise NotImplementedError
     from ansible.cli import CLI
     super(Inventory20, self).__init__()
     loader = DataLoader()
     if ask_vault_pass:
         self.vault_pass = CLI.ask_vault_passwords()
     elif vault_password_files:
         self.vault_pass = CLI.read_vault_password_file(
             vault_password_files[0], loader)
     if self.vault_pass is not None:
         loader.set_vault_password(self.vault_pass)
     self.variable_manager = VariableManager()
     try:
         self.inventory = ansible.inventory.Inventory(
             loader=loader,
             variable_manager=self.variable_manager,
             host_list=inventory)
     except ansible.errors.AnsibleError:
         raise NoVaultSecretFound
     self.variable_manager.set_inventory(self.inventory)
コード例 #17
0
def setup_inventory(ctx):
    """sets up the inventory object for use by other functions"""

    loader = DataLoader()
    variable_manager = VariableManager()

    if ctx.obj['vault_password_command']:
        try:
            vault_password = subprocess.check_output(
                ctx.obj['vault_password_command'], shell=True)
        except subprocess.CalledProcessError:
            print "Vault password command exited with non-zero code"
            sys.exit(1)
        loader.set_vault_password(vault_password.rstrip())
    elif os.environ.get('ANSIBLE_VAULT_PASSWORD_FILE'):
        with open(os.environ.get('ANSIBLE_VAULT_PASSWORD_FILE'),
                  'r') as vault_password_file:
            loader.set_vault_password(vault_password_file.read().strip())

    try:
        if (ctx.obj['inventory']):
            return Inventory(loader=loader,
                             variable_manager=variable_manager,
                             host_list=ctx.obj['inventory'])
        else:
            return Inventory(loader=loader, variable_manager=variable_manager)

    except AnsibleError as e:
        # If it fails to decrypt and a password command hasn't been provided, prompt for one
        if not ctx.obj['vault_password_command'] and str(
                e) == 'Decryption failed':
            vault_password = getpass.getpass('Enter vault password:'******'inventory']):
                return Inventory(loader=loader,
                                 variable_manager=variable_manager,
                                 host_list=ctx.obj['inventory'])
            else:
                return Inventory(loader=loader,
                                 variable_manager=variable_manager)
        else:
            print "Something went wrong:"
            print repr(e)
            sys.exit(1)
コード例 #18
0
def setup_inventory(ctx):
    """sets up the inventory object for use by other functions"""

    loader = DataLoader()
    variable_manager = VariableManager()

    if ctx.obj['vault_password_command']:
        try:
            vault_password = subprocess.check_output(ctx.obj['vault_password_command'], shell=True)
        except subprocess.CalledProcessError:
            print "Vault password command exited with non-zero code"
            sys.exit(1)
        loader.set_vault_password(vault_password.rstrip())
    elif os.environ.get('ANSIBLE_VAULT_PASSWORD_FILE'):
        with open(os.environ.get('ANSIBLE_VAULT_PASSWORD_FILE'), 'r') as vault_password_file:
            loader.set_vault_password(vault_password_file.read().strip())

    try:
        if(ctx.obj['inventory']):
            return Inventory(loader=loader,
                             variable_manager=variable_manager,
                             host_list=ctx.obj['inventory'])
        else:
            return Inventory(loader=loader,
                             variable_manager=variable_manager)

    except AnsibleError as e:
        # If it fails to decrypt and a password command hasn't been provided, prompt for one
        if not ctx.obj['vault_password_command'] and str(e) == 'Decryption failed':
            vault_password = getpass.getpass('Enter vault password:'******'inventory']):
                return Inventory(loader=loader,
                                 variable_manager=variable_manager,
                                 host_list=ctx.obj['inventory'])
            else:
                return Inventory(loader=loader,
                                 variable_manager=variable_manager)
        else:
            print "Something went wrong:"
            print repr(e)
            sys.exit(1)
コード例 #19
0
ファイル: inventory.py プロジェクト: lingroger/Python
class InventoryCLI(CLI):
    ''' used to display or dump the configured inventory as Ansible sees it '''

    ARGUMENTS = {
        'host':
        'The name of a host to match in the inventory, relevant when using --list',
        'group':
        'The name of a group in the inventory, relevant when using --graph',
    }

    def __init__(self, args):

        super(InventoryCLI, self).__init__(args)
        self.vm = None
        self.loader = None
        self.inventory = None

        self._new_api = True

    def parse(self):

        self.parser = CLI.base_parser(
            usage='usage: %prog [options] [host|group]',
            epilog=
            'Show Ansible inventory information, by default it uses the inventory script JSON format',
            inventory_opts=True,
            vault_opts=True,
            basedir_opts=True,
        )

        # remove unused default options
        self.parser.remove_option('--limit')
        self.parser.remove_option('--list-hosts')

        # Actions
        action_group = optparse.OptionGroup(
            self.parser, "Actions",
            "One of following must be used on invocation, ONLY ONE!")
        action_group.add_option(
            "--list",
            action="store_true",
            default=False,
            dest='list',
            help='Output all hosts info, works as inventory script')
        action_group.add_option(
            "--host",
            action="store",
            default=None,
            dest='host',
            help='Output specific host info, works as inventory script')
        action_group.add_option(
            "--graph",
            action="store_true",
            default=False,
            dest='graph',
            help=
            'create inventory graph, if supplying pattern it must be a valid group name'
        )
        self.parser.add_option_group(action_group)

        # graph
        self.parser.add_option(
            "-y",
            "--yaml",
            action="store_true",
            default=False,
            dest='yaml',
            help='Use YAML format instead of default JSON, ignored for --graph'
        )
        self.parser.add_option(
            "--vars",
            action="store_true",
            default=False,
            dest='show_vars',
            help='Add vars to graph display, ignored unless used with --graph')

        # list
        self.parser.add_option(
            "--export",
            action="store_true",
            default=C.INVENTORY_EXPORT,
            dest='export',
            help=
            "When doing an --list, represent in a way that is optimized for export,"
            "not as an accurate representation of how Ansible has processed it"
        )
        # self.parser.add_option("--ignore-vars-plugins", action="store_true", default=False, dest='ignore_vars_plugins',
        #                       help="When doing an --list, skip vars data from vars plugins, by default, this would include group_vars/ and host_vars/")

        super(InventoryCLI, self).parse()

        display.verbosity = self.options.verbosity

        self.validate_conflicts(vault_opts=True)

        # there can be only one! and, at least, one!
        used = 0
        for opt in (self.options.list, self.options.host, self.options.graph):
            if opt:
                used += 1
        if used == 0:
            raise AnsibleOptionsError(
                "No action selected, at least one of --host, --graph or --list needs to be specified."
            )
        elif used > 1:
            raise AnsibleOptionsError(
                "Conflicting options used, only one of --host, --graph or --list can be used at the same time."
            )

        # set host pattern to default if not supplied
        if len(self.args) > 0:
            self.options.pattern = self.args[0]
        else:
            self.options.pattern = 'all'

    def run(self):

        results = None

        super(InventoryCLI, self).run()

        # Initialize needed objects
        if getattr(self, '_play_prereqs', False):
            self.loader, self.inventory, self.vm = self._play_prereqs(
                self.options)
        else:
            # fallback to pre 2.4 way of initialzing
            from ansible.vars import VariableManager
            from ansible.inventory import Inventory

            self._new_api = False
            self.loader = DataLoader()
            self.vm = VariableManager()

            # use vault if needed
            if self.options.vault_password_file:
                vault_pass = CLI.read_vault_password_file(
                    self.options.vault_password_file, loader=self.loader)
            elif self.options.ask_vault_pass:
                vault_pass = self.ask_vault_passwords()
            else:
                vault_pass = None

            if vault_pass:
                self.loader.set_vault_password(vault_pass)
                # actually get inventory and vars

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

        if self.options.host:
            hosts = self.inventory.get_hosts(self.options.host)
            if len(hosts) != 1:
                raise AnsibleOptionsError(
                    "You must pass a single valid host to --hosts parameter")

            myvars = self._get_host_variables(host=hosts[0])
            self._remove_internal(myvars)

            # FIXME: should we template first?
            results = self.dump(myvars)

        elif self.options.graph:
            results = self.inventory_graph()
        elif self.options.list:
            top = self._get_group('all')
            if self.options.yaml:
                results = self.yaml_inventory(top)
            else:
                results = self.json_inventory(top)
            results = self.dump(results)

        if results:
            # FIXME: pager?
            display.display(results)
            exit(0)

        exit(1)

    def dump(self, stuff):

        if self.options.yaml:
            import yaml
            from ansible.parsing.yaml.dumper import AnsibleDumper
            results = yaml.dump(stuff,
                                Dumper=AnsibleDumper,
                                default_flow_style=False)
        else:
            import json
            from ansible.parsing.ajson import AnsibleJSONEncoder
            results = json.dumps(stuff,
                                 cls=AnsibleJSONEncoder,
                                 sort_keys=True,
                                 indent=4)

        return results

    # FIXME: refactor to use same for VM
    def get_plugin_vars(self, path, entity):

        data = {}

        def _get_plugin_vars(plugin, path, entities):
            data = {}
            try:
                data = plugin.get_vars(self.loader, path, entity)
            except AttributeError:
                try:
                    if isinstance(entity, Host):
                        data = combine_vars(data,
                                            plugin.get_host_vars(entity.name))
                    else:
                        data = combine_vars(data,
                                            plugin.get_group_vars(entity.name))
                except AttributeError:
                    if hasattr(plugin, 'run'):
                        raise AnsibleError(
                            "Cannot use v1 type vars plugin %s from %s" %
                            (plugin._load_name, plugin._original_path))
                    else:
                        raise AnsibleError(
                            "Invalid vars plugin %s from %s" %
                            (plugin._load_name, plugin._original_path))
            return data

        for plugin in vars_loader.all():
            data = combine_vars(data, _get_plugin_vars(plugin, path, entity))

        return data

    def _get_group_variables(self, group):

        # get info from inventory source
        res = group.get_vars()

        # FIXME: add switch to skip vars plugins, add vars plugin info
        for inventory_dir in self.inventory._sources:
            res = combine_vars(res, self.get_plugin_vars(inventory_dir, group))

        if group.priority != 1:
            res['ansible_group_priority'] = group.priority

        return res

    def _get_host_variables(self, host):

        if self.options.export:
            hostvars = host.get_vars()

            # FIXME: add switch to skip vars plugins
            # add vars plugin info
            for inventory_dir in self.inventory._sources:
                hostvars = combine_vars(
                    hostvars, self.get_plugin_vars(inventory_dir, host))
        else:
            if self._new_api:
                hostvars = self.vm.get_vars(host=host, include_hostvars=False)
            else:
                hostvars = self.vm.get_vars(self.loader,
                                            host=host,
                                            include_hostvars=False)

        return hostvars

    def _get_group(self, gname):
        if self._new_api:
            group = self.inventory.groups.get(gname)
        else:
            group = self.inventory.get_group(gname)
        return group

    def _remove_internal(self, dump):

        for internal in INTERNAL_VARS:
            if internal in dump:
                del dump[internal]

    def _remove_empty(self, dump):
        # remove empty keys
        for x in ('hosts', 'vars', 'children'):
            if x in dump and not dump[x]:
                del dump[x]

    def _show_vars(self, dump, depth):
        result = []
        self._remove_internal(dump)
        if self.options.show_vars:
            for (name, val) in sorted(dump.items()):
                result.append(
                    self._graph_name('{%s = %s}' % (name, val), depth))
        return result

    def _graph_name(self, name, depth=0):
        if depth:
            name = "  |" * (depth) + "--%s" % name
        return name

    def _graph_group(self, group, depth=0):

        result = [self._graph_name('@%s:' % group.name, depth)]
        depth = depth + 1
        for kid in sorted(group.child_groups, key=attrgetter('name')):
            result.extend(self._graph_group(kid, depth))

        if group.name != 'all':
            for host in sorted(group.hosts, key=attrgetter('name')):
                result.append(self._graph_name(host.name, depth))
                result.extend(self._show_vars(host.get_vars(), depth + 1))

        result.extend(self._show_vars(self._get_group_variables(group), depth))

        return result

    def inventory_graph(self):

        start_at = self._get_group(self.options.pattern)
        if start_at:
            return '\n'.join(self._graph_group(start_at))
        else:
            raise AnsibleOptionsError(
                "Pattern must be valid group name when using --graph")

    def json_inventory(self, top):
        def format_group(group):
            results = {}
            results[group.name] = {}
            if group.name != 'all':
                results[group.name]['hosts'] = [
                    h.name for h in sorted(group.hosts, key=attrgetter('name'))
                ]
            results[group.name]['children'] = []
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                results[group.name]['children'].append(subgroup.name)
                results.update(format_group(subgroup))
            if self.options.export:
                results[group.name]['vars'] = self._get_group_variables(group)

            self._remove_empty(results[group.name])

            return results

        results = format_group(top)

        # populate meta
        results['_meta'] = {'hostvars': {}}
        hosts = self.inventory.get_hosts()
        for host in hosts:
            hvars = self._get_host_variables(host)
            if hvars:
                self._remove_internal(hvars)
                results['_meta']['hostvars'][host.name] = hvars

        return results

    def yaml_inventory(self, top):

        seen = []

        def format_group(group):
            results = {}

            # initialize group + vars
            results[group.name] = {}

            # subgroups
            results[group.name]['children'] = {}
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                if subgroup.name != 'all':
                    results[group.name]['children'].update(
                        format_group(subgroup))

            # hosts for group
            results[group.name]['hosts'] = {}
            if group.name != 'all':
                for h in sorted(group.hosts, key=attrgetter('name')):
                    myvars = {}
                    if h.name not in seen:  # avoid defining host vars more than once
                        seen.append(h.name)
                        myvars = self._get_host_variables(host=h)
                        self._remove_internal(myvars)
                    results[group.name]['hosts'][h.name] = myvars

            if self.options.export:

                gvars = self._get_group_variables(group)
                if gvars:
                    results[group.name]['vars'] = gvars

            self._remove_empty(results[group.name])

            return results

        return format_group(top)
コード例 #20
0
class InventoryCLI(CLI):
    ''' used to display or dump the configured inventory as Ansible sees it '''

    ARGUMENTS = {
        'host':
        'The name of a host to match in the inventory, relevant when using --list',
        'group':
        'The name of a group in the inventory, relevant when using --graph',
    }

    def __init__(self, args):

        super(InventoryCLI, self).__init__(args)
        self.args = args
        self.vm = None
        self.loader = None
        self.inventory = None

        self._new_api = True

    def parse(self):

        self.parser = CLI.base_parser(
            usage='usage: %prog [options] [host|group]',
            epilog=
            'Show Ansible inventory information, by default it uses the inventory script JSON format',
            inventory_opts=True,
            vault_opts=True)
        self.parser.add_option(
            "--optimize",
            action="store_true",
            default=False,
            dest='optimize',
            help='Output variables on the group or host where they are defined'
        )

        # Actions
        action_group = optparse.OptionGroup(
            self.parser, "Actions",
            "One of following must be used on invocation, ONLY ONE!")
        action_group.add_option(
            "--list",
            action="store_true",
            default=False,
            dest='list',
            help='Output all hosts info, works as inventory script')
        action_group.add_option(
            "--host",
            action="store",
            default=None,
            dest='host',
            help='Output specific host info, works as inventory script')
        action_group.add_option(
            "--graph",
            action="store_true",
            default=False,
            dest='graph',
            help=
            'create inventory graph, if supplying pattern it must be a valid group name'
        )
        self.parser.add_option_group(action_group)

        # Options
        self.parser.add_option(
            "-y",
            "--yaml",
            action="store_true",
            default=False,
            dest='yaml',
            help='Use YAML format instead of default JSON, ignored for --graph'
        )
        self.parser.add_option(
            "--vars",
            action="store_true",
            default=False,
            dest='show_vars',
            help='Add vars to graph display, ignored unless used with --graph')

        try:
            super(InventoryCLI, self).parse()
        except Exception as e:
            if 'Need to implement!' not in e.args[0]:
                raise
            # --- Start of 2.3+ super(InventoryCLI, self).parse() ---
            self.options, self.args = self.parser.parse_args(self.args[1:])
            # --- End of 2.3+ super(InventoryCLI, self).parse() ---

        display.verbosity = self.options.verbosity

        self.validate_conflicts(vault_opts=True)

        # there can be only one! and, at least, one!
        used = 0
        for opt in (self.options.list, self.options.host, self.options.graph):
            if opt:
                used += 1
        if used == 0:
            raise AnsibleOptionsError(
                "No action selected, at least one of --host, --graph or --list needs to be specified."
            )
        elif used > 1:
            raise AnsibleOptionsError(
                "Conflicting options used, only one of --host, --graph or --list can be used at the same time."
            )

        # set host pattern to default if not supplied
        if len(self.args) > 0:
            self.options.pattern = self.args[0]
        else:
            self.options.pattern = 'all'

    def run(self):

        results = None

        super(InventoryCLI, self).run()

        # Initialize needed objects
        if getattr(self, '_play_prereqs', False):
            self.loader, self.inventory, self.vm = self._play_prereqs(
                self.options)
        else:
            # fallback to pre 2.4 way of initialzing
            from ansible.vars import VariableManager
            from ansible.inventory import Inventory

            self._new_api = False
            self.loader = DataLoader()
            self.vm = VariableManager()

            # use vault if needed
            if self.options.vault_password_file:
                vault_pass = CLI.read_vault_password_file(
                    self.options.vault_password_file, loader=self.loader)
            elif self.options.ask_vault_pass:
                vault_pass = self.ask_vault_passwords()
            else:
                vault_pass = None

            if vault_pass:
                self.loader.set_vault_password(vault_pass)
                # actually get inventory and vars

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

        if self.options.host:
            hosts = self.inventory.get_hosts(self.options.host)
            if len(hosts) != 1:
                raise AnsibleOptionsError(
                    "You must pass a single valid host to --hosts parameter")

            myvars = self._get_host_variables(host=hosts[0])
            self._remove_internal(myvars)

            # FIXME: should we template first?
            results = self.dump(myvars)

        elif self.options.graph:
            results = self.inventory_graph()
        elif self.options.list:
            top = self._get_group('all')
            if self.options.yaml:
                results = self.yaml_inventory(top)
            else:
                results = self.json_inventory(top)
            results = self.dump(results)

        if results:
            # FIXME: pager?
            display.display(results)
            exit(0)

        exit(1)

    def dump(self, stuff):

        if self.options.yaml:
            import yaml
            from ansible.parsing.yaml.dumper import AnsibleDumper
            results = yaml.dump(stuff,
                                Dumper=AnsibleDumper,
                                default_flow_style=False)
        else:
            import json
            results = json.dumps(stuff, sort_keys=True, indent=4)

        return results

    def _get_host_variables(self, host):
        if self._new_api:
            hostvars = self.vm.get_vars(host=host)
        else:
            hostvars = self.vm.get_vars(self.loader, host=host)
        return hostvars

    def _get_group(self, gname):
        if self._new_api:
            group = self.inventory.groups.get(gname)
        else:
            group = self.inventory.get_group(gname)
        return group

    def _remove_internal(self, dump):

        for internal in INTERNAL_VARS:
            if internal in dump:
                del dump[internal]

    def _remove_empty(self, dump):
        # remove empty keys
        for x in ('hosts', 'vars', 'children'):
            if x in dump and not dump[x]:
                del dump[x]

    def _show_vars(self, dump, depth):
        result = []
        self._remove_internal(dump)
        if self.options.show_vars:
            for (name, val) in sorted(dump.items()):
                result.append(
                    self._graph_name('{%s = %s}' % (name, val), depth + 1))
        return result

    def _graph_name(self, name, depth=0):
        if depth:
            name = "  |" * (depth) + "--%s" % name
        return name

    def _graph_group(self, group, depth=0):

        result = [self._graph_name('@%s:' % group.name, depth)]
        depth = depth + 1
        for kid in sorted(group.child_groups, key=attrgetter('name')):
            result.extend(self._graph_group(kid, depth))

        if group.name != 'all':
            for host in sorted(group.hosts, key=attrgetter('name')):
                result.append(self._graph_name(host.name, depth))
                result.extend(self._show_vars(host.get_vars(), depth))

        result.extend(self._show_vars(group.get_vars(), depth))

        return result

    def inventory_graph(self):

        start_at = self._get_group(self.options.pattern)
        if start_at:
            return '\n'.join(self._graph_group(start_at))
        else:
            raise AnsibleOptionsError(
                "Pattern must be valid group name when using --graph")

    def json_inventory(self, top):
        def format_group(group):
            results = {}
            results[group.name] = {}
            if group.name != 'all':
                results[group.name]['hosts'] = [
                    h.name for h in sorted(group.hosts, key=attrgetter('name'))
                ]
            results[group.name]['vars'] = group.get_vars()
            results[group.name]['children'] = []
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                results[group.name]['children'].append(subgroup.name)
                results.update(format_group(subgroup))

            self._remove_empty(results[group.name])
            return results

        results = format_group(top)

        # populate meta
        results['_meta'] = {'hostvars': {}}
        hosts = self.inventory.get_hosts()
        for host in hosts:
            results['_meta']['hostvars'][host.name] = self._get_host_variables(
                host=host)
            self._remove_internal(results['_meta']['hostvars'][host.name])

        return results

    def yaml_inventory(self, top):

        seen = []

        def format_group(group):
            results = {}

            # initialize group + vars
            results[group.name] = {}
            results[group.name]['vars'] = group.get_vars()

            # subgroups
            results[group.name]['children'] = {}
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                if subgroup.name != 'all':
                    results[group.name]['children'].update(
                        format_group(subgroup))

            # hosts for group
            results[group.name]['hosts'] = {}
            if group.name != 'all':
                for h in sorted(group.hosts, key=attrgetter('name')):
                    myvars = {}
                    if h.name not in seen:  # avoid defining host vars more than once
                        seen.append(h.name)
                        myvars = self._get_host_variables(host=h)
                        self._remove_internal(myvars)
                    results[group.name]['hosts'][h.name] = myvars

            self._remove_empty(results[group.name])
            return results

        return format_group(top)
コード例 #21
0
ファイル: task.py プロジェクト: Michael754267513/pythonnote
class Runner(object):
    def __init__(self,
                 hostnames,
                 playbook,
                 private_key_file,
                 run_data,
                 become_pass,
                 verbosity=0):

        self.run_data = run_data
        self.options = Options()
        self.options.private_key_file = private_key_file
        self.options.verbosity = verbosity
        self.options.connection = 'ssh'  # Need a connection type "smart" or "ssh"
        self.options.become = True
        self.options.become_method = 'sudo'
        self.options.become_user = '******'

        # Set global verbosity
        self.display = Display()
        self.display.verbosity = self.options.verbosity
        # Executor appears to have it's own
        # verbosity object/setting as well
        playbook_executor.verbosity = self.options.verbosity

        # Become Pass Needed if not logging in as user root
        passwords = {'become_pass': become_pass}

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        self.loader.set_vault_password(os.environ['VAULT_PASS'])

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars = self.run_data

        # Parse hosts, I haven't found a good way to
        # pass hosts in without using a parsed template :(
        # (Maybe you know how?)
        self.hosts = NamedTemporaryFile(delete=False)
        self.hosts.write("""[run_hosts]
                            %s
                                """ % hostnames)
        self.hosts.close()

        # This was my attempt to pass in hosts directly.
        #
        # Also Note: In py2.7, "isinstance(foo, str)" is valid for
        #            latin chars only. Luckily, hostnames are
        #            ascii-only, which overlaps latin charset
        ## if isinstance(hostnames, str):
        ##     hostnames = {"customers": {"hosts": [hostnames]}}

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

        # Playbook to run. Assumes it is
        # local to this python file
        pb_dir = os.path.dirname(__file__)
        playbook = "%s/%s" % (pb_dir, playbook)

        # 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):
        # Results of PlaybookExecutor
        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
        self.pbex._tqm.send_callback('record_logs',
                                     user_id=self.run_data['user_id'],
                                     success=run_success)

        # Remove created temporary files
        os.remove(self.hosts.name)

        return stats
コード例 #22
0
ファイル: commandcli.py プロジェクト: smoothify/able
    def run_command(self, name, ctx=None):
        cmd = self.able_file.get_command(name)

        from able.ablefile.command import AbleCommand
        if not isinstance(cmd, AbleCommand):
            return 0

        cmd.ablefile = self.able_file
        params, global_params = utils.filter_params(ctx.params)
        self.options = self.get_global_option_values(cmd, global_params)
        if 'verbosity' in self.options:
            display.verbosity = self.options.verbosity

        # 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()
            (conn_pass, become_pass) = self.ask_passwords()
            passwords['conn_pass'] = conn_pass if conn_pass is not None else self.options.conn_pass
            passwords['become_pass'] = become_pass if become_pass is not None else self.options.become_pass

        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)

        variable_manager = cmd.get_variable_manager()
        variable_manager.extra_vars = cmd.get_extra_vars(params, self.options)
        loader = cmd.get_loader()

        # create inventory and pass to var manager
        inventory = AbleInventory(
            loader=loader,
            variable_manager=variable_manager,
            host_list=cmd.get_inventory(),
            inventory_files=cmd.get_inventory_files()
        )
        variable_manager.set_inventory(inventory)

        # Run any confirmation prompts
        cmd.do_confirm(variable_manager, loader)

        # create the playbook executor, which manages running the plays via a task queue manager
        ex = AbleCommandExecutor(
            command=cmd,
            inventory=inventory,
            variable_manager=variable_manager,
            loader=loader,
            options=self.options,
            passwords=passwords)

        results = ex.run()

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

                display.display('\nCommand: %s' % p['command'])
                for idx, play in enumerate(p['plays']):
                    msg = "\n  command #%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'

                        all_vars = cmd.get_variable_manager().get_vars(loader=cmd.get_loader(), play=self)
                        play_context = PlayContext(play=self, options=self.options)
                        for block in play.compile():
                            block = block.filter_tagged_tasks(play_context, all_vars)
                            if not block.has_tasks():
                                continue

                            for task in block.block:
                                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)

                        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
コード例 #23
0
ファイル: runner.py プロジェクト: zhu1fei/contrail-docker
class Runner(object):
    def __init__(self,
                 playbook,
                 inventory,
                 run_data=None,
                 verbosity=0,
                 tags=None,
                 skip_tags=None):
        self.run_data = run_data or {}
        self.options = Options()

        self.options.verbosity = verbosity
        self.options.connection = 'local'  # Need a connection type "smart" or "ssh"
        self.options.become = True
        self.options.become_method = 'sudo'
        self.options.become_user = '******'
        self.options.tags = tags or []
        self.options.skip_tags = skip_tags or []
        # Set global verbosity
        self.display = Display()
        self.display.verbosity = self.options.verbosity
        # Executor appears to have it's own
        # verbosity object/setting as well
        playbook_executor.verbosity = self.options.verbosity

        # Become Pass Needed if not logging in as user root
        passwords = {}

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        self.loader.set_vault_password(os.environ.get('VAULT_PASS', ''))

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars = self.run_data

        self.inventory = Inventory(loader=self.loader,
                                   variable_manager=self.variable_manager,
                                   host_list=inventory)
        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, verbose=False):
        if not verbose:
            # Results of PlaybookExecutor
            cb = DisplayErrorCallback()
            self.pbex._tqm._stdout_callback = cb
        try:
            res = self.pbex.run()
        except AnsibleParserError as err:
            print(err)
            return None
        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

        return stats
コード例 #24
0
    def execute(self, hosts, environment, module="shell", command="ls"):
        Options = namedtuple('Options', [
            'connection', 'module_path', 'forks', 'become', 'become_method',
            'become_user', 'check'
        ])
        # initialize needed objects
        variable_manager = VariableManager()
        loader = DataLoader()
        options = Options(connection='ssh',
                          module_path=None,
                          forks=10,
                          become=None,
                          become_method=None,
                          become_user=None,
                          check=False)
        passwords = {}
        if self.vault_password_file:
            passwords = dict(
                vault_pass=open(os.path.expanduser(self.vault_password_file),
                                'r').read().strip())
            loader.set_vault_password(passwords['vault_pass'])

        # Instantiate our ResultCallback for handling results as they come in
        results_callback = ResultCallback()

        # create inventory and pass to var manager
        inventory = Inventory(loader=loader,
                              variable_manager=variable_manager,
                              host_list=environment)
        variable_manager.set_inventory(inventory)

        # create play with tasks
        play_source = dict(
            name=self.play_name,
            hosts=hosts,
            gather_facts='no',
            tasks=[
                dict(action=dict(module=module, args=command),
                     register='shell_out'),
                dict(action=dict(module='debug',
                                 args=dict(msg='{{shell_out.stdout}}')))
            ])
        play = Play().load(play_source,
                           variable_manager=variable_manager,
                           loader=loader)

        # actually run it
        tqm = None
        try:
            logger.info(
                "Executing: command [%s] in play %s on hosts %s in environment %s",
                command, self.play_name, hosts, environment)
            tqm = TaskQueueManager(
                inventory=inventory,
                variable_manager=variable_manager,
                loader=loader,
                options=options,
                passwords=passwords,
                stdout_callback=
                results_callback,  # Use our custom callback instead of the ``default`` callback plugin
            )
            result = tqm.run(play)
        finally:
            if tqm is not None:
                tqm.cleanup()
コード例 #25
0
class Runner(object):
    def __init__(
            self,
            playbooks,
            tags,  # must have
            extra_vars,
            hostnames='127.0.0.1',
            connection='local',  # smart|ssh|local
            private_key_file='',
            become_pass='',
            vault_pass='',
            verbosity=0,
            debug=False):
        self.debug = debug
        self.options = Options()
        self.options.tags = tags,
        self.options.private_key_file = private_key_file
        self.options.verbosity = verbosity
        self.options.connection = connection
        self.options.become = True
        self.options.become_method = 'sudo'
        self.options.become_user = '******'
        self.options.extra_vars = extra_vars

        # Set global verbosity
        self.display = Display()
        self.display.verbosity = self.options.verbosity

        # Executor appears to have it's own
        # verbosity object/setting as well
        playbook_executor.verbosity = self.options.verbosity

        # Become Pass Needed if not logging in as user root
        passwords = {'become_pass': become_pass}

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        self.loader.set_vault_password(vault_pass)

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars = extra_vars

        # Parse hosts, I haven't found a good way to
        # pass hosts in without using a parsed template :(
        # (Maybe you know how?)
        self.hosts = NamedTemporaryFile(delete=False, mode='wt')
        self.hosts.write("""[run_hosts]\n%s""" % hostnames)
        self.hosts.close()

        # This was my attempt to pass in hosts directly.
        #
        # Also Note: In py2.7, "isinstance(foo, str)" is valid for
        #            latin chars only. Luckily, hostnames are
        #            ascii-only, which overlaps latin charset
        # if isinstance(hostnames, str):
        # hostnames = {"customers": {"hosts": [hostnames]}}

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

        # Playbook to run. Assumes it is
        # local and relative to this python file
        # in "../../../playbooks" directory.
        dirname = os.path.dirname(__file__) or '.'
        pb_rel_dir = '../../../playbooks'
        playbook_path = os.path.join(dirname, pb_rel_dir)
        self.options.module_path = os.path.join(playbook_path, 'library')

        # os.environ['ANSIBLE_CONFIG'] = os.path.abspath(os.path.dirname(__file__))
        pbs = [os.path.join(playbook_path, pb) for pb in playbooks]

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

        # TODO: so here we construct a CLI line.
        # For whatever reason, api is not taking account for `tags`!!
        self.callme = [
            'ansible-playbook',
            '-i',
            self.hosts.name,
            ','.join(pbs),
        ]
        if tags:
            self.callme += ['--tags', ','.join(tags)]
        if extra_vars:
            extra = ["%s=%s" % (k, v) for k, v in extra_vars.items()]
            self.callme += ['--extra-vars', '"%s"' % (' '.join(extra))]
        if self.options.module_path:
            self.callme += ['--module-path', self.options.module_path]

    def run(self):
        # Results of PlaybookExecutor
        if self.debug:
            print "ansbile cmd: ", ' '.join(self.callme)

        # self.pbex.run()

        # TODO: this is truly strange! I tried all subprocess calls,
        # and this is the ONLY way that works! All others didn't, even though
        # the printed cmd line is exactly the same, and can be executed
        # if I copy & paste in a terminal. So strange!
        return_code = subprocess.call(' '.join(self.callme), shell=True)
        return True if return_code == 0 else False
コード例 #26
0
                           private_key_file=None,
                           ssh_common_args=None,
                           ssh_extra_args=None,
                           sftp_extra_args=None,
                           scp_extra_args=None,
                           become=None,
                           become_method='sudo',
                           become_user='******',
                           verbosity=None,
                           check=False)

    loader = DataLoader()
    if os.path.exists('/tmp/vault_pass.txt'):
        with open('/tmp/vault_pass.txt', 'r') as vaultfile:
            data=vaultfile.read().replace('\n', '')
        loader.set_vault_password(data)

    variable_manager = VariableManager()
    variable_manager.extra_vars.update(args.extra_vars)

    # we apply an exhaustive list of groups to the host that is created in the
    # inventory, simply to ensure that we resolve the correct hosts for each
    # play. This has the unfortunate side effect that if someone has a
    # group_var that shadows the name of a play, it could be applied unexpectedly.
    # TODO: look up plays by name and fetch the host_groups explicitly to be added.
    inventory_host_groups = args.groups + args.hosts + args.plays
    inventory = build_inventory(loader, variable_manager, inventory_host_groups, playbook_basedir)

    variable_manager.set_inventory(inventory)
    plays = build_plays(loader, variable_manager, args.playbook, plays=args.plays, hosts=args.hosts)
コード例 #27
0
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
コード例 #28
0
ファイル: console.py プロジェクト: likewg/DevOps
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()
コード例 #29
0
ファイル: utils.py プロジェクト: awcrosby/ansible-lint
def parse_yaml_from_file(filepath: str) -> AnsibleBaseYAMLObject:
    dl = DataLoader()
    if hasattr(dl, 'set_vault_password'):
        dl.set_vault_password(DEFAULT_VAULT_PASSWORD)
    return dl.load_from_file(filepath)
コード例 #30
0
ファイル: runner.py プロジェクト: heyilin416/OMServer
class Runner(object):
    def __init__(self, groups, playbook, private_key_file, display, become_pass={}, extraVars={}):
        self.extraVars = extraVars

        self.options = Options()
        self.options.private_key_file = private_key_file
        self.options.verbosity = display.verbosity
        self.options.connection = 'ssh'  # Need a connection type 'smart' or 'ssh'
        self.options.become = True
        self.options.become_method = 'sudo'
        self.options.become_user = '******'

        # Executor appears to have it's own
        # verbosity object/setting as well
        playbook_executor.verbosity = self.options.verbosity

        # Become Pass Needed if not logging in as user root
        passwords = {'become_pass':become_pass}

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        self.loader.set_vault_password(os.environ.get('VAULT_PASS', 'xiaoy_pandan'))

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars = self.extraVars

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

        # Set groups info
        for info in groups:
            group = Group(info['name'])
            self.inventory.add_group(group)

            hostInfos = info.get('hosts')
            for hostInfo in hostInfos:
                hostname = hostInfo.get('hostname')
                hostip = hostInfo.get('ip', hostname)
                hostport = hostInfo.get('port')
                username = hostInfo.get('username')
                password = hostInfo.get('password')
                ssh_key = hostInfo.get('ssh_key')
                host = Host(name=hostname, port=hostport)
                host.set_variable('ansible_ssh_host', hostip)
                host.set_variable('ansible_ssh_port', hostport)
                host.set_variable('ansible_ssh_user', username)
                host.set_variable('ansible_ssh_pass', password)
                host.set_variable('ansible_ssh_private_key_file', ssh_key)
                for key, value in hostInfo.iteritems():
                    if key not in ['hostname', 'port', 'username', 'password', 'ssh_key']:
                        host.set_variable(key, value)
                group.add_host(host)

            varInfos = info.get('vars')
            if varInfos:
                for key, value in varInfos.iteritems():
                    group.set_variable(key, value)

        # Playbook to run. Assumes it is
        # local to this python file
        pb_dir = os.path.dirname(__file__)
        playbook = '%s/%s' % (pb_dir, playbook)

        # 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)
        self.display = display
        self.callback = CallbackModule(self.display)
        self.pbex._tqm._stdout_callback = self.callback

    def run(self):
        # Results of PlaybookExecutor
        self.pbex.run()

        # calc result
        result = True
        hostResults = {}
        stats = self.pbex._tqm._stats
        hosts = sorted(stats.processed.keys())
        for h in hosts:
            t = stats.summarize(h)
            if t['unreachable'] > 0 or t['failures'] > 0:
                hostResult = result = False
            else:
                hostResult = True
            hostResults[h] = hostResult

        if result:
            self.display.display('success')
        else:
            self.display.display('fail', stderr=True)
        self.display.display('')

        return result, hostResults
コード例 #31
0
ファイル: ansible_runner.py プロジェクト: vpramo/xos-1
class Runner(object):

    def __init__(self, playbook, run_data, private_key_file=None, verbosity=0, host_file=None):

        self.playbook = playbook
        self.run_data = run_data

        self.options = Options()
        self.options.output_file = playbook + '.result'
        self.options.private_key_file = private_key_file
        self.options.verbosity = verbosity
        self.options.connection = 'ssh'  # Need a connection type "smart" or "ssh"
        #self.options.become = True
        self.options.become_method = 'sudo'
        self.options.become_user = '******'

        # Set global verbosity
        self.display = Display()
        self.display.verbosity = self.options.verbosity
        # Executor appears to have it's own
        # verbosity object/setting as well
        playbook_executor.verbosity = self.options.verbosity

        # Become Pass Needed if not logging in as user root
        #passwords = {'become_pass': become_pass}

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        try:
            self.loader.set_vault_password(os.environ['VAULT_PASS'])
        except KeyError:
            pass

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars = {} # self.run_data

        # Set inventory, using most of above objects
        if (host_file):
            self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list = host_file)
        else:
            self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager)

        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={})

    def run(self):
        os.environ['REQUESTS_CA_BUNDLE'] = '/usr/local/share/ca-certificates/local_certs.crt'
        callback = ResultCallback()
        self.pbex._tqm._stdout_callback = callback

        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

        #os.remove(self.hosts.name)

        return stats,callback.results
コード例 #32
0
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
コード例 #33
0
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
コード例 #34
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
コード例 #35
0
ファイル: console.py プロジェクト: weipingding/ansible
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()
コード例 #36
0
class Runner(object):

    def __init__(self, 
                 hosts=None, 
                 playbook=None, 
                 remote_user='******',
                 private_key_file='~/.ssh/id_rsa',
                 become_pass='', 
                 verbosity=0, 
                 extra_vars={}):
        """
        Arguments:
            hosts:- The hosts. See the docstring of InventoryWrapper.__init__
                    for more details on the acceptable formats.
            playbook:- is the path to the playbook file
            become_pass:- seems like the password
                   for priviledge escalation 

        """
        if not hosts or not playbook:
            raise ValueError("hosts and playbook arguments must be defined")

        self.run_data = extra_vars

        self.options = Options()
        self.options.private_key_file = os.path.expanduser(private_key_file)
        self.options.verbosity = verbosity
        self.options.connection = 'ssh'  # Need a connection type "smart" or "ssh"
        self.options.become = True
        self.options.become_method = 'sudo'
        self.options.become_user = '******'
        self.options.remote_user = remote_user

        # Set global verbosity
        self.display = Display()
        self.display.verbosity = self.options.verbosity
        # Executor appears to have it's own
        # verbosity object/setting as well
        playbook_executor.verbosity = self.options.verbosity

        # Become Pass Needed if not logging in as user root
        passwords = {'become_pass': become_pass}

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        self.loader.set_vault_password(os.environ['VAULT_PASS'])

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars = self.run_data

        # Parse hosts, I haven't found a good way to
        # pass hosts in without using a parsed template :(
        # (Maybe you know how?)
        self.hosts = NamedTemporaryFile(delete=False, dir=os.getcwd())
        self.inventory_wrapper = InventoryWrapper(hosts)
        self.hosts.write(str(self.inventory_wrapper))
        self.hosts.close()

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

        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):
        # Results of PlaybookExecutor
        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
        #FIXME: get rid of the following, since this is not being used
        self.pbex._tqm.send_callback(
            'record_logs',
            user_id=None, #self.run_data['user_id'],
            success=run_success
        )

        # Remove created temporary files
        os.remove(self.hosts.name)

        return stats
コード例 #37
0
class SimpleProvider(object):
    __metaclass__ = ABCMeta

    def __init__(self, name, general_type=None, box_extra_type=None):
        self.env = Environment(name, general_type, box_extra_type)
        self.loader = DataLoader()
        self.provisioned = False
        self.tags = {}
        self.extra_vars = {'prudentia_dir': io.prudentia_python_dir()}
        self.load_tags()
        self.active_user = pwd.getpwuid(os.geteuid())[0]

    def boxes(self):
        return self.env.boxes.values()

    def get_box(self, box_name):
        b = self.env.get(box_name)
        if not b:
            print ('The box \'%s\' you entered does not exists.\n\n' \
                  'After typing the command press Tab for box suggestions.\n' % box_name)
            return None
        else:
            return b

    def _show_current_vars(self):
        print('Current set variables:\n%s\n' % '\n'.join(
            [n + ' -> ' + str(v) for n, v in self.extra_vars.iteritems()]))

    def set_var(self, var, value):
        if var in self.extra_vars:
            print ('NOTICE: Variable \'{0}\' is already set to this value: \'{1}\' ' \
                  'and it will be overwritten.'.format(var, self.extra_vars[var]))
        self.extra_vars[var] = value
        if provisioning.VERBOSITY > 0:
            print("Set \'{0}\' -> {1}\n".format(var, value))

    def unset_var(self, var):
        if not var:
            print('Please provide a valid variable name to unset.\n')
            self._show_current_vars()
        elif var not in self.extra_vars:
            print(
                'WARNING: Variable \'{0}\' is NOT present so cannot be unset.\n'
                .format(var))
            self._show_current_vars()
        else:
            self.extra_vars.pop(var, None)
            print("Unset \'{0}\'\n".format(var))

    def set_vault_password(self):
        vault_pwd = io.input_value('Ansible vault password', hidden=True)
        try:
            # Ansible 2.4
            self.loader.set_vault_secrets(vault_pwd)
        except:
            # Ansible 2.3
            self.loader.set_vault_password(vault_pwd)

    def load_vars(self, vars_file):
        if not vars_file:
            vars_file = io.input_path('path of the variables file')
        vars_dict = self.loader.load_from_file(vars_file)
        for key, value in vars_dict.items():
            self.set_var(key, value)

    def add_box(self, box):
        self.env.add(box)
        self.load_tags(box)

    def load_tags(self, box=None):
        for b in [box] if box else self.boxes():
            if not os.path.exists(b.playbook):
                print ('WARNING: Box \'{0}\' points to a NON existing playbook. ' \
                      'Please `reconfigure` or `unregister` the box.\n'.format(b.name))
            else:
                plays = Playbook.load(
                    b.playbook,
                    variable_manager=provisioning.get_variable_manager(
                        self.loader),
                    loader=self.loader).get_plays()
                all_tags = set()
                for p in plays:
                    for block in p.compile():
                        for task in block.block:
                            all_tags.update(task.tags)
                self.tags[b.name] = list(all_tags)

    def remove_box(self, box):
        if box.name in self.tags:
            self.tags.pop(box.name)
        return self.env.remove(box)

    def register(self):
        try:
            box = self.define_box()
            if box:
                self.add_box(box)
                print("\nBox %s added." % box)
        except Exception as ex:
            io.track_error('cannot add box', ex)

    @abstractmethod
    def define_box(self):
        pass

    def reconfigure(self, previous_box):
        try:
            box = self.redefine_box(previous_box)
            if box:
                self.remove_box(previous_box)
                self.add_box(box)
                print("\nBox %s reconfigured." % box)
        except Exception as ex:
            io.track_error('cannot reconfigure box', ex)

    @abstractmethod
    def redefine_box(self, previous_box):
        pass

    def unregister(self, box):
        self.remove_box(box)
        print("\nBox %s removed.\n" % box.name)

    def fetch_box_hosts(self, playbook):
        ds = self.loader.load_from_file(playbook)
        if ds:
            return ds[0][
                'hosts']  # a playbook is an array of plays we take the first one

    def suggest_name(self, hostname):
        if hostname not in self.env.boxes:
            return hostname
        else:
            return hostname + '-' + str(random.randint(0, 100))

    def provision(self, box, tags):
        self.provisioned = provisioning.run_playbook(
            playbook_file=box.playbook,
            inventory_file=provisioning.generate_inventory(box),
            loader=self.loader,
            remote_user=box.get_remote_user(),
            remote_pass=box.get_remote_pwd(),
            transport=box.get_transport(),
            extra_vars=self.extra_vars,
            only_tags=tags)

    @staticmethod
    def verbose(value):
        if value:
            try:
                iv = int(value)
            except ValueError:
                iv = -1
            if 0 <= iv <= 4:
                provisioning.VERBOSITY = iv
            else:
                print(
                    'Verbosity value \'{0}\' not allowed, should be a number between 0 and 4.'
                    .format(value))
        else:
            print('Current verbosity: {0}'.format(provisioning.VERBOSITY))

    def facts(self, box, regex='*'):
        return provisioning.gather_facts(box, regex, self.loader)
コード例 #38
0
ファイル: utils.py プロジェクト: willthames/ansible-lint
 def parse_yaml_from_file(filepath):
     dl = DataLoader()
     if hasattr(dl, 'set_vault_password'):
         dl.set_vault_password(DEFAULT_VAULT_PASSWORD)
     return dl.load_from_file(filepath)
コード例 #39
0
ファイル: utils.py プロジェクト: shivasps/ansible-lint
def parse_yaml_from_file(filepath):
    dl = DataLoader()
    if hasattr(dl, 'set_vault_password'):
        dl.set_vault_password(DEFAULT_VAULT_PASSWORD)
    return dl.load_from_file(filepath)
コード例 #40
0
ファイル: ansible_runner.py プロジェクト: ttofigh/xos
class Runner(object):
    def __init__(self,
                 playbook,
                 run_data,
                 private_key_file=None,
                 verbosity=0,
                 host_file=None):

        self.playbook = playbook
        self.run_data = run_data

        self.options = Options()
        self.options.output_file = playbook + '.result'
        self.options.private_key_file = private_key_file
        self.options.verbosity = verbosity
        self.options.connection = 'ssh'  # Need a connection type "smart" or "ssh"
        #self.options.become = True
        self.options.become_method = 'sudo'
        self.options.become_user = '******'

        # Set global verbosity
        self.display = Display()
        self.display.verbosity = self.options.verbosity
        # Executor appears to have it's own
        # verbosity object/setting as well
        playbook_executor.verbosity = self.options.verbosity

        # Become Pass Needed if not logging in as user root
        #passwords = {'become_pass': become_pass}

        # Gets data from YAML/JSON files
        self.loader = DataLoader()
        try:
            self.loader.set_vault_password(os.environ['VAULT_PASS'])
        except KeyError:
            pass

        # All the variables from all the various places
        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars = {}  # self.run_data

        # Set inventory, using most of above objects
        if (host_file):
            self.inventory = Inventory(loader=self.loader,
                                       variable_manager=self.variable_manager,
                                       host_list=host_file)
        else:
            self.inventory = Inventory(loader=self.loader,
                                       variable_manager=self.variable_manager)

        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={})

    def run(self):
        os.environ[
            'REQUESTS_CA_BUNDLE'] = '/usr/local/share/ca-certificates/local_certs.crt'
        callback = ResultCallback()
        self.pbex._tqm._stdout_callback = callback

        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

        #os.remove(self.hosts.name)

        return stats, callback.results
コード例 #41
0
ファイル: inventory.py プロジェクト: ernstp/ansible
class InventoryCLI(CLI):
    ''' used to display or dump the configured inventory as Ansible sees it '''

    ARGUMENTS = {'host': 'The name of a host to match in the inventory, relevant when using --list',
                 'group': 'The name of a group in the inventory, relevant when using --graph', }

    def __init__(self, args):

        super(InventoryCLI, self).__init__(args)
        self.vm = None
        self.loader = None
        self.inventory = None

        self._new_api = True

    def parse(self):

        self.parser = CLI.base_parser(
            usage='usage: %prog [options] [host|group]',
            epilog='Show Ansible inventory information, by default it uses the inventory script JSON format',
            inventory_opts=True,
            vault_opts=True
        )

        # Actions
        action_group = optparse.OptionGroup(self.parser, "Actions", "One of following must be used on invocation, ONLY ONE!")
        action_group.add_option("--list", action="store_true", default=False, dest='list', help='Output all hosts info, works as inventory script')
        action_group.add_option("--host", action="store", default=None, dest='host', help='Output specific host info, works as inventory script')
        action_group.add_option("--graph", action="store_true", default=False, dest='graph',
                                help='create inventory graph, if supplying pattern it must be a valid group name')
        self.parser.add_option_group(action_group)

        # Options
        self.parser.add_option("-y", "--yaml", action="store_true", default=False, dest='yaml',
                               help='Use YAML format instead of default JSON, ignored for --graph')
        self.parser.add_option("--vars", action="store_true", default=False, dest='show_vars',
                               help='Add vars to graph display, ignored unless used with --graph')

        super(InventoryCLI, self).parse()

        display.verbosity = self.options.verbosity

        self.validate_conflicts(vault_opts=True)

        # there can be only one! and, at least, one!
        used = 0
        for opt in (self.options.list, self.options.host, self.options.graph):
            if opt:
                used += 1
        if used == 0:
            raise AnsibleOptionsError("No action selected, at least one of --host, --graph or --list needs to be specified.")
        elif used > 1:
            raise AnsibleOptionsError("Conflicting options used, only one of --host, --graph or --list can be used at the same time.")

        # set host pattern to default if not supplied
        if len(self.args) > 0:
            self.options.pattern = self.args[0]
        else:
            self.options.pattern = 'all'

    def run(self):

        results = None

        super(InventoryCLI, self).run()

        # Initialize needed objects
        if getattr(self, '_play_prereqs', False):
            self.loader, self.inventory, self.vm = self._play_prereqs(self.options)
        else:
            # fallback to pre 2.4 way of initialzing
            from ansible.vars import VariableManager
            from ansible.inventory import Inventory

            self._new_api = False
            self.loader = DataLoader()
            self.vm = VariableManager()

            # use vault if needed
            if self.options.vault_password_file:
                vault_pass = CLI.read_vault_password_file(self.options.vault_password_file, loader=self.loader)
            elif self.options.ask_vault_pass:
                vault_pass = self.ask_vault_passwords()
            else:
                vault_pass = None

            if vault_pass:
                self.loader.set_vault_password(vault_pass)
                # actually get inventory and vars

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

        if self.options.host:
            hosts = self.inventory.get_hosts(self.options.host)
            if len(hosts) != 1:
                raise AnsibleOptionsError("You must pass a single valid host to --hosts parameter")

            myvars = self._get_host_variables(host=hosts[0])
            self._remove_internal(myvars)

            # FIXME: should we template first?
            results = self.dump(myvars)

        elif self.options.graph:
            results = self.inventory_graph()
        elif self.options.list:
            top = self._get_group('all')
            if self.options.yaml:
                results = self.yaml_inventory(top)
            else:
                results = self.json_inventory(top)
            results = self.dump(results)

        if results:
            # FIXME: pager?
            display.display(results)
            exit(0)

        exit(1)

    def dump(self, stuff):

        if self.options.yaml:
            import yaml
            from ansible.parsing.yaml.dumper import AnsibleDumper
            results = yaml.dump(stuff, Dumper=AnsibleDumper, default_flow_style=False)
        else:
            import json
            results = json.dumps(stuff, sort_keys=True, indent=4)

        return results

    def _get_host_variables(self, host):
        if self._new_api:
            hostvars = self.vm.get_vars(host=host)
        else:
            hostvars = self.vm.get_vars(self.loader, host=host)
        return hostvars

    def _get_group(self, gname):
        if self._new_api:
            group = self.inventory.groups.get(gname)
        else:
            group = self.inventory.get_group(gname)
        return group

    def _remove_internal(self, dump):

        for internal in INTERNAL_VARS:
            if internal in dump:
                del dump[internal]

    def _remove_empty(self, dump):
        # remove empty keys
        for x in ('hosts', 'vars', 'children'):
            if x in dump and not dump[x]:
                del dump[x]

    def _show_vars(self, dump, depth):
        result = []
        self._remove_internal(dump)
        if self.options.show_vars:
            for (name, val) in sorted(dump.items()):
                result.append(self._graph_name('{%s = %s}' % (name, val), depth + 1))
        return result

    def _graph_name(self, name, depth=0):
        if depth:
            name = "  |" * (depth) + "--%s" % name
        return name

    def _graph_group(self, group, depth=0):

        result = [self._graph_name('@%s:' % group.name, depth)]
        depth = depth + 1
        for kid in sorted(group.child_groups, key=attrgetter('name')):
            result.extend(self._graph_group(kid, depth))

        if group.name != 'all':
            for host in sorted(group.hosts, key=attrgetter('name')):
                result.append(self._graph_name(host.name, depth))
                result.extend(self._show_vars(host.get_vars(), depth))

        result.extend(self._show_vars(group.get_vars(), depth))

        return result

    def inventory_graph(self):

        start_at = self._get_group(self.options.pattern)
        if start_at:
            return '\n'.join(self._graph_group(start_at))
        else:
            raise AnsibleOptionsError("Pattern must be valid group name when using --graph")

    def json_inventory(self, top):

        def format_group(group):
            results = {}
            results[group.name] = {}
            if group.name != 'all':
                results[group.name]['hosts'] = [h.name for h in sorted(group.hosts, key=attrgetter('name'))]
            results[group.name]['vars'] = group.get_vars()
            results[group.name]['children'] = []
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                results[group.name]['children'].append(subgroup.name)
                results.update(format_group(subgroup))

            self._remove_empty(results[group.name])
            return results

        results = format_group(top)

        # populate meta
        results['_meta'] = {'hostvars': {}}
        hosts = self.inventory.get_hosts()
        for host in hosts:
            results['_meta']['hostvars'][host.name] = self._get_host_variables(host=host)
            self._remove_internal(results['_meta']['hostvars'][host.name])

        return results

    def yaml_inventory(self, top):

        seen = []

        def format_group(group):
            results = {}

            # initialize group + vars
            results[group.name] = {}
            results[group.name]['vars'] = group.get_vars()

            # subgroups
            results[group.name]['children'] = {}
            for subgroup in sorted(group.child_groups, key=attrgetter('name')):
                if subgroup.name != 'all':
                    results[group.name]['children'].update(format_group(subgroup))

            # hosts for group
            results[group.name]['hosts'] = {}
            if group.name != 'all':
                for h in sorted(group.hosts, key=attrgetter('name')):
                    myvars = {}
                    if h.name not in seen:  # avoid defining host vars more than once
                        seen.append(h.name)
                        myvars = self._get_host_variables(host=h)
                        self._remove_internal(myvars)
                    results[group.name]['hosts'][h.name] = myvars

            self._remove_empty(results[group.name])
            return results

        return format_group(top)
コード例 #42
0
ファイル: playbook.py プロジェクト: KMK-ONLINE/ansible
    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
コード例 #43
0
ファイル: playbook.py プロジェクト: yangbo7907/ansible
    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 = {}

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

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

        # 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
コード例 #44
0
ファイル: __init__.py プロジェクト: zishuang951/lykops
class Base():
    def __init__(self,
                 exec_mode,
                 work_name,
                 username,
                 options_dict,
                 describe,
                 mongoclient=None):
        '''
        ansible的基类,为adhoc、playbook等父类
        :parm:
            exec_mode:ansible工作类型,接受adhoc、palybook等
            work_name:该任务的名称,用于日志
            username:执行者
            options_dict:该任务的特定设置
            mongoclient:初始化mongo连接类
        '''

        self.logger = logging.getLogger("ansible")
        if exec_mode in ('adhoc', 'playbook'):
            self.exec_mode = exec_mode
        else:
            self.logger.warn(
                '正在准备执行ansible任务,准备工作失败,原因:参数exec_mode必须是adhoc或者是playbook')
            return (False, '参数exec_mode必须是adhoc或者是playbook')

        if isinstance(work_name, str) and work_name:
            self.work_name = work_name
        else:
            self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数work_name必须是非字符串')
            return (False, '参数work_name必须是非字符串')

        if isinstance(username, str) and username:
            self.username = username
        else:
            self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数username必须是非字符串')
            return (False, '参数username必须是非字符串')

        if isinstance(options_dict, dict) and options_dict:
            self.options_dict = options_dict
        else:
            self.logger.warn('正在准备执行ansible任务,准备工作失败,原因:参数options_dict必须是非空字典')
            return (False, '参数options_dict必须是非空字典')

        if mongoclient is None:
            self.mongoclient = Op_Mongo()
        else:
            self.mongoclient = mongoclient

        self.work_uuid = str(uuid.uuid4())
        self.log_router = Routing_Logging()
        self.describe = describe

        if exec_mode == 'adhoc':
            self.log_prefix = '正在执行用户' + username + '的名为' + work_name + 'uuid为' + self.work_uuid + '的ansible临时任务,'
        else:
            self.log_prefix = '正在执行用户' + username + '的名为' + work_name + 'uuid为' + self.work_uuid + '的ansible-playbook任务,'

        # 下面是加载和初始化相关类
        self._parse_options()
        self.passwords = {
            'conn_pass': self.options.ask_pass,
            'become_pass': self.options.become_ask_pass
        }
        # 设置passwords
        self.inventory_file = self.options_dict.get('inventory', '')

        self.loader = DataLoader()
        self._get_vault_pwd()
        self.variable_manager = VariableManager()
        self.variable_manager.extra_vars = load_extra_vars(
            loader=self.loader, options=self.options)
        self.variable_manager.options_vars = load_options_vars(self.options)

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

    def _get_vault_pwd(self):
        '''
        获取vault密码,并初始化vault密码
        '''

        vault_pwd_file = self.options_dict.get('vault_password_file', False)
        ask_vault_pass = self.options_dict.get('ask_vault_pass', False)

        if ask_vault_pass:
            vault_password = ask_vault_pass
        else:
            if vault_pwd_file:
                this_path = os.path.realpath(
                    os.path.expanduser(vault_pwd_file))
                if os.path.exists(this_path):
                    mode = self.loader.is_executable(this_path)
                    result = read_file(this_path,
                                       mode=mode,
                                       sprfmt=b'\r\n',
                                       outfmt='bytes')
                    if result[0]:
                        vault_password = result[1]
                    else:
                        vault_password = None
                else:
                    vault_password = None
            else:
                vault_password = None

        if vault_password:
            b_vault_password = string2bytes(vault_password)
            self.loader.set_vault_password(b_vault_password)
            self.vault_password = vault_password
        else:
            self.vault_password = None

    def _parse_options(self):
        '''
        获取options字典
        '''

        keys_list = []
        values_list = []
        for key, value in self.options_dict.items():
            keys_list.append(key)
            values_list.append(value)

        Options = namedtuple('Options', keys_list)
        self.options = Options._make(values_list)

    def _show_protectfield(self):
        protectfield_list = [
            'ask_pass',
            'ask_su_pass',
            'ask_sudo_pass',
            'ask_vault_pass',
            'become_ask_pass',
            'new_vault_password_file',
            'vault_password_file',
            'private_key_file',
        ]

        log_options = {}
        for field in self.options_dict:
            if field in protectfield_list:
                log_options[field] = '***hidden***'
            else:
                log_options[field] = self.options_dict[field]

        return log_options