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(assets): surface the CFN Parameters that Assets create #2057

Closed
wants to merge 1 commit into from

Conversation

skinny85
Copy link
Contributor

This is needed in order to override them when deploying the Stack through CodePipeline.


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.

@skinny85 skinny85 requested a review from a team as a code owner March 20, 2019 01:53
@skinny85 skinny85 requested a review from eladb March 20, 2019 01:53
@skinny85
Copy link
Contributor Author

There is a pretty serious issue with this solution. Because Assets check whether the file/directory they point to exists, this forces the build in CodePipeline to happen sequentially - first the packaging of the Lambda source into a deployable artifact, and only then cdk synth NameOfLambdaStack. This is wasteful, as other than checking for that file existing, the CDK process does not use that artifact in any way, so the 2 builds should happen in parallel in the Pipeline.

@rix0rrr
Copy link
Contributor

rix0rrr commented Mar 20, 2019

Because Assets check whether the file/directory they point to exists

Fair point. The Correct Solution (tm) is probably to add a checkForExistence: true parameter to the assets. If left undefined, we use the default, and the default can be based on whether or not we're running in CI.

The toolkit already has a --ci flag, with logic to autodetermine whether it's most likely running on CI. We can pass that value to the CDK app either via context or an ENV_VAR.

const parameterOverrides: { [name: string]: any } = {};
parameterOverrides[lambdaCode.asset.bucketNameParam.logicalId] = lambdaBuildAction.outputArtifact.bucketName;
parameterOverrides[lambdaCode.asset.objectKeyParam.logicalId] = lambdaBuildAction.outputArtifact.objectKey;
pipeline.addStage({
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you build the next layer on top of this as well?

So that we basically do:

const stack = new MyStack(app, 'MyStack');

stack.addToPipeline(pipeline);  // (*)

And make that work? What will we need to map assets used in the application to build artifacts? Can we even find a list of all assets, so that the addToPipeline() call can determine that we satisfied all requirements? Etc.

// (*) I know this exact method call will not work because the package dependency arrows will point the wrong way, but I'm mirroring the build.addToPipeline() etc. methods here.

Copy link
Contributor

Choose a reason for hiding this comment

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

We are actually planning to remove all the addTpPipeline methods since we are moving all the pipeline integration classes to a centralized package. But maybe something like an integration class would work.

Copy link
Contributor

Choose a reason for hiding this comment

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

But yeah, this is waaayy to verbose

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you build the next layer on top of this as well?

So that we basically do:

const stack = new MyStack(app, 'MyStack');

stack.addToPipeline(pipeline);  // (*)

And make that work? What will we need to map assets used in the application to build artifacts? Can we even find a list of all assets, so that the addToPipeline() call can determine that we satisfied all requirements? Etc.

// (*) I know this exact method call will not work because the package dependency arrows will point the wrong way, but I'm mirroring the build.addToPipeline() etc. methods here.

We can't be so high level, unfortunately. You wouldn't know which Pipeline Artifacts to use to override each Asset - the customer needs to specify this.

Copy link
Contributor

Choose a reason for hiding this comment

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

I know, but what I'm saying is trying to get as close to that as possible.

packages/@aws-cdk/assets/lib/asset.ts Outdated Show resolved Hide resolved
packages/@aws-cdk/aws-lambda/README.md Outdated Show resolved Hide resolved
const parameterOverrides: { [name: string]: any } = {};
parameterOverrides[lambdaCode.asset.bucketNameParam.logicalId] = lambdaBuildAction.outputArtifact.bucketName;
parameterOverrides[lambdaCode.asset.objectKeyParam.logicalId] = lambdaBuildAction.outputArtifact.objectKey;
pipeline.addStage({
Copy link
Contributor

Choose a reason for hiding this comment

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

We are actually planning to remove all the addTpPipeline methods since we are moving all the pipeline integration classes to a centralized package. But maybe something like an integration class would work.

const parameterOverrides: { [name: string]: any } = {};
parameterOverrides[lambdaCode.asset.bucketNameParam.logicalId] = lambdaBuildAction.outputArtifact.bucketName;
parameterOverrides[lambdaCode.asset.objectKeyParam.logicalId] = lambdaBuildAction.outputArtifact.objectKey;
pipeline.addStage({
Copy link
Contributor

Choose a reason for hiding this comment

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

But yeah, this is waaayy to verbose

@skinny85
Copy link
Contributor Author

Updated according to comments. Let me know if this is better @eladb and @rix0rrr !

@skinny85
Copy link
Contributor Author

Added mention of autoDeploy: false in the ReadMe of Lambda.

This is needed in order to override them when deploying the Stack through CodePipeline.
@skinny85
Copy link
Contributor Author

Rebased on top of all of the changes (in particular, #2098 , which allows us to depend on the aws-cdk/assets package from the module that contains the Artifact class used in CodePipeline).

@rix0rrr, @eladb , I would appreciate another run through the PR!

@@ -324,9 +324,69 @@ This package defines the following actions:
changes from the people (or system) applying the changes.
* **CloudFormationExecuteChangeSetAction** - Execute a change set prepared previously.

##### Lambda deployed through CodePipeline
Copy link
Contributor

Choose a reason for hiding this comment

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

This section makes me feel that maybe we should merge the README files of aws-codepipeline and aws-codepipeline-actions. It feels artificial to have to jump between the two... What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't have any philosophical objections to that, I do have one practical concern though: nesting. As you can see, we've reached H5 in the ReadMe for codepipeline-actions, and I assume we'll need to increase the nesting of the headings by at least one level if we move them to the codepipeline ReadMe.


```typescript
const lambdaStack = new cdk.Stack(app, 'LambdaStack', {
autoDeploy: false, // to make working with the 2 Stacks easier in the toolkit
Copy link
Contributor

Choose a reason for hiding this comment

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

Change the comment to describe what this does

cdkBuildAction,
],
});
// finally, deploy your Lambda Stack
Copy link
Contributor

Choose a reason for hiding this comment

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

Style: new line before each "//" line

runtime: lambda.Runtime.NodeJS810,
});
// used to make sure each CDK synthesis produces a different Version
const version = func.newVersion();
Copy link
Contributor

Choose a reason for hiding this comment

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

This sounds weird and scary?... We can't have "cdk synth" produce a different result each time. Is this just temporary until we have #1400?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's meant to be used in a Pipeline, so I believe that's fine.

@@ -51,6 +52,13 @@ export class Artifact {
public toString() {
return this.artifactName;
}

public overrideAsset(asset: assets.Asset): { [name: string]: string } {
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing documentation. I am not sure about this name... Reads weird: artifact.overrideAsset(asset). What does this mean? Maybe something like artifact.wireAsset(asset) or artifact.useAsset(asset)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The word used is override because you're changing what the asset points to. Before, it was referencing something on the file system - now, it references something in the Pipeline. So I think it makes a lot of sense.

But if you prefer useAsset (wireAssetI don't think is great...), I won't fight you (too strongly ;p) on it.

@skinny85
Copy link
Contributor Author

skinny85 commented Apr 1, 2019

Talked with Elad offline about this PR. We decided not to go through with it.

@skinny85 skinny85 closed this Apr 1, 2019
@NGL321 NGL321 added the contribution/core This is a PR that came from AWS. label Sep 27, 2019
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.

4 participants