DevOpsInterviewPrep logo
Infrastructure as Code & Configuration / 07
hard★ EssentialNewHashiCorpAccentureIBM

Five hundred resources were built by hand over three years and must come under Terraform. Walk me through importing them without breakage.

The services-market question that decides who can actually run a migration. Import is the easy part; the hard parts are resource-for-resource fidelity and proving the first plan is empty.

Updated Sep 2026 · Grounded in researched DevOps, SRE and platform engineering interview loops, written to a senior-engineer editorial bar, and never padded to hit a word count.

TL;DR: Import adoption in waves: inventory from cloud APIs (not from memory), generate config per wave, import state, then verify with a plan that shows zero changes before moving on. Never import everything at once, never let the first real plan be a surprise, and treat resources nobody can explain as incidents to investigate rather than lines to import.

How to approach it

Structure by waves with an acceptance gate per wave. Name the tooling (import blocks or import command, plus config generation), but score comes from the process: how you handle unknown resources, dependencies, and the moment of truth when you first plan against imported state.

A strong answer

Wave 0: inventory from APIs, not from humans. List actual resources via cloud provider APIs or AWS Config, Resource Explorer or explicitly read-only provider inventory tools. Human memory and old wiki pages miss resources systematically: the test environment someone forgot, the S3 bucket created during an incident two years ago. Diff the API truth against whatever documentation exists; every mismatch is a finding, not noise.

Wave 1: the boring and low-risk. Start where mistakes are cheap and patterns are learnable: an isolated non-production stack with known owners and a verified recovery path. VPCs, routes and security groups may have a large blast radius despite simple configuration.

rendering diagram…

Per-resource loop within a wave:

  1. Write the configuration (generated scaffolds from terraform plan -generate-config-out provide a starting point; hand-finish for correctness).
  2. Add an import block with to = aws_subnet.main and id = "subnet-123" on separate lines, or use the equivalent CLI import.
  3. Generate and review a saved import plan. Configuration-driven import can also propose updates or replacements. Apply only after verifying that this adoption plan imports the intended bindings without resource mutations; otherwise fix the configuration first.
  4. Plan must return "No changes." This is the acceptance gate. Every diff is either config that does not match reality (fix the HCL) or reality that should not match config (a manual change to keep, documented). A wave ships only when its plan reads clean.

Where the difficulty concentrates:

  • Defaults that are not default. Providers often show explicit values for attributes you never set (an instance field populated by the API differently per region). Plans surface them as perpetual diffs until you align config or add ignore rules judiciously. Blanket ignore_changes hides real drift; use it surgically with comments explaining why.
  • Computed and interdependent values. Hand-built environments have implicit wiring (that subnet chosen because of an ACL added later) that modules express as references. Recreating the graph in code occasionally reveals decisions nobody remembers making; those become architecture conversations, which is a feature of this exercise.
  • Resources that cannot be safely expressed yet. Some legacy things (a database with years of unmanaged configuration, a DNS zone others mutate directly) resist clean codification. Marking a resource as explicitly out-of-scope with a dated decision beats importing it badly.
  • State hygiene throughout. Imports go into the same remote backend conventions as the rest of the estate: locking on, least-privilege access, and backups enabled before the first apply, because a corrupted state file mid-adoption is worse than no adoption.

Cutover discipline. Once a wave is adopted, the rule changes behaviour: changes to imported resources happen only through pull requests. Announce it, enforce it in review, expect violations in week one, and respond by fixing the workflow friction rather than scolding, because drift re-emerges exactly where the new path is harder than the console.

What interviewers probe next

"Plan shows a diff on an attribute nobody set. Options?" Align config to observed value if meaningful; ignore with documented reason if cosmetic; investigate if unexpected (it may be another automation writing to the same field).

"How do you prevent the console habit returning?" Read-only IAM for human identities on adopted resources, with break-glass roles logged and alarmed. Make the right path the low-friction path.

"What about secrets the hand-built setup embedded?" Expect to find credentials in user data, tags and AMIs. Rotation into a secrets manager becomes part of the migration backlog, flagged early because rotation has its own risk window.

Common mistakes

Big-bang import of everything, producing a thousand-line plan nobody can review and a team afraid to apply anything.

Trusting generated config blindly. Generation reflects current state including its accidents; without review you codify the mess you were escaping.

Declaring victory at import completion. Adoption completes when the console path is closed and plans stay clean, not when state files fill up.

Sources: Configuration-driven import.

That one was free, and so are 10 answers per topic without an account. Signing in doubles that to 20, keeps your bookmarks, and tracks which topics you keep getting wrong.one Google click · no card · nothing to cancel
HOW DID IT GO?
0
UP NEXT ON YOUR JOURNEY
DISCUSSION · 0

Nothing here yet. Say how you would answer it.