Open flynnhandley opened 6 years ago
Hi @flynnhandley!
We may be able to do something like this, though I'd want to think about it a bunch more to see if there are implications we're not thinking of.
The intended way to handle this today is to call d.SetId
immediately after the resource is created, so that it gets recorded in the state, and then to progressively record more values in the state as you go, possibly using d.Partial
and d.SetPartial
to control what gets written to the state when you return. (Partial mode allows you to prevent certain values that were provided in config from being written to the state, to avoid creating the impression that certain things were committed when they actually weren't.)
If the right values are written to state at the right times then Terraform's usual diffing machinery can take care of this by detecting on the next run that the resource state doesn't completely match the configuration, and then the Update
implementation can pick up where the Create
left off, rather than replacing the resource entirely. (Though indeed, if one of the things that needs fixing is a ForceNew
attribute then it will be marked as a replacement action, as expected.)
Hi @apparentlymart, Thanks for the feedback.
I think that d.partial
and d.setPartial
solve a slightly different problem where Create
completes but not all components of the resource have been created.
The problem I'm try to solve is where Create
terminates before the state can be persisted (leaving a Zombie resource)
Hi @flynnhandley,
Looking again at the full source-code you linked, I have some different suggestions that don't involve the use of d.Partial
:
As soon as you call d.SetId
with a non-empty string, Terraform will write the instance state out on exit.
You don't currently have a Read
implementation, but if you implement it then Create
only needs to save enough information to be able to read back the current "real" state and write it into Terraform using d.Set
calls. This means it no longer matters if Create
ends early, as long as you make sure you save all of the ids you need to implement Read
.
With Read
properly implemented, Terraform will be able to detect that the current "real" state is missing items compared to the config, and so Terraform will generate an "update" diff as expected, to finish constructing anything that wasn't built during Create
.
I notice also that your Update
implementation is just to delete and then create. In that case, you can omit the Update
function altogether and just mark all of your attributes as ForceNew
, which tells Terraform that any config change requires the resource to be destroyed and re-created.
With all of that done, you get the effect you were looking for:
Read
and that updates the Terraform state to reflect the fact that some associated objects are missing on the real instance.ForceNew
, Terraform will generate a -/+
(replace) diff, causing the instance to get rebuilt similarly to what would happen if you'd tainted it.The key thing to know here is that although Terraform writes the entire resource config into the state, most of it isn't really needed as long as the Read
implementation is robust because it will automatically update the state to match the real world on the next run.
Hi There,
It would be nice if I could mark a resource as (partially) added or tainted during creation.
Given the pseudo code below, If we create VM, then the Terraform process is destroyed before resourceHypervVMCreate can return, we end up with a VM on the hypervisor which has not been added to the Terraform state, therefore Terraform -destroy will not remove the VM.
You can see the full code here