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

Deploy stacks in parallel where possible #1973

Closed
nathanpeck opened this issue Mar 7, 2019 · 52 comments · Fixed by #19378 or #20345
Closed

Deploy stacks in parallel where possible #1973

nathanpeck opened this issue Mar 7, 2019 · 52 comments · Fixed by #19378 or #20345
Labels
effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p1 package/tools Related to AWS CDK Tools or CLI

Comments

@nathanpeck
Copy link
Member

I am deploying a CDK app that uses 9 different stacks. Many of the stacks either do not depend on each other, or can be deployed in parallel. For example one base stack that has a DynamoDB table needs to be deployed first, but then all five stacks which have a Lambda that uses that table could be deployed in parallel. Then finally a stack that creates the API gateway that points at those Lambda functions can be deployed.

Ideally I would like to be able to opt in to deploying stacks concurrently as much as possible. Right now CDK only ever deploys one stack at a time, which makes the overall cdk deploy much slower than it needs to be.

@sam-goodwin sam-goodwin added package/tools Related to AWS CDK Tools or CLI feature-request A feature should be added or improved. labels Mar 7, 2019
@dnagir
Copy link

dnagir commented Mar 11, 2019

Second that. It is very time-consuming even on relatively small projects.

@lusentis
Copy link
Contributor

lusentis commented Mar 25, 2019

Would be super useful, but I guess it's not easy to implement because there are also a few number of limitations in terms of what can happen concurrently in an account/region, such as:

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html#limits-api

& more, see:
https://twitter.com/danbdo/status/1110183888415002624?s=19

@AlexCheema
Copy link
Contributor

@eladb This would be amazing. Any thoughts/plans on this?

@sd0408
Copy link

sd0408 commented Jul 30, 2019

Bumping this, we have so many stacks that without this we would likely have to utilize some sort of wrapper for the CDK which would diminish some of the value.

@eladb eladb assigned shivlaks and unassigned shivlaks Aug 12, 2019
@nathanpeck
Copy link
Member Author

@lusentis I don't believe that concurrency limits will impact the development of this feature from the point of view of CDK, because CloudFormation already handles that concurrency internally. From CDK's perspective it would just be deploying multiple CloudFormation stacks in parallel and waiting for CFN to come back with a success status. CFN already handles the retries / concurrency internally when it is deploying multiple stacks at once

@winjer
Copy link

winjer commented Nov 1, 2019

I've got some environments with 30 or 40 stacks, so this would be very helpful.

@Pritij
Copy link

Pritij commented Jan 15, 2020

we also have a huge infrastructure. If we could execute the stacks parallelly it would save couple of hours' time.

@shivlaks shivlaks added the effort/medium Medium work item – several days of effort label Feb 3, 2020
@muhqu
Copy link

muhqu commented Mar 4, 2020

I have multiple independent stacks which manage cloudfront distributions. Updating cloudfront distribution usually takes 5-10 minutes…

Currently I work around the limitation by opening multiple terminal sessions and deploying single stack per terminal session, but hence in parallel.

@enricopesce
Copy link

Very necessary feature. With other deployment tools is possible, for example Sceptre

@erik-sab
Copy link

Especially painfull, as issue
#5637
blocks implementing workaround for this one.

@jacques-
Copy link

+1, would save us significant deploy time as well.

@OperationalFallacy
Copy link

Already painful experience with the same stack and different environments...

@nathanpeck
Copy link
Member Author

@OperationalFallacy With the same stack and different environments its not too bad because you can just run multiple copies of CDK in parallel with different profiles, or different CDK_DEFAULT_ACCOUNT env variable.

Something like this:

cdk deploy --profile dev --require-approval=never &
cdk deploy --profile production --require-approval=never &

This assumes you have two different AWS credential profiles setup, and are using two different AWS subaccounts for a developer environment and a production environment (this is best practice anyway). The & operator causes CDK to run in the background, so both instances of CDK will deploy to their respective environments in parallel.

In general I do agree that deploying to multiple environments concurrently as well as multiple stacks concurrently would be nice though

@robertd
Copy link
Contributor

robertd commented Aug 1, 2020

I'm using a CloudFront factory CDK pattern that updates 10+ CF distros (separate stacks) sequentially. It takes forever to push even simple changes. Therefore this would be a great improvement if we can parallelize cdk deploy.

In the meantime, I'm tempted to run cdk list and then simply fire off individual stacks. i.e. for stack in $(cdk list); do cdk deploy $stack --require-approval=never &; done;

Edit: I'll be exploring CDK pipelines to deploy in parallel.

@shivlaks shivlaks added the p1 label Aug 7, 2020
@laimonassutkus
Copy link

+1

We have over 200 stacks and deploying some of them in parallel would help us a lot.

@eladb
Copy link
Contributor

eladb commented Oct 1, 2020

We are not planning to support this in the foreseeable future. I would highly recommend looking into CDK pipelines to deploy multiple stacks in parallel.

@OperationalFallacy
Copy link

Is CDK pipelines a product or something? Or you’re saying creating a pipeline to deploy inparallel?

@skinny85
Copy link
Contributor

skinny85 commented Oct 1, 2020

I believe Elad was referring to this @OperationalFallacy : https://docs.aws.amazon.com/cdk/api/latest/docs/pipelines-readme.html

@OperationalFallacy
Copy link

Thanks @skinny85, that looks like something really cool, but I can't wrap my head around it.
Is there a blog post or other resources for it?

@skyrpex
Copy link
Contributor

skyrpex commented Oct 2, 2020

