diff --git a/src/spaceone/inventory/connector/aws_elasticache_connector/connector.py b/src/spaceone/inventory/connector/aws_elasticache_connector/connector.py index 2d1fefb5..eb097b50 100644 --- a/src/spaceone/inventory/connector/aws_elasticache_connector/connector.py +++ b/src/spaceone/inventory/connector/aws_elasticache_connector/connector.py @@ -1,9 +1,9 @@ import logging from spaceone.core.utils import * -from spaceone.inventory.connector.aws_elasticache_connector.schema.data import Redis, Memcached +from spaceone.inventory.connector.aws_elasticache_connector.schema.data import Redis, Memcached, Valkey from spaceone.inventory.connector.aws_elasticache_connector.schema.resource import RedisResource, RedisResponse, \ - MemcachedResource, MemcachedResponse + MemcachedResource, MemcachedResponse, ValkeyResponse, ValkeyResource from spaceone.inventory.connector.aws_elasticache_connector.schema.service_type import CLOUD_SERVICE_TYPES from spaceone.inventory.libs.connector import SchematicAWSConnector from spaceone.inventory.libs.schema.resource import ReferenceModel, CloudWatchModel @@ -39,7 +39,9 @@ def get_resources(self): resources.append(MemcachedResponse({'resource': memcached_vo})) - for redis_vo in self.get_redis_data(region_name, cache_clusters): + replication_groups = cache_clusters = [cluster for cluster in self.describe_replication_groups()] + + for redis_vo in self.get_redis_data(region_name, replication_groups, cache_clusters): if getattr(redis_vo, 'resource_type', None) and redis_vo.resource_type == 'inventory.ErrorResource': # Error Resource resources.append(redis_vo) @@ -48,6 +50,16 @@ def get_resources(self): redis_vo.cloudwatch = CloudWatchModel(redis_vo.set_cloudwatch(region_name)) resources.append(RedisResponse({'resource': redis_vo})) + + for valkey_vo in self.get_valkey_data(region_name, replication_groups, cache_clusters): + if getattr(valkey_vo, 'resource_type', None) and valkey_vo.resource_type == 'inventory.ErrorResource': + # Error Resource + resources.append(valkey_vo) + else: + if getattr(valkey_vo, 'set_cloudwatch', None): + valkey_vo.cloudwatch = CloudWatchModel(valkey_vo.set_cloudwatch(region_name)) + + resources.append(ValkeyResponse({'resource': valkey_vo})) except Exception as e: error_resource_response = self.generate_error(region_name, '', e) resources.append(error_resource_response) @@ -87,47 +99,97 @@ def get_memcached_data(self, region_name, cache_clusters): error_resource_response = self.generate_error(region_name, resource_id, e) yield {'data': error_resource_response} - def get_redis_data(self, region_name, cache_clusters): + def get_redis_data(self, region_name, replication_groups, cache_clusters): self.cloud_service_type = 'Redis' cloudtrail_resource_type = None - for replication_group in self.describe_replication_groups(): + for replication_group in replication_groups: try: - replication_group.update({ - 'mode': self.set_redis_mode(replication_group.get('ClusterEnabled')), - 'engine': 'redis', - 'engine_version': self.get_engine_version(replication_group, cache_clusters), - 'shard_count': self.get_shard_count(replication_group.get('NodeGroups', [])), - 'availability_zones': self.get_redis_availability_zones(replication_group.get('NodeGroups', [])), - 'subnet_group_name': self.get_redis_subnet_group_name(replication_group, cache_clusters), - 'parameter_group_name': self.get_redis_parameter_group_name(replication_group, cache_clusters), - 'node_count': self.get_node_count(replication_group.get('MemberClusters', [])), - 'cloudtrail': self.set_cloudtrail(region_name, cloudtrail_resource_type, - replication_group['ReplicationGroupId']), - 'nodes': self.get_redis_nodes_info(replication_group, cache_clusters), - }) - - if replication_group.get('mode') == 'Redis': + if replication_group.get('Engine') == 'redis': replication_group.update({ - 'primary_endpoint': self.get_redis_primary_endpoint(replication_group), - 'reader_endpoint': self.get_redis_reader_endpoint(replication_group) + 'mode': self.set_redis_mode(replication_group.get('ClusterEnabled')), + 'engine': 'redis', + 'engine_version': self.get_engine_version(replication_group, cache_clusters), + 'shard_count': self.get_shard_count(replication_group.get('NodeGroups', [])), + 'availability_zones': self.get_availability_zones(replication_group.get('NodeGroups', [])), + 'subnet_group_name': self.get_subnet_group_name(replication_group, cache_clusters), + 'parameter_group_name': self.get_parameter_group_name(replication_group, cache_clusters), + 'node_count': self.get_node_count(replication_group.get('MemberClusters', [])), + 'cloudtrail': self.set_cloudtrail(region_name, cloudtrail_resource_type, + replication_group['ReplicationGroupId']), + 'nodes': self.get_nodes_info(replication_group, cache_clusters), }) - elif replication_group.get('mode') == 'Clustered Redis': - replication_group.update({ - 'shards': self.get_redis_shards_info(replication_group) + + if replication_group.get('mode') == 'Redis': + replication_group.update({ + 'primary_endpoint': self.get_primary_endpoint(replication_group), + 'reader_endpoint': self.get_reader_endpoint(replication_group) + }) + elif replication_group.get('mode') == 'Clustered Redis': + replication_group.update({ + 'shards': self.get_shards_info(replication_group) + }) + + redis_vo = Redis(replication_group, strict=False) + + yield RedisResource({ + 'data': redis_vo, + 'name': redis_vo.replication_group_id, + 'instance_type': redis_vo.cache_node_type, + 'account': self.account_id, + 'region_code': region_name, + 'tags': self.list_tags(redis_vo.arn), + 'reference': ReferenceModel(redis_vo.reference(region_name)) }) - redis_vo = Redis(replication_group, strict=False) + except Exception as e: + resource_id = replication_group.get('ARN', '') + error_resource_response = self.generate_error(region_name, resource_id, e) + yield {'data': error_resource_response} + + def get_valkey_data(self, region_name, replication_groups, cache_clusters): + self.cloud_service_type = 'Valkey' + cloudtrail_resource_type = None + + for replication_group in replication_groups: + try: + if replication_group.get('Engine') == 'valkey': + replication_group.update({ + 'mode': self.set_valkey_mode(replication_group.get('ClusterEnabled')), + 'engine': 'valkey', + 'engine_version': self.get_engine_version(replication_group, cache_clusters), + 'shard_count': self.get_shard_count(replication_group.get('NodeGroups', [])), + 'availability_zones': self.get_availability_zones( + replication_group.get('NodeGroups', [])), + 'subnet_group_name': self.get_subnet_group_name(replication_group, cache_clusters), + 'parameter_group_name': self.get_parameter_group_name(replication_group, cache_clusters), + 'node_count': self.get_node_count(replication_group.get('MemberClusters', [])), + 'cloudtrail': self.set_cloudtrail(region_name, cloudtrail_resource_type, + replication_group['ReplicationGroupId']), + 'nodes': self.get_nodes_info(replication_group, cache_clusters), + }) - yield RedisResource({ - 'data': redis_vo, - 'name': redis_vo.replication_group_id, - 'instance_type': redis_vo.cache_node_type, - 'account': self.account_id, - 'region_code': region_name, - 'tags': self.list_tags(redis_vo.arn), - 'reference': ReferenceModel(redis_vo.reference(region_name)) - }) + if replication_group.get('mode') == 'Valkey': + replication_group.update({ + 'primary_endpoint': self.get_primary_endpoint(replication_group), + 'reader_endpoint': self.get_reader_endpoint(replication_group) + }) + elif replication_group.get('mode') == 'Clustered Valkey': + replication_group.update({ + 'shards': self.get_shards_info(replication_group) + }) + + valkey_vo = Valkey(replication_group, strict=False) + + yield ValkeyResource({ + 'data': valkey_vo, + 'name': valkey_vo.replication_group_id, + 'instance_type': valkey_vo.cache_node_type, + 'account': self.account_id, + 'region_code': region_name, + 'tags': self.list_tags(valkey_vo.arn), + 'reference': ReferenceModel(valkey_vo.reference(region_name)) + }) except Exception as e: resource_id = replication_group.get('ARN', '') @@ -195,6 +257,13 @@ def set_redis_mode(cluster_enabled): else: return 'Redis' + @staticmethod + def set_valkey_mode(cluster_enabled): + if cluster_enabled: + return 'Clustered Valkey' + else: + return 'Valkey' + @staticmethod def get_node_count(member_clusters): return len(member_clusters) @@ -204,13 +273,13 @@ def get_shard_count(node_groups): return len(node_groups) @staticmethod - def get_redis_primary_endpoint(replication_group): + def get_primary_endpoint(replication_group): for node_group in replication_group.get('NodeGroups', []): primary_endpoint = node_group.get("PrimaryEndpoint", {}) return f'{primary_endpoint.get("Address", "")}:{primary_endpoint.get("Port", "")}' @staticmethod - def get_redis_reader_endpoint(replication_group): + def get_reader_endpoint(replication_group): for node_group in replication_group.get('NodeGroups', []): reader_endpoint = node_group.get("ReaderEndpoint", {}) return f'{reader_endpoint.get("Address", "")}:{reader_endpoint.get("Port", "")}' @@ -225,7 +294,7 @@ def get_engine_version(replication_group, cache_clusters): return '' @staticmethod - def get_redis_availability_zones(node_groups): + def get_availability_zones(node_groups): azs = [] for node_group in node_groups: @@ -237,7 +306,7 @@ def get_redis_availability_zones(node_groups): return list(set(azs)) @staticmethod - def get_redis_subnet_group_name(replication_group, cache_clusters): + def get_subnet_group_name(replication_group, cache_clusters): for member in replication_group.get('MemberClusters', []): for cache_cluster in cache_clusters: if cache_cluster.get('CacheClusterId') == member: @@ -246,7 +315,7 @@ def get_redis_subnet_group_name(replication_group, cache_clusters): return '' @staticmethod - def get_redis_parameter_group_name(replication_group, cache_clusters): + def get_parameter_group_name(replication_group, cache_clusters): for member in replication_group.get('MemberClusters', []): for cache_cluster in cache_clusters: if cache_cluster.get('CacheClusterId') == member: @@ -254,7 +323,7 @@ def get_redis_parameter_group_name(replication_group, cache_clusters): return '' - def get_redis_nodes_info(self, replication_group, cache_clusters): + def get_nodes_info(self, replication_group, cache_clusters): nodes = [] for member in replication_group.get('MemberClusters', []): @@ -282,7 +351,7 @@ def get_redis_nodes_info(self, replication_group, cache_clusters): }) else: node_dic.update({ - 'endpoint': self.set_redis_cluster_node_endpoint(member, replication_group.get('ConfigurationEndpoint', {}).get('Address')), + 'endpoint': self.set_cluster_node_endpoint(member, replication_group.get('ConfigurationEndpoint', {}).get('Address')), 'port': replication_group.get('ConfigurationEndpoint', {}).get('Port', ''), 'zone': node_group_member.get('PreferredAvailabilityZone', ''), }) @@ -292,7 +361,7 @@ def get_redis_nodes_info(self, replication_group, cache_clusters): return nodes @staticmethod - def get_redis_shards_info(replication_group): + def get_shards_info(replication_group): shards = [] for node_group in replication_group.get('NodeGroups', []): @@ -306,7 +375,7 @@ def get_redis_shards_info(replication_group): return shards @staticmethod - def set_redis_cluster_node_endpoint(member, address): + def set_cluster_node_endpoint(member, address): if address: address_split = address.split('.')[1:] address_split.insert(0, member) diff --git a/src/spaceone/inventory/connector/aws_elasticache_connector/schema/data.py b/src/spaceone/inventory/connector/aws_elasticache_connector/schema/data.py index 961facd5..0ec7627b 100644 --- a/src/spaceone/inventory/connector/aws_elasticache_connector/schema/data.py +++ b/src/spaceone/inventory/connector/aws_elasticache_connector/schema/data.py @@ -32,7 +32,7 @@ class NodeGroupMembers(Model): current_role = StringType(deserialize_from='CurrentRole', serialize_when_none=False) -class RedisNodeGroups(Model): +class NodeGroups(Model): node_group_id = StringType(deserialize_from='NodeGroupId', serialize_when_none=False) status = StringType(deserialize_from='Status', serialize_when_none=False) primary_endpoint = ModelType(Endpoint, deserialize_from='PrimaryEndpoint', serialize_when_none=False) @@ -41,7 +41,7 @@ class RedisNodeGroups(Model): node_group_members = ListType(ModelType(NodeGroupMembers), deserialize_from='NodeGroupMembers', default=[]) -class RedisUserGroups(Model): +class UserGroups(Model): user_group_ids_to_add = ListType(StringType, deserialize_from='UserGroupIdsToAdd', default=[]) user_group_ids_to_remove = ListType(StringType, deserialize_from='UserGroupIdsToRemove', default=[]) @@ -50,21 +50,21 @@ class ReshardingSlotMigration(Model): progress_percentage = FloatType(deserialize_from='ProgressPercentage', serialize_when_none=False) -class RedisResharding(Model): +class Resharding(Model): slot_migration = ModelType(ReshardingSlotMigration, deserialize_from='SlotMigration', serialize_when_none=False) -class RedisPendingModifiedValues(Model): +class PendingModifiedValues(Model): primary_cluster_id = StringType(deserialize_from='PrimaryClusterId', serialize_when_none=False) automatic_failover_status = StringType(deserialize_from='AutomaticFailoverStatus', choices=('enabled', 'disabled'), serialize_when_none=False) - resharding = ModelType(RedisResharding, deserialize_from='Resharding', serialize_when_none=False) + resharding = ModelType(Resharding, deserialize_from='Resharding', serialize_when_none=False) auth_token_status = StringType(deserialize_from='AuthTokenStatus', choices=('SETTING', 'ROTATING'), serialize_when_none=False) - user_groups = ModelType(RedisUserGroups, deserialize_from='RedisUserGroups', serialize_when_none=False) + user_groups = ModelType(UserGroups, deserialize_from='UserGroups', serialize_when_none=False) -class RedisGlobalReplicationGroupInfo(Model): +class GlobalReplicationGroupInfo(Model): global_replication_group_id = StringType(deserialize_from='GlobalReplicationGroupId', serialize_when_none=False) global_replication_group_member_role = StringType(deserialize_from='GlobalReplicationGroupMemberRole', serialize_when_none=False) @@ -99,14 +99,14 @@ class MemcachedPendingModifiedValues(Model): serialize_when_none=False) -class RedisShard(Model): +class Shard(Model): shard_name = StringType() nodes = IntType() status = StringType() slots = StringType() -class RedisNode(Model): +class Node(Model): node_name = StringType() status = StringType() current_role = StringType(serialize_when_none=False) @@ -118,6 +118,55 @@ class RedisNode(Model): created_on = DateTimeType() +class Valkey(AWSCloudService): + arn = StringType(deserialize_from='ARN', serialize_when_none=False) + replication_group_id = StringType(deserialize_from="ReplicationGroupId", serialize_when_none=False) + mode = StringType(choices=('Clustered Valkey', 'Valkey')) + engine = StringType(deserialize_from="Engine", serialize_when_none=False) + engine_version = StringType(deserialize_from="EngineVersion", serialize_when_none=False) + shard_count = IntType() + node_count = IntType() + cache_node_type = StringType(deserialize_from="CacheNodeType", serialize_when_none=False) + description = StringType(deserialize_from="Description", serialize_when_none=False) + global_replication_group_info = ModelType(GlobalReplicationGroupInfo, + deserialize_from="GlobalReplicationGroupInfo", serialize_when_none=False) + status = StringType(deserialize_from='Status') + pending_modified_values = ModelType(PendingModifiedValues, deserialize_from='PendingModifiedValues', + serialize_when_none=False) + member_clusters = ListType(StringType, deserialize_from='MemberClusters', default=[]) + node_groups = ListType(ModelType(NodeGroups), deserialize_from='NodeGroups', default=[]) + availability_zones = ListType(StringType, default=[]) + snapshotting_cluster_id = StringType(deserialize_from='SnapshottingClusterId', serialize_when_none=False) + automatic_failover = StringType(deserialize_from='AutomaticFailover', + choices=('enabled', 'disabled', 'enabling', 'disabling'), + serialize_when_none=False) + parameter_group_name = StringType(serialize_when_none=False) + subnet_group_name = StringType(serialize_when_none=False) + multi_az = StringType(deserialize_from='MultiAZ', choices=('enabled', 'disabled'), serialize_when_none=False) + configuration_endpoint = ModelType(Endpoint, deserialize_from='ConfigurationEndpoint', serialize_when_none=False) + primary_endpoint = StringType(serialize_when_none=False) + reader_endpoint = StringType(serialize_when_none=False) + snapshot_retention_limit = IntType(deserialize_from='SnapshotRetentionLimit', serialize_when_none=False) + snapshot_window = StringType(deserialize_from='SnapshotWindow', serialize_when_none=False) + cluster_enabled = BooleanType(deserialize_from='ClusterEnabled', serialize_when_none=False) + cluster_node_type = StringType(deserialize_from='CacheNodeType', serialize_when_none=False) + auth_token_enabled = BooleanType(deserialize_from='AuthTokenEnabled', serialize_when_none=False) + auth_token_last_modified_date = DateTimeType(deserialize_from='AuthTokenLastModifiedDate', serialize_when_none=False) + transit_encryption_enabled = BooleanType(deserialize_from='TransitEncryptionEnabled', serialize_when_none=False) + at_rest_encryption_enabled = BooleanType(deserialize_from='AtRestEncryptionEnabled', serialize_when_none=False) + member_clusters_outpost_arns = ListType(StringType, deserialize_from='MemberClustersOutpostArns', default=[]) + kms_key_id = StringType(deserialize_from='KmsKeyId', serialize_when_none=False) + user_group_ids = ListType(StringType, deserialize_from='UserGroupIds', default=[]) + shards = ListType(ModelType(Shard), default=[]) + nodes = ListType(ModelType(Node), default=[]) + + def reference(self, region_code): + return { + "resource_id": self.arn, + "external_link": f"https://console.aws.amazon.com/elasticache/home?region={region_code}#redis-group-detail:id={self.replication_group_id}" + } + + class Redis(AWSCloudService): arn = StringType(deserialize_from='ARN', serialize_when_none=False) replication_group_id = StringType(deserialize_from="ReplicationGroupId", serialize_when_none=False) @@ -128,13 +177,13 @@ class Redis(AWSCloudService): node_count = IntType() cache_node_type = StringType(deserialize_from="CacheNodeType", serialize_when_none=False) description = StringType(deserialize_from="Description", serialize_when_none=False) - global_replication_group_info = ModelType(RedisGlobalReplicationGroupInfo, + global_replication_group_info = ModelType(GlobalReplicationGroupInfo, deserialize_from="GlobalReplicationGroupInfo", serialize_when_none=False) status = StringType(deserialize_from='Status') - pending_modified_values = ModelType(RedisPendingModifiedValues, deserialize_from='PendingModifiedValues', + pending_modified_values = ModelType(PendingModifiedValues, deserialize_from='PendingModifiedValues', serialize_when_none=False) member_clusters = ListType(StringType, deserialize_from='MemberClusters', default=[]) - node_groups = ListType(ModelType(RedisNodeGroups), deserialize_from='NodeGroups', default=[]) + node_groups = ListType(ModelType(NodeGroups), deserialize_from='NodeGroups', default=[]) availability_zones = ListType(StringType, default=[]) snapshotting_cluster_id = StringType(deserialize_from='SnapshottingClusterId', serialize_when_none=False) automatic_failover = StringType(deserialize_from='AutomaticFailover', @@ -157,8 +206,8 @@ class Redis(AWSCloudService): member_clusters_outpost_arns = ListType(StringType, deserialize_from='MemberClustersOutpostArns', default=[]) kms_key_id = StringType(deserialize_from='KmsKeyId', serialize_when_none=False) user_group_ids = ListType(StringType, deserialize_from='UserGroupIds', default=[]) - shards = ListType(ModelType(RedisShard), default=[]) - nodes = ListType(ModelType(RedisNode), default=[]) + shards = ListType(ModelType(Shard), default=[]) + nodes = ListType(ModelType(Node), default=[]) def reference(self, region_code): return { diff --git a/src/spaceone/inventory/connector/aws_elasticache_connector/schema/resource.py b/src/spaceone/inventory/connector/aws_elasticache_connector/schema/resource.py index 153ecc39..32b7b943 100644 --- a/src/spaceone/inventory/connector/aws_elasticache_connector/schema/resource.py +++ b/src/spaceone/inventory/connector/aws_elasticache_connector/schema/resource.py @@ -2,7 +2,7 @@ from schematics.types import ModelType, StringType, PolyModelType -from spaceone.inventory.connector.aws_elasticache_connector.schema.data import Redis, Memcached +from spaceone.inventory.connector.aws_elasticache_connector.schema.data import Redis, Memcached, Valkey from spaceone.inventory.libs.schema.resource import CloudServiceResource, CloudServiceResponse, CloudServiceMeta from spaceone.inventory.libs.schema.dynamic_field import TextDyField, ListDyField, DateTimeDyField, EnumDyField from spaceone.inventory.libs.schema.dynamic_layout import ItemDynamicLayout, TableDynamicLayout, SimpleTableDynamicLayout @@ -124,6 +124,76 @@ redis_metadata = CloudServiceMeta.set_layouts(layouts=[redis_base, redis_shards, redis_nodes]) +''' +Valkey +''' +valkey_base = ItemDynamicLayout.set_fields('Description', fields=[ + TextDyField.data_source('Name', 'data.replication_group_id'), + TextDyField.data_source('ARN', 'data.arn'), + TextDyField.data_source('Mode', 'data.mode'), + EnumDyField.data_source('Status', 'data.status', default_state={ + 'safe': ['available'], + 'warning': ['creating', 'modifying', 'deleting', 'snapshotting'], + 'alert': ['create-failed'] + }), + TextDyField.data_source('Configuration Endpoint Address', 'data.configuration_endpoint.address'), + TextDyField.data_source('Configuration Endpoint Port', 'data.configuration_endpoint.port'), + TextDyField.data_source('Primary Endpoint', 'data.primary_endpoint'), + TextDyField.data_source('Reader Endpoint', 'data.reader_endpoint'), + TextDyField.data_source('Engine', 'data.engine'), + TextDyField.data_source('Engine Version Compatibility', 'data.engine_version'), + TextDyField.data_source('Multi-AZ', 'data.multi_az'), + ListDyField.data_source('Availability Zones', 'data.availability_zones', options={ + 'delimiter': '
' + }), + TextDyField.data_source('Auto Fail-over', 'data.automatic_failover'), + TextDyField.data_source('Description', 'data.description'), + TextDyField.data_source('Parameter Group ', 'data.parameter_group_name'), + TextDyField.data_source('Subnet Group ', 'data.subnet_group_name'), + TextDyField.data_source('Description', 'data.description'), + TextDyField.data_source('Backup Retention Period', 'data.snapshot_retention_limit'), + TextDyField.data_source('Encryption in-transit', 'data.transit_encryption_enabled'), + TextDyField.data_source('Backup Window', 'data.snapshot_window'), + TextDyField.data_source('Encryption at-rest', 'data.at_rest_encryption_enabled'), + TextDyField.data_source('Redis AUTH Default User Access', 'data.auth_token_enabled'), + TextDyField.data_source('Custom Managed CMK', 'data.kms_key_id'), + ListDyField.data_source('User Group', 'data.user_group_ids', options={ + 'delimiter': '
' + }), + DateTimeDyField.data_source('AUTH token last modified date', 'data.auth_token_last_modified_date'), + ListDyField.data_source('Outpost ARN', 'data.member_clusters_outpost_arns', options={ + 'delimiter': '
' + }) +]) + +valkey_shards = TableDynamicLayout.set_fields('Shards', 'data.shards', fields=[ + TextDyField.data_source('Shard Name', 'shard_name'), + EnumDyField.data_source('Status', 'status', default_state={ + 'safe': ['available'], + }), + TextDyField.data_source('Node Counts', 'nodes'), + TextDyField.data_source('Slots', 'slots') +]) + +valkey_nodes = TableDynamicLayout.set_fields('Nodes', 'data.nodes', fields=[ + TextDyField.data_source('Node Name', 'node_name'), + EnumDyField.data_source('Status', 'status', default_state={ + 'safe': ['available'], + }), + TextDyField.data_source('Current Role', 'current_role'), + TextDyField.data_source('Port', 'port'), + TextDyField.data_source('Endpoint', 'endpoint'), + EnumDyField.data_source('Parameter Group Status', 'parameter_group_status', default_state={ + 'safe': ['in-sync'], + }), + TextDyField.data_source('Zone', 'zone'), + TextDyField.data_source('ARN', 'arn'), + DateTimeDyField.data_source('Created On', 'created_on') +]) + +valkey_metadata = CloudServiceMeta.set_layouts(layouts=[valkey_base, valkey_shards, valkey_nodes]) + + # Memcached class ElasticCacheResource(CloudServiceResource): cloud_service_group = StringType(default='ElastiCache') @@ -150,3 +220,10 @@ class RedisResponse(CloudServiceResponse): resource = PolyModelType(RedisResource) +class ValkeyResource(ElasticCacheResource): + cloud_service_type = StringType(default='Valkey') + data = ModelType(Valkey) + _metadata = ModelType(CloudServiceMeta, default=valkey_metadata, serialized_name='metadata') + +class ValkeyResponse(CloudServiceResponse): + resource = PolyModelType(ValkeyResource) diff --git a/src/spaceone/inventory/connector/aws_elasticache_connector/schema/service_type.py b/src/spaceone/inventory/connector/aws_elasticache_connector/schema/service_type.py index 0f650184..1e11a724 100644 --- a/src/spaceone/inventory/connector/aws_elasticache_connector/schema/service_type.py +++ b/src/spaceone/inventory/connector/aws_elasticache_connector/schema/service_type.py @@ -169,7 +169,98 @@ ) +cst_valkey = CloudServiceTypeResource() +cst_valkey.name = 'Valkey' +cst_valkey.provider = 'aws' +cst_valkey.group = 'ElastiCache' +cst_valkey.labels = ['Database'] +cst_valkey.is_primary = True +cst_valkey.is_major = True +cst_valkey.service_code = 'AmazonElastiCache' +cst_valkey.tags = { + 'spaceone:icon': f'{ASSET_URL}/Amazon-ElastiCache.svg', +} + +cst_valkey._metadata = CloudServiceTypeMeta.set_meta( + fields=[ + TextDyField.data_source('Mode', 'data.mode'), + EnumDyField.data_source('Status', 'data.status', default_state={ + 'safe': ['available'], + 'warning': ['creating', 'modifying', 'deleting', 'snapshotting'], + 'alert': ['create-failed', 'restore-failed'] + }), + TextDyField.data_source('Shard', 'data.shard_count'), + TextDyField.data_source('Nodes', 'data.node_count'), + TextDyField.data_source('Node Type', 'instance_type'), + TextDyField.data_source('Encryption in-transit', 'data.transit_encryption_enabled'), + TextDyField.data_source('Encryption at-rest', 'data.at_rest_encryption_enabled'), + TextDyField.data_source('ARN', 'data.arn', options={ + 'is_optional': True + }), + TextDyField.data_source('Cache Node Type', 'data.cache_node_type', options={ + 'is_optional': True + }), + TextDyField.data_source('Engine Version', 'data.engine_version', options={ + 'is_optional': True + }), + TextDyField.data_source('Description', 'data.description', options={ + 'is_optional': True + }), + TextDyField.data_source('Automatic Failover', 'data.automatic_failover', options={ + 'is_optional': True + }), + TextDyField.data_source('Endpoint Address', 'data.configuration_endpoint.address', options={ + 'is_optional': True + }), + TextDyField.data_source('Port', 'data.configuration_endpoint.port', options={ + 'is_optional': True + }), + TextDyField.data_source('Snapshot Retention Limit', 'data.snapshot_retention_limit', options={ + 'is_optional': True + }), + TextDyField.data_source('Parameter Group Name', 'data.parameter_group_name', options={ + 'is_optional': True + }), + TextDyField.data_source('Replication Group ID', 'data.replication_group_id', options={ + 'is_optional': True + }), + TextDyField.data_source('Snapshot Window', 'data.snapshot_window', options={ + 'is_optional': True + }), + TextDyField.data_source('Multi AZ', 'data.multi_az', options={ + 'is_optional': True + }), + ListDyField.data_source('Availability Zones', 'data.availability_zones', options={ + 'delimiter': '
', + 'is_optional': True + }), + TextDyField.data_source('Subnet Group Name', 'data.subnet_group_name', options={ + 'is_optional': True + }), + TextDyField.data_source('Auth Token Enabled', 'data.auth_token_enabled', options={ + 'is_optional': True + }), + TextDyField.data_source('AWS Account ID', 'account', options={ + 'is_optional': True + }) + ], + search=[ + SearchField.set(name='ARN', key='data.arn'), + SearchField.set(name='Mode', key='data.mode'), + SearchField.set(name='Status', key='data.status'), + SearchField.set(name='Shard Count', key='data.shard_count', data_type='integer'), + SearchField.set(name='Node Count', key='data.node_count', data_type='integer'), + SearchField.set(name='Node Type', key='instance_type'), + SearchField.set(name='Multi AZ', key='data.multi_az'), + SearchField.set(name='Configuration Endpoint Address', key='data.configuration_endpoint.address'), + SearchField.set(name='Configuration Endpoint Port', key='data.configuration_endpoint.port'), + SearchField.set(name='AWS Account ID', key='account') + ] +) + + CLOUD_SERVICE_TYPES = [ CloudServiceTypeResponse({'resource': cst_memcached}), CloudServiceTypeResponse({'resource': cst_redis}), + CloudServiceTypeResponse({'resource': cst_valkey}) ]