示例#1
0
class TestConfigData(unittest.TestCase):
    def setUp(self):
        self.manager = ConfigManager(os.path.join(curdir, 'test.cfg'),
                                     os.path.join(curdir, 'test.yml'))

    def tearDown(self):
        self.manager = None

    def test_initial_load(self):
        self.assertEquals(self.manager.data._global_settings, expected_ini)

    def test_value_and_origin_from_ini(self):
        self.assertEquals(
            self.manager.get_config_value_and_origin('config_entry'),
            ('fromini', cfg_file))

    def test_value_from_ini(self):
        self.assertEquals(self.manager.get_config_value('config_entry'),
                          'fromini')

    def test_value_and_origin_from_alt_ini(self):
        self.assertEquals(
            self.manager.get_config_value_and_origin('config_entry',
                                                     cfile=cfg_file2),
            ('fromini2', cfg_file2))

    def test_value_from_alt_ini(self):
        self.assertEquals(
            self.manager.get_config_value('config_entry', cfile=cfg_file2),
            'fromini2')
示例#2
0
    def run(self):

        super(ConfigCLI, self).run()

        if context.CLIARGS['config_file']:
            self.config_file = unfrackpath(context.CLIARGS['config_file'], follow=False)
            b_config = to_bytes(self.config_file)
            if os.path.exists(b_config) and os.access(b_config, os.R_OK):
                self.config = ConfigManager(self.config_file)
            else:
                raise AnsibleOptionsError('The provided configuration file is missing or not accessible: %s' % to_native(self.config_file))
        else:
            self.config = ConfigManager()
            self.config_file = find_ini_config_file()

        if self.config_file:
            try:
                if not os.path.exists(self.config_file):
                    raise AnsibleOptionsError("%s does not exist or is not accessible" % (self.config_file))
                elif not os.path.isfile(self.config_file):
                    raise AnsibleOptionsError("%s is not a valid file" % (self.config_file))

                os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
            except Exception:
                if context.CLIARGS['action'] in ['view']:
                    raise
                elif context.CLIARGS['action'] in ['edit', 'update']:
                    display.warning("File does not exist, used empty file: %s" % self.config_file)

        elif context.CLIARGS['action'] == 'view':
            raise AnsibleError('Invalid or no config file was supplied')

        context.CLIARGS['func']()
示例#3
0
文件: config.py 项目: zship/ansible
    def run(self):

        super(ConfigCLI, self).run()

        if context.CLIARGS['config_file']:
            self.config_file = unfrackpath(context.CLIARGS['config_file'], follow=False)
            self.config = ConfigManager(self.config_file)
        else:
            self.config = ConfigManager()
            self.config_file = find_ini_config_file()

        if self.config_file:
            try:
                if not os.path.exists(self.config_file):
                    raise AnsibleOptionsError("%s does not exist or is not accessible" % (self.config_file))
                elif not os.path.isfile(self.config_file):
                    raise AnsibleOptionsError("%s is not a valid file" % (self.config_file))

                os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
            except Exception:
                if self.action in ['view']:
                    raise
                elif self.action in ['edit', 'update']:
                    display.warning("File does not exist, used empty file: %s" % self.config_file)

        elif self.action == 'view':
            raise AnsibleError('Invalid or no config file was supplied')

        self.execute()
示例#4
0
    def run(self):

        super(ConfigCLI, self).run()

        if self.options.config_file:
            self.config_file = unfrackpath(self.options.config_file, follow=False)
            self.config = ConfigManager(self.config_file)
        else:
            self.config = ConfigManager()
            self.config_file = find_ini_config_file()

        if self.config_file:
            try:
                if not os.path.exists(self.config_file):
                    raise AnsibleOptionsError("%s does not exist or is not accessible" % (self.config_file))
                elif not os.path.isfile(self.config_file):
                    raise AnsibleOptionsError("%s is not a valid file" % (self.config_file))

                os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
            except:
                if self.action in ['view']:
                    raise
                elif self.action in ['edit', 'update']:
                    display.warning("File does not exist, used empty file: %s" % self.config_file)

        elif self.action == 'view':
            raise AnsibleError('Invalid or no config file was supplied')

        self.execute()
示例#5
0
    def run(self):

        super(ConfigCLI, self).run()

        if self.options.config_file:
            self.config_file = unfrackpath(self.options.config_file,
                                           follow=False)
            self.config = ConfigManager(self.config_file)
        else:
            self.config = ConfigManager()
            self.config_file = self.config.data.get_setting('ANSIBLE_CONFIG')
            try:
                if not os.path.exists(self.config_file):
                    raise AnsibleOptionsError(
                        "%s does not exist or is not accessible" %
                        (self.config_file))
                elif not os.path.isfile(self.config_file):
                    raise AnsibleOptionsError("%s is not a valid file" %
                                              (self.config_file))

                os.environ['ANSIBLE_CONFIG'] = self.config_file
            except:
                if self.action in ['view']:
                    raise
                elif self.action in ['edit', 'update']:
                    display.warning(
                        "File does not exist, used empty file: %s" %
                        self.config_file)

        self.execute()
def main():
    config_manager = ConfigManager()
    username = config_manager.data.get_setting('vault.username')
    if not username:
        username = getpass.getuser()

    keyname = config_manager.data.get_setting('vault.keyname')
    if not keyname:
        keyname = 'ansible'

    arg_parser = build_arg_parser()
    args = arg_parser.parse_args()

    username = args.username or username
    keyname = args.vault_id or keyname

    # lookup the file
    if os.path.exists('environments/local/vault-password'):
        with open('environments/local/vault-password', 'r') as stream:
            sys.stdout.write('%s\n' % stream.readline())
            sys.exit(0)
    else:
        # provide fake password
        sys.stdout.write('%s\n' % 'nevairbe')
        sys.exit(0)

    sys.exit(0)
def main():
    config = ConfigManager()
    username = get_ini_config_value(
        config._parsers[config._config_file],
        dict(section='vault', key='username')
    ) or getpass.getuser()

    keyname = get_ini_config_value(
        config._parsers[config._config_file],
        dict(section='vault', key='keyname')
    ) or 'ansible'

    if len(sys.argv) == 2 and sys.argv[1] == 'set':
        intro = 'Storing password in "{}" user keyring using key name: {}\n'
        sys.stdout.write(intro.format(username, keyname))
        password = getpass.getpass()
        confirm = getpass.getpass('Confirm password: '******'Passwords do not match\n')
            sys.exit(1)
    else:
        sys.stdout.write('{0}\n'.format(keyring.get_password(keyname,
                                                             username)))

    sys.exit(0)
示例#8
0
    def __init__(self):
        initial_dir = os.getcwd()
        ansible_basedir = os.path.join(
            os.environ.get("PROJECT_ENVIRONMENT_FILES_PATH"), "ansible")

        # Move to project directory
        os.chdir(os.environ.get("PROJECT_ENVIRONMENT_FILES_PATH"))

        # Load list of inventories from config:w
        config = ConfigManager('/etc/ansible/ansible.cfg')
        sources = config.data.get_setting('DEFAULT_HOST_LIST').value

        loader = CustomLoader()
        loader.set_basedir(ansible_basedir)

        # load the inventory, set the basic playbook directory
        self._inventory = CustomInventoryManager(loader=loader,
                                                 sources=sources)
        var_manager = VariableManager(loader=loader, inventory=self._inventory)
        play = Play.load(dict(hosts=['all']),
                         loader=loader,
                         variable_manager=var_manager)

        # Move back to directory of origin
        os.chdir(initial_dir)

        control_host = None
        if 'control' in self._inventory.groups:
            control_group = self._inventory.groups['control']

            if len(control_group.get_hosts()) > 0:
                control_host = control_group.get_hosts()[0]

        # Hostvars
        hostvars = {}
        for host in self._inventory.get_hosts():
            hostvars[host.name] = host.vars

        # make sure we load all magic variables on top of the global variables
        self._vars = combine_vars(
            var_manager.get_vars(play=play, task=Task(), host=control_host), {
                'hostvars': hostvars,
                'env': os.environ
            })

        # create the template renderer
        self._templar = Templar(loader=loader, variables=self._vars)

        # setup some easy variables that we use a lot
        self._vars['control_ip'] = self.get_var(
            "hostvars[groups['control'][0]]['ansible_host']")
        self._vars['edge_ip'] = self.get_var(
            "hostvars[groups['edge'][0]]['ansible_host']")
        self._vars['monitor_ip'] = self.get_var(
            "hostvars[groups['monitor'][0]]['ansible_host']")