Thanks @skinny85, that looks like something really cool, but I can't wrap my head around it.
Is there a blog post or other resources for it?

Check this out: https://www.youtube.com/watch?v=774leNpQXo0

@robertd
Copy link
Contributor

robertd commented Oct 2, 2020

@hoegertn did a great overview of CDK Pipelines @ CDKDay https://youtu.be/qJutZqXMdgM?t=14852

@skinny85
Copy link
Contributor

skinny85 commented Oct 5, 2020

Thanks @skinny85, that looks like something really cool, but I can't wrap my head around it.
Is there a blog post or other resources for it?

Yep 🙂 https://aws.amazon.com/blogs/developer/cdk-pipelines-continuous-delivery-for-aws-cdk-applications

@micheal-hill
Copy link

It would be great to have official support for this. For now, we're using this work around:

  • Using the logic described here to build a graph of the stacks and what other stacks they depend upon. We output a json object that has the form [ { "stack": "stackName", "dependencies": [...stackNames] }, ...]
  • Using that json object, we dynamically generate a pipeline for our CI tool (in this case we're using Buildkite) with one step per stack. Steps can run in parallel provided that their dependencies have been run.
    • Stacks are deployed using -e flag to avoid dep stacks being redeployed.

In addition, this allows us to rerun individual stacks if necessary.

@rehanvdm
Copy link

It would be great to have official support for this. For now, we're using this work around:

* Using the logic described [here](https://stackoverflow.com/a/68434839/1733526) to build a graph of the stacks and what other stacks they depend upon. We output a json object that has the form `[ { "stack": "stackName", "dependencies": [...stackNames] }, ...]`

* Using that json object, we dynamically generate a pipeline for our CI tool (in this case we're using Buildkite) with one step per stack. Steps can run in parallel provided that their dependencies have been run.
  
  * Stacks are deployed using `-e` flag to avoid dep stacks being redeployed.

In addition, this allows us to rerun individual stacks if necessary.

Cool, I can see that logic paired with the Cloud Assembly logic I wrote in the blog to probably be an "automated" way of doing things. Currently, we manually keep track of stack dependencies as an extra precaution to prevent circular dependencies between stacks.

@lony
Copy link

lony commented Aug 12, 2021

@rehanvdm thanks for your answer, but I would like a more automatic approach inside the framework.

@bgshacklett
Copy link

@rehanvdm That's a useful write-up, and I expect that I may be putting that pattern into practice at some point in the not-too-distant future. Thank you for the contribution!

One downside about this implementation, however, is that using the --exclusive flag in this way results in losing some of the orchestration capabilities of CDK. It can be very useful to allow CDK to specify the ordering of deployments, as well as its ability to pull in dependency stacks automatically based on cross-stack references.

Without having knowledge of the implementation details under the hood, it seems that expending the cdk deploy command to enable parallel deployments, limited to pre-synthesized cloud assemblies, would retain the separation that @eladb described in the above post, while still allowing for faster deployments of large applications.

I'm also thinking more about this statement:

For context: the main reason we prefer that customers not use the CDK CLI for production deployments is due to a security risk.

Does this mean that there is a separate tool, other than cdk deploy which runs within CDK Pipelines to perform the actual deployment of cloud assemblies? If so, is this something that could, perhaps, be broken out as a discrete deployment tool which could be run within other pipeline solutions?

@hoegertn
Copy link
Contributor

Regarding your last question: CDK pipelines use the native CloudFormation Deploy action in CodePipeline. So you can use aws cloudformation deploy in any other CI/CD solution for similar behavior.

@bgshacklett
Copy link

That's enlightening. With that in mind, and the cloud assembly schema available, it may not be too difficult to create a MVP tool specifically for handling deployments within 3rd-party pipeline platforms.

@laimonassutkus
Copy link

laimonassutkus commented Sep 2, 2021

Just use: https://github.com/Biomapas/B.AwsCdkParallel 😅

@CarlosDomingues
Copy link

CarlosDomingues commented Dec 21, 2021

My team can't use @aws-cdk/pipelines as it's way too opinionated for our use cases.

At the same time, waiting for deployments is a huge time sink / innovation killer. Developing things for AWS (or any public cloud) is a slow, bureaucratic process, as things generally can't be tested locally.

My experience is that this is one of the main reasons devs like keeping things in code instead of using managed services.

Anything that could help people to iterate / test things quicker would bring a ton of value IMO.

@relm923
Copy link
Contributor

relm923 commented Mar 14, 2022

@nathanpeck would #19378 meet your needs here?

@relm923
Copy link
Contributor

relm923 commented Mar 29, 2022

@eladb I'm curious to hear your thoughts on #19378 as it adds CLI support for concurrent stack deployments while maintaining the ability to separate synth and deploy

@laimonassutkus
Copy link

@rix0rrr and @eladb please pay attention to this PR: #19378

@mergify mergify bot closed this as completed in #19378 May 5, 2022
mergify bot pushed a commit that referenced this issue May 5, 2022
Closes #1973

Add `--concurrency` parameter to `cdk deploy` command to enable concurrent deployments while respecting stack dependencies. Concurrency mode will only work with `--progress events` due to the poor interaction of concurrent deployments and the progress bar rendering.

### Open Questions
- [x] How best to write automated tests around this?
Added unit and integration tests
- [x] Should other commands (ex: `destroy`) support concurrency?
Only supporting deploy command in this PR
- [x] Any other concerns with this approach as it changes a key component of `cdk`
- [x] How should this work with the `--exclusively` flag?
Only check dependencies between requested stacks


Example output:
```sh
$ yarn cdk deploy --all --require-approval "never" --concurrency 3 --progress bar
yarn run v1.22.17
warning package.json: No license field
$ cdk deploy --all --require-approval never --concurrency 3 --progress bar

✨  Synthesis time: 16.04s

⚠️ The --concurrency flag only supports --progress "events". Switching to "events".
relm-test-1
relm-test-1: deploying...
relm-test-2: deploying...
relm-test-2: creating CloudFormation changeset...
relm-test-1: creating CloudFormation changeset...
relm-test-1 | 0/3 | 4:57:19 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 4:57:24 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 0/3 | 4:57:19 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2 User Initiated
relm-test-2 | 0/3 | 4:57:24 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2 User Initiated
relm-test-2 | 0/3 | 4:57:29 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 0/3 | 4:57:29 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) Resource creation Initiated
relm-test-1 | 0/3 | 4:57:32 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-1 | 1/3 | 4:57:33 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) Resource creation Initiated
relm-test-2 | 0/3 | 4:57:31 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-2 | 1/3 | 4:57:32 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2 | 2/3 | 4:57:41 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 3/3 | 4:57:43 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-2 
relm-test-1 | 2/3 | 4:57:41 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-1 | 3/3 | 4:57:43 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-1 

 ✅  relm-test-1

✨  Deployment time: 28.39s

Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-1/ffcdb210-a6fd-11ec-b05c-0a02909bf4fb

✨  Total time: 44.43s


 ✅  relm-test-2

✨  Deployment time: 28.45s

Outputs:
relm-test-2.ExportsOutputRefTempTopic9C0CBD7CC97C6BE5 = arn:aws:sns:us-east-1:XXXXXXXXXXXX:relm-test-2-TempTopic9C0CBD7C-2ETJWELY3MFD
Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-2/ffbc7400-a6fd-11ec-ac95-0ea201c9d581

✨  Total time: 44.49s

relm-test-2B
relm-test-2B: deploying...
relm-test-2B: creating CloudFormation changeset...
relm-test-2B | 0/4 | 4:57:47 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2B User Initiated
relm-test-2B | 0/4 | 4:57:58 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2B User Initiated
relm-test-2B | 0/4 | 4:58:04 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role     | TopicRole (TopicRole3526982D) 
relm-test-2B | 0/4 | 4:58:04 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2B | 0/4 | 4:58:05 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role     | TopicRole (TopicRole3526982D) Resource creation Initiated
relm-test-2B | 0/4 | 4:58:06 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-2B | 1/4 | 4:58:07 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2B | 2/4 | 4:58:19 PM | CREATE_COMPLETE      | AWS::IAM::Role     | TopicRole (TopicRole3526982D) 
relm-test-2B | 2/4 | 4:58:22 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) 
relm-test-2B | 2/4 | 4:58:23 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) Resource creation Initiated
relm-test-2B | 3/4 | 4:58:36 PM | CREATE_COMPLETE      | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) 
relm-test-2B | 4/4 | 4:58:37 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-2B 

 ✅  relm-test-2B

✨  Deployment time: 54.71s

Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-2B/10b341d0-a6fe-11ec-a535-12d49b16bf9b

✨  Total time: 70.75s


✨  Done in 99.79s.
```

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@github-actions
Copy link

github-actions bot commented May 5, 2022

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

wphilipw pushed a commit to wphilipw/aws-cdk that referenced this issue May 23, 2022
Closes aws#1973

Add `--concurrency` parameter to `cdk deploy` command to enable concurrent deployments while respecting stack dependencies. Concurrency mode will only work with `--progress events` due to the poor interaction of concurrent deployments and the progress bar rendering.

### Open Questions
- [x] How best to write automated tests around this?
Added unit and integration tests
- [x] Should other commands (ex: `destroy`) support concurrency?
Only supporting deploy command in this PR
- [x] Any other concerns with this approach as it changes a key component of `cdk`
- [x] How should this work with the `--exclusively` flag?
Only check dependencies between requested stacks


Example output:
```sh
$ yarn cdk deploy --all --require-approval "never" --concurrency 3 --progress bar
yarn run v1.22.17
warning package.json: No license field
$ cdk deploy --all --require-approval never --concurrency 3 --progress bar

✨  Synthesis time: 16.04s

⚠️ The --concurrency flag only supports --progress "events". Switching to "events".
relm-test-1
relm-test-1: deploying...
relm-test-2: deploying...
relm-test-2: creating CloudFormation changeset...
relm-test-1: creating CloudFormation changeset...
relm-test-1 | 0/3 | 4:57:19 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 4:57:24 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 0/3 | 4:57:19 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2 User Initiated
relm-test-2 | 0/3 | 4:57:24 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2 User Initiated
relm-test-2 | 0/3 | 4:57:29 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 0/3 | 4:57:29 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) Resource creation Initiated
relm-test-1 | 0/3 | 4:57:32 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-1 | 1/3 | 4:57:33 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) Resource creation Initiated
relm-test-2 | 0/3 | 4:57:31 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-2 | 1/3 | 4:57:32 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2 | 2/3 | 4:57:41 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 3/3 | 4:57:43 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-2 
relm-test-1 | 2/3 | 4:57:41 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-1 | 3/3 | 4:57:43 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-1 

 ✅  relm-test-1

✨  Deployment time: 28.39s

Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-1/ffcdb210-a6fd-11ec-b05c-0a02909bf4fb

✨  Total time: 44.43s


 ✅  relm-test-2

✨  Deployment time: 28.45s

Outputs:
relm-test-2.ExportsOutputRefTempTopic9C0CBD7CC97C6BE5 = arn:aws:sns:us-east-1:XXXXXXXXXXXX:relm-test-2-TempTopic9C0CBD7C-2ETJWELY3MFD
Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-2/ffbc7400-a6fd-11ec-ac95-0ea201c9d581

✨  Total time: 44.49s

relm-test-2B
relm-test-2B: deploying...
relm-test-2B: creating CloudFormation changeset...
relm-test-2B | 0/4 | 4:57:47 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2B User Initiated
relm-test-2B | 0/4 | 4:57:58 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2B User Initiated
relm-test-2B | 0/4 | 4:58:04 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role     | TopicRole (TopicRole3526982D) 
relm-test-2B | 0/4 | 4:58:04 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2B | 0/4 | 4:58:05 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role     | TopicRole (TopicRole3526982D) Resource creation Initiated
relm-test-2B | 0/4 | 4:58:06 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-2B | 1/4 | 4:58:07 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2B | 2/4 | 4:58:19 PM | CREATE_COMPLETE      | AWS::IAM::Role     | TopicRole (TopicRole3526982D) 
relm-test-2B | 2/4 | 4:58:22 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) 
relm-test-2B | 2/4 | 4:58:23 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) Resource creation Initiated
relm-test-2B | 3/4 | 4:58:36 PM | CREATE_COMPLETE      | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) 
relm-test-2B | 4/4 | 4:58:37 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-2B 

 ✅  relm-test-2B

✨  Deployment time: 54.71s

Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-2B/10b341d0-a6fe-11ec-a535-12d49b16bf9b

✨  Total time: 70.75s


✨  Done in 99.79s.
```

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@BDeus
Copy link
Contributor

BDeus commented Jun 3, 2022

please @rix0rrr @kaizencc, can you review this #20345?
Really want to test this feature to reduce deploy time.
Thanks

@skinny85
Copy link
Contributor

skinny85 commented Jun 4, 2022

@BDeus #19378 has been merged since May 5 🙂.

@rittneje
Copy link

rittneje commented Jun 4, 2022

@skinny85 It was immediately reverted in #20230. The new PR is #20345. Probably this issue should be reopened.

@rix0rrr
Copy link
Contributor

rix0rrr commented Jun 22, 2022

Had to revert the previous PR, re-opening as this issue has not been solved yet.

@rix0rrr rix0rrr reopened this Jun 22, 2022
@mergify mergify bot closed this as completed in #20345 Aug 10, 2022
mergify bot pushed a commit that referenced this issue Aug 10, 2022
Closes #1973 (reattempting #19378)

Add `--concurrency` parameter to `cdk deploy` command to enable concurrent deployments while respecting stack dependencies. Concurrency mode will only work with `--progress events` due to the poor interaction of concurrent deployments and the progress bar rendering.

### Open Questions
- [x] How best to write automated tests around this?
Added unit and integration tests
- [x] Should other commands (ex: `destroy`) support concurrency?
Only supporting deploy command in this PR
- [x] Any other concerns with this approach as it changes a key component of `cdk`
- [x] How should this work with the `--exclusively` flag?
Only check dependencies between requested stacks

<details>
  <summary>Example Output (Success):</summary>
  <pre>
$ yarn cdk deploy --all --require-approval "never" --concurrency 3 --progress bar
yarn run v1.22.17
warning package.json: No license field
$ cdk deploy --all --require-approval never --concurrency 3 --progress bar

✨  Synthesis time: 16.04s

⚠️ The --concurrency flag only supports --progress "events". Switching to "events".
relm-test-1
relm-test-1: deploying...
relm-test-2: deploying...
relm-test-2: creating CloudFormation changeset...
relm-test-1: creating CloudFormation changeset...
relm-test-1 | 0/3 | 4:57:19 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 4:57:24 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 0/3 | 4:57:19 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2 User Initiated
relm-test-2 | 0/3 | 4:57:24 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2 User Initiated
relm-test-2 | 0/3 | 4:57:29 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 0/3 | 4:57:29 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) Resource creation Initiated
relm-test-1 | 0/3 | 4:57:32 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-1 | 1/3 | 4:57:33 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) Resource creation Initiated
relm-test-2 | 0/3 | 4:57:31 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-2 | 1/3 | 4:57:32 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2 | 2/3 | 4:57:41 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 3/3 | 4:57:43 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-2 
relm-test-1 | 2/3 | 4:57:41 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-1 | 3/3 | 4:57:43 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-1 

✅  relm-test-1

✨  Deployment time: 28.39s

Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-1/ffcdb210-a6fd-11ec-b05c-0a02909bf4fb

✨  Total time: 44.43s


✅  relm-test-2

✨  Deployment time: 28.45s

Outputs:
relm-test-2.ExportsOutputRefTempTopic9C0CBD7CC97C6BE5 = arn:aws:sns:us-east-1:XXXXXXXXXXXX:relm-test-2-TempTopic9C0CBD7C-2ETJWELY3MFD
Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-2/ffbc7400-a6fd-11ec-ac95-0ea201c9d581

✨  Total time: 44.49s

relm-test-2B
relm-test-2B: deploying...
relm-test-2B: creating CloudFormation changeset...
relm-test-2B | 0/4 | 4:57:47 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2B User Initiated
relm-test-2B | 0/4 | 4:57:58 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2B User Initiated
relm-test-2B | 0/4 | 4:58:04 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role     | TopicRole (TopicRole3526982D) 
relm-test-2B | 0/4 | 4:58:04 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2B | 0/4 | 4:58:05 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role     | TopicRole (TopicRole3526982D) Resource creation Initiated
relm-test-2B | 0/4 | 4:58:06 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-2B | 1/4 | 4:58:07 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2B | 2/4 | 4:58:19 PM | CREATE_COMPLETE      | AWS::IAM::Role     | TopicRole (TopicRole3526982D) 
relm-test-2B | 2/4 | 4:58:22 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) 
relm-test-2B | 2/4 | 4:58:23 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) Resource creation Initiated
relm-test-2B | 3/4 | 4:58:36 PM | CREATE_COMPLETE      | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) 
relm-test-2B | 4/4 | 4:58:37 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-2B 

