Skip to content

Commit 363aea2

Browse files
aacotroneojkodroffclaude
authored
Discovered Stacks launch content: docs, announcement blog, and CF migration tutorial (#20310)
* discovered-stacks docs * Update content/docs/insights/discovery/discovered-stacks/migrate.md Co-authored-by: Josh Kodroff <jkodroff@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Josh Kodroff <jkodroff@users.noreply.github.com> * Address review: title, value-prop, TF links, API anchors, Pulumi IaC sweep Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Polish discovered-stacks content: prose, casing, drop unshipped skill mention - Tutorial "Where you end up": add end-to-end close; lowercase "CloudFormation stack"; fix doubled-"so" run-on in Step 4. - migrate.md: direct "Start a migration" framing; remove the mention of a reusable Pulumi agent skill (not shipping); fix trailing space and a double blank line. - Terminology sweep across _index.md and both blogs (Discovery / cloud account, Pulumi IaC). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add social copy to both discovered-stacks posts; lead blog meta_desc with brand - Draft X/LinkedIn/Bluesky social frontmatter for the launch announcement and the CloudFormation migration tutorial (setup → gap → pointer; all under platform limits; critique-passed). - Launch blog meta_desc now leads with "Discovered Stacks" and says "built-in" (matches the body) instead of "seamless". Nothing posts until the 2099 publish date is changed and the page ships. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Address pre-merge review: Neo-automation consistency, grammar, style nags - Reconcile the Neo-automation framing across siblings: scope the tutorial's Step 4 to "In this case, Neo handled them automatically" and note in migrate.md that Neo makes these decisions when it drives the migration (resolves the review's one outstanding finding). - Fix 4 sentences left grammatically broken by earlier em-dash trimming (missing period/commas; reword the alias sentence). - Apply the flagged Vale prose nags across the two docs pages and both blogs (difficulty qualifiers, weasel words, wordiness, cliche, click->select, see-below->anchor, em-dash density). Keep the "Resolve Not found and No exact match resources" heading capitalized: the status labels are defined terms. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Set Discovered Stacks launch dates to 2026-07-30 Both the announcement and the CloudFormation migration tutorial publish on the same day so the announcement's link to the tutorial resolves immediately. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add releases changelog entry for the Discovered Stacks launch Dated 2026-07-30 to match the launch; links the announcement, docs, and migration tutorial. Team/Enterprise/Business Critical tiers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Josh Kodroff <jkodroff@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent a22867d commit 363aea2

14 files changed

Lines changed: 460 additions & 1 deletion

File tree

