Move aws resources from one stack to another cloudformation stack
Tags: aws, guide, serverless, cloudformation
Published: 2024-07-02 06:18:00

## Why do we need this?

- The AWS CloudFormation resource limit is currently set at 500, although this size may increase with the introduction of new features in Application.
- To accommodate this limitation, we must distribute all resources across various stacks.
- Our approach involves isolating Lambda functions into a separate stack, while other resources such as S3 buckets and DynamoDB tables reside in an infra stack.
- This is the reason why we need to import resources from the main stack into the infra stack.

&nbsp;
## Steps to move resources from one stack to another stack


&nbsp;
## Prerequisites


> **Apply 'DeletionPolicy: Retain' to all resources of the main stack**


- Applying 'DeletionPolicy: Retain' to all resources in the main stack ensures that when these resources are deleted during stack updates or deletions, they are retained rather than being deleted permanently.
- This is particularly useful for resources that contain valuable data or configurations that need to be preserved even if they are no longer actively used.

---

Consider you have two cloudformation stack(which is generated by serverless framework): main and destination, and you want to import some resources from main to destination. Here are the steps to move resources from one stack to another stack without deleting the actual resources.

1. Copy AWS resources from the main cloudFormation stack and paste them into the destination cloudFormation stack.
2. Remove resources from the main stack and deploy the main stack.
3. Prepare another file named "resourcesToImport.txt" containing the AWS resource type, logical ID, and resource identifier.
4. Run a command to create an IMPORT changeset.
5. Execute a command to apply changeset which was created in the previous step.

&nbsp;
### 1. Copy AWS resources from the main cloudFormation stack and paste them into the destination cloudFormation stack.

- Copy destination stack cloudformation code into one file ( templateToImport.json)
- Copy main stack resource’s ( which you want to import) cloudformation code and append them in destination stack code (templateToImport.json)

### 2. Remove resources from the main stack and deploy the main stack.

- Now, remove all the resources which we want to import or we added into the destination stack in step 1 .
- Redeploy main stack.

> Now resources are not in any stack and also not deleted because resource’s deletionPolicy is set to Retain.


### 3. Prepare another file named "resourcesToImport.txt" containing the aws resource type, logical ID, and resource identifier.

Now, create One file named ‘resourcesToImport.txt’ and add ResourceType, LogicalResourceId and ResourceIdentifier for each resource which we want to import.

- ResourceType will be the cloudformation resource type
- LogicalResourceId will be the Logical Name of resource
- ResourceIdentifier contains actual identifier of resource
    - If resource is S3 bucket then value will be {"BucketName": "<ACTUAL_BUCKET_NAME>"}
    - If resource is dynamodb table then value will be { "TableName": "ACTUAL_DYNAMODB_TABLE_NAME" }
    - If resource is rest api then value will be { "RestApiId": "REST_API_ID" }

Example File :

```json
[
  {
    "ResourceType": "AWS::S3::Bucket",
    "LogicalResourceId": "<LOGICAL_NAME_OF_BUCKET>",
    "ResourceIdentifier": {
      "BucketName": "<ACTUAL_NAME_OF_BUCKET>"
    }
  },
  {
    "ResourceType": "AWS::DynamoDB::Table",
    "LogicalResourceId": "<LOGICAL_NAME_OF_DYNAMODB_TABLE>",
    "ResourceIdentifier": {
      "TableName": "ACTUAL_NAME_OF_DYNAMODB_TABLE"
    }
  },
  {
    "ResourceType": "AWS::ApiGateway::RestApi",
    "LogicalResourceId": "<LOGICAL_NAME_OF_RESTAPI>",
    "ResourceIdentifier": {
      "RestApiId": "REST_API_ID"
    }
  }
]
```

4. Run a command to create IMPORT changeset

below command creates import changeset of resource

```bash
aws cloudformation create-change-set --stack-name <YOUR_STACK_NAME> --change-set-name <CHANGE_SET_NAME> --change-set-type IMPORT --resources-to-import file://resourcesToImport.txt --template-body file://templateToImport.json --capabilities CAPABILITY_NAMED_IAM --description "write here description" --profile <AWS_PROFILE>
```

### 5. Execute a command to apply the changeset.

below command executes the import changeset and resources will be move from main stack to destination stack 🥳

```bash
aws cloudformation execute-change-set --change-set-name <CHANGE_SET_NAME> --stack-name <YOUR_STACK_NAME> --profile <AWS_PROFILE>
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcp35ip0g3ifhyzrgl7s.png)

&nbsp;
> **👉 NOTE** : Cloudformation doesn’t allow to import all types of resources. Few resources are not supported to import.


#### Below link contains all the resources which are allowed  to import in cloudformation stack

[Resource type support - AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html)

&nbsp;

### Reference

[Importing existing resources into a stack - AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-existing-stack.html)