From 10aead5797d50add8008b8a1406bae8bcb327bfb Mon Sep 17 00:00:00 2001 From: jinyoungmoonDEV Date: Wed, 8 Jan 2025 18:06:10 +0900 Subject: [PATCH] fix: add history metadata & fix bugs --- .../inventory/conf/cloud_service_conf.py | 56 +++++++++---------- .../aws_cloud_watch_connector/connector.py | 34 ++++++++--- .../aws_cloud_watch_connector/schema/data.py | 9 ++- .../schema/resource.py | 13 ++++- .../schema/service_type.py | 12 ++-- 5 files changed, 79 insertions(+), 45 deletions(-) diff --git a/src/spaceone/inventory/conf/cloud_service_conf.py b/src/spaceone/inventory/conf/cloud_service_conf.py index f6987bd9..d22b6c81 100644 --- a/src/spaceone/inventory/conf/cloud_service_conf.py +++ b/src/spaceone/inventory/conf/cloud_service_conf.py @@ -12,34 +12,34 @@ DEFAULT_VULNERABLE_PORTS = "22,3306" CLOUD_SERVICE_GROUP_MAP = { - "IAM": "IAMConnectorManager", - "DynamoDB": "DynamoDBConnectorManager", - "Lambda": "LambdaConnectorManager", - "CloudFront": "CloudFrontConnectorManager", - "RDS": "RDSConnectorManager", - "Route53": "Route53ConnectorManager", - "S3": "S3ConnectorManager", - "ElastiCache": "ElastiCacheConnectorManager", - "APIGateway": "APIGatewayConnectorManager", - "DirectConnect": "DirectConnectConnectorManager", - "EFS": "EFSConnectorManager", - "DocumentDB": "DocumentDBConnectorManager", - "ECS": "ECSConnectorManager", - "Redshift": "RedshiftConnectorManager", - "EKS": "EKSConnectorManager", - "SQS": "SQSConnectorManager", - "KMS": "KMSConnectorManager", - "ECR": "ECRConnectorManager", - "CloudTrail": "CloudTrailConnectorManager", - "SNS": "SNSConnectorManager", - "SecretsManager": "SecretsManagerConnectorManager", - "ELB": "ELBConnectorManager", - "VPC": "VPCConnectorManager", - "ACM": "ACMConnectorManager", - "KinesisDataStream": "KinesisDataStreamConnectorManager", - "MSK": "MSKConnectorManager", - "KinesisFirehose": "KinesisFirehoseConnectorManager", - "Lightsail": "LightsailConnectorManager", + # "IAM": "IAMConnectorManager", + # "DynamoDB": "DynamoDBConnectorManager", + # "Lambda": "LambdaConnectorManager", + # "CloudFront": "CloudFrontConnectorManager", + # "RDS": "RDSConnectorManager", + # "Route53": "Route53ConnectorManager", + # "S3": "S3ConnectorManager", + # "ElastiCache": "ElastiCacheConnectorManager", + # "APIGateway": "APIGatewayConnectorManager", + # "DirectConnect": "DirectConnectConnectorManager", + # "EFS": "EFSConnectorManager", + # "DocumentDB": "DocumentDBConnectorManager", + # "ECS": "ECSConnectorManager", + # "Redshift": "RedshiftConnectorManager", + # "EKS": "EKSConnectorManager", + # "SQS": "SQSConnectorManager", + # "KMS": "KMSConnectorManager", + # "ECR": "ECRConnectorManager", + # "CloudTrail": "CloudTrailConnectorManager", + # "SNS": "SNSConnectorManager", + # "SecretsManager": "SecretsManagerConnectorManager", + # "ELB": "ELBConnectorManager", + # "VPC": "VPCConnectorManager", + # "ACM": "ACMConnectorManager", + # "KinesisDataStream": "KinesisDataStreamConnectorManager", + # "MSK": "MSKConnectorManager", + # "KinesisFirehose": "KinesisFirehoseConnectorManager", + # "Lightsail": "LightsailConnectorManager", "CloudWatch": "CloudWatchConnectorManager", # Not used services # "EC2": "EC2ConnectorManager", diff --git a/src/spaceone/inventory/connector/aws_cloud_watch_connector/connector.py b/src/spaceone/inventory/connector/aws_cloud_watch_connector/connector.py index b8d54208..d07384a6 100644 --- a/src/spaceone/inventory/connector/aws_cloud_watch_connector/connector.py +++ b/src/spaceone/inventory/connector/aws_cloud_watch_connector/connector.py @@ -59,6 +59,11 @@ def get_resources(self): ) return resources + def get_alarms(self): + response = self.client.describe_alarms() + # Only MetricAlarms are returned temporarily, CompositeAlarms must be applied later. + return response["MetricAlarms"] + def request_alarms_data(self, region_name): self.cloud_service_type = "Alarm" cloudwatch_resource_type = "AWS::CloudWatch::Alarm" @@ -67,9 +72,9 @@ def request_alarms_data(self, region_name): raw_alarms = self.get_alarms() for raw_alarm in raw_alarms: - - self.set_alarm_conditions(raw_alarm) + self._set_alarm_conditions(raw_alarm) self._set_alarm_actions(raw_alarm) + self._set_alarm_history(raw_alarm) alarms_vo = Alarms(raw_alarm, strict=False) self.alarms.append(alarms_vo) @@ -86,12 +91,7 @@ def request_alarms_data(self, region_name): ) yield {"data": error_resource_response} - def get_alarms(self): - response = self.client.describe_alarms() - # Only MetricAlarms are returned temporarily, CompositeAlarms must be applied later. - return response["MetricAlarms"] - - def set_alarm_conditions(self, raw_alarm): + def _set_alarm_conditions(self, raw_alarm): metric_name = raw_alarm.get("MetricName", "?") period = raw_alarm["Period"] evaluation_periods = self._convert_int_type(raw_alarm.get("EvaluationPeriods", "?")) @@ -134,6 +134,24 @@ def _set_alarm_actions(raw_alarm): else: raw_alarm["actions_enabled"] = "No Actions" + def get_alarm_history(self, alarm_name: str): + response = self.client.describe_alarm_history(AlarmName=alarm_name) + return response["AlarmHistoryItems"] + + def _set_alarm_history(self, raw_alarm): + alarm_histories = self.get_alarm_history(raw_alarm["AlarmName"]) + + raw_alarm["history"] = [] + history = raw_alarm["history"] + + for alarm_history in alarm_histories: + history.append( + { + "date": alarm_history["Timestamp"], + "type": alarm_histories["HistoryItemType"], + "description": alarm_histories["HistorySummary"] + } + ) @staticmethod def _convert_int_type(value): diff --git a/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/data.py b/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/data.py index 4a819e0a..1bba2c64 100644 --- a/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/data.py +++ b/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/data.py @@ -17,14 +17,21 @@ class Action(Model): config = StringType(deserialize_from="config") +class History(Model): + date = DateType(deserialize_from="date") + type = StringType(deserialize_from="type") + description = StringType(deserialize_from="description") + + class Alarms(AWSCloudService): alarm_arn = StringType(deserialize_from="AlarmArn") name = StringType(deserialize_from="AlarmName") state_value = StringType(choices=("OK","ALARM","INSUFFICIENT_DATA"), deserialize_from="StateValue") state_updated_timestamp = DateType(deserialize_from="StateUpdatedTimestamp") actions_enabled = StringType(deserialize_from="actions_enabled") - actions = ListType(ModelType(Action, deserialize_from="action"), deserialize_from="actions") conditions = StringType(deserialize_from="conditions") + actions = ListType(ModelType(Action, deserialize_from="action"), deserialize_from="actions") + history = ListType(ModelType(History, deserialize_from="history"), deserialize_from="history") def reference(self, region_code): return { diff --git a/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/resource.py b/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/resource.py index 3071dd08..9c00b920 100644 --- a/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/resource.py +++ b/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/resource.py @@ -1,7 +1,7 @@ from schematics.types import PolyModelType, StringType, ModelType from spaceone.inventory.connector.aws_cloud_watch_connector.schema.data import Alarms -from spaceone.inventory.libs.schema.dynamic_field import TextDyField +from spaceone.inventory.libs.schema.dynamic_field import TextDyField, DateTimeDyField from spaceone.inventory.libs.schema.dynamic_layout import TableDynamicLayout from spaceone.inventory.libs.schema.resource import CloudServiceResponse, CloudServiceResource, CloudServiceMeta @@ -15,7 +15,16 @@ ], ) -cloud_watch_metadata = CloudServiceMeta.set_layouts(layouts=[cw_actions]) +cw_history = TableDynamicLayout.set_fields( + "History", + fields=[ + DateTimeDyField.data_source("Date", "data.history.date"), + TextDyField.data_source("Type", "data.history.type"), + TextDyField.data_source("Description", "data.history.description"), + ] +) + +cloud_watch_metadata = CloudServiceMeta.set_layouts(layouts=[cw_actions,cw_history]) class CloudWatchResource(CloudServiceResource): diff --git a/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/service_type.py b/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/service_type.py index 109e5ef0..21ebf527 100644 --- a/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/service_type.py +++ b/src/spaceone/inventory/connector/aws_cloud_watch_connector/schema/service_type.py @@ -1,5 +1,5 @@ from spaceone.inventory.conf.cloud_service_conf import ASSET_URL -from spaceone.inventory.libs.schema.dynamic_field import TextDyField, ListDyField, SearchField +from spaceone.inventory.libs.schema.dynamic_field import TextDyField, ListDyField, SearchField, DateTimeDyField from spaceone.inventory.libs.schema.resource import CloudServiceTypeResponse, CloudServiceTypeResource, \ CloudServiceTypeMeta @@ -20,16 +20,16 @@ cst_alarms._metadata = CloudServiceTypeMeta.set_meta( fields=[ - TextDyField.data_source("State", "data.state"), - TextDyField.data_source("Last State Update", "data.last_state_update"), + TextDyField.data_source("State", "data.state_value"), + DateTimeDyField.data_source("Last State Update", "data.state_updated_timestamp"), TextDyField.data_source("Conditions", "data.conditions"), - ListDyField.data_source("Actions", "data.actions"), + ListDyField.data_source("Actions", "data.actions_enabled"), ], search=[ SearchField.set(name="Alarm ARN", key="data.alarm_arn"), SearchField.set(name="Alarm Name", key="data.alarm_name"), - SearchField.set(name="State", key="data.state"), - SearchField.set(name="Actions", key="data.actions"), + SearchField.set(name="State", key="data.state_value"), + SearchField.set(name="Actions", key="data.actions_enabled"), ], )