github.com/opentofu/opentofu@v1.7.1/internal/command/jsonformat/computed/renderers/set.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 renderers
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  
    12  	"github.com/opentofu/opentofu/internal/command/jsonformat/computed"
    13  	"github.com/opentofu/opentofu/internal/plans"
    14  )
    15  
    16  var _ computed.DiffRenderer = (*setRenderer)(nil)
    17  
    18  func Set(elements []computed.Diff) computed.DiffRenderer {
    19  	return &setRenderer{
    20  		elements: elements,
    21  	}
    22  }
    23  
    24  func NestedSet(elements []computed.Diff) computed.DiffRenderer {
    25  	return &setRenderer{
    26  		elements:                  elements,
    27  		overrideForcesReplacement: true,
    28  	}
    29  }
    30  
    31  type setRenderer struct {
    32  	NoWarningsRenderer
    33  
    34  	elements []computed.Diff
    35  
    36  	overrideForcesReplacement bool
    37  }
    38  
    39  func (renderer setRenderer) RenderHuman(diff computed.Diff, indent int, opts computed.RenderHumanOpts) string {
    40  	// Sets are a bit finicky, nested sets don't render the forces replacement
    41  	// suffix themselves, but push it onto their children. So if we are
    42  	// overriding the forces replacement setting, we set it to true for children
    43  	// and false for ourselves.
    44  	displayForcesReplacementInSelf := diff.Replace && !renderer.overrideForcesReplacement
    45  	displayForcesReplacementInChildren := diff.Replace && renderer.overrideForcesReplacement
    46  
    47  	if len(renderer.elements) == 0 {
    48  		return fmt.Sprintf("[]%s%s", nullSuffix(diff.Action, opts), forcesReplacement(displayForcesReplacementInSelf, opts))
    49  	}
    50  
    51  	elementOpts := opts.Clone()
    52  	elementOpts.OverrideNullSuffix = true
    53  	elementOpts.OverrideForcesReplacement = displayForcesReplacementInChildren
    54  
    55  	unchangedElements := 0
    56  
    57  	var buf bytes.Buffer
    58  	buf.WriteString(fmt.Sprintf("[%s\n", forcesReplacement(displayForcesReplacementInSelf, opts)))
    59  	for _, element := range renderer.elements {
    60  		if element.Action == plans.NoOp && !opts.ShowUnchangedChildren {
    61  			unchangedElements++
    62  			continue
    63  		}
    64  
    65  		for _, warning := range element.WarningsHuman(indent+1, opts) {
    66  			buf.WriteString(fmt.Sprintf("%s%s\n", formatIndent(indent+1), warning))
    67  		}
    68  		buf.WriteString(fmt.Sprintf("%s%s%s,\n", formatIndent(indent+1), writeDiffActionSymbol(element.Action, elementOpts), element.RenderHuman(indent+1, elementOpts)))
    69  	}
    70  
    71  	if unchangedElements > 0 {
    72  		buf.WriteString(fmt.Sprintf("%s%s%s\n", formatIndent(indent+1), writeDiffActionSymbol(plans.NoOp, opts), unchanged("element", unchangedElements, opts)))
    73  	}
    74  
    75  	buf.WriteString(fmt.Sprintf("%s%s]%s", formatIndent(indent), writeDiffActionSymbol(plans.NoOp, opts), nullSuffix(diff.Action, opts)))
    76  	return buf.String()
    77  }