Skip to content
Merged
14 changes: 11 additions & 3 deletions .ci/docs/md.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"sort"
"strings"

"github.com/UpCloudLtd/upcloud-cli/v3/internal/commands"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
Expand Down Expand Up @@ -120,9 +121,16 @@ func genMarkdown(cmd *cobra.Command, w io.Writer) error {
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine()))
}

if len(cmd.Aliases) > 0 {
buf.WriteString("## Aliases\n\n")
buf.WriteString(fmt.Sprintf("%s\n\n", formatFlags(cmd.Aliases)))
ctx := cmd.Context()
if ctx != nil {
if wrapper := ctx.Value("command"); wrapper != nil {
if c, ok := wrapper.(*commands.BaseCommand); ok {
if aliases := c.Aliases(); len(aliases) > 0 {
buf.WriteString("## Aliases\n\n")
buf.WriteString(fmt.Sprintf("%s\n\n", formatFlags(aliases)))
}
}
}
}

if len(cmd.Example) > 0 {
Expand Down
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add termination_protection to upctl database show output
- Experimental support for token authentication by defining token in `UPCLOUD_TOKEN` environment variable.
- Experimental support for managing tokens with `account token` commands.
- New command names and aliases added to improve consistency:
- Commands:
- load-balancer
- network-peering
- object-storage
- server-group
- Aliases:
- account: acc
- gateway: gw
- network-peering: np
- object-storage: obs
- partner: pr
- router: rt
- server: srv
- server-group: sg
- storage: st

### Changed

Expand All @@ -22,6 +38,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Prevent filename completion of flags that don't take filename args.

### Deprecated
- Deprecation of some commands and aliases ( new command names added to improve consistency )
- Deprecated commands:
- loadbalancer
- networkpeering
- objectstorage
- servergroup
- Deprecated aliases:
- object-storage: objsto


## [3.14.0] - 2025-01-08

### Added
Expand Down
63 changes: 56 additions & 7 deletions internal/commands/command.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package commands

import (
"context"
"fmt"
"strings"

Expand All @@ -13,15 +14,28 @@ import (
"github.com/spf13/pflag"
)

type CommandContextKey string

const commandKey CommandContextKey = "command"

// New returns a BaseCommand that implements Command. It is used as a base to create custom commands from.
func New(name, usage string, examples ...string) *BaseCommand {
return &BaseCommand{
cobra: &cobra.Command{
Use: name,
Short: usage,
Example: strings.Join(examples, "\n"),
},
cmd := &cobra.Command{
Use: name,
Short: usage,
Example: strings.Join(examples, "\n"),
}

// Initialize BaseCommand
baseCmd := &BaseCommand{
cobra: cmd,
}

// Store reference to itself in the context - We need this to access the command in the CobraCommand interface
// Specifically to generate the reference documentation
cmd.SetContext(context.WithValue(context.Background(), commandKey, baseCmd))

return baseCmd
}

// Command is the base command type for all commands.
Expand Down Expand Up @@ -125,7 +139,42 @@ func BuildCommand(child Command, parent *cobra.Command, config *config.Config) C

// BaseCommand is the base type for all commands, implementing Command
type BaseCommand struct {
cobra *cobra.Command
cobra *cobra.Command
deprecatedAliases []string
}

// Aliases return non deprecated aliases
func (s *BaseCommand) Aliases() []string {
// Get all aliases from Cobra
allAliases := s.cobra.Aliases

// Filter out deprecated aliases
var filteredAliases []string
for _, alias := range allAliases {
if !s.isDeprecatedAlias(alias) {
filteredAliases = append(filteredAliases, alias)
}
}

return filteredAliases
}

// isDeprecatedAlias checks if an alias is deprecated
func (s *BaseCommand) isDeprecatedAlias(alias string) bool {
for _, deprecated := range s.deprecatedAliases {
if alias == deprecated {
return true
}
}
return false
}

func (s *BaseCommand) DeprecatedAliases() []string {
return s.deprecatedAliases
}

func (s *BaseCommand) SetDeprecatedAliases(aliases []string) {
s.deprecatedAliases = aliases
}

// MaximumExecutions return the max executed workers
Expand Down
6 changes: 3 additions & 3 deletions internal/commands/kubernetes/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ func (c *configCommand) InitCommand() {
"Absolute path for writing output. If the file exists, the config will be merged.")
c.AddFlags(flagSet)

// Deprecating k8s
// Deprecating uks in favor of k8s
// TODO: Remove this in the future
commands.SetSubcommandDeprecationHelp(c, []string{"k8s"})
commands.SetSubcommandDeprecationHelp(c, []string{"uks"})
}

// Execute implements commands.MultipleArgumentCommand
func (c *configCommand) Execute(exec commands.Executor, uuid string) (output.Output, error) {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandExecutionDeprecationMessage(c, []string{"k8s"}, "uks")

Expand Down
6 changes: 3 additions & 3 deletions internal/commands/kubernetes/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,9 @@ func (c *createCommand) InitCommand() {
commands.Must(c.Cobra().MarkFlagRequired("zone"))
commands.Must(c.Cobra().RegisterFlagCompletionFunc("name", cobra.NoFileCompletions))

// Deprecating k8s
// Deprecating uks in favor of k8s
// TODO: Remove this in the future
commands.SetSubcommandDeprecationHelp(c, []string{"k8s"})
commands.SetSubcommandDeprecationHelp(c, []string{"uks"})
}

func (c *createCommand) InitCommandWithConfig(cfg *config.Config) {
Expand All @@ -166,7 +166,7 @@ func (c *createCommand) InitCommandWithConfig(cfg *config.Config) {

// ExecuteWithoutArguments implements commands.NoArgumentCommand
func (c *createCommand) ExecuteWithoutArguments(exec commands.Executor) (output.Output, error) {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandExecutionDeprecationMessage(c, []string{"k8s"}, "uks")

Expand Down
15 changes: 7 additions & 8 deletions internal/commands/kubernetes/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,21 @@ func DeleteCommand() commands.Command {
}
}

func (s *deleteCommand) InitCommand() {
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandDeprecationHelp(s, []string{"uks"})
}

type deleteCommand struct {
*commands.BaseCommand
resolver.CachingKubernetes
completion.Kubernetes
}

// InitCommand implements Command.InitCommand
func (s *deleteCommand) InitCommand() {
// Deprecating k8s
// TODO: Remove this in the future
commands.SetSubcommandDeprecationHelp(s, []string{"k8s"})
}

// Execute implements commands.MultipleArgumentCommand
func (s *deleteCommand) Execute(exec commands.Executor, arg string) (output.Output, error) {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandExecutionDeprecationMessage(s, []string{"k8s"}, "uks")

Expand Down
9 changes: 6 additions & 3 deletions internal/commands/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import (

// BaseKubernetesCommand creates the base "kubernetes" command
func BaseKubernetesCommand() commands.Command {
baseCmd := commands.New("kubernetes", "Manage Kubernetes clusters")
baseCmd.SetDeprecatedAliases([]string{"uks"})

return &kubernetesCommand{
commands.New("kubernetes", "Manage Kubernetes clusters"),
BaseCommand: baseCmd,
}
}

Expand All @@ -18,7 +21,7 @@ type kubernetesCommand struct {
// InitCommand implements Command.InitCommand
func (k *kubernetesCommand) InitCommand() {
k.Cobra().Aliases = []string{"k8s", "uks"}
// Deprecating k8s

// TODO: Remove this in the future
commands.SetDeprecationHelp(k.Cobra(), []string{"k8s"})
commands.SetDeprecationHelp(k.Cobra(), k.DeprecatedAliases())
}
7 changes: 3 additions & 4 deletions internal/commands/kubernetes/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,15 @@ type listCommand struct {
*commands.BaseCommand
}

// InitCommand implements Command.InitCommand
func (s *listCommand) InitCommand() {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandDeprecationHelp(s, []string{"k8s"})
commands.SetSubcommandDeprecationHelp(s, []string{"uks"})
}

// ExecuteWithoutArguments implements commands.NoArgumentCommand
func (s *listCommand) ExecuteWithoutArguments(exec commands.Executor) (output.Output, error) {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandExecutionDeprecationMessage(s, []string{"k8s"}, "uks")

Expand Down
10 changes: 5 additions & 5 deletions internal/commands/kubernetes/modify.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ type modifyCommand struct {

// InitCommand implements Command.InitCommand
func (c *modifyCommand) InitCommand() {
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandDeprecationHelp(c, []string{"uks"})

fs := &pflag.FlagSet{}
fs.StringArrayVar(
&c.controlPlaneIPFilter,
Expand All @@ -52,15 +56,11 @@ func (c *modifyCommand) InitCommand() {
c.AddFlags(fs)
c.Cobra().MarkFlagsMutuallyExclusive("label", "clear-labels")
commands.Must(c.Cobra().RegisterFlagCompletionFunc("label", cobra.NoFileCompletions))

// Deprecating k8s
// TODO: Remove this in the future
commands.SetSubcommandDeprecationHelp(c, []string{"k8s"})
}

// Execute implements commands.MultipleArgumentCommand
func (c *modifyCommand) Execute(exec commands.Executor, arg string) (output.Output, error) {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandExecutionDeprecationMessage(c, []string{"k8s"}, "uks")

Expand Down
7 changes: 3 additions & 4 deletions internal/commands/kubernetes/plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,15 @@ type plansCommand struct {
*commands.BaseCommand
}

// InitCommand implements Command.InitCommand
func (s *plansCommand) InitCommand() {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandDeprecationHelp(s, []string{"k8s"})
commands.SetSubcommandDeprecationHelp(s, []string{"uks"})
}

// Execute implements commands.NoArgumentCommand
func (s *plansCommand) ExecuteWithoutArguments(exec commands.Executor) (output.Output, error) {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandExecutionDeprecationMessage(s, []string{"k8s"}, "uks")

Expand Down
7 changes: 3 additions & 4 deletions internal/commands/kubernetes/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,15 @@ type showCommand struct {
completion.Kubernetes
}

// InitCommand implements Command.InitCommand
func (s *showCommand) InitCommand() {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandDeprecationHelp(s, []string{"k8s"})
commands.SetSubcommandDeprecationHelp(s, []string{"uks"})
}

// Execute implements commands.MultipleArgumentCommand
func (s *showCommand) Execute(exec commands.Executor, uuid string) (output.Output, error) {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandExecutionDeprecationMessage(s, []string{"k8s"}, "uks")

Expand Down
7 changes: 3 additions & 4 deletions internal/commands/kubernetes/versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@ type versionsCommand struct {
*commands.BaseCommand
}

// InitCommand implements Command.InitCommand
func (s *versionsCommand) InitCommand() {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandDeprecationHelp(s, []string{"k8s"})
commands.SetSubcommandDeprecationHelp(s, []string{"uks"})
}

// ExecuteWithoutArguments implements commands.NoArgumentCommand
func (s *versionsCommand) ExecuteWithoutArguments(exec commands.Executor) (output.Output, error) {
// Deprecating k8s
// Deprecating uks
// TODO: Remove this in the future
commands.SetSubcommandExecutionDeprecationMessage(s, []string{"k8s"}, "uks")

Expand Down
12 changes: 9 additions & 3 deletions internal/commands/loadbalancer/loadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ import (

// BaseLoadBalancerCommand creates the base "loadbalancer" command
func BaseLoadBalancerCommand() commands.Command {
return &loadbalancerCommand{
commands.New("load-balancer", "Manage load balancers"),
// Initialize the BaseCommand properly
baseCmd := commands.New("load-balancer", "Manage load balancers")
baseCmd.SetDeprecatedAliases([]string{"loadbalancer"})

lbc := &loadbalancerCommand{
BaseCommand: baseCmd,
}

return lbc
}

type loadbalancerCommand struct {
Expand All @@ -21,5 +27,5 @@ func (lb *loadbalancerCommand) InitCommand() {

// Deprecating loadbalancer in favour of load-balancer
// TODO: Remove this in the future
commands.SetDeprecationHelp(lb.Cobra(), []string{"loadbalancer"})
commands.SetDeprecationHelp(lb.Cobra(), lb.DeprecatedAliases())
}
Loading