407 KB
Loading
547 KB
Loading
309 KB
Loading
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
---
2+
title: "Migrate CloudFormation to Pulumi with Discovered Stacks"
3+
date: 2026-07-30
4+
draft: false
5+
meta_desc: "Migrate a CloudFormation stack to Pulumi with Discovered Stacks: verify every resource, import with a zero-diff preview, and track it all in Pulumi Cloud."
6+
feature_image: feature.png
7+
category: tutorials
8+
authors:
9+
- alejandro-cotroneo
10+
tags:
11+
- tutorials
12+
- insights
13+
- import
14+
- aws
15+
schema_type: auto
16+
17+
# Social media copy — auto-posted to X, LinkedIn, and Bluesky when merged to master.
18+
# Character limits: X ~280, Bluesky 300, LinkedIn 3000. Leave blank to skip a platform.
19+
social:
20+
twitter: |
21+
We migrated a 61-resource CloudFormation stack to Pulumi — a payments API, database and all — and never ran pulumi up once. Every resource proved in sync by a zero-diff preview.
22+
23+
Here's how, step by step.
24+
linkedin: |
25+
Migrating infrastructure to Pulumi has a quiet fear built into it: did every resource actually make it across, or did one slip through?
26+
27+
We took a real CloudFormation stack — payments-api, 61 resources: a VPC, an Aurora database behind an RDS Proxy, a DynamoDB table, a Kinesis pipeline, and the IAM roles, KMS keys, and secrets wiring them together — and migrated it end to end.
28+
29+
54 resources had a direct path. Seven needed a decision. None of them got lost, because the console tracks every resource by a status computed from live state, and the migration only counts as done when pulumi preview reports zero diff against the cloud.
30+
31+
The part that surprises people: there's no pulumi up anywhere in the process.
32+
33+
We wrote up the whole walkthrough.
34+
bluesky: |
35+
We migrated a 61-resource CloudFormation stack to Pulumi — payments API, database, the works — and never ran pulumi up once. A zero-diff preview proved every resource was in sync.
36+
37+
The full step-by-step is up.
38+
---
39+
40+
With [Discovered Stacks](/docs/insights/discovery/discovered-stacks/), Pulumi Cloud does the bookkeeping for a CloudFormation migration: every resource in the stack gets an explicit migration status, and the migration is done when the code provably matches the cloud. In this tutorial, we take one real CloudFormation stack from discovered to migrated and managed by Pulumi IaC, end to end.
41+
42+
<!--more-->
43+
44+
## What we're migrating
45+
46+
Our example is `payments-api`, a CloudFormation stack with 61 resources: a VPC, an Aurora ledger database behind an RDS Proxy, an assets S3 bucket, a DynamoDB ledger table, a Kinesis payment-events pipeline, and the IAM roles, KMS keys, and secrets that wire them together. The plan has five steps:
47+
48+
1. Find the stack in Pulumi Cloud.
49+
1. Review the migration breakdown at a glance.
50+
1. Start the migration.
51+
1. Resolve the stragglers, so every resource is accounted for.
52+
1. Confirm the quality gate: a zero-diff `pulumi preview`.
53+
54+
We'll use [Pulumi Neo](/docs/ai/) to do the heavy lifting, but nothing here depends on it. The same flow works with your own coding agent or entirely by hand, because migration status is derived from actual stack state — however the work gets done, the console shows the same progress.
55+
56+
## Step 1: Find your stack in Pulumi Cloud
57+
58+
Discovered Stacks builds on [Discovery](/docs/insights/discovery/), so the only prerequisite is a scanned [cloud account](/docs/insights/discovery/accounts/) — the AWS account holding your CloudFormation stacks.
59+
60+
Once a scan has run, open the **Stacks** page and turn on **Show Discovered Stacks**. Your CloudFormation stacks appear alongside your Pulumi stacks. The project name comes from the CloudFormation stack (`payments-api`), and the stack name encodes the account and region it came from, so the same template deployed to two regions shows up as two distinct discovered stacks.
61+
62+
## Step 2: Plan the migration at a glance
63+
64+
Open the discovered stack's **Migration** tab. It lays out all 61 resources of `payments-api` by status, so you can visualize the migration before touching anything:
65+
66+
- **54 Ready**: mapped to a Pulumi type and confirmed to exist — importable right now.
67+
- **2 Not found**: mapped, but Discovery couldn't confirm their current state.
68+
- **5 No exact match**: no direct Pulumi type. We'll come back to these in step 4.
69+
70+
Every row also pairs the **origin type** (`AWS::S3::Bucket`) with the **Pulumi type** it maps to (`aws:s3/bucket:Bucket`).
71+
72+
![The Migration tab of the discovered payments-api stack compared against an empty target: a status summary of 54 Ready, 2 Not found, and 5 No exact match above a resource table with Name, Type, and Status columns.](discovered-stack-migration-start.png)
73+
74+
## Step 3: Start the migration
75+
76+
Most of `payments-api` has a direct migration path — 54 of its 61 resources are **Ready** — so we'll reach for the tab's quick actions and let them do the bulk of the work.
77+
78+
From the discovered stack's **Actions** menu, select **Migrate with Neo**. Neo asks where the code should live — a git repository, a target project and stack, a language — and then works through the migration:
79+
80+
1. Fetches the discovered resources and their statuses through the [Discovered Stacks API](/docs/insights/discovery/discovered-stacks/migrate/#use-the-api).
81+
1. Imports the Ready resources in batches with `pulumi import`, building up a Pulumi program as it goes.
82+
1. Runs `pulumi preview` after each batch and reconciles the generated code against the real cloud state.
83+
1. Opens a pull request with the program and a migration report.
84+
85+
Because `pulumi import` writes state as it runs, the console updates live: statuses flip from `Ready` to `Migrated` batch by batch, without anyone marking a checkbox.
86+
87+
## Step 4: Resolve the stragglers
88+
89+
That leaves seven rows that need review. In this case, Neo handled them automatically, leaving an annotation on each that records the decision it made:
90+
91+
- **The 2 Not found rows** are CloudWatch log groups. Discovery couldn't confirm their state, but they're live, so the import succeeded and the resources were resolved without further inspection.
92+
- **Three No exact match rows** are inline IAM policies, which our Pulumi AWS Provider imported as part of their parent role. The roles are already migrated, so each policy is marked resolved.
93+
- **One** is a Secrets Manager target attachment; Pulumi expresses that link through the database's own configuration, so it's marked resolved once the database is migrated.
94+
- **The last** is a CDK-generated custom resource that strips the rules from the VPC's default security group. Pulumi models that directly as an `aws.ec2.DefaultSecurityGroup`, so there's nothing to import — it's marked resolved.
95+
96+
![The same Migration tab compared against the migrated Pulumi stack: every resource now reads Migrated, with Resolved chips on the seven rows that took a manual decision and a Next step column that explains each — imported to Pulumi, captured on the parent role, or nothing left to do.](discovered-stack-migration-end.png)
97+
98+
## Step 5: The quality gate
99+
100+
With every resource imported or resolved, the migration earns its trust in one final check: a **zero-diff `pulumi preview`**. The generated program, run against the live cloud, proposes no changes.
101+
102+
```text
103+
Resources:
104+
56 unchanged
105+
```
106+
107+
A clean preview means the code matches reality. If it shows a diff, the code gets fixed until it doesn't; the cloud is never modified to make the code look right. And notably, there's no `pulumi up` in this story: importing already synced the state to Pulumi Cloud, so the first `up` you run is for the first real change you make after the migration.
108+
109+
That zero-diff preview isn't the finish line, it's a checkpoint you can build on. Imported code is faithful but rarely the code you'd write by hand: generated names, repeated blocks, inline configuration. Now that it provably matches the cloud, refactor freely — pull settings into stack config, split the program into modules, collapse repetition into loops, group related resources into components. Rerun `pulumi preview` after each change: a clean zero-diff means you reshaped the code without touching the infrastructure. When a refactor shifts a resource's identity (for example, moving it into a new component), an [alias](/docs/iac/concepts/resources/options/aliases/) keeps it a no-op.
110+
111+
## Where you end up
112+
113+
The `payments-api` program now lives in your repository, reviewed and merged like any other code. The discovered stack remains as the migration record until you decide to remove the CloudFormation stack. And because progress is derived from real state, if the CloudFormation stack changes later, those changes surface against your Pulumi stack. Migration doesn't have to be all-or-nothing either: for a larger stack, migrate resources progressively and safely by never running `pulumi up` while CloudFormation is managing the resources. That's the migration end to end: a CloudFormation stack turned into a Pulumi program you own and manage as code, every resource accounted for and provably in sync.
114+
115+
The same flow works for Azure Resource Manager deployments, which Discovery models as discovered stacks too. And for Pulumi-hosted Terraform stacks, a **Migration** tab offers the identical experience, with statuses derived from the Terraform state.
116+
117+
To go deeper:
118+
119+
- [Discovered Stacks documentation](/docs/insights/discovery/discovered-stacks/)
120+
- [Migrate from a Discovered Stack](/docs/insights/discovery/discovered-stacks/migrate/)
121+
- [Migrating from AWS CloudFormation](/docs/iac/guides/migration/migrating-to-pulumi/from-cloudformation/)
114 KB
Loading
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
title: "Discovered Stacks: One Place for All Your Infrastructure"
3+
date: 2026-07-30
4+
draft: false
5+
meta_desc: "Discovered Stacks: Pulumi Cloud now models your CloudFormation and ARM deployments as Pulumi IaC stacks, with a built-in migration path."
6+
feature_image: feature.png
7+
category: product
8+
authors:
9+
- alejandro-cotroneo
10+
tags:
11+
- features
12+
- insights
13+
- pulumi-cloud
14+
canonical_url: /docs/insights/discovery/discovered-stacks/
15+
schema_type: auto
16+
17+
# Social media copy — auto-posted to X, LinkedIn, and Bluesky when merged to master.
18+
# Character limits: X ~280, Bluesky 300, LinkedIn 3000. Leave blank to skip a platform.
19+
social:
20+
twitter: |
21+
Every migration to IaC starts with a spreadsheet tracking which resources made it across. It's stale the day it's written — six months later nobody can say which of 800 actually migrated, and which were quietly forgotten.
22+
23+
Here's what replaces it.
24+
linkedin: |
25+
Almost nobody's cloud estate is one tool. There's the CloudFormation that came with the AWS account, the ARM templates from the Azure team, the Terraform from an acquisition, and the Pulumi you're standardizing on.
26+
27+
That fragmentation is why migrations stall. Moving a stack to Pulumi was never the hard part — knowing where you stand is. The tracking lives in a spreadsheet, the spreadsheet goes stale the day it's written, and six months later nobody can say which of 800 resources made it across and which were quietly forgotten.
28+
29+
Today we're launching Discovered Stacks: Pulumi Cloud now models your CloudFormation stacks and ARM deployments as stacks, right alongside your Pulumi IaC. Every resource carries a migration status computed from live state on both ends — never a stale line someone forgot to update.
30+
31+
We wrote up how it works.
32+
bluesky: |
33+
Six months into a migration, can you say which of 800 resources actually made it to IaC — and which were quietly forgotten? The spreadsheet tracking it went stale the day it was written.
34+
35+
The spreadsheet is retired for good.
36+
---
37+
38+
Today we're launching **Discovered Stacks**: Pulumi Cloud now models your AWS CloudFormation stacks and Azure Resource Manager deployments as stacks, right alongside your Pulumi IaC stacks. And when you're ready to bring them under Pulumi management, migration is built in, with every resource tracked until the code provably matches the cloud.
39+
40+
<!--more-->
41+
42+
## Why: your infrastructure doesn't live in one tool
43+
44+
Almost nobody's cloud estate is a single technology. There's the CloudFormation that came with the AWS account, the ARM templates from the Azure team, the Terraform from an acquisition, and the Pulumi you're standardizing on. Each tool has its own console, its own grouping, its own idea of state, and no single place shows you everything you run.
45+
46+
That fragmentation is also why migrations stall. Moving a stack to Pulumi has never been the hard part; *knowing where you stand* is. The tracking lives in a spreadsheet, the spreadsheet goes stale the day it's written, and six months later nobody can say which of the 800 resources made it across and which were quietly forgotten.
47+
48+
## Nothing gets lost
49+
50+
Discovered Stacks gives you confidence that your migration plan or governance efforts will include all resources. This catches a common failure mode where resources are missed by your existing migration scripts or automations. When [Pulumi Insights](/docs/insights/) scans your accounts, every CloudFormation stack and ARM deployment becomes a discovered stack, and every resource in it appears as a row with an explicit migration status: ready to migrate, requiring review before migration, or already migrated. Every status is computed from live state on both ends — what Pulumi manages and what the source tool reports — so it's never a stale annotation someone forgot to update.
51+
52+
Each resource shows its **origin type** (`AWS::S3::Bucket`) next to its **Pulumi type** (`aws:s3/bucket:Bucket`), with the origin properties side by side with Pulumi's view, so you can verify that Pulumi sees exactly what your source tool sees before you change anything. Decisions you make along the way (*this resource was deleted, that policy is covered by its parent role*) are recorded by marking the resource resolved: it stays visible to your whole team, deliberately handled rather than quietly forgotten. The spreadsheet is retired.
53+
54+
![The Resources grid of a discovered CloudFormation stack in Pulumi Cloud: each row pairs the Pulumi type (aws:sns:Topic) with its origin type (AWS::SNS::Topic), a Managed By column reading CloudFormation, and a provider link out to the resource in the AWS console.](resources-list.png)
55+
56+
## Migration on your terms
57+
58+
When you're ready to migrate, the console is where you plan and build confidence. **Migrate with Neo** hands the job to [Pulumi Neo](/docs/ai/), which imports the resources, reconciles the generated program, and opens a pull request for review. If you prefer local development, **Generate Import Commands** gives you the raw materials, and the same API lets your own agents drive the flow.
59+
60+
Two things hold regardless of the path. Progress is *derived*: a resource shows as migrated when it actually exists in the target Pulumi stack, not when someone checks a box. And the quality gate is a **zero-diff `pulumi preview`** — the migration is done when the code demonstrably matches your cloud.
61+
62+
Terraform stacks whose state you [store in Pulumi Cloud](/docs/iac/get-started/terraform/terraform-state-backend/) get the same treatment through a new **Migration** tab, with statuses derived from the Terraform state.
63+
64+
## Try it
65+
66+
Open the **Stacks** page in [Pulumi Cloud](https://app.pulumi.com/), turn on **Show Discovered Stacks**, and your CloudFormation and ARM estates appear next to your IaC. From there:
67+
68+
- Read the [Discovered Stacks documentation](/docs/insights/discovery/discovered-stacks/).
69+
- Follow the [step-by-step migration tutorial](/blog/discovered-stacks-migrate-cloudformation-to-pulumi/) to take a CloudFormation stack all the way to Pulumi.
70+
71+
We'd love to hear how it works on your estate — reach out through [Pulumi feedback](https://github.com/pulumi/pulumi-cloud-requests) or your customer success team.
306 KB
Loading

content/docs/iac/guides/migration/migrating-to-pulumi/from-arm.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Pulumi offers a flexible, code-first alternative to Azure ARM templates using C#
2222
If your team has already provisioned Azure infrastructure using ARM (Azure Resource Manager) templates and is looking for a more productive approach, Pulumi provides several paths to move forward:
2323

2424
* **[Neo](/product/neo/) (Recommended)**: Use Neo to automatically convert your ARM templates and import existing resources with zero downtime
25+
* **[Discovered Stacks](/docs/insights/discovery/discovered-stacks/)**: Scan your Azure account and Pulumi Cloud automatically groups your ARM deployments into discovered stacks you can migrate from the console, with per-resource status tracking.
2526
* [**Coexist**](#coexist-with-arm) with resources provisioned by ARM by referencing deployment outputs.
2627
* [**Import**](/docs/using-pulumi/adopting-pulumi/import/) existing Azure resources into Pulumi in the usual way.
2728
* [**Convert**](#convert-arm-templates-to-pulumi) your deployments to use Pulumi and then incrementally migrate resources.

content/docs/iac/guides/migration/migrating-to-pulumi/from-cloudformation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ aliases:
2020
If your team has already provisioned infrastructure using AWS CloudFormation, and you'd like to adopt Pulumi, you have several strategies you can take:
2121

2222
* **[Neo](/product/neo/) (Recommended)**: Use Neo to automatically convert your CloudFormation templates and import existing resources with zero downtime
23+
* **[Discovered Stacks](/docs/insights/discovery/discovered-stacks/)**: Scan your AWS account and Pulumi Cloud automatically groups your CloudFormation stacks into discovered stacks you can migrate from the console, with per-resource status tracking.
2324
* [**Coexist**](#referencing-stack-outputs) with resources provisioned by CloudFormation by referencing stack outputs.
2425
* [**Import**](/docs/using-pulumi/adopting-pulumi/import/) existing resources into Pulumi in the usual way.
2526
* [**Convert**](#converting-stacks-and-resources) your deployments to use Pulumi and then incrementally migrate resources.

content/docs/insights/discovery/_index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Discovery integrates with [Pulumi ESC (Environments, Secrets, and Configuration)
2929

3030
4. **Import**: Use [Visual Import](/docs/insights/discovery/visual-import/) to convert discovered resources into Pulumi IaC code, bringing unmanaged infrastructure under automated management.
3131

32+
5. **Migration**: [Discovered Stacks](/docs/insights/discovery/discovered-stacks/) automatically group resources managed by CloudFormation and ARM into stacks in Pulumi Cloud, with a per-resource [migration path to Pulumi](/docs/insights/discovery/discovered-stacks/migrate/).
33+
3234
### Account hierarchies
3335

3436
Discovery automatically creates child accounts when applicable. For AWS, each selected region becomes a child account under the main parent account, making it easy to manage resources across regions. Actions performed on parent accounts (like scanning or deletion) cascade to all children, while individual child accounts can be managed independently.
@@ -81,5 +83,6 @@ Resource search is available to all organization members, but users can only see
8183
- [Connect cloud accounts in bulk](/docs/insights/discovery/connect-cloud-accounts/)
8284
- [Create and manage accounts](/docs/insights/discovery/accounts/)
8385
- [Learn Resource Search syntax](/docs/insights/discovery/search/)
86+
- [Explore Discovered Stacks](/docs/insights/discovery/discovered-stacks/)
8487
- [Import resources into Pulumi IaC](/docs/insights/discovery/visual-import/)
8588
- [Export resource data](/docs/insights/discovery/data-export/)

0 commit comments

Comments
 (0)