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

cdk-bundle #1954

Closed
wants to merge 2 commits into from
Closed

cdk-bundle #1954

wants to merge 2 commits into from

Conversation

eladb
Copy link
Contributor

@eladb eladb commented Mar 5, 2019

An initial implementation for a new module called cdk-bundle which aims to implement the new CDK bundling system. It reads a bundle.json file and executes the commands in that file in topological order. Currently I extracted "copy", "zip" and "docker" from the toolkit. This change also updates how assets are synthesized, so CDK apps now produce an output directory that's compatible with cdk-bundle and the result of building will be a cloud assembly (yey).

Currently supports 'copy', 'zip' and 'docker' tasks.

The assets.Artifact class synthesizes a directory structure compatible
with this library.

Enable using jest for testing (simply use jest instead of cdk-test)

The current toolkit implementation conflates "build" and "deploy", so the next step in this journey is to extract the deployment tasks from the toolkit into yet another module called "cdk-deploy" which will read the built assembly and deploy it to the cloud (i.e. implement the various deployment tasks).

Instead of trying to refactor the toolkit from within (only Rico has the audacity to do that safely), I figured that a more healthy approach, would be to simply extract fresh new modules, jsii-compatible, minimal dependencies, and fully covered by unit tests.

The idea is to have three of those modules:

  1. cdk-synth (app => cdk.out): responsible to do all the trickery around context providers
  2. cdk-build (cdk.out => assembly): a build system, this is where Sam goes nuts with Lambda builds and shit)
  3. cdk-deploy (assembly => cloud): supports various deployment tasks such as CFN, S3, ECR)

Our CLI (and future unified CLIs) will thread those together into a cohesive experience, but they can also be used independently either as command line tools or as cross-language libraries (nirvana!).

TODO


