-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: allow bundling lambdas with cdk-assets
- Loading branch information
Showing
6 changed files
with
310 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
packages/cdk-assets/lib/private/handlers/bundlable-files.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import * as path from 'path'; | ||
import { ContainerBunder } from '../docker'; | ||
import { FileAssetHandler } from './files'; | ||
|
||
export class BundlableFileAssetHandler extends FileAssetHandler { | ||
|
||
public async build(): Promise<void> { | ||
if (!this.asset.source.bundling) { | ||
throw new Error('Tried to do bundling without BundlingOptions'); | ||
} | ||
|
||
if (!this.asset.source.path) { | ||
throw new Error('Source path is mandatory when bundling inside container'); | ||
} | ||
|
||
const bundler = new ContainerBunder( | ||
this.asset.source.bundling, | ||
path.resolve(this.workDir, this.asset.source.path), | ||
); | ||
|
||
const bundledPath = await bundler.bundle(); | ||
|
||
// Hack to get things tested | ||
(this.asset.source.path as any) = bundledPath; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
jest.mock('child_process'); | ||
|
||
import * as child_process from 'child_process'; | ||
import { Manifest } from '@aws-cdk/cloud-assembly-schema'; | ||
import * as mockfs from 'mock-fs'; | ||
import { AssetPublishing, AssetManifest } from '../lib'; | ||
import { mockAws, mockedApiResult, mockUpload } from './mock-aws'; | ||
|
||
const DEFAULT_DESTINATION = { | ||
region: 'us-north-50', | ||
assumeRoleArn: 'arn:aws:role', | ||
bucketName: 'some_bucket', | ||
objectKey: 'some_key', | ||
}; | ||
|
||
let aws: ReturnType<typeof mockAws>; | ||
beforeEach(() => { | ||
jest.resetAllMocks(); | ||
|
||
mockfs({ | ||
'/bundlable/cdk.out/assets.json': JSON.stringify({ | ||
version: Manifest.version(), | ||
files: { | ||
theAsset: { | ||
source: { | ||
path: 'some_file', | ||
packaging: 'zip', | ||
bundling: { | ||
image: 'node:14', | ||
}, | ||
}, | ||
destinations: { theDestination: DEFAULT_DESTINATION }, | ||
}, | ||
}, | ||
}), | ||
}); | ||
|
||
aws = mockAws(); | ||
}); | ||
|
||
afterEach(() => { | ||
mockfs.restore(); | ||
}); | ||
|
||
function getSpawnSyncReturn(status: number, output=['mock output']): child_process.SpawnSyncReturns<string | Buffer> { | ||
return { | ||
status, | ||
stderr: Buffer.from('stderr'), | ||
stdout: Buffer.from('stdout'), | ||
pid: 123, | ||
output, | ||
signal: null, | ||
}; | ||
} | ||
|
||
describe('bundlable assets', () => { | ||
test('bundle correctly within container', async () => { | ||
const pub = new AssetPublishing(AssetManifest.fromPath('/bundlable/cdk.out'), { aws }); | ||
aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: undefined }); | ||
aws.mockS3.upload = mockUpload(); | ||
jest.spyOn(child_process, 'spawnSync').mockImplementation((command: string, args?: readonly string[], _options?: child_process.SpawnSyncOptions) => { | ||
if (command === 'selinuxenabled') { | ||
return getSpawnSyncReturn(0, ['selinuxenabled output', 'stderr']); | ||
} else if (command === 'docker' && args) { | ||
if (args[0] === 'run') { | ||
// Creation of asset by running the image | ||
return getSpawnSyncReturn(0, ['Bundling started', 'Bundling done']); | ||
} | ||
} | ||
return getSpawnSyncReturn(127, ['FAIL']); | ||
}); | ||
|
||
await pub.publish(); | ||
|
||
expect(aws.mockS3.upload).toHaveBeenCalledWith(expect.objectContaining({ | ||
Bucket: 'some_bucket', | ||
Key: 'some_key', | ||
})); | ||
}); | ||
|
||
test('fails if container run returns an error', async () => { | ||
const pub = new AssetPublishing(AssetManifest.fromPath('/bundlable/cdk.out'), { aws }); | ||
jest.spyOn(child_process, 'spawnSync').mockImplementation((command: string, args?: readonly string[], _options?: child_process.SpawnSyncOptions) => { | ||
if (command === 'selinuxenabled') { | ||
return getSpawnSyncReturn(0, ['selinuxenabled output', 'stderr']); | ||
} else if (command === 'docker' && args) { | ||
if (args[0] === 'run') { | ||
// Creation of asset by running the image | ||
return getSpawnSyncReturn(127, ['Bundling started', 'Bundling failed in container']); | ||
} | ||
} | ||
return getSpawnSyncReturn(127, ['FAIL']); | ||
}); | ||
|
||
await expect(pub.publish()).rejects.toThrow('Error building and publishing: [Status 127] stdout: stdout'); | ||
}); | ||
}); |