diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 00000000..04b43fa4 Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/spaceone/inventory/connector/aws_eks_connector/connector.py b/src/spaceone/inventory/connector/aws_eks_connector/connector.py index 17f7747d..3ba54fcb 100644 --- a/src/spaceone/inventory/connector/aws_eks_connector/connector.py +++ b/src/spaceone/inventory/connector/aws_eks_connector/connector.py @@ -2,10 +2,21 @@ from typing import List from spaceone.core.utils import * -from spaceone.inventory.connector.aws_eks_connector.schema.data import Cluster, NodeGroup, Update -from spaceone.inventory.connector.aws_eks_connector.schema.resource import ClusterResource, ClusterResponse, \ - NodeGroupResource, NodeGroupResponse -from spaceone.inventory.connector.aws_eks_connector.schema.service_type import CLOUD_SERVICE_TYPES +from spaceone.inventory.connector.aws_eks_connector.schema.data import ( + Cluster, + NodeGroup, + Update, + AddOn, +) +from spaceone.inventory.connector.aws_eks_connector.schema.resource import ( + ClusterResource, + ClusterResponse, + NodeGroupResource, + NodeGroupResponse, +) +from spaceone.inventory.connector.aws_eks_connector.schema.service_type import ( + CLOUD_SERVICE_TYPES, +) from spaceone.inventory.libs.connector import SchematicAWSConnector from spaceone.inventory.libs.schema.resource import ReferenceModel, CloudWatchModel from spaceone.inventory.conf.cloud_service_conf import * @@ -15,9 +26,9 @@ class EKSConnector(SchematicAWSConnector): - service_name = 'eks' - cloud_service_group = 'EKS' - cloud_service_type = 'Cluster' + service_name = "eks" + cloud_service_group = "EKS" + cloud_service_type = "Cluster" cloud_service_types = CLOUD_SERVICE_TYPES def get_resources(self): @@ -29,68 +40,93 @@ def get_resources(self): resources.extend(self.set_cloud_service_types()) collect_resource = { - 'request_method': self.request_data, - 'resource': ClusterResource, - 'response_schema': ClusterResponse + "request_method": self.request_data, + "resource": ClusterResource, + "response_schema": ClusterResponse, } for region_name in self.region_names: try: self.reset_region(region_name) - resources.extend(self.collect_data_by_region(self.service_name, region_name, collect_resource)) + resources.extend( + self.collect_data_by_region( + self.service_name, region_name, collect_resource + ) + ) # For Node Group for node_group_vo in self.node_groups: - resources.append(NodeGroupResponse( - {'resource': NodeGroupResource({ - 'name': node_group_vo.nodegroup_name, - 'launched_at': self.datetime_to_iso8601(node_group_vo.created_at), - 'data': node_group_vo, - 'tags': node_group_vo.tags, - 'region_code': region_name, - 'reference': ReferenceModel(node_group_vo.reference(region_name))})} - )) + resources.append( + NodeGroupResponse( + { + "resource": NodeGroupResource( + { + "name": node_group_vo.nodegroup_name, + "launched_at": self.datetime_to_iso8601( + node_group_vo.created_at + ), + "data": node_group_vo, + "tags": node_group_vo.tags, + "region_code": region_name, + "reference": ReferenceModel( + node_group_vo.reference(region_name) + ), + } + ) + } + ) + ) self.node_groups = [] except Exception as e: - error_resource_response = self.generate_error(region_name, '', e) + error_resource_response = self.generate_error(region_name, "", e) resources.append(error_resource_response) - _LOGGER.debug(f'[get_resources][account_id: {self.account_id}] FINISHED: EKS ({time.time() - start_time} sec)') + _LOGGER.debug( + f"[get_resources][account_id: {self.account_id}] FINISHED: EKS ({time.time() - start_time} sec)" + ) return resources def request_data(self, region_name) -> List[Cluster]: - self.cloud_service_type = 'Cluster' - cloudtrail_resource_type = 'AWS::EKS::Cluster' + self.cloud_service_type = "Cluster" + cloudtrail_resource_type = "AWS::EKS::Cluster" - paginator = self.client.get_paginator('list_clusters') + paginator = self.client.get_paginator("list_clusters") response_iterator = paginator.paginate( PaginationConfig={ - 'MaxItems': 10000, - 'PageSize': 50, + "MaxItems": 10000, + "PageSize": 50, } ) errors = [] for data in response_iterator: - for _cluster_name in data.get('clusters', []): + for _cluster_name in data.get("clusters", []): try: raw = self.client.describe_cluster(name=_cluster_name) - if cluster := raw.get('cluster'): - cluster.update({ - 'updates': list(self.list_updates(_cluster_name)), - 'cloudwatch': self.eks_cluster_cloudwatch(cluster, region_name), - 'cloudtrail': self.set_cloudtrail(region_name, cloudtrail_resource_type, cluster['name']) - }) - - node_groups, node_group_errors = self.list_node_groups(_cluster_name, cluster.get('arn'), - region_name) - - cluster.update({ - 'node_groups': node_groups - }) + if cluster := raw.get("cluster"): + cluster.update( + { + "updates": list(self.list_updates(_cluster_name)), + "add_ons": list(self.list_add_ons(_cluster_name)), + "cloudwatch": self.eks_cluster_cloudwatch( + cluster, region_name + ), + "cloudtrail": self.set_cloudtrail( + region_name, + cloudtrail_resource_type, + cluster["name"], + ), + } + ) + + node_groups, node_group_errors = self.list_node_groups( + _cluster_name, cluster.get("arn"), region_name + ) + + cluster.update({"node_groups": node_groups}) self.node_groups.extend(node_groups) errors.extend(node_group_errors) @@ -98,11 +134,15 @@ def request_data(self, region_name) -> List[Cluster]: cluster_vo = Cluster(cluster, strict=False) yield { - 'data': cluster_vo, - 'name': cluster_vo.name, - 'launched_at': self.datetime_to_iso8601(cluster_vo.created_at), - 'account': self.account_id, - 'tags': cluster.get('tags',) + "data": cluster_vo, + "name": cluster_vo.name, + "launched_at": self.datetime_to_iso8601( + cluster_vo.created_at + ), + "account": self.account_id, + "tags": cluster.get( + "tags", + ), } except Exception as e: @@ -110,72 +150,93 @@ def request_data(self, region_name) -> List[Cluster]: errors.append(self.generate_error(region_name, resource_id, e)) for error in errors: - yield {'data': error} + yield {"data": error} def list_node_groups(self, cluster_name, cluster_arn, region_name): - self.cloud_service_type = 'NodeGroup' - cloudtrail_resource_type = 'AWS::EKS::Nodegroup' + self.cloud_service_type = "NodeGroup" + cloudtrail_resource_type = "AWS::EKS::Nodegroup" asgs = self.get_auto_scaling_groups() - paginator = self.client.get_paginator('list_nodegroups') + paginator = self.client.get_paginator("list_nodegroups") response_iterator = paginator.paginate( clusterName=cluster_name, PaginationConfig={ - 'MaxItems': 10000, - 'PageSize': 50, - } + "MaxItems": 10000, + "PageSize": 50, + }, ) node_groups = [] errors = [] for data in response_iterator: - for node_group in data.get('nodegroups', []): + for node_group in data.get("nodegroups", []): try: - node_group_response = self.client.describe_nodegroup(clusterName=cluster_name, nodegroupName=node_group) - node_group = node_group_response.get('nodegroup', {}) - node_group.update({ - 'cluster_arn': cluster_arn, - 'cloudtrail': self.set_cloudtrail(region_name, cloudtrail_resource_type, - node_group['nodegroupName']) - }) - asg_names = [asg.get("name", "") for asg in - node_group.get("resources", "").get("autoScalingGroups", [])] + node_group_response = self.client.describe_nodegroup( + clusterName=cluster_name, nodegroupName=node_group + ) + node_group = node_group_response.get("nodegroup", {}) + node_group.update( + { + "cluster_arn": cluster_arn, + "cloudtrail": self.set_cloudtrail( + region_name, + cloudtrail_resource_type, + node_group["nodegroupName"], + ), + } + ) + asg_names = [ + asg.get("name", "") + for asg in node_group.get("resources", "").get( + "autoScalingGroups", [] + ) + ] if len(asg_names) > 0: - node_group["resources"]["autoScalingGroups"] = self.get_matched_auto_scaling_groups(asgs, asg_names) + node_group["resources"]["autoScalingGroups"] = ( + self.get_matched_auto_scaling_groups(asgs, asg_names) + ) node_groups.append(NodeGroup(node_group, strict=False)) except Exception as e: - resource_id = node_group.get('nodegroupArn', '') + resource_id = node_group.get("nodegroupArn", "") errors.append(self.generate_error(region_name, resource_id, e)) return node_groups, errors def list_updates(self, cluster_name): - paginator = self.client.get_paginator('list_updates') + paginator = self.client.get_paginator("list_updates") response_iterator = paginator.paginate( name=cluster_name, PaginationConfig={ - 'MaxItems': 10000, - 'PageSize': 50, - } + "MaxItems": 10000, + "PageSize": 50, + }, ) for data in response_iterator: - for update_id in data.get('updateIds', []): - response = self.client.describe_update(name=cluster_name, updateId=update_id) - yield Update(response.get('update', {}), strict=False) + for update_id in data.get("updateIds", []): + response = self.client.describe_update( + name=cluster_name, updateId=update_id + ) + yield Update(response.get("update", {}), strict=False) def eks_cluster_cloudwatch(self, cluster, region_name): - cloudwatch_kubernetes = self.set_cloudwatch('Kubernetes', 'CLUSTER_ID', cluster['name'], region_name) - cloudwatch_container_insights = self.set_cloudwatch('ContainerInsights', 'ClusterName', - cluster['name'], region_name) + cloudwatch_kubernetes = self.set_cloudwatch( + "Kubernetes", "CLUSTER_ID", cluster["name"], region_name + ) + cloudwatch_container_insights = self.set_cloudwatch( + "ContainerInsights", "ClusterName", cluster["name"], region_name + ) - cloudwatch_vo = CloudWatchModel({ - 'region_name': region_name, - 'metrics_info': cloudwatch_kubernetes.metrics_info + - cloudwatch_container_insights.metrics_info - }, strict=False) + cloudwatch_vo = CloudWatchModel( + { + "region_name": region_name, + "metrics_info": cloudwatch_kubernetes.metrics_info + + cloudwatch_container_insights.metrics_info, + }, + strict=False, + ) return cloudwatch_vo @@ -184,27 +245,31 @@ def _convert_tag_format(tags): list_tags = [] for _key in tags: - list_tags.append({'key': _key, 'value': tags[_key]}) + list_tags.append({"key": _key, "value": tags[_key]}) return list_tags def get_auto_scaling_groups(self): - auto_scaling_client = self.session.client('autoscaling', verify=BOTO3_HTTPS_VERIFIED) - paginator = auto_scaling_client.get_paginator('describe_auto_scaling_groups') + auto_scaling_client = self.session.client( + "autoscaling", verify=BOTO3_HTTPS_VERIFIED + ) + paginator = auto_scaling_client.get_paginator("describe_auto_scaling_groups") response_iterator = paginator.paginate( PaginationConfig={ - 'MaxItems': 10000, - 'PageSize': 50, + "MaxItems": 10000, + "PageSize": 50, } ) asgs = [] for data in response_iterator: - for asg in data.get('AutoScalingGroups', []): - asgs.append({ - "name": asg.get("AutoScalingGroupName", ""), - "arn": asg.get("AutoScalingGroupARN", "") - }) + for asg in data.get("AutoScalingGroups", []): + asgs.append( + { + "name": asg.get("AutoScalingGroupName", ""), + "arn": asg.get("AutoScalingGroupARN", ""), + } + ) return asgs @staticmethod @@ -214,3 +279,28 @@ def get_matched_auto_scaling_groups(asgs, asg_names): if asg.get("name", "") in asg_names: matched_asgs.append(asg) return matched_asgs + + def list_add_ons(self, cluster_name): + paginator = self.client.get_paginator("list_addons") + response_iterator = paginator.paginate( + clusterName=cluster_name, + PaginationConfig={ + "MaxItems": 10000, + "PageSize": 50, + }, + ) + + errors = [] + + for data in response_iterator: + for addon_name in data.get("addons", []): + try: + add_on_response = self.client.describe_addon( + clusterName=cluster_name, + addonName=addon_name, + ) + + yield AddOn(add_on_response.get("addon", {}), strict=False) + + except Exception as e: + errors.append(self.generate_error(cluster_name, addon_name, e)) diff --git a/src/spaceone/inventory/connector/aws_eks_connector/schema/data.py b/src/spaceone/inventory/connector/aws_eks_connector/schema/data.py index 35561903..476099b5 100644 --- a/src/spaceone/inventory/connector/aws_eks_connector/schema/data.py +++ b/src/spaceone/inventory/connector/aws_eks_connector/schema/data.py @@ -1,35 +1,77 @@ import logging from schematics import Model -from schematics.types import ModelType, StringType, IntType, DateTimeType, ListType, BooleanType, DictType +from schematics.types import ( + ModelType, + StringType, + IntType, + DateTimeType, + ListType, + BooleanType, + DictType, +) from spaceone.inventory.libs.schema.resource import AWSCloudService _LOGGER = logging.getLogger(__name__) class UpdateParams(Model): - type = StringType(deserialize_from="type", choices=("Version", "PlatformVersion", "EndpointPrivateAccess", - "EndpointPublicAccess", "ClusterLogging", "DesiredSize", - "LabelsToAdd", "LabelsToRemove", "MaxSize", "MinSize", - "ReleaseVersion", "PublicAccessCidrs")) + type = StringType( + deserialize_from="type", + choices=( + "Version", + "PlatformVersion", + "EndpointPrivateAccess", + "EndpointPublicAccess", + "ClusterLogging", + "DesiredSize", + "LabelsToAdd", + "LabelsToRemove", + "MaxSize", + "MinSize", + "ReleaseVersion", + "PublicAccessCidrs", + ), + ) value = StringType(deserialize_from="value") class UpdateErrors(Model): - error_code = StringType(deserialize_from="errorCode", choices=("SubnetNotFound", "SecurityGroupNotFound", - "EniLimitReached", "IpNotAvailable", "AccessDenied", - "OperationNotPermitted", "VpcIdNotFound", "Unknown", - "NodeCreationFailure", "PodEvictionFailure", - "InsufficientFreeAddresses")) + error_code = StringType( + deserialize_from="errorCode", + choices=( + "SubnetNotFound", + "SecurityGroupNotFound", + "EniLimitReached", + "IpNotAvailable", + "AccessDenied", + "OperationNotPermitted", + "VpcIdNotFound", + "Unknown", + "NodeCreationFailure", + "PodEvictionFailure", + "InsufficientFreeAddresses", + ), + ) error_message = StringType(deserialize_from="errorMessage") resource_ids = ListType(StringType, deserialize_from="resourceIds") class Update(Model): id = StringType(deserialize_from="id") - status = StringType(deserialize_from="status", choices=("InProgress", "Failed", "Cancelled", "Successful")) - type = StringType(deserialize_from="type", choices=("VersionUpdate", "EndpointAccessUpdate", - "LoggingUpdate", "ConfigUpdate")) + status = StringType( + deserialize_from="status", + choices=("InProgress", "Failed", "Cancelled", "Successful"), + ) + type = StringType( + deserialize_from="type", + choices=( + "VersionUpdate", + "EndpointAccessUpdate", + "LoggingUpdate", + "ConfigUpdate", + ), + ) params = ListType(ModelType(UpdateParams), deserialize_from="params") created_at = DateTimeType(deserialize_from="createdAt") errors = ListType(ModelType(UpdateErrors), deserialize_from="errors") @@ -43,7 +85,9 @@ class scalingConfig(Model): class remoteAccess(Model): ec2_ssh_key = StringType(deserialize_from="ec2SshKey") - source_security_groups = ListType(StringType, deserialize_from="sourceSecurityGroups") + source_security_groups = ListType( + StringType, deserialize_from="sourceSecurityGroups" + ) class labels(Model): @@ -56,28 +100,37 @@ class resourcesAutoScalingGroups(Model): class resources(Model): - auto_scaling_groups = ListType(ModelType(resourcesAutoScalingGroups), deserialize_from="autoScalingGroups") - remote_access_security_group = StringType(deserialize_from="remoteAccessSecurityGroup") + auto_scaling_groups = ListType( + ModelType(resourcesAutoScalingGroups), deserialize_from="autoScalingGroups" + ) + remote_access_security_group = StringType( + deserialize_from="remoteAccessSecurityGroup" + ) class healthIssues(Model): - code = StringType(deserialize_from="code", choices=("AutoScalingGroupNotFound", - "AutoScalingGroupInvalidConfiguration", - "Ec2SecurityGroupNotFound", - "Ec2SecurityGroupDeletionFailure", - "Ec2LaunchTemplateNotFound", - "Ec2LaunchTemplateVersionMismatch", - "Ec2SubnetNotFound", - "Ec2SubnetInvalidConfiguration", - "IamInstanceProfileNotFound", - "IamLimitExceeded", - "IamNodeRoleNotFound", - "NodeCreationFailure", - "AsgInstanceLaunchFailures", - "InstanceLimitExceeded", - "InsufficientFreeAddresses", - "AccessDenied", - "InternalFailure")) + code = StringType( + deserialize_from="code", + choices=( + "AutoScalingGroupNotFound", + "AutoScalingGroupInvalidConfiguration", + "Ec2SecurityGroupNotFound", + "Ec2SecurityGroupDeletionFailure", + "Ec2LaunchTemplateNotFound", + "Ec2LaunchTemplateVersionMismatch", + "Ec2SubnetNotFound", + "Ec2SubnetInvalidConfiguration", + "IamInstanceProfileNotFound", + "IamLimitExceeded", + "IamNodeRoleNotFound", + "NodeCreationFailure", + "AsgInstanceLaunchFailures", + "InstanceLimitExceeded", + "InsufficientFreeAddresses", + "AccessDenied", + "InternalFailure", + ), + ) message = StringType(deserialize_from="message") resource_ids = ListType(StringType, deserialize_from="resourceIds") @@ -95,13 +148,25 @@ class NodeGroup(AWSCloudService): release_version = StringType(deserialize_from="releaseVersion") created_at = DateTimeType(deserialize_from="createdAt") modified_at = DateTimeType(deserialize_from="modifiedAt") - status = StringType(deserialize_from="status", choices=("CREATING", "ACTIVE", "UPDATING", "DELETING", - "CREATE_FAILED", "DELETE_FAILED", "DEGRADED")) + status = StringType( + deserialize_from="status", + choices=( + "CREATING", + "ACTIVE", + "UPDATING", + "DELETING", + "CREATE_FAILED", + "DELETE_FAILED", + "DEGRADED", + ), + ) scaling_config = ModelType(scalingConfig, deserialize_from="scalingConfig") instance_types = ListType(StringType, deserialize_from="instanceTypes") subnets = ListType(StringType, deserialize_from="subnets") remote_access = ModelType(remoteAccess, deserialize_from="remoteAccess") - ami_type = StringType(deserialize_from="amiType", choices=("AL2_x86_64", "AL2_x86_64_GPU")) + ami_type = StringType( + deserialize_from="amiType", choices=("AL2_x86_64", "AL2_x86_64_GPU") + ) node_role = StringType(deserialize_from="nodeRole") labels = ModelType(labels, deserialize_from="labels") resources = ModelType(resources, deserialize_from="resources") @@ -112,12 +177,15 @@ class NodeGroup(AWSCloudService): def reference(self, region_code): return { "resource_id": self.nodegroup_arn, - "external_link": f"https://console.aws.amazon.com/eks/home?region={region_code}#/clusters/{self.cluster_name}" + "external_link": f"https://console.aws.amazon.com/eks/home?region={region_code}#/clusters/{self.cluster_name}", } -''' + +""" CLUSTER -''' +""" + + class resourcesVpcConfig(Model): subnet_ids = ListType(StringType, deserialize_from="subnetIds") security_group_ids = ListType(StringType, deserialize_from="securityGroupIds") @@ -134,7 +202,9 @@ class loggingClusterLogging(Model): class logging(Model): - cluster_logging = ListType(ModelType(loggingClusterLogging), deserialize_from="clusterLogging") + cluster_logging = ListType( + ModelType(loggingClusterLogging), deserialize_from="clusterLogging" + ) class oidc(Model): @@ -158,6 +228,29 @@ class ClusterencryptionConfig(Model): provider = ModelType(provider, deserialize_from="provider") +class AddOn(Model): + add_on_name = StringType(deserialize_from="addonName") + status = StringType( + deserialize_from="status", + choices=( + "CREATING", + "ACTIVE", + "CREATE_FAILED", + "UPDATING", + "DELETING", + "DELETE_FAILED", + "DEGRADED", + "UPDATE_FAILED", + ), + ) + version = StringType(deserialize_from="addonVersion") + arn = StringType(deserialize_from="addonArn") + irsa = StringType(deserialize_from="serviceAccountRoleArn") + eks_pod_identity = ListType( + StringType(), deserialize_from="podIdentityAssociations" + ) + + class Cluster(AWSCloudService): name = StringType(deserialize_from="name") arn = StringType(deserialize_from="arn") @@ -165,19 +258,29 @@ class Cluster(AWSCloudService): version = StringType(deserialize_from="version") endpoint = StringType(deserialize_from="endpoint") role_arn = StringType(deserialize_from="roleArn") - resources_vpc_config = ModelType(resourcesVpcConfig, deserialize_from="resourcesVpcConfig") + resources_vpc_config = ModelType( + resourcesVpcConfig, deserialize_from="resourcesVpcConfig" + ) logging = ModelType(logging, deserialize_from="logging") identity = ModelType(identity, deserialize_from="identity") - status = StringType(deserialize_from="status", choices=("CREATING", "ACTIVE", "DELETING", "FAILED", "UPDATING")) - certificate_authority = ModelType(certificateAuthority, deserialize_from="certificateAuthority") + status = StringType( + deserialize_from="status", + choices=("CREATING", "ACTIVE", "DELETING", "FAILED", "UPDATING"), + ) + certificate_authority = ModelType( + certificateAuthority, deserialize_from="certificateAuthority" + ) client_request_token = StringType(deserialize_from="clientRequestToken") platform_version = StringType(deserialize_from="platformVersion") - encryption_config = ListType(ModelType(ClusterencryptionConfig), deserialize_from="encryptionConfig") + encryption_config = ListType( + ModelType(ClusterencryptionConfig), deserialize_from="encryptionConfig" + ) node_groups = ListType(ModelType(NodeGroup)) updates = ListType(ModelType(Update)) + add_ons = ListType(ModelType(AddOn)) def reference(self, region_code): return { "resource_id": self.arn, - "external_link": f"https://console.aws.amazon.com/eks/home?region={region_code}#/clusters/{self.name}" + "external_link": f"https://console.aws.amazon.com/eks/home?region={region_code}#/clusters/{self.name}", } diff --git a/src/spaceone/inventory/connector/aws_eks_connector/schema/resource.py b/src/spaceone/inventory/connector/aws_eks_connector/schema/resource.py index 77baa16b..0eb2b76e 100644 --- a/src/spaceone/inventory/connector/aws_eks_connector/schema/resource.py +++ b/src/spaceone/inventory/connector/aws_eks_connector/schema/resource.py @@ -1,138 +1,244 @@ from schematics.types import ModelType, StringType, PolyModelType -from spaceone.inventory.connector.aws_eks_connector.schema.data import Cluster, NodeGroup -from spaceone.inventory.libs.schema.dynamic_field import TextDyField, ListDyField, EnumDyField, DateTimeDyField -from spaceone.inventory.libs.schema.dynamic_layout import ItemDynamicLayout, TableDynamicLayout, \ - SimpleTableDynamicLayout -from spaceone.inventory.libs.schema.resource import CloudServiceResource, CloudServiceResponse, CloudServiceMeta - -cluster_base = ItemDynamicLayout.set_fields('Cluster', fields=[ - TextDyField.data_source('Name', 'data.name'), - TextDyField.data_source('ARN', 'data.arn'), - EnumDyField.data_source('Status', 'data.status', default_state={ - 'safe': ['ACTIVE'], - 'warning': ['CREATING', 'DELETING', 'UPDATING'], - 'alert': ['FAILED'] - }), - TextDyField.data_source('Version', 'data.version'), - TextDyField.data_source('Endpoint', 'data.endpoint'), - TextDyField.data_source('Role ARN', 'data.role_arn'), - TextDyField.data_source('Certificate Authority', 'data.certificate_authority.data'), -]) - -cluster_node_groups = TableDynamicLayout.set_fields('Node Groups', 'data.node_groups', fields=[ - TextDyField.data_source('Group Name', 'nodegroup_name'), - EnumDyField.data_source('Status', 'status', default_state={ - 'safe': ['ACTIVE'], - 'warning': ['CREATING', 'UPDATING', 'DELETING'], - 'alert': ['CREATE_FAILED', 'DELETE_FAILED', 'DEGRADED'], - }), - ListDyField.data_source('Instance Types', 'instance_types', options={ - 'delimiter': '
' - }), - ListDyField.data_source('Subnets', 'subnets', options={ - 'delimiter': '
' - }), - TextDyField.data_source('Disk Size', 'disk_size'), - ListDyField.data_source('Health Issue', 'instance_types', options={ - 'delimiter': '
' - }), -]) - -cluster_logging = TableDynamicLayout.set_fields('Cluster Logging', 'data.logging.cluster_logging', fields=[ - ListDyField.data_source('Types', 'types', options={ - 'delimiter': '
' - }), - EnumDyField.data_source('Enabled', 'enabled', default_badge={ - 'indigo.500': ['true'], 'coral.600': ['false'] - }), -]) - -cluster_update = TableDynamicLayout.set_fields('Updates', 'data.updates', fields=[ - TextDyField.data_source('Update ID', 'id'), - EnumDyField.data_source('Status', 'status', default_state={ - 'safe': ['Successful'], - 'warning': ['InProgress'], - 'alert': ['Failed'], - 'disable': ['Cancelled'] - }), - TextDyField.data_source('Type', 'type'), - DateTimeDyField.data_source('Submission Time', 'created_at'), - ListDyField.data_source('Error', 'errors.error_code', options={ - 'delimiter': '
' - }) -]) +from spaceone.inventory.connector.aws_eks_connector.schema.data import ( + Cluster, + NodeGroup, +) +from spaceone.inventory.libs.schema.dynamic_field import ( + TextDyField, + ListDyField, + EnumDyField, + DateTimeDyField, +) +from spaceone.inventory.libs.schema.dynamic_layout import ( + ItemDynamicLayout, + TableDynamicLayout, + SimpleTableDynamicLayout, +) +from spaceone.inventory.libs.schema.resource import ( + CloudServiceResource, + CloudServiceResponse, + CloudServiceMeta, +) + +cluster_base = ItemDynamicLayout.set_fields( + "Cluster", + fields=[ + TextDyField.data_source("Name", "data.name"), + TextDyField.data_source("ARN", "data.arn"), + EnumDyField.data_source( + "Status", + "data.status", + default_state={ + "safe": ["ACTIVE"], + "warning": ["CREATING", "DELETING", "UPDATING"], + "alert": ["FAILED"], + }, + ), + TextDyField.data_source("Version", "data.version"), + TextDyField.data_source("Endpoint", "data.endpoint"), + TextDyField.data_source("Role ARN", "data.role_arn"), + TextDyField.data_source( + "Certificate Authority", "data.certificate_authority.data" + ), + ], +) + +cluster_node_groups = TableDynamicLayout.set_fields( + "Node Groups", + "data.node_groups", + fields=[ + TextDyField.data_source("Group Name", "nodegroup_name"), + EnumDyField.data_source( + "Status", + "status", + default_state={ + "safe": ["ACTIVE"], + "warning": ["CREATING", "UPDATING", "DELETING"], + "alert": ["CREATE_FAILED", "DELETE_FAILED", "DEGRADED"], + }, + ), + ListDyField.data_source( + "Instance Types", "instance_types", options={"delimiter": "
"} + ), + ListDyField.data_source("Subnets", "subnets", options={"delimiter": "
"}), + TextDyField.data_source("Disk Size", "disk_size"), + ListDyField.data_source( + "Health Issue", "instance_types", options={"delimiter": "
"} + ), + ], +) + +cluster_addons = TableDynamicLayout.set_fields( + "Add Ons", + "data.add_ons", + fields=[ + TextDyField.data_source("Addon Name", "add_on_name"), + EnumDyField.data_source( + "Status", + "status", + default_state={ + "safe": ["ACTIVE"], + "warning": ["CREATING", "UPDATING", "DELETING"], + "alert": [ + "CREATE_FAILED", + "DELETE_FAILED", + "DEGRADED", + "UPDATE_FAILED", + ], + }, + ), + TextDyField.data_source("Version", "version"), + TextDyField.data_source("Add on Arn", "arn"), + ListDyField.data_source( + "EKS Pod Identity", "eks_pod_identity", options={"delimiter": "
"} + ), + TextDyField.data_source("IAM role for service account", "irsa"), + ], +) +cluster_logging = TableDynamicLayout.set_fields( + "Cluster Logging", + "data.logging.cluster_logging", + fields=[ + ListDyField.data_source("Types", "types", options={"delimiter": "
"}), + EnumDyField.data_source( + "Enabled", + "enabled", + default_badge={"indigo.500": ["true"], "coral.600": ["false"]}, + ), + ], +) + +cluster_update = TableDynamicLayout.set_fields( + "Updates", + "data.updates", + fields=[ + TextDyField.data_source("Update ID", "id"), + EnumDyField.data_source( + "Status", + "status", + default_state={ + "safe": ["Successful"], + "warning": ["InProgress"], + "alert": ["Failed"], + "disable": ["Cancelled"], + }, + ), + TextDyField.data_source("Type", "type"), + DateTimeDyField.data_source("Submission Time", "created_at"), + ListDyField.data_source( + "Error", "errors.error_code", options={"delimiter": "
"} + ), + ], +) cluster_metadata = CloudServiceMeta.set_layouts( - layouts=[cluster_base, cluster_node_groups, cluster_logging]) - -node_group_base = ItemDynamicLayout.set_fields('Node Group', fields=[ - TextDyField.data_source('Node Group Name', 'data.nodegroup_name'), - TextDyField.data_source('Node Group ARN', 'data.nodegroup_arn'), - EnumDyField.data_source('Status', 'data.status', default_state={ - 'safe': ['ACTIVE'], - 'warning': ['CREATING', 'UPDATING', 'DELETING'], - 'alert': ['CREATE_FAILED', 'DELETE_FAILED', 'DEGRADED'], - }), - TextDyField.data_source('EKS Cluster Name', 'data.cluster_name'), - TextDyField.data_source('EKS Cluster ARN', 'data.cluster_arn'), - TextDyField.data_source('Version', 'data.version'), - TextDyField.data_source('Release Version', 'data.release_version'), - ListDyField.data_source('Instance Types', 'data.instance_types', options={ - 'delimiter': '
' - }), - ListDyField.data_source('Subnets', 'data.subnets', options={ - 'delimiter': '
' - }), - ListDyField.data_source('Source Security Group', 'data.remote_access.source_security_groups', options={ - 'delimiter': '
' - }), - TextDyField.data_source('AMI Type', 'data.ami_type'), - TextDyField.data_source('Node Role', 'data.node_role'), - TextDyField.data_source('Labels', 'data.labels.string'), - TextDyField.data_source('Disk Size', 'data.disk_size'), - DateTimeDyField.data_source('Creation Time', 'data.created_at'), - DateTimeDyField.data_source('Modification Time', 'data.modified_at') -]) - -node_group_scaling_config = ItemDynamicLayout.set_fields('Scaling Config', fields=[ - TextDyField.data_source('Min Size', 'data.scaling_config.min_size'), - TextDyField.data_source('Max Size', 'data.scaling_config.max_size'), - TextDyField.data_source('Desired Size', 'data.scaling_config.desired_size'), -]) - -node_group_resource = ItemDynamicLayout.set_fields('Resources', fields=[ - ListDyField.data_source('Auto Scaling Group Name', 'data.resources.auto_scaling_groups', options={ - 'delimiter': '
', - 'sub_key': 'name' - }), - ListDyField.data_source('Auto Scaling Group ARN', 'data.resources.auto_scaling_groups', options={ - 'delimiter': '
', - 'sub_key': 'arn' - }), - TextDyField.data_source('Remote Access Security Group', 'data.resources.remote_access_security_group'), -]) - -node_group_health = TableDynamicLayout.set_fields('Health', 'data.health.issues', fields=[ - TextDyField.data_source('Code', 'code'), - TextDyField.data_source('Message', 'message'), - ListDyField.data_source('Resource IDs', 'resource_ids', options={ - 'delimiter': '
', - }), -]) - -node_group_metadata = CloudServiceMeta.set_layouts(layouts=[node_group_base, node_group_scaling_config, - node_group_resource, node_group_health]) + layouts=[cluster_base, cluster_node_groups, cluster_addons, cluster_logging] +) + +node_group_base = ItemDynamicLayout.set_fields( + "Node Group", + fields=[ + TextDyField.data_source("Node Group Name", "data.nodegroup_name"), + TextDyField.data_source("Node Group ARN", "data.nodegroup_arn"), + EnumDyField.data_source( + "Status", + "data.status", + default_state={ + "safe": ["ACTIVE"], + "warning": ["CREATING", "UPDATING", "DELETING"], + "alert": ["CREATE_FAILED", "DELETE_FAILED", "DEGRADED"], + }, + ), + TextDyField.data_source("EKS Cluster Name", "data.cluster_name"), + TextDyField.data_source("EKS Cluster ARN", "data.cluster_arn"), + TextDyField.data_source("Version", "data.version"), + TextDyField.data_source("Release Version", "data.release_version"), + ListDyField.data_source( + "Instance Types", "data.instance_types", options={"delimiter": "
"} + ), + ListDyField.data_source( + "Subnets", "data.subnets", options={"delimiter": "
"} + ), + ListDyField.data_source( + "Source Security Group", + "data.remote_access.source_security_groups", + options={"delimiter": "
"}, + ), + TextDyField.data_source("AMI Type", "data.ami_type"), + TextDyField.data_source("Node Role", "data.node_role"), + TextDyField.data_source("Labels", "data.labels.string"), + TextDyField.data_source("Disk Size", "data.disk_size"), + DateTimeDyField.data_source("Creation Time", "data.created_at"), + DateTimeDyField.data_source("Modification Time", "data.modified_at"), + ], +) + +node_group_scaling_config = ItemDynamicLayout.set_fields( + "Scaling Config", + fields=[ + TextDyField.data_source("Min Size", "data.scaling_config.min_size"), + TextDyField.data_source("Max Size", "data.scaling_config.max_size"), + TextDyField.data_source("Desired Size", "data.scaling_config.desired_size"), + ], +) + +node_group_resource = ItemDynamicLayout.set_fields( + "Resources", + fields=[ + ListDyField.data_source( + "Auto Scaling Group Name", + "data.resources.auto_scaling_groups", + options={"delimiter": "
", "sub_key": "name"}, + ), + ListDyField.data_source( + "Auto Scaling Group ARN", + "data.resources.auto_scaling_groups", + options={"delimiter": "
", "sub_key": "arn"}, + ), + TextDyField.data_source( + "Remote Access Security Group", + "data.resources.remote_access_security_group", + ), + ], +) + +node_group_health = TableDynamicLayout.set_fields( + "Health", + "data.health.issues", + fields=[ + TextDyField.data_source("Code", "code"), + TextDyField.data_source("Message", "message"), + ListDyField.data_source( + "Resource IDs", + "resource_ids", + options={ + "delimiter": "
", + }, + ), + ], +) + +node_group_metadata = CloudServiceMeta.set_layouts( + layouts=[ + node_group_base, + node_group_scaling_config, + node_group_resource, + node_group_health, + ] +) class EKSResource(CloudServiceResource): - cloud_service_group = StringType(default='EKS') + cloud_service_group = StringType(default="EKS") class ClusterResource(EKSResource): - cloud_service_type = StringType(default='Cluster') + cloud_service_type = StringType(default="Cluster") data = ModelType(Cluster) - _metadata = ModelType(CloudServiceMeta, default=cluster_metadata, serialized_name='metadata') + _metadata = ModelType( + CloudServiceMeta, default=cluster_metadata, serialized_name="metadata" + ) class ClusterResponse(CloudServiceResponse): @@ -140,9 +246,11 @@ class ClusterResponse(CloudServiceResponse): class NodeGroupResource(EKSResource): - cloud_service_type = StringType(default='NodeGroup') + cloud_service_type = StringType(default="NodeGroup") data = ModelType(NodeGroup) - _metadata = ModelType(CloudServiceMeta, default=node_group_metadata, serialized_name='metadata') + _metadata = ModelType( + CloudServiceMeta, default=node_group_metadata, serialized_name="metadata" + ) class NodeGroupResponse(CloudServiceResponse):