From 73c34b9f2bbe3b7c063a257a5b032b7460f263c0 Mon Sep 17 00:00:00 2001 From: Brent Jackson Date: Thu, 1 Oct 2020 12:20:08 -0400 Subject: [PATCH] fix(AWS Lambda): Ensure version hash is in all cases effective (#8310) In some instances the version hash may change due to a change involving CloudFormation instrisic functions, but upon resolving the functions, the resulting lambda configuration is identical to what is currently deployed. This causes the Lambda::Version to fail to publish since AWS sees the lambdas as identical. This commit embeds an environment variable onto each lambda function with the value of the version config hash, ensuring that anytime the config hash changes, the resulting lambda configuration will be changed, allowing a Lambda::Version to be published. --- .../aws/package/compile/functions/index.js | 11 +- .../package/compile/functions/index.test.js | 384 +++++++++++++++--- .../cloudformation.tests.js | 27 ++ 3 files changed, 364 insertions(+), 58 deletions(-) diff --git a/lib/plugins/aws/package/compile/functions/index.js b/lib/plugins/aws/package/compile/functions/index.js index c39da6a05a2..9aa0e0863f7 100644 --- a/lib/plugins/aws/package/compile/functions/index.js +++ b/lib/plugins/aws/package/compile/functions/index.js @@ -425,7 +425,7 @@ class AwsCompileFunctions { delete layerConfig.properties.Content.S3Key; } - // sort the layer conifigurations for hash consistency + // sort the layer configurations for hash consistency const sortedLayerConfigurations = {}; const byKey = ([key1], [key2]) => key1.localeCompare(key2); for (const { name, properties: layerProperties } of layerConfigurations) { @@ -474,6 +474,15 @@ class AwsCompileFunctions { Object.assign(cfTemplate.Resources, newVersionObject); + // Add an environment var with a value of the versionDigest to force + // the AWS::Lambda::Function configuration to change whenever the + // versionDigest changes + _.set( + functionResource.Properties, + 'Environment.Variables.SLS_LAMBDA_VERSION_DIGEST', + versionDigest + ); + // Add function versions to Outputs section const functionVersionOutputLogicalId = this.provider.naming.getLambdaVersionOutputLogicalId( functionName diff --git a/lib/plugins/aws/package/compile/functions/index.test.js b/lib/plugins/aws/package/compile/functions/index.test.js index a1fa9a441fd..603ec678783 100644 --- a/lib/plugins/aws/package/compile/functions/index.test.js +++ b/lib/plugins/aws/package/compile/functions/index.test.js @@ -498,6 +498,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -508,10 +513,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -539,6 +545,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -553,10 +564,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -583,6 +595,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -597,10 +614,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -629,6 +647,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -643,10 +666,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -674,6 +698,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -688,10 +717,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -724,6 +754,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -739,10 +774,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -788,6 +824,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -815,6 +856,8 @@ describe('AwsCompileFunctions', () => { compiledCfTemplate.Resources.IamRoleLambdaExecution.Properties.Policies[0] .PolicyDocument.Statement[0]; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); expect(dlqStatement).to.deep.equal(compiledDlqStatement); }); @@ -839,6 +882,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -858,6 +906,8 @@ describe('AwsCompileFunctions', () => { awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate; const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -881,6 +931,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -900,6 +955,8 @@ describe('AwsCompileFunctions', () => { awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate; const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -923,6 +980,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -942,6 +1004,8 @@ describe('AwsCompileFunctions', () => { awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate; const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -965,6 +1029,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -983,6 +1052,8 @@ describe('AwsCompileFunctions', () => { const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1016,6 +1087,11 @@ describe('AwsCompileFunctions', () => { S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, S3Key: 'somedir/new-service.zip', }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1031,6 +1107,8 @@ describe('AwsCompileFunctions', () => { const compiledCfTemplate = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate; const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1053,6 +1131,11 @@ describe('AwsCompileFunctions', () => { S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, S3Key: 'somedir/new-service.zip', }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1068,6 +1151,8 @@ describe('AwsCompileFunctions', () => { const compiledCfTemplate = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate; const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1090,6 +1175,11 @@ describe('AwsCompileFunctions', () => { S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, S3Key: 'somedir/new-service.zip', }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1105,6 +1195,8 @@ describe('AwsCompileFunctions', () => { const compiledCfTemplate = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate; const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1130,6 +1222,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1144,6 +1241,8 @@ describe('AwsCompileFunctions', () => { const compiledCfTemplate = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate; const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1174,6 +1273,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func1', Handler: 'func1.function.handler', MemorySize: 1024, @@ -1192,6 +1296,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func2', Handler: 'func2.function.handler', MemorySize: 1024, @@ -1208,6 +1317,11 @@ describe('AwsCompileFunctions', () => { const function1Resource = compiledCfTemplate.Resources.Func1LambdaFunction; const function2Resource = compiledCfTemplate.Resources.Func2LambdaFunction; + + function1Resource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; + function2Resource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(function1Resource).to.deep.equal(compiledFunction1); expect(function2Resource).to.deep.equal(compiledFunction2); }); @@ -1246,6 +1360,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1271,6 +1390,8 @@ describe('AwsCompileFunctions', () => { compiledCfTemplate.Resources.IamRoleLambdaExecution.Properties.Policies[0] .PolicyDocument.Statement[0]; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); expect(dlqStatement).to.deep.equal(compiledKmsStatement); }); @@ -1295,6 +1416,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1311,6 +1437,8 @@ describe('AwsCompileFunctions', () => { const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1348,6 +1476,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1364,6 +1497,8 @@ describe('AwsCompileFunctions', () => { const compiledCfTemplate = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate; const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1395,6 +1530,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func1', Handler: 'func1.function.handler', MemorySize: 1024, @@ -1415,6 +1555,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func2', Handler: 'func2.function.handler', MemorySize: 1024, @@ -1433,6 +1578,11 @@ describe('AwsCompileFunctions', () => { const function1Resource = compiledCfTemplate.Resources.Func1LambdaFunction; const function2Resource = compiledCfTemplate.Resources.Func2LambdaFunction; + + function1Resource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; + function2Resource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(function1Resource).to.deep.equal(compiledFunction1); expect(function2Resource).to.deep.equal(compiledFunction2); }); @@ -1471,6 +1621,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1498,6 +1653,8 @@ describe('AwsCompileFunctions', () => { compiledCfTemplate.Resources.IamRoleLambdaExecution.Properties.Policies[0] .PolicyDocument.Statement[0]; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); expect(xrayStatement).to.deep.equal(compiledXrayStatement); }); @@ -1522,6 +1679,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1540,6 +1702,8 @@ describe('AwsCompileFunctions', () => { const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1585,16 +1749,18 @@ describe('AwsCompileFunctions', () => { test1: 'test1', test2: 'test2', providerTest1: 'providerTest1', + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', }, }, }, }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1630,16 +1796,18 @@ describe('AwsCompileFunctions', () => { Environment: { Variables: { test1: 'test1', + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', }, }, }, }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1676,16 +1844,18 @@ describe('AwsCompileFunctions', () => { Environment: { Variables: { providerTest1: 'providerTest1', + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', }, }, }, }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1725,16 +1895,18 @@ describe('AwsCompileFunctions', () => { Environment: { Variables: { variable: 'overwritten', + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', }, }, }, }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1802,6 +1974,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'customized-func-function', Handler: 'func.function.handler', MemorySize: 128, @@ -1812,10 +1989,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1844,6 +2022,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1853,10 +2036,12 @@ describe('AwsCompileFunctions', () => { }, }; - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = + 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); } ); @@ -1881,6 +2066,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -1891,10 +2081,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1919,6 +2110,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 128, @@ -1929,10 +2125,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -1960,6 +2157,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: bucketName, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 128, @@ -1974,10 +2176,11 @@ describe('AwsCompileFunctions', () => { awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate = coreCloudFormationTemplate; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -2119,6 +2322,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -2130,10 +2338,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -2175,6 +2384,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -2186,10 +2400,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -2305,6 +2520,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -2315,10 +2535,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -2343,6 +2564,11 @@ describe('AwsCompileFunctions', () => { S3Key: `${s3Folder}/${s3FileName}`, S3Bucket: { Ref: 'ServerlessDeploymentBucket' }, }, + Environment: { + Variables: { + SLS_LAMBDA_VERSION_DIGEST: 'some-digest', + }, + }, FunctionName: 'new-service-dev-func', Handler: 'func.function.handler', MemorySize: 1024, @@ -2354,10 +2580,11 @@ describe('AwsCompileFunctions', () => { }; return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => { - expect( + const functionResource = awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources - .FuncLambdaFunction - ).to.deep.equal(compiledFunction); + .FuncLambdaFunction; + functionResource.Properties.Environment.Variables.SLS_LAMBDA_VERSION_DIGEST = 'some-digest'; + expect(functionResource).to.deep.equal(compiledFunction); }); }); @@ -2842,5 +3069,48 @@ describe('AwsCompileFunctions #2', () => { expect(originalVersionArn).to.equal(updatedVersionArn); }); + + it('should add a version digest env var to lambda functions ', async () => { + const data = await runServerless({ + fixture: 'function', + cliArgs: ['package'], + configExt: { + functions: { + foo: { + environment: { + bar: 'baz', + }, + }, + }, + }, + }); + + expect( + data.cfTemplate.Resources.FooLambdaFunction.Properties.Environment.Variables + .SLS_LAMBDA_VERSION_DIGEST + ).to.exist; + }); + + it('should not add a version digest env var to non-versioned functions', async () => { + const data = await runServerless({ + fixture: 'function', + cliArgs: ['package'], + configExt: { + functions: { + foo: { + versionFunction: false, + environment: { + bar: 'baz', + }, + }, + }, + }, + }); + + expect( + data.cfTemplate.Resources.FooLambdaFunction.Properties.Environment.Variables + .SLS_LAMBDA_VERSION_DIGEST + ).to.not.exist; + }); }); }); diff --git a/test/integrationPackage/cloudformation.tests.js b/test/integrationPackage/cloudformation.tests.js index 7726636d577..ad7a84c8986 100644 --- a/test/integrationPackage/cloudformation.tests.js +++ b/test/integrationPackage/cloudformation.tests.js @@ -30,6 +30,12 @@ describe('Integration test - Packaging - CloudFormation', () => { /serverless\/aws-nodejs\/dev\/[^]*\/artifact.zip/ ); delete cfnTemplate.Resources.HelloLambdaFunction.Properties.Code.S3Key; + expect( + cfnTemplate.Resources.HelloLambdaFunction.Properties.Environment.Variables + .SLS_LAMBDA_VERSION_DIGEST + ).to.exist; + delete cfnTemplate.Resources.HelloLambdaFunction.Properties.Environment.Variables + .SLS_LAMBDA_VERSION_DIGEST; expect(cfnTemplate.Resources.HelloLambdaFunction).to.deep.equal({ Type: 'AWS::Lambda::Function', Properties: { @@ -38,6 +44,9 @@ describe('Integration test - Packaging - CloudFormation', () => { Ref: 'ServerlessDeploymentBucket', }, }, + Environment: { + Variables: {}, + }, FunctionName: 'aws-nodejs-dev-hello', Handler: 'handler.hello', MemorySize: 1024, @@ -61,6 +70,12 @@ describe('Integration test - Packaging - CloudFormation', () => { /serverless\/aws-nodejs\/dev\/[^]*\/aws-nodejs.zip/ ); delete cfnTemplate.Resources.HelloLambdaFunction.Properties.Code.S3Key; + expect( + cfnTemplate.Resources.HelloLambdaFunction.Properties.Environment.Variables + .SLS_LAMBDA_VERSION_DIGEST + ).to.exist; + delete cfnTemplate.Resources.HelloLambdaFunction.Properties.Environment.Variables + .SLS_LAMBDA_VERSION_DIGEST; expect(cfnTemplate.Resources.HelloLambdaFunction).to.deep.equal({ Type: 'AWS::Lambda::Function', Properties: { @@ -69,6 +84,9 @@ describe('Integration test - Packaging - CloudFormation', () => { Ref: 'ServerlessDeploymentBucket', }, }, + Environment: { + Variables: {}, + }, FunctionName: 'aws-nodejs-dev-hello', Handler: 'handler.hello', MemorySize: 1024, @@ -95,6 +113,12 @@ describe('Integration test - Packaging - CloudFormation', () => { /serverless\/aws-nodejs\/dev\/[^]*\/hello2.zip/ ); delete cfnTemplate.Resources.HelloLambdaFunction.Properties.Code.S3Key; + expect( + cfnTemplate.Resources.HelloLambdaFunction.Properties.Environment.Variables + .SLS_LAMBDA_VERSION_DIGEST + ).to.exist; + delete cfnTemplate.Resources.HelloLambdaFunction.Properties.Environment.Variables + .SLS_LAMBDA_VERSION_DIGEST; expect(cfnTemplate.Resources.HelloLambdaFunction).to.deep.equal({ Type: 'AWS::Lambda::Function', Properties: { @@ -103,6 +127,9 @@ describe('Integration test - Packaging - CloudFormation', () => { Ref: 'ServerlessDeploymentBucket', }, }, + Environment: { + Variables: {}, + }, FunctionName: 'aws-nodejs-dev-hello', Handler: 'handler.hello', MemorySize: 1024,