1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.VERSION_LOCKED = exports.trimFromStart = exports.calculateFunctionHash = void 0;
|
4 | const crypto = require("crypto");
|
5 | const core_1 = require("@aws-cdk/core");
|
6 | const cx_api_1 = require("@aws-cdk/cx-api");
|
7 | const function_1 = require("./function");
|
8 | function calculateFunctionHash(fn) {
|
9 | const stack = core_1.Stack.of(fn);
|
10 | const functionResource = fn.node.defaultChild;
|
11 | // render the cloudformation resource from this function
|
12 | const config = stack.resolve(functionResource._toCloudFormation());
|
13 | // config is of the shape: { Resources: { LogicalId: { Type: 'Function', Properties: { ... } }}}
|
14 | const resources = config.Resources;
|
15 | const resourceKeys = Object.keys(resources);
|
16 | if (resourceKeys.length !== 1) {
|
17 | throw new Error(`Expected one rendered CloudFormation resource but found ${resourceKeys.length}`);
|
18 | }
|
19 | const logicalId = resourceKeys[0];
|
20 | const properties = resources[logicalId].Properties;
|
21 | let stringifiedConfig;
|
22 | if (core_1.FeatureFlags.of(fn).isEnabled(cx_api_1.LAMBDA_RECOGNIZE_VERSION_PROPS)) {
|
23 | const updatedProps = sortProperties(filterUsefulKeys(properties));
|
24 | stringifiedConfig = JSON.stringify(updatedProps);
|
25 | }
|
26 | else {
|
27 | const sorted = sortProperties(properties);
|
28 | config.Resources[logicalId].Properties = sorted;
|
29 | stringifiedConfig = JSON.stringify(config);
|
30 | }
|
31 | const hash = crypto.createHash('md5');
|
32 | hash.update(stringifiedConfig);
|
33 | return hash.digest('hex');
|
34 | }
|
35 | exports.calculateFunctionHash = calculateFunctionHash;
|
36 | function trimFromStart(s, maxLength) {
|
37 | const desiredLength = Math.min(maxLength, s.length);
|
38 | const newStart = s.length - desiredLength;
|
39 | return s.substring(newStart);
|
40 | }
|
41 | exports.trimFromStart = trimFromStart;
|
42 | /*
|
43 | * The list of properties found in CfnFunction (or AWS::Lambda::Function).
|
44 | * They are classified as "locked" to a Function Version or not.
|
45 | * When a property is locked, any change to that property will not take effect on previously created Versions.
|
46 | * Instead, a new Version must be generated for the change to take effect.
|
47 | * Similarly, if a property that's not locked to a Version is modified, a new Version
|
48 | * must not be generated.
|
49 | *
|
50 | * Adding a new property to this list - If the property is part of the UpdateFunctionConfiguration
|
51 | * API or UpdateFunctionCode API, then it must be classified as true, otherwise false.
|
52 | * See https://docs.aws.amazon.com/lambda/latest/dg/API_UpdateFunctionConfiguration.html and
|
53 | * https://docs.aws.amazon.com/lambda/latest/dg/API_UpdateFunctionConfiguration.html
|
54 | */
|
55 | exports.VERSION_LOCKED = {
|
56 | // locked to the version
|
57 | Architectures: true,
|
58 | Code: true,
|
59 | DeadLetterConfig: true,
|
60 | Description: true,
|
61 | Environment: true,
|
62 | EphemeralStorage: true,
|
63 | FileSystemConfigs: true,
|
64 | FunctionName: true,
|
65 | Handler: true,
|
66 | ImageConfig: true,
|
67 | KmsKeyArn: true,
|
68 | Layers: true,
|
69 | MemorySize: true,
|
70 | PackageType: true,
|
71 | Role: true,
|
72 | Runtime: true,
|
73 | Timeout: true,
|
74 | TracingConfig: true,
|
75 | VpcConfig: true,
|
76 | // not locked to the version
|
77 | CodeSigningConfigArn: false,
|
78 | ReservedConcurrentExecutions: false,
|
79 | Tags: false,
|
80 | };
|
81 | function filterUsefulKeys(properties) {
|
82 | const versionProps = { ...exports.VERSION_LOCKED, ...function_1.Function._VER_PROPS };
|
83 | const unclassified = Object.entries(properties)
|
84 | .filter(([k, v]) => v != null && !Object.keys(versionProps).includes(k))
|
85 | .map(([k, _]) => k);
|
86 | if (unclassified.length > 0) {
|
87 | throw new Error(`The following properties are not recognized as version properties: [${unclassified}].`
|
88 | + ' See the README of the aws-lambda module to learn more about this and to fix it.');
|
89 | }
|
90 | const notLocked = Object.entries(versionProps).filter(([_, v]) => !v).map(([k, _]) => k);
|
91 | notLocked.forEach(p => delete properties[p]);
|
92 | const ret = {};
|
93 | Object.entries(properties).filter(([k, _]) => versionProps[k]).forEach(([k, v]) => ret[k] = v);
|
94 | return ret;
|
95 | }
|
96 | function sortProperties(properties) {
|
97 | const ret = {};
|
98 | // We take all required properties in the order that they were historically,
|
99 | // to make sure the hash we calculate is stable.
|
100 | // There cannot be more required properties added in the future,
|
101 | // as that would be a backwards-incompatible change.
|
102 | const requiredProperties = ['Code', 'Handler', 'Role', 'Runtime'];
|
103 | for (const requiredProperty of requiredProperties) {
|
104 | ret[requiredProperty] = properties[requiredProperty];
|
105 | }
|
106 | // then, add all of the non-required properties,
|
107 | // in the original order
|
108 | for (const property of Object.keys(properties)) {
|
109 | if (requiredProperties.indexOf(property) === -1) {
|
110 | ret[property] = properties[property];
|
111 | }
|
112 | }
|
113 | return ret;
|
114 | }
|
115 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuY3Rpb24taGFzaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImZ1bmN0aW9uLWhhc2gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsaUNBQWlDO0FBQ2pDLHdDQUFpRTtBQUNqRSw0Q0FBaUU7QUFDakUseUNBQXdEO0FBRXhELFNBQWdCLHFCQUFxQixDQUFDLEVBQWtCO0lBQ3RELE1BQU0sS0FBSyxHQUFHLFlBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFM0IsTUFBTSxnQkFBZ0IsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQTJCLENBQUM7SUFFN0Qsd0RBQXdEO0lBQ3hELE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUUsZ0JBQXdCLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDO0lBQzVFLGdHQUFnRztJQUNoRyxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO0lBQ25DLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDNUMsSUFBSSxZQUFZLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLDJEQUEyRCxZQUFZLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztLQUNuRztJQUNELE1BQU0sU0FBUyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQyxNQUFNLFVBQVUsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsVUFBVSxDQUFDO0lBRW5ELElBQUksaUJBQWlCLENBQUM7SUFDdEIsSUFBSSxtQkFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsdUNBQThCLENBQUMsRUFBRTtRQUNqRSxNQUFNLFlBQVksR0FBRyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztRQUNsRSxpQkFBaUIsR0FBRyxJQUFJLENBQUMs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RCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IENmblJlc291cmNlLCBGZWF0dXJlRmxhZ3MsIFN0YWNrIH0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5pbXBvcnQgeyBMQU1CREFfUkVDT0dOSVpFX1ZFUlNJT05fUFJPUFMgfSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHsgRnVuY3Rpb24gYXMgTGFtYmRhRnVuY3Rpb24gfSBmcm9tICcuL2Z1bmN0aW9uJztcblxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUZ1bmN0aW9uSGFzaChmbjogTGFtYmRhRnVuY3Rpb24pIHtcbiAgY29uc3Qgc3RhY2sgPSBTdGFjay5vZihmbik7XG5cbiAgY29uc3QgZnVuY3Rpb25SZXNvdXJjZSA9IGZuLm5vZGUuZGVmYXVsdENoaWxkIGFzIENmblJlc291cmNlO1xuXG4gIC8vIHJlbmRlciB0aGUgY2xvdWRmb3JtYXRpb24gcmVzb3VyY2UgZnJvbSB0aGlzIGZ1bmN0aW9uXG4gIGNvbnN0IGNvbmZpZyA9IHN0YWNrLnJlc29sdmUoKGZ1bmN0aW9uUmVzb3VyY2UgYXMgYW55KS5fdG9DbG91ZEZvcm1hdGlvbigpKTtcbiAgLy8gY29uZmlnIGlzIG9mIHRoZSBzaGFwZTogeyBSZXNvdXJjZXM6IHsgTG9naWNhbElkOiB7IFR5cGU6ICdGdW5jdGlvbicsIFByb3BlcnRpZXM6IHsgLi4uIH0gfX19XG4gIGNvbnN0IHJlc291cmNlcyA9IGNvbmZpZy5SZXNvdXJjZXM7XG4gIGNvbnN0IHJlc291cmNlS2V5cyA9IE9iamVjdC5rZXlzKHJlc291cmNlcyk7XG4gIGlmIChyZXNvdXJjZUtleXMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBvbmUgcmVuZGVyZWQgQ2xvdWRGb3JtYXRpb24gcmVzb3VyY2UgYnV0IGZvdW5kICR7cmVzb3VyY2VLZXlzLmxlbmd0aH1gKTtcbiAgfVxuICBjb25zdCBsb2dpY2FsSWQgPSByZXNvdXJjZUtleXNbMF07XG4gIGNvbnN0IHByb3BlcnRpZXMgPSByZXNvdXJjZXNbbG9naWNhbElkXS5Qcm9wZXJ0aWVzO1xuXG4gIGxldCBzdHJpbmdpZmllZENvbmZpZztcbiAgaWYgKEZlYXR1cmVGbGFncy5vZihmbikuaXNFbmFibGVkKExBTUJEQV9SRUNPR05JWkVfVkVSU0lPTl9QUk9QUykpIHtcbiAgICBjb25zdCB1cGRhdGVkUHJvcHMgPSBzb3J0UHJvcGVydGllcyhmaWx0ZXJVc2VmdWxLZXlzKHByb3BlcnRpZXMpKTtcbiAgICBzdHJpbmdpZmllZENvbmZpZyA9IEpTT04uc3RyaW5naWZ5KHVwZGF0ZWRQcm9wcyk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3Qgc29ydGVkID0gc29ydFByb3BlcnRpZXMocHJvcGVydGllcyk7XG4gICAgY29uZmlnLlJlc291cmNlc1tsb2dpY2FsSWRdLlByb3BlcnRpZXMgPSBzb3J0ZWQ7XG4gICAgc3RyaW5naWZpZWRDb25maWcgPSBKU09OLnN0cmluZ2lmeShjb25maWcpO1xuICB9XG5cbiAgY29uc3QgaGFzaCA9IGNyeXB0by5jcmVhdGVIYXNoKCdtZDUnKTtcbiAgaGFzaC51cGRhdGUoc3RyaW5naWZpZWRDb25maWcpO1xuICByZXR1cm4gaGFzaC5kaWdlc3QoJ2hleCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJpbUZyb21TdGFydChzOiBzdHJpbmcsIG1heExlbmd0aDogbnVtYmVyKSB7XG4gIGNvbnN0IGRlc2lyZWRMZW5ndGggPSBNYXRoLm1pbihtYXhMZW5ndGgsIHMubGVuZ3RoKTtcbiAgY29uc3QgbmV3U3RhcnQgPSBzLmxlbmd0aCAtIGRlc2lyZWRMZW5ndGg7XG4gIHJldHVybiBzLnN1YnN0cmluZyhuZXdTdGFydCk7XG59XG5cbi8qXG4gKiBUaGUgbGlzdCBvZiBwcm9wZXJ0aWVzIGZvdW5kIGluIENmbkZ1bmN0aW9uIChvciBBV1M6OkxhbWJkYTo6RnVuY3Rpb24pLlxuICogVGhleSBhcmUgY2xhc3NpZmllZCBhcyBcImxvY2tlZFwiIHRvIGEgRnVuY3Rpb24gVmVyc2lvbiBvciBub3QuXG4gKiBXaGVuIGEgcHJvcGVydHkgaXMgbG9ja2VkLCBhbnkgY2hhbmdlIHRvIHRoYXQgcHJvcGVydHkgd2lsbCBub3QgdGFrZSBlZmZlY3Qgb24gcHJldmlvdXNseSBjcmVhdGVkIFZlcnNpb25zLlxuICogSW5zdGVhZCwgYSBuZXcgVmVyc2lvbiBtdXN0IGJlIGdlbmVyYXRlZCBmb3IgdGhlIGNoYW5nZSB0byB0YWtlIGVmZmVjdC5cbiAqIFNpbWlsYXJseSwgaWYgYSBwcm9wZXJ0eSB0aGF0J3Mgbm90IGxvY2tlZCB0byBhIFZlcnNpb24gaXMgbW9kaWZpZWQsIGEgbmV3IFZlcnNpb25cbiAqIG11c3Qgbm90IGJlIGdlbmVyYXRlZC5cbiAqXG4gKiBBZGRpbmcgYSBuZXcgcHJvcGVydHkgdG8gdGhpcyBsaXN0IC0gSWYgdGhlIHByb3BlcnR5IGlzIHBhcnQgb2YgdGhlIFVwZGF0ZUZ1bmN0aW9uQ29uZmlndXJhdGlvblxuICogQVBJIG9yIFVwZGF0ZUZ1bmN0aW9uQ29kZSBBUEksIHRoZW4gaXQgbXVzdCBiZSBjbGFzc2lmaWVkIGFzIHRydWUsIG90aGVyd2lzZSBmYWxzZS5cbiAqIFNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9BUElfVXBkYXRlRnVuY3Rpb25Db25maWd1cmF0aW9uLmh0bWwgYW5kXG4gKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9BUElfVXBkYXRlRnVuY3Rpb25Db25maWd1cmF0aW9uLmh0bWxcbiAqL1xuZXhwb3J0IGNvbnN0IFZFUlNJT05fTE9DS0VEOiB7IFtrZXk6IHN0cmluZ106IGJvb2xlYW4gfSA9IHtcbiAgLy8gbG9ja2VkIHRvIHRoZSB2ZXJzaW9uXG4gIEFyY2hpdGVjdHVyZXM6IHRydWUsXG4gIENvZGU6IHRydWUsXG4gIERlYWRMZXR0ZXJDb25maWc6IHRydWUsXG4gIERlc2NyaXB0aW9uOiB0cnVlLFxuICBFbnZpcm9ubWVudDogdHJ1ZSxcbiAgRXBoZW1lcmFsU3RvcmFnZTogdHJ1ZSxcbiAgRmlsZVN5c3RlbUNvbmZpZ3M6IHRydWUsXG4gIEZ1bmN0aW9uTmFtZTogdHJ1ZSxcbiAgSGFuZGxlcjogdHJ1ZSxcbiAgSW1hZ2VDb25maWc6IHRydWUsXG4gIEttc0tleUFybjogdHJ1ZSxcbiAgTGF5ZXJzOiB0cnVlLFxuICBNZW1vcnlTaXplOiB0cnVlLFxuICBQYWNrYWdlVHlwZTogdHJ1ZSxcbiAgUm9sZTogdHJ1ZSxcbiAgUnVudGltZTogdHJ1ZSxcbiAgVGltZW91dDogdHJ1ZSxcbiAgVHJhY2luZ0NvbmZpZzogdHJ1ZSxcbiAgVnBjQ29uZmlnOiB0cnVlLFxuXG4gIC8vIG5vdCBsb2NrZWQgdG8gdGhlIHZlcnNpb25cbiAgQ29kZVNpZ25pbmdDb25maWdBcm46IGZhbHNlLFxuICBSZXNlcnZlZENvbmN1cnJlbnRFeGVjdXRpb25zOiBmYWxzZSxcbiAgVGFnczogZmFsc2UsXG59O1xuXG5mdW5jdGlvbiBmaWx0ZXJVc2VmdWxLZXlzKHByb3BlcnRpZXM6IGFueSkge1xuICBjb25zdCB2ZXJzaW9uUHJvcHMgPSB7IC4uLlZFUlNJT05fTE9DS0VELCAuLi5MYW1iZGFGdW5jdGlvbi5fVkVSX1BST1BTIH07XG4gIGNvbnN0IHVuY2xhc3NpZmllZCA9IE9iamVjdC5lbnRyaWVzKHByb3BlcnRpZXMpXG4gICAgLmZpbHRlcigoW2ssIHZdKSA9PiB2ICE9IG51bGwgJiYgIU9iamVjdC5rZXlzKHZlcnNpb25Qcm9wcykuaW5jbHVkZXMoaykpXG4gICAgLm1hcCgoW2ssIF9dKSA9PiBrKTtcbiAgaWYgKHVuY2xhc3NpZmllZC5sZW5ndGggPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgZm9sbG93aW5nIHByb3BlcnRpZXMgYXJlIG5vdCByZWNvZ25pemVkIGFzIHZlcnNpb24gcHJvcGVydGllczogWyR7dW5jbGFzc2lmaWVkfV0uYFxuICAgICAgKyAnIFNlZSB0aGUgUkVBRE1FIG9mIHRoZSBhd3MtbGFtYmRhIG1vZHVsZSB0byBsZWFybiBtb3JlIGFib3V0IHRoaXMgYW5kIHRvIGZpeCBpdC4nKTtcbiAgfVxuICBjb25zdCBub3RMb2NrZWQgPSBPYmplY3QuZW50cmllcyh2ZXJzaW9uUHJvcHMpLmZpbHRlcigoW18sIHZdKSA9PiAhdikubWFwKChbaywgX10pID0+IGspO1xuICBub3RMb2NrZWQuZm9yRWFjaChwID0+IGRlbGV0ZSBwcm9wZXJ0aWVzW3BdKTtcblxuICBjb25zdCByZXQ6IHsgW2tleTogc3RyaW5nXTogYW55IH0gPSB7fTtcbiAgT2JqZWN0LmVudHJpZXMocHJvcGVydGllcykuZmlsdGVyKChbaywgX10pID0+IHZlcnNpb25Qcm9wc1trXSkuZm9yRWFjaCgoW2ssIHZdKSA9PiByZXRba10gPSB2KTtcbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gc29ydFByb3BlcnRpZXMocHJvcGVydGllczogYW55KSB7XG4gIGNvbnN0IHJldDogYW55ID0ge307XG4gIC8vIFdlIHRha2UgYWxsIHJlcXVpcmVkIHByb3BlcnRpZXMgaW4gdGhlIG9yZGVyIHRoYXQgdGhleSB3ZXJlIGhpc3RvcmljYWxseSxcbiAgLy8gdG8gbWFrZSBzdXJlIHRoZSBoYXNoIHdlIGNhbGN1bGF0ZSBpcyBzdGFibGUuXG4gIC8vIFRoZXJlIGNhbm5vdCBiZSBtb3JlIHJlcXVpcmVkIHByb3BlcnRpZXMgYWRkZWQgaW4gdGhlIGZ1dHVyZSxcbiAgLy8gYXMgdGhhdCB3b3VsZCBiZSBhIGJhY2t3YXJkcy1pbmNvbXBhdGlibGUgY2hhbmdlLlxuICBjb25zdCByZXF1aXJlZFByb3BlcnRpZXMgPSBbJ0NvZGUnLCAnSGFuZGxlcicsICdSb2xlJywgJ1J1bnRpbWUnXTtcbiAgZm9yIChjb25zdCByZXF1aXJlZFByb3BlcnR5IG9mIHJlcXVpcmVkUHJvcGVydGllcykge1xuICAgIHJldFtyZXF1aXJlZFByb3BlcnR5XSA9IHByb3BlcnRpZXNbcmVxdWlyZWRQcm9wZXJ0eV07XG4gIH1cbiAgLy8gdGhlbiwgYWRkIGFsbCBvZiB0aGUgbm9uLXJlcXVpcmVkIHByb3BlcnRpZXMsXG4gIC8vIGluIHRoZSBvcmlnaW5hbCBvcmRlclxuICBmb3IgKGNvbnN0IHByb3BlcnR5IG9mIE9iamVjdC5rZXlzKHByb3BlcnRpZXMpKSB7XG4gICAgaWYgKHJlcXVpcmVkUHJvcGVydGllcy5pbmRleE9mKHByb3BlcnR5KSA9PT0gLTEpIHtcbiAgICAgIHJldFtwcm9wZXJ0eV0gPSBwcm9wZXJ0aWVzW3Byb3BlcnR5XTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cbiJdfQ== |
\ | No newline at end of file |