2023-05-02 11:33:06 -04:00
// Copyright IBM Corp. 2014, 2026
2023-08-10 18:43:27 -04:00
// SPDX-License-Identifier: BUSL-1.1
2023-05-02 11:33:06 -04:00
2017-05-30 18:06:13 -04:00
package command
import (
2026-01-28 10:15:04 -05:00
"fmt"
2017-05-30 18:06:13 -04:00
"net/url"
"strings"
2023-12-20 06:04:10 -05:00
"github.com/hashicorp/cli"
2026-01-28 10:15:04 -05:00
"github.com/hashicorp/terraform/internal/backend"
"github.com/hashicorp/terraform/internal/tfdiags"
2017-05-30 18:06:13 -04:00
)
// 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 ( args [ ] string ) int {
2022-06-24 19:57:44 -04:00
c . Meta . process ( args )
envCommandShowWarning ( c . Ui , c . LegacyName )
cmdFlags := c . Meta . extendedFlagSet ( "workspace" )
cmdFlags . Usage = func ( ) { c . Ui . Error ( c . Help ( ) ) }
2022-06-24 19:33:11 -04:00
return cli . RunResultHelp
2017-05-30 18:06:13 -04:00
}
func ( c * WorkspaceCommand ) Help ( ) string {
helpText := `
2021-02-22 09:25:56 -05:00
Usage : terraform [ global options ] workspace
2017-05-30 18:06:13 -04:00
2019-11-03 12:30:03 -05:00
new , list , show , select and delete Terraform workspaces .
2017-05-30 18:06:13 -04:00
`
return strings . TrimSpace ( helpText )
}
func ( c * WorkspaceCommand ) Synopsis ( ) string {
return "Workspace management"
}
2017-05-30 20:13:43 -04:00
// validWorkspaceName returns true is this name is valid to use as a workspace name.
2017-05-30 18:06:13 -04:00
// Since most named states are accessed via a filesystem path or URL, check if
// escaping the name would be required.
2017-05-30 20:13:43 -04:00
func validWorkspaceName ( name string ) bool {
2025-06-26 07:26:58 -04:00
if name == "" {
return false
}
2017-05-30 18:06:13 -04:00
return name == url . PathEscape ( name )
}
func envCommandShowWarning ( ui cli . Ui , show bool ) {
if ! show {
return
}
ui . Warn ( ` Warning : the "terraform env" family of commands is deprecated .
"Workspace" is now the preferred term for what earlier Terraform versions
called "environment" , to reduce ambiguity caused by the latter term colliding
with other concepts .
The "terraform workspace" commands should be used instead . "terraform env"
will be removed in a future Terraform version .
` )
}
const (
envExists = ` Workspace %q already exists `
envDoesNotExist = `
Workspace % q doesn ' t exist .
2022-08-31 13:36:31 -04:00
You can create this workspace with the "new" subcommand
2022-08-31 15:13:15 -04:00
or include the "-or-create" flag with the "select" subcommand . `
2017-05-30 18:06:13 -04:00
envChanged = ` [reset][green]Switched to workspace %q. `
envCreated = `
[ reset ] [ green ] [ bold ] Created and switched to workspace % q ! [ reset ] [ green ]
You ' re now on a new , empty workspace . Workspaces isolate their state ,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration .
`
envDeleted = ` [reset][green]Deleted workspace %q! `
envWarnNotEmpty = ` [ reset ] [ yellow ] WARNING : % q was non - empty .
The resources managed by the deleted workspace may still exist ,
but are no longer manageable by Terraform since the state has
been deleted .
`
envDelCurrent = `
Workspace % [ 1 ] q is your active workspace .
You cannot delete the currently active workspace . Please switch
to another workspace and try again .
`
envInvalidName = `
The workspace name % q is not allowed . The name must contain only URL safe
2025-06-26 07:26:58 -04:00
characters , contain no path separators , and not be an empty string .
2017-05-30 18:06:13 -04:00
`
envIsOverriddenNote = `
The active workspace is being overridden using the TF_WORKSPACE environment
variable .
`
envIsOverriddenSelectError = `
The selected workspace is currently overridden using the TF_WORKSPACE
environment variable .
To select a new workspace , either update this environment variable or unset
it and then run this command again .
`
envIsOverriddenNewError = `
The workspace is currently overridden using the TF_WORKSPACE environment
variable . You cannot create a new workspace when using this setting .
To create a new workspace , either unset this environment variable or update it
to match the workspace name you are trying to create , and then run this command
again .
`
)
2026-01-28 10:15:04 -05:00
// warnNoEnvsExistDiag creates a warning diagnostic saying that no workspaces exist,
// and provides guidance about how to create the workspace based on whether the workspace is
// custom or not.
func warnNoEnvsExistDiag ( currentWorkspace string ) tfdiags . Diagnostic {
summary := "Terraform cannot find any existing workspaces."
if currentWorkspace == backend . DefaultStateName {
// Recommended actions for the user includes running `init` if they're using the default workspace.
msg := fmt . Sprintf (
"The %q workspace is selected in your working directory. You can create this workspace by running \"terraform init\", by using the \"terraform workspace new\" subcommand or by including the \"-or-create\" flag with the \"terraform workspace select\" subcommand." ,
currentWorkspace ,
)
return tfdiags . Sourceless (
tfdiags . Warning ,
summary ,
msg ,
)
}
msg := fmt . Sprintf (
"The %q workspace is selected in your working directory. You can create this workspace by using the \"terraform workspace new\" subcommand or including the \"-or-create\" flag with the \"terraform workspace select\" subcommand." ,
currentWorkspace ,
)
return tfdiags . Sourceless (
tfdiags . Warning ,
summary ,
msg ,
)
}