✅  relm-test-2B

✨  Deployment time: 54.71s

Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-2B/10b341d0-a6fe-11ec-a535-12d49b16bf9b

✨  Total time: 70.75s


✨  Done in 99.79s.
  </pre>
</details>

<details>
  <summary>Example Output (Failure):</summary>
  <pre>
yarn run v1.22.18
warning package.json: No license field
$ cdk deploy --all --require-approval never --concurrency 3 --progress bar

✨  Synthesis time: 16.18s

⚠️ The --concurrency flag only supports --progress "events". Switching to "events".
relm-broken-1
relm-broken-1: deploying...
relm-broken-2
relm-broken-2: deploying...
relm-test-1: deploying...
relm-test-1: creating CloudFormation changeset...
relm-broken-1: creating CloudFormation changeset...
relm-broken-2: creating CloudFormation changeset...
relm-broken-2 | 0/3 | 9:12:48 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-broken-2 User Initiated
relm-broken-2 | 0/3 | 9:12:53 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-broken-2 User Initiated
relm-broken-1 | 0/3 | 9:12:48 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-broken-1 User Initiated
relm-broken-1 | 0/3 | 9:12:53 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-broken-1 User Initiated
relm-test-1 | 0/3 | 9:12:48 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 9:12:54 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 9:12:59 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 
relm-test-1 | 0/3 | 9:12:59 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-1 | 0/3 | 9:13:00 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) Resource creation Initiated
relm-test-1 | 0/3 | 9:13:01 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-1 | 1/3 | 9:13:02 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-broken-2 | 0/3 | 9:12:59 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 
relm-broken-2 | 0/3 | 9:12:59 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-broken-2 | 0/3 | 9:13:00 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) Resource creation Initiated
relm-broken-2 | 0/3 | 9:13:02 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-broken-2 | 1/3 | 9:13:02 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-broken-1 | 0/3 | 9:13:04 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-broken-1 | 0/3 | 9:13:04 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 
relm-broken-1 | 0/3 | 9:13:04 PM | CREATE_FAILED        | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) TestTopic already exists in stack arn:aws:cloudformation:us-east-1:__ACCOUNT_ID__:stack/relm-broken-2/79fc1770-cc10-11ec-8279-0a02b75d1237
        new Topic (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/aws-sns/lib/topic.ts:102:22)
        \_ new BrokenStack (/Users/relm/Development/aws-cdk-test-stack/lib/broken-stack.ts:11:18)
        \_ Object.<anonymous> (/Users/relm/Development/aws-cdk-test-stack/bin/aws-cdk-test-stack.ts:12:1)
        \_ Module._compile (node:internal/modules/cjs/loader:1103:14)
        \_ Module.m._compile (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/index.ts:1455:23)
        \_ Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
        \_ Object.require.extensions.<computed> [as .ts] (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/index.ts:1458:12)
        \_ Module.load (node:internal/modules/cjs/loader:981:32)
        \_ Function.Module._load (node:internal/modules/cjs/loader:822:12)
        \_ Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
        \_ phase4 (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:567:12)
        \_ bootstrap (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:85:10)
        \_ main (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:54:10)
        \_ Object.<anonymous> (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:717:3)
        \_ Module._compile (node:internal/modules/cjs/loader:1103:14)
        \_ Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
        \_ Module.load (node:internal/modules/cjs/loader:981:32)
        \_ Function.Module._load (node:internal/modules/cjs/loader:822:12)
        \_ Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
        \_ node:internal/main/run_main_module:17:47
