Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/c7n/filters/health.py: 25%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

55 statements  

1# Copyright The Cloud Custodian Authors. 

2# SPDX-License-Identifier: Apache-2.0 

3import itertools 

4 

5from c7n.utils import local_session, chunks, type_schema 

6from .core import Filter 

7from c7n.manager import resources 

8 

9 

10class HealthEventFilter(Filter): 

11 """Check if there are operations health events (phd) related to the resources 

12 

13 https://aws.amazon.com/premiumsupport/technology/personal-health-dashboard/ 

14 

15 Health events are stored as annotation on a resource. 

16 

17 Custodian also supports responding to phd events via a lambda execution mode. 

18 """ 

19 schema_alias = True 

20 schema = type_schema( 

21 'health-event', 

22 types={'type': 'array', 'items': {'type': 'string'}}, 

23 category={'type': 'array', 'items': { 

24 'enum': ['issue', 'accountNotification', 'scheduledChange']}}, 

25 statuses={'type': 'array', 'items': { 

26 'type': 'string', 

27 'enum': ['open', 'upcoming', 'closed'] 

28 }}) 

29 permissions = ('health:DescribeEvents', 'health:DescribeAffectedEntities', 

30 'health:DescribeEventDetails') 

31 

32 def process(self, resources, event=None): 

33 client = local_session(self.manager.session_factory).client( 

34 'health', region_name='us-east-1') 

35 f = self.get_filter_parameters() 

36 if self.manager.data['resource'] in {'app-elb'}: 

37 id_attr = self.manager.get_model().name 

38 else: 

39 id_attr = self.manager.get_model().id 

40 resource_map = {r[id_attr]: r for r in resources} 

41 found = set() 

42 seen = set() 

43 

44 for resource_set in chunks(resource_map.keys(), 99): 

45 f['entityValues'] = resource_set 

46 events = client.describe_events(filter=f)['events'] 

47 events = [e for e in events if e['arn'] not in seen] 

48 entities = self.process_event(client, events) 

49 

50 event_map = {e['arn']: e for e in events} 

51 for e in entities: 

52 rid = e['entityValue'] 

53 if rid not in resource_map: 

54 continue 

55 resource_map[rid].setdefault( 

56 'c7n:HealthEvent', []).append(event_map[e['eventArn']]) 

57 found.add(rid) 

58 seen.update(event_map.keys()) 

59 return [resource_map[resource_id] for resource_id in found] 

60 

61 def get_filter_parameters(self): 

62 phd_svc_name_map = { 

63 'app-elb': 'ELASTICLOADBALANCING', 

64 'ebs': 'EBS', 

65 'efs': 'ELASTICFILESYSTEM', 

66 'elb': 'ELASTICLOADBALANCING', 

67 'emr': 'ELASTICMAPREDUCE' 

68 } 

69 m = self.manager 

70 service = phd_svc_name_map.get(m.data['resource'], m.get_model().service.upper()) 

71 f = {'services': [service], 

72 'regions': [self.manager.config.region, 'global'], 

73 'eventStatusCodes': self.data.get( 

74 'statuses', ['open', 'upcoming'])} 

75 if self.data.get('types'): 

76 f['eventTypeCodes'] = self.data.get('types') 

77 return f 

78 

79 def process_event(self, client, health_events): 

80 entities = [] 

81 for event_set in chunks(health_events, 10): 

82 event_map = {e['arn']: e for e in event_set} 

83 event_arns = list(event_map.keys()) 

84 for d in client.describe_event_details( 

85 eventArns=event_arns).get('successfulSet', ()): 

86 event_map[d['event']['arn']]['Description'] = d[ 

87 'eventDescription']['latestDescription'] 

88 paginator = client.get_paginator('describe_affected_entities') 

89 entities.extend(list(itertools.chain( 

90 *[p['entities'] for p in paginator.paginate( 

91 filter={'eventArns': event_arns})]))) 

92 return entities 

93 

94 @classmethod 

95 def register_resources(klass, registry, resource_class): 

96 """ meta model subscriber on resource registration. 

97 

98 We watch for PHD event that provides affected entities and register 

99 the health-event filter to the resources. 

100 """ 

101 services = {'acm-certificate', 'directconnect', 'dms-instance', 'directory', 'ec2', 

102 'dynamodb-table', 'cache-cluster', 'efs', 'app-elb', 'elb', 'emr', 'rds', 

103 'storage-gateway'} 

104 if resource_class.type in services: 

105 resource_class.filter_registry.register('health-event', klass) 

106 

107 

108resources.subscribe(HealthEventFilter.register_resources)