Repository: aws-cloudformation/cfn-lint

Issue:
Getting 'W2030:You must specify a valid Default value' in 0.17.1
*cfn-lint version: (`cfn-lint --version`)*
`cfn-lint 0.17.1`

*Description of issue.*
```
[cfn-lint] W2030:You must specify a valid Default value for DemoInstanceType (/Demo/DemoInstanceType).
Valid values are ['a1.2xlarge', 'a1.4xlarge', 'a1.large', 'a1.medium', 'a1.xlarge', 'c1.medium', 'c1.xlarge', 'c3.2xlarge', 'c3.4xlarge', 'c3.8xlarge', 'c3.large', 'c3.xlarge', 'c4.2xlarge', 'c4.4xlarge', 'c4.8xlarge', 'c4.large', 'c4.xlarge', 'c5.18xlarge', 'c5.2xlarge', 'c5.4xlarge', 'c5.9xlarge', 'c5.large', 'c5.xlarge', 'c5d.18xlarge', 'c5d.2xlarge', 'c5d.4xlarge', 'c5d.9xlarge', 'c5d.large', 'c5d.xlarge', 'c5n.18xlarge', 'c5n.2xlarge', 'c5n.4xlarge', 'c5n.9xlarge', 'c5n.large', 'c5n.xlarge', 'cc2.8xlarge', 'cr1.8xlarge', 'd2.2xlarge', 'd2.4xlarge', 'd2.8xlarge', 'd2.xlarge', 'f1.16xlarge', 'f1.2xlarge', 'f1.4xlarge', 'g2.2xlarge', 'g2.8xlarge', 'g3.16xlarge', 'g3.4xlarge', 'g3.8xlarge', 'g3s.xlarge', 'h1.16xlarge', 'h1.2xlarge', 'h1.4xlarge', 'h1.8xlarge', 'hs1.8xlarge', 'i2.2xlarge', 'i2.4xlarge', 'i2.8xlarge', 'i2.xlarge', 'i3.16xlarge', 'i3.2xlarge', 'i3.4xlarge', 'i3.8xlarge', 'i3.large', 'i3.xlarge', 'm1.large', 'm1.medium', 'm1.small', 'm1.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'm2.xlarge', 'm3.2xlarge', 'm3.large', 'm3.medium', 'm3.xlarge', 'm4.10xlarge', 'm4.16xlarge', 'm4.2xlarge', 'm4.4xlarge', 'm4.large', 'm4.xlarge', 'm5.12xlarge', 'm5.24xlarge', 'm5.2xlarge', 'm5.4xlarge', 'm5.large', 'm5.metal', 'm5.xlarge', 'm5a.12xlarge', 'm5a.24xlarge', 'm5a.2xlarge', 'm5a.4xlarge', 'm5a.large', 'm5a.xlarge', 'm5ad.12xlarge', 'm5ad.24xlarge', 'm5ad.2xlarge', 'm5ad.4xlarge', 'm5ad.large', 'm5ad.xlarge', 'm5d.12xlarge', 'm5d.24xlarge', 'm5d.2xlarge', 'm5d.4xlarge', 'm5d.large', 'm5d.metal', 'm5d.xlarge', 'p2.16xlarge', 'p2.8xlarge', 'p2.xlarge', 'p3.16xlarge', 'p3.2xlarge', 'p3.8xlarge', 'p3dn.24xlarge', 'r3.2xlarge', 'r3.4xlarge', 'r3.8xlarge', 'r3.large', 'r3.xlarge', 'r4.16xlarge', 'r4.2xlarge', 'r4.4xlarge', 'r4.8xlarge', 'r4.large', 'r4.xlarge', 'r5.12xlarge', 'r5.24xlarge', 'r5.2xlarge', 'r5.4xlarge', 'r5.large', 'r5.xlarge', 'r5a.12xlarge', 'r5a.24xlarge', 'r5a.2xlarge', 'r5a.4xlarge', 'r5a.large', 'r5a.xlarge', 'r5ad.12xlarge', 'r5ad.24xlarge', 'r5ad.2xlarge', 'r5ad.4xlarge', 'r5ad.large', 'r5ad.xlarge', 'r5d.12xlarge', 'r5d.24xlarge', 'r5d.2xlarge', 'r5d.4xlarge', 'r5d.large', 'r5d.xlarge', 't1.micro', 't2.2xlarge', 't2.large', 't2.medium', 't2.micro', 't2.nano', 't2.small', 't2.xlarge', 't3.2xlarge', 't3.large', 't3.medium', 't3.micro', 't3.nano', 't3.small', 't3.xlarge', 'x1.16xlarge', 'x1.32xlarge', 'x1e.16xlarge', 'x1e.2xlarge', 'x1e.32xlarge', 'x1e.4xlarge', 'x1e.8xlarge', 'x1e.xlarge', 'z1d.12xlarge', 'z1d.2xlarge', 'z1d.3xlarge', 'z1d.6xlarge', 'z1d.large', 'z1d.xlarge']
```