Pull Request Checklist

  • Testing
    • Unit test added (prefer not to modify an existing test, otherwise, it's probably a breaking change)
    • CLI change?: coordinate update of integration tests with team
    • cdk-init template change?: coordinated update of integration tests with team
  • Docs
    • jsdocs: All public APIs documented
    • README: README and/or documentation topic updated
  • Title and Description
    • Change type: title prefixed with fix, feat will appear in changelog
    • Title: use lower-case and doesn't end with a period
    • Breaking?: last paragraph: "BREAKING CHANGE: <describe what changed + link for details>"
    • Issues: Indicate issues fixed via: "Fixes #xxx" or "Closes #xxx"
  • Sensitive Modules (requires 2 PR approvers)
    • IAM Policy Document (in @aws-cdk/aws-iam)
    • EC2 Security Groups and ACLs (in @aws-cdk/aws-ec2)
    • Grant APIs (only if not based on official documentation with a reference)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license.

An initial implementation which extracts the build phase from the toolkit
into a *jsii* library. The library can read build.json files and execute
the tasks defines in it in topological order.

Currently supports 'copy', 'zip' and 'docker' tasks.

The assets.Artifact class synthesizes a directory structure compatible
with this library.

Enable using `jest` for testing (simply use `jest` instead of `cdk-test`)
@eladb eladb requested a review from a team March 5, 2019 16:03
@RomainMuller RomainMuller self-requested a review March 5, 2019 16:09
@sam-goodwin sam-goodwin self-requested a review March 5, 2019 18:35
const sourcePath = path.resolve(props.path);
validateAssetOnDisk(sourcePath, props.packaging);

// calculate content hash, which is what we use as the app-level ID of this asset
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the app-level ID should also contain the packaging type at least.

const artifact = root.node.tryFindChild(id) as AssetArtifact || new AssetArtifact(root, id, {
fingerprint: fp,
path: sourcePath,
...props
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move ...props upfront... Otherwise it could replace fingerprint and path.

super(scope, id);

this.fingerprint = props.fingerprint;
this.artifactId = id; // based on the fingerprint
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From this scope, you can't know it's based on the fingerprint. Why not make the ID from within the constructor?

return {
bucket: stack.node.findChild(bucketParamId) as cdk.Parameter,
key: stack.node.findChild(keyParamId) as cdk.Parameter,
sha256: stack.node.findChild(hashParamId) as cdk.Parameter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason, I'd prefer to findOrCreate all three parameters independently from each other. Not willing to die on that hill however.


const bucketParam = new cdk.Parameter(stack, bucketParamId, {
type: 'String',
description: `S3 bucket for asset ${this.fingerprint} from ${this.props.path}`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the path should be there. It'll be absolute and will change on every different machine that synthesizes it. At the very least if there, should ensure it is made relative to the working directory, I guess?

Also - the path could be only an "example" - if the same file is copied in multiple places, the fingerprint would still de-dupe them to the same fingerprint... And this might generate confusion.

if (code === 0) {
resolve(Buffer.concat(stdout).toString('utf-8'));
} else {
reject(new Error(`${renderCommandLine(command)} exited with error code ${code}`));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the process ends due to a signal (SIGSEVG, SIGTERM, SIGKILL, ...), the error message won't be very helpful. In such cases, code might be null.

* App-level context key/value pairs.
*
* If the environment variable `CDK_CONTEXT_JSON` is set, it is parsed as a JSON object
* and merged with this hash to form the application's context.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which has precedence over the other if there are collisions?


// both are reverse logic
this.legacyManifest = this.node.getContext(cxapi.DISABLE_LEGACY_MANIFEST_CONTEXT) ? false : true;
this.runtimeInformation = this.node.getContext(cxapi.DISABLE_VERSION_REPORTING) ? false : true;
this.outdir = props.outdir || process.env[cxapi.OUTDIR_ENV] || fs.mkdtempSync(os.tmpdir());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the records, not a huge fan of creating a temporary directory that will never be cleaned up & might be hard to locate by the customer. Also, this will fail because it'll try to create stuff like /tmp<somerandomjunk> -- as mkdtemp will NOT append a / at the end of it's prefix.

@@ -246,127 +275,23 @@ export class FileSystemStore implements ISessionStore {
}

public list(): string[] {
return fs.readdirSync(this.outdir).sort();
return fs.readdirSync(this.path).sort();
}

public finalize() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call this close? I don't know if'd feel natural to me. In any case, the error messages everywhere refer to " has already been locked", but the user never does anything called lock, so it's confusing.

@@ -511,9 +511,9 @@ export class MustUseCDKTest extends ValidationRule {
if (!shouldUseCDKBuildTools(pkg)) { return; }
if (!hasTestDirectory(pkg)) { return; }

expectJSON(this.name, pkg, 'scripts.test', 'cdk-test');
expectJSONOneOf(this.name, pkg, 'scripts.test', [ 'cdk-test', 'jest' ]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed after my change that allows cdk-test to run jest if it is configured.

@eladb eladb changed the title cdk-build cdk-bundle Mar 26, 2019
@eladb eladb removed their assignment Apr 10, 2019
@eladb eladb removed package/awscl Cross-cutting issues related to the AWS Construct Library labels May 1, 2019
@eladb eladb closed this May 29, 2019
eladb pushed a commit that referenced this pull request May 29, 2019
Formalize the concept of a cloud assembly to allow decoupling "synth" and "deploy". the main
motivation is to allow "deploy" to run in a controlled environment without needing to execute the app for security purposes.

`cdk synth` now produces a self-contained assembly in the output directory, which we call a "cloud assembly". this directory includes synthesized templates (similar to current behavior) but also a "manifest.json" file and the asset staging directories.

`cdk deploy -a assembly-dir` will now skip synthesis and will directly deploy the assembly.

To that end, we modified the behavior of asset staging such that all synth output always goes to the output directory, which is by default `cdk.out` (can be set with `--output`). if there's a single template, it is printed to stdout, otherwise the name of output directory is printed.

This PR also includes multiple clean ups and deprecations of stale APIs and modules such as:

- `cdk.AppProps` includes various new options.
- An error is thrown if references between stacks that are not in the same app (mostly in test cases).
- Added the token creation stack trace for errors emitted by tokens
- Added `ConstructNode.root` which returns the tree root.
 

**TESTING**: verified that all integration tests passed and added a few tests to verify zip and docker assets as well as cloud assemblies. See: https://github.com/awslabs/cdk-ops/pull/364

Closes #1893 
Closes #2093 
Closes #1954 
Closes #2310 
Related #2073 
Closes #1245
Closes #341
Closes #956
Closes #233

BREAKING CHANGE: *IMPORTANT*: apps created with the CDK version 0.33.0 and above cannot be used with an older CLI version.
- `--interactive` has been removed
- `--numbered` has been removed
- `--staging` is now a boolean flag that indicates whether assets should be copied to the `--output` directory or directly referenced (`--no-staging` is useful for e.g. local debugging with SAM CLI)
- Assets (e.g. Lambda code assets) are now referenced relative to the output directory.
- `SynthUtils.templateForStackName` has been removed (use `SynthUtils.synthesize(stack).template`).
- `cxapi.SynthesizedStack` renamed to `cxapi.CloudFormationStackArtifact` with multiple API changes.
- `cdk.App.run()` now returns a `cxapi.CloudAssembly` instead of `cdk.ISynthesisSession`.
- `cdk.App.synthesizeStack` and `synthesizeStacks` has been removed. The `cxapi.CloudAssembly` object returned from `app.run()` can be used as an alternative to explore a synthesized assembly programmatically (resolves #2016).
- `cdk.CfnElement.creationTimeStamp` may now return `undefined` if there is no stack trace captured.
- `cdk.ISynthesizable.synthesize` now accepts a `cxapi.CloudAssemblyBuilder` instead of `ISynthesisSession`.
- `cdk`: The concepts of a synthesis session and session stores have been removed (`cdk.FileSystemStore`, cdk.InMemoryStore`, `cdk.SynthesisSession`, `cdk.ISynthesisSession` and `cdk.SynthesisOptions`).
- No more support for legacy manifests (`cdk.ManifestOptions` member `legacyManifest` has been removed)
- All support for build/bundle manifest have been removed (`cxapi.BuildManifest`, `cxapi.BuildStep`, etc).
- Multiple deprecations and breaking changes in the `cxapi` module (`cxapi.AppRuntime` has been renamed to `cxapi.RuntimeInfo`, `cxapi.SynthesizeResponse`, `cxapi.SynthesizedStack` has been removed)
- The `@aws-cdk/applet-js` program is no longer available. Use [decdk](https://github.com/awslabs/aws-cdk/tree/master/packages/decdk) as an alternative.
@eladb eladb deleted the benisrae/cdk-build branch June 23, 2019 20:44
@NGL321 NGL321 added the contribution/core This is a PR that came from AWS. label Sep 23, 2019
@mergify
Copy link
Contributor

mergify bot commented Sep 23, 2019

Thanks so much for taking the time to contribute to the AWS CDK ❤️

We will shortly assign someone to review this pull request and help get it
merged. In the meantime, please take a minute to make sure you follow this
checklist
:

  • PR title type(scope): text
    • type: fix, feat, refactor go into CHANGELOG, chore is hidden
    • scope: name of module without aws- or cdk- prefix or postfix (e.g. s3 instead of aws-s3-deployment)
    • text: use all lower-case, do not end with a period, do not include issue refs
  • PR Description
    • Rationale: describe rationale of change and approach taken
    • Issues: indicate issues fixed via: fixes #xxx or closes #xxx
    • Breaking?: last paragraph: BREAKING CHANGE: <describe what changed + link for details>
  • Testing
    • Unit test added. Prefer to add a new test rather than modify existing tests
    • CLI or init templates change? Re-run/add CLI integration tests
  • Documentation
    • README: update module README to describe new features
    • API docs: public APIs must be documented. Copy from official AWS docs when possible
    • Design: for significant features, follow design process

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution/core This is a PR that came from AWS.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants