github.com/opentofu/opentofu@v1.7.1/internal/command/views/json/output.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 json
     7  
     8  import (
     9  	"encoding/json"
    10  	"fmt"
    11  
    12  	ctyjson "github.com/zclconf/go-cty/cty/json"
    13  
    14  	"github.com/opentofu/opentofu/internal/plans"
    15  	"github.com/opentofu/opentofu/internal/states"
    16  	"github.com/opentofu/opentofu/internal/tfdiags"
    17  )
    18  
    19  type Output struct {
    20  	Sensitive bool            `json:"sensitive"`
    21  	Type      json.RawMessage `json:"type,omitempty"`
    22  	Value     json.RawMessage `json:"value,omitempty"`
    23  	Action    ChangeAction    `json:"action,omitempty"`
    24  }
    25  
    26  type Outputs map[string]Output
    27  
    28  func OutputsFromMap(outputValues map[string]*states.OutputValue) (Outputs, tfdiags.Diagnostics) {
    29  	var diags tfdiags.Diagnostics
    30  
    31  	outputs := make(map[string]Output, len(outputValues))
    32  
    33  	for name, ov := range outputValues {
    34  		unmarked, _ := ov.Value.UnmarkDeep()
    35  		value, err := ctyjson.Marshal(unmarked, unmarked.Type())
    36  		if err != nil {
    37  			diags = diags.Append(tfdiags.Sourceless(
    38  				tfdiags.Error,
    39  				fmt.Sprintf("Error serializing output %q", name),
    40  				fmt.Sprintf("Error: %s", err),
    41  			))
    42  			return nil, diags
    43  		}
    44  		valueType, err := ctyjson.MarshalType(unmarked.Type())
    45  		if err != nil {
    46  			diags = diags.Append(err)
    47  			return nil, diags
    48  		}
    49  
    50  		var redactedValue json.RawMessage
    51  		if !ov.Sensitive {
    52  			redactedValue = json.RawMessage(value)
    53  		}
    54  
    55  		outputs[name] = Output{
    56  			Sensitive: ov.Sensitive,
    57  			Type:      json.RawMessage(valueType),
    58  			Value:     redactedValue,
    59  		}
    60  	}
    61  
    62  	return outputs, nil
    63  }
    64  
    65  func OutputsFromChanges(changes []*plans.OutputChangeSrc) Outputs {
    66  	outputs := make(map[string]Output, len(changes))
    67  
    68  	for _, change := range changes {
    69  		outputs[change.Addr.OutputValue.Name] = Output{
    70  			Sensitive: change.Sensitive,
    71  			Action:    changeAction(change.Action),
    72  		}
    73  	}
    74  
    75  	return outputs
    76  }
    77  
    78  func (o Outputs) String() string {
    79  	return fmt.Sprintf("Outputs: %d", len(o))
    80  }