Merge pull request #5139 from BlackbirdHQ/master

Allows Fn::GetAtt with Lambda DLQ-onError
This commit is contained in:
Philipp Muens 2019-01-28 13:46:31 +01:00 committed by GitHub
commit 4ae0ff18bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 10 deletions

View File

@ -392,7 +392,7 @@ provider:
functions:
hello:
handler: handler.hello
onError: arn:aws:sns:us-east-1:XXXXXX:test # Ref and Fn::ImportValue are supported as well
onError: arn:aws:sns:us-east-1:XXXXXX:test # Ref, Fn::GetAtt and Fn::ImportValue are supported as well
```
### DLQ with SQS

View File

@ -137,7 +137,7 @@ functions:
runtime: nodejs6.10 # Runtime for this specific function. Overrides the default which is set on the provider level
timeout: 10 # Timeout for this specific function. Overrides the default set above.
role: arn:aws:iam::XXXXXX:role/role # IAM role which will be used for this function
onError: arn:aws:sns:us-east-1:XXXXXX:sns-topic # Optional SNS topic arn (Ref and Fn::ImportValue are supported as well) which will be used for the DeadLetterConfig
onError: arn:aws:sns:us-east-1:XXXXXX:sns-topic # Optional SNS topic / SQS arn (Ref, Fn::GetAtt and Fn::ImportValue are supported as well) which will be used for the DeadLetterConfig
awsKmsKeyArn: arn:aws:kms:us-east-1:XXXXXX:key/some-hash # Optional KMS key arn which will be used for encryption (overwrites the one defined on the service level)
environment: # Function level environment variables
functionEnvVar: 12345678

View File

@ -184,14 +184,14 @@ class AwsCompileFunctions {
const errorMessage = 'onError config must be a SNS topic arn or SQS queue arn';
return BbPromise.reject(new this.serverless.classes.Error(errorMessage));
}
} else if (this.isArnRefOrImportValue(arn)) {
} else if (this.isArnRefGetAttOrImportValue(arn)) {
newFunction.Properties.DeadLetterConfig = {
TargetArn: arn,
};
} else {
const errorMessage = [
'onError config must be provided as an arn string,',
' Ref or Fn::ImportValue',
' Ref, Fn::GetAtt or Fn::ImportValue',
].join('');
return BbPromise.reject(new this.serverless.classes.Error(errorMessage));
}
@ -420,9 +420,9 @@ class AwsCompileFunctions {
}
// helper functions
isArnRefOrImportValue(arn) {
isArnRefGetAttOrImportValue(arn) {
return typeof arn === 'object' &&
_.some(_.keys(arn), (k) => _.includes(['Ref', 'Fn::ImportValue'], k));
_.some(_.keys(arn), (k) => _.includes(['Ref', 'Fn::GetAtt', 'Fn::ImportValue'], k));
}
cfLambdaFunctionTemplate() {

View File

@ -61,14 +61,17 @@ describe('AwsCompileFunctions', () => {
expect(awsCompileFunctions.provider).to.be.instanceof(AwsProvider));
});
describe('#isArnRefOrImportValue()', () => {
describe('#isArnRefGetAttOrImportValue()', () => {
it('should accept a Ref', () =>
expect(awsCompileFunctions.isArnRefOrImportValue({ Ref: 'DLQ' })).to.equal(true));
expect(awsCompileFunctions.isArnRefGetAttOrImportValue({ Ref: 'DLQ' })).to.equal(true));
it('should accept a Fn::GetAtt', () =>
expect(awsCompileFunctions.isArnRefGetAttOrImportValue({ 'Fn::GetAtt': ['DLQ', 'Arn'] }))
.to.equal(true));
it('should accept a Fn::ImportValue', () =>
expect(awsCompileFunctions.isArnRefOrImportValue({ 'Fn::ImportValue': 'DLQ' }))
expect(awsCompileFunctions.isArnRefGetAttOrImportValue({ 'Fn::ImportValue': 'DLQ' }))
.to.equal(true));
it('should reject other objects', () =>
expect(awsCompileFunctions.isArnRefOrImportValue({ Blah: 'vtha' })).to.equal(false));
expect(awsCompileFunctions.isArnRefGetAttOrImportValue({ Blah: 'vtha' })).to.equal(false));
});
describe('#compileFunctions()', () => {
@ -896,6 +899,52 @@ describe('AwsCompileFunctions', () => {
expect(functionResource).to.deep.equal(compiledFunction);
});
});
it('should create necessary resources if a Fn::GetAtt is provided', () => {
awsCompileFunctions.serverless.service.functions = {
func: {
handler: 'func.function.handler',
name: 'new-service-dev-func',
onError: {
'Fn::GetAtt': ['DLQ', 'Arn'],
},
},
};
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,
Role: { 'Fn::GetAtt': ['IamRoleLambdaExecution', 'Arn'] },
Runtime: 'nodejs4.3',
Timeout: 6,
DeadLetterConfig: {
TargetArn: {
'Fn::GetAtt': ['DLQ', 'Arn'],
},
},
},
};
return expect(awsCompileFunctions.compileFunctions()).to.be.fulfilled
.then(() => {
const compiledCfTemplate = awsCompileFunctions.serverless.service.provider
.compiledCloudFormationTemplate;
const functionResource = compiledCfTemplate.Resources.FuncLambdaFunction;
expect(functionResource).to.deep.equal(compiledFunction);
});
});
});
describe('when IamRoleLambdaExecution is not used', () => {