Strategy for handling mandatory, write-only attributes?

The API with which I’m working features an element which is write-only, and which is required to be populated on Create().

I’d initially planned to set Unknown: true when gathering state on Read(), and let the UseStateForUnknownModifier{} attribute plan modifier handle it.

But now I’m not sure I can do that because:

  1. Use of attribute plan modifiers requires me to set Computed: true on the attribute. (I think?)
  2. The attribute already has Required: true because it’s a mandatory API input, and I may need to remind the user of that.
  3. Computed and Required are mutually exclusive.

Is my understanding of the problem correct?

So, what’s the best way to handle this situation?

Options which have occurred to me, based on my current understanding of the framework and my problem:

  1. Skip Required: true, handle that need with a separate attribute validator.
  2. Because I know the API will never give this value back, skip the UseStateForUnknownModifier{}, and explicitly copy the old state directly into the newly-fetched state during Read()

Edit: I don’t think an attribute plan modifier can do what I need. The plan (which indicates the already-submitted write-only value) is correct.

What I need is a Read()-time state modifier, so that Read() returns the un-readable-but-known-to-the-statefile value which cannot be fetched from the API.

Hey @bumble :wave:

What it sounds like you need to capture here is:

  • The attribute value is required in the configuration, so Required: true is correct. The plan value for this attribute should always contain the configuration value due to how Terraform merges that data, in particular:

Terraform Core therefore constructs the proposed new state by taking the attribute value from Configuration if it is non-null, and then using the Prior State as a fallback otherwise, thereby helping a provider to preserve its previously-chosen value for the attribute where appropriate.

  • The configuration value changing should trigger resource recreation, which can be accomplished with the RequiresReplace() attribute plan modifier
  • In the Read logic, if you are overwriting the new state via the Set() method, you should always copy the prior state value into the new state value for that attribute since you do not receive the value via the API. The prior state value can be fetched by calling the GetAttribute() method on the read request state.

Please reach out if I can clarify things a little more.