diff --git a/Makefile b/Makefile index 684ef9ef8f..920c6b6816 100644 --- a/Makefile +++ b/Makefile @@ -525,13 +525,17 @@ coderd/apidoc/swagger.json: $(shell find ./scripts/apidocgen $(FIND_EXCLUSIONS) ./scripts/apidocgen/generate.sh yarn run --cwd=site format:write:only ../docs/api ../docs/manifest.json ../coderd/apidoc/swagger.json -update-golden-files: cli/testdata/.gen-golden helm/tests/testdata/.gen-golden scripts/ci-report/testdata/.gen-golden +update-golden-files: cli/testdata/.gen-golden helm/tests/testdata/.gen-golden scripts/ci-report/testdata/.gen-golden enterprise/cli/testdata/.gen-golden .PHONY: update-golden-files cli/testdata/.gen-golden: $(wildcard cli/testdata/*.golden) $(wildcard cli/*.tpl) $(GO_SRC_FILES) go test ./cli -run="Test(CommandHelp|ServerYAML)" -update touch "$@" +enterprise/cli/testdata/.gen-golden: $(wildcard enterprise/cli/testdata/*.golden) $(wildcard cli/*.tpl) $(GO_SRC_FILES) + go test ./enterprise/cli -run="TestEnterpriseCommandHelp" -update + touch "$@" + helm/tests/testdata/.gen-golden: $(wildcard helm/tests/testdata/*.yaml) $(wildcard helm/tests/testdata/*.golden) $(GO_SRC_FILES) go test ./helm/tests -run=TestUpdateGoldenFiles -update touch "$@" diff --git a/cli/clitest/golden.go b/cli/clitest/golden.go new file mode 100644 index 0000000000..ba445efcea --- /dev/null +++ b/cli/clitest/golden.go @@ -0,0 +1,222 @@ +package clitest + +import ( + "bytes" + "context" + "flag" + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + "testing" + + "github.com/charmbracelet/lipgloss" + "github.com/muesli/termenv" + "github.com/stretchr/testify/require" + + "github.com/coder/coder/cli/clibase" + "github.com/coder/coder/cli/config" + "github.com/coder/coder/coderd/coderdtest" + "github.com/coder/coder/coderd/database/dbtestutil" + "github.com/coder/coder/codersdk" + "github.com/coder/coder/testutil" +) + +// UpdateGoldenFiles indicates golden files should be updated. +// To update the golden files: +// make update-golden-files +var UpdateGoldenFiles = flag.Bool("update", false, "update .golden files") + +var timestampRegex = regexp.MustCompile(`(?i)\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d+)?Z`) + +type CommandHelpCase struct { + Name string + Cmd []string +} + +func DefaultCases() []CommandHelpCase { + return []CommandHelpCase{ + { + Name: "coder --help", + Cmd: []string{"--help"}, + }, + { + Name: "coder server --help", + Cmd: []string{"server", "--help"}, + }, + } +} + +// TestCommandHelp will test the help output of the given commands +// using golden files. +// +//nolint:tparallel,paralleltest +func TestCommandHelp(t *testing.T, getRoot func(t *testing.T) *clibase.Cmd, cases []CommandHelpCase) { + ogColorProfile := lipgloss.ColorProfile() + // ANSI256 escape codes are far easier for humans to parse in a diff, + // but TrueColor is probably more popular with modern terminals. + lipgloss.SetColorProfile(termenv.ANSI) + t.Cleanup(func() { + lipgloss.SetColorProfile(ogColorProfile) + }) + rootClient, replacements := prepareTestData(t) + + root := getRoot(t) + +ExtractCommandPathsLoop: + for _, cp := range extractVisibleCommandPaths(nil, root.Children) { + name := fmt.Sprintf("coder %s --help", strings.Join(cp, " ")) + cmd := append(cp, "--help") + for _, tt := range cases { + if tt.Name == name { + continue ExtractCommandPathsLoop + } + } + cases = append(cases, CommandHelpCase{Name: name, Cmd: cmd}) + } + + for _, tt := range cases { + tt := tt + t.Run(tt.Name, func(t *testing.T) { + t.Parallel() + ctx := testutil.Context(t, testutil.WaitLong) + + var outBuf bytes.Buffer + + caseCmd := getRoot(t) + + inv, cfg := NewWithCommand(t, caseCmd, tt.Cmd...) + inv.Stderr = &outBuf + inv.Stdout = &outBuf + inv.Environ.Set("CODER_URL", rootClient.URL.String()) + inv.Environ.Set("CODER_SESSION_TOKEN", rootClient.SessionToken()) + inv.Environ.Set("CODER_CACHE_DIRECTORY", "~/.cache") + + SetupConfig(t, rootClient, cfg) + + StartWithWaiter(t, inv.WithContext(ctx)).RequireSuccess() + + actual := outBuf.Bytes() + if len(actual) == 0 { + t.Fatal("no output") + } + + for k, v := range replacements { + actual = bytes.ReplaceAll(actual, []byte(k), []byte(v)) + } + + actual = NormalizeGoldenFile(t, actual) + goldenPath := filepath.Join("testdata", strings.Replace(tt.Name, " ", "_", -1)+".golden") + if *UpdateGoldenFiles { + t.Logf("update golden file for: %q: %s", tt.Name, goldenPath) + err := os.WriteFile(goldenPath, actual, 0o600) + require.NoError(t, err, "update golden file") + } + + expected, err := os.ReadFile(goldenPath) + require.NoError(t, err, "read golden file, run \"make update-golden-files\" and commit the changes") + + expected = NormalizeGoldenFile(t, expected) + require.Equal( + t, string(expected), string(actual), + "golden file mismatch: %s, run \"make update-golden-files\", verify and commit the changes", + goldenPath, + ) + }) + } +} + +// NormalizeGoldenFile replaces any strings that are system or timing dependent +// with a placeholder so that the golden files can be compared with a simple +// equality check. +func NormalizeGoldenFile(t *testing.T, byt []byte) []byte { + // Replace any timestamps with a placeholder. + byt = timestampRegex.ReplaceAll(byt, []byte("[timestamp]")) + + homeDir, err := os.UserHomeDir() + require.NoError(t, err) + + configDir := config.DefaultDir() + byt = bytes.ReplaceAll(byt, []byte(configDir), []byte("~/.config/coderv2")) + + byt = bytes.ReplaceAll(byt, []byte(codersdk.DefaultCacheDir()), []byte("[cache dir]")) + + // The home directory changes depending on the test environment. + byt = bytes.ReplaceAll(byt, []byte(homeDir), []byte("~")) + for _, r := range []struct { + old string + new string + }{ + {"\r\n", "\n"}, + {`~\.cache\coder`, "~/.cache/coder"}, + {`C:\Users\RUNNER~1\AppData\Local\Temp`, "/tmp"}, + {os.TempDir(), "/tmp"}, + } { + byt = bytes.ReplaceAll(byt, []byte(r.old), []byte(r.new)) + } + return byt +} + +func extractVisibleCommandPaths(cmdPath []string, cmds []*clibase.Cmd) [][]string { + var cmdPaths [][]string + for _, c := range cmds { + if c.Hidden { + continue + } + cmdPath := append(cmdPath, c.Name()) + cmdPaths = append(cmdPaths, cmdPath) + cmdPaths = append(cmdPaths, extractVisibleCommandPaths(cmdPath, c.Children)...) + } + return cmdPaths +} + +func prepareTestData(t *testing.T) (*codersdk.Client, map[string]string) { + t.Helper() + + ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) + defer cancel() + + db, pubsub := dbtestutil.NewDB(t) + rootClient := coderdtest.New(t, &coderdtest.Options{ + Database: db, + Pubsub: pubsub, + IncludeProvisionerDaemon: true, + }) + firstUser := coderdtest.CreateFirstUser(t, rootClient) + secondUser, err := rootClient.CreateUser(ctx, codersdk.CreateUserRequest{ + Email: "testuser2@coder.com", + Username: "testuser2", + Password: coderdtest.FirstUserParams.Password, + OrganizationID: firstUser.OrganizationID, + }) + require.NoError(t, err) + version := coderdtest.CreateTemplateVersion(t, rootClient, firstUser.OrganizationID, nil) + version = coderdtest.AwaitTemplateVersionJob(t, rootClient, version.ID) + template := coderdtest.CreateTemplate(t, rootClient, firstUser.OrganizationID, version.ID, func(req *codersdk.CreateTemplateRequest) { + req.Name = "test-template" + }) + workspace := coderdtest.CreateWorkspace(t, rootClient, firstUser.OrganizationID, template.ID, func(req *codersdk.CreateWorkspaceRequest) { + req.Name = "test-workspace" + }) + workspaceBuild := coderdtest.AwaitWorkspaceBuildJob(t, rootClient, workspace.LatestBuild.ID) + + replacements := map[string]string{ + firstUser.UserID.String(): "[first user ID]", + secondUser.ID.String(): "[second user ID]", + firstUser.OrganizationID.String(): "[first org ID]", + version.ID.String(): "[version ID]", + version.Name: "[version name]", + version.Job.ID.String(): "[version job ID]", + version.Job.FileID.String(): "[version file ID]", + version.Job.WorkerID.String(): "[version worker ID]", + template.ID.String(): "[template ID]", + workspace.ID.String(): "[workspace ID]", + workspaceBuild.ID.String(): "[workspace build ID]", + workspaceBuild.Job.ID.String(): "[workspace build job ID]", + workspaceBuild.Job.FileID.String(): "[workspace build file ID]", + workspaceBuild.Job.WorkerID.String(): "[workspace build worker ID]", + } + + return rootClient, replacements +} diff --git a/cli/root_test.go b/cli/root_test.go index 7edc46f17c..34fbdf2dad 100644 --- a/cli/root_test.go +++ b/cli/root_test.go @@ -2,235 +2,47 @@ package cli_test import ( "bytes" - "context" - "flag" - "fmt" "net/http" "net/http/httptest" - "os" - "path/filepath" - "regexp" - "strings" "testing" - "github.com/charmbracelet/lipgloss" - "github.com/muesli/termenv" + "github.com/coder/coder/cli/clibase" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/coder/coder/buildinfo" "github.com/coder/coder/cli" - "github.com/coder/coder/cli/clibase" "github.com/coder/coder/cli/clitest" - "github.com/coder/coder/cli/config" - "github.com/coder/coder/coderd/coderdtest" - "github.com/coder/coder/coderd/database/dbtestutil" - "github.com/coder/coder/codersdk" - "github.com/coder/coder/testutil" ) -// To update the golden files: -// make update-golden-files -var updateGoldenFiles = flag.Bool("update", false, "update .golden files") - -var timestampRegex = regexp.MustCompile(`(?i)\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d+)?Z`) - -// We need to override the global color profile. -// //nolint:tparallel,paralleltest func TestCommandHelp(t *testing.T) { - ogColorProfile := lipgloss.ColorProfile() - // ANSI256 escape codes are far easier for humans to parse in a diff, - // but TrueColor is probably more popular with modern terminals. - lipgloss.SetColorProfile(termenv.ANSI) - t.Cleanup(func() { - lipgloss.SetColorProfile(ogColorProfile) - }) - rootClient, replacements := prepareTestData(t) + // Test with AGPL commands + getCmds := func(t *testing.T) *clibase.Cmd { + // Must return a fresh instance of cmds each time. - type testCase struct { - name string - cmd []string + t.Helper() + var root cli.RootCmd + rootCmd, err := root.Command(root.AGPL()) + require.NoError(t, err) + + return rootCmd } - tests := []testCase{ - { - name: "coder --help", - cmd: []string{"--help"}, + clitest.TestCommandHelp(t, getCmds, append(clitest.DefaultCases(), + clitest.CommandHelpCase{ + Name: "coder agent --help", + Cmd: []string{"agent", "--help"}, }, - { - name: "coder server --help", - cmd: []string{"server", "--help"}, + clitest.CommandHelpCase{ + Name: "coder list --output json", + Cmd: []string{"list", "--output", "json"}, }, - { - name: "coder agent --help", - cmd: []string{"agent", "--help"}, + clitest.CommandHelpCase{ + Name: "coder users list --output json", + Cmd: []string{"users", "list", "--output", "json"}, }, - { - name: "coder list --output json", - cmd: []string{"list", "--output", "json"}, - }, - { - name: "coder users list --output json", - cmd: []string{"users", "list", "--output", "json"}, - }, - } - - rootCmd := new(cli.RootCmd) - root, err := rootCmd.Command(rootCmd.AGPL()) - require.NoError(t, err) - -ExtractCommandPathsLoop: - for _, cp := range extractVisibleCommandPaths(nil, root.Children) { - name := fmt.Sprintf("coder %s --help", strings.Join(cp, " ")) - cmd := append(cp, "--help") - for _, tt := range tests { - if tt.name == name { - continue ExtractCommandPathsLoop - } - } - tests = append(tests, testCase{name: name, cmd: cmd}) - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - ctx := testutil.Context(t, testutil.WaitLong) - - var outBuf bytes.Buffer - inv, cfg := clitest.New(t, tt.cmd...) - inv.Stderr = &outBuf - inv.Stdout = &outBuf - inv.Environ.Set("CODER_URL", rootClient.URL.String()) - inv.Environ.Set("CODER_SESSION_TOKEN", rootClient.SessionToken()) - inv.Environ.Set("CODER_CACHE_DIRECTORY", "~/.cache") - - clitest.SetupConfig(t, rootClient, cfg) - - clitest.StartWithWaiter(t, inv.WithContext(ctx)).RequireSuccess() - - actual := outBuf.Bytes() - if len(actual) == 0 { - t.Fatal("no output") - } - - for k, v := range replacements { - actual = bytes.ReplaceAll(actual, []byte(k), []byte(v)) - } - - actual = normalizeGoldenFile(t, actual) - goldenPath := filepath.Join("testdata", strings.Replace(tt.name, " ", "_", -1)+".golden") - if *updateGoldenFiles { - t.Logf("update golden file for: %q: %s", tt.name, goldenPath) - err = os.WriteFile(goldenPath, actual, 0o600) - require.NoError(t, err, "update golden file") - } - - expected, err := os.ReadFile(goldenPath) - require.NoError(t, err, "read golden file, run \"make update-golden-files\" and commit the changes") - - expected = normalizeGoldenFile(t, expected) - require.Equal( - t, string(expected), string(actual), - "golden file mismatch: %s, run \"make update-golden-files\", verify and commit the changes", - goldenPath, - ) - }) - } -} - -// normalizeGoldenFiles replaces any strings that are system or timing dependent -// with a placeholder so that the golden files can be compared with a simple -// equality check. -func normalizeGoldenFile(t *testing.T, byt []byte) []byte { - // Replace any timestamps with a placeholder. - byt = timestampRegex.ReplaceAll(byt, []byte("[timestamp]")) - - homeDir, err := os.UserHomeDir() - require.NoError(t, err) - - configDir := config.DefaultDir() - byt = bytes.ReplaceAll(byt, []byte(configDir), []byte("~/.config/coderv2")) - - byt = bytes.ReplaceAll(byt, []byte(codersdk.DefaultCacheDir()), []byte("[cache dir]")) - - // The home directory changes depending on the test environment. - byt = bytes.ReplaceAll(byt, []byte(homeDir), []byte("~")) - for _, r := range []struct { - old string - new string - }{ - {"\r\n", "\n"}, - {`~\.cache\coder`, "~/.cache/coder"}, - {`C:\Users\RUNNER~1\AppData\Local\Temp`, "/tmp"}, - {os.TempDir(), "/tmp"}, - } { - byt = bytes.ReplaceAll(byt, []byte(r.old), []byte(r.new)) - } - return byt -} - -func extractVisibleCommandPaths(cmdPath []string, cmds []*clibase.Cmd) [][]string { - var cmdPaths [][]string - for _, c := range cmds { - if c.Hidden { - continue - } - cmdPath := append(cmdPath, c.Name()) - cmdPaths = append(cmdPaths, cmdPath) - cmdPaths = append(cmdPaths, extractVisibleCommandPaths(cmdPath, c.Children)...) - } - return cmdPaths -} - -func prepareTestData(t *testing.T) (*codersdk.Client, map[string]string) { - t.Helper() - - ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) - defer cancel() - - db, pubsub := dbtestutil.NewDB(t) - rootClient := coderdtest.New(t, &coderdtest.Options{ - Database: db, - Pubsub: pubsub, - IncludeProvisionerDaemon: true, - }) - firstUser := coderdtest.CreateFirstUser(t, rootClient) - secondUser, err := rootClient.CreateUser(ctx, codersdk.CreateUserRequest{ - Email: "testuser2@coder.com", - Username: "testuser2", - Password: coderdtest.FirstUserParams.Password, - OrganizationID: firstUser.OrganizationID, - }) - require.NoError(t, err) - version := coderdtest.CreateTemplateVersion(t, rootClient, firstUser.OrganizationID, nil) - version = coderdtest.AwaitTemplateVersionJob(t, rootClient, version.ID) - template := coderdtest.CreateTemplate(t, rootClient, firstUser.OrganizationID, version.ID, func(req *codersdk.CreateTemplateRequest) { - req.Name = "test-template" - }) - workspace := coderdtest.CreateWorkspace(t, rootClient, firstUser.OrganizationID, template.ID, func(req *codersdk.CreateWorkspaceRequest) { - req.Name = "test-workspace" - }) - workspaceBuild := coderdtest.AwaitWorkspaceBuildJob(t, rootClient, workspace.LatestBuild.ID) - - replacements := map[string]string{ - firstUser.UserID.String(): "[first user ID]", - secondUser.ID.String(): "[second user ID]", - firstUser.OrganizationID.String(): "[first org ID]", - version.ID.String(): "[version ID]", - version.Name: "[version name]", - version.Job.ID.String(): "[version job ID]", - version.Job.FileID.String(): "[version file ID]", - version.Job.WorkerID.String(): "[version worker ID]", - template.ID.String(): "[template ID]", - workspace.ID.String(): "[workspace ID]", - workspaceBuild.ID.String(): "[workspace build ID]", - workspaceBuild.Job.ID.String(): "[workspace build job ID]", - workspaceBuild.Job.FileID.String(): "[workspace build file ID]", - workspaceBuild.Job.WorkerID.String(): "[workspace build worker ID]", - } - - return rootClient, replacements + )) } func TestRoot(t *testing.T) { diff --git a/cli/server_test.go b/cli/server_test.go index 5c8af2f2ca..075a3e8c38 100644 --- a/cli/server_test.go +++ b/cli/server_test.go @@ -1607,15 +1607,15 @@ func TestServerYAMLConfig(t *testing.T) { goldenPath := filepath.Join("testdata", "server-config.yaml.golden") - wantByt = normalizeGoldenFile(t, wantByt) - if *updateGoldenFiles { + wantByt = clitest.NormalizeGoldenFile(t, wantByt) + if *clitest.UpdateGoldenFiles { require.NoError(t, os.WriteFile(goldenPath, wantByt, 0o600)) return } got, err := os.ReadFile(goldenPath) require.NoError(t, err) - got = normalizeGoldenFile(t, got) + got = clitest.NormalizeGoldenFile(t, got) require.Equal(t, string(wantByt), string(got)) } diff --git a/enterprise/cli/root_internal_test.go b/enterprise/cli/root_internal_test.go new file mode 100644 index 0000000000..cc7b803698 --- /dev/null +++ b/enterprise/cli/root_internal_test.go @@ -0,0 +1,27 @@ +package cli + +import ( + "testing" + + "github.com/coder/coder/cli" + "github.com/stretchr/testify/require" + + "github.com/coder/coder/cli/clibase" + + "github.com/coder/coder/cli/clitest" +) + +//nolint:tparallel,paralleltest +func TestEnterpriseCommandHelp(t *testing.T) { + // Only test the enterprise commands + getCmds := func(t *testing.T) *clibase.Cmd { + // Must return a fresh instance of cmds each time. + t.Helper() + var root cli.RootCmd + rootCmd, err := root.Command((&RootCmd{}).enterpriseOnly()) + require.NoError(t, err) + + return rootCmd + } + clitest.TestCommandHelp(t, getCmds, clitest.DefaultCases()) +} diff --git a/enterprise/cli/testdata/coder_--help.golden b/enterprise/cli/testdata/coder_--help.golden new file mode 100644 index 0000000000..1a78134627 --- /dev/null +++ b/enterprise/cli/testdata/coder_--help.golden @@ -0,0 +1,50 @@ +Usage: coder [global-flags] + +Coder v0.0.0-devel — A tool for provisioning self-hosted development environments with Terraform. + - Start a Coder server: + +  $ coder server  + + - Get started by creating a template from an example: + +  $ coder templates init  + +Subcommands + features List Enterprise features + groups Manage groups + licenses Add, delete, and list licenses + provisionerd Manage provisioner daemons + server Start a Coder server + +Global Options +Global options are applied to all commands. They can be set using environment +variables or flags. + + --debug-options bool + Print all options, how they're set, then exit. + + --global-config string, $CODER_CONFIG_DIR (default: ~/.config/coderv2) + Path to the global `coder` config directory. + + --header string-array, $CODER_HEADER + Additional HTTP headers added to all requests. Provide as key=value. + Can be specified multiple times. + + --no-feature-warning bool, $CODER_NO_FEATURE_WARNING + Suppress warnings about unlicensed features. + + --no-version-warning bool, $CODER_NO_VERSION_WARNING + Suppress warning when client and server versions do not match. + + --token string, $CODER_SESSION_TOKEN + Specify an authentication token. For security reasons setting + CODER_SESSION_TOKEN is preferred. + + --url url, $CODER_URL + URL to a deployment. + + -v, --verbose bool, $CODER_VERBOSE + Enable verbose output. + +--- +Report bugs and request features at https://github.com/coder/coder/issues/new diff --git a/enterprise/cli/testdata/coder_features_--help.golden b/enterprise/cli/testdata/coder_features_--help.golden new file mode 100644 index 0000000000..7826df161c --- /dev/null +++ b/enterprise/cli/testdata/coder_features_--help.golden @@ -0,0 +1,11 @@ +Usage: coder features + +List Enterprise features + +Aliases: feature + +Subcommands + list + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_features_list_--help.golden b/enterprise/cli/testdata/coder_features_list_--help.golden new file mode 100644 index 0000000000..cb6369fb3f --- /dev/null +++ b/enterprise/cli/testdata/coder_features_list_--help.golden @@ -0,0 +1,14 @@ +Usage: coder features list [flags] + +Aliases: ls + +Options + -c, --column string-array (default: Name,Entitlement,Enabled,Limit,Actual) + Specify a column to filter in the table. Available columns are: Name, + Entitlement, Enabled, Limit, Actual. + + -o, --output string (default: table) + Output format. Available formats are: table, json. + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_groups_--help.golden b/enterprise/cli/testdata/coder_groups_--help.golden new file mode 100644 index 0000000000..1cf56bca86 --- /dev/null +++ b/enterprise/cli/testdata/coder_groups_--help.golden @@ -0,0 +1,14 @@ +Usage: coder groups + +Manage groups + +Aliases: group + +Subcommands + create Create a user group + delete Delete a user group + edit Edit a user group + list List user groups + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_groups_create_--help.golden b/enterprise/cli/testdata/coder_groups_create_--help.golden new file mode 100644 index 0000000000..1cc883ab83 --- /dev/null +++ b/enterprise/cli/testdata/coder_groups_create_--help.golden @@ -0,0 +1,10 @@ +Usage: coder groups create [flags] + +Create a user group + +Options + -u, --avatar-url string, $CODER_AVATAR_URL + Set an avatar for a group. + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_groups_delete_--help.golden b/enterprise/cli/testdata/coder_groups_delete_--help.golden new file mode 100644 index 0000000000..5997603176 --- /dev/null +++ b/enterprise/cli/testdata/coder_groups_delete_--help.golden @@ -0,0 +1,8 @@ +Usage: coder groups delete + +Delete a user group + +Aliases: rm + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_groups_edit_--help.golden b/enterprise/cli/testdata/coder_groups_edit_--help.golden new file mode 100644 index 0000000000..a265ef5215 --- /dev/null +++ b/enterprise/cli/testdata/coder_groups_edit_--help.golden @@ -0,0 +1,19 @@ +Usage: coder groups edit [flags] + +Edit a user group + +Options + -a, --add-users string-array + Add users to the group. Accepts emails or IDs. + + -u, --avatar-url string + Update the group avatar. + + -n, --name string + Update the group name. + + -r, --rm-users string-array + Remove users to the group. Accepts emails or IDs. + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_groups_list_--help.golden b/enterprise/cli/testdata/coder_groups_list_--help.golden new file mode 100644 index 0000000000..99c20f5be3 --- /dev/null +++ b/enterprise/cli/testdata/coder_groups_list_--help.golden @@ -0,0 +1,14 @@ +Usage: coder groups list [flags] + +List user groups + +Options + -c, --column string-array (default: name,organization id,members,avatar url) + Columns to display in table output. Available columns: name, + organization id, members, avatar url. + + -o, --output string (default: table) + Output format. Available formats: table, json. + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_licenses_--help.golden b/enterprise/cli/testdata/coder_licenses_--help.golden new file mode 100644 index 0000000000..c500aadce2 --- /dev/null +++ b/enterprise/cli/testdata/coder_licenses_--help.golden @@ -0,0 +1,13 @@ +Usage: coder licenses + +Add, delete, and list licenses + +Aliases: license + +Subcommands + add Add license to Coder deployment + delete Delete license by ID + list List licenses (including expired) + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_licenses_add_--help.golden b/enterprise/cli/testdata/coder_licenses_add_--help.golden new file mode 100644 index 0000000000..710a3fd67f --- /dev/null +++ b/enterprise/cli/testdata/coder_licenses_add_--help.golden @@ -0,0 +1,16 @@ +Usage: coder licenses add [flags] [-f file | -l license] + +Add license to Coder deployment + +Options + --debug bool + Output license claims for debugging. + + -f, --file string + Load license from file. + + -l, --license string + License string. + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_licenses_delete_--help.golden b/enterprise/cli/testdata/coder_licenses_delete_--help.golden new file mode 100644 index 0000000000..6492aa4414 --- /dev/null +++ b/enterprise/cli/testdata/coder_licenses_delete_--help.golden @@ -0,0 +1,8 @@ +Usage: coder licenses delete + +Delete license by ID + +Aliases: del, rm + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_licenses_list_--help.golden b/enterprise/cli/testdata/coder_licenses_list_--help.golden new file mode 100644 index 0000000000..b04256e1d1 --- /dev/null +++ b/enterprise/cli/testdata/coder_licenses_list_--help.golden @@ -0,0 +1,8 @@ +Usage: coder licenses list + +List licenses (including expired) + +Aliases: ls + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_provisionerd_--help.golden b/enterprise/cli/testdata/coder_provisionerd_--help.golden new file mode 100644 index 0000000000..973c1b4a70 --- /dev/null +++ b/enterprise/cli/testdata/coder_provisionerd_--help.golden @@ -0,0 +1,9 @@ +Usage: coder provisionerd + +Manage provisioner daemons + +Subcommands + start Run a provisioner daemon + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_provisionerd_start_--help.golden b/enterprise/cli/testdata/coder_provisionerd_start_--help.golden new file mode 100644 index 0000000000..1236cfb5ae --- /dev/null +++ b/enterprise/cli/testdata/coder_provisionerd_start_--help.golden @@ -0,0 +1,19 @@ +Usage: coder provisionerd start [flags] + +Run a provisioner daemon + +Options + -c, --cache-dir string, $CODER_CACHE_DIRECTORY (default: [cache dir]) + Directory to store cached data. + + --poll-interval duration, $CODER_PROVISIONERD_POLL_INTERVAL (default: 1s) + How often to poll for provisioner jobs. + + --poll-jitter duration, $CODER_PROVISIONERD_POLL_JITTER (default: 100ms) + How much to jitter the poll interval by. + + -t, --tag string-array, $CODER_PROVISIONERD_TAGS + Tags to filter provisioner jobs by. + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_server_--help.golden b/enterprise/cli/testdata/coder_server_--help.golden new file mode 100644 index 0000000000..f8f45b138d --- /dev/null +++ b/enterprise/cli/testdata/coder_server_--help.golden @@ -0,0 +1,395 @@ +Usage: coder server [flags] + +Start a Coder server + +Subcommands + create-admin-user Create a new admin user with the given username, + email and password and adds it to every + organization. + postgres-builtin-serve Run the built-in PostgreSQL deployment. + postgres-builtin-url Output the connection URL for the built-in + PostgreSQL deployment. + +Options + --cache-dir string, $CODER_CACHE_DIRECTORY (default: [cache dir]) + The directory to cache temporary files. If unspecified and + $CACHE_DIRECTORY is set, it will be used for compatibility with + systemd. + + --disable-owner-workspace-access bool, $CODER_DISABLE_OWNER_WORKSPACE_ACCESS + Remove the permission for the 'owner' role to have workspace execution + on all workspaces. This prevents the 'owner' from ssh, apps, and + terminal access based on the 'owner' role. They still have their user + permissions to access their own workspaces. + + --disable-path-apps bool, $CODER_DISABLE_PATH_APPS + Disable workspace apps that are not served from subdomains. Path-based + apps can make requests to the Coder API and pose a security risk when + the workspace serves malicious JavaScript. This is recommended for + security purposes if a --wildcard-access-url is configured. + + --swagger-enable bool, $CODER_SWAGGER_ENABLE + Expose the swagger endpoint via /swagger. + + --experiments string-array, $CODER_EXPERIMENTS + Enable one or more experiments. These are not ready for production. + Separate multiple experiments with commas, or enter '*' to opt-in to + all available experiments. + + --postgres-url string, $CODER_PG_CONNECTION_URL + URL of a PostgreSQL database. If empty, PostgreSQL binaries will be + downloaded from Maven (https://repo1.maven.org/maven2) and store all + data in the config root. Access the built-in database with "coder + server postgres-builtin-url". + + --ssh-keygen-algorithm string, $CODER_SSH_KEYGEN_ALGORITHM (default: ed25519) + The algorithm to use for generating ssh keys. Accepted values are + "ed25519", "ecdsa", or "rsa4096". + + --update-check bool, $CODER_UPDATE_CHECK (default: false) + Periodically check for new releases of Coder and inform the owner. The + check is performed once per day. + +Client Options +These options change the behavior of how clients interact with the Coder. +Clients include the coder cli, vs code extension, and the web UI. + + --ssh-config-options string-array, $CODER_SSH_CONFIG_OPTIONS + These SSH config options will override the default SSH config options. + Provide options in "key=value" or "key value" format separated by + commas.Using this incorrectly can break SSH to your deployment, use + cautiously. + + --ssh-hostname-prefix string, $CODER_SSH_HOSTNAME_PREFIX (default: coder.) + The SSH deployment prefix is used in the Host of the ssh config. + +Config Options +Use a YAML configuration file when your server launch become unwieldy. + + -c, --config yaml-config-path, $CODER_CONFIG_PATH + Specify a YAML file to load configuration from. + + --write-config bool + + Write out the current server config as YAML to stdout. + +Introspection / Logging Options + --log-human string, $CODER_LOGGING_HUMAN (default: /dev/stderr) + Output human-readable logs to a given file. + + --log-json string, $CODER_LOGGING_JSON + Output JSON logs to a given file. + + --log-stackdriver string, $CODER_LOGGING_STACKDRIVER + Output Stackdriver compatible logs to a given file. + + -v, --verbose bool, $CODER_VERBOSE + Output debug-level logs. + +Introspection / Prometheus Options + --prometheus-address host:port, $CODER_PROMETHEUS_ADDRESS (default: 127.0.0.1:2112) + The bind address to serve prometheus metrics. + + --prometheus-collect-agent-stats bool, $CODER_PROMETHEUS_COLLECT_AGENT_STATS + Collect agent stats (may increase charges for metrics storage). + + --prometheus-enable bool, $CODER_PROMETHEUS_ENABLE + Serve prometheus metrics on the address defined by prometheus address. + +Introspection / Tracing Options + --trace-logs bool, $CODER_TRACE_LOGS + Enables capturing of logs as events in traces. This is useful for + debugging, but may result in a very large amount of events being sent + to the tracing backend which may incur significant costs. If the + verbose flag was supplied, debug-level logs will be included. + + --trace bool, $CODER_TRACE_ENABLE + Whether application tracing data is collected. It exports to a backend + configured by environment variables. See: + https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md. + + --trace-honeycomb-api-key string, $CODER_TRACE_HONEYCOMB_API_KEY + Enables trace exporting to Honeycomb.io using the provided API Key. + +Introspection / pprof Options + --pprof-address host:port, $CODER_PPROF_ADDRESS (default: 127.0.0.1:6060) + The bind address to serve pprof. + + --pprof-enable bool, $CODER_PPROF_ENABLE + Serve pprof metrics on the address defined by pprof address. + +Networking Options + --access-url url, $CODER_ACCESS_URL + The URL that users will use to access the Coder deployment. + + --proxy-trusted-headers string-array, $CODER_PROXY_TRUSTED_HEADERS + Headers to trust for forwarding IP addresses. e.g. Cf-Connecting-Ip, + True-Client-Ip, X-Forwarded-For. + + --proxy-trusted-origins string-array, $CODER_PROXY_TRUSTED_ORIGINS + Origin addresses to respect "proxy-trusted-headers". e.g. + 192.168.1.0/24. + + --redirect-to-access-url bool, $CODER_REDIRECT_TO_ACCESS_URL + Specifies whether to redirect requests that do not match the access + URL host. + + --secure-auth-cookie bool, $CODER_SECURE_AUTH_COOKIE + Controls if the 'Secure' property is set on browser session cookies. + + --wildcard-access-url url, $CODER_WILDCARD_ACCESS_URL + Specifies the wildcard hostname to use for workspace applications in + the form "*.example.com". + +Networking / DERP Options +Most Coder deployments never have to think about DERP because all connections +between workspaces and users are peer-to-peer. However, when Coder cannot +establish a peer to peer connection, Coder uses a distributed relay network +backed by Tailscale and WireGuard. + + --derp-config-path string, $CODER_DERP_CONFIG_PATH + Path to read a DERP mapping from. See: + https://tailscale.com/kb/1118/custom-derp-servers/. + + --derp-config-url string, $CODER_DERP_CONFIG_URL + URL to fetch a DERP mapping on startup. See: + https://tailscale.com/kb/1118/custom-derp-servers/. + + --derp-server-enable bool, $CODER_DERP_SERVER_ENABLE (default: true) + Whether to enable or disable the embedded DERP relay server. + + --derp-server-region-code string, $CODER_DERP_SERVER_REGION_CODE (default: coder) + Region code to use for the embedded DERP server. + + --derp-server-region-id int, $CODER_DERP_SERVER_REGION_ID (default: 999) + Region ID to use for the embedded DERP server. + + --derp-server-region-name string, $CODER_DERP_SERVER_REGION_NAME (default: Coder Embedded Relay) + Region name that for the embedded DERP server. + + --derp-server-stun-addresses string-array, $CODER_DERP_SERVER_STUN_ADDRESSES (default: stun.l.google.com:19302) + Addresses for STUN servers to establish P2P connections. Use special + value 'disable' to turn off STUN. + +Networking / HTTP Options + --disable-password-auth bool, $CODER_DISABLE_PASSWORD_AUTH + Disable password authentication. This is recommended for security + purposes in production deployments that rely on an identity provider. + Any user with the owner role will be able to sign in with their + password regardless of this setting to avoid potential lock out. If + you are locked out of your account, you can use the `coder server + create-admin` command to create a new admin user directly in the + database. + + --disable-session-expiry-refresh bool, $CODER_DISABLE_SESSION_EXPIRY_REFRESH + Disable automatic session expiry bumping due to activity. This forces + all sessions to become invalid after the session expiry duration has + been reached. + + --http-address string, $CODER_HTTP_ADDRESS (default: 127.0.0.1:3000) + HTTP bind address of the server. Unset to disable the HTTP endpoint. + + --max-token-lifetime duration, $CODER_MAX_TOKEN_LIFETIME (default: 876600h0m0s) + The maximum lifetime duration users can specify when creating an API + token. + + --proxy-health-interval duration, $CODER_PROXY_HEALTH_INTERVAL (default: 1m0s) + The interval in which coderd should be checking the status of + workspace proxies. + + --session-duration duration, $CODER_SESSION_DURATION (default: 24h0m0s) + The token expiry duration for browser sessions. Sessions may last + longer if they are actively making requests, but this functionality + can be disabled via --disable-session-expiry-refresh. + +Networking / TLS Options +Configure TLS / HTTPS for your Coder deployment. If you're running Coder behind +a TLS-terminating reverse proxy or are accessing Coder over a secure link, you +can safely ignore these settings. + + --strict-transport-security int, $CODER_STRICT_TRANSPORT_SECURITY (default: 0) + Controls if the 'Strict-Transport-Security' header is set on all + static file responses. This header should only be set if the server is + accessed via HTTPS. This value is the MaxAge in seconds of the header. + + --strict-transport-security-options string-array, $CODER_STRICT_TRANSPORT_SECURITY_OPTIONS + Two optional fields can be set in the Strict-Transport-Security + header; 'includeSubDomains' and 'preload'. The + 'strict-transport-security' flag must be set to a non-zero value for + these options to be used. + + --tls-address host:port, $CODER_TLS_ADDRESS (default: 127.0.0.1:3443) + HTTPS bind address of the server. + + --tls-cert-file string-array, $CODER_TLS_CERT_FILE + Path to each certificate for TLS. It requires a PEM-encoded file. To + configure the listener to use a CA certificate, concatenate the + primary certificate and the CA certificate together. The primary + certificate should appear first in the combined file. + + --tls-client-auth string, $CODER_TLS_CLIENT_AUTH (default: none) + Policy the server will follow for TLS Client Authentication. Accepted + values are "none", "request", "require-any", "verify-if-given", or + "require-and-verify". + + --tls-client-ca-file string, $CODER_TLS_CLIENT_CA_FILE + PEM-encoded Certificate Authority file used for checking the + authenticity of client. + + --tls-client-cert-file string, $CODER_TLS_CLIENT_CERT_FILE + Path to certificate for client TLS authentication. It requires a + PEM-encoded file. + + --tls-client-key-file string, $CODER_TLS_CLIENT_KEY_FILE + Path to key for client TLS authentication. It requires a PEM-encoded + file. + + --tls-enable bool, $CODER_TLS_ENABLE + Whether TLS will be enabled. + + --tls-key-file string-array, $CODER_TLS_KEY_FILE + Paths to the private keys for each of the certificates. It requires a + PEM-encoded file. + + --tls-min-version string, $CODER_TLS_MIN_VERSION (default: tls12) + Minimum supported version of TLS. Accepted values are "tls10", + "tls11", "tls12" or "tls13". + +OAuth2 / GitHub Options + --oauth2-github-allow-everyone bool, $CODER_OAUTH2_GITHUB_ALLOW_EVERYONE + Allow all logins, setting this option means allowed orgs and teams + must be empty. + + --oauth2-github-allow-signups bool, $CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS + Whether new users can sign up with GitHub. + + --oauth2-github-allowed-orgs string-array, $CODER_OAUTH2_GITHUB_ALLOWED_ORGS + Organizations the user must be a member of to Login with GitHub. + + --oauth2-github-allowed-teams string-array, $CODER_OAUTH2_GITHUB_ALLOWED_TEAMS + Teams inside organizations the user must be a member of to Login with + GitHub. Structured as: /. + + --oauth2-github-client-id string, $CODER_OAUTH2_GITHUB_CLIENT_ID + Client ID for Login with GitHub. + + --oauth2-github-client-secret string, $CODER_OAUTH2_GITHUB_CLIENT_SECRET + Client secret for Login with GitHub. + + --oauth2-github-enterprise-base-url string, $CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL + Base URL of a GitHub Enterprise deployment to use for Login with + GitHub. + +OIDC Options + --oidc-allow-signups bool, $CODER_OIDC_ALLOW_SIGNUPS (default: true) + Whether new users can sign up with OIDC. + + --oidc-auth-url-params struct[map[string]string], $CODER_OIDC_AUTH_URL_PARAMS (default: {"access_type": "offline"}) + OIDC auth URL parameters to pass to the upstream provider. + + --oidc-client-id string, $CODER_OIDC_CLIENT_ID + Client ID to use for Login with OIDC. + + --oidc-client-secret string, $CODER_OIDC_CLIENT_SECRET + Client secret to use for Login with OIDC. + + --oidc-email-domain string-array, $CODER_OIDC_EMAIL_DOMAIN + Email domains that clients logging in with OIDC must match. + + --oidc-email-field string, $CODER_OIDC_EMAIL_FIELD (default: email) + OIDC claim field to use as the email. + + --oidc-group-field string, $CODER_OIDC_GROUP_FIELD + This field must be set if using the group sync feature and the scope + name is not 'groups'. Set to the claim to be used for groups. + + --oidc-group-mapping struct[map[string]string], $CODER_OIDC_GROUP_MAPPING (default: {}) + A map of OIDC group IDs and the group in Coder it should map to. This + is useful for when OIDC providers only return group IDs. + + --oidc-ignore-email-verified bool, $CODER_OIDC_IGNORE_EMAIL_VERIFIED + Ignore the email_verified claim from the upstream provider. + + --oidc-ignore-userinfo bool, $CODER_OIDC_IGNORE_USERINFO (default: false) + Ignore the userinfo endpoint and only use the ID token for user + information. + + --oidc-issuer-url string, $CODER_OIDC_ISSUER_URL + Issuer URL to use for Login with OIDC. + + --oidc-scopes string-array, $CODER_OIDC_SCOPES (default: openid,profile,email) + Scopes to grant when authenticating with OIDC. + + --oidc-username-field string, $CODER_OIDC_USERNAME_FIELD (default: preferred_username) + OIDC claim field to use as the username. + + --oidc-sign-in-text string, $CODER_OIDC_SIGN_IN_TEXT (default: OpenID Connect) + The text to show on the OpenID Connect sign in button. + + --oidc-icon-url url, $CODER_OIDC_ICON_URL + URL pointing to the icon to use on the OepnID Connect login button. + +Provisioning Options +Tune the behavior of the provisioner, which is responsible for creating, +updating, and deleting workspace resources. + + --provisioner-force-cancel-interval duration, $CODER_PROVISIONER_FORCE_CANCEL_INTERVAL (default: 10m0s) + Time to force cancel provisioning tasks that are stuck. + + --provisioner-daemon-poll-interval duration, $CODER_PROVISIONER_DAEMON_POLL_INTERVAL (default: 1s) + Time to wait before polling for a new job. + + --provisioner-daemon-poll-jitter duration, $CODER_PROVISIONER_DAEMON_POLL_JITTER (default: 100ms) + Random jitter added to the poll interval. + + --provisioner-daemons int, $CODER_PROVISIONER_DAEMONS (default: 3) + Number of provisioner daemons to create on start. If builds are stuck + in queued state for a long time, consider increasing this. + +Telemetry Options +Telemetry is critical to our ability to improve Coder. We strip all +personalinformation before sending data to our servers. Please only disable +telemetrywhen required by your organization's security policy. + + --telemetry bool, $CODER_TELEMETRY_ENABLE (default: false) + Whether telemetry is enabled or not. Coder collects anonymized usage + data to help improve our product. + + --telemetry-trace bool, $CODER_TELEMETRY_TRACE (default: false) + Whether Opentelemetry traces are sent to Coder. Coder collects + anonymized application tracing to help improve our product. Disabling + telemetry also disables this option. + +⚠️ Dangerous Options + --dangerous-allow-path-app-sharing bool, $CODER_DANGEROUS_ALLOW_PATH_APP_SHARING + Allow workspace apps that are not served from subdomains to be shared. + Path-based app sharing is DISABLED by default for security purposes. + Path-based apps can make requests to the Coder API and pose a security + risk when the workspace serves malicious JavaScript. Path-based apps + can be disabled entirely with --disable-path-apps for further + security. + + --dangerous-allow-path-app-site-owner-access bool, $CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS + Allow site-owners to access workspace apps from workspaces they do not + own. Owners cannot access path-based apps they do not own by default. + Path-based apps can make requests to the Coder API and pose a security + risk when the workspace serves malicious JavaScript. Path-based apps + can be disabled entirely with --disable-path-apps for further + security. + +Enterprise Options +These options are only available in the Enterprise Edition. + + --browser-only bool, $CODER_BROWSER_ONLY + Whether Coder only allows connections to workspaces via the browser. + + --derp-server-relay-url url, $CODER_DERP_SERVER_RELAY_URL + An HTTP URL that is accessible by other replicas to relay DERP + traffic. Required for high availability. + + --scim-auth-header string, $CODER_SCIM_AUTH_HEADER + Enables SCIM and sets the authentication header for the built-in SCIM + server. New users are automatically created with OIDC authentication. + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_server_create-admin-user_--help.golden b/enterprise/cli/testdata/coder_server_create-admin-user_--help.golden new file mode 100644 index 0000000000..6c95fb1954 --- /dev/null +++ b/enterprise/cli/testdata/coder_server_create-admin-user_--help.golden @@ -0,0 +1,32 @@ +Usage: coder server create-admin-user [flags] + +Create a new admin user with the given username, email and password and adds it +to every organization. + +Options + --email string, $CODER_EMAIL + The email of the new user. If not specified, you will be prompted via + stdin. + + --password string, $CODER_PASSWORD + The password of the new user. If not specified, you will be prompted + via stdin. + + --postgres-url string, $CODER_PG_CONNECTION_URL + URL of a PostgreSQL database. If empty, the built-in PostgreSQL + deployment will be used (Coder must not be already running in this + case). + + --raw-url bool + Output the raw connection URL instead of a psql command. + + --ssh-keygen-algorithm string, $CODER_SSH_KEYGEN_ALGORITHM (default: ed25519) + The algorithm to use for generating ssh keys. Accepted values are + "ed25519", "ecdsa", or "rsa4096". + + --username string, $CODER_USERNAME + The username of the new user. If not specified, you will be prompted + via stdin. + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_server_postgres-builtin-serve_--help.golden b/enterprise/cli/testdata/coder_server_postgres-builtin-serve_--help.golden new file mode 100644 index 0000000000..bb61bd8292 --- /dev/null +++ b/enterprise/cli/testdata/coder_server_postgres-builtin-serve_--help.golden @@ -0,0 +1,10 @@ +Usage: coder server postgres-builtin-serve [flags] + +Run the built-in PostgreSQL deployment. + +Options + --raw-url bool + Output the raw connection URL instead of a psql command. + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_server_postgres-builtin-url_--help.golden b/enterprise/cli/testdata/coder_server_postgres-builtin-url_--help.golden new file mode 100644 index 0000000000..af6ca07dc1 --- /dev/null +++ b/enterprise/cli/testdata/coder_server_postgres-builtin-url_--help.golden @@ -0,0 +1,10 @@ +Usage: coder server postgres-builtin-url [flags] + +Output the connection URL for the built-in PostgreSQL deployment. + +Options + --raw-url bool + Output the raw connection URL instead of a psql command. + +--- +Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_wsproxy_--help.golden b/enterprise/cli/testdata/coder_wsproxy_--help.golden new file mode 100644 index 0000000000..8f39caa1ec --- /dev/null +++ b/enterprise/cli/testdata/coder_wsproxy_--help.golden @@ -0,0 +1,17 @@ +Usage: coder workspace-proxy + +Manage workspace proxies + +Aliases: wsproxy + +Subcommands + create Create a workspace proxy + delete Delete a workspace proxy + edit Edit a workspace proxy + ls List all workspace proxies + regenerate-token Regenerate a workspace proxy authentication token. This + will invalidate the existing authentication token. + server Start a workspace proxy server + +--- +Run `coder --help` for a list of global options.