Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: lambda bundling with cdk-assets #22325

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/@aws-cdk/cloud-assembly-schema/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ needed in order to deploy the assembly directory.
> For example, when `cdk deploy` is executed, the CLI reads this file and performs its instructions:
>
> - Build container images.
> - Upload assets.
> - Bundle (if needed) and upload assets.
> - Deploy CloudFormation templates.

Therefore, the assembly is how the CDK class library and CDK CLI (or any other consumer) communicate. To ensure compatibility
Expand Down
115 changes: 115 additions & 0 deletions packages/@aws-cdk/cloud-assembly-schema/lib/assets/file-asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,121 @@ export interface FileSource {
* @default FILE
*/
readonly packaging?: FileAssetPackaging;

/**
* Bundling instructions if asset is not in bundled form in assembly
*
* @default - no bundling
*/
readonly bundling?: BundlingOptions;
}

/**
* Options for bundling the file asset from source
*/
export interface BundlingOptions {
/**
* Image used for bundling unless local bundling is possible
*/
readonly image: string;

/**
* The entrypoint to run in the container.
*
* @default - run the entrypoint defined in the image
*/
readonly entrypoint?: string[];

/**
* The command to run in the container.
*
* @default - run the command defined in the image
*/
readonly command?: string[];

/**
* Docker volumes to mount.
*
* @default - no volumes are mounted
*/
readonly volumes?: DockerVolume[];

/**
* The environment variables to pass to the container.
*
* @default - no environment variables.
*/
readonly environment?: { [key: string]: string; };

/**
* Working directory inside the container.
*
* @default - image default
*/
readonly workingDirectory?: string;

/**
* The user to use when running the container.
*
* @default - root or image default
*/
readonly user?: string;

/**
* [Security configuration](https://docs.docker.com/engine/reference/run/#security-configuration)
* when running the docker container.
*
* @default - no security options
*/
readonly securityOpt?: string;

/**
* Docker [Networking options](https://docs.docker.com/engine/reference/commandline/run/#connect-a-container-to-a-network---network)
*
* @default - no networking options
*/
readonly network?: string;
}

/**
* Docker volume to be added to bundling image
*/
export interface DockerVolume {
/**
* The path to the file or directory on the host machine
*/
readonly hostPath: string;

/**
* The path where the file or directory is mounted in the container
*/
readonly containerPath: string;

/**
* Mount consistency. Only applicable for macOS
*
* @default DockerConsistency.DELEGATED
* @see https://docs.docker.com/storage/bind-mounts/#configure-mount-consistency-for-macos
*/
readonly consistency?: DockerVolumeConsistency;
}

/**
* Supported Docker volume consistency types. Only valid on macOS due to the way file storage works on Mac
*/
export enum DockerVolumeConsistency {
/**
* Read/write operations inside the Docker container are applied immediately on the mounted host machine volumes
*/
CONSISTENT = 'consistent',
/**
* Read/write operations on mounted Docker volumes are first written inside the container and then synchronized to the host machine
*/
DELEGATED = 'delegated',
/**
* Read/write operations on mounted Docker volumes are first applied on the host machine and then synchronized to the container
*/
CACHED = 'cached',
}

