github.com/opentofu/opentofu@v1.7.1/internal/command/jsonformat/structured/sensitive.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  	"github.com/opentofu/opentofu/internal/plans"
    11  )
    12  
    13  type ProcessSensitiveInner func(change Change) computed.Diff
    14  type CreateSensitiveDiff func(inner computed.Diff, beforeSensitive, afterSensitive bool, action plans.Action) computed.Diff
    15  
    16  func (change Change) IsBeforeSensitive() bool {
    17  	if sensitive, ok := change.BeforeSensitive.(bool); ok {
    18  		return sensitive
    19  	}
    20  	return false
    21  }
    22  
    23  func (change Change) IsAfterSensitive() bool {
    24  	if sensitive, ok := change.AfterSensitive.(bool); ok {
    25  		return sensitive
    26  	}
    27  	return false
    28  }
    29  
    30  // CheckForSensitive is a helper function that handles all common functionality
    31  // for processing a sensitive value.
    32  //
    33  // It returns the computed sensitive diff and true if this value was sensitive
    34  // and needs to be rendered as such, otherwise it returns the second return
    35  // value as false and the first value can be discarded.
    36  //
    37  // The actual processing of sensitive values happens within the
    38  // ProcessSensitiveInner and CreateSensitiveDiff functions. Callers should
    39  // implement these functions as appropriate when using this function.
    40  //
    41  // The ProcessSensitiveInner function should simply return a computed.Diff for
    42  // the provided Change. The provided Change will be the same as the original
    43  // change but with the sensitive metadata removed. The new inner diff is then
    44  // passed into the actual CreateSensitiveDiff function which should return the
    45  // actual sensitive diff.
    46  //
    47  // We include the inner change into the sensitive diff as a way to let the
    48  // sensitive renderer have as much information as possible, while still letting
    49  // it do the actual rendering.
    50  func (change Change) CheckForSensitive(processInner ProcessSensitiveInner, createDiff CreateSensitiveDiff) (computed.Diff, bool) {
    51  	beforeSensitive := change.IsBeforeSensitive()
    52  	afterSensitive := change.IsAfterSensitive()
    53  
    54  	if !beforeSensitive && !afterSensitive {
    55  		return computed.Diff{}, false
    56  	}
    57  
    58  	// We are still going to give the change the contents of the actual change.
    59  	// So we create a new Change with everything matching the current value,
    60  	// except for the sensitivity.
    61  	//
    62  	// The change can choose what to do with this information, in most cases
    63  	// it will just be ignored in favour of printing `(sensitive value)`.
    64  
    65  	value := Change{
    66  		BeforeExplicit:     change.BeforeExplicit,
    67  		AfterExplicit:      change.AfterExplicit,
    68  		Before:             change.Before,
    69  		After:              change.After,
    70  		Unknown:            change.Unknown,
    71  		BeforeSensitive:    false,
    72  		AfterSensitive:     false,
    73  		ReplacePaths:       change.ReplacePaths,
    74  		RelevantAttributes: change.RelevantAttributes,
    75  	}
    76  
    77  	inner := processInner(value)
    78  
    79  	action := inner.Action
    80  	sensitiveStatusChanged := beforeSensitive != afterSensitive
    81  
    82  	// nullNoOp is a stronger NoOp, where not only is there no change happening
    83  	// but the before and after values are not explicitly set and are both
    84  	// null. This will override even the sensitive state changing.
    85  	nullNoOp := change.Before == nil && !change.BeforeExplicit && change.After == nil && !change.AfterExplicit
    86  
    87  	if action == plans.NoOp && sensitiveStatusChanged && !nullNoOp {
    88  		// Let's override this, since it means the sensitive status has changed
    89  		// rather than the actual content of the value.
    90  		action = plans.Update
    91  	}
    92  
    93  	return createDiff(inner, beforeSensitive, afterSensitive, action), true
    94  }