Help us shape the future of Go! Take the 2026 Go Developer Survey

planmodifiers

package
v1.7.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2026 License: MPL-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package planmodifiers provides shared Terraform Plugin Framework plan modifiers for use across all resource packages.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecideResetForUnchangedString

func DecideResetForUnchangedString(sourceEqual bool, stateValue types.String) (types.String, bool)

DecideResetForUnchangedString centralises the override decision for the String plan modifier so it can be unit-tested without constructing a full tfsdk.Plan / State. The surrounding plumbing in PlanModifyString (Raw null guards, config-value precedence, path reads) is covered by the acceptance suite.

Returns (value, true) when the caller should overwrite resp.PlanValue, or (zero, false) to leave it untouched (default Unknown).

  • sourceEqual=false → (_, false): leave Unknown; apply writes the fresh server value.
  • sourceEqual=true + state known + state non-null → (state, true): carry forward.
  • state null or unknown → (_, false).

func MirrorOfString

func MirrorOfString(sources ...SourceComparer) planmodifier.String

MirrorOfString returns a plan modifier for a Computed-only string attribute that Jamf Pro derives from one or more SIBLING attributes the same resource manages — a mirror, not an independent server-assigned value.

Neither of the obvious answers is right for a mirror. Plain UseStateForUnknown promises the value cannot change unless the practitioner changes this attribute, but it changes when the *source* changes, so the plan carries a stale value into an apply that returns a fresh one and Terraform reports "Provider produced inconsistent result after apply". Omitting the modifier entirely leaves the attribute Unknown on every plan, which makes `terraform plan -refresh=false` permanently dirty for a value nobody touched.

So: carry the prior value forward while every watched source is unchanged between state and plan, and go Unknown as soon as one of them moves. The sources may be of any type — pass StringSource or BoolSource per path.

Used by jamfplatform_pro_mobile_device_app for general.description (mirrors self_service.self_service_description) and general.deployment_type (mirrors general.deploy_automatically).

func ResetIfSourceChangedString

func ResetIfSourceChangedString(sourcePaths ...path.Expression) planmodifier.String

ResetIfSourceChangedString returns a plan modifier for Optional+Computed string attributes whose server-derived value depends on the bytes of a *_file_source upload input. When any watched source attribute differs between state and plan, the attribute's plan value is left Unknown so the server can populate a fresh value during apply. When all sources are unchanged, the prior state value carries forward (UseStateForUnknown semantics) so trivial metadata updates do not churn the diff.

func UseKeyedStateForUnknownBool added in v1.4.0

func UseKeyedStateForUnknownBool(key string) planmodifier.Bool

UseKeyedStateForUnknownBool is UseKeyedStateForUnknownString for bool attributes.

func UseKeyedStateForUnknownString added in v1.4.0

func UseKeyedStateForUnknownString(key string) planmodifier.String

UseKeyedStateForUnknownString carries the prior value of an Optional+Computed string attribute of a set- or list-nested element onto the planned element, but only from the prior element whose key attribute equals the planned element's.

It replaces UseNonNullStateForUnknown inside id-keyed sets. The framework pairs a planned set element with prior state by INDEX, not by identity, so the stock modifier copies whatever sits at the same position: re-keying an element, or reordering the set, hands the new element another object's values. For a server-derived value that is a perpetual or inconsistent diff; for a user-visible default it silently gives a new element the old element's settings. Keyed lookup carries only on a genuine match and otherwise leaves the value Unknown for the server to answer.

Two matches on one key, or none, carry nothing: with duplicates there is no telling which prior element a planned one continues. A list pairs by index in the framework too, which is just as wrong once an element is inserted or reordered. See issue #464.

func UseStateForUnknownInExistingBlockBool added in v1.4.0

func UseStateForUnknownInExistingBlockBool() planmodifier.Bool

UseStateForUnknownInExistingBlockBool is the bool sibling of UseStateForUnknownInExistingBlockString.

func UseStateForUnknownInExistingBlockInt64 added in v1.4.0

func UseStateForUnknownInExistingBlockInt64() planmodifier.Int64

UseStateForUnknownInExistingBlockInt64 is the int64 sibling of UseStateForUnknownInExistingBlockString.

func UseStateForUnknownInExistingBlockString added in v1.4.0

func UseStateForUnknownInExistingBlockString() planmodifier.String

UseStateForUnknownInExistingBlockString returns a plan modifier for an Optional+Computed string inside an Optional single-nested block. It behaves as UseStateForUnknown except when the block is new in this plan, where it leaves the value Unknown. See carryPrior for the rule.

Types

type SourceComparer

type SourceComparer func(ctx context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) (unchanged, ok bool)

SourceComparer reports whether one watched source attribute is unchanged by this plan. ok is false when the value could not be read at all, which the caller treats as "cannot tell" and resolves conservatively.

func BoolSource

func BoolSource(p path.Expression) SourceComparer

BoolSource watches a bool attribute.

func NestedStringSource added in v1.3.0

func NestedStringSource(block path.Expression, attribute string) SourceComparer

NestedStringSource watches one string attribute inside a single-nested block.

Prefer it to a path into an Optional block. When the block is null, PathMatches resolves the expression only as far as the block, so a leaf watcher receives the object's path and fails with "Cannot use attr.Value basetypes.StringValue, only basetypes.ObjectValue is supported". This reads the block first and the leaf from it.

Do not watch the whole block either. compareSource calls a block unchanged only when it is null in config. A declared block with an unset Optional+Computed leaf is null there and populated in state, so the two never compare equal, and the mirror goes Unknown in every plan that changes anything else in the resource, even when the leaf it mirrors did not move.

The result per case:

  • A null block, or a null leaf, is unchanged. The practitioner is not moving the source, and an unset Optional+Computed leaf carries its prior value forward itself.
  • An Unknown block or leaf is changed. The value is not known until apply (interpolated from a resource still being created), so a prior mirror value may be stale by then and Terraform would reject the result.
  • A leaf set where state has no block or no value is changed.
  • A set leaf is unchanged exactly when it equals the state value.
  • A block that cannot be read, or a leaf the block does not have, cannot be judged, so the mirror stays Unknown.

func StringSource

func StringSource(p path.Expression) SourceComparer

StringSource watches a string attribute.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL