Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to specify a yaml file as parameters #8133

Open
wants to merge 1 commit into
base: v2
Choose a base branch
from
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
27 changes: 27 additions & 0 deletions awscli/argprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"""Module for processing CLI args."""
import os
import logging

from ruamel.yaml import YAML, YAMLError

from awscli.compat import six

from botocore.compat import OrderedDict, json
Expand Down Expand Up @@ -188,6 +191,16 @@ def _unpack_complex_cli_arg(argument_model, value, cli_name):
if isinstance(value, six.string_types):
if value.lstrip()[0] == '[':
return _unpack_json_cli_arg(argument_model, value, cli_name)
else:
# Value could be yaml so try parsing as yaml
try:
yaml = YAML(typ='safe')
result = yaml.load(value)
if isinstance(result, list):
return result
except YAMLError as e:
# If it's not valid yaml, then we can continue on
pass
elif isinstance(value, list) and len(value) == 1:
single_value = value[0].strip()
if single_value and single_value[0] == '[':
Expand Down Expand Up @@ -406,6 +419,20 @@ def _should_parse_as_shorthand(self, cli_argument, value):
LOG.debug("Param %s looks like JSON, not considered for "
"param shorthand.", cli_argument.py_name)
return False
# The second short-circuit case is if the argument is yaml
if isinstance(check_val, six.string_types):
try:
yaml = YAML(typ='safe')
result = yaml.load(check_val)
# Yaml parsing is only supported for yaml list documents as there are currently no
# known use cases for yaml map documents
if isinstance(result, list):
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't sure if there was a use case for dictionary yaml documents. Let me know if you guys want to support it.

LOG.debug("Param %s looks like YAML, not considered for "
"param shorthand.", cli_argument.py_name)
return False
except YAMLError as e:
# If it's not valid yaml, then we can continue on
pass
model = cli_argument.argument_model
return _supports_shorthand_syntax(model)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
- ParameterKey: SecurityGroupDescription
ParameterValue: "Security group providing SSH access"
- ParameterKey: FromPort
ParameterValue: "22"
- ParameterKey: CidrIp
ParameterValue: "0.0.0.0/0"
18 changes: 18 additions & 0 deletions tests/functional/cloudformation/test_create_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
import os

from awscli.testutils import BaseAWSCommandParamsTest


Expand Down Expand Up @@ -63,3 +65,19 @@ def test_can_handle_empty_parameters(self):
result = {'StackName': 'test', 'TemplateURL': 'http://foo',
'Parameters': []}
self.assert_params_for_cmd(cmdline, result)

def test_can_handle_yaml_parameter_file(self):
param_path = os.path.join(os.path.dirname(__file__), 'create-stack-example-parameters.yml')
cmdline = self.prefix
cmdline += ' --stack-name test --template-url http://foo'
cmdline += ' --parameters file://%s' % param_path
result = {'StackName': 'test', 'TemplateURL': 'http://foo',
'Parameters': [
{'ParameterKey': 'SecurityGroupDescription',
'ParameterValue': 'Security group providing SSH access'},
{'ParameterKey': 'FromPort',
'ParameterValue': '22'},
{'ParameterKey': 'CidrIp',
'ParameterValue': '0.0.0.0/0'},
]}
self.assert_params_for_cmd(cmdline, result)
15 changes: 15 additions & 0 deletions tests/unit/test_argprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ def test_csv_syntax_errors(self):
with self.assertRaisesRegex(ParamError, error_msg):
self.parse_shorthand(p, ['ParameterKey=key,ParameterValue="foo,bar\''])

def test_should_not_parse_list_based_yaml(self):
p = self.get_param_model('cloudformation.CreateStack.Parameters')
returned = self.parse_shorthand(p, ['---\n- ParameterKey: key\n ParameterValue: foo'])
self.assertIsNone(returned)

class TestParamShorthandCustomArguments(BaseArgProcessTest):

Expand Down Expand Up @@ -782,6 +786,17 @@ def test_skip_deeply_nested_shorthand(self):
generated_example = self.get_generated_example_for(argument)
self.assertEqual(generated_example, '')

class TestUnpackYAMLParams(BaseArgProcessTest):
def setUp(self):
super(TestUnpackYAMLParams, self).setUp()
self.simplify = ParamShorthandParser()

def test_yaml_list(self):
p = self.get_param_model('cloudformation.CreateStack.Parameters')
value = '---\n- ParameterKey: key\n ParameterValue: foo'
returned = unpack_cli_arg(p, value)
self.assertEqual(returned, [{'ParameterKey': 'key',
'ParameterValue': 'foo'}])

class TestUnpackJSONParams(BaseArgProcessTest):
def setUp(self):
Expand Down
Loading