mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Add "projects list" command to the CLI (#333)
This adds a WorkspaceOwnerCount parameter returned from the projects API. It's helpful to display the amount of usage a specific project has.
This commit is contained in:
+3
-3
@@ -67,7 +67,7 @@ func login() *cobra.Command {
|
||||
if !isTTY(cmd) {
|
||||
return xerrors.New("the initial user cannot be created in non-interactive mode. use the API")
|
||||
}
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Your Coder deployment hasn't been set up!\n", color.HiBlackString(">"))
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Your Coder deployment hasn't been set up!\n", caret)
|
||||
|
||||
_, err := prompt(cmd, &promptui.Prompt{
|
||||
Label: "Would you like to create the first user?",
|
||||
@@ -147,7 +147,7 @@ func login() *cobra.Command {
|
||||
return xerrors.Errorf("write server url: %w", err)
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Welcome to Coder, %s! You're authenticated.\n", color.HiBlackString(">"), color.HiCyanString(username))
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Welcome to Coder, %s! You're authenticated.\n", caret, color.HiCyanString(username))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ func login() *cobra.Command {
|
||||
return xerrors.Errorf("write server url: %w", err)
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Welcome to Coder, %s! You're authenticated.\n", color.HiBlackString(">"), color.HiCyanString(resp.Username))
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Welcome to Coder, %s! You're authenticated.\n", caret, color.HiCyanString(resp.Username))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ func projectCreate() *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s The %s project has been created!\n", color.HiBlackString(">"), color.HiCyanString(project.Name))
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s The %s project has been created!\n", caret, color.HiCyanString(project.Name))
|
||||
_, err = prompt(cmd, &promptui.Prompt{
|
||||
Label: "Create a new workspace?",
|
||||
IsConfirm: true,
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func projectList() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "list",
|
||||
Aliases: []string{"ls"},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
client, err := createClient(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
start := time.Now()
|
||||
organization, err := currentOrganization(cmd, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
projects, err := client.Projects(cmd.Context(), organization.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(projects) == 0 {
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s No projects found in %s! Create one:\n\n", caret, color.HiWhiteString(organization.Name))
|
||||
_, _ = fmt.Fprintln(cmd.OutOrStdout(), color.HiMagentaString(" $ coder projects create <directory>\n"))
|
||||
return nil
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Projects found in %s %s\n\n",
|
||||
caret,
|
||||
color.HiWhiteString(organization.Name),
|
||||
color.HiBlackString("[%dms]",
|
||||
time.Since(start).Milliseconds()))
|
||||
|
||||
writer := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 0, 4, ' ', 0)
|
||||
_, _ = fmt.Fprintf(writer, "%s\t%s\t%s\t%s\n",
|
||||
color.HiBlackString("Project"),
|
||||
color.HiBlackString("Source"),
|
||||
color.HiBlackString("Last Updated"),
|
||||
color.HiBlackString("Used By"))
|
||||
for _, project := range projects {
|
||||
suffix := ""
|
||||
if project.WorkspaceOwnerCount != 1 {
|
||||
suffix = "s"
|
||||
}
|
||||
_, _ = fmt.Fprintf(writer, "%s\t%s\t%s\t%s\n",
|
||||
color.New(color.FgHiCyan).Sprint(project.Name),
|
||||
color.WhiteString("Archive"),
|
||||
color.WhiteString(project.UpdatedAt.Format("January 2, 2006")),
|
||||
color.New(color.FgHiWhite).Sprintf("%d developer%s", project.WorkspaceOwnerCount, suffix))
|
||||
}
|
||||
return writer.Flush()
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/pty/ptytest"
|
||||
)
|
||||
|
||||
func TestProjectList(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("None", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t)
|
||||
coderdtest.CreateInitialUser(t, client)
|
||||
cmd, root := clitest.New(t, "projects", "list")
|
||||
clitest.SetupConfig(t, client, root)
|
||||
pty := ptytest.New(t)
|
||||
cmd.SetIn(pty.Input())
|
||||
cmd.SetOut(pty.Output())
|
||||
closeChan := make(chan struct{})
|
||||
go func() {
|
||||
err := cmd.Execute()
|
||||
require.NoError(t, err)
|
||||
close(closeChan)
|
||||
}()
|
||||
pty.ExpectMatch("No projects found")
|
||||
<-closeChan
|
||||
})
|
||||
t.Run("List", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t)
|
||||
user := coderdtest.CreateInitialUser(t, client)
|
||||
daemon := coderdtest.NewProvisionerDaemon(t, client)
|
||||
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
|
||||
coderdtest.AwaitProjectImportJob(t, client, user.Organization, job.ID)
|
||||
_ = daemon.Close()
|
||||
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
|
||||
cmd, root := clitest.New(t, "projects", "list")
|
||||
clitest.SetupConfig(t, client, root)
|
||||
pty := ptytest.New(t)
|
||||
cmd.SetIn(pty.Input())
|
||||
cmd.SetOut(pty.Output())
|
||||
closeChan := make(chan struct{})
|
||||
go func() {
|
||||
err := cmd.Execute()
|
||||
require.NoError(t, err)
|
||||
close(closeChan)
|
||||
}()
|
||||
pty.ExpectMatch(project.Name)
|
||||
<-closeChan
|
||||
})
|
||||
}
|
||||
+6
-3
@@ -30,9 +30,12 @@ func projects() *cobra.Command {
|
||||
|
||||
` + color.New(color.FgHiMagenta).Sprint("$ coder projects update <name>"),
|
||||
}
|
||||
cmd.AddCommand(projectCreate())
|
||||
cmd.AddCommand(projectPlan())
|
||||
cmd.AddCommand(projectUpdate())
|
||||
cmd.AddCommand(
|
||||
projectCreate(),
|
||||
projectList(),
|
||||
projectPlan(),
|
||||
projectUpdate(),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ import (
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
var (
|
||||
caret = color.HiBlackString(">")
|
||||
)
|
||||
|
||||
const (
|
||||
varGlobalConfig = "global-config"
|
||||
varNoOpen = "no-open"
|
||||
|
||||
@@ -54,7 +54,7 @@ func workspaceCreate() *cobra.Command {
|
||||
}
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Previewing project create...\n", color.HiBlackString(">"))
|
||||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Previewing project create...\n", caret)
|
||||
|
||||
project, err := client.Project(cmd.Context(), organization.Name, args[0])
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user