示例#9
0
def main():
    config_manager = ConfigManager()
    username = config_manager.data.get_setting("vault.storedir")
    if not username:
        username = "******"

    keyprefix = config_manager.data.get_setting("vault.keyprefix")
    if not keyprefix:
        keyprefix = None

    keyname = config_manager.data.get_setting("vault.keyname")
    if not keyname:
        keyname = "dev"

    key = keyprefix + keyname if keyprefix else keyname

    arg_parser = build_arg_parser()
    args = arg_parser.parse_args()

    username = args.username or username
    keyname = args.vault_id or key

    print("username: %s keyname: %s" % (username, key))

    if args.set_password:
        # intro = 'Storing password in "{}" user keyring using key name: {}\n'
        # sys.stdout.write(intro.format(username, key))
        # password = getpass.getpass()
        # confirm = getpass.getpass("Confirm password: "******"Storing Passwords is not supported with 'pass'\n")
        sys.exit(1)
    else:
        qpass.DEFAULT_DIRECTORY = username
        s = qpass.PasswordStore()
        e = qpass.PasswordEntry(store=s, name=key)
        secret = e.text
        if secret is None:
            sys.stderr.write(
                'vault-keyring-client could not find key="%s" for user="******" via backend="%s"\n'
                % (keyname, username, s.repr()))
            sys.exit(KEYNAME_UNKNOWN_RC)

        # print('secret: %s' % secret)
        sys.stdout.write("%s\n" % secret)

    sys.exit(0)
示例#10
0
    def __init__(self, options=None):
        if not options:
            options = {}
        self.options = options

        self.loader = DataLoader()
        if "inventory_path" in self.options:
            sources = self.options["inventory_path"]
        else:
            sources = None

        self.inventory_manager = InventoryManager(self.loader, sources=sources)

        self.variable_manager = VariableManager(
            loader=self.loader, inventory=self.inventory_manager)

        # TODO load ansible configuration
        self.config_manager = ConfigManager()
示例#11
0
def main():
    config_manager = ConfigManager()
    username = config_manager.data.get_setting('vault.username')
    if not username:
        username = getpass.getuser()

    keyname = config_manager.data.get_setting('vault.keyname')
    if not keyname:
        keyname = 'ansible'

    arg_parser = build_arg_parser()
    args = arg_parser.parse_args()

    username = args.username or username
    keyname = args.vault_id or keyname

    # print('username: %s keyname: %s' % (username, keyname))

    if args.set_password:
        intro = 'Storing password in "{}" user keyring using key name: {}\n'
        sys.stdout.write(intro.format(username, keyname))
        password = getpass.getpass()
        confirm = getpass.getpass('Confirm password: '******'Passwords do not match\n')
            sys.exit(1)
    else:
        secret = keyring.get_password(keyname, username)
        if secret is None:
            sys.stderr.write(
                'vault-keyring-client could not find key="%s" for user="******" via backend="%s"\n'
                % (keyname, username, keyring.get_keyring().name))
            sys.exit(KEYNAME_UNKNOWN_RC)

        # print('secret: %s' % secret)
        sys.stdout.write('%s\n' % secret)

    sys.exit(0)
示例#12
0
    def get_default_config(self, key=None):
        """getting the default configuration defined by ansible.cfg
        (Uses default values if there is no ansible.cfg).

        :param key: get a value of a specific key of the ansible.cfg file
        :type key: str

        :return: key/values of the default ansible configuration or
                 a specifc value of the config
        :rtype: dict if key not defined or string if defined
        """
        returndict = {}
        acm = ConfigManager()
        a_settings = acm.data.get_settings()
        if key:
            for setting in a_settings:
                if setting.name == key:
                    return setting.value
            return None
        else:
            for setting in a_settings:
                if setting.name == "CONFIG_FILE":
                    self.logger.debug("Using %s for default configuration" %
                                      setting.value)
                elif setting.name == "DEFAULT_BECOME":
                    returndict["become"] = setting.value
                elif setting.name == "DEFAULT_BECOME_METHOD":
                    returndict["become_method"] = setting.value
                elif setting.name == "DEFAULT_BECOME_USER":
                    returndict["become_user"] = setting.value
                elif setting.name == "DEFAULT_REMOTE_USER":
                    returndict["remote_user"] = setting.value
                elif setting.name == "DEFAULT_FORKS":
                    returndict["forks"] = setting.value
                elif setting.name == 'DEFAULT_TRANSPORT':
                    returndict["connection"] = setting.value
            return returndict
示例#13
0
文件: config.py 项目: zship/ansible
class ConfigCLI(CLI):
    """ Config command line class """

    VALID_ACTIONS = frozenset(("view", "dump", "list"))  # TODO: edit, update, search

    def __init__(self, args, callback=None):

        self.config_file = None
        self.config = None
        super(ConfigCLI, self).__init__(args, callback)

    def init_parser(self):

        super(ConfigCLI, self).init_parser(
            usage="usage: %%prog [%s] [--help] [options] [ansible.cfg]" % "|".join(sorted(self.VALID_ACTIONS)),
            epilog="\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0]),
            desc="View, edit, and manage ansible configuration.",
        )
        self.parser.add_option('-c', '--config', dest='config_file',
                               help="path to configuration file, defaults to first file found in precedence.")

        self.set_action()

        # options specific to self.actions
        if self.action == "list":
            self.parser.set_usage("usage: %prog list [options] ")

        elif self.action == "dump":
            self.parser.add_option('--only-changed', dest='only_changed', action='store_true',
                                   help="Only show configurations that have changed from the default")

        elif self.action == "update":
            self.parser.add_option('-s', '--setting', dest='setting', help="config setting, the section defaults to 'defaults'")
            self.parser.set_usage("usage: %prog update [options] [-c ansible.cfg] -s '[section.]setting=value'")

        elif self.action == "search":
            self.parser.set_usage("usage: %prog update [options] [-c ansible.cfg] <search term>")

    def post_process_args(self, options, args):
        options, args = super(ConfigCLI, self).post_process_args(options, args)
        display.verbosity = options.verbosity

        return options, args

    def run(self):

        super(ConfigCLI, self).run()

        if context.CLIARGS['config_file']:
            self.config_file = unfrackpath(context.CLIARGS['config_file'], follow=False)
            self.config = ConfigManager(self.config_file)
        else:
            self.config = ConfigManager()
            self.config_file = find_ini_config_file()

        if self.config_file:
            try:
                if not os.path.exists(self.config_file):
                    raise AnsibleOptionsError("%s does not exist or is not accessible" % (self.config_file))
                elif not os.path.isfile(self.config_file):
                    raise AnsibleOptionsError("%s is not a valid file" % (self.config_file))

                os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
            except Exception:
                if self.action in ['view']:
                    raise
                elif self.action in ['edit', 'update']:
                    display.warning("File does not exist, used empty file: %s" % self.config_file)

        elif self.action == 'view':
            raise AnsibleError('Invalid or no config file was supplied')

        self.execute()

    def execute_update(self):
        '''
        Updates a single setting in the specified ansible.cfg
        '''
        raise AnsibleError("Option not implemented yet")

        # pylint: disable=unreachable
        if context.CLIARGS['setting'] is None:
            raise AnsibleOptionsError("update option requires a setting to update")

        (entry, value) = context.CLIARGS['setting'].split('=')
        if '.' in entry:
            (section, option) = entry.split('.')
        else:
            section = 'defaults'
            option = entry
        subprocess.call([
            'ansible',
            '-m', 'ini_file',
            'localhost',
            '-c', 'local',
            '-a', '"dest=%s section=%s option=%s value=%s backup=yes"' % (self.config_file, section, option, value)
        ])

    def execute_view(self):
        '''
        Displays the current config file
        '''
        try:
            with open(self.config_file, 'rb') as f:
                self.pager(to_text(f.read(), errors='surrogate_or_strict'))
        except Exception as e:
            raise AnsibleError("Failed to open config file: %s" % to_native(e))

    def execute_edit(self):
        '''
        Opens ansible.cfg in the default EDITOR
        '''
        raise AnsibleError("Option not implemented yet")

        # pylint: disable=unreachable
        try:
            editor = shlex.split(os.environ.get('EDITOR', 'vi'))
            editor.append(self.config_file)
            subprocess.call(editor)
        except Exception as e:
            raise AnsibleError("Failed to open editor: %s" % to_native(e))

    def execute_list(self):
        '''
        list all current configs reading lib/constants.py and shows env and config file setting names
        '''
        self.pager(to_text(yaml.dump(self.config.get_configuration_definitions(), Dumper=AnsibleDumper), errors='surrogate_or_strict'))

    def execute_dump(self):
        '''
        Shows the current settings, merges ansible.cfg if specified
        '''
        # FIXME: deal with plugins, not just base config
        text = []
        defaults = self.config.get_configuration_definitions().copy()
        for setting in self.config.data.get_settings():
            if setting.name in defaults:
                defaults[setting.name] = setting

        for setting in sorted(defaults):
            if isinstance(defaults[setting], Setting):
                if defaults[setting].origin == 'default':
                    color = 'green'
                else:
                    color = 'yellow'
                msg = "%s(%s) = %s" % (setting, defaults[setting].origin, defaults[setting].value)
            else:
                color = 'green'
                msg = "%s(%s) = %s" % (setting, 'default', defaults[setting].get('default'))
            if not context.CLIARGS['only_changed'] or color == 'yellow':
                text.append(stringc(msg, color))

        self.pager(to_text('\n'.join(text), errors='surrogate_or_strict'))
