Skip to content
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"name": "migration-to-aws",
"source": "./plugins/migration-to-aws",
"tags": ["aws", "gcp", "migration", "infrastructure"],
"version": "1.0.0"
"version": "2.0.0"
},
{
"category": "development",
Expand Down
6 changes: 4 additions & 2 deletions plugins/migration-to-aws/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
"migration",
"cloud-migration",
"terraform",
"fargate"
"fargate",
"rds",
"eks"
],
"license": "Apache-2.0",
"name": "migration-to-aws",
"repository": "https://github.com/awslabs/agent-plugins",
"version": "1.0.0"
"version": "2.0.0"
}
1 change: 1 addition & 0 deletions plugins/migration-to-aws/.mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
],
"command": "uvx",
"env": {
"AWS_REGION": "us-east-1",
"FASTMCP_LOG_LEVEL": "ERROR"
},
"timeout": 120000,
Expand Down
32 changes: 22 additions & 10 deletions plugins/migration-to-aws/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
# GCP-to-AWS Migration Plugin

Migrate workloads from Google Cloud Platform to AWS with a 5-phase guided process.
Migrate workloads from Google Cloud Platform to AWS with a 6-phase guided process.

## Overview

This plugin guides you through migrating GCP infrastructure to AWS by:

1. **Discover** - Scan Terraform files for GCP resources
2. **Clarify** - Answer 8 questions about your migration requirements
1. **Discover** - Scan Terraform files, application code, and/or billing exports for GCP resources
2. **Clarify** - Answer adaptive questions about your migration requirements
3. **Design** - Map GCP services to equivalent AWS services
4. **Estimate** - Calculate monthly costs and ROI
5. **Execute** - Plan your migration timeline and rollback procedures
5. **Generate** - Generate Terraform, migration scripts, AI adapters, and documentation
6. **Feedback** - Collect optional feedback and migration trace (optional)

## Skills

| Skill | Description |
| ------------ | --------------------------------------------------------- |
| `gcp-to-aws` | Migrate GCP workloads to AWS via a 6-phase guided process |

## Usage

Expand All @@ -20,12 +27,13 @@ Invoke the skill with migration-related phrases:
- "Move off Google Cloud"
- "Migrate Cloud SQL to RDS"
- "GCP to AWS migration plan"
- "Migrate our Vertex AI workloads to Bedrock"
- "Estimate the cost of moving from GCP to AWS"

## Scope (v1.0)

- **Supports**: Terraform-based GCP infrastructure
- **Generates**: AWS architecture design, cost estimates, execution timeline
- **Does not include** (v1.1+): App code scanning, billing data import, CDK code generation
- **Supports**: Terraform IaC, application code (AI workload detection), and GCP billing exports
- **Generates**: AWS architecture design, cost estimates, Terraform configurations, migration scripts, AI migration code, and documentation

## MCP Servers

Expand All @@ -47,10 +55,14 @@ The plugin uses state files (`.migration/[MMDD-HHMM]/`) to track migration progr

- `.phase-status.json` - Current phase and status
- `gcp-resource-inventory.json` - Discovered GCP resources
- `clarified.json` - User requirements
- `preferences.json` - User requirements
- `aws-design.json` - Mapped AWS services
- `estimation.json` - Cost analysis
- `execution.json` - Timeline and risks
- `estimation-infra.json` / `estimation-ai.json` / `estimation-billing.json` - Cost analysis
- `generation-infra.json` / `generation-ai.json` / `generation-billing.json` - Migration plans
- `terraform/` - Generated Terraform configurations
- `scripts/` - Migration scripts
- `ai-migration/` - AI provider adapter and test harness
- `MIGRATION_GUIDE.md` - Step-by-step migration guide

## Installation

Expand Down
305 changes: 210 additions & 95 deletions plugins/migration-to-aws/skills/gcp-to-aws/SKILL.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,57 @@

Hardcoded lists for classifying GCP resources as PRIMARY or SECONDARY.

Each PRIMARY resource is assigned a `tier` indicating its infrastructure layer.

## Priority 1: PRIMARY Resources (Workload-Bearing)

These resource types are always PRIMARY:

### Compute (`tier: "compute"`)

- `google_cloud_run_service` — Serverless container workload
- `google_cloud_run_v2_service` — Serverless container workload (v2 API)
- `google_container_cluster` — Kubernetes cluster
- `google_container_node_pool` — Kubernetes node pool
- `google_compute_instance` — Virtual machine
- `google_cloudfunctions_function` — Serverless function
- `google_cloudfunctions_function` — Serverless function (Gen 1)
- `google_cloudfunctions2_function` — Serverless function (Gen 2)
- `google_app_engine_application` — App Engine application

