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  }