Allows Fn::GetAtt with Lambda DLQ-onError

Arn references for SQS queues are now available using:

```
Fn::GetAtt:
  - Queue
  - Arn
```
This commit is contained in:
Martin Jesper Low Madsen 2018-07-19 16:41:29 +02:00
parent e5bf2f0d6a
commit e2e231e28d
3 changed files with 58 additions and 9 deletions

View File

@ -374,7 +374,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

@ -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));
}
@ -407,9 +407,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', () => {