Repository: aws/aws-cli

Issue:
aws cloudformation - Error Message if IAM::Group Policy given string is Unclear
### Description of Issue

In CloudFormation, if passing a string to the policy property of a IAM::Group resource the following error is given: `list index out of range`.
### Steps to Reproduce

Using `aws cloudformation` provide a template file that contains the following:
`"GroupDevelopers" : {
  "Type": "AWS::IAM::Group",
  "Properties": {
    "Policies": {"Ref": "PolicyDevelopers"}
    }
 }`
### Run

`aws cloudformation create-stack --stack-name Test --parameters --template-body file://test.template`
### Result

`aws cloudformation create-stack --stack-name Test --parameters --template-body file://test.template`
`list index out of range`
### Expected Result

A more descriptive error message.
### Documentation Detailing only Lists Expected

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-group.html



Discussion:
Agreed, this is not a good error message.  The actual problem is related to when a parameter is of type `list`:

```
       --parameters (list)
          A list of Parameter structures that specify input parameters for the
          stack.
```

which expects space separated values, but if no value is provided, you'll get a bad error message, as shown in your above command:

```
...  create-stack --stack-name Test --parameters      --template-body file://test.template
                                                ^^^^missing values
```

You can either:

a) omit the parameter
b) if you meant to explicitly send an empty list to the service (for some services an empty list is significant and means something different than omitting the param altogether), you can use the `--parameters []` syntax


Resolving patch:
diff --git a/awscli/argprocess.py b/awscli/argprocess.py
--- a/awscli/argprocess.py
+++ b/awscli/argprocess.py
@@ -349,7 +349,7 @@ def _should_parse_as_shorthand(self, cli_argument, value):
         # We first need to make sure this is a parameter that qualifies
         # for simplification.  The first short-circuit case is if it looks
         # like json we immediately return.
-        if isinstance(value, list):
+        if value and isinstance(value, list):
             check_val = value[0]
         else:
             check_val = value


Test patch:
diff --git a/tests/functional/cloudformation/test_create_stack.py b/tests/functional/cloudformation/test_create_stack.py
--- a/tests/functional/cloudformation/test_create_stack.py
+++ b/tests/functional/cloudformation/test_create_stack.py
@@ -14,7 +14,7 @@
 from awscli.testutils import BaseAWSCommandParamsTest
 
 
-class TestDescribeInstances(BaseAWSCommandParamsTest):
+class TestCreateStack(BaseAWSCommandParamsTest):
 
     prefix = 'cloudformation create-stack'
 
@@ -56,3 +56,10 @@ def test_create_stack_for_csv_with_quoting(self):
                   'Parameters': [{'ParameterKey': 'foo',
                                   'ParameterValue': 'one,two'}]}
         self.assert_params_for_cmd(cmdline, result)
+
+    def test_can_handle_empty_parameters(self):
+        cmdline = self.prefix
+        cmdline += ' --stack-name test --parameters --template-url http://foo'
+        result = {'StackName': 'test', 'TemplateURL': 'http://foo',
+                  'Parameters': []}
+        self.assert_params_for_cmd(cmdline, result)
diff --git a/tests/unit/test_argprocess.py b/tests/unit/test_argprocess.py
--- a/tests/unit/test_argprocess.py
+++ b/tests/unit/test_argprocess.py
@@ -265,6 +265,12 @@ def test_list_structure_list_scalar_2(self):
 
         self.assertEqual(simplified, expected)
 
+    def test_empty_value_of_list_structure(self):
+        p = self.get_param_model('emr.ModifyInstanceGroups.InstanceGroups')
+        expected = []
+        simplified = self.simplify(p, [])
+        self.assertEqual(simplified, expected)
+
     def test_list_structure_list_multiple_scalar(self):
         p = self.get_param_model(
             'emr.ModifyInstanceGroups.InstanceGroups')