/**
Expand Down
86 changes: 86 additions & 0 deletions packages/@aws-cdk/cloud-assembly-schema/schema/assets.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,95 @@
"zip"
],
"type": "string"
},
"bundling": {
"description": "Bundling instructions if asset is not in bundled form in assembly",
"$ref": "#/definitions/BundlingOptions"
}
}
},
"BundlingOptions": {
"type": "object",
"properties": {
"image": {
"description": "Image used for bundling unless local bundling is possible",
"type": "string"
},
"entrypoint": {
"description": "The entrypoint to run in the container. (Default - run the entrypoint defined in the image)",
"type": "array",
"items": {
"type": "string"
}
},
"command": {
"description": "The command to run in the container. (Default - run the command defined in the image)",
"type": "array",
"items": {
"type": "string"
}
},
"volumes": {
"description": "Docker volumes to mount. (Default - no volumes are mounted)",
"type": "array",
"items": {
"$ref": "#/definitions/DockerVolume"
}
},
"environment": {
"description": "The environment variables to pass to the container. (Default - no environment variables.)",
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"workingDirectory": {
"description": "Working directory inside the container. (Default - image default)",
"type": "string"
},
"user": {
"description": "The user to use when running the container. (Default - root or image default)",
"type": "string"
},
"securityOpt": {
"description": "[Security configuration](https://docs.docker.com/engine/reference/run/#security-configuration)\nwhen running the docker container. (Default - no security options)",
"type": "string"
},
"network": {
"description": "Docker [Networking options](https://docs.docker.com/engine/reference/commandline/run/#connect-a-container-to-a-network---network) (Default - no networking options)",
"type": "string"
}
},
"required": [
"image"
]
},
"DockerVolume": {
"type": "object",
"properties": {
"hostPath": {
"description": "The path to the file or directory on the host machine",
"type": "string"
},
"containerPath": {
"description": "The path where the file or directory is mounted in the container",
"type": "string"
},
"consistency": {
"description": "Mount consistency. Only applicable for macOS (Default DockerConsistency.DELEGATED)",
"enum": [
"cached",
"consistent",
"delegated"
],
"type": "string"
}
},
"required": [
"containerPath",
"hostPath"
]
},
"FileDestination": {
"description": "Where in S3 a file asset needs to be published",
"type": "object",
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":"21.0.0"}
{"version":"22.0.0"}
53 changes: 53 additions & 0 deletions packages/@aws-cdk/cloud-assembly-schema/test/assets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,31 @@ describe('File asset', () => {
}).not.toThrow();
});
}

test('with bundling', () => {
expect(() => {
validate({
version: Manifest.version(),
files: {
asset: {
source: {
path: 'a/b/c',
bundling: {
image: 'node:14',
},
},
destinations: {
dest: {
region: 'us-north-20',
bucketName: 'Bouquet',
objectKey: 'key',
},
},
},
},
});
}).not.toThrow();
});
});

describe('invalid input', () => {
Expand Down Expand Up @@ -178,6 +203,34 @@ describe('File asset', () => {
});
}).toThrow(/instance\.files\.asset\.source\.packaging is not one of enum values: file,zip/);
});

test('missing bundling image', () => {
expect(() => {
validate({
version: Manifest.version(),
files: {
asset: {
source: {
path: 'a/b/c',
bundling: {
command: [
'echo',
'hello',
],
},
},
destinations: {
dest: {
region: 'us-north-20',
bucketName: 'Bouquet',
objectKey: 'key',
},
},
},
},
});
}).toThrow(/instance\.files\.asset\.source\.bundling requires property \"image\"/);
});
});
});

Expand Down
23 changes: 23 additions & 0 deletions packages/cdk-assets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ the manifest.
Currently the following asset types are supported:

* Files and archives, uploaded to S3
* Can be either pre-bundled or bundled when `cdk-assets` is called
* Docker Images, uploaded to ECR
* Files, archives, and Docker images built by external utilities

Expand Down Expand Up @@ -90,6 +91,28 @@ An asset manifest looks like this:
}
}
},
"7aac5b80b050e7e4e168f84feffa5894": {
"source": {
"path": "some_directory",
"packaging": "zip",
"bundling": {
"image": "public.ecr.aws/sam/build-nodejs16.x",
"command": [
"bash", "-c",
"npm i -g esbuild && esbuild --bundle \"/asset-input/app.ts\" --target=node16 --platform=node --outfile=\"/asset-output/index.js\" --external:aws-sdk --loader:.png=dataurl"
],
"workingDirectory": "/"
}
},
"destinations": {
"us-east-1": {
"region": "us-east-1",
"assumeRoleArn": "arn:aws:iam::12345789012:role/my-account",
"bucketName": "MyBucket",
"objectKey": "7aac5b80b050e7e4e168f84feffa5894.zip"
}
}
},
"3dfe2b80b050e7e4e168f84feff678d4": {
"source": {
"executable": ["myzip"]
Expand Down
Loading