relm-broken-1 | 0/3 | 9:13:05 PM | CREATE_FAILED        | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation cancelled
        new MetadataResource (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/metadata-resource.ts:22:24)
        \_ /Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/synthesis.ts:166:5
        \_ visit (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/synthesis.ts:231:5)
        \_ visit (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/synthesis.ts:227:5)
        \_ injectMetadataResources (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/synthesis.ts:157:3)
        \_ Object.synthesize (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/synthesis.ts:18:3)
        \_ App.synth (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/stage.ts:180:23)
        \_ process.<anonymous> (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/app.ts:131:45)
        \_ Object.onceWrapper (node:events:646:26)
        \_ process.emit (node:events:526:28)
        \_ process.emit (node:domain:475:12)
        \_ process.emit.sharedData.processEmitHook.installedValue [as emit] (/Users/relm/Development/aws-cdk-test-stack/node_modules/@cspotcode/source-map-support/source-map-support.js:613:40)
relm-broken-1 | 0/3 | 9:13:06 PM | ROLLBACK_IN_PROGRESS | AWS::CloudFormation::Stack | relm-broken-1 The following resource(s) failed to create: [TestTopic339EC197, CDKMetadata]. Rollback requested by user.
relm-broken-1 | 1/3 | 9:13:10 PM | DELETE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-broken-1 | 2/3 | 9:13:10 PM | DELETE_COMPLETE      | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 
relm-broken-1 | 3/3 | 9:13:11 PM | ROLLBACK_COMPLETE    | AWS::CloudFormation::Stack | relm-broken-1 
relm-broken-2 | 2/3 | 9:13:11 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 
relm-broken-2 | 3/3 | 9:13:12 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-broken-2 
relm-test-1 | 2/3 | 9:13:10 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 

