github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/jsonformat/computed/renderers/block.go (about)

     1  package renderers
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"sort"
     7  
     8  	"github.com/hashicorp/terraform/internal/command/jsonformat/computed"
     9  
    10  	"github.com/hashicorp/terraform/internal/plans"
    11  )
    12  
    13  var (
    14  	_ computed.DiffRenderer = (*blockRenderer)(nil)
    15  
    16  	importantAttributes = []string{
    17  		"id",
    18  		"name",
    19  		"tags",
    20  	}
    21  )
    22  
    23  func importantAttribute(attr string) bool {
    24  	for _, attribute := range importantAttributes {
    25  		if attribute == attr {
    26  			return true
    27  		}
    28  	}
    29  	return false
    30  }
    31  
    32  func Block(attributes map[string]computed.Diff, blocks Blocks) computed.DiffRenderer {
    33  	return &blockRenderer{
    34  		attributes: attributes,
    35  		blocks:     blocks,
    36  	}
    37  }
    38  
    39  type blockRenderer struct {
    40  	NoWarningsRenderer
    41  
    42  	attributes map[string]computed.Diff
    43  	blocks     Blocks
    44  }
    45  
    46  func (renderer blockRenderer) RenderHuman(diff computed.Diff, indent int, opts computed.RenderHumanOpts) string {
    47  	if len(renderer.attributes) == 0 && len(renderer.blocks.GetAllKeys()) == 0 {
    48  		return fmt.Sprintf("{}%s", forcesReplacement(diff.Replace, opts))
    49  	}
    50  
    51  	unchangedAttributes := 0
    52  	unchangedBlocks := 0
    53  
    54  	maximumAttributeKeyLen := 0
    55  	var attributeKeys []string
    56  	escapedAttributeKeys := make(map[string]string)
    57  	for key := range renderer.attributes {
    58  		attributeKeys = append(attributeKeys, key)
    59  		escapedKey := EnsureValidAttributeName(key)
    60  		escapedAttributeKeys[key] = escapedKey
    61  		if maximumAttributeKeyLen < len(escapedKey) {
    62  			maximumAttributeKeyLen = len(escapedKey)
    63  		}
    64  	}
    65  	sort.Strings(attributeKeys)
    66  
    67  	importantAttributeOpts := opts.Clone()
    68  	importantAttributeOpts.ShowUnchangedChildren = true
    69  
    70  	attributeOpts := opts.Clone()
    71  
    72  	var buf bytes.Buffer
    73  	buf.WriteString(fmt.Sprintf("{%s\n", forcesReplacement(diff.Replace, opts)))
    74  	for _, key := range attributeKeys {
    75  		attribute := renderer.attributes[key]
    76  		if importantAttribute(key) {
    77  
    78  			// Always display the important attributes.
    79  			for _, warning := range attribute.WarningsHuman(indent+1, importantAttributeOpts) {
    80  				buf.WriteString(fmt.Sprintf("%s%s\n", formatIndent(indent+1), warning))
    81  			}
    82  			buf.WriteString(fmt.Sprintf("%s%s%-*s = %s\n", formatIndent(indent+1), writeDiffActionSymbol(attribute.Action, importantAttributeOpts), maximumAttributeKeyLen, key, attribute.RenderHuman(indent+1, importantAttributeOpts)))
    83  			continue
    84  		}
    85  		if attribute.Action == plans.NoOp && !opts.ShowUnchangedChildren {
    86  			unchangedAttributes++
    87  			continue
    88  		}
    89  
    90  		for _, warning := range attribute.WarningsHuman(indent+1, opts) {
    91  			buf.WriteString(fmt.Sprintf("%s%s\n", formatIndent(indent+1), warning))
    92  		}
    93  		buf.WriteString(fmt.Sprintf("%s%s%-*s = %s\n", formatIndent(indent+1), writeDiffActionSymbol(attribute.Action, attributeOpts), maximumAttributeKeyLen, escapedAttributeKeys[key], attribute.RenderHuman(indent+1, attributeOpts)))
    94  	}
    95  
    96  	if unchangedAttributes > 0 {
    97  		buf.WriteString(fmt.Sprintf("%s%s%s\n", formatIndent(indent+1), writeDiffActionSymbol(plans.NoOp, opts), unchanged("attribute", unchangedAttributes, opts)))
    98  	}
    99  
   100  	blockKeys := renderer.blocks.GetAllKeys()
   101  	for _, key := range blockKeys {
   102  
   103  		foundChangedBlock := false
   104  		renderBlock := func(diff computed.Diff, mapKey string, opts computed.RenderHumanOpts) {
   105  
   106  			creatingSensitiveValue := diff.Action == plans.Create && renderer.blocks.AfterSensitiveBlocks[key]
   107  			deletingSensitiveValue := diff.Action == plans.Delete && renderer.blocks.BeforeSensitiveBlocks[key]
   108  			modifyingSensitiveValue := (diff.Action == plans.Update || diff.Action == plans.NoOp) && (renderer.blocks.AfterSensitiveBlocks[key] || renderer.blocks.BeforeSensitiveBlocks[key])
   109  
   110  			if creatingSensitiveValue || deletingSensitiveValue || modifyingSensitiveValue {
   111  				// Intercept the renderer here if the sensitive data was set
   112  				// across all the blocks instead of individually.
   113  				action := diff.Action
   114  				if diff.Action == plans.NoOp && renderer.blocks.BeforeSensitiveBlocks[key] != renderer.blocks.AfterSensitiveBlocks[key] {
   115  					action = plans.Update
   116  				}
   117  
   118  				diff = computed.NewDiff(SensitiveBlock(diff, renderer.blocks.BeforeSensitiveBlocks[key], renderer.blocks.AfterSensitiveBlocks[key]), action, diff.Replace)
   119  			}
   120  
   121  			if diff.Action == plans.NoOp && !opts.ShowUnchangedChildren {
   122  				unchangedBlocks++
   123  				return
   124  			}
   125  
   126  			if !foundChangedBlock && len(renderer.attributes) > 0 {
   127  				// We always want to put an extra new line between the
   128  				// attributes and blocks, and between groups of blocks.
   129  				buf.WriteString("\n")
   130  				foundChangedBlock = true
   131  			}
   132  
   133  			// If the force replacement metadata was set for every entry in the
   134  			// block we need to override that here. Our child blocks will only
   135  			// know about the replace function if it was set on them
   136  			// specifically, and not if it was set for all the blocks.
   137  			blockOpts := opts.Clone()
   138  			blockOpts.OverrideForcesReplacement = renderer.blocks.ReplaceBlocks[key]
   139  
   140  			for _, warning := range diff.WarningsHuman(indent+1, blockOpts) {
   141  				buf.WriteString(fmt.Sprintf("%s%s\n", formatIndent(indent+1), warning))
   142  			}
   143  			buf.WriteString(fmt.Sprintf("%s%s%s%s %s\n", formatIndent(indent+1), writeDiffActionSymbol(diff.Action, blockOpts), EnsureValidAttributeName(key), mapKey, diff.RenderHuman(indent+1, blockOpts)))
   144  
   145  		}
   146  
   147  		switch {
   148  		case renderer.blocks.IsSingleBlock(key):
   149  			renderBlock(renderer.blocks.SingleBlocks[key], "", opts)
   150  		case renderer.blocks.IsMapBlock(key):
   151  			var keys []string
   152  			for key := range renderer.blocks.MapBlocks[key] {
   153  				keys = append(keys, key)
   154  			}
   155  			sort.Strings(keys)
   156  
   157  			for _, innerKey := range keys {
   158  				renderBlock(renderer.blocks.MapBlocks[key][innerKey], fmt.Sprintf(" %q", innerKey), opts)
   159  			}
   160  		case renderer.blocks.IsSetBlock(key):
   161  
   162  			setOpts := opts.Clone()
   163  			setOpts.OverrideForcesReplacement = diff.Replace
   164  
   165  			for _, block := range renderer.blocks.SetBlocks[key] {
   166  				renderBlock(block, "", opts)
   167  			}
   168  		case renderer.blocks.IsListBlock(key):
   169  			for _, block := range renderer.blocks.ListBlocks[key] {
   170  				renderBlock(block, "", opts)
   171  			}
   172  		}
   173  	}
   174  
   175  	if unchangedBlocks > 0 {
   176  		buf.WriteString(fmt.Sprintf("\n%s%s%s\n", formatIndent(indent+1), writeDiffActionSymbol(plans.NoOp, opts), unchanged("block", unchangedBlocks, opts)))
   177  	}
   178  
   179  	buf.WriteString(fmt.Sprintf("%s%s}", formatIndent(indent), writeDiffActionSymbol(plans.NoOp, opts)))
   180  	return buf.String()
   181  }