0
votes

I'm reading about the underpinnings of providers in Terraform. In my case I have two attributes as part of a resource which changes the power state of a server. They are desired_power_action and the other is power_state. desired_power_action could be something like FORCE_OFF. After the completion of this action I expect the power_state to be off.

desired_power_action is a required field and power_state is a computed field. As I understand it, in the plan phase it will project desired_power_action to be whatever the user picks. Indeed, in my provider I simply set it to whatever the user said they wanted it to be as it is only what they desire it be set to. However for power_state I'm not sure how to tell Terraform in my provider code that if the user sets desired_power_action to FORCE_OFF then the projected value of power_state is then off.

I know how to set that value at apply time but how do I tell Terraform at plan time power_state should be XXXXXX after application?

Or am I misunderstanding and this isn't something I need to do?

1
It might help if you can link to the resource documentation.user3546408
You shouldn't need to do anything here and instead it should just say in the plan that it's computed and show (known after apply) in the plan output to the terminal. Are you seeing some other issue here?ydaetskcoR
Are you writing a provider using the official SDK, or are you programming directly against the wire protocol? The answer will be quite different depending on which, because the SDK adds some additional abstractions on top of the wire protocol.Martin Atkins
@MartinAtkins the official SDKGrant Curell

1 Answers

1
votes

The "Resource Instance Change Lifecycle" documentation you linked to here is written from the perspective of a Terraform Core developer because it's documentation aimed mainly at folks contributing to Terraform Core, as opposed to provider developers.

The Terraform SDK team also refers to this documentation in order to understand what invariants the SDK ought to guarantee, but the SDK then adds its own abstractions on top of that lower-level model so that it's more convenient to develop Terraform providers that fit commonly-used patterns.

In your case, I think you've noticed that the raw protocol calls for PlanResourceChange to provide a value for each of the "computed" attributes on the resource type, where it can either use an "unknown value" placeholder (which translates to (known after apply) in Terraform's UI) or (if the provider knows enough to predict the final value) it can return a concrete value that must then match what ApplyResourceChange finally returns.

The SDK will, by default, respond to PlanResourceChange by setting all computed attributes to "unknown", and so most resource types in practice don't include any special logic for this. However, in situations like yours where there is something predictable you can optionally customize that default behavior by populating the CustomizeDiff field of schema.Resource.

The CustomizeDiff callback recieves a schema.ResourceDiff object, which is similar to schema.ResourceData but includes some extra methods to deal with the fact that a diff includes both old and new values for each argument/attribute.

In your case, you can write some logic to conditionally call SetNew in situations where you know a concrete new value. The SDK will then in turn return that in its PlanResourceChange response, instead of the default behavior of returning an unknown value.