diff --git a/bin/ansible b/bin/ansible index 7c1a3ca4f92..dc420f23ca9 100755 --- a/bin/ansible +++ b/bin/ansible @@ -127,7 +127,7 @@ if __name__ == '__main__': exit_code = 99 except Exception as e: have_cli_options = cli is not None and cli.options is not None - display.error("Unexpected Exception: %s" % to_text(e), wrap_text=False) + display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False) if not have_cli_options or have_cli_options and cli.options.verbosity > 2: log_only = False else: diff --git a/bin/ansible-config b/bin/ansible-config new file mode 120000 index 00000000000..cabb1f519aa --- /dev/null +++ b/bin/ansible-config @@ -0,0 +1 @@ +ansible \ No newline at end of file diff --git a/hacking/conf2yaml.py b/hacking/conf2yaml.py new file mode 100755 index 00000000000..d8fc8bcc3b9 --- /dev/null +++ b/hacking/conf2yaml.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python + +import ast +import yaml +import os +import sys +from ansible.parsing.yaml.dumper import AnsibleDumper + +things = {} +stuff = {} + +op_map = { + ast.Add: '+', + ast.Sub: '-', + ast.Mult: '*', + ast.Div: '/', +} + + + +def get_values(values): + if not isinstance(values, list): + return get_value(values) + ret = [] + for value in values: + ret.append(get_value(value)) + return ret + + +def get_value(value): + if hasattr(value, 'id'): + ret = value.id + elif hasattr(value, 's'): + ret = value.s + elif hasattr(value, 'n'): + ret = value.n + elif hasattr(value, 'left'): + operator = op_map[type(value.op)] + left = get_values(value.left) + right = get_values(value.right) + return '%s %s %s' % (left, operator, right) + elif hasattr(value, 'value'): + ret = value.value + elif hasattr(value, 'elts'): + ret = get_values(value.elts) + elif isinstance(value, ast.Call): + func, args, kwargs = get_call(value) + args[:] = [repr(arg) for arg in args] + for k, v in kwargs.items(): + args.append('%s=%s' % (k, repr(v))) + return '%s(%s)' % (func, ', '.join(args)) + else: + return value + + return get_value(ret) + + +def get_call(value): + args = [] + for arg in value.args: + v = get_value(arg) + try: + v = getattr(C, v, v) + except: + pass + args.append(v) + kwargs = {} + for keyword in value.keywords: + v = get_value(keyword.value) + try: + v = getattr(C, v, v) + except: + pass + kwargs[keyword.arg] = v + + func = get_value(value.func) + try: + attr = '.%s' % value.func.attr + except: + attr = '' + return '%s%s' % (func, attr), args, kwargs + + +with open(sys.argv[1]) as f: + tree = ast.parse(f.read()) + +for item in tree.body: + if hasattr(item, 'value') and isinstance(item.value, ast.Call): + try: + if item.value.func.id != 'get_config': + continue + except AttributeError: + continue + + _, args, kwargs = get_call(item.value) + + name = get_value(item.targets[0]) + section = args[1].lower() + config = args[2] + + # new form + if name not in stuff: + stuff[name] = {} + stuff[name] = { + 'desc': 'TODO: write it', + 'ini': [{'section': section, 'key': config}], + 'env': [args[3]], + 'default': args[4] if len(args) == 5 else None, + 'yaml': {'key': '%s.%s' % (section, config)}, + 'vars': [] + } + stuff[name].update(kwargs) + + ## ini like + #if section not in things: + # things[section] = {} + + #things[section][config] = { + # 'env_var': args[3], + # 'default': args[4] if len(args) == 5 else 'UNKNOWN' + #} + #things[section][config].update(kwargs) +print(yaml.dump(stuff, Dumper=AnsibleDumper, indent=2, width=170)) + diff --git a/lib/ansible/cli/__init__.py b/lib/ansible/cli/__init__.py index 3ffc5868eb1..610ea94ec03 100644 --- a/lib/ansible/cli/__init__.py +++ b/lib/ansible/cli/__init__.py @@ -269,10 +269,8 @@ class CLI(with_metaclass(ABCMeta, object)): (op.su or op.su_user) and (op.become or op.become_user) or (op.sudo or op.sudo_user) and (op.become or op.become_user)): - self.parser.error("Sudo arguments ('--sudo', '--sudo-user', and '--ask-sudo-pass') " - "and su arguments ('--su', '--su-user', and '--ask-su-pass') " - "and become arguments ('--become', '--become-user', and '--ask-become-pass')" - " are exclusive of each other") + self.parser.error("Sudo arguments ('--sudo', '--sudo-user', and '--ask-sudo-pass') and su arguments ('--su', '--su-user', and '--ask-su-pass') " + "and become arguments ('--become', '--become-user', and '--ask-become-pass') are exclusive of each other") if fork_opts: if op.forks < 1: @@ -283,20 +281,13 @@ class CLI(with_metaclass(ABCMeta, object)): setattr(parser.values, option.dest, os.path.expanduser(value)) @staticmethod - def unfrack_path(option, opt, value, parser): - setattr(parser.values, option.dest, unfrackpath(value)) + def unfrack_paths(option, opt, value, parser): + if isinstance(value, string_types): + setattr(parser.values, option.dest, [unfrackpath(x) for x in value.split(os.sep)]) @staticmethod - def expand_paths(option, opt, value, parser): - """optparse action callback to convert a PATH style string arg to a list of path strings. - - For ex, cli arg of '-p /blip/foo:/foo/bar' would be split on the - default os.pathsep and the option value would be set to - the list ['/blip/foo', '/foo/bar']. Each path string in the list - will also have '~/' values expand via os.path.expanduser().""" - path_entries = value.split(os.pathsep) - expanded_path_entries = [os.path.expanduser(path_entry) for path_entry in path_entries] - setattr(parser.values, option.dest, expanded_path_entries) + def unfrack_path(option, opt, value, parser): + setattr(parser.values, option.dest, unfrackpath(value)) @staticmethod def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False, runtask_opts=False, vault_opts=False, module_opts=False, diff --git a/lib/ansible/cli/config.py b/lib/ansible/cli/config.py new file mode 100644 index 00000000000..bf365507351 --- /dev/null +++ b/lib/ansible/cli/config.py @@ -0,0 +1,181 @@ +# (c) 2017, Ansible by Red Hat, Inc. +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# +# ansible-vault is a script that encrypts/decrypts YAML files. See +# http://docs.ansible.com/playbooks_vault.html for more details. + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import shlex +import subprocess +import sys +import yaml + +from ansible.cli import CLI +from ansible.config.data import Setting +from ansible.config.manager import ConfigManager +from ansible.errors import AnsibleError, AnsibleOptionsError +from ansible.module_utils._text import to_native, to_text +from ansible.parsing.yaml.dumper import AnsibleDumper +from ansible.utils.color import stringc +from ansible.utils.path import unfrackpath + + +try: + from __main__ import display +except ImportError: + from ansible.utils.display import Display + display = Display() + + +class ConfigCLI(CLI): + """ Config command line class """ + + VALID_ACTIONS = ("view", "edit", "update", "dump", "list") + + 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 --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0]) + ) + + 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.set_usage("usage: %prog dump [options] [-c ansible.cfg]") + elif self.action == "view": + self.parser.set_usage("usage: %prog view [options] [-c ansible.cfg] ") + elif self.action == "edit": + self.parser.set_usage("usage: %prog edit [options] [-c ansible.cfg]") + 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'") + + 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 = 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 execute_update(self): + ''' + Updates a single setting in the specified ansible.cfg + ''' + raise AnsibleError("Option not implemented yet") + + 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") + 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.initial_defs, Dumper=AnsibleDumper), errors='surrogate_or_strict')) + + def execute_dump(self): + ''' + Shows the current settings, merges ansible.cfg if specified + ''' + text = [] + defaults = self.config.initial_defs.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')) + text.append(stringc(msg, color)) + + self.pager(to_text('\n'.join(text), errors='surrogate_or_strict')) diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py index a2e6b252a69..4fdcd628672 100644 --- a/lib/ansible/cli/galaxy.py +++ b/lib/ansible/cli/galaxy.py @@ -117,11 +117,9 @@ class GalaxyCLI(CLI): if self.action not in ("delete", "import", "init", "login", "setup"): # NOTE: while the option type=str, the default is a list, and the # callback will set the value to a list. - self.parser.add_option('-p', '--roles-path', dest='roles_path', action="callback", callback=CLI.expand_paths, type=str, - default=C.DEFAULT_ROLES_PATH, - help='The path to the directory containing your roles. The default is the roles_path configured in your ansible.cfg ' - 'file (/etc/ansible/roles if not configured)') - + self.parser.add_option('-p', '--roles-path', dest='roles_path', action="callback", callback=CLI.unfrack_paths, default=C.DEFAULT_ROLES_PATH, + help='The path to the directory containing your roles. The default is the roles_path configured in your ansible.cfg' + 'file (/etc/ansible/roles if not configured)', type="string") if self.action in ("init", "install"): self.parser.add_option('-f', '--force', dest='force', action='store_true', default=False, help='Force overwriting an existing role') @@ -308,16 +306,13 @@ class GalaxyCLI(CLI): uses the args list of roles to be installed, unless -f was specified. The list of roles can be a name (which will be downloaded via the galaxy API and github), or it can be a local .tar.gz file. """ - role_file = self.get_opt("role_file", None) if len(self.args) == 0 and role_file is None: - # the user needs to specify one of either --role-file - # or specify a single user/role name + # the user needs to specify one of either --role-file or specify a single user/role name raise AnsibleOptionsError("- you must specify a user/role name or a roles file") elif len(self.args) == 1 and role_file is not None: - # using a role file is mutually exclusive of specifying - # the role name on the command line + # using a role file is mutually exclusive of specifying the role name on the command line raise AnsibleOptionsError("- please specify a user/role name, or a roles file, but not both") no_deps = self.get_opt("no_deps", False) diff --git a/lib/ansible/config/__init__.py b/lib/ansible/config/__init__.py index ae8ccff5952..e69de29bb2d 100644 --- a/lib/ansible/config/__init__.py +++ b/lib/ansible/config/__init__.py @@ -1,20 +0,0 @@ -# (c) 2012-2014, Michael DeHaan -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . - -# Make coding more python3-ish -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type diff --git a/lib/ansible/config/data.py b/lib/ansible/config/data.py new file mode 100644 index 00000000000..9158e2413d3 --- /dev/null +++ b/lib/ansible/config/data.py @@ -0,0 +1,63 @@ +# (c) 2017, Ansible by Red Hat, inc +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from collections import namedtuple + +Setting = namedtuple('Setting','name value origin') + +class ConfigData(object): + + BOOL_TRUE = frozenset(["true", "t", "y", "1", "yes", "on"]) + + def __init__(self): + self._global_settings = {} + self._plugins = {} + + def get_setting(self, name, plugin=None): + + setting = None + if plugin is None: + setting = self._global_settings.get(name) + elif plugin.type in self._plugins and plugin.name in self._plugins[plugin.type]: + setting = self._plugins[plugin.type][plugin.name].get(name) + + return setting + + def get_settings(self, plugin=None): + + settings = [] + if plugin is None: + settings = [ self._global_settings[k] for k in self._global_settings ] + elif plugin.type in self._plugins and plugin.name in self._plugins[plugin.type]: + settings = [ self._plugins[plugin.type][plugin.name][k] for k in self._plugins[plugin.type][plugin.name] ] + + return settings + + def update_setting(self, setting, plugin=None): + + if plugin is None: + self._global_settings[setting.name] = setting + else: + if plugin.type not in self._plugins: + self._plugins[plugin.type] = {} + if plugin.name not in self._plugins[plugin.type]: + self._plugins[plugin.type][plugin.name] = {} + self._plugins[plugin.type][plugin.name][setting.name] = setting diff --git a/lib/ansible/config/data/config.yml b/lib/ansible/config/data/config.yml new file mode 100644 index 00000000000..1eac76a1b79 --- /dev/null +++ b/lib/ansible/config/data/config.yml @@ -0,0 +1,1355 @@ +ACCELERATE_CONNECT_TIMEOUT: + default: 1.0 + desc: + - This setting controls the timeout for the socket connect call, and should be kept relatively low. + The connection to the accelerate_port will be attempted 3 times before Ansible will fall back to ssh or paramiko + (depending on your default connection setting) to try and start the accelerate daemon remotely. + - Note, this value can be set to less than one second, however it is probably not a good idea to do so + unless you’re on a very fast and reliable LAN. If you’re connecting to systems over the internet, it may be necessary to increase this timeout. + env: [{name: ACCELERATE_CONNECT_TIMEOUT }] + ini: + - {key: accelerate_connect_timeout, section: accelerate} + value_type: float + vars: [] + yaml: {key: accelerate.accelerate_connect_timeout} + version_added: "1.4" +ACCELERATE_DAEMON_TIMEOUT: + default: 30 + desc: + - This setting controls the timeout for the accelerated daemon, as measured in minutes. The default daemon timeout is 30 minutes. + - Prior to 1.6, the timeout was hard-coded from the time of the daemon’s launch. + - For version 1.6+, the timeout is now based on the last activity to the daemon and is configurable via this option. + env: [{name: ACCELERATE_DAEMON_TIMEOUT}] + ini: + - {key: accelerate_daemon_timeout, section: accelerate} + value_type: integer + vars: [] + yaml: {key: accelerate.accelerate_daemon_timeout} + version_added: "1.6" +ACCELERATE_KEYS_DIR: + default: ~/.fireball.keys + desc: 'TODO: write it' + env: [{name: ACCELERATE_KEYS_DIR}] + ini: + - {key: accelerate_keys_dir, section: accelerate} + vars: [] + yaml: {key: accelerate.accelerate_keys_dir} +ACCELERATE_KEYS_DIR_PERMS: + default: '700' + desc: 'TODO: write it' + env: [{name: ACCELERATE_KEYS_DIR_PERMS}] + ini: + - {key: accelerate_keys_dir_perms, section: accelerate} + vars: [] + yaml: {key: accelerate.accelerate_keys_dir_perms} +ACCELERATE_KEYS_FILE_PERMS: + default: '600' + desc: 'TODO: write it' + env: [{name: ACCELERATE_KEYS_FILE_PERMS}] + ini: + - {key: accelerate_keys_file_perms, section: accelerate} + vars: [] + yaml: {key: accelerate.accelerate_keys_file_perms} +ACCELERATE_MULTI_KEY: + default: False + desc: 'TODO: write it' + env: [{name: ACCELERATE_MULTI_KEY}] + ini: + - {key: accelerate_multi_key, section: accelerate} + value_type: boolean + vars: [] + yaml: {key: accelerate.accelerate_multi_key} +ACCELERATE_PORT: + default: 5099 + desc: 'TODO: write it' + env: [{name: ACCELERATE_PORT}] + ini: + - {key: accelerate_port, section: accelerate} + value_type: integer + vars: [] + yaml: {key: accelerate.accelerate_port} +ACCELERATE_TIMEOUT: + default: 30 + desc: 'TODO: write it' + env: [{name: ACCELERATE_TIMEOUT}] + ini: + - {key: accelerate_timeout, section: accelerate} + value_type: integer + vars: [] + yaml: {key: accelerate.accelerate_timeout} +ALLOW_WORLD_READABLE_TMPFILES: + default: False + desc: 'TODO: write it' + env: [] + ini: + - {key: allow_world_readable_tmpfiles, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.allow_world_readable_tmpfiles} +ANSIBLE_COW_SELECTION: + default: default + desc: 'TODO: write it' + env: [{name: ANSIBLE_COW_SELECTION}] + ini: + - {key: cow_selection, section: defaults} + vars: [] + yaml: {key: defaults.cow_selection} +ANSIBLE_COW_WHITELIST: + default: ['bud-frogs', 'bunny', 'cheese', 'daemon', 'default', 'dragon', 'elephant-in-snake', 'elephant', 'eyes', 'hellokitty', 'kitty', 'luke-koala', 'meow', 'milk', 'moofasa', 'moose', 'ren', 'sheep', 'small', 'stegosaurus', 'stimpy', 'supermilker', 'three-eyes', 'turkey', 'turtle', 'tux', 'udder', 'vader-koala', 'vader', 'www'] + desc: 'TODO: write it' + env: [{name: ANSIBLE_COW_WHITELIST}] + ini: + - {key: cow_whitelist, section: defaults} + value_type: list + vars: [] + yaml: {key: defaults.cow_whitelist} +ANSIBLE_FORCE_COLOR: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_FORCE_COLOR}] + ini: + - {key: force_color, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.force_color} +ANSIBLE_NOCOLOR: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_NOCOLOR}] + ini: + - {key: nocolor, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.nocolor} +ANSIBLE_NOCOWS: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_NOCOWS}] + ini: + - {key: nocows, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.nocows} +ANSIBLE_SSH_ARGS: + default: -C -o ControlMaster=auto -o ControlPersist=60s + desc: 'TODO: write it' + env: [{name: ANSIBLE_SSH_ARGS}] + ini: + - {key: ssh_args, section: ssh_connection} + vars: [] + yaml: {key: ssh_connection.ssh_args} +ANSIBLE_SSH_CONTROL_PATH: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_SSH_CONTROL_PATH}] + ini: + - {key: control_path, section: ssh_connection} + vars: [] + yaml: {key: ssh_connection.control_path} +ANSIBLE_SSH_CONTROL_PATH_DIR: + default: ~/.ansible/cp + desc: 'TODO: write it' + env: [{name: ANSIBLE_SSH_CONTROL_PATH_DIR}] + ini: + - {key: control_path_dir, section: ssh_connection} + vars: [] + yaml: {key: ssh_connection.control_path_dir} +ANSIBLE_SSH_EXECUTABLE: + default: ssh + desc: 'TODO: write it' + env: [{name: ANSIBLE_SSH_EXECUTABLE}] + ini: + - {key: ssh_executable, section: ssh_connection} + vars: [] + yaml: {key: ssh_connection.ssh_executable} +ANSIBLE_SSH_PIPELINING: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_SSH_PIPELINING}] + ini: + - {key: pipelining, section: ssh_connection} + value_type: boolean + vars: [] + yaml: {key: ssh_connection.pipelining} +ANSIBLE_SSH_RETRIES: + default: 0 + desc: 'TODO: write it' + env: [{name: ANSIBLE_SSH_RETRIES}] + ini: + - {key: retries, section: ssh_connection} + value_type: integer + vars: [] + yaml: {key: ssh_connection.retries} +BECOME_ALLOW_SAME_USER: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_BECOME_ALLOW_SAME_USER}] + ini: + - {key: become_allow_same_user, section: privilege_escalation} + value_type: boolean + vars: [] + yaml: {key: privilege_escalation.become_allow_same_user} +CACHE_PLUGIN: + default: memory + desc: 'TODO: write it' + env: [{name: ANSIBLE_CACHE_PLUGIN}] + ini: + - {key: fact_caching, section: defaults} + vars: [] + yaml: {key: defaults.fact_caching} +CACHE_PLUGIN_CONNECTION: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_CACHE_PLUGIN_CONNECTION}] + ini: + - {key: fact_caching_connection, section: defaults} + vars: [] + yaml: {key: defaults.fact_caching_connection} +CACHE_PLUGIN_PREFIX: + default: ansible_facts + desc: 'TODO: write it' + env: [{name: ANSIBLE_CACHE_PLUGIN_PREFIX}] + ini: + - {key: fact_caching_prefix, section: defaults} + vars: [] + yaml: {key: defaults.fact_caching_prefix} +CACHE_PLUGIN_TIMEOUT: + default: 86400 + desc: 'TODO: write it' + env: [{name: ANSIBLE_CACHE_PLUGIN_TIMEOUT}] + ini: + - {key: fact_caching_timeout, section: defaults} + value_type: integer + vars: [] + yaml: {key: defaults.fact_caching_timeout} +COLOR_CHANGED: + default: yellow + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_CHANGED}] + ini: + - {key: changed, section: colors} + vars: [] + yaml: {key: colors.changed} +COLOR_DEBUG: + default: dark gray + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_DEBUG}] + ini: + - {key: debug, section: colors} + vars: [] + yaml: {key: colors.debug} +COLOR_DEPRECATE: + default: purple + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_DEPRECATE}] + ini: + - {key: deprecate, section: colors} + vars: [] + yaml: {key: colors.deprecate} +COLOR_DIFF_ADD: + default: green + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_DIFF_ADD}] + ini: + - {key: diff_add, section: colors} + vars: [] + yaml: {key: colors.diff_add} +COLOR_DIFF_LINES: + default: cyan + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_DIFF_LINES}] + ini: + - {key: diff_lines, section: colors} + vars: [] + yaml: {key: colors.diff_lines} +COLOR_DIFF_REMOVE: + default: red + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_DIFF_REMOVE}] + ini: + - {key: diff_remove, section: colors} + vars: [] + yaml: {key: colors.diff_remove} +COLOR_ERROR: + default: red + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_ERROR}] + ini: + - {key: error, section: colors} + vars: [] + yaml: {key: colors.error} +COLOR_HIGHLIGHT: + default: white + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_HIGHLIGHT}] + ini: + - {key: highlight, section: colors} + vars: [] + yaml: {key: colors.highlight} +COLOR_OK: + default: green + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_OK}] + ini: + - {key: ok, section: colors} + vars: [] + yaml: {key: colors.ok} +COLOR_SKIP: + default: cyan + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_SKIP}] + ini: + - {key: skip, section: colors} + vars: [] + yaml: {key: colors.skip} +COLOR_UNREACHABLE: + default: bright red + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_UNREACHABLE}] + ini: + - {key: unreachable, section: colors} + vars: [] + yaml: {key: colors.unreachable} +COLOR_VERBOSE: + default: blue + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_VERBOSE}] + ini: + - {key: verbose, section: colors} + vars: [] + yaml: {key: colors.verbose} +COLOR_WARN: + default: bright purple + desc: 'TODO: write it' + env: [{name: ANSIBLE_COLOR_WARN}] + ini: + - {key: warn, section: colors} + vars: [] + yaml: {key: colors.warn} +COMMAND_WARNINGS: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_COMMAND_WARNINGS}] + ini: + - {key: command_warnings, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.command_warnings} +DEFAULT_ACTION_PLUGIN_PATH: + default: ~/.ansible/plugins/action:/usr/share/ansible/plugins/action + desc: 'TODO: write it' + env: [{name: ANSIBLE_ACTION_PLUGINS}] + ini: + - {key: action_plugins, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.action_plugins} +DEFAULT_ALLOW_UNSAFE_LOOKUPS: + default: False + desc: 'TODO: write it' + env: [] + ini: + - {key: allow_unsafe_lookups, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.allow_unsafe_lookups} +DEFAULT_ASK_PASS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_ASK_PASS}] + ini: + - {key: ask_pass, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.ask_pass} +DEFAULT_ASK_SUDO_PASS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_ASK_SUDO_PASS}] + ini: + - {key: ask_sudo_pass, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.ask_sudo_pass} +DEFAULT_ASK_SU_PASS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_ASK_SU_PASS}] + ini: + - {key: ask_su_pass, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.ask_su_pass} +DEFAULT_ASK_VAULT_PASS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_ASK_VAULT_PASS}] + ini: + - {key: ask_vault_pass, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.ask_vault_pass} +DEFAULT_BECOME: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_BECOME}] + ini: + - {key: become, section: privilege_escalation} + value_type: boolean + vars: [] + yaml: {key: privilege_escalation.become} +DEFAULT_BECOME_ASK_PASS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_BECOME_ASK_PASS}] + ini: + - {key: become_ask_pass, section: privilege_escalation} + value_type: boolean + vars: [] + yaml: {key: privilege_escalation.become_ask_pass} +DEFAULT_BECOME_EXE: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_BECOME_EXE}] + ini: + - {key: become_exe, section: privilege_escalation} + vars: [] + yaml: {key: privilege_escalation.become_exe} +DEFAULT_BECOME_FLAGS: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_BECOME_FLAGS}] + ini: + - {key: become_flags, section: privilege_escalation} + vars: [] + yaml: {key: privilege_escalation.become_flags} +DEFAULT_BECOME_METHOD: + default: 'sudo' + desc: + env: [{name: ANSIBLE_BECOME_METHOD}] + ini: + - {section: privilege_escalation, key: become_method} + vars: [] + yaml: {key: privilege_escalation.become_method} +DEFAULT_BECOME_USER: + default: root + desc: 'TODO: write it' + env: [{name: ANSIBLE_BECOME_USER}] + ini: + - {key: become_user, section: privilege_escalation} + vars: [] + yaml: {key: privilege_escalation.become_user} +DEFAULT_CACHE_PLUGIN_PATH: + default: ~/.ansible/plugins/cache:/usr/share/ansible/plugins/cache + desc: 'TODO: write it' + env: [{name: ANSIBLE_CACHE_PLUGINS}] + ini: + - {key: cache_plugins, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.cache_plugins} +DEFAULT_CALLABLE_WHITELIST: + default: [] + desc: 'TODO: write it' + env: [{name: ANSIBLE_CALLABLE_WHITELIST}] + ini: + - {key: callable_whitelist, section: defaults} + value_type: list + vars: [] + yaml: {key: defaults.callable_whitelist} +DEFAULT_CALLBACK_PLUGIN_PATH: + default: ~/.ansible/plugins/callback:/usr/share/ansible/plugins/callback + desc: 'TODO: write it' + env: [{name: ANSIBLE_CALLBACK_PLUGINS}] + ini: + - {key: callback_plugins, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.callback_plugins} +DEFAULT_CALLBACK_WHITELIST: + default: [] + desc: 'TODO: write it' + env: [{name: ANSIBLE_CALLBACK_WHITELIST}] + ini: + - {key: callback_whitelist, section: defaults} + value_type: list + vars: [] + yaml: {key: defaults.callback_whitelist} +DEFAULT_CONNECTION_PLUGIN_PATH: + default: ~/.ansible/plugins/connection:/usr/share/ansible/plugins/connection + desc: 'TODO: write it' + env: [{name: ANSIBLE_CONNECTION_PLUGINS}] + ini: + - {key: connection_plugins, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.connection_plugins} +DEFAULT_DEBUG: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_DEBUG}] + ini: + - {key: debug, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.debug} +DEFAULT_EXECUTABLE: + default: /bin/sh + desc: 'TODO: write it' + env: [{name: ANSIBLE_EXECUTABLE}] + ini: + - {key: executable, section: defaults} + vars: [] + yaml: {key: defaults.executable} +DEFAULT_FACT_PATH: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_FACT_PATH}] + ini: + - {key: fact_path, section: defaults} + value_type: path + vars: [] + yaml: {key: defaults.fact_path} +DEFAULT_FILTER_PLUGIN_PATH: + default: ~/.ansible/plugins/filter:/usr/share/ansible/plugins/filter + desc: 'TODO: write it' + env: [{name: ANSIBLE_FILTER_PLUGINS}] + ini: + - {key: filter_plugins, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.filter_plugins} +DEFAULT_FORCE_HANDLERS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_FORCE_HANDLERS}] + ini: + - {key: force_handlers, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.force_handlers} +DEFAULT_FORKS: + default: 5 + desc: 'TODO: write it' + env: [{name: ANSIBLE_FORKS}] + ini: + - {key: forks, section: defaults} + value_type: integer + vars: [] + yaml: {key: defaults.forks} +DEFAULT_GATHERING: + default: 'implicit' + desc: 'TODO: write it' + env: [{name: ANSIBLE_GATHERING}] + ini: + - key: gathering + section: defaults + vars: [] + yaml: {key: defaults.gathering} +DEFAULT_GATHER_SUBSET: + default: 'all' + desc: 'TODO: write it' + env: [{name: ANSIBLE_GATHER_SUBSET}] + ini: + - key: gather_subset + section: defaults + vars: [] + yaml: {key: defaults.gather_subset} +DEFAULT_GATHER_TIMEOUT: + default: 10 + desc: 'TODO: write it' + env: [{name: ANSIBLE_GATHER_TIMEOUT}] + ini: + - {key: gather_timeout, section: defaults} + value_type: integer + vars: [] + yaml: {key: defaults.gather_timeout} +DEFAULT_HANDLER_INCLUDES_STATIC: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_HANDLER_INCLUDES_STATIC}] + ini: + - {key: handler_includes_static, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.handler_includes_static} +DEFAULT_HASH_BEHAVIOUR: + default: replace + desc: 'TODO: write it' + env: [{name: ANSIBLE_HASH_BEHAVIOUR}] + ini: + - {key: hash_behaviour, section: defaults} + vars: [] + yaml: {key: defaults.hash_behaviour} +DEFAULT_HOST_LIST: + default: /etc/ansible/hosts + desc: 'TODO: write it' + env: [{name: ANSIBLE_INVENTORY}] + expand_relative_paths: True + ini: + - {key: inventory, section: defaults} + value_type: path + vars: [] + yaml: {key: defaults.inventory} +DEFAULT_INTERNAL_POLL_INTERVAL: + default: 0.001 + desc: 'TODO: write it' + env: [] + ini: + - {key: internal_poll_interval, section: defaults} + value_type: float + vars: [] + yaml: {key: defaults.internal_poll_interval} +DEFAULT_INVENTORY_PLUGIN_PATH: + default: ~/.ansible/plugins/inventory:/usr/share/ansible/plugins/inventory + desc: 'TODO: write it' + env: [{name: ANSIBLE_INVENTORY_PLUGINS}] + ini: + - {key: inventory_plugins, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.inventory_plugins} +DEFAULT_JINJA2_EXTENSIONS: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_JINJA2_EXTENSIONS}] + ini: + - {key: jinja2_extensions, section: defaults} + vars: [] + yaml: {key: defaults.jinja2_extensions} +DEFAULT_KEEP_REMOTE_FILES: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_KEEP_REMOTE_FILES}] + ini: + - {key: keep_remote_files, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.keep_remote_files} +DEFAULT_LIBVIRT_LXC_NOSECLABEL: + default: False + desc: 'TODO: write it' + env: [{name: LIBVIRT_LXC_NOSECLABEL}] + ini: + - {key: libvirt_lxc_noseclabel, section: selinux} + value_type: boolean + vars: [] + yaml: {key: selinux.libvirt_lxc_noseclabel} +DEFAULT_LOAD_CALLBACK_PLUGINS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_LOAD_CALLBACK_PLUGINS}] + ini: + - {key: bin_ansible_callbacks, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.bin_ansible_callbacks} +DEFAULT_LOCAL_TMP: + default: ~/.ansible/tmp + desc: 'TODO: write it' + env: [{name: ANSIBLE_LOCAL_TEMP}] + ini: + - {key: local_tmp, section: defaults} + value_type: tmppath + vars: [] + yaml: {key: defaults.local_tmp} +DEFAULT_LOG_PATH: + default: '' + desc: 'TODO: write it' + env: [{name: ANSIBLE_LOG_PATH}] + ini: + - {key: log_path, section: defaults} + value_type: path + vars: [] + yaml: {key: defaults.log_path} +DEFAULT_LOOKUP_PLUGIN_PATH: + default: ~/.ansible/plugins/lookup:/usr/share/ansible/plugins/lookup + desc: 'TODO: write it' + env: [{name: ANSIBLE_LOOKUP_PLUGINS}] + ini: + - {key: lookup_plugins, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.lookup_plugins} +DEFAULT_MANAGED_STR: + default: Ansible managed + desc: 'TODO: write it' + env: [] + ini: + - {key: ansible_managed, section: defaults} + vars: [] + yaml: {key: defaults.ansible_managed} +DEFAULT_MODULE_ARGS: + default: '' + desc: 'TODO: write it' + env: [{name: ANSIBLE_MODULE_ARGS}] + ini: + - {key: module_args, section: defaults} + vars: [] + yaml: {key: defaults.module_args} +DEFAULT_MODULE_COMPRESSION: + default: ZIP_DEFLATED + desc: 'TODO: write it' + env: [] + ini: + - {key: module_compression, section: defaults} + vars: [] + yaml: {key: defaults.module_compression} +DEFAULT_MODULE_LANG: + default: os.getenv('LANG', 'en_US.UTF-8') + desc: 'TODO: write it' + env: [{name: ANSIBLE_MODULE_LANG}] + ini: + - {key: module_lang, section: defaults} + vars: [] + yaml: {key: defaults.module_lang} +DEFAULT_MODULE_NAME: + default: command + desc: 'TODO: write it' + env: [] + ini: + - {key: module_name, section: defaults} + vars: [] + yaml: {key: defaults.module_name} +DEFAULT_MODULE_PATH: + default: ~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules + desc: 'TODO: write it' + env: [{name: ANSIBLE_LIBRARY}] + ini: + - {key: library, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.library} +DEFAULT_MODULE_SET_LOCALE: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_MODULE_SET_LOCALE}] + ini: + - {key: module_set_locale, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.module_set_locale} +DEFAULT_MODULE_UTILS_PATH: + default: ~/.ansible/plugins/module_utils:/usr/share/ansible/plugins/module_utils + desc: 'TODO: write it' + env: [{name: ANSIBLE_MODULE_UTILS}] + ini: + - {key: module_utils, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.module_utils} +DEFAULT_NO_LOG: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_NO_LOG}] + ini: + - {key: no_log, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.no_log} +DEFAULT_NO_TARGET_SYSLOG: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_NO_TARGET_SYSLOG}] + ini: + - {key: no_target_syslog, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.no_target_syslog} +DEFAULT_NULL_REPRESENTATION: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_NULL_REPRESENTATION}] + ini: + - {key: null_representation, section: defaults} + value_type: none + vars: [] + yaml: {key: defaults.null_representation} +DEFAULT_POLL_INTERVAL: + default: 15 + desc: 'TODO: write it' + env: [{name: ANSIBLE_POLL_INTERVAL}] + ini: + - {key: poll_interval, section: defaults} + value_type: integer + vars: [] + yaml: {key: defaults.poll_interval} +DEFAULT_PRIVATE_KEY_FILE: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_PRIVATE_KEY_FILE}] + ini: + - {key: private_key_file, section: defaults} + value_type: path + vars: [] + yaml: {key: defaults.private_key_file} +DEFAULT_PRIVATE_ROLE_VARS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_PRIVATE_ROLE_VARS}] + ini: + - {key: private_role_vars, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.private_role_vars} +DEFAULT_REMOTE_PORT: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_REMOTE_PORT}] + ini: + - {key: remote_port, section: defaults} + value_type: integer + vars: [] + yaml: {key: defaults.remote_port} +DEFAULT_REMOTE_TMP: + default: ~/.ansible/tmp + desc: 'TODO: write it' + env: [{name: ANSIBLE_REMOTE_TEMP}] + ini: + - {key: remote_tmp, section: defaults} + vars: [] + yaml: {key: defaults.remote_tmp} +DEFAULT_REMOTE_USER: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_REMOTE_USER}] + ini: + - {key: remote_user, section: defaults} + vars: [] + yaml: {key: defaults.remote_user} +DEFAULT_ROLES_PATH: + default: ~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles + desc: 'TODO: write it' + env: [{name: ANSIBLE_ROLES_PATH}] + expand_relative_paths: True + ini: + - {key: roles_path, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.roles_path} +DEFAULT_SCP_IF_SSH: + default: smart + desc: 'TODO: write it' + env: [{name: ANSIBLE_SCP_IF_SSH}] + ini: + - {key: scp_if_ssh, section: ssh_connection} + vars: [] + yaml: {key: ssh_connection.scp_if_ssh} +DEFAULT_SELINUX_SPECIAL_FS: + default: fuse, nfs, vboxsf, ramfs, 9p + desc: 'TODO: write it' + env: [] + ini: + - {key: special_context_filesystems, section: selinux} + value_type: list + vars: [] + yaml: {key: selinux.special_context_filesystems} +DEFAULT_SFTP_BATCH_MODE: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_SFTP_BATCH_MODE}] + ini: + - {key: sftp_batch_mode, section: ssh_connection} + value_type: boolean + vars: [] + yaml: {key: ssh_connection.sftp_batch_mode} +DEFAULT_SQUASH_ACTIONS: + default: apk, apt, dnf, homebrew, openbsd_pkg, pacman, pkgng, yum, zypper + desc: 'TODO: write it' + env: [{name: ANSIBLE_SQUASH_ACTIONS}] + ini: + - {key: squash_actions, section: defaults} + value_type: list + vars: [] + yaml: {key: defaults.squash_actions} +DEFAULT_SSH_TRANSFER_METHOD: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_SSH_TRANSFER_METHOD}] + ini: + - {key: transfer_method, section: ssh_connection} + vars: [] + yaml: {key: ssh_connection.transfer_method} +DEFAULT_STDOUT_CALLBACK: + default: default + desc: 'TODO: write it' + env: [{name: ANSIBLE_STDOUT_CALLBACK}] + ini: + - {key: stdout_callback, section: defaults} + vars: [] + yaml: {key: defaults.stdout_callback} +DEFAULT_STRATEGY: + default: linear + desc: 'TODO: write it' + env: [{name: ANSIBLE_STRATEGY}] + ini: + - {key: strategy, section: defaults} + vars: [] + yaml: {key: defaults.strategy} +DEFAULT_STRATEGY_PLUGIN_PATH: + default: ~/.ansible/plugins/strategy:/usr/share/ansible/plugins/strategy + desc: 'TODO: write it' + env: [{name: ANSIBLE_STRATEGY_PLUGINS}] + ini: + - {key: strategy_plugins, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.strategy_plugins} +DEFAULT_SU: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_SU}] + ini: + - {key: su, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.su} +DEFAULT_SUDO: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_SUDO}] + ini: + - {key: sudo, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.sudo} +DEFAULT_SUDO_EXE: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_SUDO_EXE}] + ini: + - {key: sudo_exe, section: defaults} + vars: [] + yaml: {key: defaults.sudo_exe} +DEFAULT_SUDO_FLAGS: + default: -H -S -n + desc: 'TODO: write it' + env: [{name: ANSIBLE_SUDO_FLAGS}] + ini: + - {key: sudo_flags, section: defaults} + vars: [] + yaml: {key: defaults.sudo_flags} +DEFAULT_SUDO_USER: + default: root + desc: 'TODO: write it' + env: [{name: ANSIBLE_SUDO_USER}] + ini: + - {key: sudo_user, section: defaults} + vars: [] + yaml: {key: defaults.sudo_user} +DEFAULT_SU_EXE: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_SU_EXE}] + ini: + - {key: su_exe, section: defaults} + vars: [] + yaml: {key: defaults.su_exe} +DEFAULT_SU_FLAGS: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_SU_FLAGS}] + ini: + - {key: su_flags, section: defaults} + vars: [] + yaml: {key: defaults.su_flags} +DEFAULT_SU_USER: + default: root + desc: 'TODO: write it' + env: [{name: ANSIBLE_SU_USER}] + ini: + - {key: su_user, section: defaults} + vars: [] + yaml: {key: defaults.su_user} +DEFAULT_SYSLOG_FACILITY: + default: LOG_USER + desc: 'TODO: write it' + env: [{name: ANSIBLE_SYSLOG_FACILITY}] + ini: + - {key: syslog_facility, section: defaults} + vars: [] + yaml: {key: defaults.syslog_facility} +DEFAULT_TASK_INCLUDES_STATIC: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_TASK_INCLUDES_STATIC}] + ini: + - {key: task_includes_static, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.task_includes_static} +DEFAULT_TEST_PLUGIN_PATH: + default: ~/.ansible/plugins/test:/usr/share/ansible/plugins/test + desc: 'TODO: write it' + env: [{name: ANSIBLE_TEST_PLUGINS}] + ini: + - {key: test_plugins, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.test_plugins} +DEFAULT_TIMEOUT: + default: 10 + desc: 'TODO: write it' + env: [{name: ANSIBLE_TIMEOUT}] + ini: + - {key: timeout, section: defaults} + value_type: integer + vars: [] + yaml: {key: defaults.timeout} +DEFAULT_TRANSPORT: + default: smart + desc: 'TODO: write it' + env: [{name: ANSIBLE_TRANSPORT}] + ini: + - {key: transport, section: defaults} + vars: [] + yaml: {key: defaults.transport} +DEFAULT_UNDEFINED_VAR_BEHAVIOR: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_ERROR_ON_UNDEFINED_VARS}] + ini: + - {key: error_on_undefined_vars, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.error_on_undefined_vars} +DEFAULT_VARS_PLUGIN_PATH: + default: ~/.ansible/plugins/vars:/usr/share/ansible/plugins/vars + desc: 'TODO: write it' + env: [{name: ANSIBLE_VARS_PLUGINS}] + ini: + - {key: vars_plugins, section: defaults} + value_type: pathlist + vars: [] + yaml: {key: defaults.vars_plugins} +DEFAULT_VAR_COMPRESSION_LEVEL: + default: 0 + desc: 'TODO: write it' + env: [{name: ANSIBLE_VAR_COMPRESSION_LEVEL}] + ini: + - {key: var_compression_level, section: defaults} + value_type: integer + vars: [] + yaml: {key: defaults.var_compression_level} +DEFAULT_VAULT_PASSWORD_FILE: + default: ~ + desc: 'TODO: write it' + env: [{name: ANSIBLE_VAULT_PASSWORD_FILE}] + ini: + - {key: vault_password_file, section: defaults} + value_type: path + vars: [] + yaml: {key: defaults.vault_password_file} +DEFAULT_VERBOSITY: + default: 0 + desc: 'TODO: write it' + env: [{name: ANSIBLE_VERBOSITY}] + ini: + - {key: verbosity, section: defaults} + value_type: integer + vars: [] + yaml: {key: defaults.verbosity} +DEPRECATION_WARNINGS: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_DEPRECATION_WARNINGS}] + ini: + - {key: deprecation_warnings, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.deprecation_warnings} +DIFF_ALWAYS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_DIFF_ALWAYS}] + ini: + - {key: always, section: diff} + value_type: bool + vars: [] + yaml: {key: diff.always} +DIFF_CONTEXT: + default: 3 + desc: 'TODO: write it' + env: [{name: ANSIBLE_DIFF_CONTEXT}] + ini: + - {key: context, section: diff} + value_type: integer + vars: [] + yaml: {key: diff.context} +DISPLAY_ARGS_TO_STDOUT: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_DISPLAY_ARGS_TO_STDOUT}] + ini: + - {key: display_args_to_stdout, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.display_args_to_stdout} +DISPLAY_SKIPPED_HOSTS: + default: True + desc: 'TODO: write it' + env: [{name: DISPLAY_SKIPPED_HOSTS}] + ini: + - {key: display_skipped_hosts, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.display_skipped_hosts} +ERROR_ON_MISSING_HANDLER: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_ERROR_ON_MISSING_HANDLER}] + ini: + - {key: error_on_missing_handler, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.error_on_missing_handler} +GALAXY_IGNORE_CERTS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_GALAXY_IGNORE}] + ini: + - {key: ignore_certs, section: galaxy} + value_type: boolean + vars: [] + yaml: {key: galaxy.ignore_certs} +GALAXY_ROLE_SKELETON: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_GALAXY_ROLE_SKELETON}] + ini: + - {key: role_skeleton, section: galaxy} + value_type: path + vars: [] + yaml: {key: galaxy.role_skeleton} +GALAXY_ROLE_SKELETON_IGNORE: + default: [^.git$, ^.*/.git_keep$] + desc: 'TODO: write it' + env: [{name: ANSIBLE_GALAXY_ROLE_SKELETON_IGNORE}] + ini: + - {key: role_skeleton_ignore, section: galaxy} + value_type: list + vars: [] + yaml: {key: galaxy.role_skeleton_ignore} +GALAXY_SCMS: + default: git, hg + desc: 'TODO: write it' + env: [{name: ANSIBLE_GALAXY_SCMS}] + ini: + - {key: scms, section: galaxy} + value_type: list + vars: [] + yaml: {key: galaxy.scms} +GALAXY_SERVER: + default: https://galaxy.ansible.com + desc: 'TODO: write it' + env: [{name: ANSIBLE_GALAXY_SERVER}] + ini: + - {key: server, section: galaxy} + vars: [] + yaml: {key: galaxy.server} +HOST_KEY_CHECKING: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_HOST_KEY_CHECKING}] + ini: + - {key: host_key_checking, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.host_key_checking} +INVENTORY_ENABLED: + default: [host_list, script, yaml, ini] + desc: 'TODO: write it' + env: [{name: ANSIBLE_INVENTORY_ENABLED}] + ini: + - {key: inventory_enabled, section: defaults} + value_type: list + vars: [] + yaml: {key: defaults.inventory_enabled} +INVENTORY_IGNORE_EXTS: + default: ['.pyc', '.pyo', '.swp', '.bak', '~', '.rpm', '.md', '.txt', '.orig', '.ini', '.cfg', '.retry'] + desc: 'TODO: write it' + env: [{name: ANSIBLE_INVENTORY_IGNORE}] + ini: + - {key: inventory_ignore_extensions, section: defaults} + value_type: list + vars: [] + yaml: {key: defaults.inventory_ignore_extensions} +INVENTORY_IGNORE_PATTERNS: + default: [] + desc: 'TODO: write it' + env: [{name: ANSIBLE_INVENTORY_IGNORE_REGEX}] + ini: + - {key: inventory_ignore_patterns, section: defaults} + value_type: list + vars: [] + yaml: {key: defaults.inventory_ignore_patterns} +MAX_FILE_SIZE_FOR_DIFF: + default: 104448 + desc: 'TODO: write it' + env: [{name: ANSIBLE_MAX_DIFF_SIZE}] + ini: + - {key: max_diff_size, section: defaults} + value_type: integer + vars: [] + yaml: {key: defaults.max_diff_size} +MERGE_MULTIPLE_CLI_TAGS: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_MERGE_MULTIPLE_CLI_TAGS}] + ini: + - {key: merge_multiple_cli_tags, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.merge_multiple_cli_tags} +NAMESPACE_FACTS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_RESTRICT_FACTS}] + ini: + - {key: restrict_facts_namespace, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.restrict_facts_namespace} +NETWORK_GROUP_MODULES: + default: [eos, nxos, ios, iosxr, junos, ce, vyos, sros, dellos9, dellos10, dellos6] + desc: 'TODO: write it' + env: [{name: NETWORK_GROUP_MODULES}] + ini: + - {key: network_group_modules, section: defaults} + value_type: list + vars: [] + yaml: {key: defaults.network_group_modules} +PARAMIKO_HOST_KEY_AUTO_ADD: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_PARAMIKO_HOST_KEY_AUTO_ADD}] + ini: + - {key: host_key_auto_add, section: paramiko_connection} + value_type: boolean + vars: [] + yaml: {key: paramiko_connection.host_key_auto_add} +PARAMIKO_LOOK_FOR_KEYS: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_PARAMIKO_LOOK_FOR_KEYS}] + ini: + - {key: look_for_keys, section: paramiko_connection} + value_type: boolean + vars: [] + yaml: {key: paramiko_connection.look_for_keys} +PARAMIKO_PROXY_COMMAND: + default: + desc: 'TODO: write it' + env: [{name: ANSIBLE_PARAMIKO_PROXY_COMMAND}] + ini: + - {key: proxy_command, section: paramiko_connection} + vars: [] + yaml: {key: paramiko_connection.proxy_command} +PARAMIKO_PTY: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_PARAMIKO_PTY}] + ini: + - {key: pty, section: paramiko_connection} + value_type: boolean + vars: [] + yaml: {key: paramiko_connection.pty} +PARAMIKO_RECORD_HOST_KEYS: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_PARAMIKO_RECORD_HOST_KEYS}] + ini: + - {key: record_host_keys, section: paramiko_connection} + value_type: boolean + vars: [] + yaml: {key: paramiko_connection.record_host_keys} +PERSISTENT_CONNECT_INTERVAL: + default: 1 + desc: 'TODO: write it' + env: [{name: ANSIBLE_PERSISTENT_CONNECT_INTERVAL}] + ini: + - {key: connect_interval, section: persistent_connection} + value_type: integer + vars: [] + yaml: {key: persistent_connection.connect_interval} +PERSISTENT_CONNECT_RETRIES: + default: 30 + desc: 'TODO: write it' + env: [{name: ANSIBLE_PERSISTENT_CONNECT_RETRIES}] + ini: + - {key: connect_retries, section: persistent_connection} + value_type: integer + vars: [] + yaml: {key: persistent_connection.connect_retries} +PERSISTENT_CONNECT_TIMEOUT: + default: 30 + desc: 'TODO: write it' + env: [{name: ANSIBLE_PERSISTENT_CONNECT_TIMEOUT}] + ini: + - {key: connect_timeout, section: persistent_connection} + value_type: integer + vars: [] + yaml: {key: persistent_connection.connect_timeout} +RETRY_FILES_ENABLED: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_RETRY_FILES_ENABLED}] + ini: + - {key: retry_files_enabled, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.retry_files_enabled} +RETRY_FILES_SAVE_PATH: + default: ~ + desc: 'TODO: write it' + env: [{name: ANSIBLE_RETRY_FILES_SAVE_PATH}] + ini: + - {key: retry_files_save_path, section: defaults} + value_type: path + vars: [] + yaml: {key: defaults.retry_files_save_path} +SHOW_CUSTOM_STATS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_SHOW_CUSTOM_STATS}] + ini: + - {key: show_custom_stats, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.show_custom_stats} +STRING_TYPE_FILTERS: + default: [string, to_json, to_nice_json, to_yaml, ppretty, json] + desc: 'TODO: write it' + env: [{name: ANSIBLE_STRING_TYPE_FILTERS}] + ini: + - {key: dont_type_filters, section: jinja2} + value_type: list + vars: [] + yaml: {key: jinja2.dont_type_filters} +SYSTEM_WARNINGS: + default: True + desc: 'TODO: write it' + env: [{name: ANSIBLE_SYSTEM_WARNINGS}] + ini: + - {key: system_warnings, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.system_warnings} +USE_PERSISTENT_CONNECTIONS: + default: False + desc: 'TODO: write it' + env: [{name: ANSIBLE_USE_PERSISTENT_CONNECTIONS}] + ini: + - {key: use_persistent_connections, section: defaults} + value_type: boolean + vars: [] + yaml: {key: defaults.use_persistent_connections} +VARIABLE_PRECEDENCE: + default: [all_inventory, groups_inventory, all_plugins_inventory, all_plugins_play, groups_plugins_inventory, groups_plugins_play] + desc: 'TODO: write it' + env: [{name: ANSIBLE_PRECEDENCE}] + ini: + - {key: precedence, section: defaults} + value_type: list + vars: [] + yaml: {key: defaults.precedence} diff --git a/lib/ansible/config/manager.py b/lib/ansible/config/manager.py new file mode 100644 index 00000000000..28a29865e86 --- /dev/null +++ b/lib/ansible/config/manager.py @@ -0,0 +1,242 @@ +# (c) 2017, Ansible by Red Hat, inc +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import sys +import tempfile +import yaml + +from ansible.config.data import ConfigData, Setting +from ansible.errors import AnsibleOptionsError, AnsibleError +from ansible.module_utils.six import string_types +from ansible.module_utils.six.moves import configparser +from ansible.module_utils._text import to_text, to_bytes, to_native +from ansible.parsing.quoting import unquote +from ansible.utils.path import unfrackpath +from ansible.utils.path import makedirs_safe + + +def resolve_path(path): + + if '{{CWD}}' in path: # allow users to force CWD using 'magic' {{CWD}} + path = path.replace('{{CWD}}', os.getcwd()) + + return unfrackpath(path, follow=False) + +def get_ini_config(p, entries): + ''' returns the value of last ini entry found ''' + value = None + if p is not None: + for entry in entries: + try: + value = p.get(entry.get('section','defaults'), entry.get('key',''), raw=True) + except: + pass + + return value + + + +class ConfigManager(object): + + def __init__(self, conf_file=None): + + self.data = ConfigData() + + #FIXME: make dynamic? + bconfig_def = to_bytes('%s/data/config.yml' % os.path.dirname(__file__)) + if os.path.exists(bconfig_def): + with open(bconfig_def, 'rb') as config_def: + self.initial_defs = yaml.safe_load(config_def) + else: + raise AnsibleError("Missing base configuration definition file (bad install?): %s" % to_native(bconfig_def)) + + ftype = None + if conf_file is None: + # set config using ini + conf_file = self.find_ini_config_file() + ftype = 'ini' + else: + ext = os.path.splitext(conf_file)[-1] + if ext in ('.ini', '.cfg'): + ftype = 'ini' + elif ext in ('.yaml', '.yml'): + ftype = 'yaml' + else: + raise AnsibleOptionsError("Unsupported configuration file extension: \n{0}".format(ext)) + + self.parse_config(conf_file, ftype) + + def parse_config(self, cfile, ftype): + # TODO: take list of files with merge/nomerge + + parser = None + if ftype == 'ini': + parser = configparser.ConfigParser() + try: + parser.read(cfile) + except configparser.Error as e: + raise AnsibleOptionsError("Error reading config file: \n{0}".format(e)) + elif ftype == 'yaml': + with open(cfile, 'rb') as config_stream: + parser = yaml.safe_load(config_stream) + else: + raise AnsibleOptionsError("Unsupported configuration file type: \n{0}".format(ftype)) + + self.update_config(cfile, self.initial_defs, parser, ftype) + + def update_config(self, configfile, defs, parser, ftype): + + # update the constant for config file + self.data.update_setting(Setting('CONFIG_FILE', configfile, '')) + + origin = None + # env and config defs can have several entries, ordered in list from lowest to highest precedence + for config in self.initial_defs: + + value = None + # env vars are highest precedence + if defs[config].get('env'): + try: + for env_var in defs[config]['env']: + env_value = os.environ.get(env_var.get('name'), None) + if env_value is not None: # only set if env var is defined + value = env_value + origin = 'env: %s' % env_var.get('name') + except: + sys.stderr.write("Error while loading environment configs for %s\n" % config) + + # try config file entries next + if value is None and defs[config].get(ftype): + if ftype == 'ini': + # load from ini config + try: + value = get_ini_config(parser, defs[config]['ini']) + origin = configfile + except Exception as e: + sys.stderr.write("Error while loading ini config %s: %s" % (configfile, str(e))) + elif ftype == 'yaml': + # FIXME: break down key from defs (. notation???) + key = 'name' + value = parser.get(key) + origin = configfile + + # set default if we got here w/o a value + if value is None: + value = defs[config].get('default') + origin = 'default' + + # ensure correct type + try: + value = self.ensure_type(value, defs[config].get('value_type')) + except: + sys.stderr.write("Unable to set correct type for %s, skipping" % config) + continue + + # set the constant + self.data.update_setting(Setting(config, value, origin)) + + + def find_ini_config_file(self): + ''' Load Config File order(first found is used): ENV, CWD, HOME, /etc/ansible ''' + + path0 = os.getenv("ANSIBLE_CONFIG", None) + if path0 is not None: + path0 = unfrackpath(path0, follow=False) + if os.path.isdir(path0): + path0 += "/ansible.cfg" + try: + path1 = os.getcwd() + "/ansible.cfg" + except OSError: + path1 = None + path2 = unfrackpath("~/.ansible.cfg", follow=False) + path3 = "/etc/ansible/ansible.cfg" + + for path in [path0, path1, path2, path3]: + if path is not None and os.path.exists(path): + break + else: + path = None + + return path + + def make_boolean(self, value): + ret = value + if not isinstance(value, bool): + if value is None: + ret = False + ret = (to_text(value).lower() in self.data.BOOL_TRUE) + return ret + + def ensure_type(self, value, value_type): + ''' return a configuration variable with casting + :arg value: The value to ensure correct typing of + :kwarg value_type: The type of the value. This can be any of the following strings: + :boolean: sets the value to a True or False value + :integer: Sets the value to an integer or raises a ValueType error + :float: Sets the value to a float or raises a ValueType error + :list: Treats the value as a comma separated list. Split the value + and return it as a python list. + :none: Sets the value to None + :path: Expands any environment variables and tilde's in the value. + :tmp_path: Create a unique temporary directory inside of the directory + specified by value and return its path. + :pathlist: Treat the value as a typical PATH string. (On POSIX, this + means colon separated strings.) Split the value and then expand + each part for environment variables and tildes. + ''' + if value_type == 'boolean': + value = self.make_boolean(value) + + elif value: + if value_type == 'integer': + value = int(value) + + elif value_type == 'float': + value = float(value) + + elif value_type == 'list': + if isinstance(value, string_types): + value = [x.strip() for x in value.split(',')] + + elif value_type == 'none': + if value == "None": + value = None + + elif value_type == 'path': + value = resolve_path(value) + + elif value_type == 'tmppath': + value = resolve_path(value) + if not os.path.exists(value): + makedirs_safe(value, 0o700) + prefix = 'ansible-local-%s' % os.getpid() + value = tempfile.mkdtemp(prefix=prefix, dir=value) + + elif value_type == 'pathlist': + if isinstance(value, string_types): + value = [resolve_path(x) for x in value.split(os.pathsep)] + + elif isinstance(value, string_types): + value = unquote(value) + + return to_text(value, errors='surrogate_or_strict', nonstring='passthru') + diff --git a/lib/ansible/constants.py b/lib/ansible/constants.py index fe01ed6ff79..a9b810712a3 100644 --- a/lib/ansible/constants.py +++ b/lib/ansible/constants.py @@ -19,441 +19,40 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os -import tempfile from string import ascii_letters, digits -from ansible.errors import AnsibleOptionsError -from ansible.module_utils.six import string_types -from ansible.module_utils.six.moves import configparser from ansible.module_utils._text import to_text -from ansible.parsing.quoting import unquote -from ansible.utils.path import makedirs_safe +from ansible.config.manager import ConfigManager -BOOL_TRUE = frozenset(["true", "t", "y", "1", "yes", "on"]) +config = ConfigManager() +# Generate constants from config +for setting in config.data.get_settings(): + vars()[setting.name] = setting.value def mk_boolean(value): - ret = value - if not isinstance(value, bool): - if value is None: - ret = False - ret = (str(value).lower() in BOOL_TRUE) - return ret + ''' moved ''' + return config.make_boolean(value) -def shell_expand(path, expand_relative_paths=False): - ''' - shell_expand is needed as os.path.expanduser does not work - when path is None, which is the default for ANSIBLE_PRIVATE_KEY_FILE - ''' - if path: - path = os.path.expanduser(os.path.expandvars(path)) - if expand_relative_paths and not path.startswith('/'): - # paths are always 'relative' to the config? - if 'CONFIG_FILE' in globals(): - CFGDIR = os.path.dirname(CONFIG_FILE) - path = os.path.join(CFGDIR, path) - path = os.path.abspath(path) - return path +### CONSTANTS ### yes, actual ones - -def get_config(p, section, key, env_var, default, value_type=None, expand_relative_paths=False): - ''' return a configuration variable with casting - - :arg p: A ConfigParser object to look for the configuration in - :arg section: A section of the ini config that should be examined for this section. - :arg key: The config key to get this config from - :arg env_var: An Environment variable to check for the config var. If - this is set to None then no environment variable will be used. - :arg default: A default value to assign to the config var if nothing else sets it. - :kwarg value_type: The type of the value. This can be any of the following strings: - :boolean: sets the value to a True or False value - :integer: Sets the value to an integer or raises a ValueType error - :float: Sets the value to a float or raises a ValueType error - :list: Treats the value as a comma separated list. Split the value - and return it as a python list. - :none: Sets the value to None - :path: Expands any environment variables and tilde's in the value. - :tmp_path: Create a unique temporary directory inside of the directory - specified by value and return its path. - :pathlist: Treat the value as a typical PATH string. (On POSIX, this - means colon separated strings.) Split the value and then expand - each part for environment variables and tildes. - :kwarg expand_relative_paths: for pathlist and path types, if this is set - to True then also change any relative paths into absolute paths. The - default is False. - ''' - value = _get_config(p, section, key, env_var, default) - if value_type == 'boolean': - value = mk_boolean(value) - - elif value: - if value_type == 'integer': - value = int(value) - - elif value_type == 'float': - value = float(value) - - elif value_type == 'list': - if isinstance(value, string_types): - value = [x.strip() for x in value.split(',')] - - elif value_type == 'none': - if value == "None": - value = None - - elif value_type == 'path': - value = shell_expand(value, expand_relative_paths=expand_relative_paths) - - elif value_type == 'tmppath': - value = shell_expand(value) - if not os.path.exists(value): - makedirs_safe(value, 0o700) - prefix = 'ansible-local-%s' % os.getpid() - value = tempfile.mkdtemp(prefix=prefix, dir=value) - - elif value_type == 'pathlist': - if isinstance(value, string_types): - value = [shell_expand(x, expand_relative_paths=expand_relative_paths) for x in value.split(os.pathsep)] - - elif isinstance(value, string_types): - value = unquote(value) - - return to_text(value, errors='surrogate_or_strict', nonstring='passthru') - - -def _get_config(p, section, key, env_var, default): - ''' helper function for get_config ''' - value = default - - if p is not None: - try: - value = p.get(section, key, raw=True) - except: - pass - - if env_var is not None: - env_value = os.environ.get(env_var, None) - if env_value is not None: - value = env_value - - return to_text(value, errors='surrogate_or_strict', nonstring='passthru') - - -def load_config_file(): - ''' Load Config File order(first found is used): ENV, CWD, HOME, /etc/ansible ''' - - p = configparser.ConfigParser() - - path0 = os.getenv("ANSIBLE_CONFIG", None) - if path0 is not None: - path0 = os.path.expanduser(path0) - if os.path.isdir(path0): - path0 += "/ansible.cfg" - try: - path1 = os.getcwd() + "/ansible.cfg" - except OSError: - path1 = None - path2 = os.path.expanduser("~/.ansible.cfg") - path3 = "/etc/ansible/ansible.cfg" - - for path in [path0, path1, path2, path3]: - if path is not None and os.path.exists(path): - try: - p.read(path) - except configparser.Error as e: - raise AnsibleOptionsError("Error reading config file: \n{0}".format(e)) - return p, path - return None, '' - - -p, CONFIG_FILE = load_config_file() - -# non configurable but used as defaults BLACKLIST_EXTS = ('.pyc', '.pyo', '.swp', '.bak', '~', '.rpm', '.md', '.txt') -# the default whitelist for cow stencils -DEFAULT_COW_WHITELIST = ['bud-frogs', 'bunny', 'cheese', 'daemon', 'default', 'dragon', 'elephant-in-snake', 'elephant', - 'eyes', 'hellokitty', 'kitty', 'luke-koala', 'meow', 'milk', 'moofasa', 'moose', 'ren', 'sheep', - 'small', 'stegosaurus', 'stimpy', 'supermilker', 'three-eyes', 'turkey', 'turtle', 'tux', 'udder', - 'vader-koala', 'vader', 'www'] - -# sections in config file -DEFAULTS = 'defaults' - -# DEPRECATED VARS # FIXME: add deprecation warning when these get set -# none left now - -# DEPRECATED FEATURE TOGGLES: these will eventually be removed as it becomes the standard - -# If --tags or --skip-tags is given multiple times on the CLI and this is True, merge the lists of tags together. -# If False, let the last argument overwrite any previous ones. -# Behaviour is overwrite through 2.2. 2.3 overwrites but prints deprecation. 2.4 the default is to merge. -MERGE_MULTIPLE_CLI_TAGS = get_config(p, DEFAULTS, 'merge_multiple_cli_tags', 'ANSIBLE_MERGE_MULTIPLE_CLI_TAGS', True, value_type='boolean') - -# Controls which 'precedence path' to take, remove when decide on which! -SOURCE_OVER_GROUPS = get_config(p, 'vars', 'source_over_groups', 'ANSIBLE_SOURCE_OVER_GROUPS', True, value_type='boolean') - -# GENERALLY CONFIGURABLE THINGS #### -DEFAULT_DEBUG = get_config(p, DEFAULTS, 'debug', 'ANSIBLE_DEBUG', False, value_type='boolean') -DEFAULT_VERBOSITY = get_config(p, DEFAULTS, 'verbosity', 'ANSIBLE_VERBOSITY', 0, value_type='integer') -DEFAULT_ROLES_PATH = get_config(p, DEFAULTS, 'roles_path', 'ANSIBLE_ROLES_PATH', - '~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles', value_type='pathlist', expand_relative_paths=True) -DEFAULT_REMOTE_TMP = get_config(p, DEFAULTS, 'remote_tmp', 'ANSIBLE_REMOTE_TEMP', '~/.ansible/tmp') -DEFAULT_LOCAL_TMP = get_config(p, DEFAULTS, 'local_tmp', 'ANSIBLE_LOCAL_TEMP', '~/.ansible/tmp', value_type='tmppath') -DEFAULT_MODULE_NAME = get_config(p, DEFAULTS, 'module_name', None, 'command') -DEFAULT_FACT_PATH = get_config(p, DEFAULTS, 'fact_path', 'ANSIBLE_FACT_PATH', None, value_type='path') -DEFAULT_FORKS = get_config(p, DEFAULTS, 'forks', 'ANSIBLE_FORKS', 5, value_type='integer') -DEFAULT_MODULE_ARGS = get_config(p, DEFAULTS, 'module_args', 'ANSIBLE_MODULE_ARGS', '') -DEFAULT_MODULE_LANG = get_config(p, DEFAULTS, 'module_lang', 'ANSIBLE_MODULE_LANG', os.getenv('LANG', 'en_US.UTF-8')) -DEFAULT_MODULE_SET_LOCALE = get_config(p, DEFAULTS, 'module_set_locale', 'ANSIBLE_MODULE_SET_LOCALE', False, value_type='boolean') -DEFAULT_MODULE_COMPRESSION = get_config(p, DEFAULTS, 'module_compression', None, 'ZIP_DEFLATED') -DEFAULT_TIMEOUT = get_config(p, DEFAULTS, 'timeout', 'ANSIBLE_TIMEOUT', 10, value_type='integer') -DEFAULT_POLL_INTERVAL = get_config(p, DEFAULTS, 'poll_interval', 'ANSIBLE_POLL_INTERVAL', 15, value_type='integer') -DEFAULT_REMOTE_USER = get_config(p, DEFAULTS, 'remote_user', 'ANSIBLE_REMOTE_USER', None) -DEFAULT_ASK_PASS = get_config(p, DEFAULTS, 'ask_pass', 'ANSIBLE_ASK_PASS', False, value_type='boolean') -DEFAULT_PRIVATE_KEY_FILE = get_config(p, DEFAULTS, 'private_key_file', 'ANSIBLE_PRIVATE_KEY_FILE', None, value_type='path') -DEFAULT_REMOTE_PORT = get_config(p, DEFAULTS, 'remote_port', 'ANSIBLE_REMOTE_PORT', None, value_type='integer') -DEFAULT_ASK_VAULT_PASS = get_config(p, DEFAULTS, 'ask_vault_pass', 'ANSIBLE_ASK_VAULT_PASS', False, value_type='boolean') -DEFAULT_VAULT_PASSWORD_FILE = get_config(p, DEFAULTS, 'vault_password_file', 'ANSIBLE_VAULT_PASSWORD_FILE', None, value_type='path') -DEFAULT_TRANSPORT = get_config(p, DEFAULTS, 'transport', 'ANSIBLE_TRANSPORT', 'smart') -DEFAULT_SCP_IF_SSH = get_config(p, 'ssh_connection', 'scp_if_ssh', 'ANSIBLE_SCP_IF_SSH', 'smart') -DEFAULT_SFTP_BATCH_MODE = get_config(p, 'ssh_connection', 'sftp_batch_mode', 'ANSIBLE_SFTP_BATCH_MODE', True, value_type='boolean') -DEFAULT_SSH_TRANSFER_METHOD = get_config(p, 'ssh_connection', 'transfer_method', 'ANSIBLE_SSH_TRANSFER_METHOD', None) -DEFAULT_MANAGED_STR = get_config(p, DEFAULTS, 'ansible_managed', None, 'Ansible managed') -DEFAULT_SYSLOG_FACILITY = get_config(p, DEFAULTS, 'syslog_facility', 'ANSIBLE_SYSLOG_FACILITY', 'LOG_USER') -DEFAULT_KEEP_REMOTE_FILES = get_config(p, DEFAULTS, 'keep_remote_files', 'ANSIBLE_KEEP_REMOTE_FILES', False, value_type='boolean') -DEFAULT_HASH_BEHAVIOUR = get_config(p, DEFAULTS, 'hash_behaviour', 'ANSIBLE_HASH_BEHAVIOUR', 'replace') -DEFAULT_PRIVATE_ROLE_VARS = get_config(p, DEFAULTS, 'private_role_vars', 'ANSIBLE_PRIVATE_ROLE_VARS', False, value_type='boolean') -DEFAULT_JINJA2_EXTENSIONS = get_config(p, DEFAULTS, 'jinja2_extensions', 'ANSIBLE_JINJA2_EXTENSIONS', None) -DEFAULT_EXECUTABLE = get_config(p, DEFAULTS, 'executable', 'ANSIBLE_EXECUTABLE', '/bin/sh') -DEFAULT_GATHERING = get_config(p, DEFAULTS, 'gathering', 'ANSIBLE_GATHERING', 'implicit').lower() -DEFAULT_GATHER_SUBSET = get_config(p, DEFAULTS, 'gather_subset', 'ANSIBLE_GATHER_SUBSET', 'all').lower() -DEFAULT_GATHER_TIMEOUT = get_config(p, DEFAULTS, 'gather_timeout', 'ANSIBLE_GATHER_TIMEOUT', 10, value_type='integer') -DEFAULT_LOG_PATH = get_config(p, DEFAULTS, 'log_path', 'ANSIBLE_LOG_PATH', '', value_type='path') -DEFAULT_FORCE_HANDLERS = get_config(p, DEFAULTS, 'force_handlers', 'ANSIBLE_FORCE_HANDLERS', False, value_type='boolean') -DEFAULT_VAR_COMPRESSION_LEVEL = get_config(p, DEFAULTS, 'var_compression_level', 'ANSIBLE_VAR_COMPRESSION_LEVEL', 0, value_type='integer') -DEFAULT_INTERNAL_POLL_INTERVAL = get_config(p, DEFAULTS, 'internal_poll_interval', None, 0.001, value_type='float') -DEFAULT_ALLOW_UNSAFE_LOOKUPS = get_config(p, DEFAULTS, 'allow_unsafe_lookups', None, False, value_type='boolean') -ERROR_ON_MISSING_HANDLER = get_config(p, DEFAULTS, 'error_on_missing_handler', 'ANSIBLE_ERROR_ON_MISSING_HANDLER', True, value_type='boolean') -SHOW_CUSTOM_STATS = get_config(p, DEFAULTS, 'show_custom_stats', 'ANSIBLE_SHOW_CUSTOM_STATS', False, value_type='boolean') -NAMESPACE_FACTS = get_config(p, DEFAULTS, 'restrict_facts_namespace', 'ANSIBLE_RESTRICT_FACTS', False, value_type='boolean') - -# Inventory -DEFAULT_HOST_LIST = get_config(p, DEFAULTS, 'inventory', 'ANSIBLE_INVENTORY', '/etc/ansible/hosts', value_type='path', expand_relative_paths=True) -INVENTORY_ENABLED = get_config(p, DEFAULTS, 'inventory_enabled', 'ANSIBLE_INVENTORY_ENABLED', - ['host_list', 'script', 'yaml', 'ini'], value_type='list') -INVENTORY_IGNORE_EXTS = get_config(p, DEFAULTS, 'inventory_ignore_extensions', 'ANSIBLE_INVENTORY_IGNORE', - BLACKLIST_EXTS + (".orig", ".ini", ".cfg", ".retry"), value_type='list') -INVENTORY_IGNORE_PATTERNS = get_config(p, DEFAULTS, 'inventory_ignore_patterns', 'ANSIBLE_INVENTORY_IGNORE_REGEX', [], value_type='list') -VARIABLE_PRECEDENCE = get_config(p, DEFAULTS, 'precedence', 'ANSIBLE_PRECEDENCE', - ['all_inventory', 'groups_inventory', 'all_plugins_inventory', 'all_plugins_play', - 'groups_plugins_inventory', 'groups_plugins_play'], - value_type='list') -# Static includes -DEFAULT_TASK_INCLUDES_STATIC = get_config(p, DEFAULTS, 'task_includes_static', 'ANSIBLE_TASK_INCLUDES_STATIC', False, value_type='boolean') -DEFAULT_HANDLER_INCLUDES_STATIC = get_config(p, DEFAULTS, 'handler_includes_static', 'ANSIBLE_HANDLER_INCLUDES_STATIC', False, value_type='boolean') - -# Disclosure -DEFAULT_NO_LOG = get_config(p, DEFAULTS, 'no_log', 'ANSIBLE_NO_LOG', False, value_type='boolean') -DEFAULT_NO_TARGET_SYSLOG = get_config(p, DEFAULTS, 'no_target_syslog', 'ANSIBLE_NO_TARGET_SYSLOG', False, value_type='boolean') -ALLOW_WORLD_READABLE_TMPFILES = get_config(p, DEFAULTS, 'allow_world_readable_tmpfiles', None, False, value_type='boolean') - -# Selinux -DEFAULT_SELINUX_SPECIAL_FS = get_config(p, 'selinux', 'special_context_filesystems', None, 'fuse, nfs, vboxsf, ramfs, 9p', value_type='list') -DEFAULT_LIBVIRT_LXC_NOSECLABEL = get_config(p, 'selinux', 'libvirt_lxc_noseclabel', 'LIBVIRT_LXC_NOSECLABEL', False, value_type='boolean') - -# PRIVILEGE ESCALATION -# Backwards Compat -DEFAULT_SU = get_config(p, DEFAULTS, 'su', 'ANSIBLE_SU', False, value_type='boolean') -DEFAULT_SU_USER = get_config(p, DEFAULTS, 'su_user', 'ANSIBLE_SU_USER', 'root') -DEFAULT_SU_EXE = get_config(p, DEFAULTS, 'su_exe', 'ANSIBLE_SU_EXE', None) -DEFAULT_SU_FLAGS = get_config(p, DEFAULTS, 'su_flags', 'ANSIBLE_SU_FLAGS', None) -DEFAULT_ASK_SU_PASS = get_config(p, DEFAULTS, 'ask_su_pass', 'ANSIBLE_ASK_SU_PASS', False, value_type='boolean') -DEFAULT_SUDO = get_config(p, DEFAULTS, 'sudo', 'ANSIBLE_SUDO', False, value_type='boolean') -DEFAULT_SUDO_USER = get_config(p, DEFAULTS, 'sudo_user', 'ANSIBLE_SUDO_USER', 'root') -DEFAULT_SUDO_EXE = get_config(p, DEFAULTS, 'sudo_exe', 'ANSIBLE_SUDO_EXE', None) -DEFAULT_SUDO_FLAGS = get_config(p, DEFAULTS, 'sudo_flags', 'ANSIBLE_SUDO_FLAGS', '-H -S -n') -DEFAULT_ASK_SUDO_PASS = get_config(p, DEFAULTS, 'ask_sudo_pass', 'ANSIBLE_ASK_SUDO_PASS', False, value_type='boolean') - -# Become -BECOME_ERROR_STRINGS = { - 'sudo': 'Sorry, try again.', - 'su': 'Authentication failure', - 'pbrun': '', - 'pfexec': '', - 'doas': 'Permission denied', - 'dzdo': '', - 'ksu': 'Password incorrect', - 'pmrun': 'You are not permitted to run this command' -} # FIXME: deal with i18n -BECOME_MISSING_STRINGS = { - 'sudo': 'sorry, a password is required to run sudo', - 'su': '', - 'pbrun': '', - 'pfexec': '', - 'doas': 'Authorization required', - 'dzdo': '', - 'ksu': 'No password given', - 'pmrun': '' -} # FIXME: deal with i18n BECOME_METHODS = ['sudo', 'su', 'pbrun', 'pfexec', 'doas', 'dzdo', 'ksu', 'runas', 'pmrun'] -BECOME_ALLOW_SAME_USER = get_config(p, 'privilege_escalation', 'become_allow_same_user', 'ANSIBLE_BECOME_ALLOW_SAME_USER', False, value_type='boolean') -DEFAULT_BECOME_METHOD = get_config(p, 'privilege_escalation', 'become_method', 'ANSIBLE_BECOME_METHOD', - 'sudo' if DEFAULT_SUDO else 'su' if DEFAULT_SU else 'sudo').lower() -DEFAULT_BECOME = get_config(p, 'privilege_escalation', 'become', 'ANSIBLE_BECOME', False, value_type='boolean') -DEFAULT_BECOME_USER = get_config(p, 'privilege_escalation', 'become_user', 'ANSIBLE_BECOME_USER', 'root') -DEFAULT_BECOME_EXE = get_config(p, 'privilege_escalation', 'become_exe', 'ANSIBLE_BECOME_EXE', None) -DEFAULT_BECOME_FLAGS = get_config(p, 'privilege_escalation', 'become_flags', 'ANSIBLE_BECOME_FLAGS', None) -DEFAULT_BECOME_ASK_PASS = get_config(p, 'privilege_escalation', 'become_ask_pass', 'ANSIBLE_BECOME_ASK_PASS', False, value_type='boolean') - -# PLUGINS - -# Modules that can optimize with_items loops into a single call. Currently -# these modules must (1) take a "name" or "pkg" parameter that is a list. If -# the module takes both, bad things could happen. -# In the future we should probably generalize this even further -# (mapping of param: squash field) -DEFAULT_SQUASH_ACTIONS = get_config(p, DEFAULTS, 'squash_actions', 'ANSIBLE_SQUASH_ACTIONS', - "apk, apt, dnf, homebrew, openbsd_pkg, pacman, pkgng, yum, zypper", value_type='list') -# paths - -DEFAULT_ACTION_PLUGIN_PATH = get_config(p, DEFAULTS, 'action_plugins', 'ANSIBLE_ACTION_PLUGINS', - '~/.ansible/plugins/action:/usr/share/ansible/plugins/action', value_type='pathlist') -DEFAULT_CACHE_PLUGIN_PATH = get_config(p, DEFAULTS, 'cache_plugins', 'ANSIBLE_CACHE_PLUGINS', - '~/.ansible/plugins/cache:/usr/share/ansible/plugins/cache', value_type='pathlist') -DEFAULT_CALLBACK_PLUGIN_PATH = get_config(p, DEFAULTS, 'callback_plugins', 'ANSIBLE_CALLBACK_PLUGINS', - '~/.ansible/plugins/callback:/usr/share/ansible/plugins/callback', value_type='pathlist') -DEFAULT_CONNECTION_PLUGIN_PATH = get_config(p, DEFAULTS, 'connection_plugins', 'ANSIBLE_CONNECTION_PLUGINS', - '~/.ansible/plugins/connection:/usr/share/ansible/plugins/connection', value_type='pathlist') -DEFAULT_LOOKUP_PLUGIN_PATH = get_config(p, DEFAULTS, 'lookup_plugins', 'ANSIBLE_LOOKUP_PLUGINS', - '~/.ansible/plugins/lookup:/usr/share/ansible/plugins/lookup', value_type='pathlist') -DEFAULT_MODULE_PATH = get_config(p, DEFAULTS, 'library', 'ANSIBLE_LIBRARY', - '~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules', value_type='pathlist') -DEFAULT_MODULE_UTILS_PATH = get_config(p, DEFAULTS, 'module_utils', 'ANSIBLE_MODULE_UTILS', - '~/.ansible/plugins/module_utils:/usr/share/ansible/plugins/module_utils', value_type='pathlist') -DEFAULT_INVENTORY_PLUGIN_PATH = get_config(p, DEFAULTS, 'inventory_plugins', 'ANSIBLE_INVENTORY_PLUGINS', - '~/.ansible/plugins/inventory:/usr/share/ansible/plugins/inventory', value_type='pathlist') -DEFAULT_VARS_PLUGIN_PATH = get_config(p, DEFAULTS, 'vars_plugins', 'ANSIBLE_VARS_PLUGINS', - '~/.ansible/plugins/vars:/usr/share/ansible/plugins/vars', value_type='pathlist') -DEFAULT_FILTER_PLUGIN_PATH = get_config(p, DEFAULTS, 'filter_plugins', 'ANSIBLE_FILTER_PLUGINS', - '~/.ansible/plugins/filter:/usr/share/ansible/plugins/filter', value_type='pathlist') -DEFAULT_TEST_PLUGIN_PATH = get_config(p, DEFAULTS, 'test_plugins', 'ANSIBLE_TEST_PLUGINS', - '~/.ansible/plugins/test:/usr/share/ansible/plugins/test', value_type='pathlist') -DEFAULT_STRATEGY_PLUGIN_PATH = get_config(p, DEFAULTS, 'strategy_plugins', 'ANSIBLE_STRATEGY_PLUGINS', - '~/.ansible/plugins/strategy:/usr/share/ansible/plugins/strategy', value_type='pathlist') - -NETWORK_GROUP_MODULES = get_config(p, DEFAULTS, 'network_group_modules', 'NETWORK_GROUP_MODULES', ['eos', 'nxos', 'ios', 'iosxr', 'junos', 'ce', - 'vyos', 'sros', 'dellos9', 'dellos10', 'dellos6'], - value_type='list') -DEFAULT_STRATEGY = get_config(p, DEFAULTS, 'strategy', 'ANSIBLE_STRATEGY', 'linear') -DEFAULT_STDOUT_CALLBACK = get_config(p, DEFAULTS, 'stdout_callback', 'ANSIBLE_STDOUT_CALLBACK', 'default') -# cache -CACHE_PLUGIN = get_config(p, DEFAULTS, 'fact_caching', 'ANSIBLE_CACHE_PLUGIN', 'memory') -CACHE_PLUGIN_CONNECTION = get_config(p, DEFAULTS, 'fact_caching_connection', 'ANSIBLE_CACHE_PLUGIN_CONNECTION', None) -CACHE_PLUGIN_PREFIX = get_config(p, DEFAULTS, 'fact_caching_prefix', 'ANSIBLE_CACHE_PLUGIN_PREFIX', 'ansible_facts') -CACHE_PLUGIN_TIMEOUT = get_config(p, DEFAULTS, 'fact_caching_timeout', 'ANSIBLE_CACHE_PLUGIN_TIMEOUT', 24 * 60 * 60, value_type='integer') - -# Display -ANSIBLE_FORCE_COLOR = get_config(p, DEFAULTS, 'force_color', 'ANSIBLE_FORCE_COLOR', None, value_type='boolean') -ANSIBLE_NOCOLOR = get_config(p, DEFAULTS, 'nocolor', 'ANSIBLE_NOCOLOR', None, value_type='boolean') -ANSIBLE_NOCOWS = get_config(p, DEFAULTS, 'nocows', 'ANSIBLE_NOCOWS', None, value_type='boolean') -ANSIBLE_COW_SELECTION = get_config(p, DEFAULTS, 'cow_selection', 'ANSIBLE_COW_SELECTION', 'default') -ANSIBLE_COW_WHITELIST = get_config(p, DEFAULTS, 'cow_whitelist', 'ANSIBLE_COW_WHITELIST', DEFAULT_COW_WHITELIST, value_type='list') -DISPLAY_SKIPPED_HOSTS = get_config(p, DEFAULTS, 'display_skipped_hosts', 'DISPLAY_SKIPPED_HOSTS', True, value_type='boolean') -DEFAULT_UNDEFINED_VAR_BEHAVIOR = get_config(p, DEFAULTS, 'error_on_undefined_vars', 'ANSIBLE_ERROR_ON_UNDEFINED_VARS', True, value_type='boolean') -HOST_KEY_CHECKING = get_config(p, DEFAULTS, 'host_key_checking', 'ANSIBLE_HOST_KEY_CHECKING', True, value_type='boolean') -SYSTEM_WARNINGS = get_config(p, DEFAULTS, 'system_warnings', 'ANSIBLE_SYSTEM_WARNINGS', True, value_type='boolean') -DEPRECATION_WARNINGS = get_config(p, DEFAULTS, 'deprecation_warnings', 'ANSIBLE_DEPRECATION_WARNINGS', True, value_type='boolean') -DEFAULT_CALLABLE_WHITELIST = get_config(p, DEFAULTS, 'callable_whitelist', 'ANSIBLE_CALLABLE_WHITELIST', [], value_type='list') -COMMAND_WARNINGS = get_config(p, DEFAULTS, 'command_warnings', 'ANSIBLE_COMMAND_WARNINGS', True, value_type='boolean') -DEFAULT_LOAD_CALLBACK_PLUGINS = get_config(p, DEFAULTS, 'bin_ansible_callbacks', 'ANSIBLE_LOAD_CALLBACK_PLUGINS', False, value_type='boolean') -DEFAULT_CALLBACK_WHITELIST = get_config(p, DEFAULTS, 'callback_whitelist', 'ANSIBLE_CALLBACK_WHITELIST', [], value_type='list') -RETRY_FILES_ENABLED = get_config(p, DEFAULTS, 'retry_files_enabled', 'ANSIBLE_RETRY_FILES_ENABLED', True, value_type='boolean') -RETRY_FILES_SAVE_PATH = get_config(p, DEFAULTS, 'retry_files_save_path', 'ANSIBLE_RETRY_FILES_SAVE_PATH', None, value_type='path') -DEFAULT_NULL_REPRESENTATION = get_config(p, DEFAULTS, 'null_representation', 'ANSIBLE_NULL_REPRESENTATION', None, value_type='none') -DISPLAY_ARGS_TO_STDOUT = get_config(p, DEFAULTS, 'display_args_to_stdout', 'ANSIBLE_DISPLAY_ARGS_TO_STDOUT', False, value_type='boolean') -MAX_FILE_SIZE_FOR_DIFF = get_config(p, DEFAULTS, 'max_diff_size', 'ANSIBLE_MAX_DIFF_SIZE', 1024 * 1024, value_type='integer') - -# CONNECTION RELATED -USE_PERSISTENT_CONNECTIONS = get_config(p, DEFAULTS, 'use_persistent_connections', 'ANSIBLE_USE_PERSISTENT_CONNECTIONS', False, value_type='boolean') -ANSIBLE_SSH_ARGS = get_config(p, 'ssh_connection', 'ssh_args', 'ANSIBLE_SSH_ARGS', '-C -o ControlMaster=auto -o ControlPersist=60s') -# WARNING: Someone might be tempted to switch this from percent-formatting -# to .format() in the future. be sure to read this: -# http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/ and understand -# that it may be a security risk to do so. -ANSIBLE_SSH_CONTROL_PATH = get_config(p, 'ssh_connection', 'control_path', 'ANSIBLE_SSH_CONTROL_PATH', None) -ANSIBLE_SSH_CONTROL_PATH_DIR = get_config(p, 'ssh_connection', 'control_path_dir', 'ANSIBLE_SSH_CONTROL_PATH_DIR', u'~/.ansible/cp') -ANSIBLE_SSH_PIPELINING = get_config(p, 'ssh_connection', 'pipelining', 'ANSIBLE_SSH_PIPELINING', False, value_type='boolean') -ANSIBLE_SSH_RETRIES = get_config(p, 'ssh_connection', 'retries', 'ANSIBLE_SSH_RETRIES', 0, value_type='integer') -ANSIBLE_SSH_EXECUTABLE = get_config(p, 'ssh_connection', 'ssh_executable', 'ANSIBLE_SSH_EXECUTABLE', 'ssh') -PARAMIKO_RECORD_HOST_KEYS = get_config(p, 'paramiko_connection', 'record_host_keys', 'ANSIBLE_PARAMIKO_RECORD_HOST_KEYS', True, value_type='boolean') -PARAMIKO_HOST_KEY_AUTO_ADD = get_config(p, 'paramiko_connection', 'host_key_auto_add', 'ANSIBLE_PARAMIKO_HOST_KEY_AUTO_ADD', False, value_type='boolean') -PARAMIKO_PROXY_COMMAND = get_config(p, 'paramiko_connection', 'proxy_command', 'ANSIBLE_PARAMIKO_PROXY_COMMAND', None) -PARAMIKO_LOOK_FOR_KEYS = get_config(p, 'paramiko_connection', 'look_for_keys', 'ANSIBLE_PARAMIKO_LOOK_FOR_KEYS', True, value_type='boolean') -PERSISTENT_CONNECT_TIMEOUT = get_config(p, 'persistent_connection', 'connect_timeout', 'ANSIBLE_PERSISTENT_CONNECT_TIMEOUT', 30, value_type='integer') -PERSISTENT_CONNECT_RETRIES = get_config(p, 'persistent_connection', 'connect_retries', 'ANSIBLE_PERSISTENT_CONNECT_RETRIES', 30, value_type='integer') -PERSISTENT_CONNECT_INTERVAL = get_config(p, 'persistent_connection', 'connect_interval', 'ANSIBLE_PERSISTENT_CONNECT_INTERVAL', 1, value_type='integer') -PERSISTENT_CONTROL_PATH_DIR = get_config(p, 'persistent_connection', 'control_path_dir', 'ANSIBLE_PERSISTENT_CONTROL_PATH_DIR', u'~/.ansible/pc') - -# obsolete -- will be formally removed -ACCELERATE_PORT = get_config(p, 'accelerate', 'accelerate_port', 'ACCELERATE_PORT', 5099, value_type='integer') -ACCELERATE_TIMEOUT = get_config(p, 'accelerate', 'accelerate_timeout', 'ACCELERATE_TIMEOUT', 30, value_type='integer') -ACCELERATE_CONNECT_TIMEOUT = get_config(p, 'accelerate', 'accelerate_connect_timeout', 'ACCELERATE_CONNECT_TIMEOUT', 1.0, value_type='float') -ACCELERATE_DAEMON_TIMEOUT = get_config(p, 'accelerate', 'accelerate_daemon_timeout', 'ACCELERATE_DAEMON_TIMEOUT', 30, value_type='integer') -ACCELERATE_KEYS_DIR = get_config(p, 'accelerate', 'accelerate_keys_dir', 'ACCELERATE_KEYS_DIR', '~/.fireball.keys') -ACCELERATE_KEYS_DIR_PERMS = get_config(p, 'accelerate', 'accelerate_keys_dir_perms', 'ACCELERATE_KEYS_DIR_PERMS', '700') -ACCELERATE_KEYS_FILE_PERMS = get_config(p, 'accelerate', 'accelerate_keys_file_perms', 'ACCELERATE_KEYS_FILE_PERMS', '600') -ACCELERATE_MULTI_KEY = get_config(p, 'accelerate', 'accelerate_multi_key', 'ACCELERATE_MULTI_KEY', False, value_type='boolean') -PARAMIKO_PTY = get_config(p, 'paramiko_connection', 'pty', 'ANSIBLE_PARAMIKO_PTY', True, value_type='boolean') - -# galaxy related -GALAXY_SERVER = get_config(p, 'galaxy', 'server', 'ANSIBLE_GALAXY_SERVER', 'https://galaxy.ansible.com') -GALAXY_IGNORE_CERTS = get_config(p, 'galaxy', 'ignore_certs', 'ANSIBLE_GALAXY_IGNORE', False, value_type='boolean') -# this can be configured to blacklist SCMS but cannot add new ones unless the code is also updated -GALAXY_SCMS = get_config(p, 'galaxy', 'scms', 'ANSIBLE_GALAXY_SCMS', 'git, hg', value_type='list') -GALAXY_ROLE_SKELETON = get_config(p, 'galaxy', 'role_skeleton', 'ANSIBLE_GALAXY_ROLE_SKELETON', None, value_type='path') -GALAXY_ROLE_SKELETON_IGNORE = get_config(p, 'galaxy', 'role_skeleton_ignore', 'ANSIBLE_GALAXY_ROLE_SKELETON_IGNORE', ['^.git$', '^.*/.git_keep$'], - value_type='list') - -STRING_TYPE_FILTERS = get_config(p, 'jinja2', 'dont_type_filters', 'ANSIBLE_STRING_TYPE_FILTERS', - ['string', 'to_json', 'to_nice_json', 'to_yaml', 'ppretty', 'json'], value_type='list') - -# colors -COLOR_HIGHLIGHT = get_config(p, 'colors', 'highlight', 'ANSIBLE_COLOR_HIGHLIGHT', 'white') -COLOR_VERBOSE = get_config(p, 'colors', 'verbose', 'ANSIBLE_COLOR_VERBOSE', 'blue') -COLOR_WARN = get_config(p, 'colors', 'warn', 'ANSIBLE_COLOR_WARN', 'bright purple') -COLOR_ERROR = get_config(p, 'colors', 'error', 'ANSIBLE_COLOR_ERROR', 'red') -COLOR_DEBUG = get_config(p, 'colors', 'debug', 'ANSIBLE_COLOR_DEBUG', 'dark gray') -COLOR_DEPRECATE = get_config(p, 'colors', 'deprecate', 'ANSIBLE_COLOR_DEPRECATE', 'purple') -COLOR_SKIP = get_config(p, 'colors', 'skip', 'ANSIBLE_COLOR_SKIP', 'cyan') -COLOR_UNREACHABLE = get_config(p, 'colors', 'unreachable', 'ANSIBLE_COLOR_UNREACHABLE', 'bright red') -COLOR_OK = get_config(p, 'colors', 'ok', 'ANSIBLE_COLOR_OK', 'green') -COLOR_CHANGED = get_config(p, 'colors', 'changed', 'ANSIBLE_COLOR_CHANGED', 'yellow') -COLOR_DIFF_ADD = get_config(p, 'colors', 'diff_add', 'ANSIBLE_COLOR_DIFF_ADD', 'green') -COLOR_DIFF_REMOVE = get_config(p, 'colors', 'diff_remove', 'ANSIBLE_COLOR_DIFF_REMOVE', 'red') -COLOR_DIFF_LINES = get_config(p, 'colors', 'diff_lines', 'ANSIBLE_COLOR_DIFF_LINES', 'cyan') - -# diff -DIFF_CONTEXT = get_config(p, 'diff', 'context', 'ANSIBLE_DIFF_CONTEXT', 3, value_type='integer') -DIFF_ALWAYS = get_config(p, 'diff', 'always', 'ANSIBLE_DIFF_ALWAYS', False, value_type='bool') - -# non-configurable things -MODULE_REQUIRE_ARGS = ['command', 'win_command', 'shell', 'win_shell', 'raw', 'script'] -MODULE_NO_JSON = ['command', 'win_command', 'shell', 'win_shell', 'raw'] +BOOL_TRUE = config.data.BOOL_TRUE DEFAULT_BECOME_PASS = None DEFAULT_PASSWORD_CHARS = to_text(ascii_letters + digits + ".,:-_", errors='strict') # characters included in auto-generated passwords DEFAULT_SUDO_PASS = None DEFAULT_REMOTE_PASS = None DEFAULT_SUBSET = None DEFAULT_SU_PASS = None +IGNORE_FILES = ["COPYING", "CONTRIBUTING", "LICENSE", "README", "VERSION", "GUIDELINES"] # ignore during module search +INTERNAL_RESULT_KEYS = ['add_host', 'add_group'] +LOCALHOST = frozenset(['127.0.0.1', 'localhost', '::1']) +MODULE_REQUIRE_ARGS = ['command', 'win_command', 'shell', 'win_shell', 'raw', 'script'] +MODULE_NO_JSON = ['command', 'win_command', 'shell', 'win_shell', 'raw'] +RESTRICTED_RESULT_KEYS = ['ansible_rsync_path', 'ansible_playbook_python'] +TREE_DIR = None VAULT_VERSION_MIN = 1.0 VAULT_VERSION_MAX = 1.0 -TREE_DIR = None -LOCALHOST = frozenset(['127.0.0.1', 'localhost', '::1']) -# module search -IGNORE_FILES = ["COPYING", "CONTRIBUTING", "LICENSE", "README", "VERSION", "GUIDELINES"] -INTERNAL_RESULT_KEYS = ['add_host', 'add_group'] -RESTRICTED_RESULT_KEYS = ['ansible_rsync_path', 'ansible_playbook_python'] -# check all of these extensions when looking for 'variable' files which should be YAML or JSON. -YAML_FILENAME_EXTENSIONS = [".yml", ".yaml", ".json"] +YAML_FILENAME_EXTENSIONS = [".yml", ".yaml", ".json"] # check all of these extensions when looking for 'variable' files which should be YAML or JSON. diff --git a/lib/ansible/executor/playbook_executor.py b/lib/ansible/executor/playbook_executor.py index b2efd435ff4..1f96e668dd8 100644 --- a/lib/ansible/executor/playbook_executor.py +++ b/lib/ansible/executor/playbook_executor.py @@ -192,7 +192,7 @@ class PlaybookExecutor: retries = sorted(retries) if len(retries) > 0: if C.RETRY_FILES_SAVE_PATH: - basedir = C.shell_expand(C.RETRY_FILES_SAVE_PATH) + basedir = C.RETRY_FILES_SAVE_PATH elif playbook_path: basedir = os.path.dirname(os.path.abspath(playbook_path)) else: diff --git a/lib/ansible/parsing/dataloader.py b/lib/ansible/parsing/dataloader.py index 9d40a3d6b08..a2579254701 100644 --- a/lib/ansible/parsing/dataloader.py +++ b/lib/ansible/parsing/dataloader.py @@ -80,6 +80,17 @@ class DataLoader: a JSON or YAML string. ''' new_data = None + + # YAML parser will take JSON as it is a subset. + if isinstance(data, AnsibleUnicode): + # The PyYAML's libyaml bindings use PyUnicode_CheckExact so + # they are unable to cope with our subclass. + # Unwrap and re-wrap the unicode so we can keep track of line + # numbers + in_data = text_type(data) + else: + in_data = data + try: # we first try to load this data as JSON new_data = json.loads(data) diff --git a/lib/ansible/playbook/base.py b/lib/ansible/playbook/base.py index d0f9c6740fd..d1b712f5fb1 100644 --- a/lib/ansible/playbook/base.py +++ b/lib/ansible/playbook/base.py @@ -149,20 +149,20 @@ class BaseMeta(type): class Base(with_metaclass(BaseMeta, object)): # connection/transport - _connection = FieldAttribute(isa='string') - _port = FieldAttribute(isa='int') + _connection = FieldAttribute(isa='string') + _port = FieldAttribute(isa='int') _remote_user = FieldAttribute(isa='string') # variables _vars = FieldAttribute(isa='dict', priority=100, inherit=False) # flags and misc. settings - _environment = FieldAttribute(isa='list') - _no_log = FieldAttribute(isa='bool') - _always_run = FieldAttribute(isa='bool') - _run_once = FieldAttribute(isa='bool') - _ignore_errors = FieldAttribute(isa='bool') - _check_mode = FieldAttribute(isa='bool') + _environment = FieldAttribute(isa='list') + _no_log = FieldAttribute(isa='bool') + _always_run = FieldAttribute(isa='bool') + _run_once = FieldAttribute(isa='bool') + _ignore_errors = FieldAttribute(isa='bool') + _check_mode = FieldAttribute(isa='bool') _any_errors_fatal = FieldAttribute(isa='bool', default=False, always_post_validate=True) # param names which have been deprecated/removed diff --git a/lib/ansible/plugins/shell/__init__.py b/lib/ansible/plugins/shell/__init__.py index bf16fa41ab9..2a34e04145a 100644 --- a/lib/ansible/plugins/shell/__init__.py +++ b/lib/ansible/plugins/shell/__init__.py @@ -34,11 +34,12 @@ class ShellBase(object): def __init__(self): self.env = dict() if C.DEFAULT_MODULE_SET_LOCALE: + module_locale = C.DEFAULT_MODULE_LANG or os.getenv('LANG', 'en_US.UTF-8') self.env.update( dict( - LANG=C.DEFAULT_MODULE_LANG, - LC_ALL=C.DEFAULT_MODULE_LANG, - LC_MESSAGES=C.DEFAULT_MODULE_LANG, + LANG=module_locale, + LC_ALL=module_locale, + LC_MESSAGES=module_locale, ) ) diff --git a/setup.py b/setup.py index d43fd299ff9..58f65b60396 100644 --- a/setup.py +++ b/setup.py @@ -69,7 +69,9 @@ setup( 'galaxy/data/*/*.*', 'galaxy/data/*/*/.*', 'galaxy/data/*/*/*.*', - 'galaxy/data/*/tests/inventory' + 'galaxy/data/*/tests/inventory', + 'config/data/*.yaml', + 'config/data/*.yml', ], }, classifiers=[ diff --git a/test/sanity/code-smell/boilerplate.sh b/test/sanity/code-smell/boilerplate.sh index b5e726d529a..85092de26e6 100755 --- a/test/sanity/code-smell/boilerplate.sh +++ b/test/sanity/code-smell/boilerplate.sh @@ -5,6 +5,7 @@ future1=$(find ./bin -type f -exec grep -HL 'from __future__ import (absolute_im metaclass2=$(find ./lib/ansible -path ./lib/ansible/modules -prune \ -o -path ./lib/ansible/modules/__init__.py \ + -o -path ./lib/ansible/config/__init__.py \ -o -path ./lib/ansible/module_utils -prune \ -o -path ./lib/ansible/module_utils/six/_six.py -prune \ -o -path ./lib/ansible/compat/selectors/_selectors2.py -prune \ @@ -15,6 +16,7 @@ metaclass2=$(find ./lib/ansible -path ./lib/ansible/modules -prune \ future2=$(find ./lib/ansible -path ./lib/ansible/modules -prune \ -o -path ./lib/ansible/modules/__init__.py \ + -o -path ./lib/ansible/config/__init__.py \ -o -path ./lib/ansible/module_utils -prune \ -o -path ./lib/ansible/module_utils/six/_six.py -prune \ -o -path ./lib/ansible/compat/selectors/_selectors2.py -prune \ diff --git a/test/sanity/pep8/legacy-files.txt b/test/sanity/pep8/legacy-files.txt index e830f50e8af..7c8810269c1 100644 --- a/test/sanity/pep8/legacy-files.txt +++ b/test/sanity/pep8/legacy-files.txt @@ -1,3 +1,8 @@ +hacking/conf2yaml.py +lib/ansible/constants.py +lib/ansible/cli/config.py +lib/ansible/config/data.py +lib/ansible/config/manager.py lib/ansible/module_utils/vmware.py lib/ansible/modules/cloud/amazon/_ec2_ami_search.py lib/ansible/modules/cloud/amazon/_ec2_vpc.py @@ -558,3 +563,4 @@ lib/ansible/modules/system/user.py lib/ansible/modules/utilities/helper/_accelerate.py lib/ansible/modules/utilities/logic/async_status.py lib/ansible/modules/utilities/logic/async_wrapper.py +lib/ansible/playbook/base.py diff --git a/test/units/cli/test_galaxy.py b/test/units/cli/test_galaxy.py index e0e2ea1ee88..f03d2b47e23 100644 --- a/test/units/cli/test_galaxy.py +++ b/test/units/cli/test_galaxy.py @@ -126,7 +126,7 @@ class TestGalaxy(unittest.TestCase): def test_execute_remove(self): # installing role - gc = GalaxyCLI(args=["install", "--offline", "-p", self.role_path, "-r", self.role_req]) + gc = GalaxyCLI(args=["install", "--offline", "-p", self.role_path, "-r", self.role_req, '--force']) gc.parse() gc.run() diff --git a/test/units/test_constants.py b/test/units/test_constants.py index accd99f8ee6..fa9902e7753 100644 --- a/test/units/test_constants.py +++ b/test/units/test_constants.py @@ -120,99 +120,3 @@ class TestMkBoolean: assert constants.mk_boolean("yes") is True assert constants.mk_boolean("y") is True assert constants.mk_boolean("on") is True - - -class TestShellExpand: - def test_shell_expand_none(self): - assert constants.shell_expand(None) is None - - def test_shell_expand_static_path(self): - assert constants.shell_expand(u'/usr/local') == u'/usr/local' - - def test_shell_expand_tilde(self, user): - assert constants.shell_expand(u'~/local') == os.path.join(user['home'], 'local') - assert constants.shell_expand(u'~%s/local' % user['username']) == os.path.join(user['home'], 'local') - - def test_shell_expand_vars(self, user): - assert constants.shell_expand(u'$HOME/local') == os.path.join(user['home'], 'local') - - os.environ['ANSIBLE_TEST_VAR'] = '/srv/ansible' - assert constants.shell_expand(u'$ANSIBLE_TEST_VAR/local') == os.path.join('/srv/ansible', 'local') - - os.environ['ANSIBLE_TEST_VAR'] = '~' - assert constants.shell_expand(u'$ANSIBLE_TEST_VAR/local') == os.path.join(user['home'], 'local') - - del os.environ['ANSIBLE_TEST_VAR'] - assert constants.shell_expand(u'$ANSIBLE_TEST_VAR/local') == u'$ANSIBLE_TEST_VAR/local' - - def test_expand_relative_abs_path(self): - assert constants.shell_expand('/absolute/path', expand_relative_paths=True) == '/absolute/path' - - def test_expand_relative_path_relative_cfg_file(self, cfg_file): - assert constants.shell_expand(u'relative/path', expand_relative_paths=True) == os.path.join(cfg_file, 'relative/path') - - def test_expand_relative_path_relative_cwd(self, cwd, null_cfg_file): - assert constants.shell_expand(u'relative/path', expand_relative_paths=True) == os.path.join(cwd, 'relative/path') - - -# configparser object -class TestGetConfig: - def test_from_config_file(self, cfgparser): - assert constants.get_config(cfgparser, 'defaults', 'defaults_one', 'ANSIBLE_TEST_VAR', 'foo', value_type=None) == 'data_defaults_one' - assert constants.get_config(cfgparser, 'level1', 'level1_one', 'ANSIBLE_TEST_VAR', 'foo', value_type=None) == 'data_level1_one' - - def test_from_env_var(self, cfgparser): - os.environ['ANSIBLE_TEST_VAR'] = 'bar' - - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 'foo', value_type=None) == 'bar' - assert constants.get_config(cfgparser, 'unknown', 'defaults_one', 'ANSIBLE_TEST_VAR', 'foo', value_type=None) == 'bar' - - del os.environ['ANSIBLE_TEST_VAR'] - - def test_from_default(self, cfgparser): - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 'foo', value_type=None) == u'foo' - assert constants.get_config(cfgparser, 'unknown', 'defaults_one', 'ANSIBLE_TEST_VAR', 'foo', value_type=None) == u'foo' - - def test_value_type_boolean(self, cfgparser): - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 'on', value_type='boolean') is True - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', True, value_type='boolean') is True - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 'other', value_type='boolean') is False - - def test_value_type_integer(self, cfgparser): - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', '10', value_type='integer') == 10 - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 10, value_type='integer') == 10 - - def test_value_type_float(self, cfgparser): - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', '10', value_type='float') == 10.0 - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 10, value_type='float') == 10.0 - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', '11.5', value_type='float') == 11.5 - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 11.5, value_type='float') == 11.5 - - def test_value_type_list(self, cfgparser): - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 'one,two,three', value_type='list') == ['one', 'two', 'three'] - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', ['one', 'two', 'three'], value_type='list') == ['one', 'two', 'three'] - - def test_value_type_none(self, cfgparser): - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 'None', value_type='none') is None - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', None, value_type='none') is None - - def test_value_type_path(self, cfgparser, user, cfg_file): - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', '~/local', value_type='path') == os.path.join(user['home'], 'local') - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 'local', value_type='path') == 'local' - assert constants.get_config(cfgparser, 'defaults', 'unknown', 'ANSIBLE_TEST_VAR', 'local', value_type='path', expand_relative_paths=True) \ - == os.path.join(cfg_file, 'local') - -# Need to implement tests for these -# def test_value_type_pathlist(self, cfgparser): -# pass -# -# def test_value_type_string(self, cfgparser): -# pass -# -# def test_value_type_temppath(self, cfgparser): -# pass - - -# Need to test this -# def test_load_config_file(): -# pass