Files
coder/enterprise/cli/provisionerkeys.go
T
Mathias Fredriksson c750695d83 feat(cli/cliui): output empty string for empty table (#20967)
This changes makes it so that we output the empty string for Format
when there is no data. It turns out there are many places in the code
where we have such handling, but in a way that would break the JSON
formatter (since we'd output nothing on stdout or text rather than
`[]`/`null`).
2025-12-03 11:32:59 +02:00

198 lines
4.5 KiB
Go

package cli
import (
"fmt"
"strings"
"golang.org/x/xerrors"
agpl "github.com/coder/coder/v2/cli"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/pretty"
"github.com/coder/serpent"
)
func (r *RootCmd) provisionerKeys() *serpent.Command {
cmd := &serpent.Command{
Use: "keys",
Short: "Manage provisioner keys",
Handler: func(inv *serpent.Invocation) error {
return inv.Command.HelpHandler(inv)
},
Aliases: []string{"key"},
Children: []*serpent.Command{
r.provisionerKeysCreate(),
r.provisionerKeysList(),
r.provisionerKeysDelete(),
},
}
return cmd
}
func (r *RootCmd) provisionerKeysCreate() *serpent.Command {
var (
orgContext = agpl.NewOrganizationContext()
rawTags []string
)
cmd := &serpent.Command{
Use: "create <name>",
Short: "Create a new provisioner key",
Middleware: serpent.Chain(
serpent.RequireNArgs(1),
),
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
client, err := r.InitClient(inv)
if err != nil {
return err
}
org, err := orgContext.Selected(inv, client)
if err != nil {
return xerrors.Errorf("current organization: %w", err)
}
tags, err := agpl.ParseProvisionerTags(rawTags)
if err != nil {
return err
}
res, err := client.CreateProvisionerKey(ctx, org.ID, codersdk.CreateProvisionerKeyRequest{
Name: inv.Args[0],
Tags: tags,
})
if err != nil {
return xerrors.Errorf("create provisioner key: %w", err)
}
_, _ = fmt.Fprintf(
inv.Stdout,
"Successfully created provisioner key %s! Save this authentication token, it will not be shown again.\n\n%s\n",
pretty.Sprint(cliui.DefaultStyles.Keyword, strings.ToLower(inv.Args[0])),
pretty.Sprint(cliui.DefaultStyles.Keyword, res.Key),
)
return nil
},
}
cmd.Options = serpent.OptionSet{
{
Flag: "tag",
FlagShorthand: "t",
Env: "CODER_PROVISIONERD_TAGS",
Description: "Tags to filter provisioner jobs by.",
Value: serpent.StringArrayOf(&rawTags),
},
}
orgContext.AttachOptions(cmd)
return cmd
}
func (r *RootCmd) provisionerKeysList() *serpent.Command {
var (
orgContext = agpl.NewOrganizationContext()
formatter = cliui.NewOutputFormatter(
cliui.TableFormat([]codersdk.ProvisionerKey{}, []string{"created at", "name", "tags"}),
cliui.JSONFormat(),
)
)
cmd := &serpent.Command{
Use: "list",
Short: "List provisioner keys in an organization",
Aliases: []string{"ls"},
Middleware: serpent.Chain(
serpent.RequireNArgs(0),
),
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
client, err := r.InitClient(inv)
if err != nil {
return err
}
org, err := orgContext.Selected(inv, client)
if err != nil {
return xerrors.Errorf("current organization: %w", err)
}
keys, err := client.ListProvisionerKeys(ctx, org.ID)
if err != nil {
return xerrors.Errorf("list provisioner keys: %w", err)
}
out, err := formatter.Format(inv.Context(), keys)
if err != nil {
return xerrors.Errorf("display provisioner keys: %w", err)
}
if out == "" {
cliui.Infof(inv.Stderr, "No provisioner keys found.")
return nil
}
_, _ = fmt.Fprintln(inv.Stdout, out)
return nil
},
}
orgContext.AttachOptions(cmd)
formatter.AttachOptions(&cmd.Options)
return cmd
}
func (r *RootCmd) provisionerKeysDelete() *serpent.Command {
orgContext := agpl.NewOrganizationContext()
cmd := &serpent.Command{
Use: "delete <name>",
Short: "Delete a provisioner key",
Middleware: serpent.Chain(
serpent.RequireNArgs(1),
),
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
client, err := r.InitClient(inv)
if err != nil {
return err
}
org, err := orgContext.Selected(inv, client)
if err != nil {
return xerrors.Errorf("current organization: %w", err)
}
_, err = cliui.Prompt(inv, cliui.PromptOptions{
Text: fmt.Sprintf("Are you sure you want to delete provisioner key %s?", pretty.Sprint(cliui.DefaultStyles.Keyword, inv.Args[0])),
IsConfirm: true,
})
if err != nil {
return err
}
err = client.DeleteProvisionerKey(ctx, org.ID, inv.Args[0])
if err != nil {
return xerrors.Errorf("delete provisioner key: %w", err)
}
_, _ = fmt.Fprintf(inv.Stdout, "Successfully deleted provisioner key %s!\n", pretty.Sprint(cliui.DefaultStyles.Keyword, strings.ToLower(inv.Args[0])))
return nil
},
}
cmd.Options = serpent.OptionSet{
cliui.SkipPromptOption(),
}
orgContext.AttachOptions(cmd)
return cmd
}