Hi @saltxwater,
I’m not sure if I’m fully understanding the situation you are describing so I want to first restate what I think you are seeing, so you can correct me if I’m wrong, and then I’ll try to answer it but of course you can ignore my answer if I misunderstood the question!
You’ve described a situation where your path
attribute is appearing as (known after apply)
in the plan, even though you have system-specific knowledge that allows you to know what that value will be and that it actually shouldn’t be changing.
Unless a provider developer writes something special in the CustomizeDiff
function, a (known after apply)
value should appear only for a “create” operation, so I think what you are seeing is that you’ve changed the configuration for an argument that has ForceNew
set, which is then causing the SDK to tell Terraform that the provider plans to replace the object, rather than to update the object.
Consequently, all of the “computed” attributes return to being (known after apply)
again, because a “replace” destroys the existing object and creates a new one. You can recognize the situation I’m describing by looking for the -/+
or +/-
symbols against the action on the resource you’re looking at, both of which represent “replace” actions, as opposed to ~
which represents an “update” action.
If the above matches what you are seeing then I think there are two possible paths forward here, and you might possibly be able to do both of them if you can meet the requirements for them.
The first and generally easier path is to look for opportunities to remove ForceNew
from some or all of your arguments and thus handle more changes as Update
rather than as Delete
+Create
. Computed attributes are preserved in the state across an Update
(unless the provider logic intentionally changes them), so your path
should therefore not show as (known after apply)
, but this is appropriate only if the remote system itself can also handle these changes as updates, because it would be confusing and unsafe to report to the user that the provider will do an update but then actually secretly delete the original object, assuming that there’s a user-visible difference between updating and recreating in this system.
The other path, which is a little more complex, is to think about whether you can use the documented behavior of the remote system to have your provider predict a value for path
during the plan phase. The typical situation where this is possible is when the computed attribute is systematically constructed from other arguments set in the configuration, such as if the remote system constructs path
by transforming a user-provided name
argument in a way that the provider code can replicate.
For the second path you’ll need to add a CustomizeDiff
function to your resource type implementation if you don’t already have one, and then include in it some logic to first check whether all of the required arguments are known (since they might themselves be populated from (known after apply)
values) and them, if so, set a known value for path
which will then appear in the plan for the resource instance as a concrete value, instead of (known after apply)
. For example:
CustomizeDiff: func(d *ResourceDiff, meta interface{}) error {
// If the name is known then we can predict the path
if d.NewValueKnown("name") {
d.SetNew("path", "/example/" + d.Get("name").(string))
} else {
d.SetNewComputed("path")
}
}
The Terraform SDK has a built-in default behavior which you’ve already observed which is, in effect, to call d.SetNewComputed
on each computed attribute when planning a “create” action, and to preserve the prior value when planning an “update” action. The above overrides those defaults so that path
can have a known value whenever name
has a known value, and additionally that if the user changes name
for an existing object the provider will also plan to change path
to match it, allowing the new path
value to propagate to downstream resources immediately during planning.