There're 2 properties for my terraform resource and one of them can be updated but the other can't so I want to mark it as immutable but when I open https://github.com/hashicorp/terraform-plugin-sdk/blob/main/helper/schema/schema.go#L37, it seems like there's no such an option.
Can I mark a property as immutable in Terraform resource anyhow?
Based on your question I think you are asking about a provider you are developing, rather than a Terraform module written against an existing provider.
Lots of remote APIs have object properties that are fixed once the object is created, but preventing them from changing altogether would violate Terraform's declarative model, and so the typical way to represent this in providers is for the provider to respond to a change on such an attribute by reporting that it can't make that change without replacing the object, which is to say: destroying the existing object and creating a new one to replace it.
In the Terraform SDK there's a convenient attribute for the common case that any value change requires replacement: if you set ForceNew: true
then the SDK will automatically notice if there's a change to the value of that attribute and report back to Terraform that the change is impossible without replacing the object. Terraform will then ask the provider to plan to create a new object instead, and present the result to the user as a planned action where the resource instance "must be replaced", with an annotation attached to the argument whose change prompted that proposal.
In some rarer cases the rules are more complicated, such as it being possible to change values in certain ways but not in other ways. For example, if a resource type is representing a virtual disk then it might be possible to grow the disk without replacing it, but not possible to shrink it. In that case, you can use the resource-level CustomizeDiff
function to specify some custom logic for making the decision, calling ResourceDiff.ForceNew
conditionally if e.g. the change to the disk size indicates that the new value is less than the old value.
You can think of the ForceNew: true
attribute-level setting as a convenience shorthand for the more general CustomizeDiff
approach, which suffices for most common situations.