cdk/event-forwarder/index.ts (89 lines of code) (raw):

import { AutoScalingClient, DescribeAutoScalingGroupsCommand, } from '@aws-sdk/client-auto-scaling'; import { fromIni } from '@aws-sdk/credential-providers'; import type { AwsCredentialIdentityProvider } from '@smithy/types'; import { getConfig } from './config'; import type { AutoscalingEvent, CloudformationEvent, HydratedEvent, } from './types'; interface AwsClientConfig { region: string; credentials?: AwsCredentialIdentityProvider; } export async function main(event: CloudformationEvent | AutoscalingEvent) { const { stage } = getConfig(); try { const hydrated: HydratedEvent = { ...event, cloudformationStackName: await getCloudformationStackName(event, stage), }; console.log(JSON.stringify(hydrated)); } catch (err) { if (err instanceof Error) { console.error(err.message); } console.log(JSON.stringify(event)); } } async function getCloudformationStackName( event: CloudformationEvent | AutoscalingEvent, stage: string, ) { switch (event.source) { case 'aws.autoscaling': { return await getCloudformationStackNameForAsg( event as AutoscalingEvent, stage, ); } case 'aws.cloudformation': { return getCloudformationStackNameForStack(event as CloudformationEvent); } default: { throw new Error('Unrecognised event source'); } } } async function getCloudformationStackNameForAsg( event: AutoscalingEvent, stage: string, ): Promise<string> { const awsConfig: AwsClientConfig = { region: 'eu-west-1', ...(stage === 'DEV' && { credentials: fromIni({ profile: 'developerPlayground' }), }), }; const { AutoScalingGroupName } = event.detail; const client = new AutoScalingClient(awsConfig); const command = new DescribeAutoScalingGroupsCommand({ AutoScalingGroupNames: [AutoScalingGroupName], }); const { AutoScalingGroups = [] } = await client.send(command); if (AutoScalingGroups.length !== 1) { throw new Error('Unable to locate unique autoscaling group'); } const [cfnStackName] = AutoScalingGroups.flatMap((_) => _.Tags ?? []) .filter((_) => _.Key === 'aws:cloudformation:stack-name') .map((_) => _.Value); if (!cfnStackName) { throw new Error( 'Unable to locate unique tag: aws:cloudformation:stack-name', ); } return cfnStackName; } async function getCloudformationStackNameForStack( event: CloudformationEvent, ): Promise<string> { const stackId = event.detail['stack-id']; const [, stackName] = stackId.split('/'); if (!stackName) { throw new Error(`Unable to parse stack-id: ${stackId}`); } return Promise.resolve(stackName); }