-
Notifications
You must be signed in to change notification settings - Fork 4k
/
Copy pathindex.ts
94 lines (89 loc) · 3 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*eslint-disable no-console*/
/* eslint-disable import/no-extraneous-dependencies */
import { SSM } from '@aws-sdk/client-ssm';
import { ExportReaderCRProps, CrossRegionExports } from '../types';
export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent) {
const props: ExportReaderCRProps = event.ResourceProperties.ReaderProps;
const imports: CrossRegionExports = props.imports as CrossRegionExports;
const importNames = Object.keys(imports);
const keyName: string = `aws-cdk:strong-ref:${props.prefix}`;
const ssm = new SSM({ region: props.region });
try {
switch (event.RequestType) {
case 'Create':
console.info('Tagging SSM Parameter imports');
await addTags(ssm, importNames, keyName);
break;
case 'Update':
const oldProps: ExportReaderCRProps = event.OldResourceProperties.ReaderProps;
const oldExports: CrossRegionExports = oldProps.imports as CrossRegionExports;
const newExports = except(importNames, Object.keys(oldExports));
const paramsToRelease = except(Object.keys(oldExports), importNames);
console.info('Releasing unused SSM Parameter imports');
if (Object.keys(paramsToRelease).length > 0) {
await removeTags(ssm, paramsToRelease, keyName);
}
console.info('Tagging new SSM Parameter imports');
await addTags(ssm, newExports, keyName);
break;
case 'Delete':
console.info('Releasing all SSM Parameter exports by removing tags');
await removeTags(ssm, importNames, keyName);
return;
}
} catch (e) {
console.error('Error importing cross region stack exports: ', e);
throw e;
}
return {
Data: imports,
};
};
/**
* Add tag to parameters for existing exports
*/
async function addTags(ssm: SSM, parameters: string[], keyName: string): Promise<void> {
await Promise.all(parameters.map(async name => {
try {
return await ssm.addTagsToResource({
ResourceId: name,
ResourceType: 'Parameter',
Tags: [{
Key: keyName,
Value: 'true',
}],
});
} catch (e) {
throw new Error(`Error importing ${name}: ${e}`);
}
}));
}
/**
* Remove tags from parameters
*/
async function removeTags(ssm: SSM, parameters: string[], keyName: string): Promise<void> {
await Promise.all(parameters.map(async name => {
try {
return await ssm.removeTagsFromResource({
TagKeys: [keyName],
ResourceType: 'Parameter',
ResourceId: name,
});
} catch (e: any) {
if (e.name === 'InvalidResourceId') {
return;
} else {
throw new Error(`Error releasing import ${name}: ${e}`);
}
}
}));
}
/**
* Return only the items from source that do not exist in the filter
*
* @param source the source object to perform the filter on
* @param filter filter out items that exist in this object
*/
function except(source: string[], filter: string[]): string[] {
return source.filter(key => !filter.includes(key));
}