RFC 52: Support for importing existing resources into a CDK stack#392
Conversation
3afafaa to
3aee196
Compare
rix0rrr
left a comment
There was a problem hiding this comment.
I love this! Thanks for your thoroughness here!
| being created). Furthermore, CDK can't automatically determine what | ||
| resources to import and what to create. For this to behave correctly, the | ||
| solution will prompt user for each resource - whether it should be imported | ||
| or not. If not, the resource is removed from the template before creating |
There was a problem hiding this comment.
Just thinking: the other way around might be easier.
Why don't we download the current template from the Stack, and then add the resources we're trying to import? Seems safer than dropping resources from the target template.
So the workflow looks a bit like:
- Take the new template, identify candidate resources to import by looking at
cdk diff - Obtain the import map by a combination of heuristics and user input. Include the resource definitions of the resources in the import map
Then:
- Download the old template
- Add the resources from the previous step to the template
- (Potentially: check the integrity of the template)
- Do an IMPORT update with the import map
There was a problem hiding this comment.
I wonder what we're going to do about dependencies on non-imported resources here... but I also don't have a good intuition for where and how those are going to crop up. I guess the best path forward is roll this feature out and seeing where it's going to creak 😅
There was a problem hiding this comment.
Yes, I am happy to revert the logic here, although it should produce exactly the same template, as:
- we already download the current template and perform the diff
- for any modification (besides CDKMetadata that we copy over) we fail so non-addition difference will never get to the import action
- for any newly defined resource, we decide whether it is going to be imported (we keep it) or not (we remove it) ... which would be the same other way around: if it's going to be imported we add it, otherwise we skip it
But now thinking about it, the above applies only to the Resources section of the template. I will double-check what if Parameters or Outputs change - this can add some more complexity. Imagine a resource properties of a resource-to-be-imported reference a parameter that did not exist in the previous template.
There was a problem hiding this comment.
Exactly. It just feels to me that taking a known-good template and doing a very concrete set of operations to it that we thought about beforehand is going to be safer than taking an unknown, new template, and hoping we remember to take out all the unintended modifications.
On the other hand, some Parameters and Mappings might be necessary to support the new resource?
There was a problem hiding this comment.
rephrased to reflect this
| the resource, causing the stack to be drifted. This can be left to the user | ||
| to handle (manually checking the config prior to the import or running drift | ||
| detection after the import), but for convenience, this solution uses | ||
| CloudControl API to look up the physical resource and validate its configuration |
There was a problem hiding this comment.
This is worth calling out in the above section as well.
I assume this happens before doing the actual import?
There was a problem hiding this comment.
I wonder if running a drift detection afterwards might be good enough for a start?
The CCAPI will require us to do a JSON diff, and I'm not sure it's complete enough. Have you experimented with this?
There was a problem hiding this comment.
I have experimented with this and it works quite nicely. The greatest benefit is that CCAPI uses the same resource type nomenclature as CloudFormation so we can simply pass the type to the API call. There are two issues I am still looking at though:
Firstly, I need to understand how the "import identifiers" of a resource relate to "primary" and "secondary" indentifiers that CCAPI uses. While for CFN import, explicit identifier key has to be provided (e.g. BucketName for S3 Bucket, or VpcId for VPC), with CCAPI call you always provide Identifier key that has a value based on the type - it can be either primary or secondary identifier. My plan is to get all resource schemas from CFN resource catalog, extract primary/secondary identifiers info, then run get-template-summary for a template containing all resource types and do some analysis on that. It will be somewhat time consuming though, not sure when I can get to that.
Secondly, CCAPI returns all resource properties, but some of them are not mandatory in CFN templates and if not specified, will be set to default values. So in order to do the comparison correctly, I would need to know the default values of all optional properties of all resources, didn't find a way to do that yet (in best-effort approach, we could only compare properties explicitly set in CFN).
I agree with your suggestion: If it is OK to get this merged without this extra validation, let's do it and either run drift detection automatically or display a post import message to tell user to run it. And leave the CCAPI extra validation for the next iteration.
There was a problem hiding this comment.
For now, I have updated the RFC to omit the CCAPI validations and I have added a "Possible future expansions" section with some thoughts on how to leverage CCAPI to provide a better user experience in future - perhaps beyond simple validations.
| in the main `aws-cdk` repository that is being iteratively expanded with the | ||
| proposed features. Once the approach is agreed and the agreed solution is | ||
| implemented, the PR will be moved from "Draft" to "Open" status and CDK team | ||
| member code review will be requested. Once all approved, the PR will be ready |
There was a problem hiding this comment.
Does that mean everything is going to be implemented in 1 big PR?
Is there a logical order in which we can deliver things incrementally?
What's the aftercare/future extensions story?
There was a problem hiding this comment.
Not sure about the lifecycle of the code post-merge, I guess that is for you and your team to decide - I can't guarantee I will be able to support this afterwards, although I will certainly watch the space for some time as I will be interested how is my so-far-biggest contribution doing :)
It might make sense to split the feature into multiple stages (and in fact, I believe the first stage might be pretty much ready now), I would take your guidance on how to split it.
There was a problem hiding this comment.
I'm thinking we slice the elephant here. We'll say something like:
- First we implement interactive import with current credentials
- Then noninteractive import
- Then support using the lookup role
- Then support CCAPI validations
I see you put some in the extensions piece, that's a good place too.
There was a problem hiding this comment.
modified as suggested
|
|
||
| First, identify what properties must be looked up/asked for for each resource to | ||
| be imported. This information can be obtained by executing CloudFormation API | ||
| action `GetTemplateSummary` with the new template. The action returns the |
There was a problem hiding this comment.
Does this require additional permissions for the cdk-deploy role in the bootstrap stack? Or are we going to use the cdk-lookup role for this?
There was a problem hiding this comment.
That's a very good point. Not sure but I will have a look
There was a problem hiding this comment.
So here I am actually using an existing SdkProvider that is initialized in the main file of CDK CLI (same as the cdk deploy command is using). If I understand the code right, it will only ever use the AWS CLI credentials - it doesn't seem to be assuming any role from the bootstrap stack or so:
https://github.com/aws/aws-cdk/blob/master/packages/aws-cdk/bin/cdk.ts#L212-L219
So I don't think the bootstrap stack needs to be updated, am I correct?
There was a problem hiding this comment.
It probably will eventually, but for now I suppose the trivial solution will do.
Can you add a note in the RFC (execution plan probably) that we're going to initially support "current" credentials, and later on support using bootstrapped roles?
(For the part where we determine the identifiers to be used, so also when --create-resource-mapping is used. For the part where we do the actual import, we should always be using the CDK deploy role if available)
| 1. make the original IaC orchestrator "abandon" the resource - remove it | ||
| from its orchestration without physically removing the resource | ||
| 2. "import" the resource in a CDK stack | ||
| - **App refactoring:** The team already uses CDK but a major refactor is needed |
There was a problem hiding this comment.
This is good to identify as a use case. I like that you thought about it.
But in practice, we're going to have (in AWS) 20+ copies of every app deployed... so if you really want to refactor something across 20 copies, we're going to need more automation to take care of this.
In any case -- not for this RFC, we will deal with that when we get to it! Perhaps people will be clever and build something on top of the structured input file.
There was a problem hiding this comment.
added in the "possible future expansions" section
| might still be needed. | ||
|
|
||
| It might be considered to release such convenience features iteratively | ||
| per resource type, beginning with the most frequently used types. |
There was a problem hiding this comment.
I think mass refactoring support (across multiple stacks) would be a great extension we could write down here.
It's going to require some additional tooling I think.
rix0rrr
left a comment
There was a problem hiding this comment.
This thing is as good as done! I like it. Some small changes and then we can ship it. Thanks!
Pull request has been modified.
rix0rrr
left a comment
There was a problem hiding this comment.
I like it! Going to merge this.
This is a request for comments about "Support importing resources". See #52 for
additional details.
Rendered version
APIs are signed off by @rix0rrr .
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache-2.0 license