• HashiCorp Developer

  • HashiCorp Cloud Platform
  • Terraform
  • Packer
  • Consul
  • Vault
  • Boundary
  • Nomad
  • Waypoint
  • Vagrant
Terraform
  • Install
  • Tutorials
    • About the Docs
    • Configuration Language
    • Terraform CLI
    • Terraform Cloud
    • Terraform Enterprise
    • CDK for Terraform
    • Provider Use
    • Plugin Development
    • Registry Publishing
    • Integration Program
  • Registry(opens in new tab)
  • Try Cloud(opens in new tab)
  • Sign up
Plugin Development

SDKv2

Skip to main content
  • SDKv2
  • Migrate to the Framework
    (opens in new tab)
    • Overview
    • Customizing Differences
    • Import
    • Retries and Customizable Timeouts
    • State Migration
  • Debugging Providers

  • Resources

  • Tutorial Library
  • Certifications
  • Community Forum
    (opens in new tab)
  • Support
    (opens in new tab)
  • GitHub
    (opens in new tab)
  • Terraform Registry
    (opens in new tab)
  1. Developer
  2. Terraform
  3. Plugin Development
  4. SDKv2
  5. Resources
  6. Customizing Differences
  • Plugin SDK
  • v2.23.x
  • v2.22.x
  • v2.21.x
  • v2.20.x
  • v2.19.x
  • v2.18.x
  • v2.17.x
  • v2.16.x
  • v2.15.x

»Resources - Customizing Differences

Terraform tracks the state of provisioned resources in its state file, and compares the user-passed configuration against that state. When Terraform detects a discrepancy, it presents the user with the differences between the configuration and the state.

Sometimes determining the differences between state and configuration requires special handling, which can be managed with the CustomizeDiff function.

CustomizeDiff is passed a *schema.ResourceDiff. This is a structure similar to schema.ResourceData — it lacks most write functions (like Set), but adds some functions for working with the difference, such as SetNew, SetNewComputed, and ForceNew.

NOTE: CustomizeDiff does not currently support computed/"known after apply" values from other resource attributes.

Any function can be provided for difference customization. For the majority of simple cases, we recommend that you first try to compose the behavior using the customdiff helper package, which allows for a more declarative configuration. However, for highly custom requirements, a custom-made function is usually easier and more maintainable than working around the helper's limitations.

package example

import (
    "fmt"

    "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
    "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceExampleInstance() *schema.Resource {
    return &schema.Resource{
        Create: resourceExampleInstanceCreate,
        Read:   resourceExampleInstanceRead,
        Update: resourceExampleInstanceUpdate,
        Delete: resourceExampleInstanceDelete,

        Schema: map[string]*schema.Schema{
            "size": {
                Type:     schema.TypeInt,
                Required: true,
            },
        },
        CustomizeDiff: customdiff.All(
            customdiff.ValidateChange("size", func (ctx context.Context, old, new, meta any) error {
                // If we are increasing "size" then the new value must be
                // a multiple of the old value.
                if new.(int) <= old.(int) {
                    return nil
                }
                if (new.(int) % old.(int)) != 0 {
                    return fmt.Errorf("new size value must be an integer multiple of old value %d", old.(int))
                }
                return nil
            }),
            customdiff.ForceNewIfChange("size", func (ctx context.Context, old, new, meta any) bool {
                // "size" can only increase in-place, so we must create a new resource
                // if it is decreased.
                return new.(int) < old.(int)
            }),
       ),
    }
}

In this example we use the helpers to ensure the size can only be increased to multiples of the original size, and that if it is ever decreased it forces a new resource. The customdiff.All helper will run all the customization functions, collecting any errors as a multierror. To have the functions short-circuit on error, please use customdiff.Sequence.

Edit this page on GitHub
Give Feedback(opens in new tab)
  • Certifications
  • System Status
  • Terms of Use
  • Security
  • Privacy
  • Trademark Policy
  • Trade Controls
  • Give Feedback(opens in new tab)