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 1d21d8d9..92bf1df6 100644 --- a/src/spaceone/inventory/connector/aws_cloud_watch_connector/connector.py +++ b/src/spaceone/inventory/connector/aws_cloud_watch_connector/connector.py @@ -1,10 +1,13 @@ import logging +from typing import Generator, List from spaceone.core.utils import * from spaceone.inventory.connector.aws_cloud_watch_connector.schema.data import Alarms from spaceone.inventory.connector.aws_cloud_watch_connector.schema.resource import AlarmsResource, AlarmsResponse from spaceone.inventory.connector.aws_cloud_watch_connector.schema.service_type import CLOUD_SERVICE_TYPES +from spaceone.inventory.connector.aws_dynamodb_connector.schema.data import Table +from spaceone.inventory.connector.aws_dynamodb_connector.schema.resource import TableResource from spaceone.inventory.libs.connector import SchematicAWSConnector @@ -24,7 +27,7 @@ class CloudWatchConnector(SchematicAWSConnector): "GreaterThanUpperThreshold": ">" } - def get_resources(self): + def get_resources(self) -> List[TableResource]: _LOGGER.debug(f"[get_resources][account_id: {self.account_id}] START: CloudWatch") resources = [] start_time = time.time() @@ -60,17 +63,24 @@ 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"] + paginator = self.client.get_paginator("describe_alarms") + response_iterator = paginator.paginate( + PaginationConfig={ + "MaxRecords": 100, + } + ) + + for data in response_iterator: + # Only MetricAlarms are returned temporarily, CompositeAlarms must be applied later. + for raw in data.get("MetricAlarms", []): + yield raw - def request_alarms_data(self, region_name): + def request_alarms_data(self, region_name: str) -> List[Table]: self.cloud_service_type = "Alarm" cloudwatch_resource_type = "AWS::CloudWatch::Alarm" try: raw_alarms = self.get_alarms() - for raw_alarm in raw_alarms: self._set_alarm_conditions(raw_alarm) self._set_alarm_actions(raw_alarm) @@ -91,7 +101,7 @@ def request_alarms_data(self, region_name): ) yield {"data": error_resource_response} - def _set_alarm_conditions(self, raw_alarm): + def _set_alarm_conditions(self, raw_alarm: Alarms) -> None: metric_name = raw_alarm.get("MetricName", "?") period = raw_alarm["Period"] evaluation_periods = self._convert_int_type(raw_alarm.get("EvaluationPeriods", "?")) @@ -104,7 +114,7 @@ def _set_alarm_conditions(self, raw_alarm): raw_alarm["conditions"] = f"{metric_name} {operator} {threshold} for {evaluation_periods} datapoionts within {period_minutes} minutes" @staticmethod - def _set_alarm_actions(raw_alarm): + def _set_alarm_actions(raw_alarm: Alarms) -> None: raw_alarm["actions"] = [] actions = raw_alarm["actions"] alarm_actions = raw_alarm.get("AlarmActions", []) @@ -132,18 +142,27 @@ def _set_alarm_actions(raw_alarm): actions.append({"type": action_type, "description": action_description, "config": action_config}) 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"] + raw_alarm["actions_enabled"] = "No actions" + + def get_alarm_history(self, alarm_name: str) -> Generator[dict, None, None]: + paginator = self.client.get_paginator("describe_alarm_history") + response_iterator = paginator.paginate( + PaginationConfig={ + "AlarmName": alarm_name, + "MaxItems": 100, + "ScanBy": "TimestampDescending", + } + ) - def _set_alarm_history(self, raw_alarm): - alarm_histories = self.get_alarm_history(raw_alarm["AlarmName"]) + for data in response_iterator: + for raw in data.get("AlarmHistoryItems", []): + yield raw + def _set_alarm_history(self, raw_alarm: Alarms) -> None: raw_alarm["history"] = [] history = raw_alarm["history"] + alarm_histories = self.get_alarm_history(raw_alarm["AlarmName"]) for alarm_history in alarm_histories: history.append( { 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 bac7a84d..f66d0662 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 @@ -24,9 +24,11 @@ EnumDyField.data_source("State", "data.state_value", default_badge={ 'gray.500': ['INSUFFICIENT_DATA'], 'green.500': ['OK'], 'red.500': ['ALARM'] }), - TextDyField.data_source("State", "data.state_value"), DateTimeDyField.data_source("Last State Update", "data.state_updated_timestamp"), TextDyField.data_source("Conditions", "data.conditions"), + EnumDyField.data_source("Actions", "data.actions_enabled", default_badge={ + 'gray.500': ['No actions'], 'green.500': ['Actions enabled'] + }), ListDyField.data_source("Actions", "data.actions_enabled"), ], search=[