Safe Terraform provider upgrades with automatic resource migration, breaking change detection, and state management using moved blocks. Use when upgrading provider versions, handling removed resources, migrating deprecated syntax, or performing major version upgrades.
This skill provides a comprehensive workflow for safely upgrading Terraform providers with automatic resource migration, breaking change detection, and proper state management.
azurerm_sql_* → azurerm_mssql_*)Use MCP tools to understand the scope:
# Get current and latest versions
get_latest_provider_version(namespace="hashicorp", name="azurerm")
# Current: 3.117.0, Latest: 4.51.0 → Major version change (likely breaking)
# Current: 3.117.0, Latest: 3.118.0 → Minor version change (likely non-breaking)
# Current: 3.117.0, Latest: 3.117.1 → Patch version (non-breaking)
# Get upgrade guide to confirm
resolveProviderDocID(...serviceSlug="4.0-upgrade-guide", providerDataType="guides"...)
getProviderDocs(providerDocID="<id>")
Characteristics:
3.117.0 → 3.118.0 or 3.117.1)Action:
versions.tfchore: upgrade azurerm provider to v3.118.0Characteristics:
3.x → 4.x)Action:
TERRAFORM_UPGRADE_BREAKING_CHANGES.mdKey indicators from upgrade guide:
Objective: Find all provider references and document current versions
# Search for all Terraform files
find . -name "*.tf"
# Search for provider version constraints
grep -r "required_providers" --include="*.tf"
grep -r "version.*=" --include="versions.tf"
Document:
Use MCP Tool:
get_latest_provider_version(namespace="hashicorp", name="azurerm")
Compare:
3.117.14.51.0Step 1: Find Upgrade Guide
resolveProviderDocID(
providerNamespace="hashicorp",
providerName="azurerm",
serviceSlug="4.0-upgrade-guide",
providerDataType="guides",
providerVersion="latest"
)
Step 2: Get Documentation
getProviderDocs(providerDocID="<id-from-previous-call>")
Analyze upgrade guide for:
Critical Step: Search for usage of removed resources
# Example: Search for removed SQL resources in Azure v4.0
grep -r "azurerm_sql_server" --include="*.tf"
grep -r "azurerm_sql_firewall_rule" --include="*.tf"
grep -r "azurerm_sql_virtual_network_rule" --include="*.tf"
Document findings:
For each removed resource found:
Step 1: Get old resource documentation
resolveProviderDocID(
providerNamespace="hashicorp",
providerName="azurerm",
serviceSlug="sql_server",
providerDataType="resources",
providerVersion="3.117.1"
)
getProviderDocs(providerDocID="<id>")
Step 2: Get new resource documentation
resolveProviderDocID(
providerNamespace="hashicorp",
providerName="azurerm",
serviceSlug="mssql_server",
providerDataType="resources",
providerVersion="latest"
)
getProviderDocs(providerDocID="<id>")
Step 3: Compare schemas
administrator_login → admin_login)Step 4: Check default values
Update resource types:
# Before
resource "azurerm_sql_server" "sql_server" {
name = "example-sqlserver"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
version = "12.0"
administrator_login = "sqladmin"
administrator_login_password = var.sql_password
}
# After
resource "azurerm_mssql_server" "sql_server" {
name = "example-sqlserver"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
version = "12.0"
administrator_login = "sqladmin"
administrator_login_password = var.sql_password
}
Add moved block for state migration:
moved {
from = azurerm_sql_server.sql_server
to = azurerm_mssql_server.sql_server
}
Update argument changes:
# Firewall rule arguments changed from name-based to ID-based
# Before (v3.x)
resource "azurerm_sql_firewall_rule" "allow_azure" {
name = "allow-azure-services"
resource_group_name = azurerm_resource_group.rg.name
server_name = azurerm_sql_server.sql_server.name
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}
# After (v4.x)
resource "azurerm_mssql_firewall_rule" "allow_azure" {
name = "allow-azure-services"
server_id = azurerm_mssql_server.sql_server.id # Changed from name to ID
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}
moved {
from = azurerm_sql_firewall_rule.allow_azure
to = azurerm_mssql_firewall_rule.allow_azure
}
Update dependent resources:
# Search for resources that reference the migrated resource
grep -r "azurerm_sql_server.sql_server" --include="*.tf"
Update references to use correct attributes (e.g., .id instead of .name where needed).
Replace deprecated provider properties:
# Before
provider "azurerm" {
features {}
skip_provider_registration = true # Deprecated
}
# After
provider "azurerm" {
features {}
resource_provider_registrations = "none" # Modern equivalent
}
Update version constraints:
terraform {
required_version = ">= 1.5.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "4.51.0" # Updated from 3.117.1
}
}
}
Only create documentation for breaking changes.
Create TERRAFORM_UPGRADE_BREAKING_CHANGES.md at repository root (not in .github/ or subdirectories):
File Location:
your-terraform-repo/
├── TERRAFORM_UPGRADE_BREAKING_CHANGES.md ← Place here
├── infra/
├── .github/
└── README.md
# Terraform Provider Upgrade: AzureRM v3.117.1 → v4.51.0
**Date:** 2026-01-27
## Summary
Upgraded HashiCorp AzureRM provider from v3.117.1 to v4.51.0. This major version upgrade included automatic migration of removed SQL resources to their modern MSSQL equivalents.
## What Changed
- Updated `required_providers` version constraint to `4.51.0`
- Migrated removed resources: `azurerm_sql_*` → `azurerm_mssql_*`
- Replaced deprecated `skip_provider_registration` with `resource_provider_registrations`
- Updated argument references from name-based to ID-based
## Breaking Changes Handled
### ✅ Removed Resources Migrated
**1. azurerm_sql_server → azurerm_mssql_server**
- **Files Modified:** `infra/modules/database/main.tf`
- **Changes Applied:**
- Updated resource type
- Added `moved` block for automatic state migration
- All arguments remain compatible
- **Argument Mappings:** No changes required (schema compatible)
- **Default Values:** No new default value changes
- **Documentation:** [azurerm_mssql_server](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/mssql_server)
**2. azurerm_sql_firewall_rule → azurerm_mssql_firewall_rule**
- **Files Modified:** `infra/modules/database/main.tf`
- **Changes Applied:**
- Updated resource type
- Changed `server_name` argument to `server_id`
- Updated reference from `.name` to `.id`
- Added `moved` block for automatic state migration
- **Argument Mappings:**
- `resource_group_name` (removed) + `server_name` → `server_id`
- Now uses: `azurerm_mssql_server.sql_server.id`
- **Default Values:** No new default value changes
- **Documentation:** [azurerm_mssql_firewall_rule](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/mssql_firewall_rule)
**State Migration:** Terraform will automatically migrate state using `moved` blocks on next plan/apply.
## Notes
- All changes are backward compatible with existing state
- `moved` blocks enable automatic state migration
- No manual `terraform state mv` commands required
- Provider block retained with updated `resource_provider_registrations` argument
## Next Steps
1. **Commit these changes** to a feature branch
2. **Run your Terraform workflow** via CI/CD pipeline to validate
3. **Review plan output** to confirm state migrations
4. **Verify no unexpected changes** before merging
## References
- [AzureRM Provider 4.0 Upgrade Guide](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/4.0-upgrade-guide)
- [AzureRM Provider v4.51.0 Release Notes](https://github.com/hashicorp/terraform-provider-azurerm/releases/tag/v4.51.0)
- [Terraform Moved Blocks](https://developer.hashicorp.com/terraform/language/modules/develop/refactoring)
- [Resource Provider Registrations](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/4.0-upgrade-guide#resource-provider-registrations)
.name to .id where neededScenario: Upgrading AzureRM from 3.117.0 to 3.118.0
# 1. Check version
get_latest_provider_version(namespace="hashicorp", name="azurerm")
# Result: 3.118.0 (minor version bump)
# 2. Check for breaking changes
resolveProviderDocID(...serviceSlug="3.118.0", providerDataType="guides"...)
getProviderDocs(providerDocID="<id>")
# Review: No removed resources, no breaking changes
# 3. Update version
# versions.tf: version = "3.118.0"
# 4. Commit
# Message: "chore: upgrade azurerm provider to v3.118.0"
# NO TERRAFORM_UPGRADE_BREAKING_CHANGES.md needed
Scenario: Upgrading AzureRM from 3.117.0 to 4.51.0
# 1. Check version
get_latest_provider_version(namespace="hashicorp", name="azurerm")
# Result: 4.51.0 (major version bump)
# 2. Get upgrade guide
resolveProviderDocID(...serviceSlug="4.0-upgrade-guide"...)
getProviderDocs(providerDocID="<id>")
# Review: azurerm_sql_* resources removed
# 3. Scan codebase
grep -r "azurerm_sql_server" --include="*.tf"
# 4. Migrate resources (fetch old + new docs)
# 5. Add moved blocks
# 6. Update arguments
# 7. Create TERRAFORM_UPGRADE_BREAKING_CHANGES.md at repository root
# 8. Commit with detailed message referencing documentation
.name to .id where neededFor detailed examples, common patterns, and troubleshooting, see the reference guide.
npx skills add thomast1906/terraform-provider-upgrade下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer