Skip to content

Commit

Permalink
Preserve order of variables and cli options for python 2.x
Browse files Browse the repository at this point in the history
Utilizing OrderedDict to
- ensure the order of the variables is preserved
- ensure the order of cli options is preserved
  • Loading branch information
Tejeda, Engelbert committed Sep 13, 2019
1 parent ddbc787 commit 22d330c
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 19 deletions.
63 changes: 45 additions & 18 deletions ansible_taskrunner/cli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Import builtins
from __future__ import print_function
from collections import OrderedDict
import logging
import logging.handlers
import os
Expand Down Expand Up @@ -318,6 +319,30 @@ def run(args=None, **kwargs):
prefix = 'echo' if kwargs.get('_echo') else ''
# Gather variables from commandline for interpolation
cli_vars = ''
# python 2.x
# Make sure kwargs adhere to the order in
# which they were called
if sys.version_info[0] < 3:
# First we build a mapping of cli variables to corresponding yaml variables
req_parameters = yaml_vars.get('required_parameters', {}) or {}
opt_parameters = yaml_vars.get('optional_parameters', {}) or {}
if req_parameters:
parameter_mapping = dict(opt_parameters).update(dict(req_parameters))
else:
parameter_mapping = dict(opt_parameters)
# Next, we create a dictionary that holds cli arguments
# in the order they were called, as per the parameter mapping
ordered_args = {}
for k, v in parameter_mapping.items():
for a in sys.argv:
if re.search(k, a):
for o in k.split('|'):
if o in sys.argv:
i = sys.argv.index(o)
ordered_args[k] = i
# Lastly, we convert our kwargs object to
# an ordered dictionary object as per the above
kwargs = OrderedDict([(parameter_mapping[k],kwargs.get(parameter_mapping[k])) for k, v in sorted(ordered_args.items(), key=lambda item: item[1])])
for key, value in kwargs.items():
if key.startswith('_'):
cli_vars += '{k}="{v}"\n'.format(k=key, v=value)
Expand All @@ -341,7 +366,10 @@ def run(args=None, **kwargs):
vars_list.append((var[0],var[1]))
else:
vars_list.append((var[0], kwargs_dict_filtered[var[0]]))
default_vars = dict(vars_list)
if sys.version_info[0] < 3:
default_vars = OrderedDict(vars_list)
else:
default_vars = dict(vars_list)
# List-type variables
list_vars = []
for var in default_vars:
Expand All @@ -363,30 +391,29 @@ def run(args=None, **kwargs):
# Short-circuit the task runner
# if we're calling functions from the commandline
cli_functions = ['{k} {v}'.format(
k=key, v=value) for key, value in kwargs.items() if
k=key, v='' if value in [True, False] else value) for key, value in kwargs.items() if
value and key in internal_functions.keys()]
if cli_functions:
for cli_function in cli_functions:
command = '''{clv}
command = '''{clv}
{dsv}
{psv}
{dlv}
{bfn}
{clf} {arg} {raw}
'''.format(
dsv='\n'.join(defaults_string_vars),
psv=paramset_var,
dlv='\n'.join(list_vars),
clv=cli_vars,
bfn='\n'.join(bash_functions),
clf=cli_function,
arg=args,
raw=raw_args
)
if prefix == 'echo':
print(command)
else:
yamlcli.call(command)
'''.format(
dsv='\n'.join(defaults_string_vars),
psv=paramset_var,
dlv='\n'.join(list_vars),
clv=cli_vars,
bfn='\n'.join(bash_functions),
clf='\n'.join(cli_functions),
arg=args,
raw=raw_args
)
if prefix == 'echo':
print(command)
else:
yamlcli.call(command)
else:
# Invoke the cli provider
provider_cli.invocation(
Expand Down
20 changes: 19 additions & 1 deletion ansible_taskrunner/lib/superduperconfig/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import os
import sys
from collections import OrderedDict
import yaml

# Logging
Expand All @@ -15,6 +16,18 @@ def __init__(self, prog_name):
self.logger = logger
pass

def ordered_load(self, stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict):
class OrderedLoader(Loader):
pass
def construct_mapping(loader, node):
loader.flatten_mapping(node)
return object_pairs_hook(loader.construct_pairs(node))
OrderedLoader.add_constructor(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
construct_mapping)
return yaml.load(stream, OrderedLoader)


def load_config(self, config_file, req_keys=[], failfast=False, data_key=None, debug=False):
""" Load config file
"""
Expand All @@ -33,7 +46,12 @@ def load_config(self, config_file, req_keys=[], failfast=False, data_key=None, d
config_found = True
try:
with open(config_path, 'r') as ymlfile:
cfg = yaml.load(ymlfile, yaml.Loader)
# Preserve dictionary order for python 2
# https://stackoverflow.com/questions/5121931/in-python-how-can-you-load-yaml-mappings-as-ordereddicts
if sys.version_info[0] < 3:
cfg = self.ordered_load(ymlfile, yaml.Loader)
else:
cfg = yaml.load(ymlfile, yaml.Loader)
config_dict = cfg[data_key] if data_key is not None else cfg
config_is_valid = all([m[m.keys()[0]].get(k)
for k in req_keys for m in config_dict])
Expand Down

0 comments on commit 22d330c

Please sign in to comment.