AI translates CloudFormation to Terraform, ARM to Bicep, or cloud A to cloud B in minutes — and gets the shape right while quietly getting the semantics wrong. This playbook wraps translation in a plan-diff parity harness so nothing is trusted until both sides prove they build the same thing.
Tier: Core · Hands-on time: ~35 minutes
Cross-cloud and cross-format IaC translation is one of the highest-frequency services-company tasks, and the research behind this track mirrors the pipeline-migration evidence from the DevOps track: assistants handle the mechanical 80% well, but LLMs are documented to hallucinate HCL resource types and attributes, so the translated stack is untrusted output until a deterministic harness — validate, plan, and a resource-inventory diff — says otherwise. The architect's job is the gate, not the typing.
aws cloudformation validate-template, az bicep build) for the parity harness.terraform plan output, not by applying to production.Inventory the source before translating. Ask the assistant for a resource inventory first — every resource type, count, and cross-reference in the source stack. This becomes the parity checklist the translation must satisfy.
Translate with explicit anti-hallucination constraints. Sameer's GCC is converting a Meridian-style retail stack from CloudFormation to Terraform as part of a wave. His prompt:
Translate this CloudFormation stack (attached: web-tier.yaml, 14 resources)
to Terraform using the hashicorp/aws provider.
Rules:
- Preserve resource-for-resource parity: same count, same types, same
property values. Produce a mapping table (CFN logical ID -> Terraform
address) as the first output.
- If a CFN property has no Terraform equivalent, DO NOT invent an
attribute. List it in a "gaps" section instead.
- Do not add defaults the source did not set. If Terraform requires an
argument CFN defaulted, flag it explicitly with the value you chose.
- Keep names, tags, and retention/deletion policies identical.
Run the deterministic chain. terraform init && terraform validate, then terraform plan against the sandbox. Validate catches invented resource types and attributes — the most common failure — for free, before any human review time is spent.
Diff the inventories. Compare the plan's resource list against the step-1 inventory: same counts per type, no silent additions, no dropped resources. A translation that "simplifies" a DeletionPolicy or drops a bucket policy passes review by eye and fails here.
Hunt the two classic service-mapping traps. When the translation crosses clouds, check every mapped service against both traps. Trap one: false equivalence — the AI maps to the service in the same category (SQS to Service Bus, CloudFront to Front Door) and assumes matching behavior; ordering guarantees, retry semantics, and feature flags differ, and the design silently changes. Trap two: silently different defaults — encryption, public-access posture, log retention, and instance families default differently across providers, so a property the source never set becomes a property the target sets wrong. Write both findings into the parity report even when the answer is "checked, no issue."
Spot-check high-blast-radius properties by hand. IAM policies, network rules, deletion/retention settings, and anything encryption-related get a line-by-line human read regardless of what the harness says.
Close the loop in the same conversation. Paste plan errors and inventory diffs back with "fix only the flagged resources, change nothing else" — scoped correction prevents the assistant from regenerating and re-breaking files that already passed.
Ship the parity report with the code. Mapping table, gaps list, trap findings, plan output hash. The report is the reviewable artifact; the client signs the report, not the vibes.
terraform validate returns zero errors — invented attributes and resource types die here. If it fails, do not hand-patch; make the assistant fix its own output against the error text.terraform plan again after apply in the sandbox; a non-empty diff means the translation encodes drift from day one.Client MSAs govern what leaves the building: extract the AI-usage and data-handling constraints from the MSA before pointing any assistant at client templates. If public tools are prohibited, strip the templates first — replace account IDs, ARNs, CIDR ranges, hostnames, and client-identifying tags with placeholders, translate the sanitized version, then substitute values locally. Where the client offers approved tenancy (Bedrock or Azure OpenAI inside their subscription), run the assistant there instead. For fully restricted estates, a local model via Ollama can do the mechanical translation; the parity harness — validate, plan, inventory diff — is identical offline and does all the real trust work anyway.
The assistant translates; the harness decides. Parity is a plan-diff and an inventory match, never a paragraph of AI assurance — and the two mapping traps get checked by name on every cross-cloud job.