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/cmd/admin/v1/commands.go b/cmd/admin/v1/commands.go index 0410c4f..af08f82 100644 --- a/cmd/admin/v1/commands.go +++ b/cmd/admin/v1/commands.go @@ -17,7 +17,10 @@ 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(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/cmd/admin/v1/size.go b/cmd/admin/v1/size.go new file mode 100644 index 0000000..5cb10fa --- /dev/null +++ b/cmd/admin/v1/size.go @@ -0,0 +1,123 @@ +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/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, req) + if err != nil { + return nil, fmt.Errorf("failed to get size: %w", err) + } + + return resp.Size, nil +} + +func (c *size) Create(rq *adminv2.SizeServiceCreateRequest) (*apiv2.Size, error) { + ctx, cancel := c.c.NewRequestContext() + defer cancel() + + resp, err := c.c.Client.Adminv2().Size().Create(ctx, rq) + if err != nil { + return nil, fmt.Errorf("failed to get size: %w", err) + } + + return resp.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, req) + if err != nil { + return nil, fmt.Errorf("failed to delete size: %w", err) + } + + return resp.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, req) + if err != nil { + return nil, fmt.Errorf("failed to get size: %w", err) + } + + return resp.Size, nil +} 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/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..e99d808 --- /dev/null +++ b/cmd/api/v1/size.go @@ -0,0 +1,92 @@ +package v1 + +import ( + "fmt" + + 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, req) + if err != nil { + return nil, fmt.Errorf("failed to get size: %w", err) + } + + return resp.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, req) + if err != nil { + return nil, fmt.Errorf("failed to get sizes: %w", err) + } + + return resp.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/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/cmd/completion/size.go b/cmd/completion/size.go new file mode 100644 index 0000000..8ebd814 --- /dev/null +++ b/cmd/completion/size.go @@ -0,0 +1,19 @@ +package completion + +import ( + 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, req) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + var names []string + for _, s := range resp.Sizes { + names = append(names, s.Id) + } + return names, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/completion/token.go b/cmd/completion/token.go index b7498f5..70cc895 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,19 +77,17 @@ 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 } - // FIXME: completion does not work at this point, investigate why - 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 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/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/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..65f72c2 --- /dev/null +++ b/cmd/tableprinters/size.go @@ -0,0 +1,45 @@ +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" +) + +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.DisableAutoWrap(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_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_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/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 1e25ad5..daacf7c 100644 --- a/go.mod +++ b/go.mod @@ -1,68 +1,68 @@ module github.com/metal-stack/cli -go 1.25 +go 1.25.0 require ( - bou.ke/monkey v1.0.2 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.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.46.0 - google.golang.org/grpc v1.76.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/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/clipperhouse/uax29/v2 v2.2.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.3 // indirect - github.com/go-openapi/strfmt v0.24.0 // 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.18.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 - github.com/klauspost/compress v1.18.0 // indirect - github.com/klauspost/connect-compress/v2 v2.0.0 // indirect + github.com/klauspost/compress v1.18.2 // 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 - github.com/olekukonko/ll v0.1.2 // indirect - github.com/olekukonko/tablewriter v1.1.0 // indirect + github.com/olekukonko/ll v0.1.3 // indirect + github.com/olekukonko/tablewriter v1.1.2 // 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.12.0 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/stretchr/objx v0.5.3 // indirect github.com/subosito/gotenv v1.6.0 // indirect - go.mongodb.org/mongo-driver v1.17.4 // indirect + 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.37.0 // indirect - golang.org/x/text v0.30.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f // 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.1 // 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 14826f0..7718693 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,15 @@ -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= +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/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= 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/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY= -github.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= +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= +github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= @@ -23,16 +23,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.3 h1:k6Hxa5Jg1TUyZnOwV2Lh81j8ayNw5VVYLvKrp4zFKFs= -github.com/go-openapi/errors v0.22.3/go.mod h1:+WvbaBBULWCOna//9B9TbLNGSFOfF8lY9dw4hGiEiKQ= -github.com/go-openapi/strfmt v0.24.0 h1:dDsopqbI3wrrlIzeXRbqMihRNnjzGC+ez4NQaAAJLuc= -github.com/go-openapi/strfmt v0.24.0/go.mod h1:Lnn1Bk9rZjXxU9VMADbEEOo7D7CDyKGLsSKekhFr7s4= +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= +github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= 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.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/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= @@ -43,10 +45,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.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= +github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +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= @@ -57,30 +59,30 @@ 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.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= 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= github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= 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.1.2 h1:lkg/k/9mlsy0SxO5aC+WEpbdT5K83ddnNhAepz7TQc0= -github.com/olekukonko/ll v0.1.2/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew= -github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY= -github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= +github.com/olekukonko/ll v0.1.3 h1:sV2jrhQGq5B3W0nENUISCR6azIPf7UBUpVq0x/y70Fg= +github.com/olekukonko/ll v0.1.3/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew= +github.com/olekukonko/tablewriter v1.1.2 h1:L2kI1Y5tZBct/O/TyZK1zIE9GlBj/TVs+AY5tZDCDSc= +github.com/olekukonko/tablewriter v1.1.2/go.mod h1:z7SYPugVqGVavWoA2sGsFIoOVNmEHxUAAMrhXONtfkg= 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= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -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= @@ -89,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= @@ -102,25 +104,25 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 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.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss= +go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= 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.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +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.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= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f h1:1FTH6cpXFsENbPR5Bu8NQddPSaUUE6NA2XdZdDSAJK4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= -google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= -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= @@ -128,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.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= -k8s.io/apimachinery v0.34.1/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=