chore(cli): rename Cmd to Command (#12616)

I think Command is cleaner and my original decision to use "Cmd"
a mistake.

Plus this creates better parity with cobra.
This commit is contained in:
Ammar Bandukwala 2024-03-17 09:45:26 -05:00 committed by GitHub
parent 2a77580ba6
commit b4c0fa80d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
95 changed files with 313 additions and 311 deletions

View File

@ -34,7 +34,7 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) workspaceAgent() *serpent.Cmd {
func (r *RootCmd) workspaceAgent() *serpent.Command {
var (
auth string
logDir string
@ -49,7 +49,7 @@ func (r *RootCmd) workspaceAgent() *serpent.Cmd {
slogJSONPath string
slogStackdriverPath string
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "agent",
Short: `Starts the Coder workspace agent.`,
// This command isn't useful to manually execute.

View File

@ -11,9 +11,9 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) autoupdate() *serpent.Cmd {
func (r *RootCmd) autoupdate() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "autoupdate <workspace> <always|never>",
Short: "Toggle auto-update policy for a workspace",

View File

@ -23,7 +23,7 @@ func TestBuilder(t *testing.T) {
t.Run("NoConfiguration", func(t *testing.T) {
t.Parallel()
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "test",
Handler: testHandler(t),
}
@ -35,7 +35,7 @@ func TestBuilder(t *testing.T) {
t.Parallel()
tempFile := filepath.Join(t.TempDir(), "test.log")
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "test",
Handler: testHandler(t,
clilog.WithHuman(tempFile),
@ -51,7 +51,7 @@ func TestBuilder(t *testing.T) {
t.Parallel()
tempFile := filepath.Join(t.TempDir(), "test.log")
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "test",
Handler: testHandler(t,
clilog.WithHuman(tempFile),
@ -68,7 +68,7 @@ func TestBuilder(t *testing.T) {
t.Parallel()
tempFile := filepath.Join(t.TempDir(), "test.log")
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "test",
Handler: testHandler(t, clilog.WithHuman(tempFile)),
}
@ -81,7 +81,7 @@ func TestBuilder(t *testing.T) {
t.Parallel()
tempFile := filepath.Join(t.TempDir(), "test.log")
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "test",
Handler: testHandler(t, clilog.WithJSON(tempFile), clilog.WithVerbose()),
}
@ -107,7 +107,7 @@ func TestBuilder(t *testing.T) {
// Use the default deployment values.
dv := coderdtest.DeploymentValues(t)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "test",
Handler: testHandler(t, clilog.FromDeploymentValues(dv)),
}
@ -135,7 +135,7 @@ func TestBuilder(t *testing.T) {
Enable: true,
},
}
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "test",
Handler: testHandler(t, clilog.FromDeploymentValues(dv)),
}
@ -150,7 +150,7 @@ func TestBuilder(t *testing.T) {
t.Parallel()
tempFile := filepath.Join(t.TempDir(), "doesnotexist", "test.log")
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "test",
Handler: func(inv *serpent.Invocation) error {
logger, closeLog, err := clilog.New(

View File

@ -56,7 +56,7 @@ func (l *logWriter) Write(p []byte) (n int, err error) {
}
func NewWithCommand(
t testing.TB, cmd *serpent.Cmd, args ...string,
t testing.TB, cmd *serpent.Command, args ...string,
) (*serpent.Invocation, config.Root) {
configDir := config.Root(t.TempDir())
// I really would like to fail test on error logs, but realistically, turning on by default

View File

@ -48,7 +48,7 @@ func DefaultCases() []CommandHelpCase {
// TestCommandHelp will test the help output of the given commands
// using golden files.
func TestCommandHelp(t *testing.T, getRoot func(t *testing.T) *serpent.Cmd, cases []CommandHelpCase) {
func TestCommandHelp(t *testing.T, getRoot func(t *testing.T) *serpent.Command, cases []CommandHelpCase) {
t.Parallel()
rootClient, replacements := prepareTestData(t)
@ -148,7 +148,7 @@ func NormalizeGoldenFile(t *testing.T, byt []byte) []byte {
return byt
}
func extractVisibleCommandPaths(cmdPath []string, cmds []*serpent.Cmd) [][]string {
func extractVisibleCommandPaths(cmdPath []string, cmds []*serpent.Command) [][]string {
var cmdPaths [][]string
for _, c := range cmds {
if c.Hidden {

View File

@ -11,8 +11,8 @@ import (
// non-root commands (like 'groups' or 'users'), a handler is required.
// These handlers are likely just the 'help' handler, but this must be
// explicitly set.
func HandlersOK(t *testing.T, cmd *serpent.Cmd) {
cmd.Walk(func(cmd *serpent.Cmd) {
func HandlersOK(t *testing.T, cmd *serpent.Command) {
cmd.Walk(func(cmd *serpent.Command) {
if cmd.Handler == nil {
// If you see this error, make the Handler a helper invoker.
// Handler: func(inv *serpent.Invocation) error {

View File

@ -382,7 +382,7 @@ func TestAgent(t *testing.T) {
output := make(chan string, 100) // Buffered to avoid blocking, overflow is discarded.
logs := make(chan []codersdk.WorkspaceAgentLog, 1)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Handler: func(inv *serpent.Invocation) error {
tc.opts.Fetch = func(_ context.Context, _ uuid.UUID) (codersdk.WorkspaceAgent, error) {
t.Log("iter", len(tc.iter))
@ -450,7 +450,7 @@ func TestAgent(t *testing.T) {
t.Parallel()
var fetchCalled uint64
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Handler: func(inv *serpent.Invocation) error {
buf := bytes.Buffer{}
err := cliui.Agent(inv.Context(), &buf, uuid.Nil, cliui.AgentOptions{

View File

@ -22,7 +22,7 @@ func TestExternalAuth(t *testing.T) {
defer cancel()
ptty := ptytest.New(t)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Handler: func(inv *serpent.Invocation) error {
var fetched atomic.Bool
return cliui.ExternalAuth(inv.Context(), inv.Stdout, cliui.ExternalAuthOptions{

View File

@ -11,12 +11,12 @@ var defaultQuery = "owner:me"
// and allows easy integration to a CLI command.
// Example usage:
//
// func (r *RootCmd) MyCmd() *serpent.Cmd {
// func (r *RootCmd) MyCmd() *serpent.Command {
// var (
// filter cliui.WorkspaceFilter
// ...
// )
// cmd := &serpent.Cmd{
// cmd := &serpent.Command{
// ...
// }
// filter.AttachOptions(&cmd.Options)

View File

@ -101,7 +101,7 @@ func Test_OutputFormatter(t *testing.T) {
},
)
cmd := &serpent.Cmd{}
cmd := &serpent.Command{}
f.AttachOptions(&cmd.Options)
fs := cmd.Options.FlagSet()

View File

@ -147,7 +147,7 @@ func TestPrompt(t *testing.T) {
func newPrompt(ptty *ptytest.PTY, opts cliui.PromptOptions, invOpt func(inv *serpent.Invocation)) (string, error) {
value := ""
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Handler: func(inv *serpent.Invocation) error {
var err error
value, err = cliui.Prompt(inv, opts)
@ -210,7 +210,7 @@ func TestPasswordTerminalState(t *testing.T) {
// nolint:unused
func passwordHelper() {
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Handler: func(inv *serpent.Invocation) error {
cliui.Prompt(inv, cliui.PromptOptions{
Text: "Password:",

View File

@ -127,7 +127,7 @@ func newProvisionerJob(t *testing.T) provisionerJobTest {
}
jobLock := sync.Mutex{}
logs := make(chan codersdk.ProvisionerJobLog, 1)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Handler: func(inv *serpent.Invocation) error {
return cliui.ProvisionerJob(inv.Context(), inv.Stdout, cliui.ProvisionerJobOptions{
FetchInterval: time.Millisecond,

View File

@ -31,7 +31,7 @@ func TestSelect(t *testing.T) {
func newSelect(ptty *ptytest.PTY, opts cliui.SelectOptions) (string, error) {
value := ""
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Handler: func(inv *serpent.Invocation) error {
var err error
value, err = cliui.Select(inv, opts)
@ -72,7 +72,7 @@ func TestRichSelect(t *testing.T) {
func newRichSelect(ptty *ptytest.PTY, opts cliui.RichSelectOptions) (string, error) {
value := ""
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Handler: func(inv *serpent.Invocation) error {
richOption, err := cliui.RichSelect(inv, opts)
if err == nil {
@ -105,7 +105,7 @@ func TestMultiSelect(t *testing.T) {
func newMultiSelect(ptty *ptytest.PTY, items []string) ([]string, error) {
var values []string
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Handler: func(inv *serpent.Invocation) error {
selectedItems, err := cliui.MultiSelect(inv, items)
if err == nil {

View File

@ -215,7 +215,7 @@ func sshPrepareWorkspaceConfigs(ctx context.Context, client *codersdk.Client) (r
}
}
func (r *RootCmd) configSSH() *serpent.Cmd {
func (r *RootCmd) configSSH() *serpent.Command {
var (
sshConfigFile string
sshConfigOpts sshConfigOptions
@ -226,7 +226,7 @@ func (r *RootCmd) configSSH() *serpent.Cmd {
coderCliPath string
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "config-ssh",
Short: "Add an SSH Host entry for your workspaces \"ssh coder.workspace\"",

View File

@ -19,7 +19,7 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) create() *serpent.Cmd {
func (r *RootCmd) create() *serpent.Command {
var (
templateName string
startAt string
@ -31,7 +31,7 @@ func (r *RootCmd) create() *serpent.Cmd {
copyParametersFrom string
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "create [name]",
Short: "Create a workspace",

View File

@ -10,10 +10,10 @@ import (
)
// nolint
func (r *RootCmd) deleteWorkspace() *serpent.Cmd {
func (r *RootCmd) deleteWorkspace() *serpent.Command {
var orphan bool
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "delete <workspace>",
Short: "Delete a workspace",

View File

@ -19,12 +19,12 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) dotfiles() *serpent.Cmd {
func (r *RootCmd) dotfiles() *serpent.Command {
var symlinkDir string
var gitbranch string
var dotfilesRepoDir string
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "dotfiles <git_repo_url>",
Middleware: serpent.RequireNArgs(1),
Short: "Personalize your workspace by applying a canonical dotfiles repository",

View File

@ -13,9 +13,9 @@ import (
"github.com/coder/serpent"
)
func (RootCmd) errorExample() *serpent.Cmd {
errorCmd := func(use string, err error) *serpent.Cmd {
return &serpent.Cmd{
func (RootCmd) errorExample() *serpent.Command {
errorCmd := func(use string, err error) *serpent.Command {
return &serpent.Command{
Use: use,
Handler: func(inv *serpent.Invocation) error {
return err
@ -52,7 +52,7 @@ func (RootCmd) errorExample() *serpent.Cmd {
// Some flags
var magicWord serpent.String
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "example-error",
Short: "Shows what different error messages look like",
Long: "This command is pretty pointless, but without it testing errors is" +
@ -61,7 +61,7 @@ func (RootCmd) errorExample() *serpent.Cmd {
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
// Typical codersdk api error
errorCmd("api", apiError),

View File

@ -2,15 +2,15 @@ package cli
import "github.com/coder/serpent"
func (r *RootCmd) expCmd() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) expCmd() *serpent.Command {
cmd := &serpent.Command{
Use: "exp",
Short: "Internal commands for testing and experimentation. These are prone to breaking changes with no notice.",
Handler: func(i *serpent.Invocation) error {
return i.Command.HelpHandler(i)
},
Hidden: true,
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.scaletestCmd(),
r.errorExample(),
},

View File

@ -44,14 +44,14 @@ import (
const scaletestTracerName = "coder_scaletest"
func (r *RootCmd) scaletestCmd() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) scaletestCmd() *serpent.Command {
cmd := &serpent.Command{
Use: "scaletest",
Short: "Run a scale test against the Coder API",
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.scaletestCleanup(),
r.scaletestDashboard(),
r.scaletestCreateWorkspaces(),
@ -398,13 +398,13 @@ func (r *userCleanupRunner) Run(ctx context.Context, _ string, _ io.Writer) erro
return nil
}
func (r *RootCmd) scaletestCleanup() *serpent.Cmd {
func (r *RootCmd) scaletestCleanup() *serpent.Command {
var template string
cleanupStrategy := &scaletestStrategyFlags{cleanup: true}
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "cleanup",
Short: "Cleanup scaletest workspaces, then cleanup scaletest users.",
Long: "The strategy flags will apply to each stage of the cleanup process.",
@ -521,7 +521,7 @@ func (r *RootCmd) scaletestCleanup() *serpent.Cmd {
return cmd
}
func (r *RootCmd) scaletestCreateWorkspaces() *serpent.Cmd {
func (r *RootCmd) scaletestCreateWorkspaces() *serpent.Command {
var (
count int64
retry int64
@ -558,7 +558,7 @@ func (r *RootCmd) scaletestCreateWorkspaces() *serpent.Cmd {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "create-workspaces",
Short: "Creates many users, then creates a workspace for each user and waits for them finish building and fully come online. Optionally runs a command inside each workspace, and connects to the workspace over WireGuard.",
Long: `It is recommended that all rate limits are disabled on the server before running this scaletest. This test generates many login events which will be rate limited against the (most likely single) IP.`,
@ -864,7 +864,7 @@ func (r *RootCmd) scaletestCreateWorkspaces() *serpent.Cmd {
return cmd
}
func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Cmd {
func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
var (
tickInterval time.Duration
bytesPerTick int64
@ -881,7 +881,7 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Cmd {
prometheusFlags = &scaletestPrometheusFlags{}
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "workspace-traffic",
Short: "Generate traffic to scaletest workspaces through coderd",
Middleware: serpent.Chain(
@ -1109,7 +1109,7 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Cmd {
return cmd
}
func (r *RootCmd) scaletestDashboard() *serpent.Cmd {
func (r *RootCmd) scaletestDashboard() *serpent.Command {
var (
interval time.Duration
jitter time.Duration
@ -1125,7 +1125,7 @@ func (r *RootCmd) scaletestDashboard() *serpent.Cmd {
prometheusFlags = &scaletestPrometheusFlags{}
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "dashboard",
Short: "Generate traffic to the HTTP API to simulate use of the dashboard.",
Middleware: serpent.Chain(

View File

@ -4,8 +4,8 @@ package cli
import "github.com/coder/serpent"
func (r *RootCmd) scaletestCmd() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) scaletestCmd() *serpent.Command {
cmd := &serpent.Command{
Use: "scaletest",
Short: "Run a scale test against the Coder API",
Handler: func(inv *serpent.Invocation) error {

View File

@ -12,23 +12,23 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) externalAuth() *serpent.Cmd {
return &serpent.Cmd{
func (r *RootCmd) externalAuth() *serpent.Command {
return &serpent.Command{
Use: "external-auth",
Short: "Manage external authentication",
Long: "Authenticate with external services inside of a workspace.",
Handler: func(i *serpent.Invocation) error {
return i.Command.HelpHandler(i)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.externalAuthAccessToken(),
},
}
}
func (r *RootCmd) externalAuthAccessToken() *serpent.Cmd {
func (r *RootCmd) externalAuthAccessToken() *serpent.Command {
var extra string
return &serpent.Cmd{
return &serpent.Command{
Use: "access-token <provider>",
Short: "Print auth for an external provider",
Long: "Print an access-token for an external auth provider. " +

View File

@ -9,9 +9,9 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) favorite() *serpent.Cmd {
func (r *RootCmd) favorite() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Aliases: []string{"fav", "favou" + "rite"},
Annotations: workspaceCommand,
Use: "favorite <workspace>",
@ -36,9 +36,9 @@ func (r *RootCmd) favorite() *serpent.Cmd {
return cmd
}
func (r *RootCmd) unfavorite() *serpent.Cmd {
func (r *RootCmd) unfavorite() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Aliases: []string{"unfav", "unfavou" + "rite"},
Annotations: workspaceCommand,
Use: "unfavorite <workspace>",

View File

@ -18,8 +18,8 @@ import (
// gitAskpass is used by the Coder agent to automatically authenticate
// with Git providers based on a hostname.
func (r *RootCmd) gitAskpass() *serpent.Cmd {
return &serpent.Cmd{
func (r *RootCmd) gitAskpass() *serpent.Command {
return &serpent.Command{
Use: "gitaskpass",
Hidden: true,
Handler: func(inv *serpent.Invocation) error {

View File

@ -18,8 +18,8 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) gitssh() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) gitssh() *serpent.Command {
cmd := &serpent.Command{
Use: "gitssh",
Hidden: true,
Short: `Wraps the "ssh" command and uses the coder gitssh key for authentication`,

View File

@ -107,7 +107,7 @@ var usageTemplate = func() *template.Template {
}
return sb.String()
},
"formatSubcommand": func(cmd *serpent.Cmd) string {
"formatSubcommand": func(cmd *serpent.Command) string {
// Minimize padding by finding the longest neighboring name.
maxNameLength := len(cmd.Name())
if parent := cmd.Parent; parent != nil {
@ -189,12 +189,12 @@ var usageTemplate = func() *template.Template {
s = wrapTTY(s)
return s
},
"visibleChildren": func(cmd *serpent.Cmd) []*serpent.Cmd {
return filterSlice(cmd.Children, func(c *serpent.Cmd) bool {
"visibleChildren": func(cmd *serpent.Command) []*serpent.Command {
return filterSlice(cmd.Children, func(c *serpent.Command) bool {
return !c.Hidden
})
},
"optionGroups": func(cmd *serpent.Cmd) []optionGroup {
"optionGroups": func(cmd *serpent.Command) []optionGroup {
groups := []optionGroup{{
// Default group.
Name: "",

View File

@ -70,7 +70,7 @@ func workspaceListRowFromWorkspace(now time.Time, workspace codersdk.Workspace)
}
}
func (r *RootCmd) list() *serpent.Cmd {
func (r *RootCmd) list() *serpent.Command {
var (
filter cliui.WorkspaceFilter
formatter = cliui.NewOutputFormatter(
@ -92,7 +92,7 @@ func (r *RootCmd) list() *serpent.Cmd {
)
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "list",
Short: "List workspaces",

View File

@ -125,7 +125,7 @@ func (r *RootCmd) loginWithPassword(
return nil
}
func (r *RootCmd) login() *serpent.Cmd {
func (r *RootCmd) login() *serpent.Command {
const firstUserTrialEnv = "CODER_FIRST_USER_TRIAL"
var (
@ -135,7 +135,7 @@ func (r *RootCmd) login() *serpent.Cmd {
trial bool
useTokenForSession bool
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "login [<url>]",
Short: "Authenticate with Coder deployment",
Middleware: serpent.RequireRangeArgs(0, 1),

View File

@ -12,9 +12,9 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) logout() *serpent.Cmd {
func (r *RootCmd) logout() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "logout",
Short: "Unauthenticate your local session",
Middleware: serpent.Chain(

View File

@ -13,10 +13,10 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) netcheck() *serpent.Cmd {
func (r *RootCmd) netcheck() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "netcheck",
Short: "Print network debug information for DERP and STUN",
Middleware: serpent.Chain(

View File

@ -17,14 +17,14 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) open() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) open() *serpent.Command {
cmd := &serpent.Command{
Use: "open",
Short: "Open a workspace",
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.openVSCode(),
},
}
@ -33,14 +33,14 @@ func (r *RootCmd) open() *serpent.Cmd {
const vscodeDesktopName = "VS Code Desktop"
func (r *RootCmd) openVSCode() *serpent.Cmd {
func (r *RootCmd) openVSCode() *serpent.Command {
var (
generateToken bool
testOpenError bool
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "vscode <workspace> [<directory in workspace>]",
Short: fmt.Sprintf("Open a workspace in %s", vscodeDesktopName),

View File

@ -16,8 +16,8 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) organizations() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) organizations() *serpent.Command {
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "organizations [subcommand]",
Short: "Organization related commands",
@ -26,7 +26,7 @@ func (r *RootCmd) organizations() *serpent.Cmd {
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.currentOrganization(),
r.switchOrganization(),
r.createOrganization(),
@ -37,10 +37,10 @@ func (r *RootCmd) organizations() *serpent.Cmd {
return cmd
}
func (r *RootCmd) switchOrganization() *serpent.Cmd {
func (r *RootCmd) switchOrganization() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "set <organization name | ID>",
Short: "set the organization used by the CLI. Pass an empty string to reset to the default organization.",
Long: "set the organization used by the CLI. Pass an empty string to reset to the default organization.\n" + formatExamples(
@ -206,7 +206,7 @@ func orgNames(orgs []codersdk.Organization) []string {
return names
}
func (r *RootCmd) currentOrganization() *serpent.Cmd {
func (r *RootCmd) currentOrganization() *serpent.Command {
var (
stringFormat func(orgs []codersdk.Organization) (string, error)
client = new(codersdk.Client)
@ -224,7 +224,7 @@ func (r *RootCmd) currentOrganization() *serpent.Cmd {
)
onlyID = false
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "show [current|me|uuid]",
Short: "Show the organization, if no argument is given, the organization currently in use will be shown.",
Middleware: serpent.Chain(

View File

@ -12,10 +12,10 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) createOrganization() *serpent.Cmd {
func (r *RootCmd) createOrganization() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "create <organization name>",
Short: "Create a new organization.",
// This action is currently irreversible, so it's hidden until we have a way to delete organizations.

View File

@ -17,7 +17,7 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) ping() *serpent.Cmd {
func (r *RootCmd) ping() *serpent.Command {
var (
pingNum int64
pingTimeout time.Duration
@ -25,7 +25,7 @@ func (r *RootCmd) ping() *serpent.Cmd {
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "ping <workspace>",
Short: "Ping a workspace",

View File

@ -23,14 +23,14 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) portForward() *serpent.Cmd {
func (r *RootCmd) portForward() *serpent.Command {
var (
tcpForwards []string // <port>:<port>
udpForwards []string // <port>:<port>
disableAutostart bool
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "port-forward <workspace>",
Short: `Forward ports from a workspace to the local machine. For reverse port forwarding, use "coder ssh -R".`,
Aliases: []string{"tunnel"},

View File

@ -12,10 +12,10 @@ import (
"github.com/coder/coder/v2/codersdk"
)
func (r *RootCmd) publickey() *serpent.Cmd {
func (r *RootCmd) publickey() *serpent.Command {
var reset bool
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "publickey",
Aliases: []string{"pubkey"},
Short: "Output your Coder public key used for Git operations",

View File

@ -12,9 +12,9 @@ import (
"github.com/coder/coder/v2/codersdk"
)
func (r *RootCmd) rename() *serpent.Cmd {
func (r *RootCmd) rename() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "rename <workspace> <new name>",
Short: "Rename a workspace",

View File

@ -17,10 +17,10 @@ import (
"github.com/coder/coder/v2/coderd/userpassword"
)
func (*RootCmd) resetPassword() *serpent.Cmd {
func (*RootCmd) resetPassword() *serpent.Command {
var postgresURL string
root := &serpent.Cmd{
root := &serpent.Command{
Use: "reset-password <username>",
Short: "Directly connect to the database to reset a user's password",
Middleware: serpent.RequireNArgs(1),

View File

@ -4,8 +4,8 @@ package cli
import "github.com/coder/serpent"
func (*RootCmd) resetPassword() *serpent.Cmd {
root := &serpent.Cmd{
func (*RootCmd) resetPassword() *serpent.Command {
root := &serpent.Command{
Use: "reset-password <username>",
Short: "Directly connect to the database to reset a user's password",
// We accept RawArgs so all commands and flags are accepted.

View File

@ -13,11 +13,11 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) restart() *serpent.Cmd {
func (r *RootCmd) restart() *serpent.Command {
var parameterFlags workspaceParameterFlags
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "restart <workspace>",
Short: "Restart a workspace",

View File

@ -84,9 +84,9 @@ var (
errUnauthenticatedURLSaved = xerrors.New(notLoggedInURLSavedMessage)
)
func (r *RootCmd) Core() []*serpent.Cmd {
func (r *RootCmd) Core() []*serpent.Command {
// Please re-sort this list alphabetically if you change it!
return []*serpent.Cmd{
return []*serpent.Command{
r.dotfiles(),
r.externalAuth(),
r.login(),
@ -132,13 +132,13 @@ func (r *RootCmd) Core() []*serpent.Cmd {
}
}
func (r *RootCmd) AGPL() []*serpent.Cmd {
func (r *RootCmd) AGPL() []*serpent.Command {
all := append(r.Core(), r.Server( /* Do not import coderd here. */ nil))
return all
}
// Main is the entrypoint for the Coder CLI.
func (r *RootCmd) RunMain(subcommands []*serpent.Cmd) {
func (r *RootCmd) RunMain(subcommands []*serpent.Command) {
rand.Seed(time.Now().UnixMicro())
cmd, err := r.Command(subcommands)
@ -166,10 +166,10 @@ func (r *RootCmd) RunMain(subcommands []*serpent.Cmd) {
}
}
func (r *RootCmd) Command(subcommands []*serpent.Cmd) (*serpent.Cmd, error) {
func (r *RootCmd) Command(subcommands []*serpent.Command) (*serpent.Command, error) {
fmtLong := `Coder %s A tool for provisioning self-hosted development environments with Terraform.
`
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "coder [global-flags] <subcommand>",
Long: fmt.Sprintf(fmtLong, buildinfo.Version()) + formatExamples(
example{
@ -200,7 +200,7 @@ func (r *RootCmd) Command(subcommands []*serpent.Cmd) (*serpent.Cmd, error) {
cmd.AddSubcommands(subcommands...)
// Set default help handler for all commands.
cmd.Walk(func(c *serpent.Cmd) {
cmd.Walk(func(c *serpent.Command) {
if c.HelpHandler == nil {
c.HelpHandler = helpFn()
}
@ -208,7 +208,7 @@ func (r *RootCmd) Command(subcommands []*serpent.Cmd) (*serpent.Cmd, error) {
var merr error
// Add [flags] to usage when appropriate.
cmd.Walk(func(cmd *serpent.Cmd) {
cmd.Walk(func(cmd *serpent.Command) {
const flags = "[flags]"
if strings.Contains(cmd.Use, flags) {
merr = errors.Join(
@ -244,7 +244,7 @@ func (r *RootCmd) Command(subcommands []*serpent.Cmd) (*serpent.Cmd, error) {
})
// Add alises when appropriate.
cmd.Walk(func(cmd *serpent.Cmd) {
cmd.Walk(func(cmd *serpent.Command) {
// TODO: we should really be consistent about naming.
if cmd.Name() == "delete" || cmd.Name() == "remove" {
if slices.Contains(cmd.Aliases, "rm") {
@ -259,7 +259,7 @@ func (r *RootCmd) Command(subcommands []*serpent.Cmd) (*serpent.Cmd, error) {
})
// Sanity-check command options.
cmd.Walk(func(cmd *serpent.Cmd) {
cmd.Walk(func(cmd *serpent.Command) {
for _, opt := range cmd.Options {
// Verify that every option is configurable.
if opt.Flag == "" && opt.Env == "" {
@ -282,7 +282,7 @@ func (r *RootCmd) Command(subcommands []*serpent.Cmd) (*serpent.Cmd, error) {
var debugOptions bool
// Add a wrapper to every command to enable debugging options.
cmd.Walk(func(cmd *serpent.Cmd) {
cmd.Walk(func(cmd *serpent.Command) {
h := cmd.Handler
if h == nil {
// We should never have a nil handler, but if we do, do not

View File

@ -28,7 +28,7 @@ import (
//nolint:tparallel,paralleltest
func TestCommandHelp(t *testing.T) {
// Test with AGPL commands
getCmds := func(t *testing.T) *serpent.Cmd {
getCmds := func(t *testing.T) *serpent.Command {
// Must return a fresh instance of cmds each time.
t.Helper()

View File

@ -53,15 +53,15 @@ When enabling scheduled stop, enter a duration in one of the following formats:
`
)
func (r *RootCmd) schedules() *serpent.Cmd {
scheduleCmd := &serpent.Cmd{
func (r *RootCmd) schedules() *serpent.Command {
scheduleCmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "schedule { show | start | stop | override } <workspace>",
Short: "Schedule automated start and stop times for workspaces",
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.scheduleShow(),
r.scheduleStart(),
r.scheduleStop(),
@ -73,7 +73,7 @@ func (r *RootCmd) schedules() *serpent.Cmd {
}
// scheduleShow() is just a wrapper for list() with some different defaults.
func (r *RootCmd) scheduleShow() *serpent.Cmd {
func (r *RootCmd) scheduleShow() *serpent.Command {
var (
filter cliui.WorkspaceFilter
formatter = cliui.NewOutputFormatter(
@ -91,7 +91,7 @@ func (r *RootCmd) scheduleShow() *serpent.Cmd {
)
)
client := new(codersdk.Client)
showCmd := &serpent.Cmd{
showCmd := &serpent.Command{
Use: "show <workspace | --search <query> | --all>",
Short: "Show workspace schedules",
Long: scheduleShowDescriptionLong,
@ -136,9 +136,9 @@ func (r *RootCmd) scheduleShow() *serpent.Cmd {
return showCmd
}
func (r *RootCmd) scheduleStart() *serpent.Cmd {
func (r *RootCmd) scheduleStart() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "start <workspace-name> { <start-time> [day-of-week] [location] | manual }",
Long: scheduleStartDescriptionLong + "\n" + formatExamples(
example{
@ -185,9 +185,9 @@ func (r *RootCmd) scheduleStart() *serpent.Cmd {
return cmd
}
func (r *RootCmd) scheduleStop() *serpent.Cmd {
func (r *RootCmd) scheduleStop() *serpent.Command {
client := new(codersdk.Client)
return &serpent.Cmd{
return &serpent.Command{
Use: "stop <workspace-name> { <duration> | manual }",
Long: scheduleStopDescriptionLong + "\n" + formatExamples(
example{
@ -229,9 +229,9 @@ func (r *RootCmd) scheduleStop() *serpent.Cmd {
}
}
func (r *RootCmd) scheduleOverride() *serpent.Cmd {
func (r *RootCmd) scheduleOverride() *serpent.Command {
client := new(codersdk.Client)
overrideCmd := &serpent.Cmd{
overrideCmd := &serpent.Command{
Use: "override-stop <workspace-name> <duration from now>",
Short: "Override the stop time of a currently running workspace instance.",
Long: scheduleOverrideDescriptionLong + "\n" + formatExamples(

View File

@ -258,7 +258,7 @@ func enablePrometheus(
), nil
}
func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.API, io.Closer, error)) *serpent.Cmd {
func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.API, io.Closer, error)) *serpent.Command {
if newAPI == nil {
newAPI = func(_ context.Context, o *coderd.Options) (*coderd.API, io.Closer, error) {
api := coderd.New(o)
@ -270,7 +270,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
vals = new(codersdk.DeploymentValues)
opts = vals.Options()
)
serverCmd := &serpent.Cmd{
serverCmd := &serpent.Command{
Use: "server",
Short: "Start a Coder server",
Options: opts,
@ -1148,7 +1148,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
var pgRawURL bool
postgresBuiltinURLCmd := &serpent.Cmd{
postgresBuiltinURLCmd := &serpent.Command{
Use: "postgres-builtin-url",
Short: "Output the connection URL for the built-in PostgreSQL deployment.",
Handler: func(inv *serpent.Invocation) error {
@ -1165,7 +1165,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
},
}
postgresBuiltinServeCmd := &serpent.Cmd{
postgresBuiltinServeCmd := &serpent.Command{
Use: "postgres-builtin-serve",
Short: "Run the built-in PostgreSQL deployment.",
Handler: func(inv *serpent.Invocation) error {

View File

@ -22,7 +22,7 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) newCreateAdminUserCommand() *serpent.Cmd {
func (r *RootCmd) newCreateAdminUserCommand() *serpent.Command {
var (
newUserDBURL string
newUserSSHKeygenAlgorithm string
@ -30,7 +30,7 @@ func (r *RootCmd) newCreateAdminUserCommand() *serpent.Cmd {
newUserEmail string
newUserPassword string
)
createAdminUserCommand := &serpent.Cmd{
createAdminUserCommand := &serpent.Command{
Use: "create-admin-user",
Short: "Create a new admin user with the given username, email and password and adds it to every organization.",
Handler: func(inv *serpent.Invocation) error {

View File

@ -4,8 +4,8 @@ package cli
import "github.com/coder/serpent"
func (r *RootCmd) Server(_ func()) *serpent.Cmd {
root := &serpent.Cmd{
func (r *RootCmd) Server(_ func()) *serpent.Command {
root := &serpent.Command{
Use: "server",
Short: "Start a Coder server",
// We accept RawArgs so all commands and flags are accepted.

View File

@ -8,9 +8,9 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) show() *serpent.Cmd {
func (r *RootCmd) show() *serpent.Command {
client := new(codersdk.Client)
return &serpent.Cmd{
return &serpent.Command{
Use: "show <workspace>",
Short: "Display details of a workspace's resources and agents",
Middleware: serpent.Chain(

View File

@ -18,7 +18,7 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) speedtest() *serpent.Cmd {
func (r *RootCmd) speedtest() *serpent.Command {
var (
direct bool
duration time.Duration
@ -26,7 +26,7 @@ func (r *RootCmd) speedtest() *serpent.Cmd {
pcapFile string
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "speedtest <workspace>",
Short: "Run upload and download tests from your machine to a workspace",

View File

@ -44,7 +44,7 @@ var (
autostopNotifyCountdown = []time.Duration{30 * time.Minute}
)
func (r *RootCmd) ssh() *serpent.Cmd {
func (r *RootCmd) ssh() *serpent.Command {
var (
stdio bool
forwardAgent bool
@ -58,7 +58,7 @@ func (r *RootCmd) ssh() *serpent.Cmd {
disableAutostart bool
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "ssh <workspace>",
Short: "Start a shell into a workspace",

View File

@ -12,11 +12,11 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) start() *serpent.Cmd {
func (r *RootCmd) start() *serpent.Command {
var parameterFlags workspaceParameterFlags
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "start <workspace>",
Short: "Start a workspace",

View File

@ -26,7 +26,7 @@ func initStatterMW(tgt **clistat.Statter, fs afero.Fs) serpent.MiddlewareFunc {
}
}
func (r *RootCmd) stat() *serpent.Cmd {
func (r *RootCmd) stat() *serpent.Command {
var (
st *clistat.Statter
fs = afero.NewReadOnlyFs(afero.NewOsFs())
@ -41,11 +41,11 @@ func (r *RootCmd) stat() *serpent.Cmd {
cliui.JSONFormat(),
)
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "stat",
Short: "Show resource usage for the current workspace.",
Middleware: initStatterMW(&st, fs),
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.statCPU(fs),
r.statMem(fs),
r.statDisk(fs),
@ -130,13 +130,13 @@ func (r *RootCmd) stat() *serpent.Cmd {
return cmd
}
func (*RootCmd) statCPU(fs afero.Fs) *serpent.Cmd {
func (*RootCmd) statCPU(fs afero.Fs) *serpent.Command {
var (
hostArg bool
st *clistat.Statter
formatter = cliui.NewOutputFormatter(cliui.TextFormat(), cliui.JSONFormat())
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "cpu",
Short: "Show CPU usage, in cores.",
Middleware: initStatterMW(&st, fs),
@ -171,14 +171,14 @@ func (*RootCmd) statCPU(fs afero.Fs) *serpent.Cmd {
return cmd
}
func (*RootCmd) statMem(fs afero.Fs) *serpent.Cmd {
func (*RootCmd) statMem(fs afero.Fs) *serpent.Command {
var (
hostArg bool
prefixArg string
st *clistat.Statter
formatter = cliui.NewOutputFormatter(cliui.TextFormat(), cliui.JSONFormat())
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "mem",
Short: "Show memory usage, in gigabytes.",
Middleware: initStatterMW(&st, fs),
@ -225,14 +225,14 @@ func (*RootCmd) statMem(fs afero.Fs) *serpent.Cmd {
return cmd
}
func (*RootCmd) statDisk(fs afero.Fs) *serpent.Cmd {
func (*RootCmd) statDisk(fs afero.Fs) *serpent.Command {
var (
pathArg string
prefixArg string
st *clistat.Statter
formatter = cliui.NewOutputFormatter(cliui.TextFormat(), cliui.JSONFormat())
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "disk",
Short: "Show disk usage, in gigabytes.",
Middleware: initStatterMW(&st, fs),

View File

@ -11,14 +11,14 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) state() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) state() *serpent.Command {
cmd := &serpent.Command{
Use: "state",
Short: "Manually manage Terraform state to fix broken workspaces",
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.statePull(),
r.statePush(),
},
@ -26,10 +26,10 @@ func (r *RootCmd) state() *serpent.Cmd {
return cmd
}
func (r *RootCmd) statePull() *serpent.Cmd {
func (r *RootCmd) statePull() *serpent.Command {
var buildNumber int64
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "pull <workspace> [file]",
Short: "Pull a Terraform state file from a workspace.",
Middleware: serpent.Chain(
@ -84,10 +84,10 @@ func buildNumberOption(n *int64) serpent.Option {
}
}
func (r *RootCmd) statePush() *serpent.Cmd {
func (r *RootCmd) statePush() *serpent.Command {
var buildNumber int64
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "push <workspace> <file>",
Short: "Push a Terraform state file to a workspace.",
Middleware: serpent.Chain(

View File

@ -9,9 +9,9 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) stop() *serpent.Cmd {
func (r *RootCmd) stop() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "stop <workspace>",
Short: "Stop a workspace",

View File

@ -21,25 +21,25 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) support() *serpent.Cmd {
supportCmd := &serpent.Cmd{
func (r *RootCmd) support() *serpent.Command {
supportCmd := &serpent.Command{
Use: "support",
Short: "Commands for troubleshooting issues with a Coder deployment.",
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Hidden: true, // TODO: un-hide once the must-haves from #12160 are completed.
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.supportBundle(),
},
}
return supportCmd
}
func (r *RootCmd) supportBundle() *serpent.Cmd {
func (r *RootCmd) supportBundle() *serpent.Command {
var outputPath string
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "bundle <workspace> [<agent>]",
Short: "Generate a support bundle to troubleshoot issues connecting to a workspace.",
Long: `This command generates a file containing detailed troubleshooting information about the Coder deployment and workspace connections. You must specify a single workspace (and optionally an agent name).`,

View File

@ -16,7 +16,7 @@ import (
"github.com/coder/coder/v2/codersdk"
)
func (r *RootCmd) templateCreate() *serpent.Cmd {
func (r *RootCmd) templateCreate() *serpent.Command {
var (
provisioner string
provisionerTags []string
@ -34,7 +34,7 @@ func (r *RootCmd) templateCreate() *serpent.Cmd {
uploadFlags templateUploadFlags
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "create [name]",
Short: "DEPRECATED: Create a template from the current directory or as specified by flag",
Middleware: serpent.Chain(

View File

@ -14,9 +14,9 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) templateDelete() *serpent.Cmd {
func (r *RootCmd) templateDelete() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "delete [name...]",
Short: "Delete templates",
Middleware: serpent.Chain(

View File

@ -15,7 +15,7 @@ import (
"github.com/coder/coder/v2/codersdk"
)
func (r *RootCmd) templateEdit() *serpent.Cmd {
func (r *RootCmd) templateEdit() *serpent.Command {
const deprecatedFlagName = "deprecated"
var (
name string
@ -40,7 +40,7 @@ func (r *RootCmd) templateEdit() *serpent.Cmd {
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "edit <template>",
Middleware: serpent.Chain(
serpent.RequireNArgs(1),

View File

@ -20,7 +20,7 @@ import (
"github.com/coder/serpent"
)
func (*RootCmd) templateInit() *serpent.Cmd {
func (*RootCmd) templateInit() *serpent.Command {
var templateID string
exampleList, err := examples.List()
if err != nil {
@ -32,7 +32,7 @@ func (*RootCmd) templateInit() *serpent.Cmd {
templateIDs = append(templateIDs, ex.ID)
}
sort.Strings(templateIDs)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "init [directory]",
Short: "Get started with a templated template.",
Middleware: serpent.RequireRangeArgs(0, 1),

View File

@ -10,14 +10,14 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) templateList() *serpent.Cmd {
func (r *RootCmd) templateList() *serpent.Command {
formatter := cliui.NewOutputFormatter(
cliui.TableFormat([]templateTableRow{}, []string{"name", "last updated", "used by"}),
cliui.JSONFormat(),
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "list",
Short: "List all the templates available for the organization",
Aliases: []string{"ls"},

View File

@ -15,7 +15,7 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) templatePull() *serpent.Cmd {
func (r *RootCmd) templatePull() *serpent.Command {
var (
tarMode bool
zipMode bool
@ -23,7 +23,7 @@ func (r *RootCmd) templatePull() *serpent.Cmd {
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "pull <name> [destination]",
Short: "Download the active, latest, or specified version of a template to a path.",
Middleware: serpent.Chain(

View File

@ -23,7 +23,7 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) templatePush() *serpent.Cmd {
func (r *RootCmd) templatePush() *serpent.Command {
var (
versionName string
provisioner string
@ -36,7 +36,7 @@ func (r *RootCmd) templatePush() *serpent.Cmd {
activate bool
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "push [template]",
Short: "Create or update a template from the current directory or as specified by flag",
Middleware: serpent.Chain(

View File

@ -12,8 +12,8 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) templates() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) templates() *serpent.Command {
cmd := &serpent.Command{
Use: "templates",
Short: "Manage templates",
Long: "Templates are written in standard Terraform and describe the infrastructure for workspaces\n" + formatExamples(
@ -30,7 +30,7 @@ func (r *RootCmd) templates() *serpent.Cmd {
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.templateCreate(),
r.templateEdit(),
r.templateInit(),

View File

@ -14,16 +14,16 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) unarchiveTemplateVersion() *serpent.Cmd {
func (r *RootCmd) unarchiveTemplateVersion() *serpent.Command {
return r.setArchiveTemplateVersion(false)
}
func (r *RootCmd) archiveTemplateVersion() *serpent.Cmd {
func (r *RootCmd) archiveTemplateVersion() *serpent.Command {
return r.setArchiveTemplateVersion(true)
}
//nolint:revive
func (r *RootCmd) setArchiveTemplateVersion(archive bool) *serpent.Cmd {
func (r *RootCmd) setArchiveTemplateVersion(archive bool) *serpent.Command {
presentVerb := "archive"
pastVerb := "archived"
if !archive {
@ -32,7 +32,7 @@ func (r *RootCmd) setArchiveTemplateVersion(archive bool) *serpent.Cmd {
}
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: presentVerb + " <template-name> [template-version-names...] ",
Short: strings.ToUpper(string(presentVerb[0])) + presentVerb[1:] + " a template version(s).",
Middleware: serpent.Chain(
@ -96,10 +96,10 @@ func (r *RootCmd) setArchiveTemplateVersion(archive bool) *serpent.Cmd {
return cmd
}
func (r *RootCmd) archiveTemplateVersions() *serpent.Cmd {
func (r *RootCmd) archiveTemplateVersions() *serpent.Command {
var all serpent.Bool
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "archive [template-name...] ",
Short: "Archive unused or failed template versions from a given template(s)",
Middleware: serpent.Chain(

View File

@ -14,8 +14,8 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) templateVersions() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) templateVersions() *serpent.Command {
cmd := &serpent.Command{
Use: "versions",
Short: "Manage different versions of the specified template",
Aliases: []string{"version"},
@ -28,7 +28,7 @@ func (r *RootCmd) templateVersions() *serpent.Cmd {
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.templateVersionsList(),
r.archiveTemplateVersion(),
r.unarchiveTemplateVersion(),
@ -38,7 +38,7 @@ func (r *RootCmd) templateVersions() *serpent.Cmd {
return cmd
}
func (r *RootCmd) templateVersionsList() *serpent.Cmd {
func (r *RootCmd) templateVersionsList() *serpent.Command {
defaultColumns := []string{
"Name",
"Created At",
@ -54,7 +54,7 @@ func (r *RootCmd) templateVersionsList() *serpent.Cmd {
var includeArchived serpent.Bool
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "list <template>",
Middleware: serpent.Chain(
serpent.RequireNArgs(1),

View File

@ -13,8 +13,8 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) tokens() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) tokens() *serpent.Command {
cmd := &serpent.Command{
Use: "tokens",
Short: "Manage personal access tokens",
Long: "Tokens are used to authenticate automated clients to Coder.\n" + formatExamples(
@ -35,7 +35,7 @@ func (r *RootCmd) tokens() *serpent.Cmd {
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.createToken(),
r.listTokens(),
r.removeToken(),
@ -44,13 +44,13 @@ func (r *RootCmd) tokens() *serpent.Cmd {
return cmd
}
func (r *RootCmd) createToken() *serpent.Cmd {
func (r *RootCmd) createToken() *serpent.Command {
var (
tokenLifetime time.Duration
name string
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "create",
Short: "Create a token",
Middleware: serpent.Chain(
@ -118,7 +118,7 @@ func tokenListRowFromToken(token codersdk.APIKeyWithOwner) tokenListRow {
}
}
func (r *RootCmd) listTokens() *serpent.Cmd {
func (r *RootCmd) listTokens() *serpent.Command {
// we only display the 'owner' column if the --all argument is passed in
defaultCols := []string{"id", "name", "last used", "expires at", "created at"}
if slices.Contains(os.Args, "-a") || slices.Contains(os.Args, "--all") {
@ -135,7 +135,7 @@ func (r *RootCmd) listTokens() *serpent.Cmd {
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List tokens",
@ -187,9 +187,9 @@ func (r *RootCmd) listTokens() *serpent.Cmd {
return cmd
}
func (r *RootCmd) removeToken() *serpent.Cmd {
func (r *RootCmd) removeToken() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "remove <name>",
Aliases: []string{"delete"},
Short: "Delete a token",

View File

@ -9,11 +9,11 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) update() *serpent.Cmd {
func (r *RootCmd) update() *serpent.Command {
var parameterFlags workspaceParameterFlags
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Annotations: workspaceCommand,
Use: "update <workspace>",
Short: "Will update and start a given workspace if it is out of date",

View File

@ -15,7 +15,7 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) userCreate() *serpent.Cmd {
func (r *RootCmd) userCreate() *serpent.Command {
var (
email string
username string
@ -24,7 +24,7 @@ func (r *RootCmd) userCreate() *serpent.Cmd {
loginType string
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "create",
Middleware: serpent.Chain(
serpent.RequireNArgs(0),

View File

@ -11,9 +11,9 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) userDelete() *serpent.Cmd {
func (r *RootCmd) userDelete() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "delete <username|user_id>",
Short: "Delete a user by username or user_id.",
Middleware: serpent.Chain(

View File

@ -13,14 +13,14 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) userList() *serpent.Cmd {
func (r *RootCmd) userList() *serpent.Command {
formatter := cliui.NewOutputFormatter(
cliui.TableFormat([]codersdk.User{}, []string{"username", "email", "created_at", "status"}),
cliui.JSONFormat(),
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "list",
Aliases: []string{"ls"},
Middleware: serpent.Chain(
@ -47,14 +47,14 @@ func (r *RootCmd) userList() *serpent.Cmd {
return cmd
}
func (r *RootCmd) userSingle() *serpent.Cmd {
func (r *RootCmd) userSingle() *serpent.Command {
formatter := cliui.NewOutputFormatter(
&userShowFormat{},
cliui.JSONFormat(),
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "show <username|user_id|'me'>",
Short: "Show a single user. Use 'me' to indicate the currently authenticated user.",
Long: formatExamples(

View File

@ -5,15 +5,15 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) users() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) users() *serpent.Command {
cmd := &serpent.Command{
Short: "Manage users",
Use: "users [subcommand]",
Aliases: []string{"user"},
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.userCreate(),
r.userList(),
r.userSingle(),

View File

@ -14,7 +14,7 @@ import (
)
// createUserStatusCommand sets a user status.
func (r *RootCmd) createUserStatusCommand(sdkStatus codersdk.UserStatus) *serpent.Cmd {
func (r *RootCmd) createUserStatusCommand(sdkStatus codersdk.UserStatus) *serpent.Command {
var verb string
var pastVerb string
var aliases []string
@ -36,7 +36,7 @@ func (r *RootCmd) createUserStatusCommand(sdkStatus codersdk.UserStatus) *serpen
client := new(codersdk.Client)
var columns []string
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: fmt.Sprintf("%s <username|user_id>", verb),
Short: short,
Aliases: aliases,

View File

@ -61,7 +61,7 @@ func defaultVersionInfo() *versionInfo {
}
// version prints the coder version
func (*RootCmd) version(versionInfo func() *versionInfo) *serpent.Cmd {
func (*RootCmd) version(versionInfo func() *versionInfo) *serpent.Command {
var (
formatter = cliui.NewOutputFormatter(
cliui.TextFormat(),
@ -70,7 +70,7 @@ func (*RootCmd) version(versionInfo func() *versionInfo) *serpent.Cmd {
vi = versionInfo()
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "version",
Short: "Show coder version",
Options: serpent.OptionSet{},

View File

@ -32,7 +32,7 @@ import (
// This command needs to remain stable for compatibility with
// various VS Code versions, so it's kept separate from our
// standard SSH command.
func (r *RootCmd) vscodeSSH() *serpent.Cmd {
func (r *RootCmd) vscodeSSH() *serpent.Command {
var (
sessionTokenFile string
urlFile string
@ -41,7 +41,7 @@ func (r *RootCmd) vscodeSSH() *serpent.Cmd {
networkInfoInterval time.Duration
waitEnum string
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
// A SSH config entry is added by the VS Code extension that
// passes %h to ProxyCommand. The prefix of `coder-vscode--`
// is a magical string represented in our VS Code extension.

View File

@ -22,8 +22,8 @@ import (
)
func main() {
var root *serpent.Cmd
root = &serpent.Cmd{
var root *serpent.Command
root = &serpent.Command{
Use: "cliui",
Short: "Used for visually testing UI components for the CLI.",
HelpHandler: func(inv *serpent.Invocation) error {
@ -37,7 +37,7 @@ func main() {
},
}
root.Children = append(root.Children, &serpent.Cmd{
root.Children = append(root.Children, &serpent.Command{
Use: "prompt",
Handler: func(inv *serpent.Invocation) error {
_, err := cliui.Prompt(inv, cliui.PromptOptions{
@ -75,7 +75,7 @@ func main() {
},
})
root.Children = append(root.Children, &serpent.Cmd{
root.Children = append(root.Children, &serpent.Command{
Use: "select",
Handler: func(inv *serpent.Invocation) error {
value, err := cliui.Select(inv, cliui.SelectOptions{
@ -87,7 +87,7 @@ func main() {
},
})
root.Children = append(root.Children, &serpent.Cmd{
root.Children = append(root.Children, &serpent.Command{
Use: "job",
Handler: func(inv *serpent.Invocation) error {
job := codersdk.ProvisionerJob{
@ -173,7 +173,7 @@ func main() {
},
})
root.Children = append(root.Children, &serpent.Cmd{
root.Children = append(root.Children, &serpent.Command{
Use: "agent",
Handler: func(inv *serpent.Invocation) error {
var agent codersdk.WorkspaceAgent
@ -265,7 +265,7 @@ func main() {
},
})
root.Children = append(root.Children, &serpent.Cmd{
root.Children = append(root.Children, &serpent.Command{
Use: "resources",
Handler: func(inv *serpent.Invocation) error {
disconnected := dbtime.Now().Add(-4 * time.Second)
@ -315,7 +315,7 @@ func main() {
},
})
root.Children = append(root.Children, &serpent.Cmd{
root.Children = append(root.Children, &serpent.Command{
Use: "git-auth",
Handler: func(inv *serpent.Invocation) error {
var count atomic.Int32

View File

@ -15,22 +15,22 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) features() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) features() *serpent.Command {
cmd := &serpent.Command{
Short: "List Enterprise features",
Use: "features",
Aliases: []string{"feature"},
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.featuresList(),
},
}
return cmd
}
func (r *RootCmd) featuresList() *serpent.Cmd {
func (r *RootCmd) featuresList() *serpent.Command {
var (
featureColumns = []string{"Name", "Entitlement", "Enabled", "Limit", "Actual"}
columns []string
@ -38,7 +38,7 @@ func (r *RootCmd) featuresList() *serpent.Cmd {
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "list",
Aliases: []string{"ls"},
Middleware: serpent.Chain(

View File

@ -12,14 +12,14 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) groupCreate() *serpent.Cmd {
func (r *RootCmd) groupCreate() *serpent.Command {
var (
avatarURL string
displayName string
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "create <name>",
Short: "Create a user group",
Middleware: serpent.Chain(

View File

@ -12,9 +12,9 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) groupDelete() *serpent.Cmd {
func (r *RootCmd) groupDelete() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "delete <name>",
Short: "Delete a user group",
Middleware: serpent.Chain(

View File

@ -15,7 +15,7 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) groupEdit() *serpent.Cmd {
func (r *RootCmd) groupEdit() *serpent.Command {
var (
avatarURL string
name string
@ -24,7 +24,7 @@ func (r *RootCmd) groupEdit() *serpent.Cmd {
rmUsers []string
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "edit <name>",
Short: "Edit a user group",
Middleware: serpent.Chain(

View File

@ -13,14 +13,14 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) groupList() *serpent.Cmd {
func (r *RootCmd) groupList() *serpent.Command {
formatter := cliui.NewOutputFormatter(
cliui.TableFormat([]groupTableRow{}, nil),
cliui.JSONFormat(),
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "list",
Short: "List user groups",
Middleware: serpent.Chain(

View File

@ -2,15 +2,15 @@ package cli
import "github.com/coder/serpent"
func (r *RootCmd) groups() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) groups() *serpent.Command {
cmd := &serpent.Command{
Use: "groups",
Short: "Manage groups",
Aliases: []string{"group"},
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.groupCreate(),
r.groupList(),
r.groupEdit(),

View File

@ -20,15 +20,15 @@ import (
var jwtRegexp = regexp.MustCompile(`^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$`)
func (r *RootCmd) licenses() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) licenses() *serpent.Command {
cmd := &serpent.Command{
Short: "Add, delete, and list licenses",
Use: "licenses",
Aliases: []string{"license"},
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.licenseAdd(),
r.licensesList(),
r.licenseDelete(),
@ -37,14 +37,14 @@ func (r *RootCmd) licenses() *serpent.Cmd {
return cmd
}
func (r *RootCmd) licenseAdd() *serpent.Cmd {
func (r *RootCmd) licenseAdd() *serpent.Command {
var (
filename string
license string
debug bool
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "add [-f file | -l license]",
Short: "Add license to Coder deployment",
Middleware: serpent.Chain(
@ -136,7 +136,7 @@ func validJWT(s string) error {
return xerrors.New("Invalid license")
}
func (r *RootCmd) licensesList() *serpent.Cmd {
func (r *RootCmd) licensesList() *serpent.Command {
type tableLicense struct {
ID int32 `table:"id,default_sort"`
UUID uuid.UUID `table:"uuid" format:"uuid"`
@ -208,7 +208,7 @@ func (r *RootCmd) licensesList() *serpent.Cmd {
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "list",
Short: "List licenses (including expired)",
Aliases: []string{"ls"},
@ -239,9 +239,9 @@ func (r *RootCmd) licensesList() *serpent.Cmd {
return cmd
}
func (r *RootCmd) licenseDelete() *serpent.Cmd {
func (r *RootCmd) licenseDelete() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "delete <id>",
Short: "Delete license by ID",
Aliases: []string{"del"},

View File

@ -32,14 +32,14 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) provisionerDaemons() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) provisionerDaemons() *serpent.Command {
cmd := &serpent.Command{
Use: "provisionerd",
Short: "Manage provisioner daemons",
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.provisionerDaemonStart(),
},
}
@ -57,7 +57,7 @@ func validateProvisionerDaemonName(name string) error {
return nil
}
func (r *RootCmd) provisionerDaemonStart() *serpent.Cmd {
func (r *RootCmd) provisionerDaemonStart() *serpent.Command {
var (
cacheDir string
logHuman string
@ -75,7 +75,7 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Cmd {
prometheusAddress string
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "start",
Short: "Run a provisioner daemon",
Middleware: serpent.Chain(

View File

@ -7,8 +7,8 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) provisionerDaemons() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) provisionerDaemons() *serpent.Command {
cmd := &serpent.Command{
Use: "provisionerd",
Short: "Manage provisioner daemons",
// We accept RawArgs so all commands and flags are accepted.

View File

@ -44,7 +44,7 @@ func (c *closers) Add(f func()) {
*c = append(*c, f)
}
func (r *RootCmd) proxyServer() *serpent.Cmd {
func (r *RootCmd) proxyServer() *serpent.Command {
var (
cfg = new(codersdk.DeploymentValues)
// Filter options for only relevant ones.
@ -102,7 +102,7 @@ func (r *RootCmd) proxyServer() *serpent.Cmd {
},
)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "server",
Short: "Start a workspace proxy server",
Options: opts,

View File

@ -7,8 +7,8 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) proxyServer() *serpent.Cmd {
root := &serpent.Cmd{
func (r *RootCmd) proxyServer() *serpent.Command {
root := &serpent.Command{
Use: "server",
Short: "Start a workspace proxy server",
Aliases: []string{},

View File

@ -9,8 +9,8 @@ type RootCmd struct {
cli.RootCmd
}
func (r *RootCmd) enterpriseOnly() []*serpent.Cmd {
return []*serpent.Cmd{
func (r *RootCmd) enterpriseOnly() []*serpent.Command {
return []*serpent.Command{
r.Server(nil),
r.workspaceProxy(),
r.features(),
@ -20,7 +20,7 @@ func (r *RootCmd) enterpriseOnly() []*serpent.Cmd {
}
}
func (r *RootCmd) EnterpriseSubcommands() []*serpent.Cmd {
func (r *RootCmd) EnterpriseSubcommands() []*serpent.Command {
all := append(r.Core(), r.enterpriseOnly()...)
return all
}

View File

@ -13,7 +13,7 @@ import (
//nolint:tparallel,paralleltest
func TestEnterpriseCommandHelp(t *testing.T) {
// Only test the enterprise commands
getCmds := func(t *testing.T) *serpent.Cmd {
getCmds := func(t *testing.T) *serpent.Command {
// Must return a fresh instance of cmds each time.
t.Helper()
var root cli.RootCmd

View File

@ -28,7 +28,7 @@ import (
agplcoderd "github.com/coder/coder/v2/coderd"
)
func (r *RootCmd) Server(_ func()) *serpent.Cmd {
func (r *RootCmd) Server(_ func()) *serpent.Command {
cmd := r.RootCmd.Server(func(ctx context.Context, options *agplcoderd.Options) (*agplcoderd.API, io.Closer, error) {
if options.DeploymentValues.DERP.Server.RelayURL.String() != "" {
_, err := url.Parse(options.DeploymentValues.DERP.Server.RelayURL.String())

View File

@ -18,8 +18,8 @@ import (
"golang.org/x/xerrors"
)
func (r *RootCmd) dbcryptCmd() *serpent.Cmd {
dbcryptCmd := &serpent.Cmd{
func (r *RootCmd) dbcryptCmd() *serpent.Command {
dbcryptCmd := &serpent.Command{
Use: "dbcrypt",
Short: "Manage database encryption.",
Handler: func(inv *serpent.Invocation) error {
@ -34,9 +34,9 @@ func (r *RootCmd) dbcryptCmd() *serpent.Cmd {
return dbcryptCmd
}
func (*RootCmd) dbcryptRotateCmd() *serpent.Cmd {
func (*RootCmd) dbcryptRotateCmd() *serpent.Command {
var flags rotateFlags
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "rotate",
Short: "Rotate database encryption keys.",
Handler: func(inv *serpent.Invocation) error {
@ -107,9 +107,9 @@ func (*RootCmd) dbcryptRotateCmd() *serpent.Cmd {
return cmd
}
func (*RootCmd) dbcryptDecryptCmd() *serpent.Cmd {
func (*RootCmd) dbcryptDecryptCmd() *serpent.Command {
var flags decryptFlags
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "decrypt",
Short: "Decrypt a previously encrypted database.",
Handler: func(inv *serpent.Invocation) error {
@ -164,9 +164,9 @@ func (*RootCmd) dbcryptDecryptCmd() *serpent.Cmd {
return cmd
}
func (*RootCmd) dbcryptDeleteCmd() *serpent.Cmd {
func (*RootCmd) dbcryptDeleteCmd() *serpent.Command {
var flags deleteFlags
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "delete",
Short: "Delete all encrypted data from the database. THIS IS A DESTRUCTIVE OPERATION.",
Handler: func(inv *serpent.Invocation) error {

View File

@ -15,8 +15,8 @@ import (
"github.com/coder/serpent"
)
func (r *RootCmd) workspaceProxy() *serpent.Cmd {
cmd := &serpent.Cmd{
func (r *RootCmd) workspaceProxy() *serpent.Command {
cmd := &serpent.Command{
Use: "workspace-proxy",
Short: "Workspace proxies provide low-latency experiences for geo-distributed teams.",
Long: "Workspace proxies provide low-latency experiences for geo-distributed teams. " +
@ -27,7 +27,7 @@ func (r *RootCmd) workspaceProxy() *serpent.Cmd {
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Children: []*serpent.Cmd{
Children: []*serpent.Command{
r.proxyServer(),
r.createProxy(),
r.deleteProxy(),
@ -40,10 +40,10 @@ func (r *RootCmd) workspaceProxy() *serpent.Cmd {
return cmd
}
func (r *RootCmd) regenerateProxyToken() *serpent.Cmd {
func (r *RootCmd) regenerateProxyToken() *serpent.Command {
formatter := newUpdateProxyResponseFormatter()
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "regenerate-token <name|id>",
Short: "Regenerate a workspace proxy authentication token. " +
"This will invalidate the existing authentication token.",
@ -86,7 +86,7 @@ func (r *RootCmd) regenerateProxyToken() *serpent.Cmd {
return cmd
}
func (r *RootCmd) patchProxy() *serpent.Cmd {
func (r *RootCmd) patchProxy() *serpent.Command {
var (
proxyName string
displayName string
@ -113,7 +113,7 @@ func (r *RootCmd) patchProxy() *serpent.Cmd {
)
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "edit <name|id>",
Short: "Edit a workspace proxy",
Middleware: serpent.Chain(
@ -186,9 +186,9 @@ func (r *RootCmd) patchProxy() *serpent.Cmd {
return cmd
}
func (r *RootCmd) deleteProxy() *serpent.Cmd {
func (r *RootCmd) deleteProxy() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "delete <name|id>",
Short: "Delete a workspace proxy",
Options: serpent.OptionSet{
@ -229,7 +229,7 @@ func (r *RootCmd) deleteProxy() *serpent.Cmd {
return cmd
}
func (r *RootCmd) createProxy() *serpent.Cmd {
func (r *RootCmd) createProxy() *serpent.Command {
var (
proxyName string
displayName string
@ -245,7 +245,7 @@ func (r *RootCmd) createProxy() *serpent.Cmd {
}
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "create",
Short: "Create a workspace proxy",
Middleware: serpent.Chain(
@ -335,7 +335,7 @@ func (r *RootCmd) createProxy() *serpent.Cmd {
return cmd
}
func (r *RootCmd) listProxies() *serpent.Cmd {
func (r *RootCmd) listProxies() *serpent.Command {
formatter := cliui.NewOutputFormatter(
cliui.TableFormat([]codersdk.WorkspaceProxy{}, []string{"name", "url", "proxy status"}),
cliui.JSONFormat(),
@ -363,7 +363,7 @@ func (r *RootCmd) listProxies() *serpent.Cmd {
)
client := new(codersdk.Client)
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "ls",
Aliases: []string{"list"},
Short: "List all workspace proxies",

2
go.mod
View File

@ -208,7 +208,7 @@ require go.uber.org/mock v0.4.0
require (
github.com/benbjohnson/clock v1.3.5
github.com/coder/serpent v0.4.0
github.com/coder/serpent v0.4.1-0.20240315163851-a0148c87ea3f
github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47
)

2
go.sum
View File

@ -216,6 +216,8 @@ github.com/coder/retry v1.5.1 h1:iWu8YnD8YqHs3XwqrqsjoBTAVqT9ml6z9ViJ2wlMiqc=
github.com/coder/retry v1.5.1/go.mod h1:blHMk9vs6LkoRT9ZHyuZo360cufXEhrxqvEzeMtRGoY=
github.com/coder/serpent v0.4.0 h1:L/itwnCxfhLutxQ2mScP3tH1ro8z8+Kc/iKKyZZxEMk=
github.com/coder/serpent v0.4.0/go.mod h1:Wud83ikZF/ulbdMcEMAwqvkEIQx7+l47+ef69M/arAA=
github.com/coder/serpent v0.4.1-0.20240315163851-a0148c87ea3f h1:nqJ/Mvm+nLI22n5BIYhvSmTZ6CD+MRo/aGVZwVQgr1k=
github.com/coder/serpent v0.4.1-0.20240315163851-a0148c87ea3f/go.mod h1:REkJ5ZFHQUWFTPLExhXYZ1CaHFjxvGNRlLXLdsI08YA=
github.com/coder/ssh v0.0.0-20231128192721-70855dedb788 h1:YoUSJ19E8AtuUFVYBpXuOD6a/zVP3rcxezNsoDseTUw=
github.com/coder/ssh v0.0.0-20231128192721-70855dedb788/go.mod h1:aGQbuCLyhRLMzZF067xc84Lh7JDs1FKwCmF1Crl9dxQ=
github.com/coder/tailscale v1.1.1-0.20240214140224-3788ab894ba1 h1:A7dZHNidAVH6Kxn5D3hTEH+iRO8slnM0aRer6/cxlyE=

View File

@ -59,7 +59,7 @@ func TestPtytest(t *testing.T) {
tt := tt
// nolint:paralleltest // Avoid parallel test to more easily identify the issue.
t.Run(tt.name, func(t *testing.T) {
cmd := &serpent.Cmd{
cmd := &serpent.Command{
Use: "test",
Handler: func(inv *serpent.Invocation) error {
fmt.Fprint(inv.Stdout, tt.output)

View File

@ -25,8 +25,8 @@ var commandTemplate *template.Template
func init() {
commandTemplate = template.Must(
template.New("command.tpl").Funcs(template.FuncMap{
"visibleSubcommands": func(cmd *serpent.Cmd) []*serpent.Cmd {
var visible []*serpent.Cmd
"visibleSubcommands": func(cmd *serpent.Command) []*serpent.Command {
var visible []*serpent.Command
for _, sub := range cmd.Children {
if sub.Hidden {
continue
@ -35,7 +35,7 @@ func init() {
}
return visible
},
"visibleOptions": func(cmd *serpent.Cmd) []serpent.Option {
"visibleOptions": func(cmd *serpent.Command) []serpent.Option {
var visible []serpent.Option
for _, opt := range cmd.Options {
if opt.Hidden {
@ -45,7 +45,7 @@ func init() {
}
return visible
},
"atRoot": func(cmd *serpent.Cmd) bool {
"atRoot": func(cmd *serpent.Command) bool {
return cmd.FullName() == "coder"
},
"newLinesToBr": func(s string) string {
@ -54,7 +54,7 @@ func init() {
"wrapCode": func(s string) string {
return fmt.Sprintf("<code>%s</code>", s)
},
"commandURI": func(cmd *serpent.Cmd) string {
"commandURI": func(cmd *serpent.Command) string {
return fmtDocFilename(cmd)
},
"fullName": fullName,
@ -67,14 +67,14 @@ func init() {
)
}
func fullName(cmd *serpent.Cmd) string {
func fullName(cmd *serpent.Command) string {
if cmd.FullName() == "coder" {
return "coder"
}
return strings.TrimPrefix(cmd.FullName(), "coder ")
}
func fmtDocFilename(cmd *serpent.Cmd) string {
func fmtDocFilename(cmd *serpent.Command) string {
if cmd.FullName() == "coder" {
// Special case for index.
return "../cli.md"
@ -83,7 +83,7 @@ func fmtDocFilename(cmd *serpent.Cmd) string {
return fmt.Sprintf("%s.md", name)
}
func writeCommand(w io.Writer, cmd *serpent.Cmd) error {
func writeCommand(w io.Writer, cmd *serpent.Command) error {
var b strings.Builder
err := commandTemplate.Execute(&b, cmd)
if err != nil {
@ -112,7 +112,7 @@ func writeCommand(w io.Writer, cmd *serpent.Cmd) error {
return err
}
func genTree(dir string, cmd *serpent.Cmd, wroteLog map[string]*serpent.Cmd) error {
func genTree(dir string, cmd *serpent.Command, wroteLog map[string]*serpent.Command) error {
if cmd.Hidden {
return nil
}

View File

@ -83,7 +83,7 @@ func main() {
root := (&cli.RootCmd{})
// wroteMap indexes file paths to commands.
wroteMap := make(map[string]*serpent.Cmd)
wroteMap := make(map[string]*serpent.Command)
var (
docsDir = filepath.Join(workdir, "docs")