Make Terraform reject empty strings as invalid workspace names (#37267)

* Add tests defining what are valid workspace names

* Update workspace name validation to mark an empty string as not valid

* Add change file

* Add command-level test showing the "" workspace cannot be created or selected

* Update invalid name error text to include empty string as invalid.
pull/37275/head
Sarah French 8 months ago committed by GitHub
parent 8a498df05d
commit 9212a2efdd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
kind: BUG FIXES
body: 'workspace: Updated validation to reject workspaces named ""'
time: 2025-06-23T12:55:14.226554+01:00
custom:
Issue: "37267"

@ -45,6 +45,9 @@ func (c *WorkspaceCommand) Synopsis() string {
// 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 {
if name == "" {
return false
}
return name == url.PathEscape(name)
}
@ -100,7 +103,7 @@ to another workspace and try again.
envInvalidName = `
The workspace name %q is not allowed. The name must contain only URL safe
characters, and no path separators.
characters, contain no path separators, and not be an empty string.
`
envIsOverriddenNote = `

@ -62,6 +62,49 @@ func TestWorkspace_createAndChange(t *testing.T) {
}
func TestWorkspace_cannotCreateOrSelectEmptyStringWorkspace(t *testing.T) {
// Create a temporary working directory that is empty
td := t.TempDir()
os.MkdirAll(td, 0755)
defer testChdir(t, td)()
newCmd := &WorkspaceNewCommand{}
current, _ := newCmd.Workspace()
if current != backend.DefaultStateName {
t.Fatal("current workspace should be 'default'")
}
args := []string{""}
ui := cli.NewMockUi()
view, _ := testView(t)
newCmd.Meta = Meta{Ui: ui, View: view}
if code := newCmd.Run(args); code != 1 {
t.Fatalf("expected failure when trying to create the \"\" workspace.\noutput: %s", ui.OutputWriter)
}
gotStderr := ui.ErrorWriter.String()
if want, got := `The workspace name "" is not allowed`, gotStderr; !strings.Contains(got, want) {
t.Errorf("missing expected error message\nwant substring: %s\ngot:\n%s", want, got)
}
ui = cli.NewMockUi()
selectCmd := &WorkspaceSelectCommand{
Meta: Meta{
Ui: ui,
View: view,
},
}
if code := selectCmd.Run(args); code != 1 {
t.Fatalf("expected failure when trying to select the the \"\" workspace.\noutput: %s", ui.OutputWriter)
}
gotStderr = ui.ErrorWriter.String()
if want, got := `The workspace name "" is not allowed`, gotStderr; !strings.Contains(got, want) {
t.Errorf("missing expected error message\nwant substring: %s\ngot:\n%s", want, got)
}
}
// Create some workspaces and test the list output.
// This also ensures we switch to the correct env after each call
func TestWorkspace_createAndList(t *testing.T) {
@ -476,3 +519,36 @@ func TestWorkspace_selectWithOrCreate(t *testing.T) {
}
}
func TestValidWorkspaceName(t *testing.T) {
cases := map[string]struct {
input string
valid bool
}{
"foobar": {
input: "foobar",
valid: true,
},
"valid symbols": {
input: "-._~@:",
valid: true,
},
"includes space": {
input: "two words",
valid: false,
},
"empty string": {
input: "",
valid: false,
},
}
for tn, tc := range cases {
t.Run(tn, func(t *testing.T) {
valid := validWorkspaceName(tc.input)
if valid != tc.valid {
t.Fatalf("unexpected output when processing input %q. Wanted %v got %v", tc.input, tc.valid, valid)
}
})
}
}

Loading…
Cancel
Save