4
votes

Would it be possible to have two CDK Apps in the same project, something like this:

from aws_cdk import core

from stack1 import Stack1
from stack2 import Stack2

app1 = core.App()
Stack1(app1, "CDK1")
app1.synth()

app2 = core.App()
Stack2(app2, "CDK2")
app2.synth()

And deploy them? Synchronously/Asynchronously?

Would it be possible to reference some resources from one app in the other one?

2

2 Answers

4
votes

Yes you can have multiple applications in a CDK project, but there are some serious caveats.

  1. A CDK process can only synth/deploy one app at a time.

  2. They cannot be defined in the same file.

  3. They cannot directly reference each other's resources.

To put this in perspective, each app is functionally isolated from each other and it is roughly equivalent to having two separate CDK projects just sharing the same codebase, so the use cases for this are limited.

The only way for them to share resources is either to extract it to an additional common app that must be deployed first, or for you to store the ARN of that resource in something (e.g., Parameter Store), and load it at run time. You cannot assume that the resource will exist as one of the apps may not have been deployed yet, and if you import the resource into your Stack directly, you've defeated the whole point of splitting them apart.

That is to say, this is ok:

stack1.lambda:

    from ssm_parameter_store import SSMParameterStore

    store = SSMParameterStore(prefix='/Prod')
    ssn_arn = store['stack2.sns']
    if !ssn_arn
        // Doesn't matter
        return
    try:
        sns.publish(ssn_arn, 'something')
    except:
        // Doesn't matter

But if it's critical to stack1 that a resource from stack2 exists, or you want to import a stack2 resource into stack1, then you either need to do a third split of all the common resources: common-resources.app.py, or there's no point splitting them.


We do this a lot in our projects, with one app creating a CodePipeline that automatically deploys the other app. However, we only do this because we prefer the pipeline lives next to the code it is deploying and it would be equally valid to extract it into an entirely new project.


If you want to do this, you need to do:

app1.py:

from aws_cdk import core

from stack1 import Stack1

app1 = core.App()
Stack1(app1, "CDK1")
app1.synth()

app2.py:

from aws_cdk import core

from stack2 import Stack2

app2 = core.App()
Stack2(app2, "CDK2")
app2.synth()

You then deploy this by running in parallel or sequentially:

  • cdk deploy --app "python app1.py"
  • cdk deploy --app "python app2.py"
2
votes

Having re-read your question, the short answer is no. In testing this, I found that CDK would only create the second app defined.

You can, however, deploy multiple-stack applications:

https://docs.aws.amazon.com/cdk/latest/guide/stack_how_to_create_multiple_stacks.html

It's also possible to reference resources from one stack in another, by using core.CfnOutput and core.Fn.importValue:

https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.core/CfnOutput.html https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.core/Fn.html

Under the hood, this uses CloudFormation's ability to export outputs and import them in other stacks. Effectively your multiple stack CDK app will create nested CloudFormation stacks.

In terms of deployments, CDK creates a CloudFormation change set and deploys it, so all changes will be deployed on cdk deploy. From your perspective, it'll be synchronous, but there may be some asynchronous API calls happening under the hood through CloudFormation.