### Database (`tier: "database"`)

- `google_sql_database_instance` — Relational database
- `google_firestore_database` — Document database (Firestore instance)
- `google_firestore_document` — Document database (Firestore document resource)
- `google_bigquery_dataset` — Data warehouse
- `google_storage_bucket` — Object storage
- `google_spanner_instance` — Globally-distributed relational database
- `google_firestore_database` — Document database
- `google_bigtable_instance` — Wide-column NoSQL database
- `google_redis_instance` — In-memory cache

### Storage (`tier: "storage"`)

- `google_storage_bucket` — Object storage
- `google_filestore_instance` — Managed NFS file storage
- `google_bigquery_dataset` — Data warehouse

### Messaging (`tier: "messaging"`)

- `google_pubsub_topic` — Message queue
- `google_compute_network` — Virtual network (VPC). Anchors the networking cluster (see clustering-algorithm.md Rule 1)
- `google_dns_managed_zone` — DNS zone
- `google_app_engine_application` — App Engine application
- `google_cloud_tasks_queue` — Task queue
- `google_compute_forwarding_rule` — Load balancer forwarding rule
- `module.*` — Terraform module (treated as primary container)

**Action**: Mark as `PRIMARY`, classification done. No secondary_role.
### Networking (`tier: "networking"`)

- `google_compute_network` — Virtual network (VPC — primary because it defines topology)
- `google_compute_security_policy` — Web application firewall (Cloud Armor)
- `google_dns_managed_zone` — DNS zone

### Monitoring (`tier: "monitoring"`)

- `google_monitoring_alert_policy` — Alert policy

### Other

- `module.*` — Terraform module that wraps primary resources (tier inferred from wrapped resource)

**Action**: Mark as `PRIMARY` with assigned `tier`. Classification done. No secondary_role.

## Priority 2: SECONDARY Resources by Role

Expand All @@ -33,10 +61,11 @@ Match resource type against secondary classification table. Each match assigns a
### Identity (`identity`)

- `google_service_account` — Workload identity
- `data.google_service_account` — Data source reference to existing service account

### Access Control (`access_control`)

- `google_*_iam_member` — IAM binding (all variants)
- `google_*_iam_member` — IAM binding (all variants: project, cloud_run_service, storage_bucket, etc.)
- `google_*_iam_policy` — IAM policy (all variants)

### Network Path (`network_path`)
Expand All @@ -46,15 +75,18 @@ Match resource type against secondary classification table. Each match assigns a
- `google_compute_firewall` — Firewall rule
- `google_compute_router` — Cloud router
- `google_compute_router_nat` — NAT rule
- `google_compute_global_address` — Global IP address (for VPC peering, load balancing)
- `google_service_networking_connection` — VPC peering

### Configuration (`configuration`)

- `google_sql_database` — SQL schema
- `google_sql_user` — SQL user
- `google_spanner_database` — Spanner database schema
- `google_secret_manager_secret` — Secret vault
- `google_secret_manager_secret_version` — Secret value
- `google_dns_record_set` — DNS record
- `google_monitoring_alert_policy` — Alert rule (skipped in design; no AWS equivalent)
- `google_monitoring_notification_channel` — Alert notification target

### Encryption (`encryption`)

Expand All @@ -71,21 +103,24 @@ Match resource type against secondary classification table. Each match assigns a

## Priority 3: LLM Inference Fallback

If resource type not in Priority 1 or 2, apply heuristic patterns:
If resource type not in Priority 1 or 2, apply these **deterministic fallback heuristics** BEFORE free-form LLM reasoning:

- Name contains `scheduler`, `task`, `job` → `SECONDARY` / `orchestration`
- Name contains `log`, `metric`, `alert`, `trace` → `SECONDARY` / `configuration`
- Type contains `policy` or `binding` → `SECONDARY` / `access_control`
- Type contains `network` or `subnet` → `SECONDARY` / `network_path`
| Pattern | Classification | secondary_role | confidence |
| ---------------------------------------------------- | ----------------- | -------------- | ---------- |
| Name contains `scheduler`, `task`, `job`, `workflow` | SECONDARY | orchestration | 0.65 |
| Name contains `log`, `metric`, `alert`, `dashboard` | SECONDARY | configuration | 0.60 |
| Resource has zero references to/from other resources | SECONDARY | configuration | 0.50 |
| Resource only referenced by a `module` block | SECONDARY | configuration | 0.55 |
| Type contains `policy` or `binding` | SECONDARY | access_control | 0.65 |
| Type contains `network` or `subnet` | SECONDARY | network_path | 0.60 |
| None of the above match | Use LLM reasoning | — | 0.50-0.75 |