示例#14
0
class TestConfigData(unittest.TestCase):

    def setUp(self):
        self.manager = ConfigManager(cfg_file, os.path.join(curdir, 'test.yml'))

    def tearDown(self):
        self.manager = None

    def test_initial_load(self):
        self.assertEquals(self.manager.data._global_settings, expected_ini)

    def test_ensure_type_list(self):
        self.assertIsInstance(ensure_type('a,b', 'list'), list)
        self.assertIsInstance(ensure_type(['a', 'b'], 'list'), list)

    def test_ensure_type_bool(self):
        self.assertIsInstance(ensure_type('yes', 'bool'), bool)
        self.assertIsInstance(ensure_type(True, 'bool'), bool)

    def test_ensure_type_int(self):
        self.assertIsInstance(ensure_type('10', 'int'), int)
        self.assertIsInstance(ensure_type(20, 'int'), int)

    def test_ensure_type_float(self):
        self.assertIsInstance(ensure_type('0.10', 'float'), float)
        self.assertIsInstance(ensure_type(0.2, 'float'), float)

    def test_find_ini_file(self):
        cur_config = os.environ['ANSIBLE_CONFIG']
        os.environ['ANSIBLE_CONFIG'] = cfg_file
        self.assertEquals(cfg_file, find_ini_config_file())
        os.environ['ANSIBLE_CONFIG'] = cur_config

    def test_resolve_path(self):
        self.assertEquals(os.path.join(curdir, 'test.yml'), resolve_path('./test.yml', cfg_file))

    def test_resolve_path_cwd(self):
        self.assertEquals(os.path.join(os.getcwd(), 'test.yml'), resolve_path('{{CWD}}/test.yml'))
        self.assertEquals(os.path.join(os.getcwd(), 'test.yml'), resolve_path('./test.yml'))

    def test_get_config_dest(self):
        pass

    def test_value_and_origin_from_ini(self):
        self.assertEquals(self.manager.get_config_value_and_origin('config_entry'), ('fromini', cfg_file))

    def test_value_from_ini(self):
        self.assertEquals(self.manager.get_config_value('config_entry'), 'fromini')

    def test_value_and_origin_from_alt_ini(self):
        self.assertEquals(self.manager.get_config_value_and_origin('config_entry', cfile=cfg_file2), ('fromini2', cfg_file2))

    def test_value_from_alt_ini(self):
        self.assertEquals(self.manager.get_config_value('config_entry', cfile=cfg_file2), 'fromini2')

    def test_value_and_origin_from_yaml(self):
        pass

    def test_value_from_yaml(self):
        pass

    def test_value_and_origin_from_alt_yaml(self):
        pass

    def test_value_from_alt_yaml(self):
        pass

    def test_config_type_bool(self):
        pass

    def test_config_type_list(self):
        pass

    def test_config_default(self):
        pass

    def test_deprecated_config(self):
        pass

    def test_deprecated_config_source(self):
        pass

    def test_multi_precedence(self):
        pass

    def test_initialize_plugin_config(self):
        pass

    def test_update_config_data(self):
        pass
示例#15
0
class ConfigCLI(CLI):
    """ Config command line class """

    def __init__(self, args, callback=None):

        self.config_file = None
        self.config = None
        super(ConfigCLI, self).__init__(args, callback)

    def init_parser(self):

        super(ConfigCLI, self).init_parser(
            desc="View ansible configuration.",
        )

        common = opt_help.argparse.ArgumentParser(add_help=False)
        opt_help.add_verbosity_options(common)
        common.add_argument('-c', '--config', dest='config_file',
                            help="path to configuration file, defaults to first file found in precedence.")

        subparsers = self.parser.add_subparsers(dest='action')
        subparsers.required = True

        list_parser = subparsers.add_parser('list', help='Print all config options', parents=[common])
        list_parser.set_defaults(func=self.execute_list)

        dump_parser = subparsers.add_parser('dump', help='Dump configuration', parents=[common])
        dump_parser.set_defaults(func=self.execute_dump)
        dump_parser.add_argument('--only-changed', dest='only_changed', action='store_true',
                                 help="Only show configurations that have changed from the default")

        view_parser = subparsers.add_parser('view', help='View configuration file', parents=[common])
        view_parser.set_defaults(func=self.execute_view)

        # update_parser = subparsers.add_parser('update', help='Update configuration option')
        # update_parser.set_defaults(func=self.execute_update)
        # update_parser.add_argument('-s', '--setting', dest='setting',
        #                            help="config setting, the section defaults to 'defaults'",
        #                            metavar='[section.]setting=value')

        # search_parser = subparsers.add_parser('search', help='Search configuration')
        # search_parser.set_defaults(func=self.execute_search)
        # search_parser.add_argument('args', help='Search term', metavar='<search term>')

    def post_process_args(self, options):
        options = super(ConfigCLI, self).post_process_args(options)
        display.verbosity = options.verbosity

        return options

    def run(self):

        super(ConfigCLI, self).run()

        if context.CLIARGS['config_file']:
            self.config_file = unfrackpath(context.CLIARGS['config_file'], follow=False)
            b_config = to_bytes(self.config_file)
            if os.path.exists(b_config) and os.access(b_config, os.R_OK):
                self.config = ConfigManager(self.config_file)
            else:
                raise AnsibleOptionsError('The provided configuration file is missing or not accessible: %s' % to_native(self.config_file))
        else:
            self.config = ConfigManager()
            self.config_file = find_ini_config_file()

        if self.config_file:
            try:
                if not os.path.exists(self.config_file):
                    raise AnsibleOptionsError("%s does not exist or is not accessible" % (self.config_file))
                elif not os.path.isfile(self.config_file):
                    raise AnsibleOptionsError("%s is not a valid file" % (self.config_file))

                os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
            except Exception:
                if context.CLIARGS['action'] in ['view']:
                    raise
                elif context.CLIARGS['action'] in ['edit', 'update']:
                    display.warning("File does not exist, used empty file: %s" % self.config_file)

        elif context.CLIARGS['action'] == 'view':
            raise AnsibleError('Invalid or no config file was supplied')

        context.CLIARGS['func']()

    def execute_update(self):
        '''
        Updates a single setting in the specified ansible.cfg
        '''
        raise AnsibleError("Option not implemented yet")

        # pylint: disable=unreachable
        if context.CLIARGS['setting'] is None:
            raise AnsibleOptionsError("update option requires a setting to update")

        (entry, value) = context.CLIARGS['setting'].split('=')
        if '.' in entry:
            (section, option) = entry.split('.')
        else:
            section = 'defaults'
            option = entry
        subprocess.call([
            'ansible',
            '-m', 'ini_file',
            'localhost',
            '-c', 'local',
            '-a', '"dest=%s section=%s option=%s value=%s backup=yes"' % (self.config_file, section, option, value)
        ])

    def execute_view(self):
        '''
        Displays the current config file
        '''
        try:
            with open(self.config_file, 'rb') as f:
                self.pager(to_text(f.read(), errors='surrogate_or_strict'))
        except Exception as e:
            raise AnsibleError("Failed to open config file: %s" % to_native(e))

    def execute_edit(self):
        '''
        Opens ansible.cfg in the default EDITOR
        '''
        raise AnsibleError("Option not implemented yet")

        # pylint: disable=unreachable
        try:
            editor = shlex.split(os.environ.get('EDITOR', 'vi'))
            editor.append(self.config_file)
            subprocess.call(editor)
        except Exception as e:
            raise AnsibleError("Failed to open editor: %s" % to_native(e))

    def execute_list(self):
        '''
        list all current configs reading lib/constants.py and shows env and config file setting names
        '''
        self.pager(to_text(yaml.dump(self.config.get_configuration_definitions(ignore_private=True), Dumper=AnsibleDumper), errors='surrogate_or_strict'))

    def execute_dump(self):
        '''
        Shows the current settings, merges ansible.cfg if specified
        '''
        # FIXME: deal with plugins, not just base config
        text = []
        defaults = self.config.get_configuration_definitions(ignore_private=True).copy()
        for setting in self.config.data.get_settings():
            if setting.name in defaults:
                defaults[setting.name] = setting

        for setting in sorted(defaults):
            if isinstance(defaults[setting], Setting):
                if defaults[setting].origin == 'default':
                    color = 'green'
                else:
                    color = 'yellow'
                msg = "%s(%s) = %s" % (setting, defaults[setting].origin, defaults[setting].value)
            else:
                color = 'green'
                msg = "%s(%s) = %s" % (setting, 'default', defaults[setting].get('default'))
            if not context.CLIARGS['only_changed'] or color == 'yellow':
                text.append(stringc(msg, color))

        self.pager(to_text('\n'.join(text), errors='surrogate_or_strict'))
