Skip to content
Open
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
1 change: 1 addition & 0 deletions docs/README.skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Skills differ from other primitives by supporting bundled assets (scripts, code
| [refactor](../skills/refactor/SKILL.md) | Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than repo-rebuilder; use for gradual improvements. | None |
| [scoutqa-test](../skills/scoutqa-test/SKILL.md) | This skill should be used when the user asks to "test this website", "run exploratory testing", "check for accessibility issues", "verify the login flow works", "find bugs on this page", or requests automated QA testing. Triggers on web application testing scenarios including smoke tests, accessibility audits, e-commerce flows, and user flow validation using ScoutQA CLI. IMPORTANT: Use this skill proactively after implementing web application features to verify they work correctly - don't wait for the user to ask for testing. | None |
| [snowflake-semanticview](../skills/snowflake-semanticview/SKILL.md) | Create, alter, and validate Snowflake semantic views using Snowflake CLI (snow). Use when asked to build or troubleshoot semantic views/semantic layer definitions with CREATE/ALTER SEMANTIC VIEW, to validate semantic-view DDL against Snowflake via CLI, or to guide Snowflake CLI installation and connection setup. | None |
| [terraform-azurerm-set-diff-analyzer](../skills/terraform-azurerm-set-diff-analyzer/SKILL.md) | Analyze Terraform plan JSON output for AzureRM Provider to distinguish between false-positive diffs (order-only changes in Set-type attributes) and actual resource changes. Use when reviewing terraform plan output for Azure resources like Application Gateway, Load Balancer, Firewall, Front Door, NSG, and other resources with Set-type attributes that cause spurious diffs due to internal ordering changes. | `references/azurerm_set_attributes.json`<br />`references/azurerm_set_attributes.md`<br />`scripts/.gitignore`<br />`scripts/README.md`<br />`scripts/analyze_plan.py` |
| [vscode-ext-commands](../skills/vscode-ext-commands/SKILL.md) | Guidelines for contributing commands in VS Code extensions. Indicates naming convention, visibility, localization and other relevant attributes, following VS Code extension development guidelines, libraries and good practices | None |
| [vscode-ext-localization](../skills/vscode-ext-localization/SKILL.md) | Guidelines for proper localization of VS Code extensions, following VS Code extension development guidelines, libraries and good practices | None |
| [web-design-reviewer](../skills/web-design-reviewer/SKILL.md) | This skill enables visual inspection of websites running locally or remotely to identify and fix design issues. Triggers on requests like "review website design", "check the UI", "fix the layout", "find design problems". Detects issues with responsive design, accessibility, visual consistency, and layout breakage, then performs fixes at the source code level. | `references/framework-fixes.md`<br />`references/visual-checklist.md` |
Expand Down
37 changes: 37 additions & 0 deletions skills/terraform-azurerm-set-diff-analyzer/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
name: terraform-azurerm-set-diff-analyzer
description: Analyze Terraform plan JSON output for AzureRM Provider to distinguish between false-positive diffs (order-only changes in Set-type attributes) and actual resource changes. Use when reviewing terraform plan output for Azure resources like Application Gateway, Load Balancer, Firewall, Front Door, NSG, and other resources with Set-type attributes that cause spurious diffs due to internal ordering changes.
license: MIT
---

# Terraform AzureRM Set Diff Analyzer

A skill to identify "false-positive diffs" in Terraform plans caused by AzureRM Provider's Set-type attributes and distinguish them from actual changes.

## When to Use

- `terraform plan` shows many changes, but you only added/removed a single element
- Application Gateway, Load Balancer, NSG, etc. show "all elements changed"
- You want to automatically filter false-positive diffs in CI/CD

## Background

Terraform's Set type compares by position rather than by key, so when adding or removing elements, all elements appear as "changed". This is a general Terraform issue, but it's particularly noticeable with AzureRM resources that heavily use Set-type attributes like Application Gateway, Load Balancer, and NSG.

These "false-positive diffs" don't actually affect the resources, but they make reviewing terraform plan output difficult.

## Basic Usage

```bash
# 1. Generate plan JSON output
terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > plan.json

# 2. Analyze
python scripts/analyze_plan.py plan.json
```

## Detailed Documentation

- [scripts/README.md](scripts/README.md) - All options, output formats, exit codes, CI/CD examples
- [references/azurerm_set_attributes.md](references/azurerm_set_attributes.md) - Supported resources and attributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
{
"metadata": {
"description": "AzureRM Provider Set-type attribute definitions",
"lastUpdated": "2026-01-28",
"source": "Terraform Registry documentation and AzureRM Provider source code"
},
"resources": {
"azurerm_application_gateway": {
"backend_address_pool": "name",
"backend_http_settings": "name",
"custom_error_configuration": "status_code",
"frontend_ip_configuration": "name",
"frontend_port": "name",
"gateway_ip_configuration": "name",
"http_listener": "name",
"probe": "name",
"private_link_configuration": "name",
"redirect_configuration": "name",
"request_routing_rule": "name",
"rewrite_rule_set": {
"_key": "name",
"rewrite_rule": {
"_key": "name",
"condition": "variable",
"request_header_configuration": "header_name",
"response_header_configuration": "header_name"
}
},
"ssl_certificate": "name",
"ssl_profile": "name",
"trusted_client_certificate": "name",
"trusted_root_certificate": "name",
"url_path_map": {
"_key": "name",
"path_rule": {
"_key": "name",
"paths": null
}
}
},
"azurerm_lb": {
"frontend_ip_configuration": "name"
},
"azurerm_lb_backend_address_pool": {
"backend_address": "name"
},
"azurerm_lb_rule": {
"backend_address_pool_ids": null
},
"azurerm_firewall": {
"ip_configuration": "name",
"management_ip_configuration": "name",
"virtual_hub": null
},
"azurerm_firewall_policy_rule_collection_group": {
"application_rule_collection": {
"_key": "name",
"rule": {
"_key": "name",
"protocols": null,
"destination_fqdns": null
}
},
"network_rule_collection": {
"_key": "name",
"rule": {
"_key": "name",
"destination_addresses": null,
"destination_ports": null
}
},
"nat_rule_collection": {
"_key": "name",
"rule": "name"
}
},
"azurerm_frontdoor": {
"backend_pool": {
"_key": "name",
"backend": "address"
},
"backend_pool_health_probe": "name",
"backend_pool_load_balancing": "name",
"frontend_endpoint": "name",
"routing_rule": "name"
},
"azurerm_cdn_frontdoor_origin_group": {
"health_probe": null,
"load_balancing": null
},
"azurerm_network_security_group": {
"security_rule": "name"
},
"azurerm_route_table": {
"route": "name"
},
"azurerm_virtual_network": {
"subnet": "name"
},
"azurerm_virtual_network_gateway": {
"ip_configuration": "name",
"vpn_client_configuration": {
"_key": null,
"root_certificate": "name",
"revoked_certificate": "name",
"radius_server": "address"
},
"policy_group": "name"
},
"azurerm_virtual_network_gateway_connection": {
"ipsec_policy": null
},
"azurerm_nat_gateway": {
"public_ip_address_ids": null,
"public_ip_prefix_ids": null
},
"azurerm_private_endpoint": {
"ip_configuration": "name",
"private_dns_zone_group": "name",
"private_service_connection": "name"
},
"azurerm_api_management": {
"additional_location": "location",
"certificate": "encoded_certificate",
"hostname_configuration": {
"_key": null,
"management": "host_name",
"portal": "host_name",
"developer_portal": "host_name",
"proxy": "host_name",
"scm": "host_name"
}
},
"azurerm_storage_account": {
"network_rules": null,
"blob_properties": null
},
"azurerm_key_vault": {
"network_acls": null
},
"azurerm_cosmosdb_account": {
"geo_location": "location",
"capabilities": "name",
"virtual_network_rule": "id"
},
"azurerm_kubernetes_cluster": {
"default_node_pool": null
},
"azurerm_kubernetes_cluster_node_pool": {
"node_labels": null,
"node_taints": null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# AzureRM Set-Type Attributes Reference

This document explains the overview and maintenance of `azurerm_set_attributes.json`.

> **Last Updated**: January 28, 2026

## Overview

`azurerm_set_attributes.json` is a definition file for attributes treated as Set-type in the AzureRM Provider.
The `analyze_plan.py` script reads this JSON to identify "false-positive diffs" in Terraform plans.

### What are Set-Type Attributes?

Terraform's Set type is a collection that **does not guarantee order**.
Therefore, when adding or removing elements, unchanged elements may appear as "changed".
This is called a "false-positive diff".

## JSON File Structure

### Basic Format

```json
{
"resources": {
"azurerm_resource_type": {
"attribute_name": "key_attribute"
}
}
}
```

- **key_attribute**: The attribute that uniquely identifies Set elements (e.g., `name`, `id`)
- **null**: When there is no key attribute (compare entire element)

### Nested Format

When a Set attribute contains another Set attribute:

```json
{
"rewrite_rule_set": {
"_key": "name",
"rewrite_rule": {
"_key": "name",
"condition": "variable",
"request_header_configuration": "header_name"
}
}
}
```

- **`_key`**: The key attribute for that level's Set elements
- **Other keys**: Definitions for nested Set attributes

### Example: azurerm_application_gateway

```json
"azurerm_application_gateway": {
"backend_address_pool": "name", // Simple Set (key is name)
"rewrite_rule_set": { // Nested Set
"_key": "name",
"rewrite_rule": {
"_key": "name",
"condition": "variable"
}
}
}
```

## Maintenance

### Adding New Attributes

1. **Check Official Documentation**
- Search for the resource in [Terraform Registry](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
- Verify the attribute is listed as "Set of ..."
- Some resources like `azurerm_application_gateway` have Set attributes noted explicitly

2. **Check Source Code (more reliable)**
- Search for the resource in [AzureRM Provider GitHub](https://github.com/hashicorp/terraform-provider-azurerm)
- Confirm `Type: pluginsdk.TypeSet` in the schema definition
- Identify attributes within the Set's `Schema` that can serve as `_key`

3. **Add to JSON**
```json
"azurerm_new_resource": {
"set_attribute": "key_attribute"
}
```

4. **Test**
```bash
# Verify with an actual plan
python3 scripts/analyze_plan.py your_plan.json
```

### Identifying Key Attributes

| Common Key Attribute | Usage |
|---------------------|-------|
| `name` | Named blocks (most common) |
| `id` | Resource ID reference |
| `location` | Geographic location |
| `address` | Network address |
| `host_name` | Hostname |
| `null` | When no key exists (compare entire element) |

## Related Tools

### analyze_plan.py

Analyzes Terraform plan JSON to identify false-positive diffs.

```bash
# Basic usage
terraform show -json plan.tfplan | python3 scripts/analyze_plan.py

# Read from file
python3 scripts/analyze_plan.py plan.json

# Use custom attribute file
python3 scripts/analyze_plan.py plan.json --attributes /path/to/custom.json
```

## Supported Resources

Please refer to `azurerm_set_attributes.json` directly for currently supported resources:

```bash
# List resources
jq '.resources | keys' azurerm_set_attributes.json
```

Key resources:
- `azurerm_application_gateway` - Backend pools, listeners, rules, etc.
- `azurerm_firewall_policy_rule_collection_group` - Rule collections
- `azurerm_frontdoor` - Backend pools, routing
- `azurerm_network_security_group` - Security rules
- `azurerm_virtual_network_gateway` - IP configuration, VPN client configuration

## Notes

- Attribute behavior may differ depending on Provider/API version
- New resources and attributes need to be added as they become available
- Defining all levels of deeply nested structures improves accuracy
Loading