diff --git a/tfexec/workspace_list.go b/tfexec/workspace_list.go index b4517310..8d767b3c 100644 --- a/tfexec/workspace_list.go +++ b/tfexec/workspace_list.go @@ -5,6 +5,7 @@ package tfexec import ( "context" + "net/url" "os/exec" "strings" ) @@ -72,12 +73,28 @@ func parseWorkspaceList(stdout string) ([]string, string) { for _, line := range lines { line = strings.TrimSpace(line) if line == "" { + // results from successive newlines in stdout string; ignore continue } + if strings.HasPrefix(line, currentWorkspacePrefix) { line = strings.TrimPrefix(line, currentWorkspacePrefix) current = line } + + if line != url.PathEscape(line) { + // If a line isn't URL-escaped then it's not a valid workspace name. + // If we're encountering a processed line string that isn't a valid workspace name it's + // almost certainly due to a warning being sent to stdout after the workspace commands + // were migrated from using cli.Ui to view.View, which causes warnings to begin being sent to + // stdout instead of stderr. + // See: https://github.com/hashicorp/terraform/blob/9fb1177c3566c247c72e6c36ca219463c4b6be2b/internal/command/workspace_command.go#L44-L52 + // + // tl;dr this line isn't a workspace name, so lets skip and see if there is a list of + // workspaces later in the output, under any warning text. + continue + } + workspaces = append(workspaces, line) } diff --git a/tfexec/workspace_list_test.go b/tfexec/workspace_list_test.go index 72d305e5..4e2012d4 100644 --- a/tfexec/workspace_list_test.go +++ b/tfexec/workspace_list_test.go @@ -94,6 +94,36 @@ func TestParseWorkspaceList(t *testing.T) { "foo", " default\r\n* foo\r\n\r\n", }, + // warning about no workspaces being present is set to stdout and + // should not be parsed as a list. + { + []string{}, + "", + ` +Warning: Terraform cannot find any existing workspaces. + +The "default" 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. + +`, + }, + // warning present alongside a list of workspaces. + { + []string{"default", "foo", "bar"}, + "foo", + ` +Warning: This warning is part of a test! + +This warning doesn't exist in Terraform core, but we're seeing if it can be +ignored while parsing the list below: + + default +* foo + bar +`, + }, } { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { actualList, actualCurrent := parseWorkspaceList(c.stdout)