from moto.core.responses import BaseResponse from .exceptions import ( InvalidParameterCombinationException, InvalidParameterValueException, PasswordTooShort, ) from .models import ElastiCacheBackend, elasticache_backends from .utils import VALID_AUTH_MODE_KEYS, VALID_ENGINE_TYPES, AuthenticationTypes class ElastiCacheResponse(BaseResponse): """Handler for ElastiCache requests and responses.""" def __init__(self) -> None: super().__init__(service_name="elasticache") @property def elasticache_backend(self) -> ElastiCacheBackend: """Return backend instance specific for this region.""" return elasticache_backends[self.current_account][self.region] def create_user(self) -> str: params = self._get_params() user_id = params.get("UserId") user_name = params.get("UserName") engine = params.get("Engine", "").lower() passwords = params.get("Passwords", []) no_password_required = self._get_bool_param("NoPasswordRequired") authentication_mode = params.get("AuthenticationMode") authentication_type = "null" if no_password_required is not None: authentication_type = ( AuthenticationTypes.NOPASSWORD.value if no_password_required else AuthenticationTypes.PASSWORD.value ) if passwords: authentication_type = AuthenticationTypes.PASSWORD.value if engine not in VALID_ENGINE_TYPES: raise InvalidParameterValueException( f'Unknown parameter for Engine: "{engine}", must be one of: {", ".join(VALID_ENGINE_TYPES)}' ) if authentication_mode: for key in authentication_mode.keys(): if key not in VALID_AUTH_MODE_KEYS: raise InvalidParameterValueException( f'Unknown parameter in AuthenticationMode: "{key}", must be one of: {", ".join(VALID_AUTH_MODE_KEYS)}' ) authentication_type = authentication_mode.get("Type") authentication_passwords = authentication_mode.get("Passwords", []) if passwords and authentication_passwords: raise InvalidParameterCombinationException( "Passwords provided via multiple arguments. Use only one argument" ) # if passwords is empty, then we can use the authentication_passwords passwords = passwords if passwords else authentication_passwords if any([len(p) < 16 for p in passwords]): raise PasswordTooShort access_string = params.get("AccessString") user = self.elasticache_backend.create_user( user_id=user_id, # type: ignore[arg-type] user_name=user_name, # type: ignore[arg-type] engine=engine, # type: ignore[arg-type] passwords=passwords, access_string=access_string, # type: ignore[arg-type] no_password_required=no_password_required, authentication_type=authentication_type, ) template = self.response_template(CREATE_USER_TEMPLATE) return template.render(user=user) def delete_user(self) -> str: params = self._get_params() user_id = params.get("UserId") user = self.elasticache_backend.delete_user(user_id=user_id) # type: ignore[arg-type] template = self.response_template(DELETE_USER_TEMPLATE) return template.render(user=user) def describe_users(self) -> str: params = self._get_params() user_id = params.get("UserId") users = self.elasticache_backend.describe_users(user_id=user_id) template = self.response_template(DESCRIBE_USERS_TEMPLATE) return template.render(users=users) def create_cache_cluster(self) -> str: cache_cluster_id = self._get_param("CacheClusterId") replication_group_id = self._get_param("ReplicationGroupId") az_mode = self._get_param("AZMode") preferred_availability_zone = self._get_param("PreferredAvailabilityZone") preferred_availability_zones = self._get_param("PreferredAvailabilityZones") num_cache_nodes = self._get_int_param("NumCacheNodes") cache_node_type = self._get_param("CacheNodeType") engine = self._get_param("Engine") engine_version = self._get_param("EngineVersion") cache_parameter_group_name = self._get_param("CacheParameterGroupName") cache_subnet_group_name = self._get_param("CacheSubnetGroupName") cache_security_group_names = self._get_param("CacheSecurityGroupNames") security_group_ids = self._get_param("SecurityGroupIds") tags = (self._get_multi_param_dict("Tags") or {}).get("Tag", []) snapshot_arns = self._get_param("SnapshotArns") snapshot_name = self._get_param("SnapshotName") preferred_maintenance_window = self._get_param("PreferredMaintenanceWindow") port = self._get_param("Port") notification_topic_arn = self._get_param("NotificationTopicArn") auto_minor_version_upgrade = self._get_bool_param("AutoMinorVersionUpgrade") snapshot_retention_limit = self._get_int_param("SnapshotRetentionLimit") snapshot_window = self._get_param("SnapshotWindow") auth_token = self._get_param("AuthToken") outpost_mode = self._get_param("OutpostMode") preferred_outpost_arn = self._get_param("PreferredOutpostArn") preferred_outpost_arns = self._get_param("PreferredOutpostArns") log_delivery_configurations = self._get_param("LogDeliveryConfigurations") transit_encryption_enabled = self._get_bool_param("TransitEncryptionEnabled") network_type = self._get_param("NetworkType") ip_discovery = self._get_param("IpDiscovery") # Define the following attributes as they're included in the response even during creation of a cache cluster cache_node_ids_to_remove = self._get_param("CacheNodeIdsToRemove", []) cache_node_ids_to_reboot = self._get_param("CacheNodeIdsToReboot", []) cache_cluster = self.elasticache_backend.create_cache_cluster( cache_cluster_id=cache_cluster_id, replication_group_id=replication_group_id, az_mode=az_mode, preferred_availability_zone=preferred_availability_zone, preferred_availability_zones=preferred_availability_zones, num_cache_nodes=num_cache_nodes, cache_node_type=cache_node_type, engine=engine, engine_version=engine_version, cache_parameter_group_name=cache_parameter_group_name, cache_subnet_group_name=cache_subnet_group_name, cache_security_group_names=cache_security_group_names, security_group_ids=security_group_ids, tags=tags, snapshot_arns=snapshot_arns, snapshot_name=snapshot_name, preferred_maintenance_window=preferred_maintenance_window, port=port, notification_topic_arn=notification_topic_arn, auto_minor_version_upgrade=auto_minor_version_upgrade, snapshot_retention_limit=snapshot_retention_limit, snapshot_window=snapshot_window, auth_token=auth_token, outpost_mode=outpost_mode, preferred_outpost_arn=preferred_outpost_arn, preferred_outpost_arns=preferred_outpost_arns, log_delivery_configurations=log_delivery_configurations, transit_encryption_enabled=transit_encryption_enabled, network_type=network_type, ip_discovery=ip_discovery, cache_node_ids_to_remove=cache_node_ids_to_remove, cache_node_ids_to_reboot=cache_node_ids_to_reboot, ) template = self.response_template(CREATE_CACHE_CLUSTER_TEMPLATE) return template.render(cache_cluster=cache_cluster) def describe_cache_clusters(self) -> str: cache_cluster_id = self._get_param("CacheClusterId") max_records = self._get_int_param("MaxRecords") marker = self._get_param("Marker") cache_clusters, marker = self.elasticache_backend.describe_cache_clusters( cache_cluster_id=cache_cluster_id, marker=marker, max_records=max_records, ) template = self.response_template(DESCRIBE_CACHE_CLUSTERS_TEMPLATE) return template.render(marker=marker, cache_clusters=cache_clusters) def delete_cache_cluster(self) -> str: cache_cluster_id = self._get_param("CacheClusterId") cache_cluster = self.elasticache_backend.delete_cache_cluster( cache_cluster_id=cache_cluster_id, ) template = self.response_template(DELETE_CACHE_CLUSTER_TEMPLATE) return template.render(cache_cluster=cache_cluster) def list_tags_for_resource(self) -> str: arn = self._get_param("ResourceName") template = self.response_template(LIST_TAGS_FOR_RESOURCE_TEMPLATE) tags = self.elasticache_backend.list_tags_for_resource(arn) return template.render(tags=tags) USER_TEMPLATE = """<UserId>{{ user.id }}</UserId> <UserName>{{ user.name }}</UserName> <Status>{{ user.status }}</Status> <Engine>{{ user.engine }}</Engine> <MinimumEngineVersion>{{ user.minimum_engine_version }}</MinimumEngineVersion> <AccessString>{{ user.access_string }}</AccessString> <UserGroupIds> {% for usergroupid in user.usergroupids %} <member>{{ usergroupid }}</member> {% endfor %} </UserGroupIds> <Authentication> {% if user.no_password_required %} <Type>no-password</Type> {% else %} <Type>{{ user.authentication_type }}</Type> {% endif %} {% if user.passwords %} <PasswordCount>{{ user.passwords|length }}</PasswordCount> {% endif %} </Authentication> <ARN>{{ user.arn }}</ARN>""" CREATE_USER_TEMPLATE = ( """<CreateUserResponse xmlns="http://elasticache.amazonaws.com/doc/2015-02-02/"> <ResponseMetadata> <RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId> </ResponseMetadata> <CreateUserResult> """ + USER_TEMPLATE + """ </CreateUserResult> </CreateUserResponse>""" ) DELETE_USER_TEMPLATE = ( """<DeleteUserResponse xmlns="http://elasticache.amazonaws.com/doc/2015-02-02/"> <ResponseMetadata> <RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId> </ResponseMetadata> <DeleteUserResult> """ + USER_TEMPLATE + """ </DeleteUserResult> </DeleteUserResponse>""" ) DESCRIBE_USERS_TEMPLATE = ( """<DescribeUsersResponse xmlns="http://elasticache.amazonaws.com/doc/2015-02-02/"> <ResponseMetadata> <RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId> </ResponseMetadata> <DescribeUsersResult> <Users> {% for user in users %} <member> """ + USER_TEMPLATE + """ </member> {% endfor %} </Users> <Marker></Marker> </DescribeUsersResult> </DescribeUsersResponse>""" ) CREATE_CACHE_CLUSTER_TEMPLATE = """<CreateCacheClusterResponse xmlns="http://elasticache.amazonaws.com/doc/2015-02-02/"> <ResponseMetadata> <RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId> </ResponseMetadata> <CreateCacheClusterResult> <CacheCluster> <CacheClusterId>{{ cache_cluster.cache_cluster_id }}</CacheClusterId> <ConfigurationEndpoint> <Address>example.cache.amazonaws.com</Address> <Port>{{ cache_cluster.port }}</Port> </ConfigurationEndpoint> <ClientDownloadLandingPage></ClientDownloadLandingPage> <CacheNodeType>{{ cache_cluster.cache_node_type }}</CacheNodeType> <Engine>{{ cache_cluster.engine }}</Engine> <EngineVersion>{{ cache_cluster.engine_version }}</EngineVersion> <CacheClusterStatus>available</CacheClusterStatus> <NumCacheNodes>{{ cache_cluster.num_cache_nodes }}</NumCacheNodes> <PreferredAvailabilityZone>{{ cache_cluster.preferred_availability_zone }}</PreferredAvailabilityZone> <PreferredOutpostArn>{{ cache_cluster.preferred_outpost_arn }}</PreferredOutpostArn> <CacheClusterCreateTime>{{ cache_cluster.cache_cluster_create_time }}</CacheClusterCreateTime> <PreferredMaintenanceWindow>{{ cache_cluster.preferred_maintenance_window }}</PreferredMaintenanceWindow> {% if cache_cluster.cache_node_ids_to_remove != [] %} <PendingModifiedValues> <NumCacheNodes>{{ cache_cluster.num_cache_nodes }}</NumCacheNodes> {% for cache_node_id_to_remove in cache_cluster.cache_node_ids_to_remove %} <CacheNodeIdsToRemove>{{ cache_node_id_to_remove }}</CacheNodeIdsToRemove> {% endfor %} <EngineVersion>{{ cache_cluster.engine_version }}</EngineVersion> <CacheNodeType>{{ cache_cluster.cache_node_type }}</CacheNodeType> <AuthTokenStatus>SETTING</AuthTokenStatus> <LogDeliveryConfigurations> {% for log_delivery_configuration in cache_cluster.log_delivery_configurations %} <LogType>{{ log_delivery_configuration.LogType }}</LogType> <DestinationType>{{ log_delivery_configuration.DestinationType }}</DestinationType> <DestinationDetails> <CloudWatchLogsDetails> <LogGroup>{{ log_delivery_configuration.LogGroup }}</LogGroup> </CloudWatchLogsDetails> <KinesisFirehoseDetails> <DeliveryStream>{{ log_delivery_configuration.DeliveryStream }}</DeliveryStream> </KinesisFirehoseDetails> </DestinationDetails> <LogFormat>{{ log_delivery_configuration.LogFormat }}</LogFormat> {% endfor %} </LogDeliveryConfigurations> <TransitEncryptionEnabled>{{ cache_cluster.transit_encryption_enabled|lower }}</TransitEncryptionEnabled> <TransitEncryptionMode>preferred</TransitEncryptionMode> </PendingModifiedValues> {% endif %} <NotificationConfiguration> <TopicArn>{{ cache_cluster.notification_topic_arn }}</TopicArn> <TopicStatus>active</TopicStatus> </NotificationConfiguration> <CacheSecurityGroups> {% for cache_security_group_name in cache_cluster.cache_security_group_names %} <CacheSecurityGroupName>{{ cache_security_group_name }}</CacheSecurityGroupName> {% endfor %} <Status>active</Status> </CacheSecurityGroups> <CacheParameterGroup> <CacheParameterGroupName>{{ cache_cluster.cache_parameter_group_name }}</CacheParameterGroupName> <ParameterApplyStatus>active</ParameterApplyStatus> {% for cache_node_id_to_reboot in cache_cluster.cache_node_ids_to_reboot %} <CacheNodeIdsToReboot> {{ cache_node_id_to_reboot }} </CacheNodeIdsToReboot> {% endfor %} </CacheParameterGroup> <CacheSubnetGroupName>{{ cache_cluster.cache_subnet_group_name }}</CacheSubnetGroupName> <CacheNodes> <CacheNodeId>{{ cache_cluster.cache_node_id }}</CacheNodeId> <CacheNodeStatus>{{ cache_cluster.cache_node_status }}</CacheNodeStatus> <CacheNodeCreateTime>{{ cache_cluster.cache_cluster_create_time }}</CacheNodeCreateTime> <Endpoint> <Address>{{ cache_cluster.address }}</Address> <Port>{{ cache_cluster.port }}</Port> </Endpoint> <ParameterGroupStatus>active</ParameterGroupStatus> <SourceCacheNodeId>{{ cache_cluster.cache_node_id }}</SourceCacheNodeId> <CustomerAvailabilityZone>{{ cache_cluster.preferred_availability_zone }}</CustomerAvailabilityZone> <CustomerOutpostArn>{{ cache_cluster.preferred_output_arn }}</CustomerOutpostArn> </CacheNodes> <AutoMinorVersionUpgrade>{{ cache_cluster.auto_minor_version_upgrade|lower }}</AutoMinorVersionUpgrade> <SecurityGroups> {% for security_group_id in cache_cluster.security_group_ids %} <SecurityGroupId>{{ security_group_id }}</SecurityGroupId> <Status>active</Status> {% endfor %} </SecurityGroups> {% if cache_cluster.engine == "redis" %} <ReplicationGroupId>{{ cache_cluster.replication_group_id }}</ReplicationGroupId> <SnapshotRetentionLimit>{{ cache_cluster.snapshot_retention_limit }}</SnapshotRetentionLimit> <SnapshotWindow>{{ cache_cluster.snapshot_window }}</SnapshotWindow> {% endif %} <AuthTokenEnabled>true</AuthTokenEnabled> <AuthTokenLastModifiedDate>{{ cache_cluster.cache_cluster_create_time }}</AuthTokenLastModifiedDate> <TransitEncryptionEnabled>{{ cache_cluster.transit_encryption_enabled|lower }}</TransitEncryptionEnabled> <AtRestEncryptionEnabled>true</AtRestEncryptionEnabled> <ARN>{{ cache_cluster.arn }}</ARN> <ReplicationGroupLogDeliveryEnabled>true</ReplicationGroupLogDeliveryEnabled> <LogDeliveryConfigurations> {% for log_delivery_configuration in cache_cluster.log_delivery_configurations %} <LogType>{{ log_delivery_configuration.LogType }}</LogType> <DestinationType>{{ log_delivery_configuration.DestinationType }}</DestinationType> <DestinationDetails> <CloudWatchLogsDetails> <LogGroup>{{ log_delivery_configuration.LogGroup }}</LogGroup> </CloudWatchLogsDetails> <KinesisFirehoseDetails> <DeliveryStream>{{ log_delivery_configuration.DeliveryStream }}</DeliveryStream> </KinesisFirehoseDetails> </DestinationDetails> <LogFormat>{{ log_delivery_configuration.LogFormat }}</LogFormat> <Status>active</Status> <Message></Message> {% endfor %} </LogDeliveryConfigurations> <NetworkType>{{ cache_cluster.network_type }}</NetworkType> <IpDiscovery>{{ cache_cluster.ip_discovery }}</IpDiscovery> <TransitEncryptionMode>preferred</TransitEncryptionMode> </CacheCluster> </CreateCacheClusterResult> </CreateCacheClusterResponse>""" DESCRIBE_CACHE_CLUSTERS_TEMPLATE = """<DescribeCacheClustersResponse xmlns="http://elasticache.amazonaws.com/doc/2015-02-02/"> <ResponseMetadata> <RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId> </ResponseMetadata> <DescribeCacheClustersResult> {% if marker %}<Marker>{{ marker }}</Marker>{% endif %} <CacheClusters> {% for cache_cluster in cache_clusters %} <member> <CacheClusterId>{{ cache_cluster.cache_cluster_id }}</CacheClusterId> <ConfigurationEndpoint>{{ cache_cluster.configuration_endpoint }}</ConfigurationEndpoint> <ClientDownloadLandingPage>{{ cache_cluster.client_download_landing_page }}</ClientDownloadLandingPage> <CacheNodeType>{{ cache_cluster.cache_node_type }}</CacheNodeType> <Engine>{{ cache_cluster.engine }}</Engine> <EngineVersion>{{ cache_cluster.engine_version }}</EngineVersion> <CacheClusterStatus>{{ cache_cluster.cache_cluster_status }}</CacheClusterStatus> <NumCacheNodes>{{ cache_cluster.num_cache_nodes }}</NumCacheNodes> <PreferredAvailabilityZone>{{ cache_cluster.preferred_availability_zone }}</PreferredAvailabilityZone> <PreferredOutpostArn>{{ cache_cluster.preferred_outpost_arn }}</PreferredOutpostArn> <CacheClusterCreateTime>{{ cache_cluster.cache_cluster_create_time }}</CacheClusterCreateTime> <PreferredMaintenanceWindow>{{ cache_cluster.preferred_maintenance_window }}</PreferredMaintenanceWindow> <PendingModifiedValues>{{ cache_cluster.pending_modified_values }}</PendingModifiedValues> <NotificationConfiguration>{{ cache_cluster.notification_configuration }}</NotificationConfiguration> <CacheSecurityGroups> {% for cache_security_group in cache_cluster.cache_security_groups %} <member> <CacheSecurityGroupName>{{ cache_security_group.cache_security_group_name }}</CacheSecurityGroupName> <Status>{{ cache_security_group.status }}</Status> </member> {% endfor %} </CacheSecurityGroups> <CacheParameterGroup>{{ cache_cluster.cache_parameter_group }}</CacheParameterGroup> <CacheSubnetGroupName>{{ cache_cluster.cache_subnet_group_name }}</CacheSubnetGroupName> <CacheNodes> {% for cache_node in cache_cluster.cache_nodes %} <member> <CacheNodeId>{{ cache_node.cache_node_id }}</CacheNodeId> <CacheNodeStatus>{{ cache_node.cache_node_status }}</CacheNodeStatus> <CacheNodeCreateTime>{{ cache_node.cache_node_create_time }}</CacheNodeCreateTime> <Endpoint>{{ cache_node.endpoint }}</Endpoint> <ParameterGroupStatus>{{ cache_node.parameter_group_status }}</ParameterGroupStatus> <SourceCacheNodeId>{{ cache_node.source_cache_node_id }}</SourceCacheNodeId> <CustomerAvailabilityZone>{{ cache_node.customer_availability_zone }}</CustomerAvailabilityZone> <CustomerOutpostArn>{{ cache_node.customer_outpost_arn }}</CustomerOutpostArn> </member> {% endfor %} </CacheNodes> <AutoMinorVersionUpgrade>{{ cache_cluster.auto_minor_version_upgrade|lower }}</AutoMinorVersionUpgrade> <SecurityGroups> {% for security_group in cache_cluster.security_groups %} <member> <SecurityGroupId>{{ security_group.security_group_id }}</SecurityGroupId> <Status>{{ security_group.status }}</Status> </member> {% endfor %} </SecurityGroups> <ReplicationGroupId>{{ cache_cluster.replication_group_id }}</ReplicationGroupId> <SnapshotRetentionLimit>{{ cache_cluster.snapshot_retention_limit }}</SnapshotRetentionLimit> <SnapshotWindow>{{ cache_cluster.snapshot_window }}</SnapshotWindow> <AuthTokenEnabled>{{ cache_cluster.auth_token_enabled }}</AuthTokenEnabled> <AuthTokenLastModifiedDate>{{ cache_cluster.auth_token_last_modified_date }}</AuthTokenLastModifiedDate> <TransitEncryptionEnabled>{{ cache_cluster.transit_encryption_enabled|lower }}</TransitEncryptionEnabled> <AtRestEncryptionEnabled>{{ cache_cluster.at_rest_encryption_enabled }}</AtRestEncryptionEnabled> <ARN>{{ cache_cluster.arn }}</ARN> <ReplicationGroupLogDeliveryEnabled>{{ cache_cluster.replication_group_log_delivery_enabled }}</ReplicationGroupLogDeliveryEnabled> <LogDeliveryConfigurations> {% for log_delivery_configuration in cache_cluster.log_delivery_configurations %} <member> <LogType>{{ log_delivery_configuration.log_type }}</LogType> <DestinationType>{{ log_delivery_configuration.destination_type }}</DestinationType> <DestinationDetails>{{ log_delivery_configuration.destination_details }}</DestinationDetails> <LogFormat>{{ log_delivery_configuration.log_format }}</LogFormat> <Status>{{ log_delivery_configuration.status }}</Status> <Message>{{ log_delivery_configuration.message }}</Message> </member> {% endfor %} </LogDeliveryConfigurations> <NetworkType>{{ cache_cluster.network_type }}</NetworkType> <IpDiscovery>{{ cache_cluster.ip_discovery }}</IpDiscovery> <TransitEncryptionMode>{{ cache_cluster.transit_encryption_mode }}</TransitEncryptionMode> </member> {% endfor %} </CacheClusters> </DescribeCacheClustersResult> </DescribeCacheClustersResponse>""" DELETE_CACHE_CLUSTER_TEMPLATE = """<DeleteCacheClusterResponse xmlns="http://elasticache.amazonaws.com/doc/2015-02-02/"> <ResponseMetadata> <RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId> </ResponseMetadata> <DeleteCacheClusterResult> <CacheCluster> <CacheClusterId>{{ cache_cluster.cache_cluster_id }}</CacheClusterId> <ConfigurationEndpoint> <Address>example.cache.amazonaws.com</Address> <Port>{{ cache_cluster.port }}</Port> </ConfigurationEndpoint> <ClientDownloadLandingPage></ClientDownloadLandingPage> <CacheNodeType>{{ cache_cluster.cache_node_type }}</CacheNodeType> <Engine>{{ cache_cluster.engine }}</Engine> <EngineVersion>{{ cache_cluster.engine_version }}</EngineVersion> <CacheClusterStatus>available</CacheClusterStatus> <NumCacheNodes>{{ cache_cluster.num_cache_nodes }}</NumCacheNodes> <PreferredAvailabilityZone>{{ cache_cluster.preferred_availability_zone }}</PreferredAvailabilityZone> <PreferredOutpostArn>{{ cache_cluster.preferred_outpost_arn }}</PreferredOutpostArn> <CacheClusterCreateTime>{{ cache_cluster.cache_cluster_create_time }}</CacheClusterCreateTime> <PreferredMaintenanceWindow>{{ cache_cluster.preferred_maintenance_window }}</PreferredMaintenanceWindow> {% if cache_cluster.cache_node_ids_to_remove != [] %} <PendingModifiedValues> <NumCacheNodes>{{ cache_cluster.num_cache_nodes }}</NumCacheNodes> {% for cache_node_id_to_remove in cache_cluster.cache_node_ids_to_remove %} <CacheNodeIdsToRemove>{{ cache_node_id_to_remove }}</CacheNodeIdsToRemove> {% endfor %} <EngineVersion>{{ cache_cluster.engine_version }}</EngineVersion> <CacheNodeType>{{ cache_cluster.cache_node_type }}</CacheNodeType> <AuthTokenStatus>SETTING</AuthTokenStatus> <LogDeliveryConfigurations> {% for log_delivery_configuration in cache_cluster.log_delivery_configurations %} <LogType>{{ log_delivery_configuration.LogType }}</LogType> <DestinationType>{{ log_delivery_configuration.DestinationType }}</DestinationType> <DestinationDetails> <CloudWatchLogsDetails> <LogGroup>{{ log_delivery_configuration.LogGroup }}</LogGroup> </CloudWatchLogsDetails> <KinesisFirehoseDetails> <DeliveryStream>{{ log_delivery_configuration.DeliveryStream }}</DeliveryStream> </KinesisFirehoseDetails> </DestinationDetails> <LogFormat>{{ log_delivery_configuration.LogFormat }}</LogFormat> {% endfor %} </LogDeliveryConfigurations> <TransitEncryptionEnabled>{{ cache_cluster.transit_encryption_enabled|lower }}</TransitEncryptionEnabled> <TransitEncryptionMode>preferred</TransitEncryptionMode> </PendingModifiedValues> {% endif %} <NotificationConfiguration> <TopicArn>{{ cache_cluster.notification_topic_arn }}</TopicArn> <TopicStatus>active</TopicStatus> </NotificationConfiguration> <CacheSecurityGroups> {% for cache_security_group_name in cache_cluster.cache_security_group_names %} <CacheSecurityGroupName>{{ cache_security_group_name }}</CacheSecurityGroupName> {% endfor %} <Status>active</Status> </CacheSecurityGroups> <CacheParameterGroup> <CacheParameterGroupName>{{ cache_cluster.cache_parameter_group_name }}</CacheParameterGroupName> <ParameterApplyStatus>active</ParameterApplyStatus> {% for cache_node_id_to_reboot in cache_cluster.cache_node_ids_to_reboot %} <CacheNodeIdsToReboot> {{ cache_node_id_to_reboot }} </CacheNodeIdsToReboot> {% endfor %} </CacheParameterGroup> <CacheSubnetGroupName>{{ cache_cluster.cache_subnet_group_name }}</CacheSubnetGroupName> <CacheNodes> <CacheNodeId>{{ cache_cluster.cache_node_id }}</CacheNodeId> <CacheNodeStatus>{{ cache_cluster.cache_node_status }}</CacheNodeStatus> <CacheNodeCreateTime>{{ cache_cluster.cache_cluster_create_time }}</CacheNodeCreateTime> <Endpoint> <Address>{{ cache_cluster.address }}</Address> <Port>{{ cache_cluster.port }}</Port> </Endpoint> <ParameterGroupStatus>active</ParameterGroupStatus> <SourceCacheNodeId>{{ cache_cluster.cache_node_id }}</SourceCacheNodeId> <CustomerAvailabilityZone>{{ cache_cluster.preferred_availability_zone }}</CustomerAvailabilityZone> <CustomerOutpostArn>{{ cache_cluster.preferred_output_arn }}</CustomerOutpostArn> </CacheNodes> <AutoMinorVersionUpgrade>{{ cache_cluster.auto_minor_version_upgrade|lower }}</AutoMinorVersionUpgrade> <SecurityGroups> {% for security_group_id in cache_cluster.security_group_ids %} <SecurityGroupId>{{ security_group_id }}</SecurityGroupId> <Status>active</Status> {% endfor %} </SecurityGroups> {% if cache_cluster.engine == "redis" %} <ReplicationGroupId>{{ cache_cluster.replication_group_id }}</ReplicationGroupId> <SnapshotRetentionLimit>{{ cache_cluster.snapshot_retention_limit }}</SnapshotRetentionLimit> <SnapshotWindow>{{ cache_cluster.snapshot_window }}</SnapshotWindow> {% endif %} <AuthTokenEnabled>true</AuthTokenEnabled> <AuthTokenLastModifiedDate>{{ cache_cluster.cache_cluster_create_time }}</AuthTokenLastModifiedDate> <TransitEncryptionEnabled>{{ cache_cluster.transit_encryption_enabled|lower }}</TransitEncryptionEnabled> <AtRestEncryptionEnabled>true</AtRestEncryptionEnabled> <ARN>{{ cache_cluster.arn }}</ARN> <ReplicationGroupLogDeliveryEnabled>true</ReplicationGroupLogDeliveryEnabled> <LogDeliveryConfigurations> {% for log_delivery_configuration in cache_cluster.log_delivery_configurations %} <LogType>{{ log_delivery_configuration.LogType }}</LogType> <DestinationType>{{ log_delivery_configuration.DestinationType }}</DestinationType> <DestinationDetails> <CloudWatchLogsDetails> <LogGroup>{{ log_delivery_configuration.LogGroup }}</LogGroup> </CloudWatchLogsDetails> <KinesisFirehoseDetails> <DeliveryStream>{{ log_delivery_configuration.DeliveryStream }}</DeliveryStream> </KinesisFirehoseDetails> </DestinationDetails> <LogFormat>{{ log_delivery_configuration.LogFormat }}</LogFormat> <Status>active</Status> <Message></Message> {% endfor %} </LogDeliveryConfigurations> <NetworkType>{{ cache_cluster.network_type }}</NetworkType> <IpDiscovery>{{ cache_cluster.ip_discovery }}</IpDiscovery> <TransitEncryptionMode>preferred</TransitEncryptionMode> </CacheCluster> </DeleteCacheClusterResult> </DeleteCacheClusterResponse>""" LIST_TAGS_FOR_RESOURCE_TEMPLATE = """<ListTagsForResourceResponse xmlns="http://elasticache.amazonaws.com/doc/2015-02-02/"> <ListTagsForResourceResult> <TagList> {%- for tag in tags -%} <Tag> <Key>{{ tag['Key'] }}</Key> <Value>{{ tag['Value'] }}</Value> </Tag> {%- endfor -%} </TagList> </ListTagsForResourceResult> <ResponseMetadata> <RequestId>8c21ba39-a598-11e4-b688-194eaf8658fa</RequestId> </ResponseMetadata> </ListTagsForResourceResponse>"""
Memory