Source code for c7n.resources.health

# Copyright 2017 Capital One Services, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function, unicode_literals

import itertools

import six

from c7n.exceptions import PolicyValidationError
from c7n.query import QueryResourceManager
from c7n.manager import resources
from c7n.utils import local_session, chunks


[docs]@resources.register('health-event') class HealthEvents(QueryResourceManager): """Query resource manager for AWS health events """
[docs] class resource_type(object): service = 'health' type = 'event' enum_spec = ('describe_events', 'events', None) name = 'eventTypeCode' id = 'arn' filter_name = None filter_type = None dimension = None date = 'startTime'
permissions = ( 'health:DescribeEvents', 'health:DescribeEventDetails', 'health:DescribeAffectedEntities') def __init__(self, ctx, data): super(HealthEvents, self).__init__(ctx, data) self.queries = QueryFilter.parse( self.data.get('query', [ {'eventStatusCodes': 'open'}, {'eventTypeCategories': ['issue', 'accountNotification']}]))
[docs] def resource_query(self): qf = {} for q in self.queries: qd = q.query() if qd['Name'] in qf: for qv in qf[qd['Name']]: if qv in qf[qd['Name']]: continue qf[qd['Name']].append(qv) else: qf[qd['Name']] = [] for qv in qd['Values']: qf[qd['Name']].append(qv) return qf
[docs] def resources(self, query=None): q = self.resource_query() if q is not None: query = query or {} query['filter'] = q return super(HealthEvents, self).resources(query=query)
[docs] def augment(self, resources): client = local_session(self.session_factory).client('health') for resource_set in chunks(resources, 10): event_map = {r['arn']: r for r in resource_set} event_details = client.describe_event_details( eventArns=list(event_map.keys()))['successfulSet'] for d in event_details: event_map[d['event']['arn']][ 'Description'] = d['eventDescription']['latestDescription'] event_arns = [r['arn'] for r in resource_set if r['eventTypeCategory'] != 'accountNotification'] if not event_arns: continue paginator = client.get_paginator('describe_affected_entities') entities = list(itertools.chain( *[p['entities']for p in paginator.paginate( filter={'eventArns': event_arns})])) for e in entities: event_map[e.pop('eventArn')].setdefault( 'AffectedEntities', []).append(e) return resources
HEALTH_VALID_FILTERS = { 'availability-zone': str, 'eventTypeCategories': {'issue', 'accountNotification', 'scheduledChange'}, 'regions': str, 'services': str, 'eventStatusCodes': {'open', 'closed', 'upcoming'}, 'eventTypeCodes': str }
[docs]class QueryFilter(object):
[docs] @classmethod def parse(cls, data): results = [] for d in data: if not isinstance(d, dict): raise PolicyValidationError( "Health Query Filter Invalid structure %s" % d) results.append(cls(d).validate()) return results
def __init__(self, data): self.data = data self.key = None self.value = None
[docs] def validate(self): if not len(list(self.data.keys())) == 1: raise ValueError( "Health Query Filter Invalid %s" % self.data) self.key = list(self.data.keys())[0] self.value = list(self.data.values())[0] if self.key not in HEALTH_VALID_FILTERS: raise PolicyValidationError( "Health Query Filter invalid filter name %s" % (self.data)) if self.value is None: raise PolicyValidationError( "Health Query Filters must have a value, use tag-key" " w/ tag name as value for tag present checks" " %s" % self.data) return self
[docs] def query(self): value = self.value if isinstance(self.value, six.string_types): value = [self.value] return {'Name': self.key, 'Values': value}