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(cli): implementation of the new bootstrap logic #5856

Merged
merged 5 commits into from
Feb 17, 2020

Conversation

skinny85
Copy link
Contributor

This is the logic of the new bootstrap command, deploying the template discussed in #4461 and then further in #5757 . You activate the new bootstrap behavior by passing the --new-bootstrap=true option to the CLI.

I've manually verified that bootstrapping succeeds, and that a CDK app using assets can successfully be deployed using this new bootstrap stack.

I've posting this as a draft, to get early feedback, as there are a few ways we can go about incorporating this new functionality, so I wanted to get the team's opinion on the direction taken.

I'm in the process of writing an automated integ test that checks whether this works without the need for manual testing, but it's proving to be a little tricky, so I figured I won't hold up the main logic PR on it.


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

@skinny85 skinny85 requested review from rix0rrr, eladb and NetaNir January 18, 2020 02:21
@skinny85 skinny85 self-assigned this Jan 18, 2020
@mergify mergify bot added the contribution/core This is a PR that came from AWS. label Jan 18, 2020
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

Comment on lines 11 to 43
const builder = new cxapi.CloudAssemblyBuilder(outdir);
const templateFile = `${toolkitStackName}.template.json`;

await fs.copy(
path.join(__dirname, 'bootstrap-template.json'),
path.join(builder.outdir, templateFile));

builder.addArtifact(toolkitStackName, {
type: cxapi.ArtifactType.AWS_CLOUDFORMATION_STACK,
environment: cxapi.EnvironmentUtils.format(environment.account, environment.region),
properties: {
templateFile,
},
});

