Skip to content

Commit

Permalink
feat: Split, export BundlingOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
setu4993 committed Dec 25, 2021
1 parent 7cad703 commit e6d466a
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 115 deletions.
75 changes: 15 additions & 60 deletions packages/@aws-cdk/aws-lambda-python/lib/bundling.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as path from 'path';
import { Architecture, AssetCode, Code, Runtime } from '@aws-cdk/aws-lambda';
import { AssetHashType, AssetStaging, BundlingOptions, DockerImage } from '@aws-cdk/core';
import { AssetStaging, BundlingOptions as CdkBundlingOptions, DockerImage } from '@aws-cdk/core';
import { Packaging, DependenciesFile } from './packaging';
import { BundlingOptions } from './types';

/**
* Dependency files to exclude from the asset hash.
Expand All @@ -16,80 +17,29 @@ export const BUNDLER_DEPENDENCIES_CACHE = '/var/dependencies';
/**
* Options for bundling
*/
export interface BundlingProps {
export interface BundlingProps extends BundlingOptions {
/**
* Entry path
*/
readonly entry: string;

/**
* The runtime of the lambda function
* The runtime environment.
*/
readonly runtime: Runtime;

/**
* The system architecture of the lambda function
*/
readonly architecture: Architecture;

/**
* Output path suffix ('python' for a layer, '.' otherwise)
*/
readonly outputPathSuffix?: string;

/**
* Docker image to use for bundling. If no options are provided, the default bundling image
* will be used. The bundling Docker image must have `rsync` installed. Dependencies will be
* copied from the image's`/var/dependencies` directory into the Lambda asset.
* @default: - the default bundling image
*/
readonly image?: DockerImage;

/**
* Determines how asset hash is calculated. Assets will get rebuild and
* uploaded only if their hash has changed.
*
* If asset hash is set to `SOURCE` (default), then only changes to the source
* directory will cause the asset to rebuild. This means, for example, that in
* order to pick up a new dependency version, a change must be made to the
* source tree. Ideally, this can be implemented by including a dependency
* lockfile in your source tree or using fixed dependencies.
*
* If the asset hash is set to `OUTPUT`, the hash is calculated after
* bundling. This means that any change in the output will cause the asset to
* be invalidated and uploaded. Bear in mind that `pip` adds timestamps to
* dependencies it installs, which implies that in this mode Python bundles
* will _always_ get rebuild and uploaded. Normally this is an anti-pattern
* since build
*
* @default AssetHashType.SOURCE By default, hash is calculated based on the
* contents of the source directory. If `assetHash` is also specified, the
* default is `CUSTOM`. This means that only updates to the source will cause
* the asset to rebuild.
* @default Architecture.X86_64
*/
readonly assetHashType?: AssetHashType;

/**
* Specify a custom hash for this asset. If `assetHashType` is set it must
* be set to `AssetHashType.CUSTOM`. For consistency, this custom hash will
* be SHA256 hashed and encoded as hex. The resulting hash will be the asset
* hash.
*
* NOTE: the hash is used in order to identify a specific revision of the asset, and
* used for optimizing and caching deployment activities related to this asset such as
* packaging, uploading to Amazon S3, etc. If you chose to customize the hash, you will
* need to make sure it is updated every time the asset changes, or otherwise it is
* possible that some deployments will not be invalidated.
*
* @default - based on `assetHashType`
*/
readonly assetHash?: string;
readonly architecture?: Architecture;
}

/**
* Produce bundled Lambda asset code
*/
export class Bundling implements BundlingOptions {
export class Bundling implements CdkBundlingOptions {
public static bundle(options: BundlingProps): AssetCode {
return Code.fromAsset(options.entry, {
assetHash: options.assetHash,
Expand All @@ -103,8 +53,12 @@ export class Bundling implements BundlingOptions {
public readonly command: string[];

constructor(props: BundlingProps) {

const { entry, runtime, architecture, outputPathSuffix } = props;
const {
entry,
runtime = Runtime.PYTHON_3_7,
architecture = Architecture.X86_64, outputPathSuffix,
image,
} = props;

const outputPath = path.join(AssetStaging.BUNDLING_OUTPUT_DIR, outputPathSuffix ?? '');

Expand All @@ -120,9 +74,10 @@ export class Bundling implements BundlingOptions {
},
platform: architecture.dockerPlatform,
});
this.image = props.image ?? defaultImage;
this.image = image ?? defaultImage;
this.command = ['bash', '-c', chain(bundlingCommands)];
}

private createBundlingCommand(options: BundlingCommandOptions): string[] {
const packaging = Packaging.fromEntry(options.entry);
let bundlingCommands: string[] = [];
Expand Down
71 changes: 17 additions & 54 deletions packages/@aws-cdk/aws-lambda-python/lib/function.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as fs from 'fs';
import * as path from 'path';
import * as lambda from '@aws-cdk/aws-lambda';
import { AssetHashType } from '@aws-cdk/core';
import { Function, FunctionOptions, Runtime, RuntimeFamily } from '@aws-cdk/aws-lambda';
import { Bundling } from './bundling';
import { BundlingOptions } from './types';


// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
Expand All @@ -11,7 +12,7 @@ import { Construct } from '@aws-cdk/core';
/**
* Properties for a PythonFunction
*/
export interface PythonFunctionProps extends lambda.FunctionOptions {
export interface PythonFunctionProps extends FunctionOptions {
/**
* The path to the root directory of the function.
*/
Expand All @@ -37,83 +38,45 @@ export interface PythonFunctionProps extends lambda.FunctionOptions {
*
* @default lambda.Runtime.PYTHON_3_7
*/
readonly runtime?: lambda.Runtime;

/**
* Determines how asset hash is calculated. Assets will get rebuild and
* uploaded only if their hash has changed.
*
* If asset hash is set to `SOURCE` (default), then only changes to the source
* directory will cause the asset to rebuild. This means, for example, that in
* order to pick up a new dependency version, a change must be made to the
* source tree. Ideally, this can be implemented by including a dependency
* lockfile in your source tree or using fixed dependencies.
*
* If the asset hash is set to `OUTPUT`, the hash is calculated after
* bundling. This means that any change in the output will cause the asset to
* be invalidated and uploaded. Bear in mind that `pip` adds timestamps to
* dependencies it installs, which implies that in this mode Python bundles
* will _always_ get rebuild and uploaded. Normally this is an anti-pattern
* since build
*
* @default AssetHashType.SOURCE By default, hash is calculated based on the
* contents of the source directory. This means that only updates to the
* source will cause the asset to rebuild.
*/
readonly assetHashType?: AssetHashType;
readonly runtime?: Runtime;

/**
* Specify a custom hash for this asset. If `assetHashType` is set it must
* be set to `AssetHashType.CUSTOM`. For consistency, this custom hash will
* be SHA256 hashed and encoded as hex. The resulting hash will be the asset
* hash.
*
* NOTE: the hash is used in order to identify a specific revision of the asset, and
* used for optimizing and caching deployment activities related to this asset such as
* packaging, uploading to Amazon S3, etc. If you chose to customize the hash, you will
* need to make sure it is updated every time the asset changes, or otherwise it is
* possible that some deployments will not be invalidated.
* Bundling options to use for this function. Use this to specify custom bundling options like
* the bundling Docker image, asset hash type, custom hash, architecture, etc.
*
* @default - based on `assetHashType`
* @default - Use the default bundling Docker image, with x86_64 architecture.
*/
readonly assetHash?: string;
readonly bundling?: BundlingOptions;
}

/**
* A Python Lambda function
*/
export class PythonFunction extends lambda.Function {
export class PythonFunction extends Function {
constructor(scope: Construct, id: string, props: PythonFunctionProps) {
if (props.runtime && props.runtime.family !== lambda.RuntimeFamily.PYTHON) {
throw new Error('Only `PYTHON` runtimes are supported.');
}
const { index = 'index.py', handler = 'handler', runtime = Runtime.PYTHON_3_7 } = props;
if (props.index && !/\.py$/.test(props.index)) {
throw new Error('Only Python (.py) index files are supported.');
}

// Entry and defaults
// Entry
const entry = path.resolve(props.entry);
const index = props.index ?? 'index.py';

const resolvedIndex = path.resolve(entry, index);
if (!fs.existsSync(resolvedIndex)) {
throw new Error(`Cannot find index file at ${resolvedIndex}`);
}

const handler = props.handler ?? 'handler';
const runtime = props.runtime ?? lambda.Runtime.PYTHON_3_7;
const architecture = props.architecture ?? lambda.Architecture.X86_64;
if (props.runtime && props.runtime.family !== RuntimeFamily.PYTHON) {
throw new Error('Only `PYTHON` runtimes are supported.');
}

super(scope, id, {
...props,
runtime,
code: Bundling.bundle({
runtime,
architecture,
entry,
outputPathSuffix: '.',
assetHashType: props.assetHashType,
assetHash: props.assetHash,
runtime,
...props.bundling,
}),
handler: `${index.slice(0, -3)}.${handler}`,
});
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-lambda-python/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './function';
export * from './layer';
export * from './packaging';
export * from './types';
62 changes: 62 additions & 0 deletions packages/@aws-cdk/aws-lambda-python/lib/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { AssetHashType, DockerImage } from '@aws-cdk/core';


/**
* Options for bundling
*/
export interface BundlingOptions {
/**
* Output path suffix ('python' for a layer, '' otherwise)
*
* @default '''
*/
readonly outputPathSuffix?: string;

/**
* Docker image to use for bundling. If no options are provided, the default bundling image
* will be used. The bundling Docker image must have `rsync` installed. Dependencies will be
* copied from the image's`/var/dependencies` directory into the Lambda asset.
* @default - Default bundling image.
*/
readonly image?: DockerImage;

/**
* Determines how asset hash is calculated. Assets will get rebuild and
* uploaded only if their hash has changed.
*
* If asset hash is set to `SOURCE` (default), then only changes to the source
* directory will cause the asset to rebuild. This means, for example, that in
* order to pick up a new dependency version, a change must be made to the
* source tree. Ideally, this can be implemented by including a dependency
* lockfile in your source tree or using fixed dependencies.
*
* If the asset hash is set to `OUTPUT`, the hash is calculated after
* bundling. This means that any change in the output will cause the asset to
* be invalidated and uploaded. Bear in mind that `pip` adds timestamps to
* dependencies it installs, which implies that in this mode Python bundles
* will _always_ get rebuild and uploaded. Normally this is an anti-pattern
* since build
*
* @default AssetHashType.SOURCE By default, hash is calculated based on the
* contents of the source directory. This means that only updates to the
* source will cause the asset to rebuild.
*/

readonly assetHashType?: AssetHashType;

/**
* Specify a custom hash for this asset. If `assetHashType` is set it must
* be set to `AssetHashType.CUSTOM`. For consistency, this custom hash will
* be SHA256 hashed and encoded as hex. The resulting hash will be the asset
* hash.
*
* NOTE: the hash is used in order to identify a specific revision of the asset, and
* used for optimizing and caching deployment activities related to this asset such as
* packaging, uploading to Amazon S3, etc. If you chose to customize the hash, you will
* need to make sure it is updated every time the asset changes, or otherwise it is
* possible that some deployments will not be invalidated.
*
* @default - Based on `assetHashType`
*/
readonly assetHash?: string;
}

0 comments on commit e6d466a

Please sign in to comment.