text: """
  Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  SPDX-License-Identifier: MIT-0
  """
  import six
  from cfnlint.rules import CloudFormationLintRule
  from cfnlint.rules import RuleMatch
  
  
  class UpdateReplacePolicy(CloudFormationLintRule):
      """Check Base Resource Configuration"""
      id = 'E3036'
      shortdesc = 'Check UpdateReplacePolicy values for Resources'
      description = 'Check that the UpdateReplacePolicy values are valid'
      source_url = 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html'
      tags = ['resources', 'updatereplacepolicy']
  
      def check_value(self, key, path, res_type):
          """Check resource names for UpdateReplacePolicy"""
          matches = []
  
          valid_values = [
              'Delete',
              'Retain',
              'Snapshot'
          ]
  
          valid_snapshot_types = [
              'AWS::EC2::Volume',
              'AWS::ElastiCache::CacheCluster',
              'AWS::ElastiCache::ReplicationGroup',
              'AWS::Neptune::DBCluster',
              'AWS::RDS::DBCluster',
              'AWS::RDS::DBInstance',
              'AWS::Redshift::Cluster',
          ]
          if not isinstance(key, (six.text_type, six.string_types)):
              message = 'UpdateReplacePolicy values should be of string at {0}'
              matches.append(RuleMatch(path, message.format('/'.join(map(str, path)))))
              return matches
          if key not in valid_values:
              message = 'UpdateReplacePolicy should be only one of {0} at {1}'
              matches.append(RuleMatch(
                  path,
                  message.format(', '.join(map(str, valid_values)),
                                 '/'.join(map(str, path)))))
          if key == 'Snapshot' and res_type not in valid_snapshot_types:
              message = 'UpdateReplacePolicy cannot be Snapshot for resources of type {0} at {1}'
              matches.append(RuleMatch(
                  path,
                  message.format(res_type,
                                 '/'.join(map(str, path)))))
  
          return matches
  
      def match(self, cfn):
          """Check CloudFormation Resources"""
  
          matches = []
  
          resources = cfn.get_resources()
  
          for resource_name, resource_values in resources.items():
              updatereplace_policies = resource_values.get('UpdateReplacePolicy')
              if updatereplace_policies:
                  path = ['Resources', resource_name, 'UpdateReplacePolicy']
                  res_type = resource_values.get('Type')
                  self.logger.debug('Validating UpdateReplacePolicy for %s base configuration', resource_name)
                  if isinstance(updatereplace_policies, list):
                      message = 'Only one UpdateReplacePolicy allowed per resource at {0}'
                      matches.append(RuleMatch(path, message.format('/'.join(map(str, path)))))
                  else:
                      matches.extend(self.check_value(updatereplace_policies, path, res_type))
  
          return matches
  