Failed resources:
relm-broken-1 | 9:13:04 PM | CREATE_FAILED        | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) TestTopic already exists in stack arn:aws:cloudformation:us-east-1:__ACCOUNT_ID__:stack/relm-broken-2/79fc1770-cc10-11ec-8279-0a02b75d1237
        new Topic (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/aws-sns/lib/topic.ts:102:22)
        \_ new BrokenStack (/Users/relm/Development/aws-cdk-test-stack/lib/broken-stack.ts:11:18)
        \_ Object.<anonymous> (/Users/relm/Development/aws-cdk-test-stack/bin/aws-cdk-test-stack.ts:12:1)
        \_ Module._compile (node:internal/modules/cjs/loader:1103:14)
        \_ Module.m._compile (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/index.ts:1455:23)
        \_ Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
        \_ Object.require.extensions.<computed> [as .ts] (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/index.ts:1458:12)
        \_ Module.load (node:internal/modules/cjs/loader:981:32)
        \_ Function.Module._load (node:internal/modules/cjs/loader:822:12)
        \_ Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
        \_ phase4 (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:567:12)
        \_ bootstrap (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:85:10)
        \_ main (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:54:10)
        \_ Object.<anonymous> (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:717:3)
        \_ Module._compile (node:internal/modules/cjs/loader:1103:14)
        \_ Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
        \_ Module.load (node:internal/modules/cjs/loader:981:32)
        \_ Function.Module._load (node:internal/modules/cjs/loader:822:12)
        \_ Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
        \_ node:internal/main/run_main_module:17:47

