Skip to content

Manual Test Runbook — F12: Brownfield Import Library

Owner: Sagar  |  Time: ~6 min (Parts A + B offline) / +15–30 min per module (optional Part C live adoption)  |  Sandbox: snowops-sandbox-01

Overview

F12 (modules/azure/import-blocks/) is the SnowOps brownfield import library: config-driven Terraform import {} blocks that adopt pre-existing Azure resources into the F-modules, one <module>.tf per module. It makes the "Brownfield-Safe by Default" principle executable.

Covered modules (this drop): F1 baseline · F2 network-hub · F3 aks-secure · F4 acr · F5 key-vault · F6 state-backend · J1 log-analytics · J2 policy-diagnostics · J6 audit-log-archive.

The directory double-duties as its own offline test harness: each file pairs the import blocks with a placeholder module call so terraform validate proves every to = address resolves against a real module resource. Parts A + B verify that offline; Part C is an optional live adoption of one real sandbox resource.

Part A — Offline validate + fmt (no cloud, ~3 min)

terraform -chdir=modules/azure/import-blocks init -backend=false -input=false
terraform -chdir=modules/azure/import-blocks validate
terraform -chdir=modules/azure/import-blocks fmt -check -recursive

Expect: Success! The configuration is valid. and clean fmt. A failure here means an import { to = … } references an address that no longer exists in a module (e.g. a resource was renamed) — the gate's whole purpose.

Part B — Terratest + tflint (offline, ~3 min)

cd tests/terratest
go test -v -timeout 5m ./modules/azure/... -run TestImportBlocksValidate
go test -count=1 -timeout 15m ./...          # full offline suite still green
( cd ../../modules/azure/import-blocks && tflint )

Expect: TestImportBlocksValidate PASS; full suite green; tflint exit 0.

Part C — Live adoption drill (sandbox, optional, ~15–30 min)

Proves a real resource can be adopted with a zero-change plan. state-backend (F6) is the cheapest target. Use an ephemeral sandbox RG tagged ephemeral=true.

  1. Create a throwaway resource outside Terraform (e.g. a storage account):
az group create -n snowops-import-drill-rg -l eastus --tags ephemeral=true
az storage account create -n snoimportdrill$RANDOM -g snowops-import-drill-rg \
  -l eastus --sku Standard_LRS
  1. In a scratch root module, call module "state_backend" with inputs matching the live resource, then copy the relevant import {} blocks from modules/azure/import-blocks/state-backend.tf, replacing the placeholder IDs with the real ones (az storage account show --ids …).

  2. terraform plan → review the Plan: N to import, 0 to add, 0 to change, 0 to destroy line (after the first adopt-and-reconcile pass). terraform apply adopts into state. Re-run terraform planNo changes is the success criterion.

  3. Teardown:

az group delete -n snowops-import-drill-rg --yes --no-wait

Pass criteria

  • Part A — validate succeeds; fmt -check clean
  • Part B — TestImportBlocksValidate passes; full offline suite green; tflint exit 0
  • (Part C) a real resource adopts with a subsequent zero-change plan; drill RG removed

Per-module key-scheme cheatsheet

Module for_each key scheme
F1 baseline sub policy assignment = subscription GUID; Defender pricing = service name
F2 network-hub hub subnet/NSG = subnet name; spoke vNet/RT/peering = spoke name; spoke subnet/NSG = "<spoke>/<subnet>"; DNS zone/hub link = zone name; spoke DNS link = "<zone>/<spoke>"; flow log = the NSG's key
F3 aks-secure user node pool = pool name
F4 acr AcrPull role assignment = principal object ID
F5 key-vault role assignment = "<Role Name>/<principal_id>"
F6 state-backend container / immutability policy = container name
J1 log-analytics table = table name; role assignment = "<Role Name>/<principal_id>"
J2 policy-diagnostics remediation role assignment = role definition name
J6 audit-log-archive archive-reader role assignment = principal object ID

Counted (count) resources use [0]; the import gate proves the base address resolves but not the key — follow these schemes when replicating blocks.

Sign-off

  • Tester: _  |  Date: _  |  Result: PASS / FAIL / N/A
  • Notes: