From c43df6f36f2868979285bf0b0e996171b68d0660 Mon Sep 17 00:00:00 2001 From: genglu Date: Sun, 7 Jun 2026 19:01:21 +0800 Subject: [PATCH] feat: add azure-cli-patterns skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new core skill covering Azure CLI best practices for scripting, automation, and resource management. Includes authentication patterns, JMESPath queries, idempotent scripts, and CI/CD integration. - SKILL.md with 8 sections covering common az patterns - 7 test scenarios with acceptance criteria - README updated (174 → 175 skills, Core 10 → 11) --- .github/skills/azure-cli-patterns/SKILL.md | 323 ++++++++++++++++++ README.md | 9 +- .../azure-cli-patterns/acceptance-criteria.md | 201 +++++++++++ .../azure-cli-patterns/scenarios.yaml | 268 +++++++++++++++ 4 files changed, 797 insertions(+), 4 deletions(-) create mode 100644 .github/skills/azure-cli-patterns/SKILL.md create mode 100644 tests/scenarios/azure-cli-patterns/acceptance-criteria.md create mode 100644 tests/scenarios/azure-cli-patterns/scenarios.yaml diff --git a/.github/skills/azure-cli-patterns/SKILL.md b/.github/skills/azure-cli-patterns/SKILL.md new file mode 100644 index 00000000..9b837695 --- /dev/null +++ b/.github/skills/azure-cli-patterns/SKILL.md @@ -0,0 +1,323 @@ +--- +name: azure-cli-patterns +description: >- + Azure CLI best practices and common patterns for scripting, automation, and resource management. + Use when writing az commands, building deployment scripts, automating Azure operations in CI/CD, + or troubleshooting CLI issues. Triggers: "az command", "azure cli", "az group", "az vm", + "az aks", "shell script azure", "az login", "az deployment", "az resource". +--- + +# Azure CLI Patterns + +Best practices and reusable patterns for Azure CLI (`az`) scripting, automation, and resource management. + +## Installation & Configuration + +```bash +# Install (macOS) +brew install azure-cli + +# Install (Linux) +curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash + +# Upgrade +az upgrade + +# Set defaults to avoid repetitive flags +az configure --defaults group=myResourceGroup location=eastus +``` + +--- + +## Authentication Patterns + +| Method | Use Case | Command | +|--------|----------|---------| +| **Interactive** | Local development, manual operations | `az login` | +| **Service Principal** | CI/CD pipelines, automation scripts | `az login --service-principal` | +| **Managed Identity** | Azure-hosted VMs, Container Apps, Functions | `az login --identity` | +| **Device Code** | Environments without browser | `az login --use-device-code` | + +### Service Principal (CI/CD) + +```bash +# Login with service principal (preferred for automation) +az login --service-principal \ + --username "$AZURE_CLIENT_ID" \ + --password "$AZURE_CLIENT_SECRET" \ + --tenant "$AZURE_TENANT_ID" + +# Set subscription context +az account set --subscription "$AZURE_SUBSCRIPTION_ID" +``` + +### Managed Identity (Azure-hosted) + +```bash +# System-assigned managed identity +az login --identity + +# User-assigned managed identity +az login --identity --username "$MANAGED_IDENTITY_CLIENT_ID" +``` + +--- + +## Output & Query Patterns + +### Output Formats + +| Format | Use Case | Flag | +|--------|----------|------| +| `json` | Programmatic processing (default) | `--output json` | +| `table` | Human-readable display | `--output table` | +| `tsv` | Shell variable assignment, piping | `--output tsv` | +| `yaml` | Configuration files, readability | `--output yaml` | +| `none` | Suppress output (write operations) | `--output none` | + +### JMESPath Queries (`--query`) + +```bash +# Get single value +az vm show -g myRG -n myVM --query "powerState" --output tsv + +# Get multiple fields +az vm list --query "[].{Name:name, Size:hardwareProfile.vmSize, State:powerState}" --output table + +# Filter results +az vm list --query "[?powerState=='VM running'].name" --output tsv + +# Nested access +az aks show -g myRG -n myAKS --query "agentPoolProfiles[0].count" --output tsv + +# Array indexing +az account list --query "[0].id" --output tsv +``` + +--- + +## Resource Management Patterns + +### Resource Group Lifecycle + +```bash +# Create +az group create --name myRG --location eastus --tags env=dev team=platform + +# List with filter +az group list --query "[?tags.env=='dev'].name" --output tsv + +# Delete (with confirmation bypass for scripts) +az group delete --name myRG --yes --no-wait +``` + +### Common Resource Operations + +```bash +# Create a Storage Account +az storage account create \ + --name mystorageacct \ + --resource-group myRG \ + --sku Standard_LRS \ + --kind StorageV2 + +# Create an AKS cluster +az aks create \ + --resource-group myRG \ + --name myAKS \ + --node-count 3 \ + --enable-managed-identity \ + --generate-ssh-keys + +# Deploy a Web App +az webapp create \ + --resource-group myRG \ + --plan myPlan \ + --name myApp \ + --runtime "NODE:20-lts" + +# Create Azure SQL +az sql server create \ + --resource-group myRG \ + --name mysqlserver \ + --admin-user azureuser \ + --admin-password "$SQL_ADMIN_PASSWORD" +``` + +### Batch Operations + +```bash +# Delete all VMs in a resource group +az vm list -g myRG --query "[].id" --output tsv | xargs -I {} az vm delete --ids {} --yes --no-wait + +# Tag all resources in a group +az resource list -g myRG --query "[].id" --output tsv | \ + xargs -I {} az resource tag --ids {} --tags env=production + +# Stop all running VMs +az vm list -g myRG --query "[?powerState=='VM running'].id" --output tsv | \ + xargs -I {} az vm stop --ids {} --no-wait +``` + +--- + +## Scripting Best Practices + +### Error Handling + +```bash +#!/bin/bash +set -euo pipefail + +# Trap errors for cleanup +cleanup() { echo "Cleaning up..."; } +trap cleanup EXIT + +# Check command success explicitly +if ! az group show --name myRG &>/dev/null; then + echo "Resource group does not exist, creating..." + az group create --name myRG --location eastus --output none +fi +``` + +### Idempotent Scripts + +```bash +# Pattern: create-if-not-exists +az group create --name myRG --location eastus --output none 2>/dev/null || true + +# Pattern: check-then-create +if ! az storage account show --name mystorageacct --resource-group myRG &>/dev/null; then + az storage account create \ + --name mystorageacct \ + --resource-group myRG \ + --sku Standard_LRS \ + --output none +fi + +# Pattern: use --only-show-errors to suppress warnings on re-runs +az role assignment create \ + --assignee "$PRINCIPAL_ID" \ + --role "Contributor" \ + --scope "/subscriptions/$SUB_ID" \ + --only-show-errors 2>/dev/null || true +``` + +### Variables & Parameterization + +```bash +#!/bin/bash +set -euo pipefail + +# Parameters at the top +RESOURCE_GROUP="${RESOURCE_GROUP:-myapp-rg}" +LOCATION="${LOCATION:-eastus}" +ENVIRONMENT="${ENVIRONMENT:-dev}" +APP_NAME="myapp-${ENVIRONMENT}" + +# Capture outputs for later use +STORAGE_KEY=$(az storage account keys list \ + --account-name "$STORAGE_ACCOUNT" \ + --query "[0].value" --output tsv) + +PRINCIPAL_ID=$(az identity show \ + --name "$IDENTITY_NAME" \ + --resource-group "$RESOURCE_GROUP" \ + --query "principalId" --output tsv) +``` + +### CI/CD Integration + +```yaml +# GitHub Actions example +- name: Azure Login + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + +- name: Deploy + run: | + az webapp deploy \ + --resource-group myRG \ + --name myApp \ + --src-path ./app.zip \ + --type zip +``` + +--- + +## Deployment Patterns + +### ARM/Bicep Deployment via CLI + +```bash +# Deploy Bicep template +az deployment group create \ + --resource-group myRG \ + --template-file main.bicep \ + --parameters environment=prod \ + --name "deploy-$(date +%Y%m%d-%H%M%S)" + +# What-if (dry run) +az deployment group what-if \ + --resource-group myRG \ + --template-file main.bicep \ + --parameters environment=prod + +# Subscription-level deployment +az deployment sub create \ + --location eastus \ + --template-file infra.bicep +``` + +### Wait for Long-Running Operations + +```bash +# Create with --no-wait, then poll +az aks create --resource-group myRG --name myAKS --no-wait +az aks wait --resource-group myRG --name myAKS --created --timeout 600 + +# Wait for a specific state +az vm wait --resource-group myRG --name myVM --custom "powerState=='VM running'" +``` + +--- + +## Common Anti-Patterns + +| Anti-Pattern | Problem | Fix | +|---|---|---| +| Hardcoded subscription ID | Breaks across environments | Use `az account show --query id -o tsv` or env vars | +| `az login` in automated scripts | Requires interactive input, fails in CI | Use service principal or managed identity | +| No `--output tsv` when assigning vars | JSON wrapping breaks variable assignment | Always use `--output tsv` for shell vars | +| Full JSON output without `--query` | Wasteful, hard to parse, exposes secrets | Use `--query` to select only needed fields | +| Missing `set -euo pipefail` | Script continues after failures silently | Always set at script top | +| Using `--password` in plain text | Credential exposure in logs/history | Use env vars: `--password "$VAR"` | +| No `--no-wait` for batch operations | Sequential waits on independent resources | Add `--no-wait`, poll later if needed | +| Skipping `--yes` in delete commands | Script hangs waiting for confirmation | Use `--yes` for non-interactive deletes | + +--- + +## Quick Reference + +| Task | Command | +|------|---------| +| Login (interactive) | `az login` | +| Login (service principal) | `az login --service-principal -u $ID -p $SECRET --tenant $TENANT` | +| Set subscription | `az account set --subscription $SUB` | +| List resources | `az resource list -g myRG --output table` | +| Create resource group | `az group create -n myRG -l eastus` | +| Deploy template | `az deployment group create -g myRG --template-file main.bicep` | +| Get credentials (AKS) | `az aks get-credentials -g myRG -n myAKS` | +| Stream logs (App Service) | `az webapp log tail -g myRG -n myApp` | +| Open SSH (VM) | `az ssh vm -g myRG -n myVM` | +| Find command | `az find "create web app"` | +| Interactive mode | `az interactive` | + +--- + +## Source + +Content derived from [Azure CLI documentation](https://learn.microsoft.com/en-us/cli/azure/) — Microsoft's official command-line tool for managing Azure resources. diff --git a/README.md b/README.md index 73b716f8..a46f9735 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Skills, custom agents, AGENTS.md templates, and MCP configurations for AI coding > **Blog post:** [Context-Driven Development: Agent Skills for Microsoft Foundry and Azure](https://devblogs.microsoft.com/all-things-azure/context-driven-development-agent-skills-for-microsoft-foundry-and-azure/) -> **🔍 Skill Explorer:** [Browse all 174 skills with 1-click install](https://microsoft.github.io/skills/) +> **🔍 Skill Explorer:** [Browse all 175 skills with 1-click install](https://microsoft.github.io/skills/) ## Quick Start @@ -70,11 +70,11 @@ Coding agents like [Copilot CLI](https://github.com/features/copilot/cli) and [G ## Skill Catalog -> 174 skills across language plugins — see [skill catalog](#skill-catalog) below for the full breakdown +> 175 skills across language plugins — see [skill catalog](#skill-catalog) below for the full breakdown | Language | Count | Suffix | |----------|-------|--------| -| [Core](#core) | 10 | — | +| [Core](#core) | 11 | — | | [Foundry (Language-Agnostic)](#foundry-language-agnostic) | 11 | — | | [Python](#python) | 39 | `-py` | | [.NET](#net) | 28 | `-dotnet` | @@ -86,10 +86,11 @@ Coding agents like [Copilot CLI](https://github.com/features/copilot/cli) and [G ### Core -> 10 skills — tooling, infrastructure, language-agnostic +> 11 skills — tooling, infrastructure, language-agnostic | Skill | Description | |-------|-------------| +| [azure-cli-patterns](.github/skills/azure-cli-patterns/) | Azure CLI best practices for scripting, automation, and resource management. Authentication, JMESPath queries, idempotent scripts, CI/CD integration. | | [cloud-solution-architect](.github/skills/cloud-solution-architect/) | Design well-architected Azure cloud systems. Architecture styles, 44 design patterns, technology choices, mission-critical design, WAF pillars. | | [copilot-sdk](.github/skills/copilot-sdk/) | Build applications powered by GitHub Copilot using the Copilot SDK. Session management, custom tools, streaming, hooks, MCP servers, BYOK, deployment patterns. | | [entra-agent-id](.github/skills/entra-agent-id/) | Microsoft Entra Agent ID (preview) — create OAuth2-capable AI agent identities via Microsoft Graph beta API. Blueprints, BlueprintPrincipals, permissions, WIF. | diff --git a/tests/scenarios/azure-cli-patterns/acceptance-criteria.md b/tests/scenarios/azure-cli-patterns/acceptance-criteria.md new file mode 100644 index 00000000..7f70ffba --- /dev/null +++ b/tests/scenarios/azure-cli-patterns/acceptance-criteria.md @@ -0,0 +1,201 @@ +# Acceptance Criteria: azure-cli-patterns + +**Skill**: `azure-cli-patterns` +**Purpose**: Produce correct, secure, and idempotent Azure CLI scripts following best practices +**Focus**: Authentication patterns, JMESPath queries, scripting idioms, error handling, CI/CD integration + +--- + +## 1. Authentication Patterns + +### 1.1 ✅ CORRECT: Service Principal for Automation + +```bash +az login --service-principal \ + --username "$AZURE_CLIENT_ID" \ + --password "$AZURE_CLIENT_SECRET" \ + --tenant "$AZURE_TENANT_ID" + +az account set --subscription "$AZURE_SUBSCRIPTION_ID" +``` + +### 1.2 ✅ CORRECT: Managed Identity for Azure-hosted Workloads + +```bash +az login --identity +``` + +### 1.3 ❌ INCORRECT: Interactive Login in Automation Scripts + +```bash +#!/bin/bash +# BAD: requires human interaction, fails in CI +az login +az group create --name myRG --location eastus +``` + +### 1.4 ❌ INCORRECT: Hardcoded Credentials + +```bash +# BAD: credentials exposed in script +az login --service-principal \ + --username "a1b2c3d4-1234-5678-abcd-ef1234567890" \ + --password "MyS3cr3tP@ssw0rd!" \ + --tenant "my-tenant-id" +``` + +--- + +## 2. Output and Query Patterns + +### 2.1 ✅ CORRECT: Using --query with --output tsv for Variable Assignment + +```bash +STORAGE_KEY=$(az storage account keys list \ + --account-name mystorageacct \ + --query "[0].value" --output tsv) +``` + +### 2.2 ✅ CORRECT: Filtering with JMESPath + +```bash +az vm list --query "[?powerState=='VM running'].{Name:name, RG:resourceGroup}" --output table +``` + +### 2.3 ❌ INCORRECT: Parsing Full JSON Output with External Tools + +```bash +# BAD: fetches entire JSON, pipes through jq unnecessarily +STORAGE_KEY=$(az storage account keys list --account-name mystorageacct | jq -r '.[0].value') +``` + +### 2.4 ❌ INCORRECT: No Output Format for Variable Assignment + +```bash +# BAD: captures JSON-wrapped string with quotes +VM_NAME=$(az vm show -g myRG -n myVM --query "name") +# Result: "myVM" (with quotes) instead of: myVM +``` + +--- + +## 3. Scripting Best Practices + +### 3.1 ✅ CORRECT: Strict Error Handling + +```bash +#!/bin/bash +set -euo pipefail + +RESOURCE_GROUP="${RESOURCE_GROUP:-myapp-rg}" +LOCATION="${LOCATION:-eastus}" + +az group create --name "$RESOURCE_GROUP" --location "$LOCATION" --output none +``` + +### 3.2 ✅ CORRECT: Idempotent Resource Creation + +```bash +if ! az storage account show --name mystorageacct --resource-group myRG &>/dev/null; then + az storage account create \ + --name mystorageacct \ + --resource-group myRG \ + --sku Standard_LRS \ + --output none +fi +``` + +### 3.3 ❌ INCORRECT: No Error Handling + +```bash +#!/bin/bash +# BAD: no set -e, failures ignored silently +az group create --name myRG --location eastus +az storage account create --name mystorageacct --resource-group myRG --sku Standard_LRS +az vm create --resource-group myRG --name myVM --image Ubuntu2204 +``` + +### 3.4 ❌ INCORRECT: Hardcoded Subscription/Resource IDs + +```bash +# BAD: breaks across environments +az account set --subscription "a1b2c3d4-1234-5678-abcd-ef1234567890" +az vm show --ids "/subscriptions/a1b2c3d4-1234-5678-abcd-ef1234567890/resourceGroups/myRG/providers/Microsoft.Compute/virtualMachines/myVM" +``` + +--- + +## 4. Resource Management + +### 4.1 ✅ CORRECT: Parameterized Resource Creation with Tags + +```bash +az group create \ + --name "$RESOURCE_GROUP" \ + --location "$LOCATION" \ + --tags env="$ENVIRONMENT" team="$TEAM" managed-by=cli + +az storage account create \ + --name "$STORAGE_ACCOUNT" \ + --resource-group "$RESOURCE_GROUP" \ + --sku Standard_LRS \ + --kind StorageV2 \ + --output none +``` + +### 4.2 ✅ CORRECT: Batch Operations with --no-wait + +```bash +az vm list -g myRG --query "[].id" --output tsv | \ + xargs -I {} az vm stop --ids {} --no-wait +``` + +### 4.3 ❌ INCORRECT: Sequential Blocking Operations on Independent Resources + +```bash +# BAD: waits for each VM to stop before starting the next +for vm in vm1 vm2 vm3 vm4 vm5; do + az vm stop --resource-group myRG --name "$vm" +done +``` + +--- + +## 5. Deployment Patterns + +### 5.1 ✅ CORRECT: Bicep Deployment with What-If + +```bash +az deployment group what-if \ + --resource-group myRG \ + --template-file main.bicep \ + --parameters environment=prod + +az deployment group create \ + --resource-group myRG \ + --template-file main.bicep \ + --parameters environment=prod \ + --name "deploy-$(date +%Y%m%d-%H%M%S)" +``` + +### 5.2 ❌ INCORRECT: Deployment Without Naming + +```bash +# BAD: no deployment name makes tracking/rollback impossible +az deployment group create --resource-group myRG --template-file main.bicep +``` + +--- + +## 6. Anti-Patterns Summary + +| Anti-Pattern | Impact | Fix | +|---|---|---| +| Interactive `az login` in scripts | CI failure | Service principal or managed identity | +| Hardcoded subscription ID | Env-specific breakage | Environment variables | +| No `--output tsv` for vars | Quoted JSON in shell vars | Always `--output tsv` | +| No `--query` filtering | Wasted bandwidth, secret exposure | JMESPath to select fields | +| Missing `set -euo pipefail` | Silent failures | Always set at script top | +| Plain-text credentials | Security breach | Env vars or Key Vault refs | +| Sequential blocking without `--no-wait` | Slow execution | `--no-wait` + `az wait` | +| Unnamed deployments | No audit trail | Always `--name` with timestamp | diff --git a/tests/scenarios/azure-cli-patterns/scenarios.yaml b/tests/scenarios/azure-cli-patterns/scenarios.yaml new file mode 100644 index 00000000..99736540 --- /dev/null +++ b/tests/scenarios/azure-cli-patterns/scenarios.yaml @@ -0,0 +1,268 @@ +# Test scenarios for azure-cli-patterns skill evaluation +# Each scenario tests a specific Azure CLI usage pattern + +config: + model: gpt-4 + max_tokens: 2000 + temperature: 0.3 + +scenarios: + - name: service_principal_auth + prompt: | + Write a bash script that logs into Azure using a service principal + for a CI/CD pipeline, sets the subscription, and creates a resource group. + expected_patterns: + - "az login --service-principal" + - "AZURE_CLIENT_ID" + - "AZURE_CLIENT_SECRET" + - "AZURE_TENANT_ID" + - "az account set" + - "az group create" + forbidden_patterns: + - "az login\\s*$" + - "password.*=.*[\"'][A-Za-z0-9]" + tags: + - authentication + - ci-cd + mock_response: | + #!/bin/bash + set -euo pipefail + + az login --service-principal \ + --username "$AZURE_CLIENT_ID" \ + --password "$AZURE_CLIENT_SECRET" \ + --tenant "$AZURE_TENANT_ID" + + az account set --subscription "$AZURE_SUBSCRIPTION_ID" + + az group create \ + --name "$RESOURCE_GROUP" \ + --location "$LOCATION" \ + --output none + + - name: query_and_filter_output + prompt: | + Show how to use Azure CLI --query parameter with JMESPath to: + 1. Get a storage account key into a shell variable + 2. List only running VMs with their names and resource groups in table format + expected_patterns: + - "--query" + - "--output tsv" + - "az storage account keys list" + - "az vm list" + - "powerState" + forbidden_patterns: + - "jq " + - "| grep" + tags: + - query + - output + mock_response: | + #!/bin/bash + set -euo pipefail + + # Get storage account key into a variable + STORAGE_KEY=$(az storage account keys list \ + --account-name "$STORAGE_ACCOUNT" \ + --resource-group "$RESOURCE_GROUP" \ + --query "[0].value" --output tsv) + + # List running VMs with name and resource group + az vm list \ + --query "[?powerState=='VM running'].{Name:name, ResourceGroup:resourceGroup}" \ + --output table + + - name: idempotent_script + prompt: | + Write an idempotent bash script that creates a storage account only if + it doesn't already exist. The script should be safe to run multiple times + without errors. + expected_patterns: + - "set -euo pipefail" + - "az storage account show" + - "az storage account create" + - "if !" + forbidden_patterns: + - "az login\\s*$" + tags: + - scripting + - idempotent + mock_response: | + #!/bin/bash + set -euo pipefail + + RESOURCE_GROUP="${RESOURCE_GROUP:-myapp-rg}" + STORAGE_ACCOUNT="${STORAGE_ACCOUNT:-myappstorage}" + LOCATION="${LOCATION:-eastus}" + + # Create resource group (idempotent by default) + az group create --name "$RESOURCE_GROUP" --location "$LOCATION" --output none + + # Create storage account only if it doesn't exist + if ! az storage account show --name "$STORAGE_ACCOUNT" --resource-group "$RESOURCE_GROUP" &>/dev/null; then + echo "Creating storage account: $STORAGE_ACCOUNT" + az storage account create \ + --name "$STORAGE_ACCOUNT" \ + --resource-group "$RESOURCE_GROUP" \ + --sku Standard_LRS \ + --kind StorageV2 \ + --output none + else + echo "Storage account already exists: $STORAGE_ACCOUNT" + fi + + - name: batch_operations + prompt: | + Write a script that stops all running VMs in a resource group using + batch operations. Don't wait for each one to stop before starting the next. + expected_patterns: + - "az vm list" + - "--query" + - "--output tsv" + - "--no-wait" + - "xargs" + forbidden_patterns: + - "az vm stop --resource-group.*--name.*\n.*az vm stop" + tags: + - batch + - performance + mock_response: | + #!/bin/bash + set -euo pipefail + + RESOURCE_GROUP="${1:-myRG}" + + echo "Stopping all running VMs in $RESOURCE_GROUP..." + + az vm list \ + --resource-group "$RESOURCE_GROUP" \ + --query "[?powerState=='VM running'].id" \ + --output tsv | \ + xargs -I {} az vm stop --ids {} --no-wait + + echo "Stop commands issued. Use 'az vm wait' to poll for completion." + + - name: deployment_with_whatif + prompt: | + Write a script that deploys a Bicep template to Azure. Include a what-if + check before the actual deployment, and give the deployment a unique name. + expected_patterns: + - "az deployment group what-if" + - "az deployment group create" + - "--template-file" + - "--name" + - "date" + forbidden_patterns: + - "az login\\s*$" + tags: + - deployment + - bicep + mock_response: | + #!/bin/bash + set -euo pipefail + + RESOURCE_GROUP="${RESOURCE_GROUP:-myapp-rg}" + TEMPLATE_FILE="${TEMPLATE_FILE:-main.bicep}" + ENVIRONMENT="${ENVIRONMENT:-prod}" + DEPLOYMENT_NAME="deploy-$(date +%Y%m%d-%H%M%S)" + + echo "Running what-if analysis..." + az deployment group what-if \ + --resource-group "$RESOURCE_GROUP" \ + --template-file "$TEMPLATE_FILE" \ + --parameters environment="$ENVIRONMENT" + + echo "Deploying $TEMPLATE_FILE as $DEPLOYMENT_NAME..." + az deployment group create \ + --resource-group "$RESOURCE_GROUP" \ + --template-file "$TEMPLATE_FILE" \ + --parameters environment="$ENVIRONMENT" \ + --name "$DEPLOYMENT_NAME" + + - name: aks_cluster_management + prompt: | + Write a script that creates an AKS cluster with managed identity, + gets the credentials, and checks the cluster health. + expected_patterns: + - "az aks create" + - "--enable-managed-identity" + - "az aks get-credentials" + - "--resource-group" + forbidden_patterns: + - "--service-principal" + - "password.*=.*[\"'][A-Za-z0-9]" + tags: + - aks + - compute + mock_response: | + #!/bin/bash + set -euo pipefail + + RESOURCE_GROUP="${RESOURCE_GROUP:-myapp-rg}" + CLUSTER_NAME="${CLUSTER_NAME:-myaks}" + LOCATION="${LOCATION:-eastus}" + NODE_COUNT="${NODE_COUNT:-3}" + + # Create resource group + az group create --name "$RESOURCE_GROUP" --location "$LOCATION" --output none + + # Create AKS cluster with managed identity + az aks create \ + --resource-group "$RESOURCE_GROUP" \ + --name "$CLUSTER_NAME" \ + --node-count "$NODE_COUNT" \ + --enable-managed-identity \ + --generate-ssh-keys \ + --output none + + # Get credentials for kubectl + az aks get-credentials \ + --resource-group "$RESOURCE_GROUP" \ + --name "$CLUSTER_NAME" \ + --overwrite-existing + + # Check cluster health + az aks show \ + --resource-group "$RESOURCE_GROUP" \ + --name "$CLUSTER_NAME" \ + --query "{Status:provisioningState, PowerState:powerState.code, Nodes:agentPoolProfiles[0].count}" \ + --output table + + - name: error_handling_cleanup + prompt: | + Write a bash script with proper error handling that creates resources + and cleans up on failure. Use a trap for cleanup. + expected_patterns: + - "set -euo pipefail" + - "trap" + - "cleanup" + - "trap cleanup EXIT" + forbidden_patterns: + - "az login\\s*$" + tags: + - scripting + - error-handling + mock_response: | + #!/bin/bash + set -euo pipefail + + RESOURCE_GROUP="temp-rg-$(date +%s)" + LOCATION="eastus" + + cleanup() { + echo "Cleaning up resource group: $RESOURCE_GROUP" + az group delete --name "$RESOURCE_GROUP" --yes --no-wait 2>/dev/null || true + } + trap cleanup EXIT + + echo "Creating resource group: $RESOURCE_GROUP" + az group create --name "$RESOURCE_GROUP" --location "$LOCATION" --output none + + echo "Creating storage account..." + az storage account create \ + --name "tempstore$(date +%s)" \ + --resource-group "$RESOURCE_GROUP" \ + --sku Standard_LRS \ + --output none + + echo "Operations complete. Cleaning up..."