mirror of
https://github.com/serverless/serverless.git
synced 2026-01-25 15:07:39 +00:00
241 lines
7.9 KiB
JavaScript
241 lines
7.9 KiB
JavaScript
'use strict'
|
|
|
|
const path = require('path')
|
|
const chai = require('chai')
|
|
const runServerless = require('../../../../../../utils/run-serverless')
|
|
|
|
chai.use(require('chai-as-promised'))
|
|
|
|
const expect = chai.expect
|
|
|
|
const awsRequestStubMap = {
|
|
CloudFormation: {
|
|
describeStacks: {
|
|
Stacks: [
|
|
{
|
|
Outputs: [
|
|
{ OutputKey: 'LayerLambdaLayerHash', OutputValue: '1qaz' },
|
|
{
|
|
OutputKey: 'LayerLambdaLayerS3Key',
|
|
OutputValue: 'a/b/c/foo.zip',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
},
|
|
}
|
|
|
|
describe('lib/plugins/aws/package/compile/layers/index.test.js', () => {
|
|
const allowedAccount = 'arn:aws:iam::123456789012:root'
|
|
let cfResources
|
|
let naming
|
|
let updateConfig
|
|
let serviceDir
|
|
let service
|
|
let cfOutputs
|
|
|
|
before(async () => {
|
|
const { awsNaming, cfTemplate, fixtureData, serverless } =
|
|
await runServerless({
|
|
fixture: 'layer',
|
|
command: 'package',
|
|
configExt: {
|
|
package: {
|
|
individually: true,
|
|
},
|
|
layers: {
|
|
layerOne: {
|
|
path: 'layer',
|
|
allowedAccounts: ['*'],
|
|
},
|
|
layerTwo: {
|
|
description: 'Layer two example',
|
|
path: 'layer',
|
|
compatibleRuntimes: ['nodejs16.x'],
|
|
compatibleArchitectures: ['arm64'],
|
|
licenseInfo: 'GPL',
|
|
allowedAccounts: ['123456789012', '123456789013'],
|
|
},
|
|
layerRetain: {
|
|
path: 'layer',
|
|
retain: true,
|
|
allowedAccounts: [allowedAccount],
|
|
},
|
|
},
|
|
},
|
|
awsRequestStubMap,
|
|
})
|
|
cfResources = cfTemplate.Resources
|
|
cfOutputs = cfTemplate.Outputs
|
|
naming = awsNaming
|
|
service = serverless.service
|
|
;({ updateConfig, servicePath: serviceDir } = fixtureData)
|
|
})
|
|
|
|
it('should support `layers[].package.artifact` with `package.individually`', () => {
|
|
const resourceName = 'layer'
|
|
const layerResource =
|
|
cfResources[naming.getLambdaLayerLogicalId(resourceName)]
|
|
const s3Folder = service.package.artifactDirectoryName
|
|
const s3FileName = service.layers[resourceName].package.artifact
|
|
.split(path.sep)
|
|
.pop()
|
|
|
|
expect(layerResource.Properties.Content.S3Key).to.equal(
|
|
`${s3Folder}/${s3FileName}`,
|
|
)
|
|
})
|
|
|
|
it('should generate expected layer version resource', () => {
|
|
const resourceName = 'layer'
|
|
const layerResource =
|
|
cfResources[naming.getLambdaLayerLogicalId(resourceName)]
|
|
const s3Folder = service.package.artifactDirectoryName
|
|
const s3FileName = service.layers[resourceName].package.artifact
|
|
.split(path.sep)
|
|
.pop()
|
|
|
|
expect(layerResource.Type).to.equals('AWS::Lambda::LayerVersion')
|
|
expect(layerResource.Properties.Content.S3Key).to.equal(
|
|
`${s3Folder}/${s3FileName}`,
|
|
)
|
|
expect(layerResource.Properties.LayerName).to.equal('layer')
|
|
expect(layerResource.Properties.Content.S3Bucket.Ref).to.equal(
|
|
'ServerlessDeploymentBucket',
|
|
)
|
|
|
|
expect(cfOutputs.LayerLambdaLayerQualifiedArn.Description).to.equals(
|
|
'Current Lambda layer version',
|
|
)
|
|
expect(cfOutputs.LayerLambdaLayerQualifiedArn.Value.Ref).to.equals(
|
|
'LayerLambdaLayer',
|
|
)
|
|
})
|
|
|
|
describe('`layers[].retain` property', () => {
|
|
it('should ensure expected deletion policy for layer resource', () => {
|
|
const layerResourceNamePrefix =
|
|
naming.getLambdaLayerLogicalId('layerRetain')
|
|
const layerResourceName = Object.keys(cfResources).find((resourceName) =>
|
|
resourceName.startsWith(layerResourceNamePrefix),
|
|
)
|
|
expect(layerResourceName).to.not.equal(layerResourceNamePrefix)
|
|
const layerResource = cfResources[layerResourceName]
|
|
expect(layerResource.DeletionPolicy).to.equal('Retain')
|
|
})
|
|
|
|
it('should ensure expected deletion policy for layer permission resource', () => {
|
|
const layerPermissionResourceNamePrefix =
|
|
naming.getLambdaLayerPermissionLogicalId('layerRetain', allowedAccount)
|
|
const layerPermissionResourceName = Object.keys(cfResources).find(
|
|
(resourceName) =>
|
|
resourceName.startsWith(layerPermissionResourceNamePrefix),
|
|
)
|
|
expect(layerPermissionResourceName).to.not.equal(
|
|
layerPermissionResourceNamePrefix,
|
|
)
|
|
const layerPermissionResource = cfResources[layerPermissionResourceName]
|
|
expect(layerPermissionResource.DeletionPolicy).to.equal('Retain')
|
|
})
|
|
|
|
it('should ensure unique resource id per layer version', async () => {
|
|
const layerResourceNamePrefix =
|
|
naming.getLambdaLayerLogicalId('layerRetain')
|
|
const firstLayerResourceName = Object.keys(cfResources).find(
|
|
(resourceName) => resourceName.startsWith(layerResourceNamePrefix),
|
|
)
|
|
|
|
await updateConfig({ layers: { layerRetain: { description: 'foo' } } })
|
|
const {
|
|
cfTemplate: { Resources: secondCfResources },
|
|
} = await runServerless({
|
|
cwd: serviceDir,
|
|
command: 'package',
|
|
awsRequestStubMap,
|
|
})
|
|
expect(secondCfResources).to.not.have.property(firstLayerResourceName)
|
|
|
|
await updateConfig({ layers: { layerRetain: { description: null } } })
|
|
const {
|
|
cfTemplate: { Resources: firstCfResources },
|
|
} = await runServerless({
|
|
cwd: serviceDir,
|
|
command: 'package',
|
|
awsRequestStubMap,
|
|
})
|
|
expect(firstCfResources).to.have.property(firstLayerResourceName)
|
|
})
|
|
})
|
|
|
|
it('should generate expected permissions resource', () => {
|
|
const layerNamePermission = naming.getLambdaLayerPermissionLogicalId(
|
|
'LayerOne',
|
|
'Wild',
|
|
)
|
|
const layerPermission = cfResources[layerNamePermission]
|
|
|
|
expect(layerPermission.Type).to.equals(
|
|
'AWS::Lambda::LayerVersionPermission',
|
|
)
|
|
expect(layerPermission.Properties.Action).to.equals(
|
|
'lambda:GetLayerVersion',
|
|
)
|
|
expect(layerPermission.Properties.LayerVersionArn.Ref).to.equals(
|
|
'LayerOneLambdaLayer',
|
|
)
|
|
expect(layerPermission.Properties.Principal).to.equals('*')
|
|
})
|
|
|
|
it('should support `layers[].allowedAccounts`', () => {
|
|
const layerNamePermissionFirstUser =
|
|
naming.getLambdaLayerPermissionLogicalId('layerTwo', '123456789012')
|
|
const layerPermissionFirstUser = cfResources[layerNamePermissionFirstUser]
|
|
expect(layerPermissionFirstUser.Properties.Principal).to.equals(
|
|
'123456789012',
|
|
)
|
|
|
|
const layerNamePermissionUserSecond =
|
|
naming.getLambdaLayerPermissionLogicalId('layerTwo', '123456789013')
|
|
const layerPermissionSecondUser = cfResources[layerNamePermissionUserSecond]
|
|
expect(layerPermissionSecondUser.Properties.Principal).to.equals(
|
|
'123456789013',
|
|
)
|
|
})
|
|
|
|
it('should support `layers[].description`', () => {
|
|
const layerResourceName = naming.getLambdaLayerLogicalId('LayerTwo')
|
|
const layerOne = cfResources[layerResourceName]
|
|
|
|
expect(layerOne.Type).to.equals('AWS::Lambda::LayerVersion')
|
|
expect(layerOne.Properties.Description).to.equals('Layer two example')
|
|
})
|
|
|
|
it('should support `layers[].compatibleRuntimes`', () => {
|
|
const layerResourceName = naming.getLambdaLayerLogicalId('LayerTwo')
|
|
const layerOne = cfResources[layerResourceName]
|
|
|
|
expect(layerOne.Type).to.equals('AWS::Lambda::LayerVersion')
|
|
expect(layerOne.Properties.CompatibleRuntimes).to.deep.equals([
|
|
'nodejs16.x',
|
|
])
|
|
})
|
|
|
|
it('should support `layers[].compatibleArchitectures`', () => {
|
|
const layerResourceName = naming.getLambdaLayerLogicalId('LayerTwo')
|
|
const layerOne = cfResources[layerResourceName]
|
|
|
|
expect(layerOne.Properties.CompatibleArchitectures).to.deep.equals([
|
|
'arm64',
|
|
])
|
|
})
|
|
|
|
it('should support `layers[].licenseInfo`', () => {
|
|
const layerResourceName = naming.getLambdaLayerLogicalId('LayerTwo')
|
|
const layerOne = cfResources[layerResourceName]
|
|
|
|
expect(layerOne.Type).to.equals('AWS::Lambda::LayerVersion')
|
|
expect(layerOne.Properties.LicenseInfo).to.deep.equals('GPL')
|
|
})
|
|
})
|