4.8 KiB
Nested Assemblies
For the CI/CD project we need to be able to a final, authoritative, immutable rendition of part of the construct tree. This is a part of the application that we can ask the CI/CD system to deploy as a unit, and have it get a fighting chance of getting it right. This is because:
- The stacks will be known.
- Their interdependencies will be known, and won't change anymore.
To that end, we're introducing the concept of an "nested cloud assembly". This is a part of the construct tree that is finalized independently of the rest, so that other constructs can reflect on it.
Constructs of type Stage will produce nested cloud assemblies.
Restrictions
Assets
Right now, if the same asset is used in multiple cloud assemblies, it will be staged independently in ever Cloud Assembly (making it take up more space than necessary).
This is unfortunate. We can think about sharing the staging directories between Stages, should be an easy optimization that can be applied later.
Dependencies
It seems that it might be desirable to have dependencies that reach outside
a single Stage. Consider the case where we have shared resources that
may be shared between Stages. A typical example would be a VPC:
┌───────────────┐
│ │
│ VpcStack │
│ │
└───────────────┘
▲
│
│
┌─────────────┴─────────────┐
│ │
┌───────────────┼──────────┐ ┌──────────┼───────────────┐
│Stage │ │ │ │ Stage│
│ │ │ │ │ │
│ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ │ │ │ │ │ │
│ │ App1Stack │ │ │ │ App2Stack │ │
│ │ │ │ │ │ │ │
│ └───────────────┘ │ │ └───────────────┘ │
│ │ │ │
└──────────────────────────┘ └──────────────────────────┘
This seems like a reasonable thing to want to be able to do.
Right now, for practical reasons we're disallowing dependencies outside nested assemblies. That is not to say that this can never be made to work, but as it's really rather a significant chunk of work it has not been implemented yet. Things to consider:
- Do artifact identifiers need to be globally unique? (Does that destroy local assumptions around naming that constructs can make?)
- How are artifacts addressed across assembly boundaries? Are they just the
absolute name, wherever in the Cloud Assembly tree the artifact is? Do they
represent a path from the top-level cloud assembly
(
SubAsm/SubAsm/Artifact)? Are they relative paths (../SubAsm/Artifact)? - Can there be cyclic dependencies between nested assemblies? Is it okay to
have both dependencies
AsmA/Stack1 -> AsmB/Stack1, andAsmB/Stack2 -> AsmA/Stack2? Why, or why not? How will we ensure that?
Even if we can make the addressing work at the artifact level, at the
construct tree level we'd be giving up the guarantees we are getting from
having Stage constructs produce isolated Cloud Assemblies by having
dependencies outside them. Consider having two stages, StageA with StackA
and StageB with StackB. We must synth() them in some order, either A or
B first. Let's say A goes first (but the same argument obviously holds in
reverse). What if during the synth() of StageB, we discover StackB
introduces a dependency on StackA? By that point, StageA has already
synthesized and StackA has produced a (so-called "immutable") template.
Obviously we can't change that anymore, so we can't introduce that dependency
anymore.
Seems like we should be calling synth() on multiple stages consumer-first!
The problem is that we are generally building a Pipeline producer-first, since
we are modeling and building it in deployment order, which is the reverse order
the pipeline would synth() each of the stages in, in order to build itself.
Since this is all very tricky, let's consider it out of scope for now.