Terraform Import: How to Handle Optional Field That’s API-Unretrievable & Non-Updatable?

I’m developing a Terraform Provider and encountered an issue: I have an optional immutable field configured with Optional: true + RequireReplace(), and the remote API cannot retrieve this field. Creating resources directly via Terraform works without problems. However, when a resource is first created through the console and then imported using Terraform’s import block:

  • If the actual value of this field is explicitly specified in the configuration file, running terraform plan will show “will be replaced”.

  • If the field is not declared in the configuration file, the import works normally.

In this scenario, should I keep the RequireReplace() modifier, or implement a custom planmodifier that allows updating the state with the value from the configuration file (only updating the state, as the remote API does not support modifications) when the field’s value in the state is null (which is the case after import)?

Do you think it would be reasonable to model the attribute you’re talking about as a write-only argument?

That concept directly models the idea of something that an API only allows to be written and not read back, but that has some implications for how the argument can be used. Those implications are largely just natural consequences of something not being readable from the API, but might nonetheless be undesirable anyway.

If you can model it as a write-only argument then Terraform won’t require you to import it, though if you follow some of the ideas in Best Practices then you may encounter other variations of the “how to import” problem, though…

For example, if you choose to use the strategy with a separate _version argument to indicate that a change is needed then you’d need to document what version number gets used when first importing something so that authors can make sure to write their configuration to match that initial version number.

If you choose to implement the “private state” idea that the documentation discusses then another option would be to have the import process set the private state in a special way that would never be caused in any other case, and then on the first plan after an import you can notice that the item was imported and just arrange to copy the _version argument’s value from the configuration into the state, instead of using it to trigger an update of the write-only argument. If you use this approach then you must make sure that the first plan/apply round after import causes the “private state” to be updated so it no longer implies that the item was freshly imported, so that subsequent changes to _version will have the expected effect of updating the write-only argument.