示例#16
0
 def setUp(self):
     self.manager = ConfigManager(os.path.join(curdir, 'test.cfg'),
                                  os.path.join(curdir, 'test.yml'))
示例#17
0
 def setUp(self):
     self.manager = ConfigManager(cfg_file, os.path.join(curdir, 'test.yml'))
示例#18
0
 def setup_class(cls):
     cls.manager = ConfigManager(cfg_file, os.path.join(curdir, 'test.yml'))
示例#19
0
import argparse
import base64
import getpass
import binascii
from ansible import errors
from ansible.config.manager import ConfigManager, get_ini_config_value
from cryptography.fernet import Fernet, InvalidToken
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

# Section in config file
CONFIG_SECTION = 'vault_filter'

# Read config values
config_manager = ConfigManager()
config_parser = config_manager._parsers.values()[0]

VAULT_FILTER_KEY = get_ini_config_value(
    config_parser, dict(section=CONFIG_SECTION, key='key')) or 'vault.key'
VAULT_FILTER_SALT = get_ini_config_value(
    config_parser, dict(section=CONFIG_SECTION, key='salt')) or None
VAULT_FILTER_ITERATIONS = get_ini_config_value(
    config_parser, dict(section=CONFIG_SECTION, key='iterations')) or 1000000
VAULT_FILTER_GENERATE_KEY = get_ini_config_value(
    config_parser, dict(section=CONFIG_SECTION, key='generate_key')) or False
DEFAULT_VAULT_PASSWORD_FILE = config_manager.data.get_setting(
    'DEFAULT_VAULT_PASSWORD_FILE').value

