Skip to content

Commit

Permalink
Merge pull request #7045 from serverless/lambda-provisioned-concurrency
Browse files Browse the repository at this point in the history
Fix lambda provisioned concurrency setup
  • Loading branch information
medikoo committed Dec 4, 2019
2 parents 4c1cee3 + 1cf29ff commit 0bc5014
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 59 deletions.
73 changes: 38 additions & 35 deletions lib/plugins/aws/package/compile/functions/index.js
Expand Up @@ -409,21 +409,18 @@ class AwsCompileFunctions {
}
}

if (functionObject.provisionedConcurrency) {
const provisionedConcurrency = _.parseInt(functionObject.provisionedConcurrency);

if (_.isInteger(provisionedConcurrency)) {
newFunction.Properties.ProvisionedConcurrencyConfig = {
ProvisionedConcurrentExecutions: provisionedConcurrency,
};
} else {
return BbPromise.reject(
new this.serverless.classes.Error(
'You should use integer as provisionedConcurrency value on function: ' +
`${newFunction.Properties.FunctionName}`
)
);
}
const versionFunction =
functionObject.versionFunction != null
? functionObject.versionFunction
: this.serverless.service.provider.versionFunctions;

if (functionObject.provisionedConcurrency && !versionFunction) {
return BbPromise.reject(
new this.serverless.classes.Error(
'Cannot setup provisioned conncurrency with lambda versioning disabled on function: ' +
`${newFunction.Properties.FunctionName}`
)
);
}

newFunction.DependsOn = [this.provider.naming.getLogGroupLogicalId(functionName)].concat(
Expand All @@ -449,8 +446,6 @@ class AwsCompileFunctions {
newFunctionObject
);

const newVersion = this.cfLambdaVersionTemplate();

// Create hashes for the artifact and the logical id of the version resource
// The one for the version resource must include the function configuration
// to make sure that a new version is created on configuration changes and
Expand Down Expand Up @@ -490,12 +485,31 @@ class AwsCompileFunctions {
const fileDigest = fileHash.read();
const versionDigest = versionHash.read();

if (!versionFunction) return;

const newVersion = this.cfLambdaVersionTemplate();

newVersion.Properties.CodeSha256 = fileDigest;
newVersion.Properties.FunctionName = { Ref: functionLogicalId };
if (functionObject.description) {
newVersion.Properties.Description = functionObject.description;
}

if (functionObject.provisionedConcurrency) {
const provisionedConcurrency = _.parseInt(functionObject.provisionedConcurrency);

if (_.isInteger(provisionedConcurrency)) {
newVersion.Properties.ProvisionedConcurrencyConfig = {
ProvisionedConcurrentExecutions: provisionedConcurrency,
};
} else {
throw new this.serverless.classes.Error(
'You should use integer as provisionedConcurrency value on function: ' +
`${newFunction.Properties.FunctionName}`
);
}
}

// use the version SHA in the logical resource ID of the version because
// AWS::Lambda::Version resource will not support updates
const versionLogicalId = this.provider.naming.getLambdaVersionLogicalId(
Expand All @@ -506,17 +520,10 @@ class AwsCompileFunctions {
[versionLogicalId]: newVersion,
};

const versionFunction =
functionObject.versionFunction != null
? functionObject.versionFunction
: this.serverless.service.provider.versionFunctions;

if (versionFunction) {
_.merge(
this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
newVersionObject
);
}
_.merge(
this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
newVersionObject
);

// Add function versions to Outputs section
const functionVersionOutputLogicalId = this.provider.naming.getLambdaVersionOutputLogicalId(
Expand All @@ -526,13 +533,9 @@ class AwsCompileFunctions {

newVersionOutput.Value = { Ref: versionLogicalId };

if (versionFunction) {
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Outputs, {
[functionVersionOutputLogicalId]: newVersionOutput,
});
}

return BbPromise.resolve();
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Outputs, {
[functionVersionOutputLogicalId]: newVersionOutput,
});
});
}

Expand Down
31 changes: 7 additions & 24 deletions lib/plugins/aws/package/compile/functions/index.test.js
Expand Up @@ -2201,40 +2201,23 @@ describe('AwsCompileFunctions', () => {
});

it('should set function declared provisioned concurrency limit', () => {
const s3Folder = awsCompileFunctions.serverless.service.package.artifactDirectoryName;
const s3FileName = awsCompileFunctions.serverless.service.package.artifact
.split(path.sep)
.pop();
awsCompileFunctions.serverless.service.functions = {
func: {
handler: 'func.function.handler',
name: 'new-service-dev-func',
provisionedConcurrency: 5,
},
};
const compiledFunction = {
Type: 'AWS::Lambda::Function',
DependsOn: ['FuncLogGroup', 'IamRoleLambdaExecution'],
Properties: {
Code: {
S3Key: `${s3Folder}/${s3FileName}`,
S3Bucket: { Ref: 'ServerlessDeploymentBucket' },
},
FunctionName: 'new-service-dev-func',
Handler: 'func.function.handler',
MemorySize: 1024,
ProvisionedConcurrencyConfig: { ProvisionedConcurrentExecutions: 5 },
Role: { 'Fn::GetAtt': ['IamRoleLambdaExecution', 'Arn'] },
Runtime: 'nodejs12.x',
Timeout: 6,
},
};

return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled.then(() => {
const resourceId =
awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Outputs
.FuncLambdaFunctionQualifiedArn.Value.Ref;
expect(
awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources
.FuncLambdaFunction
).to.deep.equal(compiledFunction);
awsCompileFunctions.serverless.service.provider.compiledCloudFormationTemplate.Resources[
resourceId
].Properties.ProvisionedConcurrencyConfig
).to.deep.equal({ ProvisionedConcurrentExecutions: 5 });
});
});

Expand Down

0 comments on commit 0bc5014

Please sign in to comment.