Repository: aws-cloudformation/cfn-lint

Issue:
E0002 during E3028: 'dict' object has no attribute 'get_safe'
*cfn-lint version: (0.28.1)*

```
> cfn-lint cloudformation_templates/lint_fail.yaml
E0002 Unknown exception while processing rule E3028: 'dict' object has no attribute 'get_safe'
cloudformation_templates/lint_fail.yaml:1:1
```

This did not occur on 0.27.4, which is what I was running before.

Here's the template:
```yaml
---
AWSTemplateFormatVersion: '2010-09-09'


Parameters:
  Serverless:
    Description: Whether to use Aurora Serverless
    Type: String
    AllowedValues: ["false", "true"]


Conditions:
  UseServerless: !Equals [!Ref Serverless, "true"]


Resources:
  AuroraCluster:
    Type: AWS::RDS::DBCluster
    Properties:
      Engine: aurora-postgresql
      EngineMode: !If [UseServerless, "serverless", "provisioned"]
      EngineVersion: "10.7"
      ScalingConfiguration: !If
        - UseServerless
        - AutoPause: true
          MaxCapacity: 192
          MinCapacity: 384
          SecondsUntilAutoPause: 1800
        - !Ref AWS::NoValue

```


Discussion:
@iamed2 fix coming shortly

Resolving patch:
diff --git a/src/cfnlint/__init__.py b/src/cfnlint/__init__.py
--- a/src/cfnlint/__init__.py
+++ b/src/cfnlint/__init__.py
@@ -24,11 +24,14 @@
 from cfnlint.rules import ParseError as _ParseError
 from cfnlint.rules import TransformError as _TransformError
 from cfnlint.rules import RuleError as _RuleError
+from cfnlint.decode.node import dict_node
 import cfnlint.rules
 
 LOGGER = logging.getLogger(__name__)
 
 # pylint: disable=too-many-lines
+
+
 def refactored(message):
     """ Decoreate for refactoring classes """
     def cls_wrapper(cls):
@@ -745,7 +748,7 @@ def get_value(value, scenario):  # pylint: disable=R0911
 
             return value
 
-        result = {}
+        result = dict_node({}, obj.start_mark, obj.end_mark)
         if isinstance(obj, dict):
             if len(obj) == 1:
                 if obj.get('Fn::If'):
@@ -753,13 +756,11 @@ def get_value(value, scenario):  # pylint: disable=R0911
                     if new_value is not None:
                         result = new_value
                 else:
-                    result = {}
                     for key, value in obj.items():
                         new_value = get_value(value, scenario)
                         if new_value is not None:
                             result[key] = new_value
             else:
-                result = {}
                 for key, value in obj.items():
                     new_value = get_value(value, scenario)
                     if new_value is not None:
