1st part of ansible config, adds ansible-config to view/manage configs (#12797)
* Start of ansible config project moved configuration definitions to external yaml file vs hardcoded * updated constants to be a data strcutures that are looped over and also return origin of setting changed to manager/data scheme for base classes new cli ansible-config to view/manage ansible configuration settings * prints green for default/unchanged and yellow for those that have been overriden * added list action to show all configurable settings and their associated ini and env var names * allows specifying config file to see what result would look like * TBD update, edit and view options removed test for functions that have been removed env_Vars are now list of dicts allows for version_added and deprecation in future added a couple of descriptions for future doc autogeneration ensure test does not fail if delete_me exists normalized 'path expansion' added yaml config to setup packaging removed unused imports better encoding handling updated as per feedback * pep8
This commit is contained in:
parent
4344132a7d
commit
74842adc07
20 changed files with 2032 additions and 575 deletions
|
@ -127,7 +127,7 @@ if __name__ == '__main__':
|
||||||
exit_code = 99
|
exit_code = 99
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
have_cli_options = cli is not None and cli.options is not None
|
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:
|
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
|
||||||
log_only = False
|
log_only = False
|
||||||
else:
|
else:
|
||||||
|
|
1
bin/ansible-config
Symbolic link
1
bin/ansible-config
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
ansible
|
124
hacking/conf2yaml.py
Executable file
124
hacking/conf2yaml.py
Executable file
|
@ -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))
|
||||||
|
|
|
@ -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.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)):
|
(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') "
|
self.parser.error("Sudo arguments ('--sudo', '--sudo-user', and '--ask-sudo-pass') and su arguments ('--su', '--su-user', and '--ask-su-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")
|
||||||
"and become arguments ('--become', '--become-user', and '--ask-become-pass')"
|
|
||||||
" are exclusive of each other")
|
|
||||||
|
|
||||||
if fork_opts:
|
if fork_opts:
|
||||||
if op.forks < 1:
|
if op.forks < 1:
|
||||||
|
@ -283,20 +281,13 @@ class CLI(with_metaclass(ABCMeta, object)):
|
||||||
setattr(parser.values, option.dest, os.path.expanduser(value))
|
setattr(parser.values, option.dest, os.path.expanduser(value))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def unfrack_path(option, opt, value, parser):
|
def unfrack_paths(option, opt, value, parser):
|
||||||
setattr(parser.values, option.dest, unfrackpath(value))
|
if isinstance(value, string_types):
|
||||||
|
setattr(parser.values, option.dest, [unfrackpath(x) for x in value.split(os.sep)])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def expand_paths(option, opt, value, parser):
|
def unfrack_path(option, opt, value, parser):
|
||||||
"""optparse action callback to convert a PATH style string arg to a list of path strings.
|
setattr(parser.values, option.dest, unfrackpath(value))
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False, runtask_opts=False, vault_opts=False, module_opts=False,
|
def base_parser(usage="", output_opts=False, runas_opts=False, meta_opts=False, runtask_opts=False, vault_opts=False, module_opts=False,
|
||||||
|
|
181
lib/ansible/cli/config.py
Normal file
181
lib/ansible/cli/config.py
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# 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 <command> --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'))
|
|
@ -117,11 +117,9 @@ class GalaxyCLI(CLI):
|
||||||
if self.action not in ("delete", "import", "init", "login", "setup"):
|
if self.action not in ("delete", "import", "init", "login", "setup"):
|
||||||
# NOTE: while the option type=str, the default is a list, and the
|
# NOTE: while the option type=str, the default is a list, and the
|
||||||
# callback will set the value to a list.
|
# 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,
|
self.parser.add_option('-p', '--roles-path', dest='roles_path', action="callback", callback=CLI.unfrack_paths, default=C.DEFAULT_ROLES_PATH,
|
||||||
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'
|
||||||
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")
|
||||||
'file (/etc/ansible/roles if not configured)')
|
|
||||||
|
|
||||||
if self.action in ("init", "install"):
|
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')
|
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
|
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.
|
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)
|
role_file = self.get_opt("role_file", None)
|
||||||
|
|
||||||
if len(self.args) == 0 and role_file is None:
|
if len(self.args) == 0 and role_file is None:
|
||||||
# the user needs to specify one of either --role-file
|
# the user needs to specify one of either --role-file or specify a single user/role name
|
||||||
# or specify a single user/role name
|
|
||||||
raise AnsibleOptionsError("- you must specify a user/role name or a roles file")
|
raise AnsibleOptionsError("- you must specify a user/role name or a roles file")
|
||||||
elif len(self.args) == 1 and role_file is not None:
|
elif len(self.args) == 1 and role_file is not None:
|
||||||
# using a role file is mutually exclusive of specifying
|
# using a role file is mutually exclusive of specifying the role name on the command line
|
||||||
# the role name on the command line
|
|
||||||
raise AnsibleOptionsError("- please specify a user/role name, or a roles file, but not both")
|
raise AnsibleOptionsError("- please specify a user/role name, or a roles file, but not both")
|
||||||
|
|
||||||
no_deps = self.get_opt("no_deps", False)
|
no_deps = self.get_opt("no_deps", False)
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
|
||||||
#
|
|
||||||
# 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Make coding more python3-ish
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
63
lib/ansible/config/data.py
Normal file
63
lib/ansible/config/data.py
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# 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
|
1355
lib/ansible/config/data/config.yml
Normal file
1355
lib/ansible/config/data/config.yml
Normal file
File diff suppressed because it is too large
Load diff
242
lib/ansible/config/manager.py
Normal file
242
lib/ansible/config/manager.py
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# 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')
|
||||||
|
|
|
@ -19,441 +19,40 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import os
|
|
||||||
import tempfile
|
|
||||||
from string import ascii_letters, digits
|
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.module_utils._text import to_text
|
||||||
from ansible.parsing.quoting import unquote
|
from ansible.config.manager import ConfigManager
|
||||||
from ansible.utils.path import makedirs_safe
|
|
||||||
|
|
||||||
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):
|
def mk_boolean(value):
|
||||||
ret = value
|
''' moved '''
|
||||||
if not isinstance(value, bool):
|
return config.make_boolean(value)
|
||||||
if value is None:
|
|
||||||
ret = False
|
|
||||||
ret = (str(value).lower() in BOOL_TRUE)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def shell_expand(path, expand_relative_paths=False):
|
### CONSTANTS ### yes, actual ones
|
||||||
'''
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
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')
|
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_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')
|
BOOL_TRUE = config.data.BOOL_TRUE
|
||||||
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']
|
|
||||||
DEFAULT_BECOME_PASS = None
|
DEFAULT_BECOME_PASS = None
|
||||||
DEFAULT_PASSWORD_CHARS = to_text(ascii_letters + digits + ".,:-_", errors='strict') # characters included in auto-generated passwords
|
DEFAULT_PASSWORD_CHARS = to_text(ascii_letters + digits + ".,:-_", errors='strict') # characters included in auto-generated passwords
|
||||||
DEFAULT_SUDO_PASS = None
|
DEFAULT_SUDO_PASS = None
|
||||||
DEFAULT_REMOTE_PASS = None
|
DEFAULT_REMOTE_PASS = None
|
||||||
DEFAULT_SUBSET = None
|
DEFAULT_SUBSET = None
|
||||||
DEFAULT_SU_PASS = 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_MIN = 1.0
|
||||||
VAULT_VERSION_MAX = 1.0
|
VAULT_VERSION_MAX = 1.0
|
||||||
TREE_DIR = None
|
YAML_FILENAME_EXTENSIONS = [".yml", ".yaml", ".json"] # check all of these extensions when looking for 'variable' files which should be YAML or JSON.
|
||||||
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"]
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ class PlaybookExecutor:
|
||||||
retries = sorted(retries)
|
retries = sorted(retries)
|
||||||
if len(retries) > 0:
|
if len(retries) > 0:
|
||||||
if C.RETRY_FILES_SAVE_PATH:
|
if C.RETRY_FILES_SAVE_PATH:
|
||||||
basedir = C.shell_expand(C.RETRY_FILES_SAVE_PATH)
|
basedir = C.RETRY_FILES_SAVE_PATH
|
||||||
elif playbook_path:
|
elif playbook_path:
|
||||||
basedir = os.path.dirname(os.path.abspath(playbook_path))
|
basedir = os.path.dirname(os.path.abspath(playbook_path))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -80,6 +80,17 @@ class DataLoader:
|
||||||
a JSON or YAML string.
|
a JSON or YAML string.
|
||||||
'''
|
'''
|
||||||
new_data = None
|
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:
|
try:
|
||||||
# we first try to load this data as JSON
|
# we first try to load this data as JSON
|
||||||
new_data = json.loads(data)
|
new_data = json.loads(data)
|
||||||
|
|
|
@ -149,20 +149,20 @@ class BaseMeta(type):
|
||||||
class Base(with_metaclass(BaseMeta, object)):
|
class Base(with_metaclass(BaseMeta, object)):
|
||||||
|
|
||||||
# connection/transport
|
# connection/transport
|
||||||
_connection = FieldAttribute(isa='string')
|
_connection = FieldAttribute(isa='string')
|
||||||
_port = FieldAttribute(isa='int')
|
_port = FieldAttribute(isa='int')
|
||||||
_remote_user = FieldAttribute(isa='string')
|
_remote_user = FieldAttribute(isa='string')
|
||||||
|
|
||||||
# variables
|
# variables
|
||||||
_vars = FieldAttribute(isa='dict', priority=100, inherit=False)
|
_vars = FieldAttribute(isa='dict', priority=100, inherit=False)
|
||||||
|
|
||||||
# flags and misc. settings
|
# flags and misc. settings
|
||||||
_environment = FieldAttribute(isa='list')
|
_environment = FieldAttribute(isa='list')
|
||||||
_no_log = FieldAttribute(isa='bool')
|
_no_log = FieldAttribute(isa='bool')
|
||||||
_always_run = FieldAttribute(isa='bool')
|
_always_run = FieldAttribute(isa='bool')
|
||||||
_run_once = FieldAttribute(isa='bool')
|
_run_once = FieldAttribute(isa='bool')
|
||||||
_ignore_errors = FieldAttribute(isa='bool')
|
_ignore_errors = FieldAttribute(isa='bool')
|
||||||
_check_mode = FieldAttribute(isa='bool')
|
_check_mode = FieldAttribute(isa='bool')
|
||||||
_any_errors_fatal = FieldAttribute(isa='bool', default=False, always_post_validate=True)
|
_any_errors_fatal = FieldAttribute(isa='bool', default=False, always_post_validate=True)
|
||||||
|
|
||||||
# param names which have been deprecated/removed
|
# param names which have been deprecated/removed
|
||||||
|
|
|
@ -34,11 +34,12 @@ class ShellBase(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.env = dict()
|
self.env = dict()
|
||||||
if C.DEFAULT_MODULE_SET_LOCALE:
|
if C.DEFAULT_MODULE_SET_LOCALE:
|
||||||
|
module_locale = C.DEFAULT_MODULE_LANG or os.getenv('LANG', 'en_US.UTF-8')
|
||||||
self.env.update(
|
self.env.update(
|
||||||
dict(
|
dict(
|
||||||
LANG=C.DEFAULT_MODULE_LANG,
|
LANG=module_locale,
|
||||||
LC_ALL=C.DEFAULT_MODULE_LANG,
|
LC_ALL=module_locale,
|
||||||
LC_MESSAGES=C.DEFAULT_MODULE_LANG,
|
LC_MESSAGES=module_locale,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -69,7 +69,9 @@ setup(
|
||||||
'galaxy/data/*/*.*',
|
'galaxy/data/*/*.*',
|
||||||
'galaxy/data/*/*/.*',
|
'galaxy/data/*/*/.*',
|
||||||
'galaxy/data/*/*/*.*',
|
'galaxy/data/*/*/*.*',
|
||||||
'galaxy/data/*/tests/inventory'
|
'galaxy/data/*/tests/inventory',
|
||||||
|
'config/data/*.yaml',
|
||||||
|
'config/data/*.yml',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
classifiers=[
|
classifiers=[
|
||||||
|
|
|
@ -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 \
|
metaclass2=$(find ./lib/ansible -path ./lib/ansible/modules -prune \
|
||||||
-o -path ./lib/ansible/modules/__init__.py \
|
-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 -prune \
|
||||||
-o -path ./lib/ansible/module_utils/six/_six.py -prune \
|
-o -path ./lib/ansible/module_utils/six/_six.py -prune \
|
||||||
-o -path ./lib/ansible/compat/selectors/_selectors2.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 \
|
future2=$(find ./lib/ansible -path ./lib/ansible/modules -prune \
|
||||||
-o -path ./lib/ansible/modules/__init__.py \
|
-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 -prune \
|
||||||
-o -path ./lib/ansible/module_utils/six/_six.py -prune \
|
-o -path ./lib/ansible/module_utils/six/_six.py -prune \
|
||||||
-o -path ./lib/ansible/compat/selectors/_selectors2.py -prune \
|
-o -path ./lib/ansible/compat/selectors/_selectors2.py -prune \
|
||||||
|
|
|
@ -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/module_utils/vmware.py
|
||||||
lib/ansible/modules/cloud/amazon/_ec2_ami_search.py
|
lib/ansible/modules/cloud/amazon/_ec2_ami_search.py
|
||||||
lib/ansible/modules/cloud/amazon/_ec2_vpc.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/helper/_accelerate.py
|
||||||
lib/ansible/modules/utilities/logic/async_status.py
|
lib/ansible/modules/utilities/logic/async_status.py
|
||||||
lib/ansible/modules/utilities/logic/async_wrapper.py
|
lib/ansible/modules/utilities/logic/async_wrapper.py
|
||||||
|
lib/ansible/playbook/base.py
|
||||||
|
|
|
@ -126,7 +126,7 @@ class TestGalaxy(unittest.TestCase):
|
||||||
|
|
||||||
def test_execute_remove(self):
|
def test_execute_remove(self):
|
||||||
# installing role
|
# 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.parse()
|
||||||
gc.run()
|
gc.run()
|
||||||
|
|
||||||
|
|
|
@ -120,99 +120,3 @@ class TestMkBoolean:
|
||||||
assert constants.mk_boolean("yes") is True
|
assert constants.mk_boolean("yes") is True
|
||||||
assert constants.mk_boolean("y") is True
|
assert constants.mk_boolean("y") is True
|
||||||
assert constants.mk_boolean("on") 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
|
|
||||||
|
|
Loading…
Reference in a new issue