prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  I3013 - Incorrectly flagged for aurora-<engine> database instances
  **cfn-lint version**: 0.61.3
  
  cfn-lint is falsely flagging the missing `BackupRetentionPeriod` property and it's subsequent value from `AWS::RDS:DBInstance` for an Aurora based database instance.
  
  This property and a set value **is not required** if it is part of an Aurora cluster. Assumption is the `Engine` property value would need to be checked for the presence of `aurora-<engine>` to not flag this linting issue.
  
  I suspect if the value is set via a CloudFormation function cfn-lint would still incorrectly flag this.
  
  **AWS Documentation reference** - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-backupretentionperiod
  
  > Amazon Aurora
  > Not applicable. The retention period for automated backups is managed by the DB cluster.
  
  **CloudFormation example**
  
  ```yaml
  AuroraInstance:
      Type: AWS::RDS::DBInstance
      DeletionPolicy: Retain
      UpdateReplacePolicy: Retain
      Properties:
        AllowMajorVersionUpgrade: false
        AutoMinorVersionUpgrade: !Ref AutoMinorVersionUpgrade
        DBClusterIdentifier: !Ref AuroraCluster
        DBInstanceClass: !Ref InstanceClass
        DBInstanceIdentifier: "MyAuroraInstance"
        DBParameterGroupName: !Ref ParamGroup
        DBSubnetGroupName: !Ref SubnetGroup
        DeleteAutomatedBackups: !Ref DeleteAutomatedBackups
        EnablePerformanceInsights: !Ref EnablePerformanceInsights
        Engine: aurora-postgresql
        EngineVersion: !Ref EngineVersion
        PerformanceInsightsKMSKeyId: !Ref KmsKey
        PerformanceInsightsRetentionPeriod: 7
        PubliclyAccessible: false
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py`
  Content:
  ```
  1 """
  2 Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3 SPDX-License-Identifier: MIT-0
  4 """
  5 from cfnlint.rules import CloudFormationLintRule
  6 from cfnlint.rules import RuleMatch
  7 
  8 
  9 class RetentionPeriodOnResourceTypesWithAutoExpiringContent(CloudFormationLintRule):
  10     """Check for RetentionPeriod """
  11     id = 'I3013'
  12     shortdesc = 'Check resources with auto expiring content have explicit retention period'
  13     description = 'The behaviour for data retention is different across AWS Services.'\
  14                   'If no retention period is specified the default for some services is to delete the data after a period of time.' \
  15                   'This check requires you to explicitly set the retention period for those resources to avoid unexpected data losses'
  16     source_url = 'https://github.com/aws-cloudformation/cfn-python-lint'
  17     tags = ['resources', 'retentionperiod']
  18 
  19     def _check_ref(self, value, parameters, resources, path):  # pylint: disable=W0613
  20         print('called')
  21         print(value)
  22 
  23     def match(self, cfn):
  24         """Check for RetentionPeriod"""
  25         matches = []
  26 
  27         retention_attributes_by_resource_type = {
  28             'AWS::Kinesis::Stream': [
  29                 {
  30                     'Attribute': 'RetentionPeriodHours',
  31                     'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesis-stream.html#cfn-kinesis-stream-retentionperiodhours'
  32                 }
  33             ],
  34             'AWS::SQS::Queue':  [
  35                 {
  36                     'Attribute': 'MessageRetentionPeriod',
  37                     'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#aws-sqs-queue-msgretentionperiod'
  38                 }
  39             ],
  40             'AWS::DocDB::DBCluster': [
  41                 {
  42                     'Attribute': 'BackupRetentionPeriod',
  43                     'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-docdb-dbcluster.html#cfn-docdb-dbcluster-backupretentionperiod'
  44                 }
  45             ],
  46             'AWS::Synthetics::Canary': [
  47                 {
  48                     'Attribute': 'SuccessRetentionPeriod',
  49                     'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html#cfn-synthetics-canary-successretentionperiod'
  50                 },
  51                 {
  52                     'Attribute': 'FailureRetentionPeriod',
  53                     'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html#cfn-synthetics-canary-failureretentionperiod'
  54                 }
  55             ],
  56             'AWS::Redshift::Cluster': [
  57                 {
  58                     'Attribute': 'AutomatedSnapshotRetentionPeriod',
  59                     'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-automatedsnapshotretentionperiod'
  60                 }
  61             ],
  62             'AWS::RDS::DBInstance': [
  63                 {
  64                     'Attribute': 'BackupRetentionPeriod',
  65                     'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-backupretentionperiod'
  66                 }
  67             ],
  68             'AWS::RDS::DBCluster': [
  69                 {
  70                     'Attribute': 'BackupRetentionPeriod',
  71                     'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-backuprententionperiod'
  72                 }
  73             ]
  74         }
  75 
  76         resources = cfn.get_resources()
  77         for r_name, r_values in resources.items():
  78             if r_values.get('Type') in retention_attributes_by_resource_type:
  79                 for attr_def in retention_attributes_by_resource_type[r_values.get('Type')]:
  80                     property_sets = r_values.get_safe('Properties')
  81                     for property_set, path in property_sets:
  82                         error_path = ['Resources', r_name] + path
  83                         if not property_set:
  84                             message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(
  85                                 str(x) for x in error_path)
  86                             matches.append(RuleMatch(error_path, message))
  87                         else:
  88                             value = property_set.get(attr_def.get('Attribute'))
  89                             if not value:
  90                                 message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(
  91                                     str(x) for x in error_path)
  92                                 matches.append(RuleMatch(error_path, message))
  93                             if isinstance(value, dict):
  94                                 # pylint: disable=protected-access
  95                                 refs = cfn._search_deep_keys(
  96                                     'Ref', value, error_path + [attr_def.get('Attribute')])
  97                                 for ref in refs:
  98                                     if ref[-1] == 'AWS::NoValue':
  99                                         message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(
  100                                             str(x) for x in ref[0:-1])
  101                                         matches.append(RuleMatch(ref[0:-1], message))
  102 
  103         return matches
  104
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py b/src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py
  --- a/src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py
  +++ b/src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py
  @@ -2,6 +2,7 @@
   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   SPDX-License-Identifier: MIT-0
   """
  +import re
   from cfnlint.rules import CloudFormationLintRule
   from cfnlint.rules import RuleMatch
   
  @@ -17,7 +18,6 @@
       tags = ['resources', 'retentionperiod']
   
       def _check_ref(self, value, parameters, resources, path):  # pylint: disable=W0613
  -        print('called')
           print(value)
   
       def match(self, cfn):
  @@ -62,7 +62,9 @@
               'AWS::RDS::DBInstance': [
                   {
                       'Attribute': 'BackupRetentionPeriod',
  -                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-backupretentionperiod'
  +                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-backupretentionperiod',
  +                    'CheckAttribute': 'Engine',
  +                    'CheckAttributeRegex': re.compile('^((?!aurora).)*$'),
                   }
               ],
               'AWS::RDS::DBCluster': [
  @@ -81,23 +83,29 @@
                       for property_set, path in property_sets:
                           error_path = ['Resources', r_name] + path
                           if not property_set:
  -                            message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(
  -                                str(x) for x in error_path)
  +                            message = f'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : {"/".join(str(x) for x in error_path)}'
                               matches.append(RuleMatch(error_path, message))
                           else:
                               value = property_set.get(attr_def.get('Attribute'))
                               if not value:
  -                                message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(
  -                                    str(x) for x in error_path)
  -                                matches.append(RuleMatch(error_path, message))
  +                                message = f'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : {"/".join(str(x) for x in error_path)}'
  +                                if attr_def.get('CheckAttribute'):
  +                                    if self._validate_property(property_set.get(attr_def.get('CheckAttribute')), attr_def.get('CheckAttributeRegex')):
  +                                        matches.append(RuleMatch(error_path, message))
  +                                else:
  +                                    matches.append(RuleMatch(error_path, message))
                               if isinstance(value, dict):
                                   # pylint: disable=protected-access
                                   refs = cfn._search_deep_keys(
                                       'Ref', value, error_path + [attr_def.get('Attribute')])
                                   for ref in refs:
                                       if ref[-1] == 'AWS::NoValue':
  -                                        message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(
  -                                            str(x) for x in ref[0:-1])
  +                                        message = f'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : {"/".join(str(x) for x in ref[0:-1])}'
                                           matches.append(RuleMatch(ref[0:-1], message))
   
           return matches
  +
  +    def _validate_property(self, value, regex) -> bool:
  +        if regex.match(value):
  +            return True
  +        return False
  
verification_info: {"golden_diff": "diff --git a/src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py b/src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py\n--- a/src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py\n+++ b/src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py\n@@ -2,6 +2,7 @@\n Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n SPDX-License-Identifier: MIT-0\n \"\"\"\n+import re\n from cfnlint.rules import CloudFormationLintRule\n from cfnlint.rules import RuleMatch\n \n@@ -17,7 +18,6 @@\n     tags = ['resources', 'retentionperiod']\n \n     def _check_ref(self, value, parameters, resources, path):  # pylint: disable=W0613\n-        print('called')\n         print(value)\n \n     def match(self, cfn):\n@@ -62,7 +62,9 @@\n             'AWS::RDS::DBInstance': [\n                 {\n                     'Attribute': 'BackupRetentionPeriod',\n-                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-backupretentionperiod'\n+                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-backupretentionperiod',\n+                    'CheckAttribute': 'Engine',\n+                    'CheckAttributeRegex': re.compile('^((?!aurora).)*$'),\n                 }\n             ],\n             'AWS::RDS::DBCluster': [\n@@ -81,23 +83,29 @@\n                     for property_set, path in property_sets:\n                         error_path = ['Resources', r_name] + path\n                         if not property_set:\n-                            message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(\n-                                str(x) for x in error_path)\n+                            message = f'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : {\"/\".join(str(x) for x in error_path)}'\n                             matches.append(RuleMatch(error_path, message))\n                         else:\n                             value = property_set.get(attr_def.get('Attribute'))\n                             if not value:\n-                                message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(\n-                                    str(x) for x in error_path)\n-                                matches.append(RuleMatch(error_path, message))\n+                                message = f'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : {\"/\".join(str(x) for x in error_path)}'\n+                                if attr_def.get('CheckAttribute'):\n+                                    if self._validate_property(property_set.get(attr_def.get('CheckAttribute')), attr_def.get('CheckAttributeRegex')):\n+                                        matches.append(RuleMatch(error_path, message))\n+                                else:\n+                                    matches.append(RuleMatch(error_path, message))\n                             if isinstance(value, dict):\n                                 # pylint: disable=protected-access\n                                 refs = cfn._search_deep_keys(\n                                     'Ref', value, error_path + [attr_def.get('Attribute')])\n                                 for ref in refs:\n                                     if ref[-1] == 'AWS::NoValue':\n-                                        message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(\n-                                            str(x) for x in ref[0:-1])\n+                                        message = f'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : {\"/\".join(str(x) for x in ref[0:-1])}'\n                                         matches.append(RuleMatch(ref[0:-1], message))\n \n         return matches\n+\n+    def _validate_property(self, value, regex) -> bool:\n+        if regex.match(value):\n+            return True\n+        return False\n", "issue": "I3013 - Incorrectly flagged for aurora-<engine> database instances\n**cfn-lint version**: 0.61.3\r\n\r\ncfn-lint is falsely flagging the missing `BackupRetentionPeriod` property and it's subsequent value from `AWS::RDS:DBInstance` for an Aurora based database instance.\r\n\r\nThis property and a set value **is not required** if it is part of an Aurora cluster. Assumption is the `Engine` property value would need to be checked for the presence of `aurora-<engine>` to not flag this linting issue.\r\n\r\nI suspect if the value is set via a CloudFormation function cfn-lint would still incorrectly flag this.\r\n\r\n**AWS Documentation reference** - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-backupretentionperiod\r\n\r\n> Amazon Aurora\r\n> Not applicable. The retention period for automated backups is managed by the DB cluster.\r\n\r\n**CloudFormation example**\r\n\r\n```yaml\r\nAuroraInstance:\r\n    Type: AWS::RDS::DBInstance\r\n    DeletionPolicy: Retain\r\n    UpdateReplacePolicy: Retain\r\n    Properties:\r\n      AllowMajorVersionUpgrade: false\r\n      AutoMinorVersionUpgrade: !Ref AutoMinorVersionUpgrade\r\n      DBClusterIdentifier: !Ref AuroraCluster\r\n      DBInstanceClass: !Ref InstanceClass\r\n      DBInstanceIdentifier: \"MyAuroraInstance\"\r\n      DBParameterGroupName: !Ref ParamGroup\r\n      DBSubnetGroupName: !Ref SubnetGroup\r\n      DeleteAutomatedBackups: !Ref DeleteAutomatedBackups\r\n      EnablePerformanceInsights: !Ref EnablePerformanceInsights\r\n      Engine: aurora-postgresql\r\n      EngineVersion: !Ref EngineVersion\r\n      PerformanceInsightsKMSKeyId: !Ref KmsKey\r\n      PerformanceInsightsRetentionPeriod: 7\r\n      PubliclyAccessible: false\r\n```\r\n\n", "before_files": [{"content": "\"\"\"\nCopyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\nfrom cfnlint.rules import CloudFormationLintRule\nfrom cfnlint.rules import RuleMatch\n\n\nclass RetentionPeriodOnResourceTypesWithAutoExpiringContent(CloudFormationLintRule):\n    \"\"\"Check for RetentionPeriod \"\"\"\n    id = 'I3013'\n    shortdesc = 'Check resources with auto expiring content have explicit retention period'\n    description = 'The behaviour for data retention is different across AWS Services.'\\\n                  'If no retention period is specified the default for some services is to delete the data after a period of time.' \\\n                  'This check requires you to explicitly set the retention period for those resources to avoid unexpected data losses'\n    source_url = 'https://github.com/aws-cloudformation/cfn-python-lint'\n    tags = ['resources', 'retentionperiod']\n\n    def _check_ref(self, value, parameters, resources, path):  # pylint: disable=W0613\n        print('called')\n        print(value)\n\n    def match(self, cfn):\n        \"\"\"Check for RetentionPeriod\"\"\"\n        matches = []\n\n        retention_attributes_by_resource_type = {\n            'AWS::Kinesis::Stream': [\n                {\n                    'Attribute': 'RetentionPeriodHours',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesis-stream.html#cfn-kinesis-stream-retentionperiodhours'\n                }\n            ],\n            'AWS::SQS::Queue':  [\n                {\n                    'Attribute': 'MessageRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#aws-sqs-queue-msgretentionperiod'\n                }\n            ],\n            'AWS::DocDB::DBCluster': [\n                {\n                    'Attribute': 'BackupRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-docdb-dbcluster.html#cfn-docdb-dbcluster-backupretentionperiod'\n                }\n            ],\n            'AWS::Synthetics::Canary': [\n                {\n                    'Attribute': 'SuccessRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html#cfn-synthetics-canary-successretentionperiod'\n                },\n                {\n                    'Attribute': 'FailureRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html#cfn-synthetics-canary-failureretentionperiod'\n                }\n            ],\n            'AWS::Redshift::Cluster': [\n                {\n                    'Attribute': 'AutomatedSnapshotRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-automatedsnapshotretentionperiod'\n                }\n            ],\n            'AWS::RDS::DBInstance': [\n                {\n                    'Attribute': 'BackupRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-backupretentionperiod'\n                }\n            ],\n            'AWS::RDS::DBCluster': [\n                {\n                    'Attribute': 'BackupRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-backuprententionperiod'\n                }\n            ]\n        }\n\n        resources = cfn.get_resources()\n        for r_name, r_values in resources.items():\n            if r_values.get('Type') in retention_attributes_by_resource_type:\n                for attr_def in retention_attributes_by_resource_type[r_values.get('Type')]:\n                    property_sets = r_values.get_safe('Properties')\n                    for property_set, path in property_sets:\n                        error_path = ['Resources', r_name] + path\n                        if not property_set:\n                            message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(\n                                str(x) for x in error_path)\n                            matches.append(RuleMatch(error_path, message))\n                        else:\n                            value = property_set.get(attr_def.get('Attribute'))\n                            if not value:\n                                message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(\n                                    str(x) for x in error_path)\n                                matches.append(RuleMatch(error_path, message))\n                            if isinstance(value, dict):\n                                # pylint: disable=protected-access\n                                refs = cfn._search_deep_keys(\n                                    'Ref', value, error_path + [attr_def.get('Attribute')])\n                                for ref in refs:\n                                    if ref[-1] == 'AWS::NoValue':\n                                        message = 'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : %s' % '/'.join(\n                                            str(x) for x in ref[0:-1])\n                                        matches.append(RuleMatch(ref[0:-1], message))\n\n        return matches\n", "path": "src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py"}], "after_files": [{"content": "\"\"\"\nCopyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\nimport re\nfrom cfnlint.rules import CloudFormationLintRule\nfrom cfnlint.rules import RuleMatch\n\n\nclass RetentionPeriodOnResourceTypesWithAutoExpiringContent(CloudFormationLintRule):\n    \"\"\"Check for RetentionPeriod \"\"\"\n    id = 'I3013'\n    shortdesc = 'Check resources with auto expiring content have explicit retention period'\n    description = 'The behaviour for data retention is different across AWS Services.'\\\n                  'If no retention period is specified the default for some services is to delete the data after a period of time.' \\\n                  'This check requires you to explicitly set the retention period for those resources to avoid unexpected data losses'\n    source_url = 'https://github.com/aws-cloudformation/cfn-python-lint'\n    tags = ['resources', 'retentionperiod']\n\n    def _check_ref(self, value, parameters, resources, path):  # pylint: disable=W0613\n        print(value)\n\n    def match(self, cfn):\n        \"\"\"Check for RetentionPeriod\"\"\"\n        matches = []\n\n        retention_attributes_by_resource_type = {\n            'AWS::Kinesis::Stream': [\n                {\n                    'Attribute': 'RetentionPeriodHours',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesis-stream.html#cfn-kinesis-stream-retentionperiodhours'\n                }\n            ],\n            'AWS::SQS::Queue':  [\n                {\n                    'Attribute': 'MessageRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#aws-sqs-queue-msgretentionperiod'\n                }\n            ],\n            'AWS::DocDB::DBCluster': [\n                {\n                    'Attribute': 'BackupRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-docdb-dbcluster.html#cfn-docdb-dbcluster-backupretentionperiod'\n                }\n            ],\n            'AWS::Synthetics::Canary': [\n                {\n                    'Attribute': 'SuccessRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html#cfn-synthetics-canary-successretentionperiod'\n                },\n                {\n                    'Attribute': 'FailureRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-synthetics-canary.html#cfn-synthetics-canary-failureretentionperiod'\n                }\n            ],\n            'AWS::Redshift::Cluster': [\n                {\n                    'Attribute': 'AutomatedSnapshotRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-automatedsnapshotretentionperiod'\n                }\n            ],\n            'AWS::RDS::DBInstance': [\n                {\n                    'Attribute': 'BackupRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-backupretentionperiod',\n                    'CheckAttribute': 'Engine',\n                    'CheckAttributeRegex': re.compile('^((?!aurora).)*$'),\n                }\n            ],\n            'AWS::RDS::DBCluster': [\n                {\n                    'Attribute': 'BackupRetentionPeriod',\n                    'SourceUrl': 'http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-backuprententionperiod'\n                }\n            ]\n        }\n\n        resources = cfn.get_resources()\n        for r_name, r_values in resources.items():\n            if r_values.get('Type') in retention_attributes_by_resource_type:\n                for attr_def in retention_attributes_by_resource_type[r_values.get('Type')]:\n                    property_sets = r_values.get_safe('Properties')\n                    for property_set, path in property_sets:\n                        error_path = ['Resources', r_name] + path\n                        if not property_set:\n                            message = f'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : {\"/\".join(str(x) for x in error_path)}'\n                            matches.append(RuleMatch(error_path, message))\n                        else:\n                            value = property_set.get(attr_def.get('Attribute'))\n                            if not value:\n                                message = f'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : {\"/\".join(str(x) for x in error_path)}'\n                                if attr_def.get('CheckAttribute'):\n                                    if self._validate_property(property_set.get(attr_def.get('CheckAttribute')), attr_def.get('CheckAttributeRegex')):\n                                        matches.append(RuleMatch(error_path, message))\n                                else:\n                                    matches.append(RuleMatch(error_path, message))\n                            if isinstance(value, dict):\n                                # pylint: disable=protected-access\n                                refs = cfn._search_deep_keys(\n                                    'Ref', value, error_path + [attr_def.get('Attribute')])\n                                for ref in refs:\n                                    if ref[-1] == 'AWS::NoValue':\n                                        message = f'The default retention period will delete the data after a pre-defined time. Set an explicit values to avoid data loss on resource : {\"/\".join(str(x) for x in ref[0:-1])}'\n                                        matches.append(RuleMatch(ref[0:-1], message))\n\n        return matches\n\n    def _validate_property(self, value, regex) -> bool:\n        if regex.match(value):\n            return True\n        return False\n", "path": "src/cfnlint/rules/resources/RetentionPeriodOnResourceTypesWithAutoExpiringContent.py"}]}