[lambda-python] Abstraction for bundling code for use in either a Function or a Layer
See original GitHub issueThe current bundling function that drives PythonFunction contains 99% of what I need to accomplish building a Layer, but doesn’t allow me to place assets into runtime-specific directories.
It would be nice if there were a publicized construct of some sort that encapsulated the knowledge about runtime specific paths, and contained the bundling code that could be used for either a PythonFunction or a python-based Layer.
Use Case
This would make integrating layer code into function code more intuitive since a python layer would put the code and dependencies in the right /opt path for me. It would also cut down on the amount of code currently needed to build a layer, which is almost completely redundant of what is currently in the bundle functions (for both lambda-nodejs and lambda-python).
Proposed Solution
I hacked this quickly by allowing an output subdirectory as part of my bundle options. But an abstraction that houses all those runtime specific paths and drops code into them would be cool.
/**
* Options for bundling
*/
export interface BundlingOptions {
/**
* Entry path
*/
readonly entry: string;
/**
* The runtime of the lambda function
*/
readonly runtime: lambda.Runtime;
/**
* Subdirectory in which to place bundled assets inside the output directory
*
* This is useful if building a layer and you need to place
* bundled assets inside the AWS specified runtime folders.
*
* e.g. /python for Python
*
* @default ""
*/
readonly outputSubdirectory?: string;
}
enum Installer {
PIP = 'pip',
PIP3 = 'pip3',
}
function chain(commands: string[]): string {
return commands.filter((c) => !!c).join(' && ');
}
/**
* Produce bundled Lambda asset code
*/
export function bundle(options: BundlingOptions): lambda.AssetCode {
const installer = options.runtime === lambda.Runtime.PYTHON_2_7 ? Installer.PIP : Installer.PIP3;
const outputSubdirectory = options.outputSubdirectory || '';
const targetDirectory = path.join(cdk.AssetStaging.BUNDLING_OUTPUT_DIR, outputSubdirectory);
const hasRequirements = fs.existsSync(path.join(options.entry, 'requirements.txt'));
const depsCommand = chain([
hasRequirements ? `${installer} install -r requirements.txt -t ${targetDirectory}` : '',
`cp -r . ${targetDirectory}`,
]);
return lambda.Code.fromAsset(options.entry, {
bundling: {
image: BundlingDockerImage.fromRegistry(`amazon/aws-sam-cli-build-image-${options.runtime.name}`),
command: ['bash', '-c', depsCommand],
},
});
}
Other
- 👋 I may be able to implement this feature request
- ⚠️ This feature might incur a breaking change
This is a 🚀 Feature Request
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (3 by maintainers)
Top GitHub Comments
FYI, layer support will be coming soon in https://github.com/aws/aws-cdk/pull/9582
This was closed out by #9582 cc @eladb @SomayaB