Terraform
- Plugin Framework
- v1.16.x (latest)
- No versions of this document exist before v1.15.x. Click below to redirect to the version homepage.
- v1.15.x
- v1.14.x
- v1.13.x
- v1.12.x
- v1.11.x
- v1.10.x
- v1.9.x
- v1.8.x
- v1.7.x
- v1.6.x
- v1.5.x
- v1.4.x
- v1.3.x
- v1.2.x
- v1.1.x
- v1.0.x
- v0.16.x
- v0.15.x
- v0.14.x
- v0.13.x
- v0.12.x
- v0.11.x
- v0.10.x
- v0.9.x
- v0.8.x
- v0.7.x
ForceNew
Note: The Plugin Framework is in beta.
In Terraform, sometimes a resource must be replaced when the value of an attribute changes. In SDKv2, this is
accomplished via the ForceNew field. In the Framework, you implement the same behavior via a RequiresReplace plan
modifier. Refer to
Plan Modification - Attribute Plan Modification
in the Framework documentation for details.
This page explains how to migrate this behavior from SDKv2 to the Framework.
SDKv2
In SDKv2, setting the ForceNew field on an attribute's schema.Schema triggers a replace (i.e., a destroy-create
cycle) whenever the attribute's value is changed.
func resourceExample() *schema.Resource {
    return &schema.Resource{
        /* ... */
        Schema: map[string]*schema.Schema{
            "attribute_example": {
                ForceNew:    true
                /* ... */
Framework
In the Framework, you implement the same behavior by using the resource.RequiresReplace plan modifier on your
attribute's schema.Attribute implementation.
func (r *ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
    return schema.Schema{
        /* ... */
        Attributes: map[string]schema.Attribute{
            "attribute_example": schema.StringAttribute{
                PlanModifiers: []planmodifier.String{
                    stringplanmodifier.RequiresReplace(),
                    /* ... */
Migration Notes
Remember the following differences between SDKv2 and the Framework when completing the migration.
- In both SDKv2 and Framework, ForceNewandRequiresReplace, respectively, only trigger a replace if the attribute is not computed. In the Framework, if an attribute which is computed requires that the resource be replaced when it is changed, implement a plan modifier that triggers the replacement. Refer to RequiresReplacePlanModifier for an example, but bear in mind that each implementation requires different logic and you may need to detect whether the plan has already been modified.
Example
The following examples show how to migrate portions of the random provider.
For a complete example, clone the
terraform-random-provider repository and compare the resource_password.go file in
v3.3.2
with the file after the migration.
SDKv2
The following example from the resource_password.go file shows the implementation of the ForceNew field of the
random_password resource's keepers attribute with SDKv2.
func resourcePassword() *schema.Resource {
    return &schema.Resource{
        Schema: map[string]*schema.Schema{
            "keepers": {
                ForceNew: true,
                /* ... */
            },
            /* ... */
        },
        /* ... */
    }
}
Framework
The following shows the same section of provider code after the migration.
This code forces the replacement of a random_password resource when the value of the keepers attribute is changed.
The example does this using the PlanModifiers field within the random_password attribute's schema.
func (r *passwordResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
    resp.Schema = schema.Schema{
        Attributes: map[string]schema.Attribute{
            "keepers": schema.MapAttribute{
                PlanModifiers: []planmodifier.Map{
                    mapplanmodifier.RequiresReplace(),
                },
                /* ... */
            },
            /* ... */
        },
    }
}