-
Notifications
You must be signed in to change notification settings - Fork 102
Expand file tree
/
Copy pathindex.ts
More file actions
129 lines (110 loc) · 3.62 KB
/
index.ts
File metadata and controls
129 lines (110 loc) · 3.62 KB
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { mkdtempSync, writeFileSync } from 'fs';
import { resolve } from 'path';
import { GetFunctionCommand, LambdaClient, UpdateFunctionCodeCommand, waitUntilFunctionActiveV2 } from '@aws-sdk/client-lambda';
import Zip from 'adm-zip';
import type {
CloudFormationCustomResourceCreateEvent,
CloudFormationCustomResourceUpdateEvent,
CloudFormationCustomResourceEventCommon,
} from 'aws-lambda';
import axios from 'axios';
import {
camelizeKeys,
customResourceHelper,
OnCreateHandler,
OnUpdateHandler,
ResourceHandler,
ResourceHandlerReturn,
} from 'custom-resource-helper';
interface WithConfiguration {
region: string;
functionName: string;
configuration: string;
}
const updateLambdaCode = async (
event: CloudFormationCustomResourceCreateEvent | CloudFormationCustomResourceUpdateEvent,
): Promise<ResourceHandlerReturn> => {
console.log(`Recieved event: ${event}`);
const { region, functionName, configuration } = camelizeKeys<
WithConfiguration,
CloudFormationCustomResourceEventCommon['ResourceProperties']
>(event.ResourceProperties);
const lambda = new LambdaClient({
region,
});
const { Code: code } = await lambda.send(
new GetFunctionCommand({
FunctionName: functionName,
}),
);
if (!code?.Location) {
throw new Error(`The code of the lambda function ${functionName} could not be downloaded.`);
}
const { data } = await axios.get<Buffer>(code.Location, {
responseType: 'arraybuffer',
});
const lambdaZip = new Zip(data);
const tempDir = mkdtempSync('/tmp/lambda-package');
lambdaZip.extractAllTo(tempDir, true);
writeFileSync(resolve(tempDir, 'configuration.json'), Buffer.from(configuration));
const newLambdaZip = new Zip();
newLambdaZip.addLocalFolder(tempDir);
const {
CodeSha256: codeSha256,
Version: version,
FunctionArn: functionArn,
} = await lambda.send(
new UpdateFunctionCodeCommand({
FunctionName: functionName,
ZipFile: newLambdaZip.toBuffer(),
Publish: true,
}),
);
let responseDetails = {
responseStatus: 'FAILED',
reason: 'Internal Error',
physicalResourceId: functionName,
responseData: {},
};
// wait for functions to go active before proceeding because if an edge function isn't active updates to the
// related distribution fail
console.log(`Waiting for ${functionName} to go active...`);
waitUntilFunctionActiveV2(
{client: lambda, maxWaitTime: 60},
{FunctionName: functionName}
)
.then((result=>{
console.log(`Lambda function ${functionName} is active. Result: ${result}`);
responseDetails = {
physicalResourceId: functionName,
responseStatus: 'SUCCESS',
reason: `Lambda function ${functionName} is active.`,
responseData: {
CodeSha256: codeSha256,
Version: version,
FunctionArn: functionArn,
},
};
setTimeout(()=>{
console.log(`Waiting 5s for lambda status propagation...`);
}, 5000);
}))
.catch((err=>{
console.log(`Error waiting for ${functionName} to go active: ${err}`);
responseDetails = {
responseStatus: 'FAILED',
physicalResourceId: functionName,
reason: `Encountered error while waiting for ${functionName} to go active: ${err}`,
responseData: {}
};
}));
return responseDetails;
};
const handleCreate: OnCreateHandler = async (event): Promise<ResourceHandlerReturn> => updateLambdaCode(event);
const handleUpdate: OnUpdateHandler = async (event): Promise<ResourceHandlerReturn> => updateLambdaCode(event);
export const handler = customResourceHelper(
(): ResourceHandler => ({
onCreate: handleCreate,
onUpdate: handleUpdate,
}),
);