// Copyright (c) The OpenTofu Authors // SPDX-License-Identifier: MPL-2.0 // Copyright (c) 2023 HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package command import ( "net/url" "strings" "github.com/mitchellh/cli" "github.com/opentofu/opentofu/internal/command/arguments" "github.com/opentofu/opentofu/internal/command/views" ) // WorkspaceCommand is a Command Implementation that manipulates workspaces, // which allow multiple distinct states and variables from a single config. type WorkspaceCommand struct { Meta LegacyName bool } func (c *WorkspaceCommand) Run(rawArgs []string) int { common, rawArgs := arguments.ParseView(rawArgs) c.View.Configure(common) // Because the legacy UI was using println to show diagnostics and the new view is using, by default, print, // in order to keep functional parity, we setup the view to add a new line after each diagnostic. c.View.DiagsWithNewline() // Propagate -no-color for legacy use of Ui. The remote backend and // cloud package use this; it should be removed when/if they are // migrated to views. c.Meta.color = !common.NoColor c.Meta.Color = c.Meta.color // Parse and validate flags args, closer, diags := arguments.ParseWorkspace(rawArgs) defer closer() // Instantiate the view, even if there are flag errors, so that we render // diagnostics according to the desired view view := views.NewWorkspace(args.ViewOptions, c.View) // ... and initialise the Meta.Ui to wrap Meta.View into a new implementation // that is able to print by using View abstraction and use the Meta.Ui // to ask for the user input. c.Meta.configureUiFromView(args.ViewOptions) if diags.HasErrors() { view.Diagnostics(diags) return cli.RunResultHelp } view.WarnWhenUsedAsEnvCmd(c.LegacyName) return cli.RunResultHelp } func (c *WorkspaceCommand) Help() string { helpText := ` Usage: tofu [global options] workspace new, list, show, select and delete OpenTofu workspaces. ` return strings.TrimSpace(helpText) } func (c *WorkspaceCommand) Synopsis() string { return "Workspace management" } // validWorkspaceName returns true is this name is valid to use as a workspace name. // Since most named states are accessed via a filesystem path or URL, check if // escaping the name would be required. func validWorkspaceName(name string) bool { return name == url.PathEscape(name) }