Overview: In large-scale cloud environments, ensuring that deployed infrastructure matches design specifications is a constant challenge. Teams often maintain: π Excel sheets with approved SKUs and configurations π¦ Terraform code for deployments βοΈ Live Azure resources running in production This agent will perform : β Reads infrastructure specs from Excel β Parses Terraform configurations β Validates deployed resources in Azure β Flags mismatches and compliance issues
1. Introduction
Infrastructure consistency is critical in large-scale Azure environments, especially in migration programs and DevOps-driven deployments. While Infrastructure as Code (IaC) using Terraform improves reproducibility, it does not fully eliminate:
- Manual errors in design specifications
- Drift between Terraform and deployed resources
- Misalignment between approved design (Excel/architecture docs) and deployed state
To address this, we propose building an AI-powered Infrastructure Validation Agent that continuously validates and reconciles:
- Excel (Source of Truth)
- Terraform (.tf files)
- Azure Deployed Resources
This blog explains the architecture, implementation, validation logic, and real-world applicability of such an agent.
2. Problem Statement
In enterprise environments, infrastructure data flows through multiple stages:
| Source | Purpose |
|---|---|
| Excel / Design Sheets | Approved architecture specifications |
| Terraform | Infrastructure as Code implementation |
| Azure Portal | Actual deployed infrastructure |
3.Common Challenges
- Configuration mismatches across stages
- Drift due to manual portal changes
- Incorrect SKU, region, or configuration deployment
- Lack of automated validation before and after deployment
The absence of unified validation leads to compliance risks, deployment errors, and operational inefficiencies.
4. Solution Overview
The proposed solution is an AI-powered validation agent that:
- Ingests Excel as configuration input
- Parses Terraform configurations
- Fetches deployed resource details from Azure
5. Architecture Overview
High-Level Architecture Components
-
- Input Layer
- Excel file (configuration source)
- Processing Layer
- Terraform Parser
- Azure Resource Fetcher
- AI-based Validator (optional reasoning layer)
- Comparison Engine
- Schema-based comparison
- Drift detection logic
- Output Layer
- Validation report (JSON / Excel / HTML)
- Hosting
- Azure Function App
- Optional Enhancements
- Azure AI Search for semantic matching and reasoning
- Input Layer
6. Agent Design (Modular Components)
| Module | Description |
|---|---|
| Excel Reader | Reads and standardizes input |
| Terraform Parser | Extracts resource configuration |
| Azure Fetcher | Queries deployed resources |
| Comparator Engine | Identifies mismatches |
| AI Validator | Enhances validation and recommendations |
| Report Generator | Produces actionable outputs |
`
7. Agent Design
Step 1: Read Excel Input
import pandas as pd
ef read_excel(file_path):
df = pd.read_excel(file_path)
df.columns = df.columns.str.strip()
return df
excel_df = read_excel("infra_config.xlsx")
print(excel_df.head())
Step 2:Parse Terraform Files
import hcl2
def parse_terraform(file_path):
with open(file_path, 'r') as file:
data = hcl2.load(file)
resources = []
for resource_type in data.get('resource', []):
for rtype, instances in resource_type.items():
for name, config in instances.items():
resource = {
"resource_type": rtype,
"resource_name": name,
"config": config
}
resources.append(resource)
return resources
tf_resources = parse_terraform("main.tf")
print(tf_resources)
Step 3:Parse Terraform Files
from azure.identity import DefaultAzureCredential
from azure.mgmt.resource import ResourceManagementClient
credential = DefaultAzureCredential()
subscription_id = "your-subscription-id"
resource_client = ResourceManagementClient(credential, subscription_id)
def fetch_azure_resources():
resources = []
for resource in resource_client.resources.list():
res = {
"name": resource.name,
"type": resource.type,
"location": resource.location,
"id": resource.id
}
resources.append(res)
return resources
azure_resources = fetch_azure_resources()
print(azure_resources)
Step 4:Normalize Data
def normalize_excel(df):
return df.to_dict(orient='records')
def normalize_tf(tf_resources):
normalized = []
for res in tf_resources:
normalized.append({
"resource_name": res["resource_name"],
"resource_type": res["resource_type"],
"config": res["config"]
})
return normalized
def normalize_azure(azure_resources):
normalized = []
for res in azure_resources:
normalized.append({
"resource_name": res["name"],
"resource_type": res["type"],
"location": res["location"]
})
return normalized
Step 5: Validation Logic (Drift Detection)
def compare_resources(excel_data, tf_data, azure_data):
issues = []
for excel_res in excel_data:
name = excel_res['resource_name']
tf_match = next((r for r in tf_data if r['resource_name'] == name), None)
az_match = next((r for r in azure_data if r['resource_name'] == name), None)
if not tf_match:
issues.append({
"resource": name,
"issue": "Missing in Terraform",
"severity": "High"
})
if not az_match:
issues.append({
"resource": name,
"issue": "Missing in Azure",
"severity": "Critical"
})
if tf_match and az_match:
if excel_res['region'] != az_match.get('location'):
issues.append({
"resource": name,
"issue": "Region mismatch",
"expected": excel_res['region'],
"actual": az_match.get('location')
})
return issues
drift_report = compare_resources(
normalize_excel(excel_df),
normalize_tf(tf_resources),
normalize_azure(azure_resources)
)
print(drift_report)
Step 6: Export Report to Excel
Sample validation
| Resource | Issue | Expected | Actual | Severity |
|---|---|---|---|---|
| func-app-01 | Missing in Terraform | - | - | High |
| search-01 | SKU mismatch | Standard | Basic | Medium |
| webapp-01 | Region mismatch | East US | West Europe | High |