diff --git a/software/workspace/workspace.go b/software/workspace/workspace.go index dd522c3ce..8bdb9735f 100644 --- a/software/workspace/workspace.go +++ b/software/workspace/workspace.go @@ -19,6 +19,12 @@ type workspacePaginationOptions struct { userSelection int } +type workspaceSelection struct { + id string + quit bool + err error +} + const ( defaultWorkspacePaginationOptions = "f. first p. previous n. next q. quit\n> " workspacePaginationWithoutNextOptions = "f. first p. previous q. quit\n> " @@ -156,7 +162,7 @@ var workspacesPromptPaginatedOption = func(pageSize, pageNumber, totalRecord int } } -func getWorkspaceSelection(pageSize, pageNumber int, client houston.ClientInterface, out io.Writer) (string, error) { +func getWorkspaceSelection(pageSize, pageNumber int, client houston.ClientInterface, out io.Writer) workspaceSelection { tab := newTableOut() tab.GetUserInput = true var ws []houston.Workspace @@ -168,12 +174,12 @@ func getWorkspaceSelection(pageSize, pageNumber int, client houston.ClientInterf ws, err = client.ListWorkspaces() } if err != nil { - return "", err + return workspaceSelection{id: "", quit: false, err: err} } c, err := config.GetCurrentContext() if err != nil { - return "", err + return workspaceSelection{id: "", quit: false, err: err} } for i := range ws { @@ -193,7 +199,7 @@ func getWorkspaceSelection(pageSize, pageNumber int, client houston.ClientInterf tabPrintErr := tab.PrintWithPageNumber(pageNumber*pageSize, out) if tabPrintErr != nil { - return "", fmt.Errorf("unable to print with page number: %w", tabPrintErr) + return workspaceSelection{id: "", quit: false, err: fmt.Errorf("unable to print with page number: %w", tabPrintErr)} } totalRecords := len(ws) @@ -201,9 +207,9 @@ func getWorkspaceSelection(pageSize, pageNumber int, client houston.ClientInterf selectedOption := workspacesPromptPaginatedOption(pageSize, pageNumber, totalRecords) if selectedOption.quit { if selectedOption.userSelection == 0 { - return "", nil + return workspaceSelection{id: "", quit: true, err: nil} } - return ws[selectedOption.userSelection-1].ID, nil + return workspaceSelection{id: ws[selectedOption.userSelection-1].ID, quit: false, err: nil} } return getWorkspaceSelection(selectedOption.pageSize, selectedOption.pageNumber, client, out) } @@ -211,21 +217,24 @@ func getWorkspaceSelection(pageSize, pageNumber int, client houston.ClientInterf in := input.Text("\n> ") i, err := strconv.ParseInt(in, 10, 64) //nolint:gomnd if err != nil { - return "", fmt.Errorf("cannot parse %s to int: %w", in, err) + return workspaceSelection{id: "", quit: false, err: fmt.Errorf("cannot parse %s to int: %w", in, err)} } - - return ws[i-1].ID, nil + return workspaceSelection{id: ws[i-1].ID, quit: false, err: nil} } // Switch switches workspaces func Switch(id string, pageSize int, client houston.ClientInterface, out io.Writer) error { if id == "" { - _id, err := getWorkspaceSelection(pageSize, 0, client, out) - if err != nil { - return err + workspaceSelection := getWorkspaceSelection(pageSize, 0, client, out) + + if workspaceSelection.quit { + return nil + } + if workspaceSelection.err != nil { + return workspaceSelection.err } - id = _id + id = workspaceSelection.id } // validate workspace _, err := client.GetWorkspace(id) diff --git a/software/workspace/workspace_test.go b/software/workspace/workspace_test.go index 2df6b39c7..1611959e1 100644 --- a/software/workspace/workspace_test.go +++ b/software/workspace/workspace_test.go @@ -215,8 +215,8 @@ func TestGetWorkspaceSelectionError(t *testing.T) { api.On("ListWorkspaces").Return(nil, errMock) buf := new(bytes.Buffer) - _, err := getWorkspaceSelection(0, 0, api, buf) - assert.EqualError(t, err, errMock.Error()) + workspaceSelection := getWorkspaceSelection(0, 0, api, buf) + assert.EqualError(t, workspaceSelection.err, errMock.Error()) api.AssertExpectations(t) } @@ -252,6 +252,67 @@ contexts: api.AssertExpectations(t) } +func TestSwitchWithQuitSelection(t *testing.T) { + // prepare test config and init it + configRaw := []byte(`cloud: + api: + port: "443" + protocol: https + ws_protocol: wss +context: localhost +contexts: + localhost: + domain: localhost + token: token + last_used_workspace: ck05r3bor07h40d02y2hw4n4v + workspace: +`) + fs := afero.NewMemMapFs() + _ = afero.WriteFile(fs, config.HomeConfigFile, configRaw, 0o777) + config.InitConfig(fs) + + api := new(mocks.ClientInterface) + api.On("PaginatedListWorkspaces", 10, 0).Return(mockWorkspaceList, nil) + + defer testUtil.MockUserInput(t, "q")() + + buf := new(bytes.Buffer) + err := Switch("", 10, api, buf) + assert.NoError(t, err) + api.AssertExpectations(t) +} + +func TestSwitchWithError(t *testing.T) { + // prepare test config and init it + configRaw := []byte(`cloud: + api: + port: "443" + protocol: https + ws_protocol: wss +context: localhost +contexts: + localhost: + domain: localhost + token: token + last_used_workspace: ck05r3bor07h40d02y2hw4n4v + workspace: +`) + fs := afero.NewMemMapFs() + _ = afero.WriteFile(fs, config.HomeConfigFile, configRaw, 0o777) + config.InitConfig(fs) + + api := new(mocks.ClientInterface) + api.On("ListWorkspaces").Return(mockWorkspaceList, nil) + + defer testUtil.MockUserInput(t, "y")() + + buf := new(bytes.Buffer) + err := Switch("", 0, api, buf) + assert.Contains(t, err.Error(), "cannot parse y to int") + assert.Contains(t, buf.String(), mockWorkspace.ID) + api.AssertExpectations(t) +} + func TestSwitchHoustonError(t *testing.T) { // prepare test config and init it configRaw := []byte(`cloud: @@ -324,10 +385,10 @@ func TestGetWorkspaceSelection(t *testing.T) { err := config.ResetCurrentContext() assert.NoError(t, err) out := new(bytes.Buffer) - resp, err := getWorkspaceSelection(0, 0, api, out) + workspaceSelection := getWorkspaceSelection(0, 0, api, out) - assert.Contains(t, err.Error(), "no context set, have you authenticated to Astro or Astronomer Software? Run astro login and try again") - assert.Equal(t, "", resp) + assert.Contains(t, workspaceSelection.err.Error(), "no context set, have you authenticated to Astro or Astronomer Software? Run astro login and try again") + assert.Equal(t, "", workspaceSelection.id) }) testUtil.InitTestConfig("software") @@ -335,36 +396,37 @@ func TestGetWorkspaceSelection(t *testing.T) { t.Run("success", func(t *testing.T) { out := new(bytes.Buffer) defer testUtil.MockUserInput(t, "1")() - resp, err := getWorkspaceSelection(0, 0, api, out) + workspaceSelection := getWorkspaceSelection(0, 0, api, out) - assert.NoError(t, err) - assert.Equal(t, "ck05r3bor07h40d02y2hw4n4v", resp) + assert.NoError(t, workspaceSelection.err) + assert.Equal(t, "ck05r3bor07h40d02y2hw4n4v", workspaceSelection.id) }) t.Run("success with pagination", func(t *testing.T) { out := new(bytes.Buffer) defer testUtil.MockUserInput(t, "1")() - resp, err := getWorkspaceSelection(10, 0, api, out) + workspaceSelection := getWorkspaceSelection(10, 0, api, out) - assert.NoError(t, err) - assert.Equal(t, "ck05r3bor07h40d02y2hw4n4v", resp) + assert.NoError(t, workspaceSelection.err) + assert.Equal(t, "ck05r3bor07h40d02y2hw4n4v", workspaceSelection.id) }) t.Run("invalid selection", func(t *testing.T) { out := new(bytes.Buffer) defer testUtil.MockUserInput(t, "y")() - resp, err := getWorkspaceSelection(0, 0, api, out) + workspaceSelection := getWorkspaceSelection(0, 0, api, out) - assert.Contains(t, err.Error(), "cannot parse y to int") - assert.Equal(t, "", resp) + assert.Contains(t, workspaceSelection.err.Error(), "cannot parse y to int") + assert.Equal(t, "", workspaceSelection.id) }) t.Run("quit selection when paginated", func(t *testing.T) { out := new(bytes.Buffer) defer testUtil.MockUserInput(t, "q")() - resp, err := getWorkspaceSelection(10, 0, api, out) - assert.Nil(t, err) - assert.Equal(t, "", resp) + workspaceSelection := getWorkspaceSelection(10, 0, api, out) + assert.Nil(t, workspaceSelection.err) + assert.Equal(t, "", workspaceSelection.id) + assert.Equal(t, true, workspaceSelection.quit) }) }