$npx -y skills add pulumi/agent-skills --skill pulumi-cdk-to-pulumiLoad this skill when a user wants to migrate, convert, port, translate, or move an AWS CDK application (including CDK stacks, constructs, or CloudFormation-synthesized templates) to Pulumi. Phrases such as "convert CDK to Pulumi", "migrate CDK app", "port CDK stacks", "replace CD
| 1 | # CRITICAL SUCCESS REQUIREMENTS |
| 2 | |
| 3 | The migration output MUST meet all of the following: |
| 4 | |
| 5 | 1. **Complete Resource Coverage** |
| 6 | - Every CloudFormation resource synthesized by CDK MUST: |
| 7 | - Be represented in the Pulumi program **OR** |
| 8 | - Be explicitly justified in the final report. |
| 9 | |
| 10 | 2. **Successful Deployment** |
| 11 | - The produced Pulumi program must be structurally valid and capable of a successful `pulumi up` (assuming proper config). |
| 12 | |
| 13 | 3. **Final Migration Report** |
| 14 | - Always output a formal migration report suitable for a Pull Request. |
| 15 | - Include: |
| 16 | - CDK → Pulumi resource mapping |
| 17 | - Provider decisions (aws-native vs aws) |
| 18 | - Behavioral differences |
| 19 | - Missing or manually required steps |
| 20 | - Validation instructions |
| 21 | |
| 22 | ## WHEN INFORMATION IS MISSING |
| 23 | |
| 24 | If a user-provided CDK project is incomplete, ambiguous, or missing artifacts (such as `cdk.out`), ask **targeted questions** before generating Pulumi code. |
| 25 | |
| 26 | ## MIGRATION WORKFLOW |
| 27 | |
| 28 | Follow this workflow **exactly** and in this order: |
| 29 | |
| 30 | ### 1. INFORMATION GATHERING |
| 31 | |
| 32 | #### 1.1 Verify AWS Credentials (ESC) |
| 33 | |
| 34 | Running AWS commands (e.g., `aws cloudformation list-stack-resources`) and CDK commands (e.g. `cdk synth`) requires credentials loaded via Pulumi ESC. |
| 35 | |
| 36 | - If the user has already provided an ESC environment, use it. |
| 37 | - If no ESC environment is specified, **ask the user which ESC environment to use** before proceeding with AWS commands. |
| 38 | |
| 39 | You MUST confirm the AWS region with the user. The `cdk synth` results may be incorrect if ran with the wrong AWS Region. |
| 40 | |
| 41 | #### 1.2 Synthesize CDK |
| 42 | |
| 43 | Run/inspect: |
| 44 | |
| 45 | ```bash |
| 46 | npx cdk synth --quiet |
| 47 | ``` |
| 48 | |
| 49 | - ALWAYS run `synth` with `--quiet` to prevent the template from being output on stdout. |
| 50 | |
| 51 | If failing, inspect `cdk.json` or `package.json` for custom synth behavior. |
| 52 | |
| 53 | #### 1.3 Identify CDK Stacks & Environments |
| 54 | |
| 55 | Read `cdk.out/manifest.json`: |
| 56 | |
| 57 | ```bash |
| 58 | jq '.artifacts | to_entries | map(select(.value.type == "aws:cloudformation:stack") | {displayName: .key, environment: .value.environment}) | .[]' cdk.out/manifest.json |
| 59 | ``` |
| 60 | |
| 61 | Example output: |
| 62 | |
| 63 | ```json |
| 64 | { |
| 65 | "displayName": "DataStack-dev", |
| 66 | "environment": "aws://616138583583/us-east-2" |
| 67 | } |
| 68 | { |
| 69 | "displayName": "AppStack-dev", |
| 70 | "environment": "aws://616138583583/us-east-2" |
| 71 | } |
| 72 | ``` |
| 73 | |
| 74 | In the Pulumi stack you create you MUST set both the `aws:region` and `aws-native:region` config variables. For example: |
| 75 | |
| 76 | ```bash |
| 77 | pulumi config set aws-native:region us-east-2 --stack dev |
| 78 | pulumi config set aws:region us-east-2 --stack dev |
| 79 | ``` |
| 80 | |
| 81 | #### 1.4 Build Resource Inventory |
| 82 | |
| 83 | For each stack: |
| 84 | |
| 85 | ```bash |
| 86 | aws cloudformation list-stack-resources \ |
| 87 | --region <region> \ |
| 88 | --stack-name <stack> \ |
| 89 | --output json |
| 90 | ``` |
| 91 | |
| 92 | #### 1.5 Analyze CDK Structure |
| 93 | |
| 94 | Extract: |
| 95 | |
| 96 | - Environment-specific conditionals |
| 97 | - Stack dependencies & cross-stack references |
| 98 | - Runtime config (context/env vars) |
| 99 | - Construct types (L1, L2, L3) |
| 100 | |
| 101 | ### 2. CODE CONVERSION (CDK → PULUMI) |
| 102 | |
| 103 | - Perform the initial conversion using the `cdk2pulumi` tool. Follow [cdk-convert.md](cdk-convert.md) to perform the conversion. |
| 104 | - Read the conversion report and fill in any gaps. For example, if the conversion fails to convert a resource you have to convert it manually yourself. |
| 105 | |
| 106 | #### 2.1 Custom Resources Handling |
| 107 | |
| 108 | CDK uses Lambda-backed Custom Resources for functionality not available in CloudFormation. In synthesized CloudFormation, these appear as: |
| 109 | |
| 110 | - Resource type: `AWS::CloudFormation::CustomResource` or `Custom::<name>` |
| 111 | - Metadata contains `aws:cdk:path` with the handler name (e.g., `aws-s3/auto-delete-objects-handler`) |
| 112 | |
| 113 | **Default behavior**: `cdk2pulumi` rewrites custom resources to `aws-native:cloudformation:CustomResourceEmulator`, which invokes the original Lambda. This works but has tradeoffs (Lambda dependency, cold starts, eventual consistency). |
| 114 | |
| 115 | **Migration strategies by handler type:** |
| 116 | |
| 117 | | Handler | Strategy | |
| 118 | |---------|----------| |
| 119 | | `aws-certificatemanager/dns-validated-certificate-handler` | Replace with `aws.acm.Certificate`, `aws.route53.Record`, and `aws.acm.CertificateValidation` | |
| 120 | | `aws-ec2/restrict-default-security-group-handler` | Replace with `aws.ec2.DefaultSecurityGroup` resource with empty ingress/egress rules | |
| 121 | | `aws-ecr/auto-delete-images-handler` | Replace `aws-native:ecr:Repository` with `aws.ecr.Repository` with `forceDelete: true` | |
| 122 | | `aws-s3/auto-delete-objects-handler` | Replace `aws-native:s3:Bucket` with `aws.s3.Bucket` with `forceDestroy: true` | |
| 123 | | `aws-s3/notifications-resource-handler` | Replace with `aws.s3.BucketNotification` | |
| 124 | | `aws-logs/log-retention-handler` |