While researching how to import existing resources into a CloudFormation stack, I noticed that most examples focused on S3 buckets. But there were rarely any about ECR (Elastic Container Registry). So, I decided write an example using ECR and share my experience.
Context
Like many developers, I started by creating AWS resources like ECR repositories and Lambda functions through the AWS Console (often called “clickops”). While this approach works initially, it quickly becomes unsustainable as your infrastructure grows. That’s why I decided to transition these manually created resources to Infrastructure as Code (IaC). While I can’t share the exact code due to company privacy policies, I’ll walk you through a simplified example that demonstrates the process.
Resource Identifiers
One important concept to understand is how CDK handles resource identifiers. CDK appends a unique identifier to the end of the logical ID of each resource. Let’s look at a simple example:
import { Stack, StackProps, aws_s3 as s3 } from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class S3ImportStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const bucket = new s3.Bucket(this, 'MyNewBucket', {
bucketName: 'my-existing-bucket'
});
}
}
This CDK code will generate a CloudFormation template that looks like this:
{
"Resources": {
"MyNewBucketC8B64525": {
...
}
}
}
CDK uses this resource identifier for any operations it performs on the resource. Understanding this is crucial for the import process.
Now, let’s break down the import process into manageable steps:
Create CDK Block
First, we’ll create a CDK block for our ECR repository. Note that we won’t actually deploy this - we’re just using it to generate a CloudFormation template for the import process.
import { Stack, StackProps, aws_ecr as ecr } from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class EcrImportStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Add the ECR repository as if creating a new one
const repo = new ecr.Repository(this, 'ExistingRepo', {
// replace with repo name that is to be imported
repositoryName: 'my-existing-repo'
});
}
}
Generate CloudFormation Template
Running cdk synth
will generate a CloudFormation template in the cdk.out
directory. We’ll create a simplified version with only the necessary components:
{
"Resources": {
"ExistingRepoFEDAB8B5": {
"Type": "AWS::ECR::Repository",
"Properties": {
"RepositoryName": "my-existing-repo"
},
"UpdateReplacePolicy": "Retain",
"DeletionPolicy": "Retain",
"Metadata": {
"aws:cdk:path": "EcrImportStack/ExistingRepo/Resource"
}
}
}
}
Import Using AWS Console
The import process in the AWS CloudFormation console is straightforward:
- Select “Create stack” with existing resources (import resources)
- Upload your simplified template file (SimplifiedEcr.template.json)
- Set RepositoryName to “my-existing-repo”
- Name your stack (e.g., “my-imported-ecr-stack”)
- Start the import process
Verify Import
After the import completes successfully, you should see the stack status change to IMPORT_COMPLETE
. At this point, your existing ECR repository is now managed through CloudFormation!