blob: 319824ac3c570a698c85d87fc39fffa74f031755 [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package structured
import (
"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
)
type ProcessUnknown func(current Change) computed.Diff
type ProcessUnknownWithBefore func(current Change, before Change) computed.Diff
func (change Change) IsUnknown() bool {
if unknown, ok := change.Unknown.(bool); ok {
return unknown
}
return false
}
// CheckForUnknown is a helper function that handles all common functionality
// for processing an unknown value.
//
// It returns the computed unknown diff and true if this value was unknown and
// needs to be rendered as such, otherwise it returns the second return value as
// false and the first return value should be discarded.
//
// The actual processing of unknown values happens in the ProcessUnknown and
// ProcessUnknownWithBefore functions. If a value is unknown and is being
// created, the ProcessUnknown function is called and the caller should decide
// how to create the unknown value. If a value is being updated the
// ProcessUnknownWithBefore function is called and the function provides the
// before value as if it is being deleted for the caller to handle. Note that
// values being deleted will never be marked as unknown so this case isn't
// handled.
//
// The childUnknown argument is meant to allow callers with extra information
// about the type being processed to provide a list of known children that might
// not be present in the before or after values. These values will be propagated
// as the unknown values in the before value should it be needed.
func (change Change) CheckForUnknown(childUnknown interface{}, process ProcessUnknown, processBefore ProcessUnknownWithBefore) (computed.Diff, bool) {
unknown := change.IsUnknown()
if !unknown {
return computed.Diff{}, false
}
// No matter what we do here, we want to treat the after value as explicit.
// This is because it is going to be null in the value, and we don't want
// the functions in this package to assume this means it has been deleted.
change.AfterExplicit = true
if change.Before == nil {
return process(change), true
}
// If we get here, then we have a before value. We're going to model a
// delete operation and our renderer later can render the overall change
// accurately.
before := change.AsDelete()
// We also let our callers override the unknown values in any before, this
// is the renderers can display them as being computed instead of deleted.
before.Unknown = childUnknown
return processBefore(change, before), true
}