cli: add --id flag to API key expire/delete commands

Add --id flag as an alternative to --prefix for expiring and
deleting API keys. This allows users to use the ID shown in
'headscale apikeys list' output, which is more convenient than
the prefix.

Either --id or --prefix must be provided; both flags are optional
but at least one is required.

Updates #2986
This commit is contained in:
Kristoffer Dalby 2026-01-16 14:00:38 +00:00
parent a194712c34
commit e0bae9b769

View File

@ -9,7 +9,6 @@ import (
"github.com/juanfont/headscale/hscontrol/util" "github.com/juanfont/headscale/hscontrol/util"
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
"github.com/pterm/pterm" "github.com/pterm/pterm"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/timestamppb"
) )
@ -29,15 +28,11 @@ func init() {
apiKeysCmd.AddCommand(createAPIKeyCmd) apiKeysCmd.AddCommand(createAPIKeyCmd)
expireAPIKeyCmd.Flags().StringP("prefix", "p", "", "ApiKey prefix") expireAPIKeyCmd.Flags().StringP("prefix", "p", "", "ApiKey prefix")
if err := expireAPIKeyCmd.MarkFlagRequired("prefix"); err != nil { expireAPIKeyCmd.Flags().Uint64P("id", "i", 0, "ApiKey ID")
log.Fatal().Err(err).Msg("")
}
apiKeysCmd.AddCommand(expireAPIKeyCmd) apiKeysCmd.AddCommand(expireAPIKeyCmd)
deleteAPIKeyCmd.Flags().StringP("prefix", "p", "", "ApiKey prefix") deleteAPIKeyCmd.Flags().StringP("prefix", "p", "", "ApiKey prefix")
if err := deleteAPIKeyCmd.MarkFlagRequired("prefix"); err != nil { deleteAPIKeyCmd.Flags().Uint64P("id", "i", 0, "ApiKey ID")
log.Fatal().Err(err).Msg("")
}
apiKeysCmd.AddCommand(deleteAPIKeyCmd) apiKeysCmd.AddCommand(deleteAPIKeyCmd)
} }
@ -154,11 +149,20 @@ var expireAPIKeyCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output") output, _ := cmd.Flags().GetString("output")
prefix, err := cmd.Flags().GetString("prefix") id, _ := cmd.Flags().GetUint64("id")
if err != nil { prefix, _ := cmd.Flags().GetString("prefix")
switch {
case id == 0 && prefix == "":
ErrorOutput( ErrorOutput(
err, errMissingParameter,
fmt.Sprintf("Error getting prefix from CLI flag: %s", err), "Either --id or --prefix must be provided",
output,
)
case id != 0 && prefix != "":
ErrorOutput(
errMissingParameter,
"Only one of --id or --prefix can be provided",
output, output,
) )
} }
@ -167,8 +171,11 @@ var expireAPIKeyCmd = &cobra.Command{
defer cancel() defer cancel()
defer conn.Close() defer conn.Close()
request := &v1.ExpireApiKeyRequest{ request := &v1.ExpireApiKeyRequest{}
Prefix: prefix, if id != 0 {
request.Id = id
} else {
request.Prefix = prefix
} }
response, err := client.ExpireApiKey(ctx, request) response, err := client.ExpireApiKey(ctx, request)
@ -191,11 +198,20 @@ var deleteAPIKeyCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output") output, _ := cmd.Flags().GetString("output")
prefix, err := cmd.Flags().GetString("prefix") id, _ := cmd.Flags().GetUint64("id")
if err != nil { prefix, _ := cmd.Flags().GetString("prefix")
switch {
case id == 0 && prefix == "":
ErrorOutput( ErrorOutput(
err, errMissingParameter,
fmt.Sprintf("Error getting prefix from CLI flag: %s", err), "Either --id or --prefix must be provided",
output,
)
case id != 0 && prefix != "":
ErrorOutput(
errMissingParameter,
"Only one of --id or --prefix can be provided",
output, output,
) )
} }
@ -204,8 +220,11 @@ var deleteAPIKeyCmd = &cobra.Command{
defer cancel() defer cancel()
defer conn.Close() defer conn.Close()
request := &v1.DeleteApiKeyRequest{ request := &v1.DeleteApiKeyRequest{}
Prefix: prefix, if id != 0 {
request.Id = id
} else {
request.Prefix = prefix
} }
response, err := client.DeleteApiKey(ctx, request) response, err := client.DeleteApiKey(ctx, request)