Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions .agents/skills/AVM-Terraform-Development/AzAPI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# AzAPI Provider

All Azure resources in AVM modules MUST be deployed using the **AzAPI provider** (`Azure/azapi`).

## Provider Configuration

```hcl
terraform {
required_providers {
azapi = {
source = "Azure/azapi"
version = "~> 2.8"
}
}
}
```

## Resource Pattern

AzAPI resources use ARM resource types with explicit API versions:

```hcl
resource "azapi_resource" "example" {
type = "<ResourceProvider>/<ResourceType>@<ApiVersion>"
parent_id = "<parent resource ID>"
name = "<resource name>"
location = "<Azure region>"

body = {
properties = {
# Resource-specific properties (HCL object, NOT JSON string)
}
}

# MUST include this, set to empty list if no exports are needed.
response_export_values = [
"properties.<field>",
]
}
```

### Key attributes

| Attribute | Description |
| ------------------------ | ----------------------------------------------------------------------------------------------------- |
| `type` | ARM resource type with API version (e.g., `Microsoft.Storage/storageAccounts@2023-01-01`) |
| `parent_id` | ID of the parent resource. For top-level resources: `/subscriptions/{sub}/resourceGroups/{rg}` |
| `name` | Resource name |
| `location` | Azure region |
| `body` | Resource properties as an **HCL object** (not a JSON string) |
| `response_export_values` | List of ARM property paths to export set to empty list if not used (e.g., `"properties.principalId"`) |
| `locks` | A mutex. List of resource IDs to lock on to prevent concurrent operations |

### Accessing outputs

Use `.output` to access exported values:

```hcl
azapi_resource.example.output.properties.principalId
```

## Data sources

```hcl
# Get current client context (subscription, tenant)
data "azapi_client_config" "current" {}

# Use in expressions:
data.azapi_client_config.current.subscription_id
data.azapi_client_config.current.subscription_resource_id
data.azapi_client_config.current.tenant_id
```

## Unit test mocking

```hcl
mock_provider "azapi" {}
```

## Azure Resource Schema Lookup

Use the `azure-schema` CLI tool (bundled at `.agents/skills/AVM-Terraform-Development/azure-schema`) to look up resource type schemas, properties, constraints, and available API versions. This is essential for knowing the correct `type` and `body` structure for `azapi_resource`.

### List available API versions

```bash
.agents/skills/AVM-Terraform-Development/azure-schema versions Microsoft.Storage
```

### Get a resource schema (human-readable)

```bash
.agents/skills/AVM-Terraform-Development/azure-schema get Microsoft.Storage/storageAccounts 2023-01-01
```

### Get a resource schema (resolved JSON)

```bash
.agents/skills/AVM-Terraform-Development/azure-schema get Microsoft.Storage/storageAccounts 2023-01-01 --json
```

### Control depth

```bash
# Shallow view (top-level properties only)
.agents/skills/AVM-Terraform-Development/azure-schema get Microsoft.Storage/storageAccounts 2023-01-01 --depth 2

# Deep view (default is 5)
.agents/skills/AVM-Terraform-Development/azure-schema get Microsoft.Storage/storageAccounts 2023-01-01 --depth 8
```

## Sensitive attributes

- Passwords, keys, etc should be passed in using the `sensitive_body` attribute. This object is merged with the `body` at runtime.
- All sensitive values MUST be ephemeral.
- Use `sensitive_body_version` as a map to track the JSON properties that are set via `sensitive_body`. This allows Terraform to know when the sensitive value has changed, e.g. `sensitive_body_version = { "properties.key1" = "1" }`."
- Reference each sensitive body version as a variable.

### Workflow

1. Find the API version: `azure-schema versions <Provider>`
2. Get the schema: `azure-schema get <ResourceType> <ApiVersion>`
3. Map the schema properties into the `body` block of your `azapi_resource`
4. Properties marked `[READ-ONLY]` should not be set in `body` -- use `response_export_values` to read them if required
5. Properties marked `[REQUIRED]` must be included in `body`
125 changes: 125 additions & 0 deletions .agents/skills/AVM-Terraform-Development/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
name: AVM-Terraform-Development
description: Azure Verified Modules (AVM) Terraform development workflow for fixing issues and adding features
glob: "**/*.terraform,**/*.tf,**/*.tfvars,**/*.tfstate,**/*.tflint.hcl,**/*.tf.json,**/*.tfvars.json"
---

