github.com/opentofu/opentofu@v1.7.1/internal/command/jsonformat/structured/unknown.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package structured 7 8 import ( 9 "github.com/opentofu/opentofu/internal/command/jsonformat/computed" 10 ) 11 12 type ProcessUnknown func(current Change) computed.Diff 13 type ProcessUnknownWithBefore func(current Change, before Change) computed.Diff 14 15 func (change Change) IsUnknown() bool { 16 if unknown, ok := change.Unknown.(bool); ok { 17 return unknown 18 } 19 return false 20 } 21 22 // CheckForUnknown is a helper function that handles all common functionality 23 // for processing an unknown value. 24 // 25 // It returns the computed unknown diff and true if this value was unknown and 26 // needs to be rendered as such, otherwise it returns the second return value as 27 // false and the first return value should be discarded. 28 // 29 // The actual processing of unknown values happens in the ProcessUnknown and 30 // ProcessUnknownWithBefore functions. If a value is unknown and is being 31 // created, the ProcessUnknown function is called and the caller should decide 32 // how to create the unknown value. If a value is being updated the 33 // ProcessUnknownWithBefore function is called and the function provides the 34 // before value as if it is being deleted for the caller to handle. Note that 35 // values being deleted will never be marked as unknown so this case isn't 36 // handled. 37 // 38 // The childUnknown argument is meant to allow callers with extra information 39 // about the type being processed to provide a list of known children that might 40 // not be present in the before or after values. These values will be propagated 41 // as the unknown values in the before value should it be needed. 42 func (change Change) CheckForUnknown(childUnknown interface{}, process ProcessUnknown, processBefore ProcessUnknownWithBefore) (computed.Diff, bool) { 43 unknown := change.IsUnknown() 44 45 if !unknown { 46 return computed.Diff{}, false 47 } 48 49 // No matter what we do here, we want to treat the after value as explicit. 50 // This is because it is going to be null in the value, and we don't want 51 // the functions in this package to assume this means it has been deleted. 52 change.AfterExplicit = true 53 54 if change.Before == nil { 55 return process(change), true 56 } 57 58 // If we get here, then we have a before value. We're going to model a 59 // delete operation and our renderer later can render the overall change 60 // accurately. 61 before := change.AsDelete() 62 63 // We also let our callers override the unknown values in any before, this 64 // is the renderers can display them as being computed instead of deleted. 65 before.Unknown = childUnknown 66 return processBefore(change, before), true 67 }