Add toml inventory plugin (#41593)

* First pass at a toml inventory

* Make EXAMPLES yaml

* Remove unnecessary comment

* Small formatting changes

* Add ansible-inventory option to list as TOML

* TOML inventory improvements, to allow a more simple inventory, specifically related to children

* changelog

* Simplify logic

* Dedupe _expand_hostpattern, making it available to all inventory plugins

* Don't make the TOML inventory dependent on the YAML inventory

* Quote IP address values

* Add more TOML examples

* Further cleanups

* Enable the toml inventory to run by default

* Create toml specific dumper

* 2.8

* Clean up imports

* No toml pygments lexer

* Don't raise an exception early when toml isn't present, and move toml to the end, since it requires an external dep

* Require toml>=0.10.0

* Further clean up of empty data

* Don't require toml>=0.10.0, but prefer it, add code for fallback in older versions

* Ensure we actually pass an encoder to toml.dumps

* Simplify recursive data converter

* Appease tests, since we haven't limited controller testing to 2.7+

* Update docstring for convert_yaml_objects_to_native

* remove outdated catching of AttributeError

* We don't need to catch ImportError when import ansible.plugins.inventory.toml

* Add note about what self.dump_funcs.update is doing

* Address some things

* A little extra comment

* Fix toml availability check

* Don't create an intermediate list

* Require toml file extension

* Add metadata

* Remove TOML docs from intro_inventory to prevent people from getting the wrong idea

* It's in defaults, remove note

* core supported, indicate very clearly that this is preview status
This commit is contained in:
Matt Martz
2018-11-06 10:02:36 -06:00
committed by GitHub
parent 1441c6ad3f
commit 9949629e5a
8 changed files with 353 additions and 83 deletions

View File

@@ -94,6 +94,8 @@ class InventoryCLI(CLI):
# graph
self.parser.add_option("-y", "--yaml", action="store_true", default=False, dest='yaml',
help='Use YAML format instead of default JSON, ignored for --graph')
self.parser.add_option('--toml', action='store_true', default=False, dest='toml',
help='Use TOML format instead of default JSON, ignored for --graph')
self.parser.add_option("--vars", action="store_true", default=False, dest='show_vars',
help='Add vars to graph display, ignored unless used with --graph')
@@ -176,6 +178,8 @@ class InventoryCLI(CLI):
top = self._get_group('all')
if self.options.yaml:
results = self.yaml_inventory(top)
elif self.options.toml:
results = self.toml_inventory(top)
else:
results = self.json_inventory(top)
results = self.dump(results)
@@ -193,6 +197,13 @@ class InventoryCLI(CLI):
import yaml
from ansible.parsing.yaml.dumper import AnsibleDumper
results = yaml.dump(stuff, Dumper=AnsibleDumper, default_flow_style=False)
elif self.options.toml:
from ansible.plugins.inventory.toml import toml_dumps, HAS_TOML
if not HAS_TOML:
raise AnsibleError(
'The python "toml" library is required when using the TOML output format'
)
results = toml_dumps(stuff)
else:
import json
from ansible.parsing.ajson import AnsibleJSONEncoder
@@ -385,3 +396,45 @@ class InventoryCLI(CLI):
return results
return format_group(top)
def toml_inventory(self, top):
seen = set()
has_ungrouped = bool(next(g.hosts for g in top.child_groups if g.name == 'ungrouped'))
def format_group(group):
results = {}
results[group.name] = {}
results[group.name]['children'] = []
for subgroup in sorted(group.child_groups, key=attrgetter('name')):
if subgroup.name == 'ungrouped' and not has_ungrouped:
continue
if group.name != 'all':
results[group.name]['children'].append(subgroup.name)
results.update(format_group(subgroup))
if group.name != 'all':
for host in sorted(group.hosts, key=attrgetter('name')):
if host.name not in seen:
seen.add(host.name)
host_vars = self._get_host_variables(host=host)
self._remove_internal(host_vars)
else:
host_vars = {}
try:
results[group.name]['hosts'][host.name] = host_vars
except KeyError:
results[group.name]['hosts'] = {host.name: host_vars}
if self.options.export:
results[group.name]['vars'] = self._get_group_variables(group)
self._remove_empty(results[group.name])
if not results[group.name]:
del results[group.name]
return results
results = format_group(top)
return results