❌  relm-broken-1 failed: Error: The stack named relm-broken-1 failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE
    at Object.waitForStackDeploy (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/api/util/cloudformation.ts:307:11)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at prepareAndExecuteChangeSet (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/api/deploy-stack.ts:355:26)
    at deployStack (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/cdk-toolkit.ts:229:24)
    at /Users/relm/Development/aws-cdk/packages/aws-cdk/lib/cdk-toolkit.ts:306:13
    at run (/Users/relm/Development/aws-cdk/node_modules/p-queue/dist/index.js:163:29)

/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/api/util/cloudformation.ts:307
    throw new Error(`The stack named ${stackName} failed creation, it may need to be manually deleted from the AWS console: ${status}`);
          ^
Error: The stack named relm-broken-1 failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE
    at Object.waitForStackDeploy (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/api/util/cloudformation.ts:307:11)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at prepareAndExecuteChangeSet (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/api/deploy-stack.ts:355:26)
    at deployStack (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/cdk-toolkit.ts:229:24)
    at /Users/relm/Development/aws-cdk/packages/aws-cdk/lib/cdk-toolkit.ts:306:13
    at run (/Users/relm/Development/aws-cdk/node_modules/p-queue/dist/index.js:163:29)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
  </pre>
</details>

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@github-actions
Copy link

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

@rittneje
Copy link

@rix0rrr Please re-open this issue since the PR got reverted again in #21664.

@BDeus
Copy link
Contributor

BDeus commented Aug 25, 2022

@rix0rrr Please re-open this issue since the PR got reverted again in #21664.

the endless story

@valmaev
Copy link

valmaev commented Aug 25, 2022

the endless story

Hopefully, not: #21681 🤞

josephedward pushed a commit to josephedward/aws-cdk that referenced this issue Aug 30, 2022
Closes aws#1973 (reattempting aws#19378)

Add `--concurrency` parameter to `cdk deploy` command to enable concurrent deployments while respecting stack dependencies. Concurrency mode will only work with `--progress events` due to the poor interaction of concurrent deployments and the progress bar rendering.

### Open Questions
- [x] How best to write automated tests around this?
Added unit and integration tests
- [x] Should other commands (ex: `destroy`) support concurrency?
Only supporting deploy command in this PR
- [x] Any other concerns with this approach as it changes a key component of `cdk`
- [x] How should this work with the `--exclusively` flag?
Only check dependencies between requested stacks

<details>
  <summary>Example Output (Success):</summary>
  <pre>
$ yarn cdk deploy --all --require-approval "never" --concurrency 3 --progress bar
yarn run v1.22.17
warning package.json: No license field
$ cdk deploy --all --require-approval never --concurrency 3 --progress bar

✨  Synthesis time: 16.04s

⚠️ The --concurrency flag only supports --progress "events". Switching to "events".
relm-test-1
relm-test-1: deploying...
relm-test-2: deploying...
relm-test-2: creating CloudFormation changeset...
relm-test-1: creating CloudFormation changeset...
relm-test-1 | 0/3 | 4:57:19 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 4:57:24 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 0/3 | 4:57:19 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2 User Initiated
relm-test-2 | 0/3 | 4:57:24 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2 User Initiated
relm-test-2 | 0/3 | 4:57:29 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 0/3 | 4:57:29 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-1 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) Resource creation Initiated
relm-test-1 | 0/3 | 4:57:32 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-1 | 1/3 | 4:57:33 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2 | 0/3 | 4:57:30 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) Resource creation Initiated
relm-test-2 | 0/3 | 4:57:31 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-2 | 1/3 | 4:57:32 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2 | 2/3 | 4:57:41 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-2 | 3/3 | 4:57:43 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-2 
relm-test-1 | 2/3 | 4:57:41 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TempTopic (TempTopic9C0CBD7C) 
relm-test-1 | 3/3 | 4:57:43 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-1 