# Read environment variables
VAULT_FILTER_KEY = os.getenv('VAULT_FILTER_KEY', VAULT_FILTER_KEY)
示例#20
0
class ConfigCLI(CLI):
    """ Config command line class """

    def __init__(self, args, callback=None):

        self.config_file = None
        self.config = None
        super(ConfigCLI, self).__init__(args, callback)

    def init_parser(self):

        super(ConfigCLI, self).init_parser(
            desc="View ansible configuration.",
        )

        common = opt_help.argparse.ArgumentParser(add_help=False)
        opt_help.add_verbosity_options(common)
        common.add_argument('-c', '--config', dest='config_file',
                            help="path to configuration file, defaults to first file found in precedence.")
        common.add_argument("-t", "--type", action="store", default='base', dest='type', choices=['all', 'base'] + list(C.CONFIGURABLE_PLUGINS),
                            help="Show configuration for a plugin type, for a specific plugin's options see ansible-doc.")

        subparsers = self.parser.add_subparsers(dest='action')
        subparsers.required = True

        list_parser = subparsers.add_parser('list', help='Print all config options', parents=[common])
        list_parser.set_defaults(func=self.execute_list)

        dump_parser = subparsers.add_parser('dump', help='Dump configuration', parents=[common])
        dump_parser.set_defaults(func=self.execute_dump)
        dump_parser.add_argument('--only-changed', '--changed-only', dest='only_changed', action='store_true',
                                 help="Only show configurations that have changed from the default")

        view_parser = subparsers.add_parser('view', help='View configuration file', parents=[common])
        view_parser.set_defaults(func=self.execute_view)

        # update_parser = subparsers.add_parser('update', help='Update configuration option')
        # update_parser.set_defaults(func=self.execute_update)
        # update_parser.add_argument('-s', '--setting', dest='setting',
        #                            help="config setting, the section defaults to 'defaults'",
        #                            metavar='[section.]setting=value')

        # search_parser = subparsers.add_parser('search', help='Search configuration')
        # search_parser.set_defaults(func=self.execute_search)
        # search_parser.add_argument('args', help='Search term', metavar='<search term>')

    def post_process_args(self, options):
        options = super(ConfigCLI, self).post_process_args(options)
        display.verbosity = options.verbosity

        return options

    def run(self):

        super(ConfigCLI, self).run()

        if context.CLIARGS['config_file']:
            self.config_file = unfrackpath(context.CLIARGS['config_file'], follow=False)
            b_config = to_bytes(self.config_file)
            if os.path.exists(b_config) and os.access(b_config, os.R_OK):
                self.config = ConfigManager(self.config_file)
            else:
                raise AnsibleOptionsError('The provided configuration file is missing or not accessible: %s' % to_native(self.config_file))
        else:
            self.config = C.config
            self.config_file = self.config._config_file

        if self.config_file:
            try:
                if not os.path.exists(self.config_file):
                    raise AnsibleOptionsError("%s does not exist or is not accessible" % (self.config_file))
                elif not os.path.isfile(self.config_file):
                    raise AnsibleOptionsError("%s is not a valid file" % (self.config_file))

                os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
            except Exception:
                if context.CLIARGS['action'] in ['view']:
                    raise
                elif context.CLIARGS['action'] in ['edit', 'update']:
                    display.warning("File does not exist, used empty file: %s" % self.config_file)

        elif context.CLIARGS['action'] == 'view':
            raise AnsibleError('Invalid or no config file was supplied')

        context.CLIARGS['func']()

    def execute_update(self):
        '''
        Updates a single setting in the specified ansible.cfg
        '''
        raise AnsibleError("Option not implemented yet")

        # pylint: disable=unreachable
        if context.CLIARGS['setting'] is None:
            raise AnsibleOptionsError("update option requires a setting to update")

        (entry, value) = context.CLIARGS['setting'].split('=')
        if '.' in entry:
            (section, option) = entry.split('.')
        else:
            section = 'defaults'
            option = entry
        subprocess.call([
            'ansible',
            '-m', 'ini_file',
            'localhost',
            '-c', 'local',
            '-a', '"dest=%s section=%s option=%s value=%s backup=yes"' % (self.config_file, section, option, value)
        ])

    def execute_view(self):
        '''
        Displays the current config file
        '''
        try:
            with open(self.config_file, 'rb') as f:
                self.pager(to_text(f.read(), errors='surrogate_or_strict'))
        except Exception as e:
            raise AnsibleError("Failed to open config file: %s" % to_native(e))

    def execute_edit(self):
        '''
        Opens ansible.cfg in the default EDITOR
        '''
        raise AnsibleError("Option not implemented yet")

        # pylint: disable=unreachable
        try:
            editor = shlex.split(os.environ.get('EDITOR', 'vi'))
            editor.append(self.config_file)
            subprocess.call(editor)
        except Exception as e:
            raise AnsibleError("Failed to open editor: %s" % to_native(e))

    def _list_plugin_settings(self, ptype):
        entries = {}
        loader = getattr(plugin_loader, '%s_loader' % ptype)
        for plugin in loader.all(class_only=True):
            finalname = name = plugin._load_name
            if name.startswith('_'):
                # alias or deprecated
                if os.path.islink(plugin._original_path):
                    continue
                else:
                    finalname = name.replace('_', '', 1) + ' (DEPRECATED)'

            entries[finalname] = self.config.get_configuration_definitions(ptype, name)

        return entries

    def execute_list(self):
        '''
        list all current configs reading lib/constants.py and shows env and config file setting names
        '''

        config_entries = {}
        if context.CLIARGS['type'] == 'base':
            # this dumps main/common configs
            config_entries = self.config.get_configuration_definitions(ignore_private=True)
        elif context.CLIARGS['type'] == 'all':
            # get global
            config_entries = self.config.get_configuration_definitions(ignore_private=True)

            config_entries['PLUGINS'] = {}
            # now each plugin type
            for ptype in C.CONFIGURABLE_PLUGINS:
                config_entries['PLUGINS'][ptype.upper()] = self._list_plugin_settings(ptype)
        else:
            config_entries = self._list_plugin_settings(context.CLIARGS['type'])

        self.pager(to_text(yaml.dump(config_entries, Dumper=AnsibleDumper), errors='surrogate_or_strict'))

    def _render_settings(self, config):

        text = []
        for setting in sorted(config):
            if isinstance(config[setting], Setting):
                if config[setting].origin == 'default':
                    color = 'green'
                elif config[setting].origin == 'REQUIRED':
                    color = 'red'
                else:
                    color = 'yellow'
                msg = "%s(%s) = %s" % (setting, config[setting].origin, config[setting].value)
            else:
                color = 'green'
                msg = "%s(%s) = %s" % (setting, 'default', config[setting].get('default'))
            if not context.CLIARGS['only_changed'] or color == 'yellow':
                text.append(stringc(msg, color))

        return text

    def _get_global_configs(self):
        config = self.config.get_configuration_definitions(ignore_private=True).copy()
        for setting in self.config.data.get_settings():
            if setting.name in config:
                config[setting.name] = setting

        return self._render_settings(config)

    def _get_plugin_configs(self, ptype):

        # prep loading
        loader = getattr(plugin_loader, '%s_loader' % ptype)

        # acumulators
        text = []
        config_entries = {}
        for plugin in loader.all(class_only=True):

            # in case of deprecastion they diverge
            finalname = name = plugin._load_name
            if name.startswith('_'):
                if os.path.islink(plugin._original_path):
                    # skip alias
                    continue
                # deprecated, but use 'nice name'
                finalname = name.replace('_', '', 1) + ' (DEPRECATED)'

            # default entries per plugin
            config_entries[finalname] = self.config.get_configuration_definitions(ptype, name)

            try:
                # populate config entries by loading plugin
                dump = loader.get(name, class_only=True)
            except Exception as e:
                display.warning('Skipping "%s" %s plugin, as we cannot load plugin to check config due to : %s' % (name, ptype, to_native(e)))
                continue

            # actually get the values
            for setting in config_entries[finalname].keys():
                try:
                    v, o = C.config.get_config_value_and_origin(setting, plugin_type=ptype, plugin_name=name)
                except AnsibleError as e:
                    if to_text(e).startswith('No setting was provided for required configuration'):
                        v = None
                        o = 'REQUIRED'
                    else:
                        raise e
                config_entries[finalname][setting] = Setting(setting, v, o, None)

            # pretty please!
            results = self._render_settings(config_entries[finalname])
            if results:
                # avoid header for empty lists (only changed!)
                text.append('\n%s:\n%s' % (finalname, '_' * len(finalname)))
                text.extend(results)
        return text

    def execute_dump(self):
        '''
        Shows the current settings, merges ansible.cfg if specified
        '''
        if context.CLIARGS['type'] == 'base':
            # deal with base
            text = self._get_global_configs()
        elif context.CLIARGS['type'] == 'all':
            # deal with base
            text = self._get_global_configs()
            # deal with plugins
            for ptype in C.CONFIGURABLE_PLUGINS:
                text.append('\n%s:\n%s' % (ptype.upper(), '=' * len(ptype)))
                text.extend(self._get_plugin_configs(ptype))
        else:
            # deal with plugins
            text = self._get_plugin_configs(context.CLIARGS['type'])

        self.pager(to_text('\n'.join(text), errors='surrogate_or_strict'))
示例#21
0
 def __init__(self):
     self._config = ConfigManager()
     self._loader = DataLoader()
     self._file_vault_secrets = {}
     self._inventory: InventoryManager = None
     self._variables: VariableManager = None
示例#22
0
class TestConfigData(unittest.TestCase):
    def setUp(self):
        self.manager = ConfigManager(cfg_file,
                                     os.path.join(curdir, 'test.yml'))

    def tearDown(self):
        self.manager = None

    def test_initial_load(self):
        self.assertEquals(self.manager.data._global_settings, expected_ini)

    def test_ensure_type_list(self):
        self.assertIsInstance(ensure_type('a,b', 'list'), list)
        self.assertIsInstance(ensure_type(['a', 'b'], 'list'), list)

    def test_ensure_type_bool(self):
        self.assertIsInstance(ensure_type('yes', 'bool'), bool)
        self.assertIsInstance(ensure_type(True, 'bool'), bool)

    def test_ensure_type_int(self):
        self.assertIsInstance(ensure_type('10', 'int'), int)
        self.assertIsInstance(ensure_type(20, 'int'), int)

    def test_ensure_type_float(self):
        self.assertIsInstance(ensure_type('0.10', 'float'), float)
        self.assertIsInstance(ensure_type(0.2, 'float'), float)

    def test_find_ini_file(self):
        cur_config = os.environ['ANSIBLE_CONFIG']
        os.environ['ANSIBLE_CONFIG'] = cfg_file
        self.assertEquals(cfg_file, find_ini_config_file())
        os.environ['ANSIBLE_CONFIG'] = cur_config

    def test_resolve_path(self):
        self.assertEquals(os.path.join(curdir, 'test.yml'),
                          resolve_path('./test.yml', cfg_file))

    def test_resolve_path_cwd(self):
        self.assertEquals(os.path.join(os.getcwd(), 'test.yml'),
                          resolve_path('{{CWD}}/test.yml'))
        self.assertEquals(os.path.join(os.getcwd(), 'test.yml'),
                          resolve_path('./test.yml'))

    def test_get_config_dest(self):
        pass

    def test_value_and_origin_from_ini(self):
        self.assertEquals(
            self.manager.get_config_value_and_origin('config_entry'),
            ('fromini', cfg_file))

    def test_value_from_ini(self):
        self.assertEquals(self.manager.get_config_value('config_entry'),
                          'fromini')

    def test_value_and_origin_from_alt_ini(self):
        self.assertEquals(
            self.manager.get_config_value_and_origin('config_entry',
                                                     cfile=cfg_file2),
            ('fromini2', cfg_file2))

    def test_value_from_alt_ini(self):
        self.assertEquals(
            self.manager.get_config_value('config_entry', cfile=cfg_file2),
            'fromini2')

    def test_value_and_origin_from_yaml(self):
        pass

    def test_value_from_yaml(self):
        pass

    def test_value_and_origin_from_alt_yaml(self):
        pass

    def test_value_from_alt_yaml(self):
        pass

    def test_config_type_bool(self):
        pass

    def test_config_type_list(self):
        pass

    def test_config_default(self):
        pass

    def test_deprecated_config(self):
        pass

    def test_deprecated_config_source(self):
        pass

    def test_multi_precedence(self):
        pass

    def test_initialize_plugin_config(self):
        pass

    def test_update_config_data(self):
        pass
