Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 15 additions & 55 deletions pkg/cmd/ls/ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/brevdev/brev-cli/pkg/cmdcontext"
"github.com/brevdev/brev-cli/pkg/config"
"github.com/brevdev/brev-cli/pkg/entity"
"github.com/brevdev/brev-cli/pkg/entity/virtualproject"
breverrors "github.com/brevdev/brev-cli/pkg/errors"
"github.com/brevdev/brev-cli/pkg/featureflag"
"github.com/brevdev/brev-cli/pkg/store"
Expand Down Expand Up @@ -383,27 +382,14 @@ func (ls Ls) RunUser(_ bool) error {
return nil
}

func (ls Ls) ShowAllWorkspaces(org *entity.Organization, otherOrgs []entity.Organization, user *entity.User, allWorkspaces []entity.Workspace, gpuLookup map[string]string) {
userWorkspaces := store.FilterForUserWorkspaces(allWorkspaces, user.ID)
ls.displayWorkspacesAndHelp(org, otherOrgs, userWorkspaces, allWorkspaces, gpuLookup)

projects := virtualproject.NewVirtualProjects(allWorkspaces)

var unjoinedProjects []virtualproject.VirtualProject
for _, p := range projects {
wks := p.GetUserWorkspaces(user.ID)
if len(wks) == 0 {
unjoinedProjects = append(unjoinedProjects, p)
}
}

displayProjects(ls.terminal, org.Name, unjoinedProjects)
func (ls Ls) ShowAllWorkspaces(org *entity.Organization, otherOrgs []entity.Organization, workspacesToShow []entity.Workspace, gpuLookup map[string]string) {
ls.displayWorkspacesAndHelp(org, otherOrgs, workspacesToShow, workspacesToShow, true, gpuLookup)
}

func (ls Ls) ShowUserWorkspaces(org *entity.Organization, otherOrgs []entity.Organization, user *entity.User, allWorkspaces []entity.Workspace, gpuLookup map[string]string) {
userWorkspaces := store.FilterForUserWorkspaces(allWorkspaces, user.ID)

ls.displayWorkspacesAndHelp(org, otherOrgs, userWorkspaces, allWorkspaces, gpuLookup)
ls.displayWorkspacesAndHelp(org, otherOrgs, userWorkspaces, allWorkspaces, false, gpuLookup)
}

func (ls Ls) ShowOrgWorkspaces(org *entity.Organization, workspaces []entity.Workspace, gpuLookup map[string]string) {
Expand All @@ -419,10 +405,10 @@ func (ls Ls) ShowOrgWorkspaces(org *entity.Organization, workspaces []entity.Wor
displayLsResetBreadCrumb(ls.terminal, workspaces)
}

func (ls Ls) displayWorkspacesAndHelp(org *entity.Organization, otherOrgs []entity.Organization, userWorkspaces []entity.Workspace, allWorkspaces []entity.Workspace, gpuLookup map[string]string) {
if len(userWorkspaces) == 0 {
func (ls Ls) displayWorkspacesAndHelp(org *entity.Organization, otherOrgs []entity.Organization, workspacesToDisplay []entity.Workspace, allWorkspaces []entity.Workspace, showAll bool, gpuLookup map[string]string) {
if len(workspacesToDisplay) == 0 {
ls.terminal.Vprint(ls.terminal.Yellow("No instances in org %s\n", org.Name))
if len(allWorkspaces) > 0 {
if !showAll && len(allWorkspaces) > 0 {
ls.terminal.Vprintf("%s", ls.terminal.Green("See teammates' instances:\n"))
ls.terminal.Vprintf("%s", ls.terminal.Yellow("\tbrev ls --all\n"))
} else {
Expand All @@ -434,13 +420,17 @@ func (ls Ls) displayWorkspacesAndHelp(org *entity.Organization, otherOrgs []enti
ls.terminal.Vprintf("%s", ls.terminal.Yellow(fmt.Sprintf("\tbrev set %s\n", getOtherOrg(otherOrgs, *org).Name)))
}
} else {
ls.terminal.Vprintf("You have %d instances in Org %s\n", len(userWorkspaces), ls.terminal.Yellow(org.Name))
displayWorkspacesTable(ls.terminal, userWorkspaces, gpuLookup)
if showAll {
ls.terminal.Vprintf("%d instances in Org %s\n", len(workspacesToDisplay), ls.terminal.Yellow(org.Name))
} else {
ls.terminal.Vprintf("You have %d instances in Org %s\n", len(workspacesToDisplay), ls.terminal.Yellow(org.Name))
}
displayWorkspacesTable(ls.terminal, workspacesToDisplay, gpuLookup)

fmt.Print("\n")

displayLsResetBreadCrumb(ls.terminal, userWorkspaces)
// displayLsConnectBreadCrumb(ls.terminal, userWorkspaces)
displayLsResetBreadCrumb(ls.terminal, workspacesToDisplay)
// displayLsConnectBreadCrumb(ls.terminal, workspacesToDisplay)
}
}

Expand Down Expand Up @@ -548,7 +538,7 @@ func (ls Ls) RunWorkspaces(cliAuth auth.CLIAuth, org *entity.Organization, showA
return breverrors.WrapAndTrace(err)
}
if showAll {
ls.ShowAllWorkspaces(org, orgs, user, allWorkspaces, gpuLookup)
ls.ShowAllWorkspaces(org, orgs, workspacesToShow, gpuLookup)
if len(nodes) > 0 {
ls.terminal.Vprintf("\nYou have %d external node(s) in Org %s\n", len(nodes), ls.terminal.Yellow(org.Name))
displayNodesTable(ls.terminal, nodes, ls.piped)
Expand Down Expand Up @@ -680,23 +670,6 @@ func (ls Ls) RunHosts(org *entity.Organization) error {
return nil
}

func displayProjects(t *terminal.Terminal, orgName string, projects []virtualproject.VirtualProject) {
if len(projects) > 0 {
fmt.Print("\n")
t.Vprintf("%d other projects in Org %s\n", len(projects), t.Yellow(orgName))
displayProjectsTable(projects)

fmt.Print("\n")
t.Vprintf("%s", t.Green("Join a project:\n")+
t.Yellow(fmt.Sprintf("\tbrev start %s\n", projects[0].Name)))
} else {
t.Vprintf("no other projects in Org %s\n", t.Yellow(orgName))
fmt.Print("\n")
t.Vprintf("%s", t.Green("Invite a teamate:\n")+
t.Yellow("\tbrev invite"))
}
}

func getBrevTableOptions() table.Options {
options := table.OptionsDefault
options.DrawBorder = false
Expand Down Expand Up @@ -793,19 +766,6 @@ func displayOrgTable(t *terminal.Terminal, orgs []entity.Organization, currentOr
ta.Render()
}

func displayProjectsTable(projects []virtualproject.VirtualProject) {
ta := table.NewWriter()
ta.SetOutputMirror(os.Stdout)
ta.Style().Options = getBrevTableOptions()
header := table.Row{"NAME", "MEMBERS"}
ta.AppendHeader(header)
for _, p := range projects {
workspaceRow := []table.Row{{p.Name, p.GetUniqueUserCount()}}
ta.AppendRows(workspaceRow)
}
ta.Render()
}

func getStatusColoredText(t *terminal.Terminal, status string) string {
switch status {
case entity.Running, entity.Ready, string(entity.Completed):
Expand Down
35 changes: 35 additions & 0 deletions pkg/cmd/ls/ls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,41 @@ func TestRunLs_OrgsJSON(t *testing.T) {
}
}

// TestRunLs_ShowAllTable verifies that --all lists every org instance in table output.
func TestRunLs_ShowAllTable(t *testing.T) {
s := newTestStore()
s.workspaces = []entity.Workspace{
{
ID: "ws-mine",
Name: "my-ws",
Status: entity.Running,
VerbBuildStatus: entity.Completed,
CreatedByUserID: "u1",
},
{
ID: "ws-other",
Name: "other-ws",
Status: entity.Running,
VerbBuildStatus: entity.Completed,
CreatedByUserID: "u2",
},
}
term := terminal.New()

out := captureStdout(t, func() {
err := RunLs(term, resolveTestCLIAuth(t, s), s, nil, "", true, false)
if err != nil {
t.Fatalf("RunLs --all returned error: %v", err)
}
})
if !strings.Contains(out, "my-ws") || !strings.Contains(out, "other-ws") {
t.Fatalf("expected both workspaces in table output, got:\n%s", out)
}
if strings.Contains(out, "brev ls --all") {
t.Fatal("should not suggest brev ls --all when already using --all")
}
}

// TestRunLs_ShowAll verifies that --all includes workspaces from other users.
func TestRunLs_ShowAllJSON(t *testing.T) {
s := newTestStore()
Expand Down
Loading