✅  relm-test-1

✨  Deployment time: 28.39s

Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-1/ffcdb210-a6fd-11ec-b05c-0a02909bf4fb

✨  Total time: 44.43s


✅  relm-test-2

✨  Deployment time: 28.45s

Outputs:
relm-test-2.ExportsOutputRefTempTopic9C0CBD7CC97C6BE5 = arn:aws:sns:us-east-1:XXXXXXXXXXXX:relm-test-2-TempTopic9C0CBD7C-2ETJWELY3MFD
Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-2/ffbc7400-a6fd-11ec-ac95-0ea201c9d581

✨  Total time: 44.49s

relm-test-2B
relm-test-2B: deploying...
relm-test-2B: creating CloudFormation changeset...
relm-test-2B | 0/4 | 4:57:47 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2B User Initiated
relm-test-2B | 0/4 | 4:57:58 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-2B User Initiated
relm-test-2B | 0/4 | 4:58:04 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role     | TopicRole (TopicRole3526982D) 
relm-test-2B | 0/4 | 4:58:04 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2B | 0/4 | 4:58:05 PM | CREATE_IN_PROGRESS   | AWS::IAM::Role     | TopicRole (TopicRole3526982D) Resource creation Initiated
relm-test-2B | 0/4 | 4:58:06 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-2B | 1/4 | 4:58:07 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-2B | 2/4 | 4:58:19 PM | CREATE_COMPLETE      | AWS::IAM::Role     | TopicRole (TopicRole3526982D) 
relm-test-2B | 2/4 | 4:58:22 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) 
relm-test-2B | 2/4 | 4:58:23 PM | CREATE_IN_PROGRESS   | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) Resource creation Initiated
relm-test-2B | 3/4 | 4:58:36 PM | CREATE_COMPLETE      | AWS::IAM::Policy   | TopicRole/DefaultPolicy (TopicRoleDefaultPolicy489E2B68) 
relm-test-2B | 4/4 | 4:58:37 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-test-2B 

✅  relm-test-2B

✨  Deployment time: 54.71s

Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXXXX:stack/relm-test-2B/10b341d0-a6fe-11ec-a535-12d49b16bf9b

✨  Total time: 70.75s


✨  Done in 99.79s.
  </pre>
</details>

<details>
  <summary>Example Output (Failure):</summary>
  <pre>
yarn run v1.22.18
warning package.json: No license field
$ cdk deploy --all --require-approval never --concurrency 3 --progress bar

✨  Synthesis time: 16.18s

⚠️ The --concurrency flag only supports --progress "events". Switching to "events".
relm-broken-1
relm-broken-1: deploying...
relm-broken-2
relm-broken-2: deploying...
relm-test-1: deploying...
relm-test-1: creating CloudFormation changeset...
relm-broken-1: creating CloudFormation changeset...
relm-broken-2: creating CloudFormation changeset...
relm-broken-2 | 0/3 | 9:12:48 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-broken-2 User Initiated
relm-broken-2 | 0/3 | 9:12:53 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-broken-2 User Initiated
relm-broken-1 | 0/3 | 9:12:48 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-broken-1 User Initiated
relm-broken-1 | 0/3 | 9:12:53 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-broken-1 User Initiated
relm-test-1 | 0/3 | 9:12:48 PM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 9:12:54 PM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | relm-test-1 User Initiated
relm-test-1 | 0/3 | 9:12:59 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 
relm-test-1 | 0/3 | 9:12:59 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-test-1 | 0/3 | 9:13:00 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) Resource creation Initiated
relm-test-1 | 0/3 | 9:13:01 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-test-1 | 1/3 | 9:13:02 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-broken-2 | 0/3 | 9:12:59 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 
relm-broken-2 | 0/3 | 9:12:59 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-broken-2 | 0/3 | 9:13:00 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) Resource creation Initiated
relm-broken-2 | 0/3 | 9:13:02 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
relm-broken-2 | 1/3 | 9:13:02 PM | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-broken-1 | 0/3 | 9:13:04 PM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-broken-1 | 0/3 | 9:13:04 PM | CREATE_IN_PROGRESS   | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 
relm-broken-1 | 0/3 | 9:13:04 PM | CREATE_FAILED        | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) TestTopic already exists in stack arn:aws:cloudformation:us-east-1:__ACCOUNT_ID__:stack/relm-broken-2/79fc1770-cc10-11ec-8279-0a02b75d1237
        new Topic (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/aws-sns/lib/topic.ts:102:22)
        \_ new BrokenStack (/Users/relm/Development/aws-cdk-test-stack/lib/broken-stack.ts:11:18)
        \_ Object.<anonymous> (/Users/relm/Development/aws-cdk-test-stack/bin/aws-cdk-test-stack.ts:12:1)
        \_ Module._compile (node:internal/modules/cjs/loader:1103:14)
        \_ Module.m._compile (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/index.ts:1455:23)
        \_ Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
        \_ Object.require.extensions.<computed> [as .ts] (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/index.ts:1458:12)
        \_ Module.load (node:internal/modules/cjs/loader:981:32)
        \_ Function.Module._load (node:internal/modules/cjs/loader:822:12)
        \_ Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
        \_ phase4 (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:567:12)
        \_ bootstrap (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:85:10)
        \_ main (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:54:10)
        \_ Object.<anonymous> (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:717:3)
        \_ Module._compile (node:internal/modules/cjs/loader:1103:14)
        \_ Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
        \_ Module.load (node:internal/modules/cjs/loader:981:32)
        \_ Function.Module._load (node:internal/modules/cjs/loader:822:12)
        \_ Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
        \_ node:internal/main/run_main_module:17:47
