From e5746638bbf1b725dc4e602e4a59e9c12e2bf23f Mon Sep 17 00:00:00 2001 From: Madhura Bharadwaj Date: Thu, 26 Feb 2026 10:20:39 -0600 Subject: [PATCH 01/31] Add azure-migrate skill with Lambda-to-Functions migration learnings - SKILL.md with 13 rules and comprehensive error handling - Assessment, code-migration, and global-rules references - Lambda-to-Functions service mapping with EventGrid Bicep patterns - JavaScript/TypeScript/Python/C#/Java/PowerShell runtime references - Proposed updates for azure-prepare, azure-validate, azure-deploy - Captures 7 key learnings from real Flex Consumption + EventGrid migration --- plugin/skills/azure-migrate/SKILL.md | 113 ++++++ .../azure-migrate/references/assessment.md | 171 +++++++++ .../references/code-migration.md | 138 +++++++ .../azure-migrate/references/global-rules.md | 51 +++ .../references/proposed-updates/README.md | 11 + .../azure-deploy-troubleshooting.md | 84 +++++ .../azure-prepare-security.md | 52 +++ .../proposed-updates/azure-validate-checks.md | 46 +++ .../references/runtimes/csharp.md | 225 +++++++++++ .../azure-migrate/references/runtimes/java.md | 214 +++++++++++ .../references/runtimes/javascript.md | 284 ++++++++++++++ .../references/runtimes/powershell.md | 221 +++++++++++ .../references/runtimes/python.md | 200 ++++++++++ .../references/runtimes/typescript.md | 119 ++++++ .../services/lambda-to-functions.md | 352 ++++++++++++++++++ 15 files changed, 2281 insertions(+) create mode 100644 plugin/skills/azure-migrate/SKILL.md create mode 100644 plugin/skills/azure-migrate/references/assessment.md create mode 100644 plugin/skills/azure-migrate/references/code-migration.md create mode 100644 plugin/skills/azure-migrate/references/global-rules.md create mode 100644 plugin/skills/azure-migrate/references/proposed-updates/README.md create mode 100644 plugin/skills/azure-migrate/references/proposed-updates/azure-deploy-troubleshooting.md create mode 100644 plugin/skills/azure-migrate/references/proposed-updates/azure-prepare-security.md create mode 100644 plugin/skills/azure-migrate/references/proposed-updates/azure-validate-checks.md create mode 100644 plugin/skills/azure-migrate/references/runtimes/csharp.md create mode 100644 plugin/skills/azure-migrate/references/runtimes/java.md create mode 100644 plugin/skills/azure-migrate/references/runtimes/javascript.md create mode 100644 plugin/skills/azure-migrate/references/runtimes/powershell.md create mode 100644 plugin/skills/azure-migrate/references/runtimes/python.md create mode 100644 plugin/skills/azure-migrate/references/runtimes/typescript.md create mode 100644 plugin/skills/azure-migrate/references/services/lambda-to-functions.md diff --git a/plugin/skills/azure-migrate/SKILL.md b/plugin/skills/azure-migrate/SKILL.md new file mode 100644 index 00000000..21ba623e --- /dev/null +++ b/plugin/skills/azure-migrate/SKILL.md @@ -0,0 +1,113 @@ +```skill +--- +name: azure-migrate +description: "Assess and migrate applications to Azure, including AWS Lambda to Azure Functions migration. USE FOR: migrate Lambda to Functions, migrate AWS to Azure, Lambda migration assessment, migrate serverless to Azure, convert Lambda to Functions, AWS to Azure migration, migration readiness, migration assessment report, migrate code to Azure Functions. Handles assessment and code migration, then hands off to azure-prepare for IaC, azure-validate for validation, and azure-deploy for deployment. DO NOT USE FOR: creating new Azure apps from scratch (use azure-prepare), generating IaC from scratch (use azure-prepare), deploying apps (use azure-deploy), validating existing Azure configs (use azure-validate)." +--- + +# Azure Migrate + +> **AUTHORITATIVE GUIDANCE — MANDATORY COMPLIANCE** +> +> This skill handles **assessment and code migration** of existing cloud workloads to Azure. +> After migration, hand off to **azure-prepare → azure-validate → azure-deploy** for infrastructure, validation, and deployment. + +## Quick Reference + +| Property | Value | +|----------|-------| +| **Best For** | Assessing & migrating AWS Lambda → Azure Functions code | +| **Prereqs** | Source project in workspace | +| **Outputs** | Assessment report, migrated function code, migration status | +| **MCP Tools** | `get_bestpractices`, `documentation` | +| **Handoff** | → azure-prepare → azure-validate → azure-deploy | + +## Triggers + +Activate this skill when user wants to: +- Migrate AWS Lambda functions to Azure Functions +- Assess an AWS Lambda project for Azure migration readiness +- Convert serverless code from AWS to Azure +- Generate a migration assessment report + +## Rules + +1. Follow phases sequentially — do not skip +2. Generate assessment report before any code migration +3. Use Azure Functions best practices from `get_bestpractices` tool +4. **Always use bindings and triggers instead of SDKs** — Use `input.storageBlob()`, `output.storageBlob()`, `app.storageQueue()`, etc. for all storage and queue operations. Only fall back to SDK when no binding exists for the target service (e.g., Azure AI Face API) +5. **Always use the latest supported language runtime** — Check [supported languages](https://learn.microsoft.com/en-us/azure/azure-functions/supported-languages) and use the newest GA version (e.g., Node.js 22, Python 3.11, .NET 8). Never default to older LTS versions when a newer one is supported +6. Update migration status after each phase +7. After code migration, hand off to **azure-prepare** for IaC generation +8. ⛔ **Destructive actions require `ask_user`** — [global-rules](references/global-rules.md) +9. **Blob trigger + EventGrid source on Flex Consumption requires always-ready** — Configure `alwaysReady: [{ name: 'blob', instanceCount: 1 }]` to avoid the bootstrap problem where the trigger group never starts +10. **EventGrid source blob triggers require queue endpoint** — Always provision `AzureWebJobsStorage__queueServiceUri` alongside the blob endpoint — the blob extension uses queues internally for poison-message tracking +11. **Deploy Event Grid subscriptions via Bicep/ARM, not CLI** — CLI webhook validation times out on Flex Consumption. Use `listKeys()` in Bicep to get the `blobs_extension` system key at deployment time +12. **UAMI requires explicit client ID in DefaultAzureCredential** — Always pass `{ managedIdentityClientId: process.env.AZURE_CLIENT_ID }` when using User Assigned Managed Identity +13. **Pin beta Azure SDK versions explicitly** — Some Azure SDKs (e.g., `@azure-rest/ai-vision-image-analysis`) are beta-only. Use exact versions like `1.0.0-beta.3` — semver ranges like `^1.0.0` won't resolve + +## Migration Scenarios + +| Scenario | Reference | +|----------|-----------| +| AWS Lambda → Azure Functions | [services/lambda-to-functions.md](references/services/lambda-to-functions.md) | + +## Steps + +| # | Action | Reference | +|---|--------|-----------| +| 1 | **Assess** — Analyze source project, map services, generate assessment report | [assessment.md](references/assessment.md) | +| 2 | **Migrate Code** — Convert functions using target programming model | [code-migration.md](references/code-migration.md) | +| 3 | **Hand Off** — Invoke **azure-prepare** with assessment context for IaC, then **azure-validate** and **azure-deploy** | — | + +## Handoff to Azure Pipeline + +After completing assessment and code migration: + +1. **→ azure-prepare** — Generates IaC (Bicep/Terraform), `azure.yaml`, security hardening, and `.azure/preparation-manifest.md`. The assessment report's service mapping table provides the requirements input, replacing the manual "gather requirements" step. +2. **→ azure-validate** — Validates IaC, code structure, and deployment readiness. +3. **→ azure-deploy** — Deploys validated project to Azure via `azd up` or equivalent. + +> 💡 **Tip:** The assessment report produced in Phase 1 contains the service mapping and architecture that azure-prepare needs. Pass this context when invoking azure-prepare. + +## MCP Tools + +| Tool | Purpose | When | +|------|---------|------| +| `get_bestpractices` | Azure Functions code gen best practices | Phase 2 | +| `documentation` | Azure docs for service mapping | Phase 1 | + +## Status Tracking + +Maintain a `migration-status.md` file in the workspace root: + +```markdown +# Migration Status +| Phase | Status | Notes | +|-------|--------|-------| +| Assessment | ⬜ Not Started | | +| Code Migration | ⬜ Not Started | | +| Handoff to azure-prepare | ⬜ Not Started | | +``` + +Update status: ⬜ Not Started → 🔄 In Progress → ✅ Complete → ❌ Failed + +## Error Handling + +| Error | Cause | Remediation | +|-------|-------|-------------| +| Unsupported runtime | Lambda runtime not available in Functions | Check [supported languages](https://learn.microsoft.com/en-us/azure/azure-functions/supported-languages) | +| Missing service mapping | AWS service has no direct Azure equivalent | Use closest Azure alternative, document in assessment | +| Code migration failure | Incompatible patterns or dependencies | Review scenario guide in [services/](references/services/) | +| Blob trigger never fires (Flex Consumption) | Missing always-ready config for EventGrid source | Add `alwaysReady: [{ name: 'blob', instanceCount: 1 }]` to Bicep | +| QueueServiceClient constructor error | Missing queue endpoint for EventGrid source blob trigger | Add `AzureWebJobsStorage__queueServiceUri` app setting | +| Event Grid subscription creation fails via CLI | Webhook validation handshake timeout | Deploy via Bicep/ARM instead — see [lambda-to-functions.md](references/services/lambda-to-functions.md) | +| DefaultAzureCredential auth failure | UAMI not specified, trying SystemAssigned | Pass `{ managedIdentityClientId: process.env.AZURE_CLIENT_ID }` | +| RequestDisallowedByPolicy on Cognitive Services | Enterprise policy requires `disableLocalAuth: true` | Set `disableLocalAuth: true`, use UAMI + Cognitive Services User RBAC | +| npm install resolves no version for `^1.0.0` | Azure SDK package is beta-only | Pin exact beta version (e.g., `1.0.0-beta.3`) | +| `azd init` refuses non-empty directory | azd requires clean directory for template init | Use temp directory approach: init in empty dir, copy files back | + +## Next + +**→ Invoke azure-prepare to generate infrastructure and prepare for deployment** + +``` diff --git a/plugin/skills/azure-migrate/references/assessment.md b/plugin/skills/azure-migrate/references/assessment.md new file mode 100644 index 00000000..19db2dc9 --- /dev/null +++ b/plugin/skills/azure-migrate/references/assessment.md @@ -0,0 +1,171 @@ +# Assessment Phase + +Generate a migration assessment report before any code changes. + +## Prerequisites + +- Workspace contains AWS Lambda functions, SAM templates, or CloudFormation templates +- Prompt user to upload relevant files if not present + +## Assessment Steps + +1. **Identify Functions** — List all Lambda functions with runtimes, triggers, and dependencies +2. **Map AWS Services** — Map AWS services to Azure equivalents (see [lambda-to-functions.md](services/lambda-to-functions.md)) +3. **Map Properties** — Map Lambda properties to Azure Functions properties +4. **Check Dependencies** — List 3rd-party libraries and verify Azure compatibility +5. **Analyze Code** — Check language support and runtime differences +6. **Map Triggers** — Identify equivalent Azure Functions triggers +7. **Map Deployment** — Identify equivalent Azure deployment strategies (CLI, Bicep, azd) +8. **Review CI/CD** — Check pipeline compatibility with Azure DevOps or GitHub Actions +9. **Map Monitoring** — Map CloudWatch → Application Insights / Azure Monitor + +## Code Preview + +During assessment, show a **sneak peek** of what the migrated Azure Functions code will look like for each function. Use bindings and triggers (not SDKs) in all previews, following Azure Functions best practices. **Always use the latest supported language runtime** in previews (e.g., Node.js 22, Python 3.11). This helps the user understand the migration scope before committing to code migration. + +> ⚠️ **Binding-first rule**: Code previews MUST use `input.storageBlob()`, `output.storageBlob()`, `app.storageQueue()`, etc. instead of `BlobServiceClient`, `QueueClient`, or other SDK clients. Only use SDK for services that have no binding equivalent. + +## Architecture Diagrams + +Generate two diagrams: +1. **Current State** — AWS Lambda architecture with triggers and integrations +2. **Target State** — Azure Functions architecture showing equivalent structure + +## Assessment Report Format + +> ⚠️ **MANDATORY**: Use these exact section headings in every assessment report. Do NOT rename, reorder, or omit sections. + +The report MUST be saved as `migration-assessment-report.md` in the workspace root. + +```markdown +# Migration Assessment Report + +## 1. Executive Summary + +| Property | Value | +|----------|-------| +| **Total Functions** | | +| **Source Platform** | AWS Lambda | +| **Source Runtime** | | +| **Target Platform** | Azure Functions | +| **Target Runtime** | | +| **Migration Readiness** | | +| **Estimated Effort** | | +| **Assessment Date** | | + +## 2. Functions Inventory + +| # | Function Name | Runtime | Trigger Type | Memory (MB) | Timeout (s) | Description | +|---|--------------|---------|-------------- |-------------|-------------|-------------| +| 1 | | | | | | | + +## 3. Service Mapping + +| AWS Service | Azure Equivalent | Migration Complexity | Notes | +|-------------|------------------|----------------------|-------| +| Lambda | Azure Functions | | | +| API Gateway | Azure Functions HTTP Trigger / APIM | | | +| S3 | Azure Blob Storage | | | +| DynamoDB | Cosmos DB | | | +| SQS | Service Bus / Storage Queue | | | +| SNS | Event Grid | | | +| CloudWatch | Application Insights / Azure Monitor | | | +| IAM Roles | Managed Identity + RBAC | | | +| CloudFormation / SAM | Bicep / ARM Templates | | | + +## 4. Trigger & Binding Mapping + +| # | Function Name | AWS Trigger | Azure Trigger | AWS Inputs/Outputs | Azure Bindings | Notes | +|---|--------------|-------------|---------------|--------------------| ---------------|-------| +| 1 | | | | | | | + +## 5. Dependencies Analysis + +| # | Package/Library | Version | AWS-Specific? | Azure Equivalent | Compatible? | Notes | +|---|----------------|---------|---------------|------------------|-------------|-------| +| 1 | | | | | | | + +## 6. Environment Variables & Configuration + +| # | AWS Variable | Purpose | Azure Equivalent | Auth Method | Notes | +|---|-------------|---------|------------------|-------------|-------| +| 1 | | | | Managed Identity / App Setting | | + +## 7. Architecture Diagrams + +### 7a. Current State (AWS) + + + +### 7b. Target State (Azure) + + + +## 8. IAM & Security Mapping + +| AWS IAM Role/Policy | Azure RBAC Role | Scope | Notes | +|---------------------|-----------------|-------|-------| +| | | | | + +## 9. Monitoring & Observability Mapping + +| AWS Service | Azure Equivalent | Migration Notes | +|-------------|------------------|-----------------| +| CloudWatch Logs | Application Insights | | +| CloudWatch Metrics | Azure Monitor Metrics | | +| CloudWatch Alarms | Azure Monitor Alerts | | +| X-Ray | Application Insights (distributed tracing) | | + +## 10. CI/CD & Deployment Mapping + +| AWS Tool | Azure Equivalent | Notes | +|----------|------------------|-------| +| SAM CLI | Azure Functions Core Tools / azd | | +| CloudFormation | Bicep / ARM Templates | | +| CodePipeline | Azure DevOps Pipelines / GitHub Actions | | +| CodeBuild | Azure DevOps Build / GitHub Actions | | + +## 11. Project Structure Comparison + +| AWS Lambda Structure | Azure Functions Structure | +|---------------------|--------------------------| +| `template.yaml` (SAM) | `host.json` | +| `handler.js / handler.py` | `src/app.js` / `src/function_app.py` | +| `requirements.txt` / `package.json` | `requirements.txt` / `package.json` | +| Per-function directories (optional) | Single entry point (v4 JS / v2 Python) | +| `event` object | Trigger-specific parameter | +| `context` object | `InvocationContext` | + +## 12. Risks & Mitigations + +| # | Risk | Severity | Mitigation | +|---|------|----------|------------| +| 1 | | High / Medium / Low | | + +> **⚠️ Include these risks when they apply to the migration:** +> +> | Risk | Severity | When It Applies | Mitigation | +> |------|----------|-----------------|------------| +> | Blob trigger with EventGrid source requires always-ready instances on Flex Consumption (bootstrap problem) | High | S3 event → Blob trigger + EventGrid | Configure `alwaysReady: [{ name: 'blob', instanceCount: 1 }]` in Flex Consumption | +> | Blob extension requires queue endpoint even when not using queue triggers | High | Any blob trigger with `source: 'EventGrid'` | Enable `AzureWebJobsStorage__queueServiceUri` + Storage Queue Data Contributor RBAC | +> | Event Grid subscription must be deployed via Bicep/ARM, not CLI | High | EventGrid source blob triggers | Use Bicep with `listKeys()` for webhook URL — CLI webhook validation times out on Flex Consumption | +> | Azure AI Vision SDK is beta-only | Medium | Rekognition → Azure AI Computer Vision | Pin exact beta version (e.g., `1.0.0-beta.3`); `^1.0.0` semver won't resolve | +> | `azd init` refuses non-empty directories | Low | Any migration adding azd to existing project | Use temp directory approach: init in empty dir, copy infra files back | +> | DefaultAzureCredential tries System Assigned identity first | Medium | UAMI-based auth for Azure AI or other SDK services | Pass `{ managedIdentityClientId: process.env.AZURE_CLIENT_ID }` explicitly | + +## 13. Recommendations + +1. **Runtime**: +2. **Hosting Plan**: +3. **IaC Strategy**: +4. **Auth Strategy**: +5. **Monitoring**: + +## 14. Next Steps + +- [ ] Review and approve this assessment report +- [ ] Proceed to code migration (azure-migrate Phase 2) +- [ ] Hand off to azure-prepare for IaC generation +``` + +> 💡 **Tip:** Use `get_bestpractices` tool to learn Azure Functions project structure best practices for the comparison. diff --git a/plugin/skills/azure-migrate/references/code-migration.md b/plugin/skills/azure-migrate/references/code-migration.md new file mode 100644 index 00000000..0e064079 --- /dev/null +++ b/plugin/skills/azure-migrate/references/code-migration.md @@ -0,0 +1,138 @@ +# Code Migration Phase + +Migrate AWS Lambda function code to Azure Functions. + +## Prerequisites + +- Assessment report completed +- Azure Functions extension installed in VS Code +- Best practices loaded via `get_bestpractices` tool + +## Rules + +- If runtime is Python or Node.js: **do NOT create function.json files** +- If runtime is .NET, PowerShell, or Java: create function.json with bindings +- Use extension bundle version `[4.*, 5.0.0)` in host.json +- Use latest programming model (v4 for JavaScript, v2 for Python) +- **Always use bindings and triggers instead of SDKs** — For blob read/write, use `input.storageBlob()` / `output.storageBlob()` with `extraInputs`/`extraOutputs`. For queues, use `app.storageQueue()` or `app.serviceBusQueue()`. Only use SDK when there is no equivalent binding (e.g., Azure AI, custom HTTP calls) +- **Always use the latest supported language runtime** — Consult [supported languages](https://learn.microsoft.com/en-us/azure/azure-functions/supported-languages) and select the newest GA version. Do NOT default to an older LTS version when a newer version is available on Azure Functions (e.g., use Node.js 22, not Node.js 20) + +## Steps + +1. **Install Azure Functions Extension** — Ensure VS Code extension is installed +2. **Load Best Practices** — Use `get_bestpractices` tool for code generation guidance +3. **Create Project Structure** — Set up standard Azure Functions project layout +4. **Migrate Functions** — Convert each Lambda function to Azure Functions equivalent +5. **Update Dependencies** — Replace AWS SDKs with Azure SDKs in package.json / requirements.txt +6. **Configure Bindings** — Set up triggers and bindings inline (v4 JS / v2 Python) +7. **Configure Environment** — Map Lambda env vars to Azure Functions app settings +8. **Add Error Handling** — Ensure proper error handling in all functions + +## Key Configuration Files + +### host.json + +```json +{ + "version": "2.0", + "extensionBundle": { + "id": "Microsoft.Azure.Functions.ExtensionBundle", + "version": "[4.*, 5.0.0)" + }, + "extensions": { + "queues": { + "maxPollingInterval": "00:00:02", + "visibilityTimeout": "00:00:30", + "batchSize": 1, + "maxDequeueCount": 5 + } + }, + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + } + } + } +} +``` + +## Critical Infrastructure Dependencies + +### Blob Trigger with EventGrid Source — Additional Requirements + +When migrating S3 event triggers to Azure blob triggers with `source: 'EventGrid'`, the following infrastructure must be configured **at the IaC level** (not code level). Failure to set these up results in silent trigger failures. + +| Requirement | Why | Consequence of Missing | +|------------|-----|----------------------| +| **Queue endpoint** (`AzureWebJobsStorage__queueServiceUri`) | Blob extension uses queues internally for poison-message tracking with EventGrid source | Function fails to index: "Unable to find matching constructor...QueueServiceClient" | +| **Always-ready instances** (Flex Consumption only) | Blob trigger group must be running to register the Event Grid webhook | Trigger group never starts → webhook never registered → events never delivered | +| **Event Grid subscription via Bicep/ARM** | CLI-based webhook validation handshake times out on Flex Consumption | Use `listKeys()` in Bicep to obtain the `blobs_extension` system key at deployment time | +| **Storage Queue Data Contributor** RBAC | Identity-based queue access for poison messages | 403 errors during blob trigger indexing | + +See [lambda-to-functions.md](services/lambda-to-functions.md#flex-consumption--blob-trigger-with-eventgrid-source) for Bicep patterns. + +### UAMI Credential Pattern + +When using User Assigned Managed Identity (UAMI), `DefaultAzureCredential()` without arguments tries System Assigned first and fails. Always pass the client ID: + +```javascript +const credential = new DefaultAzureCredential({ + managedIdentityClientId: process.env.AZURE_CLIENT_ID +}); +``` + +Add `AZURE_CLIENT_ID` as an app setting in Bicep pointing to the UAMI client ID. + +### azd init Workaround for Non-Empty Directories + +`azd init --template