const assembly = builder.buildAssembly();
return await deployStack({
stack: assembly.getStackByName(toolkitStackName),
sdk,
roleArn,
tags: props.tags,
execute: props.execute
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps extract this to deployStackFromTemplate as a more low-level building block and then just call it from here with the bootstrap template.

Also, I expected to see the bootstrap options passed in to CFN parameters...

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 tried extracting a deployStackFromTemplate() function, but it was super awkward (the file are created differently (fs.writeJson() versus fs.copy(), the temporary directories have different hints, we need to reference the output property of the CloudAssemblyBuilder to know where to put the files, etc.), so I abandoned it for now. If you have any suggestions how to make that part better, I'm all ears.

I've added passing the CLI options through the parameters.

@skinny85 skinny85 force-pushed the feat/new-bootstrap-command branch from a7fa19e to 60f3e48 Compare February 4, 2020 02:19
@skinny85 skinny85 requested review from rix0rrr and eladb February 4, 2020 02:19
@skinny85
Copy link
Contributor Author

skinny85 commented Feb 4, 2020

@eladb @rix0rrr this is ready for a re-review.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@skinny85 skinny85 force-pushed the feat/new-bootstrap-command branch from 60f3e48 to 42de894 Compare February 4, 2020 02:28
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@skinny85 skinny85 force-pushed the feat/new-bootstrap-command branch from 798b004 to 4c90b55 Compare February 4, 2020 19:34
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@skinny85 skinny85 changed the title feat(cli): basic implementation of the new bootstrap logic feat(cli): implementation of the new bootstrap logic Feb 6, 2020
@skinny85 skinny85 force-pushed the feat/new-bootstrap-command branch from 4c90b55 to 36c1ecf Compare February 6, 2020 03:06
@skinny85 skinny85 marked this pull request as ready for review February 6, 2020 03:06
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@skinny85 skinny85 force-pushed the feat/new-bootstrap-command branch from 36c1ecf to bec7408 Compare February 6, 2020 19:19
@skinny85
Copy link
Contributor Author

skinny85 commented Feb 6, 2020

Apologies for leaving the old comments in the PR @eladb , they are removed now.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

toolkitStackName: string, roleArn: string | undefined,
props: BootstrapEnvironmentProps = {}): Promise<DeployStackResult> {
if (props.trustedAccounts?.length && !props.cloudFormationExecutionPolicies?.length) {
throw new Error('--cloudformation-execution-policies are required if --trust has been passed!');
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not super happy with this user experience. What if I'm trusting a new account? Not only do I have to list all previous accounts, but I also have to re-list the policy?

And the policy even needs to be referenced by ARN, which is super annoying.

I know we're going bare-bones functionality for now and worry about the experience later, but this is going to need some attention I feel...

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 agree this is medium.

  1. For the "trusting new accounts" problem: would your comment here be applicable? We read the current value of the parameter, and add to it (with set semantics) the array of accounts that were passed in --trust, and that's the final value of the parameter? This way, --trust would always be additive.

  2. For the "policy needs to be referenced by ARN" problem: originally, we wanted to prompt the customer if they didn't pass anything in the --cloudformation-execution-policies with a list like this:

This will create a new IAM Role, trusting any principal from the ACCOUNT_ID AWS account,
that will be used for deploying your CloudFormation stack(s) in that environment.
Please choose the Managed Policy or Policies to attach to the Role
that contain the permissions required to perform those deployments:

[1]  AdministratorAccess
[2]  AmazonDynamoDBFullAccess
[3]  AmazonEC2FullAccess
[4]  AmazonECS_FullAccess
[5]  AmazonS3FullAccess
[6]  AmazonSageMakerFullAccess
[7]  AmazonSESFullAccess
[8]  AmazonSNSFullAccess
[9]  AmazonSQSFullAccess
[10] AWSLambdaFullAccess
[11] SimpleWorkflowFullAccess
...

Please input the number of the chosen Policy from the above list,
or provide a fully qualified ARN of a different Managed Policy.
You can input multiple numbers and/or ARNs (up to 10),
separated by commas.

>

But it was scrapped for time purposes. Do you want to revisit this topic?

Copy link
Contributor

Choose a reason for hiding this comment

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

  1. For the "trusting new accounts" problem: would your comment here be applicable? We read the current value of the parameter, and add to it (with set semantics) the array of accounts that were passed in --trust, and that's the final value of the parameter? This way, --trust would always be additive.

Yes, I would definitely like that. We would only use UsePreviousValue if there was NO change to the parameter, but if we used --trust or --untrust (?) we would do set logic on the parameter.

  1. I think I might want to revisit, or get people to the "right" solutions in an easier way. Maybe a UI, maybe we recognize some aliases for "standard" policies ("admin" => "arn:aws:iam:::policy/AdministratorAccess"). Doesn't have to be here and now (let's get this merged), but I want to put it into your head already.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I would definitely like that. We would only use UsePreviousValue if there was NO change to the parameter, but if we used --trust or --untrust (?) we would do set logic on the parameter.

Blah. This is kind of hard ☹️.

The problem is that you can't use UsePreviousValue if you're creating the Stack. Which means it's not good enough for our case. We would have to call DescribeStack before the deployment, and based on what that returns:

  • If the bootstrap Stack doesn't exist yet (= we're creating it), then pass whatever accounts were given in --trust as the value of the TrustedAccounts parameter.
  • If the bootstrap Stack does exist, add the current value of the TrustedAccounts parameter (split on commas of course, as its Type is CommaSeparatedList) to the set of accounts passed through --trust, and use that as the value.

That also means we need some way to remove accounts from the trust relationship (like the --untrust CLI option you mentioned).

Do you want me to add this logic as part of this PR, or are you OK coming back to this later @rix0rrr ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Totally later!

@@ -54,6 +66,16 @@ export async function deployStack(options: DeployStackOptions): Promise<DeploySt

const params = await prepareAssets(options.stack, options.toolkitInfo, options.reuseAssets);

// add passed CloudFormation parameters
for (const [paramName, paramValue] of Object.entries((options.parameters || {}))) {
if (paramValue) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We can consider looking at the existing stack here, and if there are any Parameters on the current stack that aren't passed here, we can be passing UsePreviousValue: true to make ergonomics around parameters a lot better.

Maybe not for this PR, but keep that in mind.

https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_Parameter.html

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great idea. I think we can use it to make --trust better - see #5856 (comment) .

@skinny85 skinny85 force-pushed the feat/new-bootstrap-command branch from bec7408 to 6b6826f Compare February 11, 2020 01:23
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@skinny85 skinny85 force-pushed the feat/new-bootstrap-command branch from 6b6826f to 2eb905a Compare February 11, 2020 01:38
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

This adds a new `cdk bootstrap` mode,
hidden behind the environment variable CDK_NEW_BOOTSTRAP,
that adds the necessary resources (ECR repository, IAM roles, etc.)
for our "CI/CD for CDK apps" epic,
as well as 2 new (hidden for now)
options: --trust (for specifying the accounts that are trusted to deploy into this environment)
and --cloudformation-execution-policies
(for specifying the ARNs of the Managed Policis that will be attached to the CFN deploying role).
@skinny85 skinny85 force-pushed the feat/new-bootstrap-command branch from 2eb905a to 892fa32 Compare February 11, 2020 22:36
@skinny85
Copy link
Contributor Author

@rix0rrr should be ready for another round of reviews (included your last comments).

@skinny85 skinny85 requested review from rix0rrr and eladb February 11, 2020 22:36
toolkitStackName: string, roleArn: string | undefined,
props: BootstrapEnvironmentProps = {}): Promise<DeployStackResult> {
if (props.trustedAccounts?.length && !props.cloudFormationExecutionPolicies?.length) {
throw new Error('--cloudformation-execution-policies are required if --trust has been passed!');
Copy link
Contributor

Choose a reason for hiding this comment

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

Totally later!

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 1f72085
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

There was a release since the PR was published.
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: e5b5fa7
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: f131e07
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: f131e07
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: cba700b
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@skinny85 skinny85 merged commit de48222 into aws:master Feb 17, 2020
@skinny85 skinny85 deleted the feat/new-bootstrap-command branch February 17, 2020 21:24
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