**Default**: If all heuristics fail: `SECONDARY` / `configuration` with confidence 0.5
If still uncertain after heuristics, use LLM reasoning. Mark with:

**Downstream flagging for low-confidence classifications**: Any resource classified with confidence ≤ 0.5 (including the default fallback) MUST be:
- `classification_source: "llm_inference"`
- `confidence: 0.5-0.75`

1. Flagged in `gcp-resource-inventory.json` with `"confidence": 0.5` on the resource entry
2. Added to a `low_confidence_resources[]` warning array in inventory metadata
3. Reported to the user during Phase 1 completion: "⚠️ N resources were classified with low confidence and may need manual review: [list of addresses]"
4. Passed through to Phase 3 (Design) where they appear in `warnings[]` as: "Low-confidence classification for [address] (classified as [role]). Verify AWS mapping is correct."
**Default**: If all heuristics and LLM fail: `SECONDARY` / `configuration` with confidence 0.5. It is safer to under-classify (secondary) than over-classify (primary), because secondaries are grouped into existing clusters while primaries create new clusters.

## Serves[] Population

Expand All @@ -95,6 +130,6 @@ For SECONDARY resources, populate `serves[]` array (list of PRIMARY resources it
2. Include direct references: `field = resource_type.name.id` patterns
3. Include transitive chains: if referenced resource is also SECONDARY, trace to PRIMARY

**Example**: `google_compute_firewall` → references `google_compute_network` (PRIMARY, network cluster anchor). The firewall is a `network_path` SECONDARY that serves the network cluster. Its `serves[]` includes the PRIMARY `google_compute_network.vpc`.
**Example**: `google_compute_firewall` → references `google_compute_network` (SECONDARY) → serves `google_compute_instance.web` (PRIMARY)

**Serves array**: Points to the PRIMARY resources this SECONDARY supports. For `network_path` secondaries, this is the `google_compute_network` PRIMARY that anchors the network cluster (see clustering-algorithm.md Rule 1).
**Serves array**: Points back to PRIMARY workloads affected by this firewall rule. Trace through SECONDARY resources until a PRIMARY is reached.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ All resources with fields:
**IF** `google_compute_network` resource exists:

- Group: `google_compute_network` + ALL network_path secondaries (subnetworks, firewalls, routers)
- Cluster ID: `network_vpc_{gcp_region}_{sequence}` (e.g., `network_vpc_us-central1_001`)
- Cluster ID: `networking_vpc_{gcp_region}_001` (e.g., `networking_vpc_us-central1_001`)
- **Reasoning**: Network is shared infrastructure; groups all config together

**Output**: 1 cluster (or 0 if no networks found)
Expand Down Expand Up @@ -70,7 +70,7 @@ All resources with fields:

**Output**: ONE cluster per resource type (not per resource)

**Reasoning**: Identical workloads of the same GCP service type migrate together, share operational characteristics, and should be managed as a unit.
**Reasoning**: Identical workloads of the same GCP service type migrate together, share operational characteristics, and are managed as a unit.

**Mark all resources of this type as clustered; remove from unassigned pool.**

Expand All @@ -89,16 +89,15 @@ All resources with fields:

### Rule 4: Merge on Dependencies

**IF** two clusters have bidirectional or data_dependency edges between their PRIMARY resources:
**IF** two clusters have **bidirectional** `data_dependency` edges between their PRIMARY resources (A→B AND B→A):

- **AND** they form a single logical deployment unit (determined by: shared infrastructure, sequential deploy, business logic)
- **THEN** merge clusters

**Action**: Combine into one cluster; update ID to reflect both (e.g., `web-api_us-central1_001`)

**Reasoning**: Some workloads must deploy together (e.g., two Cloud Runs sharing database)
**Reasoning**: Bidirectional data dependencies indicate a tightly coupled deployment unit that must migrate together.

**Heuristic**: Merge if one PRIMARY depends on another's output (e.g., Function → Database). Do NOT merge independent workloads.
**Do NOT merge** when edges are unidirectional (A→B only). Unidirectional dependencies are captured in `dependencies[]` instead.

### Rule 5: Skip API Services

Expand All @@ -115,7 +114,7 @@ All resources with fields:
Apply consistent cluster naming:

- **Format**: `{service_category}_{service_type}_{gcp_region}_{sequence}`
- **service_category**: One of: `compute`, `database`, `storage`, `network`, `messaging`, `analytics`, `security`
- **service_category**: One of: `compute`, `database`, `storage`, `networking`, `messaging`, `monitoring`, `analytics`, `security`
- **service_type**: GCP service shortname (e.g., `cloudrun`, `sql`, `bucket`, `vpc`)
- **gcp_region**: Source region (e.g., `us-central1`)
- **sequence**: Zero-padded counter (e.g., `001`, `002`)
Expand All @@ -125,36 +124,76 @@ Apply consistent cluster naming:
- `compute_cloudrun_us-central1_001`
- `database_sql_us-west1_001`
- `storage_bucket_multi-region_001`
- `network_vpc_us-central1_001` (rule 1 network cluster)
- `networking_vpc_us-central1_001` (rule 1 network cluster)

**Reasoning**: Names reflect deployment intent; deterministic for reproducibility.

## Post-Clustering: Populate Cluster Metadata

After all clusters are formed, populate these fields for each cluster:

### `network`

Identify which VPC/network the cluster's resources belong to. Trace `network_path` edges from resources in this cluster to find the `google_compute_network` they reference. Store the network cluster ID (e.g., `networking_vpc_us-central1_001`). Set to `null` if resources have no network association.

### `must_migrate_together`

Default: `true` for all clusters. Set to `false` only if the cluster contains resources that can be independently migrated without breaking dependencies (rare — most clusters are atomic).

### `dependencies`

Derive from Primary→Primary edges that cross cluster boundaries. If cluster A contains a resource with a `data_dependency` edge to a resource in cluster B, then cluster A depends on cluster B. Store as array of cluster IDs.

### `creation_order`

Build a global ordering of clusters by depth level:

```json
"creation_order": [
{ "depth": 0, "clusters": ["networking_vpc_us-central1_001"] },
{ "depth": 1, "clusters": ["security_iam_us-central1_001"] },
{ "depth": 2, "clusters": ["database_sql_us-central1_001", "storage_gcs_us-central1_001"] },
{ "depth": 3, "clusters": ["compute_cloudrun_us-central1_001"] }
]
```

Cluster depth = minimum depth across all primary resources in the cluster. Clusters at the same depth can be migrated in parallel.

## Output Cluster Schema

Each cluster includes:

```json
{
"cluster_id": "compute_cloudrun_us-central1_001",
"name": "Cloud Run Application",
"type": "compute",
"description": "Primary: cloud_run_service.app, Secondary: service_account, iam_policy",
"gcp_region": "us-central1",
"primary_resources": ["google_cloud_run_service.app"],
"secondary_resources": ["google_service_account.app_runner"],
"network": "network_vpc_us-central1_001",
"network": "networking_vpc_us-central1_001",
"creation_order_depth": 2,
"must_migrate_together": true,
"dependencies": [],
"edges": [{ "from": "...", "to": "...", "relationship_type": "..." }]
"dependencies": ["database_sql_us-central1_001"],
"edges": [
{
"from": "google_cloud_run_service.app",
"to": "google_sql_database_instance.db",
"relationship_type": "data_dependency",
"evidence": {
"field_path": "template.spec.containers[0].env[].value",
"reference": "DATABASE_URL"
}
}
]
}
```

## Determinism Guarantee

Given same Terraform input, algorithm produces same cluster structure every run:
Given the same classified resource inputs, the clustering algorithm produces the same cluster structure every run:

1. Rules applied in fixed order
2. Sequence counters increment deterministically
3. Naming reflects source state, not random IDs
4. Deterministic for Priority 1 and Priority 2 resources. Priority 3 (LLM inference fallback in classification-rules.md and typed-edges-strategy.md) may produce non-deterministic results for unknown resource types
4. All clustering heuristics are deterministic (no LLM-based decisions within the clustering algorithm itself)

**Note:** Resource classification (see `classification-rules.md`) may use LLM inference as a fallback for resource types not in the hardcoded tables. If LLM-classified resources enter the pipeline, overall reproducibility depends on the LLM producing consistent classifications.
Loading
Loading