From c2a3058488722a1b9732c85ad7f1d1c2e64a612d Mon Sep 17 00:00:00 2001 From: ahzia Date: Wed, 10 Aug 2022 21:12:31 +0500 Subject: [PATCH] write multi asset function --- packages/@aws-cdk/aws-lambda/lib/code.ts | 13 +++++ .../aws-lambda/lib/private/archive.ts | 48 +++++++++++++++++++ packages/@aws-cdk/aws-lambda/package.json | 1 + 3 files changed, 62 insertions(+) create mode 100644 packages/@aws-cdk/aws-lambda/lib/private/archive.ts diff --git a/packages/@aws-cdk/aws-lambda/lib/code.ts b/packages/@aws-cdk/aws-lambda/lib/code.ts index e8348d9da3c36..ebe33c9c807c7 100644 --- a/packages/@aws-cdk/aws-lambda/lib/code.ts +++ b/packages/@aws-cdk/aws-lambda/lib/code.ts @@ -4,6 +4,7 @@ import * as iam from '@aws-cdk/aws-iam'; import * as s3 from '@aws-cdk/aws-s3'; import * as s3_assets from '@aws-cdk/aws-s3-assets'; import * as cdk from '@aws-cdk/core'; +import { zipDirectories } from './private/archive'; import { Construct } from 'constructs'; /** @@ -54,6 +55,18 @@ export abstract class Code { return new AssetCode(path, options); } + /** + * Loads the function code from local disk paths. + * + * @param paths an array of directories with the Lambda code bundle + */ + public static async fromMultiAsset(paths: string[], options?: s3_assets.AssetOptions): Promise { + //create a zip file from paths in paths[] + const outputFileAddress = './cdk.out/directories.zip'; + await zipDirectories(paths, outputFileAddress); + return new AssetCode(outputFileAddress, options); + } + /** * Loads the function code from an asset created by a Docker build. * diff --git a/packages/@aws-cdk/aws-lambda/lib/private/archive.ts b/packages/@aws-cdk/aws-lambda/lib/private/archive.ts new file mode 100644 index 0000000000000..746fb1fd600f6 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/lib/private/archive.ts @@ -0,0 +1,48 @@ +import { createWriteStream, promises as fs } from 'fs'; +import * as path from 'path'; +import * as glob from 'glob'; + +// namespace object imports won't work in the bundle for function exports +// eslint-disable-next-line @typescript-eslint/no-require-imports +const archiver = require('archiver'); + +export function zipDirectories(directories: string[], outputFile: string): Promise { + return new Promise(async (ok, fail) => { + + const output = createWriteStream(outputFile); + + const archive = archiver('zip'); + archive.on('warning', fail); + archive.on('error', fail); + + // archive has been finalized and the output file descriptor has closed, resolve promise + // this has to be done before calling `finalize` since the events may fire immediately after. + // see https://www.npmjs.com/package/archiver + output.once('close', ok); + + archive.pipe(output); + for (const directory of directories) { + // The below options are needed to support following symlinks when building zip files: + // - nodir: This will prevent symlinks themselves from being copied into the zip. + // - follow: This will follow symlinks and copy the files within. + const globOptions = { + dot: true, + nodir: true, + follow: true, + cwd: directory, + }; + const files = glob.sync('**', globOptions); // The output here is already sorted + // Append files serially to ensure file order + for (const file of files) { + const fullPath = path.resolve(directory, file); + const [data, stat] = await Promise.all([fs.readFile(fullPath), fs.stat(fullPath)]); + archive.append(data, { + name: file, + date: new Date('1980-01-01T00:00:00.000Z'), // reset dates to get the same hash for the same content + mode: stat.mode, + }); + } + } + await archive.finalize(); + }); +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/package.json b/packages/@aws-cdk/aws-lambda/package.json index 7cecadb30ca66..a09affe5a5507 100644 --- a/packages/@aws-cdk/aws-lambda/package.json +++ b/packages/@aws-cdk/aws-lambda/package.json @@ -117,6 +117,7 @@ "@aws-cdk/core": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/region-info": "0.0.0", + "@types/archiver": "^5.3.1", "constructs": "^10.0.0" }, "homepage": "https://github.com/aws/aws-cdk",