Files
opentf/internal/command/arguments/show.go
baa-ableton 3bdd0073a5 command: tofu show -config (#2820)
Signed-off-by: Babur Ayanlar <babur.ayanlar@ableton.com>
2025-06-02 10:15:46 -07:00

165 lines
4.8 KiB
Go

// Copyright (c) The OpenTofu Authors
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2023 HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package arguments
import (
"github.com/opentofu/opentofu/internal/tfdiags"
)
// Show represents the command-line arguments for the show command.
type Show struct {
// TargetType and TargetArg together describe the object that was
// requested to be shown.
//
// The meaning of TargetArg varies depending on TargetType. Refer to
// the documentation for each [ShowTargetType] constant for details.
TargetType ShowTargetType
TargetArg string
// ViewType specifies which output format to use: human, JSON, or "raw".
ViewType ViewType
Vars *Vars
// ShowSensitive is used to display the value of variables marked as sensitive.
ShowSensitive bool
}
// ShowTargetType represents the type of object that is requested to be
// shown by the "tofu show" command.
type ShowTargetType int
//go:generate go run golang.org/x/tools/cmd/stringer -type=ShowTargetType
const (
// ShowUnknownType is the zero value of [ShowTargetType], and represents
// that the target type is ambiguous and so must be inferred by the
// caller based on the [Show.TargetArg] value.
ShowUnknownType ShowTargetType = iota
// ShowState represents a request to show the latest state snapshot.
//
// This target type does not use [Show.TargetArg].
ShowState
// ShowPlan represents a request to show a plan loaded from a saved
// plan file.
//
// For this target type, [Show.TargetArg] is the plan file to load.
ShowPlan
// ShowConfig represents a request to show the current configuration.
//
// This target type does not use [Show.TargetArg].
ShowConfig
)
// ParseShow processes CLI arguments, returning a Show value and errors.
// If errors are encountered, a Show value is still returned representing
// the best effort interpretation of the arguments.
func ParseShow(args []string) (*Show, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
show := &Show{
Vars: &Vars{},
}
var jsonOutput bool
var stateTarget bool
var planTarget string
var configTarget bool
cmdFlags := extendedFlagSet("show", nil, nil, show.Vars)
cmdFlags.BoolVar(&jsonOutput, "json", false, "json")
cmdFlags.BoolVar(&show.ShowSensitive, "show-sensitive", false, "displays sensitive values")
cmdFlags.BoolVar(&stateTarget, "state", false, "show the latest state snapshot")
cmdFlags.StringVar(&planTarget, "plan", "", "show the plan from a saved plan file")
cmdFlags.BoolVar(&configTarget, "config", false, "show the current configuration")
if err := cmdFlags.Parse(args); err != nil {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Failed to parse command-line options",
err.Error(),
))
}
// If -config is specified, -json is required
if configTarget && !jsonOutput {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"JSON output required for configuration",
"The -config option requires -json to be specified.",
))
return show, diags
}
switch {
case jsonOutput:
show.ViewType = ViewJSON
default:
show.ViewType = ViewHuman
}
if planTarget == "" && !stateTarget && !configTarget {
// If none of the target type options was provided then we're
// in the legacy mode where the target type is implied by
// the number of arguments.
args = cmdFlags.Args()
switch len(args) {
case 0:
show.TargetType = ShowState
show.TargetArg = ""
case 1:
// This case is ambiguous: the argument could be either
// a saved plan file or a local state snapshot such as
// the output from "tofu state pull". The caller will need
// to probe TargetArg to decide which it is.
show.TargetType = ShowUnknownType
show.TargetArg = args[0]
default:
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Too many command line arguments",
"Expected at most one positional argument for the legacy positional argument mode.",
))
}
return show, diags
}
// The following handles the modern mode where the target type is
// chosen based on which target type option was used.
if len(cmdFlags.Args()) != 0 {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Unexpected command line arguments",
"This command does not expect any positional arguments when using a target-selection option.",
))
return show, diags
}
targetTypes := 0
if stateTarget {
targetTypes++
show.TargetType = ShowState
show.TargetArg = ""
}
if planTarget != "" {
targetTypes++
show.TargetType = ShowPlan
show.TargetArg = planTarget
}
if configTarget {
targetTypes++
show.TargetType = ShowConfig
show.TargetArg = ""
}
if targetTypes != 1 {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Conflicting object types to show",
"The -state, -plan=FILENAME, and -config options are mutually-exclusive, to specify which kind of object to show.",
))
}
return show, diags
}