github.com/opentofu/opentofu@v1.7.1/internal/command/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 command
     7  
     8  import (
     9  	"fmt"
    10  	"strings"
    11  
    12  	"github.com/opentofu/opentofu/internal/command/arguments"
    13  	"github.com/opentofu/opentofu/internal/command/views"
    14  	"github.com/opentofu/opentofu/internal/encryption"
    15  	"github.com/opentofu/opentofu/internal/states"
    16  	"github.com/opentofu/opentofu/internal/tfdiags"
    17  )
    18  
    19  // OutputCommand is a Command implementation that reads an output
    20  // from a OpenTofu state and prints it.
    21  type OutputCommand struct {
    22  	Meta
    23  }
    24  
    25  func (c *OutputCommand) Run(rawArgs []string) int {
    26  	// Parse and apply global view arguments
    27  	common, rawArgs := arguments.ParseView(rawArgs)
    28  	c.View.Configure(common)
    29  
    30  	// Parse and validate flags
    31  	args, diags := arguments.ParseOutput(rawArgs)
    32  	if diags.HasErrors() {
    33  		c.View.Diagnostics(diags)
    34  		c.View.HelpPrompt("output")
    35  		return 1
    36  	}
    37  
    38  	view := views.NewOutput(args.ViewType, c.View)
    39  
    40  	// Load the encryption configuration
    41  	enc, encDiags := c.Encryption()
    42  	diags = diags.Append(encDiags)
    43  	if encDiags.HasErrors() {
    44  		c.View.Diagnostics(diags)
    45  		return 1
    46  	}
    47  
    48  	// Fetch data from state
    49  	outputs, diags := c.Outputs(args.StatePath, enc)
    50  	if diags.HasErrors() {
    51  		view.Diagnostics(diags)
    52  		return 1
    53  	}
    54  
    55  	// Render the view
    56  	viewDiags := view.Output(args.Name, outputs)
    57  	diags = diags.Append(viewDiags)
    58  
    59  	view.Diagnostics(diags)
    60  
    61  	if diags.HasErrors() {
    62  		return 1
    63  	}
    64  
    65  	return 0
    66  }
    67  
    68  func (c *OutputCommand) Outputs(statePath string, enc encryption.Encryption) (map[string]*states.OutputValue, tfdiags.Diagnostics) {
    69  	var diags tfdiags.Diagnostics
    70  
    71  	// Allow state path override
    72  	if statePath != "" {
    73  		c.Meta.statePath = statePath
    74  	}
    75  
    76  	// Load the backend
    77  	b, backendDiags := c.Backend(nil, enc.State())
    78  	diags = diags.Append(backendDiags)
    79  	if diags.HasErrors() {
    80  		return nil, diags
    81  	}
    82  
    83  	// This is a read-only command
    84  	c.ignoreRemoteVersionConflict(b)
    85  
    86  	env, err := c.Workspace()
    87  	if err != nil {
    88  		diags = diags.Append(fmt.Errorf("Error selecting workspace: %w", err))
    89  		return nil, diags
    90  	}
    91  
    92  	// Get the state
    93  	stateStore, err := b.StateMgr(env)
    94  	if err != nil {
    95  		diags = diags.Append(fmt.Errorf("Failed to load state: %w", err))
    96  		return nil, diags
    97  	}
    98  
    99  	output, err := stateStore.GetRootOutputValues()
   100  	if err != nil {
   101  		return nil, diags.Append(err)
   102  	}
   103  
   104  	return output, diags
   105  }
   106  
   107  func (c *OutputCommand) Help() string {
   108  	helpText := `
   109  Usage: tofu [global options] output [options] [NAME]
   110  
   111    Reads an output variable from a OpenTofu state file and prints
   112    the value. With no additional arguments, output will display all
   113    the outputs for the root module.  If NAME is not specified, all
   114    outputs are printed.
   115  
   116  Options:
   117  
   118    -state=path      Path to the state file to read. Defaults to
   119                     "terraform.tfstate". Ignored when remote 
   120                     state is used.
   121  
   122    -no-color        If specified, output won't contain any color.
   123  
   124    -json            If specified, machine readable output will be
   125                     printed in JSON format.
   126  
   127    -raw             For value types that can be automatically
   128                     converted to a string, will print the raw
   129                     string directly, rather than a human-oriented
   130                     representation of the value.
   131  `
   132  	return strings.TrimSpace(helpText)
   133  }
   134  
   135  func (c *OutputCommand) Synopsis() string {
   136  	return "Show output values from your root module"
   137  }