示例#23
0
    # ssh TODO: remove
    ssh_executable=('ansible_ssh_executable', ),
    ssh_common_args=('ansible_ssh_common_args', ),
    sftp_extra_args=('ansible_sftp_extra_args', ),
    scp_extra_args=('ansible_scp_extra_args', ),
    ssh_extra_args=('ansible_ssh_extra_args', ),
    ssh_transfer_method=('ansible_ssh_transfer_method', ),

    # docker TODO: remove
    docker_extra_args=('ansible_docker_extra_args', ),

    # become
    become=('ansible_become', ),
    become_method=('ansible_become_method', ),
    become_user=('ansible_become_user', ),
    become_pass=('ansible_become_password', 'ansible_become_pass'),
    become_exe=('ansible_become_exe', ),
    become_flags=('ansible_become_flags', ),
)

# POPULATE SETTINGS FROM CONFIG ###
config = ConfigManager()

# Generate constants from config
for setting in config.get_configuration_definitions():
    set_constant(setting, config.get_config_value(setting, variables=vars()))

for warn in config.WARNINGS:
    _warning(warn)
示例#24
0
    # deprecated
    sudo=('ansible_sudo', ),
    sudo_user=('ansible_sudo_user', ),
    sudo_pass=('ansible_sudo_password', 'ansible_sudo_pass'),
    sudo_exe=('ansible_sudo_exe', ),
    sudo_flags=('ansible_sudo_flags', ),
    su=('ansible_su', ),
    su_user=('ansible_su_user', ),
    su_pass=('ansible_su_password', 'ansible_su_pass'),
    su_exe=('ansible_su_exe', ),
    su_flags=('ansible_su_flags', ),
)

# POPULATE SETTINGS FROM CONFIG ###
config = ConfigManager()

# Generate constants from config
for setting in config.data.get_settings():

    value = setting.value
    if setting.origin == 'default' and \
       isinstance(setting.value, string_types) and \
       (setting.value.startswith('{{') and setting.value.endswith('}}')):
        try:
            t = Template(setting.value)
            value = t.render(vars())
            try:
                value = literal_eval(value)
            except ValueError:
                pass  # not a python data structure
