CloudPort
Your AWS app → Azure-ready code in 3 commands. With receipts.
You built on AWS. Now you need Azure. CloudPort reads your infrastructure, tells you how hard the move is (0-100), and writes the Azure code for you. It also tells you what it couldn't check — so you don't get surprised at launch.
pip install cloudport # or: uv sync
cloudport analyze ./your-app # what do you depend on?
cloudport plan --target azure # how hard is the move?
cloudport generate --target azure # write the Azure code
TL;DR for busy people
Problem: Moving clouds takes months because nobody knows what's actually hard until they're halfway through. A single IAM policy or queue setting can block you for weeks.
Solution: CloudPort scans your Terraform, Kubernetes, Docker, and even your app code (boto3 calls). It scores you 0-100, maps every resource to Azure, and generates working OpenTofu. If it's unsure, it says MANUAL_REVIEW_REQUIRED instead of guessing.
Not magic. Not AI. Just honest static analysis.
Try it in 90 seconds
We ship a realistic example app (FastAPI + worker + Terraform + K8s) so you don't need your own code:
git clone https://github.com/cloudport/cloudport && cd cloudport
uv sync
cd examples/aws-production
# 1. Analyze - what did we find?
uv run --project ../.. cloudport analyze .
# 2. Score - how portable are we?
uv run --project ../.. cloudport score
# 3. Plan - what maps to what on Azure?
uv run --project ../.. cloudport plan --target azure
# 4. Generate - write the Azure files
uv run --project ../.. cloudport generate --target azure
# 5. Validate - prove what works
uv run --project ../.. cloudport validate
What you'll see:
Portability Score: 76/100 (target: azure)
compute ............ 85/100 ✅ EC2 → AKS is straightforward
database ........... 80/100 ✅ RDS → PostgreSQL Flexible Server
storage ............ 90/100 ✅ S3 → Azure Blob
messaging .......... 65/100 ⚠️ SQS FIFO needs sessions on Service Bus
identity ........... 50/100 🔴 IAM → Entra ID needs human review
└─ BLOCKER IAM Role (task_role): MANUAL_REVIEW_REQUIRED
A low identity score isn't a bug. AWS IAM and Azure Entra ID work completely differently. Any tool that says otherwise is lying.
How it works (explain like I'm 5)
Imagine you're moving houses.
- Inventory: CloudPort opens every box (your
.tffiles, K8s YAML, Dockerfiles) and lists what's inside. It also peeks at your app code to see if you're calling AWS directly. - Map: For each item, it looks up "what's the Azure version of this?" in a big dictionary (
providers/mappings/aws_azure.yaml). It writes down price, differences, and how much work it'll take. - Build: It writes the new house (Azure Terraform) using templates. Same input = same output, byte-for-byte, every time.
- Check: It double-checks its own work. Did the Terraform parse? Are secrets still private? If you have LocalStack/Azurite running, it even tests uploading a file for real. If it can't check something, it marks it
NOT_VALIDATED— it never fakes a green check.
That's it. No hidden cloud calls. No secrets leave your machine.
What you get — the 7 commands
| Command | Plain English | Example |
|---|---|---|
analyze |
Inventory. "What do I have?" Parses Terraform, K8s, Compose, Dockerfiles + scans code for boto3 / @aws-sdk/*. |
cloudport analyze . |
score |
Grade. "How hard is the move?" Score 0-100, broken down by 9 areas (compute, DB, identity...). Every point is explained. | cloudport score --target azure |
plan |
Game plan. Maps each AWS thing → Azure thing. Tells you compatibility %, what will break, and S/M/L effort. |
cloudport plan --target azure |
generate |
The code. Writes deterministic Azure OpenTofu, K8s manifests (images rewritten ECR → ACR), and provider-neutral interfaces for your app. | cloudport generate --target azure |
validate |
The proof. Checks the generated code. Labels things PASS / FAIL / SIMULATED (emulator) / NOT_VALIDATED (couldn't check). |
cloudport validate --emulator http://localhost:4566 |
iam |
The checklist. Turns IAM roles into an RBAC worksheet for your security team. It never auto-writes policies. | cloudport iam --target azure |
datamigrate |
The moving truck. Gives you the actual pg_dump, azcopy, and DynamoDB commands to move your data. |
cloudport datamigrate |
All commands are read-only except deploy/destroy (which ask for confirmation). No cloud credentials needed.
Why teams pick this over doing it by hand (or using a "magic" tool)
| Other tools | CloudPort |
|---|---|
| "We migrate everything automatically! (trust us)" | Says MANUAL_REVIEW_REQUIRED when it's not sure. That's the feature. |
| Hides SDK lock-in in your app code | Finds boto3 calls and docks your score honestly. |
| Score is 100/100 before anything is tested | Max is 99 without live validation. Emulator tests count as half-credit (SIMULATED). |
| "We estimated the cost!" (made it up) | Never invents prices. Ever. |
| One big messy script | Knowledge is in reviewable YAML, not code. Your architect can PR the mappings. |
Our promise — 5 things we never blur:
- What we read from your files (
DECLARED) - What we guessed (
INFERRED— always labeled) - What we generated (with
sha256manifest) - What we checked (
PASS/WARN/FAIL) - What we could NOT check (
NOT_VALIDATED+ why)
More on this: docs/honesty-model.md
Works with your real setup
Multiple environments? Same repo, different tfvars:
cloudport analyze . --env prod --tfvar-file prod.tfvars
cloudport plan . --env prod --target azure
cloudport validate --generated ./out --env prod --emulator http://localhost:4566
# artifacts: .cloudport/envs/prod/ + score history per env
Want GCP instead? Adapters are plugins. The example GCP adapter at examples/plugins/cloudport-gcp-adapter/ adds cloudport adapter list → gcp with zero core changes. See docs/adapter-guide.md.
CI included. Generated projects ship a GitHub Action that re-scores every PR and comments with drift. This repo itself runs LocalStack + Azurite in CI.
Dashboard (optional, read-only)
Visual view over the CLI's JSON — graph, score, waves, validation, trends per env. If artifacts are missing it says so, it doesn't guess.
cd dashboard && pnpm install && pnpm build
CLOUDPORT_WORKSPACE=/path/to/project pnpm start
Honest limitations
We'd rather tell you now than waste your month:
- We see declared infrastructure, not live traffic. Real perf needs live validation (we have the adapter interface ready, just not all probes yet).
- AWS → Azure is deep (20 capability pairs, reverse generation too). Other clouds work but are thinner — unsupported services are called unsupported, not faked.
- Application Gateway output is a reviewed skeleton, not battle-tested L7 routing.
- Generated code has passed structural checks +
terraform plan -refresh=false(if you run it). It hasn't touched a real Azure subscription until you do.
Full architecture: docs/architecture.md
Development
136 tests — parsers, graph, adapters, scoring, determinism (golden files + sha256), validator, fuzzing, CLI e2e.
Emulator probes run against real LocalStack/Azurite in CI.
uv run pytest
uv run ruff check src tests scripts examples/plugins
License
Apache-2.0 — see LICENSE.
CloudPort is the portability layer for production infrastructure. If you move clouds twice a year, you shouldn't have to re-learn everything twice a year.
Built for teams who ship on Friday and migrate on Monday.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cloudport-0.2.0.tar.gz.
File metadata
- Download URL: cloudport-0.2.0.tar.gz
- Upload date:
- Size: 240.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.30 {"installer":{"name":"uv","version":"0.11.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f0308eda2b70738f21535e778cf1cabfa9f93b3b07ea2d5d64f1c417b673a83
|
|
| MD5 |
9331e5db0820cf58c7e538bab3c16b53
|
|
| BLAKE2b-256 |
8d9c3f2ec44f9da97c8b35dda18b5684ea61df56168f9e545e5717d27ea3a5fa
|
File details
Details for the file cloudport-0.2.0-py3-none-any.whl.
File metadata
- Download URL: cloudport-0.2.0-py3-none-any.whl
- Upload date:
- Size: 129.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.30 {"installer":{"name":"uv","version":"0.11.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8fee6034069b0672156ea9571c53ea26f66f270e84be348ebae18d3f29ef3f7
|
|
| MD5 |
f304788bcb50e792c5068324f6b84073
|
|
| BLAKE2b-256 |
2008da147cd2e804680bd9ed1ba96b5f8f3b4d15f9dfa73e135970854442d6b6
|