If a resource has been manually created and it is then brought into terraform, why couldn’t terraform just compare and update against the existing resource rather than:
requiring the user to do a “terraform import” first before plan/apply
allowing the user to do a run that will fail when they don’t import, when it would be (presumably) possible for it to succeed (just by updating the resource that exists).
I’m not necessarily asking from an architecture perspective. e.g. “it’s required because terraform works like blah”. I’m asking from a DX perspective. wouldn’t it be better if terraform did this? rather than forcing the user to have to correct it with terraform import commands that are error prone.
I know there are some cases where it wouldn’t be able to do this. But so many terraform resources have a field that makes the resources uniquely identified. If there is no way it could accidentally choose the wrong resource why not just update it in place without requiring the import step?
Terraform requires an explicit import step so that you can confirm that you intend to bind the specific remote object to the specific resource instance address specified, and not to anything else.
Terraform’s model assumes that each object is managed by one resource instance in one configuration. Normally Terraform guarantees that by having been the one to create the object in the first place.
If you are instead intending to make Terraform treat an existing object as if it had been created by Terraform, there’s no way for Terraform itself to prove that the object isn’t already managed by a resource instance in some other configuration. By running terraform import you are telling Terraform that you’ve checked yourself to ensure that this existing object is not already being managed by something else and so it’s safe for Terraform to adopt it.
Thinking a bit about your point around encouraging the user to “check”. Whether the user has to check or not check if it’s safe to start managing it, the problem of more than one manager of a given resource could still occur. As an example, if two teams were managing the same resource via terraform (unknowingly) it could in theory be imported into both workspaces. They would be seeing diffs in the plan and correcting accordingly (to the later dissatisfaction of the other party). To me that’s the same experience as if it just didn’t force the import upon anyone. The problem should in theory be resolved when one or both parties start questioning why the plan is looking different. Or, they both go on (forever) unknowing of the multiple managers because it’s defined the same on both side.
For the cases where something else is not managing it (e.g. it was just created manually once by a dev), which in my opinion is the most common case, then no harm done and a lot of time saved if it just started managing it without forcing the “import”.
I love terraform. I really like it. But almost every working day I think about this as something that doesn’t feel right. It increases the barrier of using terraform for people who have already done some manual things. The kind of people who would be great to have on-board the terraform train. At least in my mind!
In addition to the already mentioned issue around not wanting to import resources which are actually mentioned elsewhere (and therefore having a manual step to get someone to check/investigate that) there is also the problem of knowing what to import.
Many resources have nothing that requires uniqueness, so you have no way of knowing that any pre-existing resources are actually ones you would want to associate with some Terraform code. And even if there are unique characteristics how would Terraform know that there is the intention of associating an existing resource with some code - what if the unique name matched, but other attributes differed? What if the name was actually wrong in the code and so a link wasn’t made?
Finally while doing imports can be a bit of a pain at times (remembering/checking what ID needs to be used) in general it should really be something that is used pretty infrequently. It can be really useful if you are retrofitting Terraform around existing resources (at which point from a UX perspective it would probably be nicer to have a facility to say “make me some code from these resources” - akin to the old Terraforming tool) that is generally one-off and infrequent. We find that we are actually using terraform import a handful of times a month (if that) as everything is handled via Terraform instead of being handled manually.
I think a lot depends on what exactly you’re managing with Terraform.
I’ve done quite a lot of work bringing a legacy Vault installation under Terraform control:
Since many of the configuration items in Vault are manipulated using CRUD REST APIs, for which “update” and “create” are the same HTTP call, I was able to cheat extensively, by having Terraform believe it was “creating” objects when it was actually just doing a no-op “update”, thus sparing me the need to explicitly import many things.
Some of the configuration items in Vault don’t follow this pattern. They had to be imported. Writing a script to manufacture several thousand terraform import commands was OK. Having to run a separate terraform import command for every resource instance was really slow.
Lastly, there are some unexpected risks with imports - if you import some objects, and don’t take care to ensure there are no race conditions between running your import, and putting your updated Terraform source code in place for future runs - such that TFE runs on old Terraform source but new state - your imported objects could be accidentally destroyed by Terraform!
Putting all these things together, I’d really like to see a new addition to the Terraform language - similar to moved blocks - that allows for declarative import operations to be included as part of a plan-and-apply.