relm-broken-1 | 0/3 | 9:13:05 PM | CREATE_FAILED        | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation cancelled
        new MetadataResource (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/metadata-resource.ts:22:24)
        \_ /Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/synthesis.ts:166:5
        \_ visit (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/synthesis.ts:231:5)
        \_ visit (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/synthesis.ts:227:5)
        \_ injectMetadataResources (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/synthesis.ts:157:3)
        \_ Object.synthesize (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/private/synthesis.ts:18:3)
        \_ App.synth (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/stage.ts:180:23)
        \_ process.<anonymous> (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/core/lib/app.ts:131:45)
        \_ Object.onceWrapper (node:events:646:26)
        \_ process.emit (node:events:526:28)
        \_ process.emit (node:domain:475:12)
        \_ process.emit.sharedData.processEmitHook.installedValue [as emit] (/Users/relm/Development/aws-cdk-test-stack/node_modules/@cspotcode/source-map-support/source-map-support.js:613:40)
relm-broken-1 | 0/3 | 9:13:06 PM | ROLLBACK_IN_PROGRESS | AWS::CloudFormation::Stack | relm-broken-1 The following resource(s) failed to create: [TestTopic339EC197, CDKMetadata]. Rollback requested by user.
relm-broken-1 | 1/3 | 9:13:10 PM | DELETE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) 
relm-broken-1 | 2/3 | 9:13:10 PM | DELETE_COMPLETE      | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 
relm-broken-1 | 3/3 | 9:13:11 PM | ROLLBACK_COMPLETE    | AWS::CloudFormation::Stack | relm-broken-1 
relm-broken-2 | 2/3 | 9:13:11 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 
relm-broken-2 | 3/3 | 9:13:12 PM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | relm-broken-2 
relm-test-1 | 2/3 | 9:13:10 PM | CREATE_COMPLETE      | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) 

Failed resources:
relm-broken-1 | 9:13:04 PM | CREATE_FAILED        | AWS::SNS::Topic    | TestTopic (TestTopic339EC197) TestTopic already exists in stack arn:aws:cloudformation:us-east-1:__ACCOUNT_ID__:stack/relm-broken-2/79fc1770-cc10-11ec-8279-0a02b75d1237
        new Topic (/Users/relm/Development/aws-cdk/packages/aws-cdk-lib/aws-sns/lib/topic.ts:102:22)
        \_ new BrokenStack (/Users/relm/Development/aws-cdk-test-stack/lib/broken-stack.ts:11:18)
        \_ Object.<anonymous> (/Users/relm/Development/aws-cdk-test-stack/bin/aws-cdk-test-stack.ts:12:1)
        \_ Module._compile (node:internal/modules/cjs/loader:1103:14)
        \_ Module.m._compile (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/index.ts:1455:23)
        \_ Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
        \_ Object.require.extensions.<computed> [as .ts] (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/index.ts:1458:12)
        \_ Module.load (node:internal/modules/cjs/loader:981:32)
        \_ Function.Module._load (node:internal/modules/cjs/loader:822:12)
        \_ Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
        \_ phase4 (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:567:12)
        \_ bootstrap (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:85:10)
        \_ main (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:54:10)
        \_ Object.<anonymous> (/Users/relm/Development/aws-cdk-test-stack/node_modules/ts-node/src/bin.ts:717:3)
        \_ Module._compile (node:internal/modules/cjs/loader:1103:14)
        \_ Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
        \_ Module.load (node:internal/modules/cjs/loader:981:32)
        \_ Function.Module._load (node:internal/modules/cjs/loader:822:12)
        \_ Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
        \_ node:internal/main/run_main_module:17:47

❌  relm-broken-1 failed: Error: The stack named relm-broken-1 failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE
    at Object.waitForStackDeploy (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/api/util/cloudformation.ts:307:11)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at prepareAndExecuteChangeSet (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/api/deploy-stack.ts:355:26)
    at deployStack (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/cdk-toolkit.ts:229:24)
    at /Users/relm/Development/aws-cdk/packages/aws-cdk/lib/cdk-toolkit.ts:306:13
    at run (/Users/relm/Development/aws-cdk/node_modules/p-queue/dist/index.js:163:29)

/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/api/util/cloudformation.ts:307
    throw new Error(`The stack named ${stackName} failed creation, it may need to be manually deleted from the AWS console: ${status}`);
          ^
Error: The stack named relm-broken-1 failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE
    at Object.waitForStackDeploy (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/api/util/cloudformation.ts:307:11)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at prepareAndExecuteChangeSet (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/api/deploy-stack.ts:355:26)
    at deployStack (/Users/relm/Development/aws-cdk/packages/aws-cdk/lib/cdk-toolkit.ts:229:24)
    at /Users/relm/Development/aws-cdk/packages/aws-cdk/lib/cdk-toolkit.ts:306:13
    at run (/Users/relm/Development/aws-cdk/node_modules/p-queue/dist/index.js:163:29)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
  </pre>
</details>

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p1 package/tools Related to AWS CDK Tools or CLI
Projects
None yet
Development

Successfully merging a pull request may close this issue.