示例#25
0
class ConfigCLI(CLI):
    """ Config command line class """

    name = 'ansible-config'

    def __init__(self, args, callback=None):

        self.config_file = None
        self.config = None
        super(ConfigCLI, self).__init__(args, callback)

    def init_parser(self):

        super(ConfigCLI,
              self).init_parser(desc="View ansible configuration.", )

        common = opt_help.argparse.ArgumentParser(add_help=False)
        opt_help.add_verbosity_options(common)
        common.add_argument(
            '-c',
            '--config',
            dest='config_file',
            help=
            "path to configuration file, defaults to first file found in precedence."
        )
        common.add_argument("-t",
                            "--type",
                            action="store",
                            default='base',
                            dest='type',
                            choices=['all', 'base'] +
                            list(C.CONFIGURABLE_PLUGINS),
                            help="Filter down to a specific plugin type.")
        common.add_argument(
            'args',
            help='Specific plugin to target, requires type of plugin to be set',
            nargs='*')

        subparsers = self.parser.add_subparsers(dest='action')
        subparsers.required = True

        list_parser = subparsers.add_parser('list',
                                            help='Print all config options',
                                            parents=[common])
        list_parser.set_defaults(func=self.execute_list)

        dump_parser = subparsers.add_parser('dump',
                                            help='Dump configuration',
                                            parents=[common])
        dump_parser.set_defaults(func=self.execute_dump)
        dump_parser.add_argument(
            '--only-changed',
            '--changed-only',
            dest='only_changed',
            action='store_true',
            help="Only show configurations that have changed from the default")

        view_parser = subparsers.add_parser('view',
                                            help='View configuration file',
                                            parents=[common])
        view_parser.set_defaults(func=self.execute_view)

        init_parser = subparsers.add_parser(
            'init', help='Create initial configuration', parents=[common])
        init_parser.set_defaults(func=self.execute_init)
        init_parser.add_argument('--format',
                                 '-f',
                                 dest='format',
                                 action='store',
                                 choices=['ini', 'env', 'vars'],
                                 default='ini',
                                 help='Output format for init')
        init_parser.add_argument(
            '--disabled',
            dest='commented',
            action='store_true',
            default=False,
            help='Prefixes all entries with a comment character to disable them'
        )

        # search_parser = subparsers.add_parser('find', help='Search configuration')
        # search_parser.set_defaults(func=self.execute_search)
        # search_parser.add_argument('args', help='Search term', metavar='<search term>')

    def post_process_args(self, options):
        options = super(ConfigCLI, self).post_process_args(options)
        display.verbosity = options.verbosity

        return options

    def run(self):

        super(ConfigCLI, self).run()

        if context.CLIARGS['config_file']:
            self.config_file = unfrackpath(context.CLIARGS['config_file'],
                                           follow=False)
            b_config = to_bytes(self.config_file)
            if os.path.exists(b_config) and os.access(b_config, os.R_OK):
                self.config = ConfigManager(self.config_file)
            else:
                raise AnsibleOptionsError(
                    'The provided configuration file is missing or not accessible: %s'
                    % to_native(self.config_file))
        else:
            self.config = C.config
            self.config_file = self.config._config_file

        if self.config_file:
            try:
                if not os.path.exists(self.config_file):
                    raise AnsibleOptionsError(
                        "%s does not exist or is not accessible" %
                        (self.config_file))
                elif not os.path.isfile(self.config_file):
                    raise AnsibleOptionsError("%s is not a valid file" %
                                              (self.config_file))

                os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
            except Exception:
                if context.CLIARGS['action'] in ['view']:
                    raise
                elif context.CLIARGS['action'] in ['edit', 'update']:
                    display.warning(
                        "File does not exist, used empty file: %s" %
                        self.config_file)

        elif context.CLIARGS['action'] == 'view':
            raise AnsibleError('Invalid or no config file was supplied')

        # run the requested action
        context.CLIARGS['func']()

    def execute_update(self):
        '''
        Updates a single setting in the specified ansible.cfg
        '''
        raise AnsibleError("Option not implemented yet")

        # pylint: disable=unreachable
        if context.CLIARGS['setting'] is None:
            raise AnsibleOptionsError(
                "update option requires a setting to update")

        (entry, value) = context.CLIARGS['setting'].split('=')
        if '.' in entry:
            (section, option) = entry.split('.')
        else:
            section = 'defaults'
            option = entry
        subprocess.call([
            'ansible', '-m', 'ini_file', 'localhost', '-c', 'local', '-a',
            '"dest=%s section=%s option=%s value=%s backup=yes"' %
            (self.config_file, section, option, value)
        ])

    def execute_view(self):
        '''
        Displays the current config file
        '''
        try:
            with open(self.config_file, 'rb') as f:
                self.pager(to_text(f.read(), errors='surrogate_or_strict'))
        except Exception as e:
            raise AnsibleError("Failed to open config file: %s" % to_native(e))

    def execute_edit(self):
        '''
        Opens ansible.cfg in the default EDITOR
        '''
        raise AnsibleError("Option not implemented yet")

        # pylint: disable=unreachable
        try:
            editor = shlex.split(os.environ.get('EDITOR', 'vi'))
            editor.append(self.config_file)
            subprocess.call(editor)
        except Exception as e:
            raise AnsibleError("Failed to open editor: %s" % to_native(e))

    def _list_plugin_settings(self, ptype, plugins=None):
        entries = {}
        loader = getattr(plugin_loader, '%s_loader' % ptype)

        # build list
        if plugins:
            plugin_cs = []
            for plugin in plugins:
                p = loader.get(plugin, class_only=True)
                if p is None:
                    display.warning(
                        "Skipping %s as we could not find matching plugin" %
                        plugin)
                else:
                    plugin_cs.append(p)
        else:
            plugin_cs = loader.all(class_only=True)

        # iterate over class instances
        for plugin in plugin_cs:
            finalname = name = plugin._load_name
            if name.startswith('_'):
                # alias or deprecated
                if os.path.islink(plugin._original_path):
                    continue
                else:
                    finalname = name.replace('_', '', 1) + ' (DEPRECATED)'

            entries[finalname] = self.config.get_configuration_definitions(
                ptype, name)

        return entries

    def _list_entries_from_args(self):
        '''
        build a dict with the list requested configs
        '''
        config_entries = {}
        if context.CLIARGS['type'] in ('base', 'all'):
            # this dumps main/common configs
            config_entries = self.config.get_configuration_definitions(
                ignore_private=True)

        if context.CLIARGS['type'] != 'base':
            config_entries['PLUGINS'] = {}

        if context.CLIARGS['type'] == 'all':
            # now each plugin type
            for ptype in C.CONFIGURABLE_PLUGINS:
                config_entries['PLUGINS'][
                    ptype.upper()] = self._list_plugin_settings(ptype)
        elif context.CLIARGS['type'] != 'base':
            config_entries['PLUGINS'][
                context.CLIARGS['type']] = self._list_plugin_settings(
                    context.CLIARGS['type'], context.CLIARGS['args'])

        return config_entries

    def execute_list(self):
        '''
        list and output available configs
        '''

        config_entries = self._list_entries_from_args()
        self.pager(
            to_text(yaml.dump(config_entries, Dumper=AnsibleDumper),
                    errors='surrogate_or_strict'))

    def _get_settings_vars(self, settings, subkey):

        data = []
        if context.CLIARGS['commented']:
            prefix = '#'
        else:
            prefix = ''

        for setting in settings:

            if not settings[setting].get('description'):
                continue

            default = settings[setting].get('default', '')
            if subkey == 'env':
                stype = settings[setting].get('type', '')
                if stype == 'boolean':
                    if default:
                        default = '1'
                    else:
                        default = '0'
                elif default:
                    if stype == 'list':
                        if not isinstance(default, string_types):
                            # python lists are not valid env ones
                            try:
                                default = ', '.join(default)
                            except Exception as e:
                                # list of other stuff
                                default = '%s' % to_native(default)
                    if isinstance(default,
                                  string_types) and not is_quoted(default):
                        default = shlex.quote(default)
                elif default is None:
                    default = ''

            if subkey in settings[setting] and settings[setting][subkey]:
                entry = settings[setting][subkey][-1]['name']
                if isinstance(settings[setting]['description'], string_types):
                    desc = settings[setting]['description']
                else:
                    desc = '\n#'.join(settings[setting]['description'])
                name = settings[setting].get('name', setting)
                data.append(
                    '# %s(%s): %s' %
                    (name, settings[setting].get('type', 'string'), desc))

                # TODO: might need quoting and value coercion depending on type
                if subkey == 'env':
                    data.append('%s%s=%s' % (prefix, entry, default))
                elif subkey == 'vars':
                    data.append(prefix +
                                to_text(yaml.dump({entry: default},
                                                  Dumper=AnsibleDumper,
                                                  default_flow_style=False),
                                        errors='surrogate_or_strict'))
                data.append('')

        return data

    def _get_settings_ini(self, settings):

        sections = {}
        for o in sorted(settings.keys()):

            opt = settings[o]

            if not isinstance(opt, Mapping):
                # recursed into one of the few settings that is a mapping, now hitting it's strings
                continue

            if not opt.get('description'):
                # its a plugin
                new_sections = self._get_settings_ini(opt)
                for s in new_sections:
                    if s in sections:
                        sections[s].extend(new_sections[s])
                    else:
                        sections[s] = new_sections[s]
                continue

            if isinstance(opt['description'], string_types):
                desc = '# (%s) %s' % (opt.get('type',
                                              'string'), opt['description'])
            else:
                desc = "# (%s) " % opt.get('type', 'string')
                desc += "\n# ".join(opt['description'])

            if 'ini' in opt and opt['ini']:
                entry = opt['ini'][-1]
                if entry['section'] not in sections:
                    sections[entry['section']] = []

                default = opt.get('default', '')
                if opt.get('type', '') == 'list' and not isinstance(
                        default, string_types):
                    # python lists are not valid ini ones
                    default = ', '.join(default)
                elif default is None:
                    default = ''

                if context.CLIARGS['commented']:
                    entry['key'] = ';%s' % entry['key']

                key = desc + '\n%s=%s' % (entry['key'], default)
                sections[entry['section']].append(key)

        return sections

    def execute_init(self):

        data = []
        config_entries = self._list_entries_from_args()
        plugin_types = config_entries.pop('PLUGINS', None)

        if context.CLIARGS['format'] == 'ini':
            sections = self._get_settings_ini(config_entries)

            if plugin_types:
                for ptype in plugin_types:
                    plugin_sections = self._get_settings_ini(
                        plugin_types[ptype])
                    for s in plugin_sections:
                        if s in sections:
                            sections[s].extend(plugin_sections[s])
                        else:
                            sections[s] = plugin_sections[s]

            if sections:
                for section in sections.keys():
                    data.append('[%s]' % section)
                    for key in sections[section]:
                        data.append(key)
                        data.append('')
                    data.append('')

        elif context.CLIARGS['format'] in (
                'env',
                'vars'):  # TODO: add yaml once that config option is added
            data = self._get_settings_vars(config_entries,
                                           context.CLIARGS['format'])
            if plugin_types:
                for ptype in plugin_types:
                    for plugin in plugin_types[ptype].keys():
                        data.extend(
                            self._get_settings_vars(
                                plugin_types[ptype][plugin],
                                context.CLIARGS['format']))

        self.pager(to_text('\n'.join(data), errors='surrogate_or_strict'))

    def _render_settings(self, config):

        text = []
        for setting in sorted(config):
            changed = False
            if isinstance(config[setting], Setting):
                # proceed normally
                if config[setting].origin == 'default':
                    color = 'green'
                elif config[setting].origin == 'REQUIRED':
                    # should include '_terms', '_input', etc
                    color = 'red'
                else:
                    color = 'yellow'
                    changed = True
                msg = "%s(%s) = %s" % (setting, config[setting].origin,
                                       config[setting].value)
            else:
                color = 'green'
                msg = "%s(%s) = %s" % (setting, 'default',
                                       config[setting].get('default'))

            if not context.CLIARGS['only_changed'] or changed:
                text.append(stringc(msg, color))

        return text

    def _get_global_configs(self):
        config = self.config.get_configuration_definitions(
            ignore_private=True).copy()
        for setting in self.config.data.get_settings():
            if setting.name in config:
                config[setting.name] = setting

        return self._render_settings(config)

    def _get_plugin_configs(self, ptype, plugins):

        # prep loading
        loader = getattr(plugin_loader, '%s_loader' % ptype)

        # acumulators
        text = []
        config_entries = {}

        # build list
        if plugins:
            plugin_cs = []
            for plugin in plugins:
                p = loader.get(plugin, class_only=True)
                if p is None:
                    display.warning(
                        "Skipping %s as we could not find matching plugin" %
                        plugin)
                else:
                    plugin_cs.append(loader.get(plugin, class_only=True))
        else:
            plugin_cs = loader.all(class_only=True)

        for plugin in plugin_cs:
            # in case of deprecastion they diverge
            finalname = name = plugin._load_name
            if name.startswith('_'):
                if os.path.islink(plugin._original_path):
                    # skip alias
                    continue
                # deprecated, but use 'nice name'
                finalname = name.replace('_', '', 1) + ' (DEPRECATED)'

            # default entries per plugin
            config_entries[
                finalname] = self.config.get_configuration_definitions(
                    ptype, name)

            try:
                # populate config entries by loading plugin
                dump = loader.get(name, class_only=True)
            except Exception as e:
                display.warning(
                    'Skipping "%s" %s plugin, as we cannot load plugin to check config due to : %s'
                    % (name, ptype, to_native(e)))
                continue

            # actually get the values
            for setting in config_entries[finalname].keys():
                try:
                    v, o = C.config.get_config_value_and_origin(
                        setting, plugin_type=ptype, plugin_name=name)
                except AnsibleError as e:
                    if to_text(e).startswith(
                            'No setting was provided for required configuration'
                    ):
                        v = None
                        o = 'REQUIRED'
                    else:
                        raise e

                if v is None and o is None:
                    # not all cases will be error
                    o = 'REQUIRED'

                config_entries[finalname][setting] = Setting(
                    setting, v, o, None)

            # pretty please!
            results = self._render_settings(config_entries[finalname])
            if results:
                # avoid header for empty lists (only changed!)
                text.append('\n%s:\n%s' % (finalname, '_' * len(finalname)))
                text.extend(results)
        return text

    def execute_dump(self):
        '''
        Shows the current settings, merges ansible.cfg if specified
        '''
        if context.CLIARGS['type'] == 'base':
            # deal with base
            text = self._get_global_configs()
        elif context.CLIARGS['type'] == 'all':
            # deal with base
            text = self._get_global_configs()
            # deal with plugins
            for ptype in C.CONFIGURABLE_PLUGINS:
                text.append('\n%s:\n%s' % (ptype.upper(), '=' * len(ptype)))
                text.extend(
                    self._get_plugin_configs(ptype, context.CLIARGS['args']))
        else:
            # deal with plugins
            text = self._get_plugin_configs(context.CLIARGS['type'],
                                            context.CLIARGS['args'])

        self.pager(to_text('\n'.join(text), errors='surrogate_or_strict'))
