def delete_dashboard(dashboard_name): ''' Deletes a Cloudwatch Dashboard ''' print("deleting", dashboard_name) response = CLIENT.delete_dashboards(DashboardNames=[dashboard_name]) show('delete_dashboards returns') show(response)
def get_dashboard_dynamodb(prefix, environment): ''' Reads the tags from the s3 buckets and returns a list of dictionaries. Each dict has a key containing the dashboard name, and their values have properties that contains a list of all the dynamodb table that are tagged with that dashboard name. ''' list_tables_response = CLIENT.list_tables() #print('list_tables_response') if DEBUG: show(list_tables_response) ret = [] tables_by_dashboard = {} offset = len(f'{prefix}-{environment}') + 1 for table_name in list_tables_response['TableNames']: if f'{prefix}-{environment}' in table_name: if DEBUG: print("\n\n\ntable_name", table_name) describe_table_response = CLIENT.describe_table(TableName=table_name) table_arn = describe_table_response['Table']['TableArn'] tags = CLIENT.list_tags_of_resource(ResourceArn=table_arn) if DEBUG: print("tags") show(tags) dashboard_list = DEFAULT_DASHBOARD_NAME for tag in tags['Tags']: if DEBUG: print('tag', tag) if tag['Key'] == TAG_NAME: dashboard_list = tag['Value'] if DEBUG: print("dashboard_list", dashboard_list) for dashboard_name in dashboard_list.split('[ ,;]'): if DEBUG: print("dashboard_name", dashboard_name) if dashboard_name not in tables_by_dashboard: # make a new dashboard name if DEBUG: print(f"----dynamodb: making a new dashboard object for {dashboard_name}") tables_by_dashboard[dashboard_name] = { 'dashboard_type': 'dynamodb', 'metric_names': list(map(lambda m: m['name'], DYNAMODB_METRICS)), 'names': [] } tables_by_dashboard[dashboard_name]['names'].append(table_name[offset:]) if DEBUG: print('tables_by_dashboard', json.dumps(tables_by_dashboard, indent=4)) print('offset', offset) for key, value in tables_by_dashboard.items(): ret.append({key: value}) return ret
def lambda_handler(event, _): ''' normal lambda entrypoint ''' messages = [] show(event) ret = {'messages': messages} try: ret['result'] = update_dashboards(event) except Exception as exc: print("Caught exception %s" % str(exc)) ret['result'] = "Caught exception %s" % str(exc) return ret
def get_dashboard_apigws(prefix, environment): ''' Similar to `get_dashboard_lambdas`, but for the restapis in the API Gateway service. ''' ret = [] get_rest_apis_response = CLIENT.get_rest_apis() apigws_by_dashboard = {} offset = len(f'{prefix}-{environment}') + 1 for item in get_rest_apis_response['items']: rest_id = item['id'] name = item['name'] if DEBUG: print('item') show(item) if f'{prefix}-{environment}' in name: if DEBUG: print("\n\n\nid", rest_id) print('name', name) arn = f'arn:aws:apigateway:{get_region()}::/restapis/{rest_id}' tags = CLIENT.get_tags(resourceArn=arn) if DEBUG: print("tags") show(tags) dashboard_list = DEFAULT_DASHBOARD_NAME if TAG_NAME not in tags['tags']: if DEBUG: print(TAG_NAME, "not found above") else: dashboard_list = tags['tags'][TAG_NAME] if DEBUG: print("dashboard_list", dashboard_list) for dashboard_name in dashboard_list.split('[ ,;]'): if DEBUG: print(".1 dashboard_name", dashboard_name) if dashboard_name not in apigws_by_dashboard: # make a new dashboard name if DEBUG: print(f"----apigw: making a new dashboard object for {dashboard_name}") apigws_by_dashboard[dashboard_name] = { 'dashboard_type': SERVICE_NAME, 'metric_names' : list(map(lambda m: m['name'], APIGW_METRICS)), 'names' : [] } apigws_by_dashboard[dashboard_name]['names'].append(name[offset:]) if DEBUG: print('apigws_by_dashboard') show(apigws_by_dashboard) print('offset', offset) for key, value in apigws_by_dashboard.items(): ret.append({key: value}) return ret
''' main entrypoint for invoking from a zip file: python3 cloudwatch_dashboards.zip ''' import json import os import sys from cloudwatch_dashboards.cloudwatch_dashboards import update_dashboards from cloudwatch_dashboards.helpers.util import show print("sys.argv", sys.argv) if len(sys.argv) < 2: print("Usage: cloudwatch_dashboards.py event.json") sys.exit(1) event = json.loads(open(sys.argv[1]).read()) response = update_dashboards(event) show(response)
def update_dashboards(event): prefix = os.getenv( "PREFIX", "timba" ) # from the environment sections of terraform/lambda_function.tf environment = os.getenv( "ENVIRONMENT", "none" ) # from the environment sections of terraform/lambda_function.tf show(event) source = event['source'] if source not in SOURCE_MAPPINGS: return {'message', f'unknown source: "{source}"'} dashboard_type = DASHBOARD_TYPE_MAPPINGS[source] new_dashboards = SOURCE_MAPPINGS[source](prefix, environment) remaining_dashboards = get_existing_dashboards(prefix, environment) original_remaining_dashboard_count = len(remaining_dashboards) if DEBUG: print('original_remaining_dashboard_count', original_remaining_dashboard_count) print('remaining_dashboards') show(remaining_dashboards) for dashboard in new_dashboards: if DEBUG: print("dashboard", type(dashboard)) show(dashboard) for dashboard_name, details in dashboard.items(): names = details["names"] metric_names = details["metric_names"] dashboard_type = details["dashboard_type"] create_dashboard( prefix=prefix, environment=environment, dashboard_type=dashboard_type, metric_names=metric_names, basename=dashboard_name, names=names, ) # remove current dashboard from list of remaining dashboards, # so we can delete them at the end of the this loop remaining_dashboards = list( filter( lambda x: x != f'{prefix}-{environment}-{dashboard_name}-{dashboard_type}', remaining_dashboards)) deleted_dashboard_count = 0 for remaining_dashboard in remaining_dashboards: # only delete if it has the same suffix/dashboard_type # as the service we're handling. if remaining_dashboard.endswith(f'-{dashboard_type}'): delete_dashboard(remaining_dashboard) deleted_dashboard_count = deleted_dashboard_count + 1 return { 'new_dashboard_count': len(new_dashboards), 'original_dashboard_count': original_remaining_dashboard_count, 'remaining_dashboards': len(remaining_dashboards), 'deleted_dashboard_count': deleted_dashboard_count }
def get_dashboard_cloudfront(prefix, environment): ''' Reads the tags from the cloudfront distributions and returns a list of dictionaries. Each dict has a key containing the dashboard name, and their values have properties that contains a list of all the distributions that are tagged with that dashboard name. ''' list_distributions_response = CLIENT.list_distributions() if DEBUG: print('list_distributions_response') show(list_distributions_response) ret = [] cloudfronts_by_dashboard = {} if 'Items' not in list_distributions_response['DistributionList']: return ret # no cloudfront distributions found for dist in list_distributions_response['DistributionList']['Items']: cloudfront_dist = None matches_prefix_environment = False for origin in dist['Origins']['Items']: if f'{prefix}-{environment}' in origin['Id']: matches_prefix_environment = True cloudfront_dist = dist if matches_prefix_environment: if DEBUG: print("\n\n\ncloudfront_dist", cloudfront_dist) show(dist) tags = CLIENT.list_tags_for_resource(Resource=cloudfront_dist['ARN']) if DEBUG: print("tags") show(tags) dashboard_list = DEFAULT_DASHBOARD_NAME for item in tags['Tags']['Items']: if item['Key'] == TAG_NAME: dashboard_list = item['Value'] if DEBUG: print("dashboard_list", dashboard_list) for dashboard_name in dashboard_list.split('[ ,;]'): if DEBUG: print("dashboard_name", dashboard_name) if dashboard_name not in cloudfronts_by_dashboard: # make a new dashboard name if DEBUG: print(f"----cloudfront: making a new dashboard object for {dashboard_name}") cloudfronts_by_dashboard[dashboard_name] = { 'dashboard_type': 'cloudfront', 'metric_names' : list(map(lambda m: m['name'], CLOUDFRONT_METRICS)), 'names' : [] } dist_id = dist['Id'] if DEBUG: print('dist_id', dist_id) cloudfronts_by_dashboard[dashboard_name]['names'].append(dist_id) if DEBUG: print('cloudfronts_by_dashboard') show(cloudfronts_by_dashboard) for key, value in cloudfronts_by_dashboard.items(): ret.append({key: value}) return ret
def create_dashboard(*, prefix, environment, metric_names, dashboard_type, basename, names): ''' Creates a Cloudwatch Dashboard for one such element returned from `get_dashboard_lambdas()` and `get_dashboard_apigws()` ''' row_number = 0 dashboard_name = f"{prefix}-{environment.lower()}-{basename}-{dashboard_type}" print(f"create_dashboard({dashboard_name})... ", end='') widgets = [] # # put in a descriptor # descriptor = { "type": "text", "x": 0, "y": row_number, "width": len(DURATIONS) * 8, "height": 2, "properties": { "markdown": "\n# " + dashboard_name + "\n" } } widgets.append(descriptor) # # add a graph for each metric_name # col_number = 0 for duration in DURATIONS: row_number = 0 for metric_name in metric_names: metrics = _create_metrics(metric_name, dashboard_type, prefix, environment, names) widget = { 'type': 'metric', 'x': col_number, 'y': row_number, 'width': 8, 'height': 6, 'properties': { 'title': f'{metric_name}-{duration}m', # multiple lambdas on each graph 'metrics': metrics, 'period': duration * 60, 'stat': 'Maximum', 'region': os.getenv('AWS_DEFAULT_REGION', 'us-east-1') } } widgets.append(widget) row_number += 1 col_number += 8 dashboard_body = {'widgets': widgets} dashboard_body_j = json.dumps(dashboard_body) response = CLIENT.put_dashboard(DashboardName=dashboard_name, DashboardBody=dashboard_body_j) show(response) print('created!') if DEBUG: print(f'dashboard_body for {dashboard_name}') show(dashboard_body)
def get_dashboard_s3(prefix, environment): ''' Reads the tags from the s3 buckets and returns a list of dictionaries. Each dict has a key containing the dashboard name, and their values have properties that contains a list of all the buckets that are tagged with that dashboard name. ''' list_buckets_response = CLIENT.list_buckets() ret = [] buckets_by_dashboard = {} offset = len(f'{prefix}-{environment}') + 1 show(list_buckets_response) for bucket in list_buckets_response['Buckets']: bucket_name = bucket['Name'] if f'{prefix}-{environment}' in bucket_name: if DEBUG: print("\n\n\nbucket_name", bucket_name) dashboard_list = DEFAULT_DASHBOARD_NAME try: tags = CLIENT.get_bucket_tagging(Bucket=bucket_name) if DEBUG: print("tags") show(tags) for tag in tags['TagSet']: if DEBUG: print('tag', tag) if tag['Key'] == TAG_NAME: dashboard_list = tag['Value'] except Exception as exc: # If the get_bucket_tagging fails, assume the default pass if DEBUG: print("dashboard_list", dashboard_list) for dashboard_name in dashboard_list.split('[ ,;]'): if DEBUG: print("dashboard_name", dashboard_name) if dashboard_name not in buckets_by_dashboard: # make a new dashboard name if DEBUG: print( f"----s3: making a new dashboard object for {dashboard_name}" ) buckets_by_dashboard[dashboard_name] = { 'dashboard_type': 's3', 'metric_names': list(map(lambda m: m['name'], BUCKET_METRICS)), 'names': [] } buckets_by_dashboard[dashboard_name]['names'].append( bucket_name[offset:]) else: if DEBUG: print("skipping bucket_name", bucket_name) if DEBUG: print('buckets_by_dashboard') show(buckets_by_dashboard) print('offset', offset) for key, value in buckets_by_dashboard.items(): ret.append({key: value}) return ret