From ba0a0209df5d49be319ea5b2b89114f7e474450a Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Tue, 8 Jul 2025 14:57:21 +0200 Subject: [PATCH 01/10] size, admin not finished yet --- cmd/admin/v1/commands.go | 1 + cmd/admin/v1/size.go | 142 +++++++++++++++++++++++++++++++ cmd/api/v1/commands.go | 1 + cmd/api/v1/size.go | 93 ++++++++++++++++++++ cmd/completion/size.go | 20 +++++ cmd/tableprinters/common.go | 5 ++ cmd/tableprinters/size.go | 48 +++++++++++ docs/metalctlv2.md | 1 + docs/metalctlv2_size.md | 33 +++++++ docs/metalctlv2_size_describe.md | 31 +++++++ docs/metalctlv2_size_list.md | 34 ++++++++ go.mod | 6 +- go.sum | 8 +- 13 files changed, 418 insertions(+), 5 deletions(-) create mode 100644 cmd/admin/v1/size.go create mode 100644 cmd/api/v1/size.go create mode 100644 cmd/completion/size.go create mode 100644 cmd/tableprinters/size.go create mode 100644 docs/metalctlv2_size.md create mode 100644 docs/metalctlv2_size_describe.md create mode 100644 docs/metalctlv2_size_list.md diff --git a/cmd/admin/v1/commands.go b/cmd/admin/v1/commands.go index 0410c4f..1c4b1c2 100644 --- a/cmd/admin/v1/commands.go +++ b/cmd/admin/v1/commands.go @@ -17,6 +17,7 @@ func AddCmds(cmd *cobra.Command, c *config.Config) { adminCmd.AddCommand(newImageCmd(c)) adminCmd.AddCommand(newIPCmd(c)) adminCmd.AddCommand(newNetworkCmd(c)) + adminCmd.AddCommand(newSizeCmd(c)) adminCmd.AddCommand(newTokenCmd(c)) cmd.AddCommand(adminCmd) diff --git a/cmd/admin/v1/size.go b/cmd/admin/v1/size.go new file mode 100644 index 0000000..f68388c --- /dev/null +++ b/cmd/admin/v1/size.go @@ -0,0 +1,142 @@ +package v1 + +import ( + "fmt" + + "connectrpc.com/connect" + adminv2 "github.com/metal-stack/api/go/metalstack/admin/v2" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/metal-stack/cli/cmd/config" + "github.com/metal-stack/metal-lib/pkg/genericcli" + "github.com/metal-stack/metal-lib/pkg/genericcli/printers" + "github.com/metal-stack/metal-lib/pkg/pointer" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +type size struct { + c *config.Config +} + +func newSizeCmd(c *config.Config) *cobra.Command { + w := &size{ + c: c, + } + gcli := genericcli.NewGenericCLI(w).WithFS(c.Fs) + + cmdsConfig := &genericcli.CmdsConfig[*adminv2.SizeServiceCreateRequest, *adminv2.SizeServiceUpdateRequest, *apiv2.Size]{ + BinaryName: config.BinaryName, + GenericCLI: gcli, + Singular: "size", + Plural: "sizes", + Description: "manage sizes which defines the cpu, gpu, memory and storage properties of machines", + DescribePrinter: func() printers.Printer { return c.DescribePrinter }, + ListPrinter: func() printers.Printer { return c.ListPrinter }, + ValidArgsFn: c.Completion.SizeListCompletion, + OnlyCmds: genericcli.OnlyCmds(genericcli.CreateCmd, genericcli.UpdateCmd, genericcli.DeleteCmd, genericcli.EditCmd), + } + + return genericcli.NewCmds(cmdsConfig) +} + +func (c *size) Get(id string) (*apiv2.Size, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + req := &apiv2.SizeServiceGetRequest{Id: id} + + resp, err := c.c.Client.Apiv2().Size().Get(ctx, connect.NewRequest(req)) + if err != nil { + return nil, fmt.Errorf("failed to get image: %w", err) + } + + return resp.Msg.Size, nil +} + +func (c *size) Create(rq *adminv2.SizeServiceCreateRequest) (*apiv2.Size, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + labels, err := genericcli.LabelsToMap(viper.GetStringSlice("labels")) + if err != nil { + return nil, err + } + + req := &adminv2.SizeServiceCreateRequest{ + Size: &apiv2.Size{ + Id: viper.GetString("id"), + Name: pointer.PointerOrNil(viper.GetString("Name")), + Description: pointer.PointerOrNil(viper.GetString("description")), + Meta: &apiv2.Meta{ + Labels: &apiv2.Labels{ + Labels: labels, + }, + }, + Constraints: []*apiv2.SizeConstraint{}, // FIXME + }, + } + + resp, err := c.c.Client.Adminv2().Size().Create(ctx, connect.NewRequest(req)) + if err != nil { + return nil, fmt.Errorf("failed to get size: %w", err) + } + + return resp.Msg.Size, nil +} + +func (c *size) Delete(id string) (*apiv2.Size, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + req := &adminv2.SizeServiceDeleteRequest{Id: id} + + resp, err := c.c.Client.Adminv2().Size().Delete(ctx, connect.NewRequest(req)) + if err != nil { + return nil, fmt.Errorf("failed to delete size: %w", err) + } + + return resp.Msg.Size, nil +} +func (c *size) List() ([]*apiv2.Size, error) { + panic("unimplemented") + +} +func (c *size) Convert(r *apiv2.Size) (string, *adminv2.SizeServiceCreateRequest, *adminv2.SizeServiceUpdateRequest, error) { + + return r.Id, &adminv2.SizeServiceCreateRequest{ + Size: &apiv2.Size{ + Id: r.Id, + Name: r.Name, + Description: r.Description, + Meta: r.Meta, + Constraints: r.Constraints, + }, + }, &adminv2.SizeServiceUpdateRequest{ + Id: r.Id, + Name: r.Name, + Description: r.Description, + Constraints: r.Constraints, + // FIXME + Labels: &apiv2.UpdateLabels{}, + }, nil + +} + +func (c *size) Update(rq *adminv2.SizeServiceUpdateRequest) (*apiv2.Size, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + req := &adminv2.SizeServiceUpdateRequest{ + Id: viper.GetString("id"), + Name: pointer.PointerOrNil(viper.GetString("name")), + Description: pointer.PointerOrNil(viper.GetString("description")), + Constraints: rq.Constraints, + Labels: &apiv2.UpdateLabels{}, // FIXME + } + + resp, err := c.c.Client.Adminv2().Size().Update(ctx, connect.NewRequest(req)) + if err != nil { + return nil, fmt.Errorf("failed to get image: %w", err) + } + + return resp.Msg.Size, nil +} diff --git a/cmd/api/v1/commands.go b/cmd/api/v1/commands.go index 09490f3..e3dbe42 100644 --- a/cmd/api/v1/commands.go +++ b/cmd/api/v1/commands.go @@ -12,6 +12,7 @@ func AddCmds(cmd *cobra.Command, c *config.Config) { cmd.AddCommand(newMethodsCmd(c)) cmd.AddCommand(newNetworkCmd(c)) cmd.AddCommand(newProjectCmd(c)) + cmd.AddCommand(newSizeCmd(c)) cmd.AddCommand(newTenantCmd(c)) cmd.AddCommand(newTokenCmd(c)) cmd.AddCommand(newUserCmd(c)) diff --git a/cmd/api/v1/size.go b/cmd/api/v1/size.go new file mode 100644 index 0000000..0ad9fcc --- /dev/null +++ b/cmd/api/v1/size.go @@ -0,0 +1,93 @@ +package v1 + +import ( + "fmt" + + "connectrpc.com/connect" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/metal-stack/cli/cmd/config" + "github.com/metal-stack/metal-lib/pkg/genericcli" + "github.com/metal-stack/metal-lib/pkg/genericcli/printers" + "github.com/metal-stack/metal-lib/pkg/pointer" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +type size struct { + c *config.Config +} + +func newSizeCmd(c *config.Config) *cobra.Command { + w := &size{ + c: c, + } + + gcli := genericcli.NewGenericCLI(w).WithFS(c.Fs) + + cmdsConfig := &genericcli.CmdsConfig[any, any, *apiv2.Size]{ + BinaryName: config.BinaryName, + GenericCLI: gcli, + Singular: "size", + Plural: "sizes", + Description: "manage sizes which defines the cpu, gpu, memory and storage properties of machines", + DescribePrinter: func() printers.Printer { return c.DescribePrinter }, + ListPrinter: func() printers.Printer { return c.ListPrinter }, + ValidArgsFn: c.Completion.SizeListCompletion, + OnlyCmds: genericcli.OnlyCmds(genericcli.DescribeCmd, genericcli.ListCmd), + ListCmdMutateFn: func(cmd *cobra.Command) { + cmd.Flags().StringP("id", "", "", "size id to filter for") + cmd.Flags().StringP("name", "", "", "size name to filter for") + cmd.Flags().StringP("description", "", "", "size description to filter for") + }, + } + + return genericcli.NewCmds(cmdsConfig) +} + +func (c *size) Get(id string) (*apiv2.Size, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + req := &apiv2.SizeServiceGetRequest{Id: id} + + resp, err := c.c.Client.Apiv2().Size().Get(ctx, connect.NewRequest(req)) + if err != nil { + return nil, fmt.Errorf("failed to get size: %w", err) + } + + return resp.Msg.Size, nil +} + +func (c *size) List() ([]*apiv2.Size, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + req := &apiv2.SizeServiceListRequest{Query: &apiv2.SizeQuery{ + Id: pointer.PointerOrNil(viper.GetString("id")), + Name: pointer.PointerOrNil(viper.GetString("name")), + Description: pointer.PointerOrNil(viper.GetString("description")), + }} + + resp, err := c.c.Client.Apiv2().Size().List(ctx, connect.NewRequest(req)) + if err != nil { + return nil, fmt.Errorf("failed to get sizes: %w", err) + } + + return resp.Msg.Sizes, nil +} + +func (c *size) Create(rq any) (*apiv2.Size, error) { + panic("unimplemented") +} + +func (c *size) Delete(id string) (*apiv2.Size, error) { + panic("unimplemented") +} + +func (t *size) Convert(r *apiv2.Size) (string, any, any, error) { + panic("unimplemented") +} + +func (t *size) Update(rq any) (*apiv2.Size, error) { + panic("unimplemented") +} diff --git a/cmd/completion/size.go b/cmd/completion/size.go new file mode 100644 index 0000000..1ecbc09 --- /dev/null +++ b/cmd/completion/size.go @@ -0,0 +1,20 @@ +package completion + +import ( + "connectrpc.com/connect" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/spf13/cobra" +) + +func (c *Completion) SizeListCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + req := &apiv2.SizeServiceListRequest{} + resp, err := c.Client.Apiv2().Size().List(c.Ctx, connect.NewRequest(req)) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + var names []string + for _, s := range resp.Msg.Sizes { + names = append(names, s.Id) + } + return names, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/tableprinters/common.go b/cmd/tableprinters/common.go index 9fd32a3..6cbc632 100644 --- a/cmd/tableprinters/common.go +++ b/cmd/tableprinters/common.go @@ -49,6 +49,11 @@ func (t *TablePrinter) ToHeaderAndRows(data any, wide bool) ([]string, [][]strin case []*apiv2.Image: return t.ImageTable(d, wide) + case *apiv2.Size: + return t.SizeTable(pointer.WrapInSlice(d), wide) + case []*apiv2.Size: + return t.SizeTable(d, wide) + case *apiv2.Network: return t.NetworkTable(pointer.WrapInSlice(d), wide) case []*apiv2.Network: diff --git a/cmd/tableprinters/size.go b/cmd/tableprinters/size.go new file mode 100644 index 0000000..217abf2 --- /dev/null +++ b/cmd/tableprinters/size.go @@ -0,0 +1,48 @@ +package tableprinters + +import ( + "fmt" + + "github.com/dustin/go-humanize" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/metal-stack/metal-lib/pkg/pointer" + "github.com/olekukonko/tablewriter" +) + +func (t *TablePrinter) SizeTable(data []*apiv2.Size, wide bool) ([]string, [][]string, error) { + var ( + rows [][]string + header = []string{"ID", "Name", "Description", "CPU Range", "Memory Range", "Storage Range", "GPU Range"} + ) + + for _, size := range data { + var ( + cpu string + memory string + storage string + gpu string + ) + + for _, c := range size.Constraints { + switch c.Type { + case apiv2.SizeConstraintType_SIZE_CONSTRAINT_TYPE_CORES: + cpu = fmt.Sprintf("%d - %d", c.Min, c.Max) + case apiv2.SizeConstraintType_SIZE_CONSTRAINT_TYPE_MEMORY: + memory = fmt.Sprintf("%s - %s", humanize.Bytes(uint64(c.Min)), humanize.Bytes(uint64(c.Max))) //nolint:gosec + case apiv2.SizeConstraintType_SIZE_CONSTRAINT_TYPE_STORAGE: + storage = fmt.Sprintf("%s - %s", humanize.Bytes(uint64(c.Min)), humanize.Bytes(uint64(c.Max))) //nolint:gosec + case apiv2.SizeConstraintType_SIZE_CONSTRAINT_TYPE_GPU: + gpu = fmt.Sprintf("%s: %d - %d", pointer.SafeDeref(c.Identifier), c.Min, c.Max) + } + + } + + rows = append(rows, []string{size.Id, pointer.SafeDeref(size.Name), pointer.SafeDeref(size.Description), cpu, memory, storage, gpu}) + } + + t.t.MutateTable(func(table *tablewriter.Table) { + table.SetAutoWrapText(false) + }) + + return header, rows, nil +} diff --git a/docs/metalctlv2.md b/docs/metalctlv2.md index 965a721..276000a 100644 --- a/docs/metalctlv2.md +++ b/docs/metalctlv2.md @@ -29,6 +29,7 @@ cli for managing entities in metal-stack * [metalctlv2 markdown](metalctlv2_markdown.md) - create markdown documentation * [metalctlv2 network](metalctlv2_network.md) - manage network entities * [metalctlv2 project](metalctlv2_project.md) - manage project entities +* [metalctlv2 size](metalctlv2_size.md) - manage size entities * [metalctlv2 tenant](metalctlv2_tenant.md) - manage tenant entities * [metalctlv2 token](metalctlv2_token.md) - manage token entities * [metalctlv2 user](metalctlv2_user.md) - manage user entities diff --git a/docs/metalctlv2_size.md b/docs/metalctlv2_size.md new file mode 100644 index 0000000..a5f4c21 --- /dev/null +++ b/docs/metalctlv2_size.md @@ -0,0 +1,33 @@ +## metalctlv2 size + +manage size entities + +### Synopsis + +manage sizes which defines the cpu, gpu, memory and storage properties of machines + +### Options + +``` + -h, --help help for size +``` + +### Options inherited from parent commands + +``` + --api-token string the token used for api requests + --api-url string the url to the metal-stack.io api (default "https://api.metal-stack.io") + -c, --config string alternative config file path, (default is ~/.metal-stack/config.yaml) + --debug debug output + --force-color force colored output even without tty + -o, --output-format string output format (table|wide|markdown|json|yaml|template|jsonraw|yamlraw), wide is a table with more columns, jsonraw and yamlraw do not translate proto enums into string types but leave the original int32 values intact. (default "table") + --template string output template for template output-format, go template format. For property names inspect the output of -o json or -o yaml for reference. + --timeout duration request timeout used for api requests +``` + +### SEE ALSO + +* [metalctlv2](metalctlv2.md) - cli for managing entities in metal-stack +* [metalctlv2 size describe](metalctlv2_size_describe.md) - describes the size +* [metalctlv2 size list](metalctlv2_size_list.md) - list all sizes + diff --git a/docs/metalctlv2_size_describe.md b/docs/metalctlv2_size_describe.md new file mode 100644 index 0000000..98d7d0f --- /dev/null +++ b/docs/metalctlv2_size_describe.md @@ -0,0 +1,31 @@ +## metalctlv2 size describe + +describes the size + +``` +metalctlv2 size describe [flags] +``` + +### Options + +``` + -h, --help help for describe +``` + +### Options inherited from parent commands + +``` + --api-token string the token used for api requests + --api-url string the url to the metal-stack.io api (default "https://api.metal-stack.io") + -c, --config string alternative config file path, (default is ~/.metal-stack/config.yaml) + --debug debug output + --force-color force colored output even without tty + -o, --output-format string output format (table|wide|markdown|json|yaml|template|jsonraw|yamlraw), wide is a table with more columns, jsonraw and yamlraw do not translate proto enums into string types but leave the original int32 values intact. (default "table") + --template string output template for template output-format, go template format. For property names inspect the output of -o json or -o yaml for reference. + --timeout duration request timeout used for api requests +``` + +### SEE ALSO + +* [metalctlv2 size](metalctlv2_size.md) - manage size entities + diff --git a/docs/metalctlv2_size_list.md b/docs/metalctlv2_size_list.md new file mode 100644 index 0000000..cd5d5cd --- /dev/null +++ b/docs/metalctlv2_size_list.md @@ -0,0 +1,34 @@ +## metalctlv2 size list + +list all sizes + +``` +metalctlv2 size list [flags] +``` + +### Options + +``` + --description string size description to filter for + -h, --help help for list + --id string size id to filter for + --name string size name to filter for +``` + +### Options inherited from parent commands + +``` + --api-token string the token used for api requests + --api-url string the url to the metal-stack.io api (default "https://api.metal-stack.io") + -c, --config string alternative config file path, (default is ~/.metal-stack/config.yaml) + --debug debug output + --force-color force colored output even without tty + -o, --output-format string output format (table|wide|markdown|json|yaml|template|jsonraw|yamlraw), wide is a table with more columns, jsonraw and yamlraw do not translate proto enums into string types but leave the original int32 values intact. (default "table") + --template string output template for template output-format, go template format. For property names inspect the output of -o json or -o yaml for reference. + --timeout duration request timeout used for api requests +``` + +### SEE ALSO + +* [metalctlv2 size](metalctlv2_size.md) - manage size entities + diff --git a/go.mod b/go.mod index c719dd2..04a65b6 100644 --- a/go.mod +++ b/go.mod @@ -10,8 +10,8 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.18.0 github.com/google/go-cmp v0.7.0 - github.com/metal-stack/api v0.0.2-0.20250618071913-3260d4be4c0a - github.com/metal-stack/metal-lib v0.23.0 + github.com/metal-stack/api v0.0.2-0.20250708065749-a71fdf19addc + github.com/metal-stack/metal-lib v0.23.1 github.com/metal-stack/v v1.0.3 github.com/olekukonko/tablewriter v0.0.5 github.com/spf13/afero v1.14.0 @@ -59,7 +59,7 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/text v0.26.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apimachinery v0.33.2 // indirect diff --git a/go.sum b/go.sum index f5a2968..b74b054 100644 --- a/go.sum +++ b/go.sum @@ -54,10 +54,12 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/metal-stack/api v0.0.2-0.20250618071913-3260d4be4c0a h1:L9YYgqs53q73w4FuBEQXMtnYM6W9q8L9SC+EASmeGZY= -github.com/metal-stack/api v0.0.2-0.20250618071913-3260d4be4c0a/go.mod h1:hWv9QiPqNsiur7iE+Xa6byMhx5WznHMSQqsbjH0HfUg= +github.com/metal-stack/api v0.0.2-0.20250708065749-a71fdf19addc h1:dLj1QeyfUWNqneqDV21wNRmLdkIqIm2B2Ix1kxNxiOc= +github.com/metal-stack/api v0.0.2-0.20250708065749-a71fdf19addc/go.mod h1:k6l9ETFpaswp0JRHbFXNkPFs/InyGbv8ylOgrg4onfQ= github.com/metal-stack/metal-lib v0.23.0 h1:O0I/kF49GeJjMkvrhSdNS/bIcXd5KcqyX2fNngefF6E= github.com/metal-stack/metal-lib v0.23.0/go.mod h1:QiFb7TpSrvnLAHOlxLiUm1aG+1t5nPHsoDT/bw+F5r8= +github.com/metal-stack/metal-lib v0.23.1 h1:/Cpb9Js8RA2wwi12Gy+9D1tMhxh0Ge4VO+fjxMacSs4= +github.com/metal-stack/metal-lib v0.23.1/go.mod h1:QiFb7TpSrvnLAHOlxLiUm1aG+1t5nPHsoDT/bw+F5r8= github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs= github.com/metal-stack/v v1.0.3/go.mod h1:YTahEu7/ishwpYKnp/VaW/7nf8+PInogkfGwLcGPdXg= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -114,6 +116,8 @@ golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= From 3d1c4a417e6941565c6d52e693b2a4f17fbf312f Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Tue, 12 Aug 2025 08:47:58 +0200 Subject: [PATCH 02/10] Adopt to new metal-lib --- cmd/admin/v1/size.go | 20 +-------- cmd/login.go | 5 ++- cmd/root.go | 11 +++-- cmd/tableprinters/image.go | 5 +-- cmd/tableprinters/ip.go | 5 +-- cmd/tableprinters/project.go | 9 +--- cmd/tableprinters/size.go | 5 +-- cmd/tableprinters/tenant.go | 5 +-- cmd/tableprinters/token.go | 5 +-- go.mod | 40 +++++++++-------- go.sum | 84 ++++++++++++++++++------------------ 11 files changed, 83 insertions(+), 111 deletions(-) diff --git a/cmd/admin/v1/size.go b/cmd/admin/v1/size.go index f68388c..0872818 100644 --- a/cmd/admin/v1/size.go +++ b/cmd/admin/v1/size.go @@ -56,26 +56,8 @@ func (c *size) Get(id string) (*apiv2.Size, error) { func (c *size) Create(rq *adminv2.SizeServiceCreateRequest) (*apiv2.Size, error) { ctx, cancel := c.c.NewRequestContext() defer cancel() - labels, err := genericcli.LabelsToMap(viper.GetStringSlice("labels")) - if err != nil { - return nil, err - } - - req := &adminv2.SizeServiceCreateRequest{ - Size: &apiv2.Size{ - Id: viper.GetString("id"), - Name: pointer.PointerOrNil(viper.GetString("Name")), - Description: pointer.PointerOrNil(viper.GetString("description")), - Meta: &apiv2.Meta{ - Labels: &apiv2.Labels{ - Labels: labels, - }, - }, - Constraints: []*apiv2.SizeConstraint{}, // FIXME - }, - } - resp, err := c.c.Client.Adminv2().Size().Create(ctx, connect.NewRequest(req)) + resp, err := c.c.Client.Adminv2().Size().Create(ctx, connect.NewRequest(rq)) if err != nil { return nil, fmt.Errorf("failed to get size: %w", err) } diff --git a/cmd/login.go b/cmd/login.go index 8090102..da75063 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -117,7 +117,10 @@ func (l *login) login() error { ctx.Token = token if ctx.DefaultProject == "" { - mc := newApiClient(l.c.GetApiURL(), token) + mc, err := newApiClient(l.c.GetApiURL(), token) + if err != nil { + return err + } projects, err := mc.Apiv2().Project().List(context.Background(), connect.NewRequest(&apiv2.ProjectServiceListRequest{})) if err != nil { diff --git a/cmd/root.go b/cmd/root.go index 6f170a0..5320980 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,6 +1,7 @@ package cmd import ( + "log/slog" "os" client "github.com/metal-stack/api/go/client" @@ -108,7 +109,10 @@ func initConfigWithViperCtx(c *config.Config) error { return nil } - mc := newApiClient(c.GetApiURL(), c.GetToken()) + mc, err := newApiClient(c.GetApiURL(), c.GetToken()) + if err != nil { + return err + } c.Client = mc c.Completion.Client = mc @@ -118,12 +122,13 @@ func initConfigWithViperCtx(c *config.Config) error { return nil } -func newApiClient(apiURL, token string) client.Client { - dialConfig := client.DialConfig{ +func newApiClient(apiURL, token string) (client.Client, error) { + dialConfig := &client.DialConfig{ BaseURL: apiURL, Token: token, UserAgent: "metal-stack-cli", Debug: viper.GetBool("debug"), + Log: slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})), } return client.New(dialConfig) diff --git a/cmd/tableprinters/image.go b/cmd/tableprinters/image.go index c7f7460..d70d6c2 100644 --- a/cmd/tableprinters/image.go +++ b/cmd/tableprinters/image.go @@ -7,7 +7,6 @@ import ( "github.com/metal-stack/api/go/enum" apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" "github.com/metal-stack/metal-lib/pkg/pointer" - "github.com/olekukonko/tablewriter" ) func (t *TablePrinter) ImageTable(data []*apiv2.Image, wide bool) ([]string, [][]string, error) { @@ -42,9 +41,7 @@ func (t *TablePrinter) ImageTable(data []*apiv2.Image, wide bool) ([]string, [][ rows = append(rows, []string{image.Id, pointer.SafeDeref(image.Name), pointer.SafeDeref(image.Description), strings.Join(features, ","), expiresIn, *classification}) } - t.t.MutateTable(func(table *tablewriter.Table) { - table.SetAutoWrapText(false) - }) + t.t.DisableAutoWrap(false) return header, rows, nil } diff --git a/cmd/tableprinters/ip.go b/cmd/tableprinters/ip.go index f9c01b6..696ccae 100644 --- a/cmd/tableprinters/ip.go +++ b/cmd/tableprinters/ip.go @@ -6,7 +6,6 @@ import ( apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" "github.com/metal-stack/metal-lib/pkg/pointer" - "github.com/olekukonko/tablewriter" ) func (t *TablePrinter) IPTable(data []*apiv2.IP, wide bool) ([]string, [][]string, error) { @@ -52,9 +51,7 @@ func (t *TablePrinter) IPTable(data []*apiv2.IP, wide bool) ([]string, [][]strin } } - t.t.MutateTable(func(table *tablewriter.Table) { - table.SetAutoWrapText(false) - }) + t.t.DisableAutoWrap(false) return header, rows, nil } diff --git a/cmd/tableprinters/project.go b/cmd/tableprinters/project.go index 4462efd..27e893a 100644 --- a/cmd/tableprinters/project.go +++ b/cmd/tableprinters/project.go @@ -7,7 +7,6 @@ import ( "github.com/dustin/go-humanize" apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" "github.com/metal-stack/metal-lib/pkg/genericcli" - "github.com/olekukonko/tablewriter" ) func (t *TablePrinter) ProjectTable(data []*apiv2.Project, _ bool) ([]string, [][]string, error) { @@ -28,9 +27,7 @@ func (t *TablePrinter) ProjectTable(data []*apiv2.Project, _ bool) ([]string, [] rows = append(rows, row) } - t.t.MutateTable(func(table *tablewriter.Table) { - table.SetAutoWrapText(false) - }) + t.t.DisableAutoWrap(false) return header, rows, nil } @@ -52,9 +49,7 @@ func (t *TablePrinter) ProjectInviteTable(data []*apiv2.ProjectInvite, _ bool) ( rows = append(rows, row) } - t.t.MutateTable(func(table *tablewriter.Table) { - table.SetAutoWrapText(false) - }) + t.t.DisableAutoWrap(false) return header, rows, nil } diff --git a/cmd/tableprinters/size.go b/cmd/tableprinters/size.go index 217abf2..65f72c2 100644 --- a/cmd/tableprinters/size.go +++ b/cmd/tableprinters/size.go @@ -6,7 +6,6 @@ import ( "github.com/dustin/go-humanize" apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" "github.com/metal-stack/metal-lib/pkg/pointer" - "github.com/olekukonko/tablewriter" ) func (t *TablePrinter) SizeTable(data []*apiv2.Size, wide bool) ([]string, [][]string, error) { @@ -40,9 +39,7 @@ func (t *TablePrinter) SizeTable(data []*apiv2.Size, wide bool) ([]string, [][]s rows = append(rows, []string{size.Id, pointer.SafeDeref(size.Name), pointer.SafeDeref(size.Description), cpu, memory, storage, gpu}) } - t.t.MutateTable(func(table *tablewriter.Table) { - table.SetAutoWrapText(false) - }) + t.t.DisableAutoWrap(false) return header, rows, nil } diff --git a/cmd/tableprinters/tenant.go b/cmd/tableprinters/tenant.go index 74eda2d..5e09727 100644 --- a/cmd/tableprinters/tenant.go +++ b/cmd/tableprinters/tenant.go @@ -2,7 +2,6 @@ package tableprinters import ( "github.com/dustin/go-humanize" - "github.com/olekukonko/tablewriter" apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" ) @@ -73,9 +72,7 @@ func (t *TablePrinter) TenantInviteTable(data []*apiv2.TenantInvite, _ bool) ([] rows = append(rows, row) } - t.t.MutateTable(func(table *tablewriter.Table) { - table.SetAutoWrapText(false) - }) + t.t.DisableAutoWrap(false) return header, rows, nil } diff --git a/cmd/tableprinters/token.go b/cmd/tableprinters/token.go index 62644ff..c5a4712 100644 --- a/cmd/tableprinters/token.go +++ b/cmd/tableprinters/token.go @@ -7,7 +7,6 @@ import ( apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" "github.com/metal-stack/cli/pkg/helpers" - "github.com/olekukonko/tablewriter" ) func (t *TablePrinter) TokenTable(data []*apiv2.Token, _ bool) ([]string, [][]string, error) { @@ -38,9 +37,7 @@ func (t *TablePrinter) TokenTable(data []*apiv2.Token, _ bool) ([]string, [][]st rows = append(rows, row) } - t.t.MutateTable(func(table *tablewriter.Table) { - table.SetAutoWrapText(false) - }) + t.t.DisableAutoWrap(false) return header, rows, nil } diff --git a/go.mod b/go.mod index 04a65b6..58e23d2 100644 --- a/go.mod +++ b/go.mod @@ -10,32 +10,32 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.18.0 github.com/google/go-cmp v0.7.0 - github.com/metal-stack/api v0.0.2-0.20250708065749-a71fdf19addc - github.com/metal-stack/metal-lib v0.23.1 + github.com/metal-stack/api v0.0.11 + github.com/metal-stack/metal-lib v0.23.3 github.com/metal-stack/v v1.0.3 - github.com/olekukonko/tablewriter v0.0.5 github.com/spf13/afero v1.14.0 github.com/spf13/cobra v1.9.1 - github.com/spf13/pflag v1.0.6 + github.com/spf13/pflag v1.0.7 github.com/spf13/viper v1.20.1 github.com/stretchr/testify v1.10.0 - golang.org/x/net v0.41.0 - google.golang.org/grpc v1.73.0 - google.golang.org/protobuf v1.36.6 - sigs.k8s.io/yaml v1.5.0 + golang.org/x/net v0.43.0 + google.golang.org/grpc v1.74.2 + google.golang.org/protobuf v1.36.7 + sigs.k8s.io/yaml v1.6.0 ) require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250625184727-c923a0c2a132.1 // indirect + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.7-20250717185734-6c6e0d3c608e.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/go-openapi/errors v0.22.1 // indirect + github.com/go-openapi/errors v0.22.2 // indirect github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/go-viper/mapstructure/v2 v2.3.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/goccy/go-yaml v1.18.0 // indirect + github.com/golang-jwt/jwt/v5 v5.3.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.18.0 // indirect @@ -45,23 +45,25 @@ require ( github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/oklog/ulid v1.3.1 // indirect + github.com/olekukonko/errors v1.1.0 // indirect + github.com/olekukonko/ll v0.0.9 // indirect + github.com/olekukonko/tablewriter v1.0.9 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.9.0 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect + github.com/sagikazarmark/locafero v0.10.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/cast v1.9.2 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.mongodb.org/mongo-driver v1.17.4 // indirect - go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.26.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apimachinery v0.33.2 // indirect - sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + k8s.io/apimachinery v0.33.3 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect ) diff --git a/go.sum b/go.sum index b74b054..a4cf51c 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ bou.ke/monkey v1.0.2 h1:kWcnsrCNUatbxncxR/ThdYqbytgOIArtYWqcQLQzKLI= bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250625184727-c923a0c2a132.1 h1:6tCo3lsKNLqUjRPhyc8JuYWYUiQkulufxSDOfG1zgWQ= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250625184727-c923a0c2a132.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.7-20250717185734-6c6e0d3c608e.1 h1:/AZH8sVB6LHv8G+hZlAMCP31NevnesHwYgnlgS5Vt14= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.7-20250717185734-6c6e0d3c608e.1/go.mod h1:eva/VCrd8X7xuJw+JtwCEyrCKiRRASukFqmirnWBvFU= connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw= connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= @@ -21,16 +21,18 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU= -github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= +github.com/go-openapi/errors v0.22.2 h1:rdxhzcBUazEcGccKqbY1Y7NS8FDcMyIRr0934jrYnZg= +github.com/go-openapi/errors v0.22.2/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= -github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -51,23 +53,24 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/metal-stack/api v0.0.2-0.20250708065749-a71fdf19addc h1:dLj1QeyfUWNqneqDV21wNRmLdkIqIm2B2Ix1kxNxiOc= -github.com/metal-stack/api v0.0.2-0.20250708065749-a71fdf19addc/go.mod h1:k6l9ETFpaswp0JRHbFXNkPFs/InyGbv8ylOgrg4onfQ= -github.com/metal-stack/metal-lib v0.23.0 h1:O0I/kF49GeJjMkvrhSdNS/bIcXd5KcqyX2fNngefF6E= -github.com/metal-stack/metal-lib v0.23.0/go.mod h1:QiFb7TpSrvnLAHOlxLiUm1aG+1t5nPHsoDT/bw+F5r8= -github.com/metal-stack/metal-lib v0.23.1 h1:/Cpb9Js8RA2wwi12Gy+9D1tMhxh0Ge4VO+fjxMacSs4= -github.com/metal-stack/metal-lib v0.23.1/go.mod h1:QiFb7TpSrvnLAHOlxLiUm1aG+1t5nPHsoDT/bw+F5r8= +github.com/metal-stack/api v0.0.11 h1:aWMT1WTCIRm+DZFWZGUI08M/9LY2XIdtJZA5zJ/o1zo= +github.com/metal-stack/api v0.0.11/go.mod h1:GZEuAwwZXo1szv+0iLstU9sSra8gOIwSiquuRtGWxWo= +github.com/metal-stack/metal-lib v0.23.3 h1:ZcouyuCXy2bMZn+CB0yx1JdAl8SEkfjmlzNLyrmD/kA= +github.com/metal-stack/metal-lib v0.23.3/go.mod h1:29JMehA4KSeDovG9y1xgQkdc5pAk2/MBvOufRNSk5Bc= github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs= github.com/metal-stack/v v1.0.3/go.mod h1:YTahEu7/ishwpYKnp/VaW/7nf8+PInogkfGwLcGPdXg= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= +github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= +github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= +github.com/olekukonko/tablewriter v1.0.9 h1:XGwRsYLC2bY7bNd93Dk51bcPZksWZmLYuaTHR0FqfL8= +github.com/olekukonko/tablewriter v1.0.9/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= @@ -79,18 +82,19 @@ github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= -github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/sagikazarmark/locafero v0.10.0 h1:FM8Cv6j2KqIhM2ZK7HZjm4mpj9NBktLgowT1aN9q5Cc= +github.com/sagikazarmark/locafero v0.10.0/go.mod h1:Ieo3EUsjifvQu4NZwV5sPd4dwvu0OCgEQV7vjc9yDjw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= @@ -101,27 +105,23 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a h1:tPE/Kp+x9dMSwUm/uM0JKK0IfdiJkwAbSMSeZBXXJXc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= +google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= +google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= +google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= +google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -129,9 +129,9 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY= -k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= -sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= -sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= +k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= +k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= From 64bddb4787b511d0b78e02021467facf930a9259 Mon Sep 17 00:00:00 2001 From: Gerrit Date: Mon, 20 Oct 2025 15:17:41 +0200 Subject: [PATCH 03/10] Add admin tenant cmds. (#12) --- cmd/admin/v1/commands.go | 3 +- cmd/admin/v1/tenant.go | 105 +++++++++++++++++++++++++++++++ cmd/api/v1/tenant.go | 1 - cmd/common_test.go | 8 --- docs/metalctlv2_tenant_create.md | 1 - go.mod | 3 +- go.sum | 2 - 7 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 cmd/admin/v1/tenant.go diff --git a/cmd/admin/v1/commands.go b/cmd/admin/v1/commands.go index ddfef8c..997638a 100644 --- a/cmd/admin/v1/commands.go +++ b/cmd/admin/v1/commands.go @@ -14,8 +14,9 @@ func AddCmds(cmd *cobra.Command, c *config.Config) { Hidden: true, } - adminCmd.AddCommand(newTokenCmd(c)) adminCmd.AddCommand(newImageCmd(c)) + adminCmd.AddCommand(newTenantCmd(c)) + adminCmd.AddCommand(newTokenCmd(c)) cmd.AddCommand(adminCmd) } diff --git a/cmd/admin/v1/tenant.go b/cmd/admin/v1/tenant.go new file mode 100644 index 0000000..7c7895d --- /dev/null +++ b/cmd/admin/v1/tenant.go @@ -0,0 +1,105 @@ +package v1 + +import ( + "fmt" + + adminv2 "github.com/metal-stack/api/go/metalstack/admin/v2" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/metal-stack/cli/cmd/config" + "github.com/metal-stack/cli/cmd/sorters" + "github.com/metal-stack/metal-lib/pkg/genericcli" + "github.com/metal-stack/metal-lib/pkg/genericcli/printers" + "github.com/metal-stack/metal-lib/pkg/pointer" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +type tenant struct { + c *config.Config +} + +func newTenantCmd(c *config.Config) *cobra.Command { + w := &tenant{ + c: c, + } + + cmdsConfig := &genericcli.CmdsConfig[*adminv2.TenantServiceCreateRequest, any, *apiv2.Tenant]{ + BinaryName: config.BinaryName, + GenericCLI: genericcli.NewGenericCLI(w).WithFS(c.Fs), + Singular: "tenant", + Plural: "tenants", + Description: "manage api tenants", + Sorter: sorters.TenantSorter(), + DescribePrinter: func() printers.Printer { return c.DescribePrinter }, + ListPrinter: func() printers.Printer { return c.ListPrinter }, + ListCmdMutateFn: func(cmd *cobra.Command) { + cmd.Flags().String("name", "", "lists only tenants with the given name") + cmd.Flags().String("id", "", "lists only tenant with the given tenant id") + cmd.Flags().String("email", "", "lists only tenant with the given email address") + }, + CreateCmdMutateFn: func(cmd *cobra.Command) { + cmd.Flags().String("name", "", "the name of the tenant to create") + cmd.Flags().String("description", "", "the description of the tenant to create") + cmd.Flags().String("email", "", "the email of the tenant to create") + cmd.Flags().String("avatar-url", "", "the avatar url of the tenant to create") + }, + CreateRequestFromCLI: func() (*adminv2.TenantServiceCreateRequest, error) { + return &adminv2.TenantServiceCreateRequest{ + Name: viper.GetString("name"), + Description: pointer.PointerOrNil(viper.GetString("description")), + Email: pointer.PointerOrNil(viper.GetString("email")), + AvatarUrl: pointer.PointerOrNil(viper.GetString("avatar-url")), + }, nil + }, + OnlyCmds: genericcli.OnlyCmds(genericcli.ListCmd, genericcli.CreateCmd), + ValidArgsFn: w.c.Completion.AdminTenantListCompletion, + } + + return genericcli.NewCmds(cmdsConfig) +} + +func (c *tenant) Get(id string) (*apiv2.Tenant, error) { + panic("unimplemented") +} + +func (c *tenant) List() ([]*apiv2.Tenant, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + req := &adminv2.TenantServiceListRequest{ + Name: pointer.PointerOrNil(viper.GetString("name")), + Login: pointer.PointerOrNil(viper.GetString("id")), + Email: pointer.PointerOrNil(viper.GetString("email")), + } + + resp, err := c.c.Client.Adminv2().Tenant().List(ctx, req) + if err != nil { + return nil, fmt.Errorf("failed to list tenants: %w", err) + } + + return resp.GetTenants(), nil +} + +func (c *tenant) Create(rq *adminv2.TenantServiceCreateRequest) (*apiv2.Tenant, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + resp, err := c.c.Client.Adminv2().Tenant().Create(ctx, rq) + if err != nil { + return nil, fmt.Errorf("failed to create tenant: %w", err) + } + + return resp.Tenant, nil +} + +func (c *tenant) Delete(id string) (*apiv2.Tenant, error) { + panic("unimplemented") +} + +func (c *tenant) Convert(r *apiv2.Tenant) (string, *adminv2.TenantServiceCreateRequest, any, error) { + panic("unimplemented") +} + +func (c *tenant) Update(rq any) (*apiv2.Tenant, error) { + panic("unimplemented") +} diff --git a/cmd/api/v1/tenant.go b/cmd/api/v1/tenant.go index c26fe7e..f94258c 100644 --- a/cmd/api/v1/tenant.go +++ b/cmd/api/v1/tenant.go @@ -41,7 +41,6 @@ func newTenantCmd(c *config.Config) *cobra.Command { cmd.Flags().String("name", "", "the name of the tenant to create") cmd.Flags().String("description", "", "the description of the tenant to create") cmd.Flags().String("email", "", "the email of the tenant to create") - cmd.Flags().String("phone", "", "the phone number of the tenant to create") cmd.Flags().String("avatar-url", "", "the avatar url of the tenant to create") }, CreateRequestFromCLI: w.createRequestFromCLI, diff --git a/cmd/common_test.go b/cmd/common_test.go index ce7f960..bd80e37 100644 --- a/cmd/common_test.go +++ b/cmd/common_test.go @@ -8,11 +8,9 @@ import ( "os" "strings" "testing" - "time" "slices" - "bou.ke/monkey" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" apitests "github.com/metal-stack/api/go/tests" @@ -28,12 +26,6 @@ import ( "sigs.k8s.io/yaml" ) -var testTime = time.Date(2022, time.May, 19, 1, 2, 3, 4, time.UTC) - -func init() { - _ = monkey.Patch(time.Now, func() time.Time { return testTime }) -} - type Test[R any] struct { Name string Cmd func(want R) []string diff --git a/docs/metalctlv2_tenant_create.md b/docs/metalctlv2_tenant_create.md index 48b7a0e..86f7da7 100644 --- a/docs/metalctlv2_tenant_create.md +++ b/docs/metalctlv2_tenant_create.md @@ -27,7 +27,6 @@ metalctlv2 tenant create [flags] -h, --help help for create --name string the name of the tenant to create - --phone string the phone number of the tenant to create --skip-security-prompts skips security prompt for bulk operations --timestamps when used with --file (bulk operation): prints timestamps in-between the operations ``` diff --git a/go.mod b/go.mod index 1b2f7a0..fe32d8e 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,6 @@ module github.com/metal-stack/cli go 1.25 require ( - bou.ke/monkey v1.0.2 - connectrpc.com/connect v1.19.1 github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.18.0 github.com/google/go-cmp v0.7.0 @@ -23,6 +21,7 @@ require ( require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1 // indirect + connectrpc.com/connect v1.19.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/clipperhouse/uax29/v2 v2.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect diff --git a/go.sum b/go.sum index 4846edb..1f721ba 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -bou.ke/monkey v1.0.2 h1:kWcnsrCNUatbxncxR/ThdYqbytgOIArtYWqcQLQzKLI= -bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1 h1:31on4W/yPcV4nZHL4+UCiCvLPsMqe/vJcNg8Rci0scc= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1/go.mod h1:fUl8CEN/6ZAMk6bP8ahBJPUJw7rbp+j4x+wCcYi2IG4= connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14= From cf17498d8a82ccee59df0f448d867938612bbfbb Mon Sep 17 00:00:00 2001 From: Botond Gal Date: Wed, 22 Oct 2025 15:04:35 +0200 Subject: [PATCH 04/10] fix-docs-links (#7) --- README.md | 2 +- docs/metalctlv2_tenant_invite.md | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index e8cb47c..04a72be 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ In addition to the standard API services, there are also admin services that req You can access help for every service and command by using `--help` or `-h`. If you encounter any issues not covered in the help prompt, or if you have suggestions for improvement, please feel free to [contact us](mailto:support@metal-stack.io) or open an issue in this repository. Your feedback is greatly appreciated! -A list of all available services (excluding admin topics). For their associated commands, arguments and flags visit the correct [documentation](./docs/metal.md). +A list of all available services (excluding admin topics). For their associated commands, arguments and flags visit the [metalctlv2 documentation](./docs/metalctlv2.md). | Entity | Description | Documentation | |---------------|------------------------------------------------------------|-------------------------------------------------------| diff --git a/docs/metalctlv2_tenant_invite.md b/docs/metalctlv2_tenant_invite.md index 16bea96..aa0c0e5 100644 --- a/docs/metalctlv2_tenant_invite.md +++ b/docs/metalctlv2_tenant_invite.md @@ -26,6 +26,5 @@ manage tenant invites * [metalctlv2 tenant](metalctlv2_tenant.md) - manage tenant entities * [metalctlv2 tenant invite delete](metalctlv2_tenant_invite_delete.md) - deletes a pending invite * [metalctlv2 tenant invite generate-join-secret](metalctlv2_tenant_invite_generate-join-secret.md) - generate an invite secret to share with the new member -* [metalctlv2 tenant invite join](metalctlv2_tenant_invite_join.md) - join a tenant of someone who shared an invite secret with you * [metalctlv2 tenant invite list](metalctlv2_tenant_invite_list.md) - lists the currently pending invites From 04c8797a880011486f1a13a80d19ef8e1e65fa9a Mon Sep 17 00:00:00 2001 From: AnnaSchreiner Date: Tue, 2 Dec 2025 15:29:00 +0100 Subject: [PATCH 05/10] Add admin project list (#13) --- cmd/admin/v1/commands.go | 1 + cmd/admin/v1/project.go | 77 ++++++++++++++++++++++++++++++++++++++++ go.mod | 9 ++--- go.sum | 20 ++++++----- 4 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 cmd/admin/v1/project.go diff --git a/cmd/admin/v1/commands.go b/cmd/admin/v1/commands.go index 997638a..52d9c49 100644 --- a/cmd/admin/v1/commands.go +++ b/cmd/admin/v1/commands.go @@ -17,6 +17,7 @@ func AddCmds(cmd *cobra.Command, c *config.Config) { adminCmd.AddCommand(newImageCmd(c)) adminCmd.AddCommand(newTenantCmd(c)) adminCmd.AddCommand(newTokenCmd(c)) + adminCmd.AddCommand(newProjectCmd(c)) cmd.AddCommand(adminCmd) } diff --git a/cmd/admin/v1/project.go b/cmd/admin/v1/project.go new file mode 100644 index 0000000..7228228 --- /dev/null +++ b/cmd/admin/v1/project.go @@ -0,0 +1,77 @@ +package v1 + +import ( + "fmt" + + adminv2 "github.com/metal-stack/api/go/metalstack/admin/v2" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/metal-stack/cli/cmd/config" + "github.com/metal-stack/cli/cmd/sorters" + "github.com/metal-stack/metal-lib/pkg/genericcli" + "github.com/metal-stack/metal-lib/pkg/genericcli/printers" + "github.com/metal-stack/metal-lib/pkg/pointer" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +type project struct { + c *config.Config +} + +func newProjectCmd(c *config.Config) *cobra.Command { + w := &project{ + c: c, + } + + cmdsConfig := &genericcli.CmdsConfig[*apiv2.ProjectServiceCreateRequest, *apiv2.ProjectServiceUpdateRequest, *apiv2.Project]{ + BinaryName: config.BinaryName, + GenericCLI: genericcli.NewGenericCLI(w).WithFS(c.Fs), + Singular: "project", + Plural: "projects", + Description: "manage api projects", + Sorter: sorters.ProjectSorter(), + DescribePrinter: func() printers.Printer { return c.DescribePrinter }, + ListPrinter: func() printers.Printer { return c.ListPrinter }, + ListCmdMutateFn: func(cmd *cobra.Command) { + cmd.Flags().String("tenant", "", "lists only projects with the given tenant") + }, + } + + return genericcli.NewCmds(cmdsConfig) +} + +func (c *project) Get(id string) (*apiv2.Project, error) { + panic("unimplemented") +} + +func (c *project) List() ([]*apiv2.Project, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + req := &adminv2.ProjectServiceListRequest{ + Tenant: pointer.PointerOrNil(viper.GetString("tenant")), + } + + resp, err := c.c.Client.Adminv2().Project().List(ctx, req) + if err != nil { + return nil, fmt.Errorf("failed to list projects: %w", err) + } + + return resp.GetProjects(), nil +} + +func (c *project) Create(rq *apiv2.ProjectServiceCreateRequest) (*apiv2.Project, error) { + panic("unimplemented") +} + +func (c *project) Delete(id string) (*apiv2.Project, error) { + panic("unimplemented") +} + +func (c *project) Convert(r *apiv2.Project) (string, *apiv2.ProjectServiceCreateRequest, *apiv2.ProjectServiceUpdateRequest, error) { + panic("unimplemented") +} + +func (c *project) Update(rq *apiv2.ProjectServiceUpdateRequest) (*apiv2.Project, error) { + panic("unimplemented") +} diff --git a/go.mod b/go.mod index fe32d8e..9399bc5 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.18.0 github.com/google/go-cmp v0.7.0 - github.com/metal-stack/api v0.0.31 + github.com/metal-stack/api v0.0.35 github.com/metal-stack/metal-lib v0.23.5 github.com/metal-stack/v v1.0.3 github.com/spf13/afero v1.15.0 @@ -35,11 +35,12 @@ require ( github.com/golang-jwt/jwt/v5 v5.3.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect - github.com/klauspost/connect-compress/v2 v2.0.0 // indirect + github.com/klauspost/compress v1.18.1 // indirect + github.com/klauspost/connect-compress/v2 v2.1.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.19 // indirect + github.com/minio/minlz v1.0.1 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.1.0 // indirect @@ -57,7 +58,7 @@ require ( go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/sys v0.37.0 // indirect - golang.org/x/text v0.30.0 // indirect + golang.org/x/text v0.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apimachinery v0.34.1 // indirect diff --git a/go.sum b/go.sum index 1f721ba..cbca136 100644 --- a/go.sum +++ b/go.sum @@ -39,10 +39,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/klauspost/connect-compress/v2 v2.0.0 h1:L7TVsLa6Oo9Hkkb6r3DwSrhBbcWlXjneqBj7fCRXviU= -github.com/klauspost/connect-compress/v2 v2.0.0/go.mod h1:604CD9JSAjGqtVzCM4SRgM/9TFTkWBcp+2wlQfGyJ6c= +github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co= +github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0= +github.com/klauspost/connect-compress/v2 v2.1.0 h1:8fM8QrVeHT69e5VVSh4yjDaQASYIvOp2uMZq7nVLj2U= +github.com/klauspost/connect-compress/v2 v2.1.0/go.mod h1:Ayurh2wscMMx3AwdGGVL+ylSR5316WfApREDgsqHyH8= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -53,12 +53,16 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= -github.com/metal-stack/api v0.0.31 h1:ivgaqYuWFrGO4IZS/9ViwkuV1AzytZlji6zgDnANo+s= -github.com/metal-stack/api v0.0.31/go.mod h1:LcJkrJPJRdLPFaeCiWy5tL0dJXU74kq+vFe5uc/Cm9U= +github.com/metal-stack/api v0.0.35-0.20251124101516-a3076941d0f8 h1:PGBiFwASqhtmI6dGzVo0IEVQiBTIsQ2eo3pMriPViNY= +github.com/metal-stack/api v0.0.35-0.20251124101516-a3076941d0f8/go.mod h1:EBwS/oZr5tIcnV6hM7iK4aBQrw4wlU7vF5p+O1p3YIU= +github.com/metal-stack/api v0.0.35 h1:XxxYKTscSeYJg/ftL519nY3FAZ01atPeyD7+Zz/amQQ= +github.com/metal-stack/api v0.0.35/go.mod h1:EBwS/oZr5tIcnV6hM7iK4aBQrw4wlU7vF5p+O1p3YIU= github.com/metal-stack/metal-lib v0.23.5 h1:ozrkB3DNr3Cqn8nkBvmzc/KKpYqC1j1mv2OVOj8i7Ac= github.com/metal-stack/metal-lib v0.23.5/go.mod h1:7uyHIrE19dkLwCZyeh2jmd7IEq5pEpzrzUGLoMN1eqY= github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs= github.com/metal-stack/v v1.0.3/go.mod h1:YTahEu7/ishwpYKnp/VaW/7nf8+PInogkfGwLcGPdXg= +github.com/minio/minlz v1.0.1 h1:OUZUzXcib8diiX+JYxyRLIdomyZYzHct6EShOKtQY2A= +github.com/minio/minlz v1.0.1/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= @@ -109,8 +113,8 @@ golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From da7e395c8005645c448cc84933f9f3d9f278f150 Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Wed, 3 Dec 2025 09:15:53 +0100 Subject: [PATCH 06/10] Fix naming --- cmd/admin/v1/size.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/admin/v1/size.go b/cmd/admin/v1/size.go index dc4b5f8..5cb10fa 100644 --- a/cmd/admin/v1/size.go +++ b/cmd/admin/v1/size.go @@ -46,7 +46,7 @@ func (c *size) Get(id string) (*apiv2.Size, error) { resp, err := c.c.Client.Apiv2().Size().Get(ctx, req) if err != nil { - return nil, fmt.Errorf("failed to get image: %w", err) + return nil, fmt.Errorf("failed to get size: %w", err) } return resp.Size, nil @@ -116,7 +116,7 @@ func (c *size) Update(rq *adminv2.SizeServiceUpdateRequest) (*apiv2.Size, error) resp, err := c.c.Client.Adminv2().Size().Update(ctx, req) if err != nil { - return nil, fmt.Errorf("failed to get image: %w", err) + return nil, fmt.Errorf("failed to get size: %w", err) } return resp.Size, nil From 97a8c5b0248774882002185b2f02c39e6aaf2199 Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Wed, 3 Dec 2025 15:28:12 +0100 Subject: [PATCH 07/10] Methods from api --- cmd/completion/token.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/cmd/completion/token.go b/cmd/completion/token.go index b7498f5..e404115 100644 --- a/cmd/completion/token.go +++ b/cmd/completion/token.go @@ -7,6 +7,7 @@ import ( "github.com/spf13/cobra" apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" + "github.com/metal-stack/api/go/permissions" ) func (c *Completion) TokenListCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -66,11 +67,8 @@ func (c *Completion) TokenAdminRoleCompletion(cmd *cobra.Command, args []string, } func (c *Completion) TokenPermissionsCompletionfunc(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - methods, err := c.Client.Apiv2().Method().TokenScopedList(c.Ctx, &apiv2.MethodServiceTokenScopedListRequest{}) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } + methods := permissions.GetServicePermissions().Methods subject := "" if s, _, ok := strings.Cut(toComplete, "="); ok { subject = s @@ -79,8 +77,8 @@ func (c *Completion) TokenPermissionsCompletionfunc(cmd *cobra.Command, args []s if subject == "" { var perms []string - for _, p := range methods.Permissions { - perms = append(perms, p.Subject) + for p := range methods { + perms = append(perms, p) } return perms, cobra.ShellCompDirectiveNoFileComp @@ -90,8 +88,8 @@ func (c *Completion) TokenPermissionsCompletionfunc(cmd *cobra.Command, args []s var perms []string - for _, p := range methods.Permissions { - perms = append(perms, p.Methods...) + for p := range methods { + perms = append(perms, p) } return perms, cobra.ShellCompDirectiveDefault From 4688d91f2de97c3b8633034839e592c150115024 Mon Sep 17 00:00:00 2001 From: ostempel Date: Thu, 4 Dec 2025 16:56:53 +0100 Subject: [PATCH 08/10] change default provider to openid-connect --- cmd/login.go | 4 ++-- cmd/logout.go | 4 ++-- docs/metalctlv2_login.md | 2 +- docs/metalctlv2_logout.md | 2 +- docs/metalctlv2_tenant_invite.md | 1 + 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cmd/login.go b/cmd/login.go index 739d77d..960a172 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -36,12 +36,12 @@ func newLoginCmd(c *config.Config) *cobra.Command { }, } - loginCmd.Flags().String("provider", "oidc", "the provider used to login with") + loginCmd.Flags().String("provider", "openid-connect", "the provider used to login with") loginCmd.Flags().String("context", "", "the context into which the token gets injected, if not specified it uses the current context or creates a context named default in case there is no current context set") loginCmd.Flags().String("admin-role", "", "operators can use this flag to issue an admin token with the token retrieved from login and store this into context") genericcli.Must(loginCmd.Flags().MarkHidden("admin-role")) - genericcli.Must(loginCmd.RegisterFlagCompletionFunc("provider", cobra.FixedCompletions([]string{"oidc"}, cobra.ShellCompDirectiveNoFileComp))) + genericcli.Must(loginCmd.RegisterFlagCompletionFunc("provider", cobra.FixedCompletions([]string{"openid-connect"}, cobra.ShellCompDirectiveNoFileComp))) genericcli.Must(loginCmd.RegisterFlagCompletionFunc("admin-role", c.Completion.TokenAdminRoleCompletion)) return loginCmd diff --git a/cmd/logout.go b/cmd/logout.go index 19788e2..1cd4f5b 100644 --- a/cmd/logout.go +++ b/cmd/logout.go @@ -33,10 +33,10 @@ func newLogoutCmd(c *config.Config) *cobra.Command { }, } - logoutCmd.Flags().String("provider", "oidc", "the provider used to logout with") + logoutCmd.Flags().String("provider", "openid-connect", "the provider used to logout with") logoutCmd.Flags().String("context-name", "", "the context into which the token gets injected, if not specified it uses the current context or creates a context named default in case there is no current context set") - genericcli.Must(logoutCmd.RegisterFlagCompletionFunc("provider", cobra.FixedCompletions([]string{"oidc"}, cobra.ShellCompDirectiveNoFileComp))) + genericcli.Must(logoutCmd.RegisterFlagCompletionFunc("provider", cobra.FixedCompletions([]string{"openid-connect"}, cobra.ShellCompDirectiveNoFileComp))) return logoutCmd } diff --git a/docs/metalctlv2_login.md b/docs/metalctlv2_login.md index 7315df6..28e50a8 100644 --- a/docs/metalctlv2_login.md +++ b/docs/metalctlv2_login.md @@ -11,7 +11,7 @@ metalctlv2 login [flags] ``` --context string the context into which the token gets injected, if not specified it uses the current context or creates a context named default in case there is no current context set -h, --help help for login - --provider string the provider used to login with (default "oidc") + --provider string the provider used to login with (default "openid-connect") ``` ### Options inherited from parent commands diff --git a/docs/metalctlv2_logout.md b/docs/metalctlv2_logout.md index ee3a40b..bc7f032 100644 --- a/docs/metalctlv2_logout.md +++ b/docs/metalctlv2_logout.md @@ -11,7 +11,7 @@ metalctlv2 logout [flags] ``` --context-name string the context into which the token gets injected, if not specified it uses the current context or creates a context named default in case there is no current context set -h, --help help for logout - --provider string the provider used to logout with (default "oidc") + --provider string the provider used to logout with (default "openid-connect") ``` ### Options inherited from parent commands diff --git a/docs/metalctlv2_tenant_invite.md b/docs/metalctlv2_tenant_invite.md index aa0c0e5..16bea96 100644 --- a/docs/metalctlv2_tenant_invite.md +++ b/docs/metalctlv2_tenant_invite.md @@ -26,5 +26,6 @@ manage tenant invites * [metalctlv2 tenant](metalctlv2_tenant.md) - manage tenant entities * [metalctlv2 tenant invite delete](metalctlv2_tenant_invite_delete.md) - deletes a pending invite * [metalctlv2 tenant invite generate-join-secret](metalctlv2_tenant_invite_generate-join-secret.md) - generate an invite secret to share with the new member +* [metalctlv2 tenant invite join](metalctlv2_tenant_invite_join.md) - join a tenant of someone who shared an invite secret with you * [metalctlv2 tenant invite list](metalctlv2_tenant_invite_list.md) - lists the currently pending invites From 2d04d638b5fdb45526842106d4ee4e00ad33ee7a Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Fri, 12 Dec 2025 14:31:15 +0100 Subject: [PATCH 09/10] fix --- cmd/completion/token.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/completion/token.go b/cmd/completion/token.go index e404115..70cc895 100644 --- a/cmd/completion/token.go +++ b/cmd/completion/token.go @@ -84,8 +84,6 @@ func (c *Completion) TokenPermissionsCompletionfunc(cmd *cobra.Command, args []s return perms, cobra.ShellCompDirectiveNoFileComp } - // FIXME: completion does not work at this point, investigate why - var perms []string for p := range methods { From b67bc1edb21cf974468192191a71f6a628fe2e89 Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Sun, 11 Jan 2026 15:15:49 +0100 Subject: [PATCH 10/10] Updates --- cmd/root.go | 3 ++- go.mod | 28 +++++++++++++-------------- go.sum | 56 ++++++++++++++++++++++++++--------------------------- 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 9bb0ce1..34157e5 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "log/slog" "os" @@ -10,13 +11,13 @@ import ( adminv2 "github.com/metal-stack/cli/cmd/admin/v1" apiv2 "github.com/metal-stack/cli/cmd/api/v1" + "github.com/metal-stack/cli/cmd/completion" "github.com/metal-stack/cli/cmd/config" "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" "github.com/spf13/viper" - "golang.org/x/net/context" ) func Execute() { diff --git a/go.mod b/go.mod index 5322ad6..daacf7c 100644 --- a/go.mod +++ b/go.mod @@ -1,39 +1,38 @@ module github.com/metal-stack/cli -go 1.25 +go 1.25.0 require ( github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.18.0 github.com/google/go-cmp v0.7.0 - github.com/metal-stack/api v0.0.35 + github.com/metal-stack/api v0.0.36 github.com/metal-stack/metal-lib v0.23.5 github.com/metal-stack/v v1.0.3 github.com/spf13/afero v1.15.0 - github.com/spf13/cobra v1.10.1 + github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 - golang.org/x/net v0.47.0 - google.golang.org/grpc v1.77.0 - google.golang.org/protobuf v1.36.10 + google.golang.org/grpc v1.78.0 + google.golang.org/protobuf v1.36.11 sigs.k8s.io/yaml v1.6.0 ) require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1 // indirect + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1 // indirect connectrpc.com/connect v1.19.1 // indirect - github.com/clipperhouse/displaywidth v0.6.0 // indirect + github.com/clipperhouse/displaywidth v0.6.2 // indirect github.com/clipperhouse/stringish v0.1.1 // indirect github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/go-openapi/errors v0.22.4 // indirect + github.com/go-openapi/errors v0.22.6 // indirect github.com/go-openapi/strfmt v0.25.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect - github.com/goccy/go-yaml v1.19.0 // indirect + github.com/goccy/go-yaml v1.19.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -58,11 +57,12 @@ require ( go.mongodb.org/mongo-driver v1.17.6 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/text v0.31.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/text v0.33.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apimachinery v0.34.2 // indirect + k8s.io/apimachinery v0.35.0 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect ) diff --git a/go.sum b/go.sum index 0f0cd3e..7718693 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1 h1:31on4W/yPcV4nZHL4+UCiCvLPsMqe/vJcNg8Rci0scc= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1/go.mod h1:fUl8CEN/6ZAMk6bP8ahBJPUJw7rbp+j4x+wCcYi2IG4= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1 h1:j9yeqTWEFrtimt8Nng2MIeRrpoCvQzM9/g25XTvqUGg= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1/go.mod h1:tvtbpgaVXZX4g6Pn+AnzFycuRK3MOz5HJfEGeEllXYM= connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14= connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w= github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= -github.com/clipperhouse/displaywidth v0.6.0 h1:k32vueaksef9WIKCNcoqRNyKbyvkvkysNYnAWz2fN4s= -github.com/clipperhouse/displaywidth v0.6.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= +github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo= +github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= @@ -23,8 +23,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/go-openapi/errors v0.22.4 h1:oi2K9mHTOb5DPW2Zjdzs/NIvwi2N3fARKaTJLdNabaM= -github.com/go-openapi/errors v0.22.4/go.mod h1:z9S8ASTUqx7+CP1Q8dD8ewGH/1JWFFLX/2PmAYNQLgk= +github.com/go-openapi/errors v0.22.6 h1:eDxcf89O8odEnohIXwEjY1IB4ph5vmbUsBMsFNwXWPo= +github.com/go-openapi/errors v0.22.6/go.mod h1:z9S8ASTUqx7+CP1Q8dD8ewGH/1JWFFLX/2PmAYNQLgk= github.com/go-openapi/strfmt v0.25.0 h1:7R0RX7mbKLa9EYCTHRcCuIPcaqlyQiWNPTXwClK0saQ= github.com/go-openapi/strfmt v0.25.0/go.mod h1:nNXct7OzbwrMY9+5tLX4I21pzcmE6ccMGXl3jFdPfn8= github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= @@ -33,8 +33,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/goccy/go-yaml v1.19.0 h1:EmkZ9RIsX+Uq4DYFowegAuJo8+xdX3T/2dwNPXbxEYE= -github.com/goccy/go-yaml v1.19.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -59,8 +59,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= -github.com/metal-stack/api v0.0.35 h1:XxxYKTscSeYJg/ftL519nY3FAZ01atPeyD7+Zz/amQQ= -github.com/metal-stack/api v0.0.35/go.mod h1:EBwS/oZr5tIcnV6hM7iK4aBQrw4wlU7vF5p+O1p3YIU= +github.com/metal-stack/api v0.0.36 h1:h2vf25SpcTH6BuXHUPbtObcnGSAkoEU6rVIgYSyrm8s= +github.com/metal-stack/api v0.0.36/go.mod h1:4wrEGm7Qfm/PQ9zsl64A2T9efHYL/0b21+Wjla3TF+k= github.com/metal-stack/metal-lib v0.23.5 h1:ozrkB3DNr3Cqn8nkBvmzc/KKpYqC1j1mv2OVOj8i7Ac= github.com/metal-stack/metal-lib v0.23.5/go.mod h1:7uyHIrE19dkLwCZyeh2jmd7IEq5pEpzrzUGLoMN1eqY= github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs= @@ -81,8 +81,8 @@ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= @@ -91,8 +91,8 @@ github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= -github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= -github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -110,19 +110,19 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= -google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= +google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -130,8 +130,8 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4= -k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/apimachinery v0.35.0 h1:Z2L3IHvPVv/MJ7xRxHEtk6GoJElaAqDCCU0S6ncYok8= +k8s.io/apimachinery v0.35.0/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=