示例#26
0
class ConfigCLI(CLI):
    """ Config command line class """

    VALID_ACTIONS = ("view", "dump", "list")  # TODO: edit, update, search

    def __init__(self, args, callback=None):

        self.config_file = None
        self.config = None
        super(ConfigCLI, self).__init__(args, callback)

    def parse(self):

        self.parser = CLI.base_parser(
            usage="usage: %%prog [%s] [--help] [options] [ansible.cfg]" % "|".join(self.VALID_ACTIONS),
            epilog="\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0]),
            desc="View, edit, and manage ansible configuration.",
        )
        self.parser.add_option('-c', '--config', dest='config_file', help="path to configuration file, defaults to first file found in precedence.")

        self.set_action()

        # options specific to self.actions
        if self.action == "list":
            self.parser.set_usage("usage: %prog list [options] ")
        if self.action == "dump":
            self.parser.add_option('--only-changed', dest='only_changed', action='store_true',
                                   help="Only show configurations that have changed from the default")
        elif self.action == "update":
            self.parser.add_option('-s', '--setting', dest='setting', help="config setting, the section defaults to 'defaults'")
            self.parser.set_usage("usage: %prog update [options] [-c ansible.cfg] -s '[section.]setting=value'")
        elif self.action == "search":
            self.parser.set_usage("usage: %prog update [options] [-c ansible.cfg] <search term>")

        self.options, self.args = self.parser.parse_args()
        display.verbosity = self.options.verbosity

    def run(self):

        super(ConfigCLI, self).run()

        if self.options.config_file:
            self.config_file = unfrackpath(self.options.config_file, follow=False)
            self.config = ConfigManager(self.config_file)
        else:
            self.config = ConfigManager()
            self.config_file = find_ini_config_file()

        if self.config_file:
            try:
                if not os.path.exists(self.config_file):
                    raise AnsibleOptionsError("%s does not exist or is not accessible" % (self.config_file))
                elif not os.path.isfile(self.config_file):
                    raise AnsibleOptionsError("%s is not a valid file" % (self.config_file))

                os.environ['ANSIBLE_CONFIG'] = to_native(self.config_file)
            except:
                if self.action in ['view']:
                    raise
                elif self.action in ['edit', 'update']:
                    display.warning("File does not exist, used empty file: %s" % self.config_file)

        elif self.action == 'view':
            raise AnsibleError('Invalid or no config file was supplied')

        self.execute()

    def execute_update(self):
        '''
        Updates a single setting in the specified ansible.cfg
        '''
        raise AnsibleError("Option not implemented yet")

        # pylint: disable=unreachable
        if self.options.setting is None:
            raise AnsibleOptionsError("update option requries a setting to update")

        (entry, value) = self.options.setting.split('=')
        if '.' in entry:
            (section, option) = entry.split('.')
        else:
            section = 'defaults'
            option = entry
        subprocess.call([
            'ansible',
            '-m', 'ini_file',
            'localhost',
            '-c', 'local',
            '-a', '"dest=%s section=%s option=%s value=%s backup=yes"' % (self.config_file, section, option, value)
        ])

    def execute_view(self):
        '''
        Displays the current config file
        '''
        try:
            with open(self.config_file, 'rb') as f:
                self.pager(to_text(f.read(), errors='surrogate_or_strict'))
        except Exception as e:
            raise AnsibleError("Failed to open config file: %s" % to_native(e))

    def execute_edit(self):
        '''
        Opens ansible.cfg in the default EDITOR
        '''
        raise AnsibleError("Option not implemented yet")

        # pylint: disable=unreachable
        try:
            editor = shlex.split(os.environ.get('EDITOR', 'vi'))
            editor.append(self.config_file)
            subprocess.call(editor)
        except Exception as e:
            raise AnsibleError("Failed to open editor: %s" % to_native(e))

    def execute_list(self):
        '''
        list all current configs reading lib/constants.py and shows env and config file setting names
        '''
        self.pager(to_text(yaml.dump(self.config.get_configuration_definitions(), Dumper=AnsibleDumper), errors='surrogate_or_strict'))

    def execute_dump(self):
        '''
        Shows the current settings, merges ansible.cfg if specified
        '''
        # FIXME: deal with plugins, not just base config
        text = []
        defaults = self.config.get_configuration_definitions().copy()
        for setting in self.config.data.get_settings():
            if setting.name in defaults:
                defaults[setting.name] = setting

        for setting in sorted(defaults):
            if isinstance(defaults[setting], Setting):
                if defaults[setting].origin == 'default':
                    color = 'green'
                else:
                    color = 'yellow'
                msg = "%s(%s) = %s" % (setting, defaults[setting].origin, defaults[setting].value)
            else:
                color = 'green'
                msg = "%s(%s) = %s" % (setting, 'default', defaults[setting].get('default'))
            if not self.options.only_changed or color == 'yellow':
                text.append(stringc(msg, color))

        self.pager(to_text('\n'.join(text), errors='surrogate_or_strict'))
示例#27
0
 def setUp(self):
     self.manager = ConfigManager(cfg_file,
                                  os.path.join(curdir, 'test.yml'))
示例#28
0
class Loader:
    def __init__(self):
        self._config = ConfigManager()
        self._loader = DataLoader()
        self._file_vault_secrets = {}
        self._inventory: InventoryManager = None
        self._variables: VariableManager = None

    def _load_file_vault_secrets(self, password_file_path=None):
        if password_file_path is None:
            password_file_path = self._config.get_config_value(
                "DEFAULT_VAULT_PASSWORD_FILE")

        password_file = Path(password_file_path)

        if password_file.name in self._file_vault_secrets:
            return

        if not password_file.is_file():
            raise FileNotFoundError(password_file)

        self._file_vault_secrets[password_file.name] = get_file_vault_secret(
            filename=password_file, loader=self._loader)
        self._file_vault_secrets[password_file.name].load()
        self._loader.set_vault_secrets([
            (password_file.name, self._file_vault_secrets[password_file.name])
        ])

    def _get_inventory(self, source=None):
        if source is None:
            source = self._config.get_config_value("DEFAULT_HOST_LIST")

        if self._inventory is None:
            self._inventory = InventoryManager(loader=self._loader,
                                               sources=source)
        else:
            sources = source if isinstance(source, list) else [source]
            (self._inventory.parse_source(s) for s in sources)
            self._inventory.reconcile_inventory()

        return self._inventory

    def _get_variables(self, source=None):
        self._load_file_vault_secrets()
        if self._variables is None:
            self._variables = VariableManager(
                loader=self._loader, inventory=self._get_inventory(source))

        return self._variables

    def get_hosts(self, pattern='all', source=None):
        return self._get_inventory(source).get_hosts(pattern)

    def get_host(self, hostname, source=None):
        return self._get_inventory(source).get_host(hostname)

    def get_vars(self, host, data={}):
        play = Play.load(data,
                         loader=self._loader,
                         variable_manager=self._get_variables())
        return self._get_variables().get_vars(host=host, play=play)