diff --git a/src/cfnlint/decode/node.py b/src/cfnlint/decode/node.py
--- a/src/cfnlint/decode/node.py
+++ b/src/cfnlint/decode/node.py
@@ -116,6 +116,9 @@ def get_safe(self, key, default=None, path=None, type_t=()):
                 Get values in format
             """
             path = path or []
+
+            if default == {}:
+                default = dict_node({}, self.start_mark, self.end_mark)
             value = self.get(key, default)
             if value is None and default is None:
                 # if default is None and value is None return empty list
diff --git a/src/cfnlint/rules/resources/rds/AuroraScalingConfiguration.py b/src/cfnlint/rules/resources/rds/AuroraScalingConfiguration.py
--- a/src/cfnlint/rules/resources/rds/AuroraScalingConfiguration.py
+++ b/src/cfnlint/rules/resources/rds/AuroraScalingConfiguration.py
@@ -27,15 +27,20 @@ def check(self, properties, path, cfn):
             properties, ['EngineMode', 'ScalingConfiguration'])
         for property_set in property_sets:
             properties = property_set.get('Object')
+            scenario = property_set.get('Scenario')
             engine_sets = properties.get_safe('EngineMode', type_t=six.string_types)
             for engine, _ in engine_sets:
                 if engine != 'serverless':
                     if properties.get('ScalingConfiguration'):
-                        message = 'You cannot specify ScalingConfiguration for non Aurora Serverless AWS::RDS::DBCluster: {}'
-                        matches.append(RuleMatch(
-                            path,
-                            message.format('/'.join(map(str, path)))
-                        ))
+                        message = 'You cannot specify ScalingConfiguration for non Aurora Serverless AWS::RDS::DBCluster at {}'
+                        if scenario is None:
+                            matches.append(
+                                RuleMatch(path, message.format('/'.join(map(str, path)))))
+                        else:
+                            scenario_text = ' and '.join(
+                                ['when condition "%s" is %s' % (k, v) for (k, v) in scenario.items()])
+                            matches.append(
+                                RuleMatch(path, message.format('/'.join(map(str, path)) + ' ' + scenario_text)))
         return matches
 
     def match_resource_properties(self, properties, _, path, cfn):


Test patch:
diff --git a/test/fixtures/templates/bad/resources/rds/aurora_autoscaling.yaml b/test/fixtures/templates/bad/resources/rds/aurora_autoscaling.yaml
--- a/test/fixtures/templates/bad/resources/rds/aurora_autoscaling.yaml
+++ b/test/fixtures/templates/bad/resources/rds/aurora_autoscaling.yaml
@@ -1,6 +1,15 @@
 ---
 AWSTemplateFormatVersion: 2010-09-09
 
+Parameters:
+  Serverless:
+    Description: Whether to use Aurora Serverless
+    Type: String
+    AllowedValues: ["false", "true"]
+
+Conditions:
+  UseServerless: !Equals [!Ref Serverless, "true"]
+
 Resources:
   DatabaseCluster2:
     Type: AWS::RDS::DBCluster
@@ -11,3 +20,19 @@ Resources:
       ScalingConfiguration:
         MinCapacity: 1
         MaxCapacity: 3
+  DatabaseCluster3:
+    Type: AWS::RDS::DBCluster
+    Properties:
+      Engine: aurora-postgresql
+      EngineMode: !If [UseServerless, "serverless", "provisioned"]
+      EngineVersion: "10.7"
+      ScalingConfiguration: !If
+        - UseServerless
+        - AutoPause: true
+          MaxCapacity: 192
+          MinCapacity: 384
+          SecondsUntilAutoPause: 1800
+        - AutoPause: true
+          MaxCapacity: 192
+          MinCapacity: 384
+          SecondsUntilAutoPause: 1800
diff --git a/test/fixtures/templates/good/resources/rds/aurora_autoscaling.yaml b/test/fixtures/templates/good/resources/rds/aurora_autoscaling.yaml
--- a/test/fixtures/templates/good/resources/rds/aurora_autoscaling.yaml
+++ b/test/fixtures/templates/good/resources/rds/aurora_autoscaling.yaml
@@ -1,6 +1,13 @@
 ---
 AWSTemplateFormatVersion: 2010-09-09
+Parameters:
+  Serverless:
+    Description: Whether to use Aurora Serverless
+    Type: String
+    AllowedValues: ["false", "true"]
 
+Conditions:
+  UseServerless: !Equals [!Ref Serverless, "true"]
 Resources:
   DatabaseCluster1:
     Type: AWS::RDS::DBCluster
@@ -16,3 +23,16 @@ Resources:
       ScalingConfiguration:
         MinCapacity: 1
         MaxCapacity: 3
+  DatabaseCluster3:
+    Type: AWS::RDS::DBCluster
+    Properties:
+      Engine: aurora-postgresql
+      EngineMode: !If [UseServerless, "serverless", "provisioned"]
+      EngineVersion: "10.7"
+      ScalingConfiguration: !If
+        - UseServerless
+        - AutoPause: true
+          MaxCapacity: 192
+          MinCapacity: 384
+          SecondsUntilAutoPause: 1800
+        - !Ref AWS::NoValue
diff --git a/test/unit/module/test_template.py b/test/unit/module/test_template.py
--- a/test/unit/module/test_template.py
+++ b/test/unit/module/test_template.py
@@ -449,7 +449,7 @@ def test_get_conditions_scenarios_from_object(self):
 
     def test_get_object_without_conditions(self):
         """ Test Getting condition names in an object/list """
-        template = {
+        template = cfnlint.helpers.convert_dict({
             'Conditions': {
                 'useAmiId': {'Fn::Not': [{'Fn::Equals': [{'Ref': 'myAmiId'}, '']}]}
             },
@@ -462,7 +462,7 @@ def test_get_object_without_conditions(self):
                     }
                 }
             }
-        }
+        })
         template = Template('test.yaml', template)
 
         results = template.get_object_without_conditions(
@@ -545,7 +545,7 @@ def test_get_object_without_conditions_no_value(self):
 
     def test_get_object_without_conditions_for_list(self):
         """ Test Getting condition names in an object/list """
-        template = {
+        template = cfnlint.helpers.convert_dict({
             'Conditions': {
                 'CreateAppVolume': {'Fn::Equals': [{'Ref': 'CreateVolums'}, 'true']}
             },
@@ -581,7 +581,7 @@ def test_get_object_without_conditions_for_list(self):
                     }
                 }
             }
-        }
+        })
 
         template = Template('test.yaml', template)
 
@@ -667,7 +667,7 @@ def test_get_object_without_conditions_for_bad_formats(self):
 
     def test_get_object_without_nested_conditions(self):
         """ Test Getting condition names in an object/list """
-        template = {
+        template = cfnlint.helpers.convert_dict({
             'Conditions': {
                 'isProduction': {'Fn::Equals': [{'Ref': 'myEnvironment'}, 'prod']},
                 'isDevelopment': {'Fn::Equals': [{'Ref': 'myEnvironment'}, 'dev']}
@@ -692,7 +692,7 @@ def test_get_object_without_nested_conditions(self):
                     }
                 }
             }
-        }
+        })
         template = Template('test.yaml', template)
 
         results = template.get_object_without_conditions(
diff --git a/test/unit/rules/resources/rds/test_aurora_scaling_configuration.py b/test/unit/rules/resources/rds/test_aurora_scaling_configuration.py
--- a/test/unit/rules/resources/rds/test_aurora_scaling_configuration.py
+++ b/test/unit/rules/resources/rds/test_aurora_scaling_configuration.py
@@ -24,4 +24,4 @@ def test_file_positive(self):
     def test_file_negative_alias(self):
         """Test failure"""
         self.helper_file_negative(
-            'test/fixtures/templates/bad/resources/rds/aurora_autoscaling.yaml', 1)
+            'test/fixtures/templates/bad/resources/rds/aurora_autoscaling.yaml', 2)