Skip to content
This repository was archived by the owner on Sep 16, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions tower_cli/cli/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import os
import re
import six
import json

import click

Expand Down Expand Up @@ -72,14 +73,26 @@ class StructuredInput(Variables):
name = 'structured_input'
__name__ = 'structured_input'

def __init__(self, allow_kv=False, as_string=False):
self.allow_kv = allow_kv
# The API is inconsistent about which format it requires
# some fields must string-ify variables, and others can
# pass variables as a dictionary
self.as_string = as_string
super(StructuredInput, self).__init__()

def convert(self, value, param, ctx):
s = super(StructuredInput, self).convert(value, param, ctx)
try:
return string_to_dict(s, allow_kv=False)
except Exception:
data = string_to_dict(s, allow_kv=self.allow_kv)
if self.as_string:
return json.dumps(data)
return data
except Exception as e:
raise exc.UsageError(
'Error loading structured input given by %s parameter. Please '
'check the validity of your JSON/YAML format.' % param.name
'check the validity of your JSON/YAML format. '
'Parse error: %s' % (param.name, e)
)


Expand Down
3 changes: 2 additions & 1 deletion tower_cli/resources/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class Resource(models.Resource):
name = models.Field(unique=True)
description = models.Field(required=False, display=False)
inventory = models.Field(type=types.Related('inventory'))
variables = models.Field(type=types.Variables(), required=False, display=False,
variables = models.Field(type=types.StructuredInput(allow_kv=True, as_string=True),
required=False, display=False,
help_text='Group variables, use "@" to get from file.')

def lookup_with_inventory(self, group, inventory=None):
Expand Down
3 changes: 2 additions & 1 deletion tower_cli/resources/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class Resource(models.Resource):
description = models.Field(required=False, display=False)
inventory = models.Field(type=types.Related('inventory'))
enabled = models.Field(type=bool, required=False)
variables = models.Field(type=types.Variables(), required=False, display=False,
variables = models.Field(type=types.StructuredInput(allow_kv=True, as_string=True),
required=False, display=False,
help_text='Host variables, use "@" to get from file.')
insights_system_id = models.Field(required=False, display=False)

Expand Down
3 changes: 2 additions & 1 deletion tower_cli/resources/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class Resource(models.Resource):
name = models.Field(unique=True)
description = models.Field(required=False, display=False)
organization = models.Field(type=types.Related('organization'))
variables = models.Field(type=types.Variables(), required=False, display=False,
variables = models.Field(type=types.StructuredInput(allow_kv=True, as_string=True),
required=False, display=False,
help_text='Inventory variables, use "@" to get from file.')
kind = models.Field(type=click.Choice(['', 'smart']), required=False, display=False,
help_text='The kind field. Cannot be modified after created.')
Expand Down
25 changes: 11 additions & 14 deletions tower_cli/utils/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,26 +84,23 @@ def string_to_dict(var_string, allow_kv=True, require_dict=True):
Attempts processing string by 3 different methods in order:
1. as JSON 2. as YAML 3. as custom key=value syntax
Throws an error if all of these fail in the standard ways."""
# try:
# # Accept all valid "key":value types of json
# return_dict = json.loads(var_string)
# assert type(return_dict) is dict
# except (TypeError, AttributeError, ValueError, AssertionError):
try:
# Accept all JSON and YAML
return_dict = yaml.load(var_string)
if require_dict:
assert type(return_dict) is dict
except (AttributeError, yaml.YAMLError, AssertionError):
except (AttributeError, yaml.YAMLError, AssertionError) as yaml_e:
# if these fail, parse by key=value syntax
try:
assert allow_kv
return_dict = parse_kv(var_string)
except Exception:
raise exc.TowerCLIError(
'failed to parse some of the extra '
'variables.\nvariables: \n%s' % var_string
)
msg = six.text_type(
'failed to parse some of the '
'variables.\nvariables: \n{0}\nYAML error: \n{1}'
).format(var_string, yaml_e)
if allow_kv:
try:
return parse_kv(var_string)
except Exception as kv_e:
msg += six.text_type('\nkey=value error: {0}').format(kv_e)
raise exc.TowerCLIError(msg)
return return_dict


Expand Down