# Azure Verified Modules (AVM) Terraform

Azure Verified Modules (AVM) are pre-built, tested, and validated Terraform and Bicep modules that follow Azure best practices. Use these modules to create, update, or review Azure Infrastructure as Code (IaC) with confidence.

## Development Workflow

Follow these steps in order when fixing an issue or adding a feature.

### Step 1: Start from a clean main branch

```bash
git checkout main
git pull
```

### Step 2: Create and checkout a feature/issue branch

```bash
git checkout -b feature/<short-description>
# or
git checkout -b fix/<issue-number>-<short-description>
```

### Step 3: Implement the change

All Azure resources MUST be deployed using the **AzAPI provider** (`Azure/azapi`). For AzAPI resource patterns, schema lookups, and the `azure-schema` CLI tool, read [AzAPI.md](AzAPI.md).

To query Terraform provider schemas (resources, data sources, functions, ephemeral resources), use the `tfpluginschema` CLI. See [tfpluginschema.md](tfpluginschema.md).

Make the necessary code changes to add the feature or fix the issue.

### Step 4: Add unit tests (if justified)

Unit tests use **provider mocking** and live in the `tests/unit` directory. Add or update unit tests when your change introduces new logic, variables, or outputs that can be validated without deploying real infrastructure. For test writing guidance, syntax, and patterns, read [terraform-test.md](terraform-test.md).

```bash
PORCH_NO_TUI=1 ./avm tf-test-unit
```

### Step 5: Add integration tests (if justified)

Integration tests do **not** use provider mocking and live in the `tests/integration` directory. Add or update integration tests when your change requires validation against real Azure infrastructure. For test writing guidance, syntax, and patterns, read [terraform-test.md](terraform-test.md).

```bash
PORCH_NO_TUI=1 ./avm tf-test-integration
```

### Step 6: Add or update examples (if justified)

If your change affects module usage or introduces new functionality, add or update examples in the `examples/` directory. Test only the pertinent example:

```bash
PORCH_NO_TUI=1 AVM_EXAMPLE="<ExampleDir>" ./avm test-examples
```

### Step 7: Update documentation (if justified)

If documentation changes are needed, edit `_header.md`. **NEVER edit README.md directly** -- it is auto-generated and will be overwritten.

### Step 8: Run pre-commit checks (MANDATORY)

This must **always** be run before committing:

```bash
PORCH_NO_TUI=1 ./avm pre-commit
```

### Step 9: Commit changes

```bash
git add .
git commit -m "<type>: <meaningful description>"
```

### Step 10: Run PR checks (MANDATORY)

This must **always** be run after committing:

```bash
PORCH_NO_TUI=1 ./avm pr-check
```

### Step 11: Push and open a PR

Push the branch to remote and open a pull request with a meaningful description. Reference any issues that should be closed.

```bash
git push -u origin HEAD
```

When creating the PR, include:

- A clear description of what was changed and why
- References to related issues (e.g., `Closes #123`)

## Troubleshooting Test Failures

If any issues arise during testing or PR checks, refer to the official AVM testing documentation:

<https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/refs/heads/main/docs/content/contributing/terraform/testing.md>

## Reference

### Code Quality

- Always run `terraform fmt` after making changes
- Always run `terraform validate` after making changes
- Use meaningful variable names and descriptions
- Use snake_case
- Add proper tags and metadata
- Document complex configurations

### Tool Integration

- **AzAPI Provider & Schema Lookup**: See [AzAPI.md](AzAPI.md) for resource patterns and the `azure-schema` CLI tool
- **Terraform Provider Schemas**: See [tfpluginschema.md](tfpluginschema.md) for querying resource, data source, function, and ephemeral schemas from any provider
- **Terraform Tests**: See [terraform-test.md](terraform-test.md) for writing unit and integration tests
- **Deployment Guidance**: Use `azure_get_deployment_best_practices` tool
- **Service Documentation**: Use `microsoft.docs.mcp` tool for Azure service-specific guidance
Loading
Loading