summaryrefslogtreecommitdiff
path: root/bin/ansible-config
diff options
context:
space:
mode:
Diffstat (limited to 'bin/ansible-config')
-rwxr-xr-xbin/ansible-config125
1 files changed, 89 insertions, 36 deletions
diff --git a/bin/ansible-config b/bin/ansible-config
index 7dfad9ca..3a5c2421 100755
--- a/bin/ansible-config
+++ b/bin/ansible-config
@@ -10,13 +10,12 @@ __metaclass__ = type
from ansible.cli import CLI
import os
+import yaml
import shlex
import subprocess
from collections.abc import Mapping
-import yaml
-
from ansible import context
import ansible.plugins.loader as plugin_loader
@@ -25,6 +24,7 @@ from ansible.cli.arguments import option_helpers as opt_help
from ansible.config.manager import ConfigManager, Setting
from ansible.errors import AnsibleError, AnsibleOptionsError
from ansible.module_utils._text import to_native, to_text, to_bytes
+from ansible.module_utils.common.json import json_dump
from ansible.module_utils.six import string_types
from ansible.parsing.quoting import is_quoted
from ansible.parsing.yaml.dumper import AnsibleDumper
@@ -35,6 +35,21 @@ from ansible.utils.path import unfrackpath
display = Display()
+def yaml_dump(data, default_flow_style=False, default_style=None):
+ return yaml.dump(data, Dumper=AnsibleDumper, default_flow_style=default_flow_style, default_style=default_style)
+
+
+def yaml_short(data):
+ return yaml_dump(data, default_flow_style=True, default_style="''")
+
+
+def get_constants():
+ ''' helper method to ensure we can template based on existing constants '''
+ if not hasattr(get_constants, 'cvars'):
+ get_constants.cvars = {k: getattr(C, k) for k in dir(C) if not k.startswith('__')}
+ return get_constants.cvars
+
+
class ConfigCLI(CLI):
""" Config command line class """
@@ -65,11 +80,15 @@ class ConfigCLI(CLI):
list_parser = subparsers.add_parser('list', help='Print all config options', parents=[common])
list_parser.set_defaults(func=self.execute_list)
+ list_parser.add_argument('--format', '-f', dest='format', action='store', choices=['json', 'yaml'], default='yaml',
+ help='Output format for list')
dump_parser = subparsers.add_parser('dump', help='Dump configuration', parents=[common])
dump_parser.set_defaults(func=self.execute_dump)
dump_parser.add_argument('--only-changed', '--changed-only', dest='only_changed', action='store_true',
help="Only show configurations that have changed from the default")
+ dump_parser.add_argument('--format', '-f', dest='format', action='store', choices=['json', 'yaml', 'display'], default='display',
+ help='Output format for dump')
view_parser = subparsers.add_parser('view', help='View configuration file', parents=[common])
view_parser.set_defaults(func=self.execute_view)
@@ -231,7 +250,12 @@ class ConfigCLI(CLI):
'''
config_entries = self._list_entries_from_args()
- self.pager(to_text(yaml.dump(config_entries, Dumper=AnsibleDumper), errors='surrogate_or_strict'))
+ if context.CLIARGS['format'] == 'yaml':
+ output = yaml_dump(config_entries)
+ elif context.CLIARGS['format'] == 'json':
+ output = json_dump(config_entries)
+
+ self.pager(to_text(output, errors='surrogate_or_strict'))
def _get_settings_vars(self, settings, subkey):
@@ -279,9 +303,13 @@ class ConfigCLI(CLI):
# TODO: might need quoting and value coercion depending on type
if subkey == 'env':
+ if entry.startswith('_ANSIBLE_'):
+ continue
data.append('%s%s=%s' % (prefix, entry, default))
elif subkey == 'vars':
- data.append(prefix + to_text(yaml.dump({entry: default}, Dumper=AnsibleDumper, default_flow_style=False), errors='surrogate_or_strict'))
+ if entry.startswith('_ansible_'):
+ continue
+ data.append(prefix + '%s: %s' % (entry, to_text(yaml_short(default), errors='surrogate_or_strict')))
data.append('')
return data
@@ -370,34 +398,41 @@ class ConfigCLI(CLI):
def _render_settings(self, config):
- text = []
+ entries = []
for setting in sorted(config):
- changed = False
- if isinstance(config[setting], Setting):
- # proceed normally
- if config[setting].origin == 'default':
- color = 'green'
- elif config[setting].origin == 'REQUIRED':
- # should include '_terms', '_input', etc
- color = 'red'
+ changed = (config[setting].origin not in ('default', 'REQUIRED'))
+
+ if context.CLIARGS['format'] == 'display':
+ if isinstance(config[setting], Setting):
+ # proceed normally
+ if config[setting].origin == 'default':
+ color = 'green'
+ elif config[setting].origin == 'REQUIRED':
+ # should include '_terms', '_input', etc
+ color = 'red'
+ else:
+ color = 'yellow'
+ msg = "%s(%s) = %s" % (setting, config[setting].origin, config[setting].value)
else:
- color = 'yellow'
- changed = True
- msg = "%s(%s) = %s" % (setting, config[setting].origin, config[setting].value)
+ color = 'green'
+ msg = "%s(%s) = %s" % (setting, 'default', config[setting].get('default'))
+
+ entry = stringc(msg, color)
else:
- color = 'green'
- msg = "%s(%s) = %s" % (setting, 'default', config[setting].get('default'))
+ entry = {}
+ for key in config[setting]._fields:
+ entry[key] = getattr(config[setting], key)
if not context.CLIARGS['only_changed'] or changed:
- text.append(stringc(msg, color))
+ entries.append(entry)
- return text
+ return entries
def _get_global_configs(self):
config = self.config.get_configuration_definitions(ignore_private=True).copy()
- for setting in self.config.data.get_settings():
- if setting.name in config:
- config[setting.name] = setting
+ for setting in config.keys():
+ v, o = C.config.get_config_value_and_origin(setting, cfile=self.config_file, variables=get_constants())
+ config[setting] = Setting(setting, v, o, None)
return self._render_settings(config)
@@ -407,7 +442,7 @@ class ConfigCLI(CLI):
loader = getattr(plugin_loader, '%s_loader' % ptype)
# acumulators
- text = []
+ output = []
config_entries = {}
# build list
@@ -445,7 +480,7 @@ class ConfigCLI(CLI):
# actually get the values
for setting in config_entries[finalname].keys():
try:
- v, o = C.config.get_config_value_and_origin(setting, plugin_type=ptype, plugin_name=name)
+ v, o = C.config.get_config_value_and_origin(setting, cfile=self.config_file, plugin_type=ptype, plugin_name=name, variables=get_constants())
except AnsibleError as e:
if to_text(e).startswith('No setting was provided for required configuration'):
v = None
@@ -462,10 +497,14 @@ class ConfigCLI(CLI):
# pretty please!
results = self._render_settings(config_entries[finalname])
if results:
- # avoid header for empty lists (only changed!)
- text.append('\n%s:\n%s' % (finalname, '_' * len(finalname)))
- text.extend(results)
- return text
+ if context.CLIARGS['format'] == 'display':
+ # avoid header for empty lists (only changed!)
+ output.append('\n%s:\n%s' % (finalname, '_' * len(finalname)))
+ output.extend(results)
+ else:
+ output.append({finalname: results})
+
+ return output
def execute_dump(self):
'''
@@ -473,21 +512,35 @@ class ConfigCLI(CLI):
'''
if context.CLIARGS['type'] == 'base':
# deal with base
- text = self._get_global_configs()
+ output = self._get_global_configs()
elif context.CLIARGS['type'] == 'all':
# deal with base
- text = self._get_global_configs()
+ output = self._get_global_configs()
# deal with plugins
for ptype in C.CONFIGURABLE_PLUGINS:
plugin_list = self._get_plugin_configs(ptype, context.CLIARGS['args'])
- if not context.CLIARGS['only_changed'] or plugin_list:
- text.append('\n%s:\n%s' % (ptype.upper(), '=' * len(ptype)))
- text.extend(plugin_list)
+ if context.CLIARGS['format'] == 'display':
+ if not context.CLIARGS['only_changed'] or plugin_list:
+ output.append('\n%s:\n%s' % (ptype.upper(), '=' * len(ptype)))
+ output.extend(plugin_list)
+ else:
+ if ptype in ('modules', 'doc_fragments'):
+ pname = ptype.upper()
+ else:
+ pname = '%s_PLUGINS' % ptype.upper()
+ output.append({pname: plugin_list})
else:
# deal with plugins
- text = self._get_plugin_configs(context.CLIARGS['type'], context.CLIARGS['args'])
+ output = self._get_plugin_configs(context.CLIARGS['type'], context.CLIARGS['args'])
+
+ if context.CLIARGS['format'] == 'display':
+ text = '\n'.join(output)
+ if context.CLIARGS['format'] == 'yaml':
+ text = yaml_dump(output)
+ elif context.CLIARGS['format'] == 'json':
+ text = json_dump(output)
- self.pager(to_text('\n'.join(text), errors='surrogate_or_strict'))
+ self.pager(to_text(text, errors='surrogate_or_strict'))
def main(args=None):