The CloudFormation parameter is :
```
  DemoInstanceType:
    Default: /Demo/DemoInstanceType # Recommend t3.nano
    Description: EC2 instance type to use to create the collector host
    Type: AWS::SSM::Parameter::Value<String>
```

The value of the SSM parameter is `t3.nano`

I have an older project using the same pattern and the virtual environment still has cfn-lint version 0.12.0. It's not raising this complaint. I verified by updating to latest (0.17.1) and the problem cropped up. When I downgraded back to 0.12.0, the problem went away.


Discussion:
Looking into it now.  Thanks for reporting this.

Resolving patch:
diff --git a/src/cfnlint/rules/parameters/AllowedValue.py b/src/cfnlint/rules/parameters/AllowedValue.py
--- a/src/cfnlint/rules/parameters/AllowedValue.py
+++ b/src/cfnlint/rules/parameters/AllowedValue.py
@@ -14,6 +14,7 @@
   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 """
+import six
 from cfnlint import CloudFormationLintRule
 from cfnlint import RuleMatch
 
@@ -47,20 +48,24 @@ def check_value_ref(self, value, **kwargs):
                 param = cfn.template.get('Parameters').get(value, {})
                 parameter_values = param.get('AllowedValues')
                 default_value = param.get('Default')
-
-                # Check Allowed Values
-                if parameter_values:
-                    for index, allowed_value in enumerate(parameter_values):
-                        if allowed_value not in allowed_value_specs:
-                            param_path = ['Parameters', value, 'AllowedValues', index]
-                            message = 'You must specify a valid allowed value for {0} ({1}).\nValid values are {2}'
-                            matches.append(RuleMatch(param_path, message.format(value, allowed_value, allowed_value_specs)))
-                elif default_value:
-                    # Check Default, only if no allowed Values are specified in the parameter (that's covered by E2015)
-                    if default_value not in allowed_value_specs:
-                        param_path = ['Parameters', value, 'Default']
-                        message = 'You must specify a valid Default value for {0} ({1}).\nValid values are {2}'
-                        matches.append(RuleMatch(param_path, message.format(value, default_value, allowed_value_specs)))
+                parameter_type = param.get('Type')
+                if isinstance(parameter_type, six.string_types):
+                    if ((not parameter_type.startswith('List<')) and
+                            (not parameter_type.startswith('AWS::SSM::Parameter::Value<')) and
+                            parameter_type not in ['CommaDelimitedList']):
+                        # Check Allowed Values
+                        if parameter_values:
+                            for index, allowed_value in enumerate(parameter_values):
+                                if allowed_value not in allowed_value_specs:
+                                    param_path = ['Parameters', value, 'AllowedValues', index]
+                                    message = 'You must specify a valid allowed value for {0} ({1}).\nValid values are {2}'
+                                    matches.append(RuleMatch(param_path, message.format(value, allowed_value, allowed_value_specs)))
+                        elif default_value:
+                            # Check Default, only if no allowed Values are specified in the parameter (that's covered by E2015)
+                            if default_value not in allowed_value_specs:
+                                param_path = ['Parameters', value, 'Default']
+                                message = 'You must specify a valid Default value for {0} ({1}).\nValid values are {2}'
+                                matches.append(RuleMatch(param_path, message.format(value, default_value, allowed_value_specs)))
 
         return matches
 


Test patch:
diff --git a/test/fixtures/templates/good/resources/properties/allowed_values.yaml b/test/fixtures/templates/good/resources/properties/allowed_values.yaml
--- a/test/fixtures/templates/good/resources/properties/allowed_values.yaml
+++ b/test/fixtures/templates/good/resources/properties/allowed_values.yaml
@@ -17,6 +17,10 @@ Parameters:
       - "standard"
   ImageId:
     Type: "AWS::EC2::Image::Id"
+  SsmInstanceType:
+    Default: /Demo/DemoInstanceType # Recommend t3.nano
+    Description: EC2 instance type to use to create the collector host
+    Type: AWS::SSM::Parameter::Value<String>
 Resources:
   AmazonMQBroker:
     Type: "AWS::AmazonMQ::Broker"
@@ -525,6 +529,11 @@ Resources:
         - DeviceName: "/dev/sdm"
           Ebs:
             VolumeType: "gp2" # Valid AllowedValue
+  EC2Instance2:
+    Type: AWS::EC2::Instance
+    Properties:
+      ImageId: "ami-2f726546"
+      InstanceType: !Ref SsmInstanceType
   GlueConnection:
     Type: "AWS::Glue::Connection"
     Properties: