Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/admin/v2/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func AddCmds(cmd *cobra.Command, c *config.Config) {
adminCmd.AddCommand(newComponentCmd(c))
adminCmd.AddCommand(newImageCmd(c))
adminCmd.AddCommand(newProjectCmd(c))
adminCmd.AddCommand(newSizeCmd(c))
adminCmd.AddCommand(newSwitchCmd(c))
adminCmd.AddCommand(newTaskCmd(c))
adminCmd.AddCommand(newTenantCmd(c))
Expand Down
3 changes: 1 addition & 2 deletions cmd/admin/v2/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,9 @@ func (c *image) Delete(id string) (*apiv2.Image, error) {
}
func (c *image) List() ([]*apiv2.Image, error) {
panic("unimplemented")

}
func (c *image) Convert(r *apiv2.Image) (string, *adminv2.ImageServiceCreateRequest, *adminv2.ImageServiceUpdateRequest, error) {

func (c *image) Convert(r *apiv2.Image) (string, *adminv2.ImageServiceCreateRequest, *adminv2.ImageServiceUpdateRequest, error) {
return r.Id, &adminv2.ImageServiceCreateRequest{
Image: &apiv2.Image{
Id: r.Id,
Expand Down
143 changes: 143 additions & 0 deletions cmd/admin/v2/size.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package v2

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 size struct {
c *config.Config
}

func newSizeCmd(c *config.Config) *cobra.Command {
w := &size{
c: c,
}

cmdsConfig := &genericcli.CmdsConfig[*adminv2.SizeServiceCreateRequest, *adminv2.SizeServiceUpdateRequest, *apiv2.Size]{
BinaryName: config.BinaryName,
GenericCLI: genericcli.NewGenericCLI(w).WithFS(c.Fs),
Singular: "size",
Plural: "sizes",
Description: "manage sizes which defines the cpu, gpu, memory and storage properties of machines",
Sorter: sorters.SizeSorter(),
DescribePrinter: func() printers.Printer { return c.DescribePrinter },
ListPrinter: func() printers.Printer { return c.ListPrinter },
ValidArgsFn: c.Completion.SizeListCompletion,
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")
},
UpdateCmdMutateFn: func(cmd *cobra.Command) {
cmd.Flags().StringP("id", "", "", "size id to update")
cmd.Flags().StringP("name", "", "", "size name to update")
cmd.Flags().StringP("description", "", "", "size description to update")
},
CreateCmdMutateFn: func(cmd *cobra.Command) {

},
// TODO: create from CLI might be nice to have?
}

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 create size: %w", err)
}

return resp.Size, nil
}

func (c *size) Delete(id string) (*apiv2.Size, error) {
ctx, cancel := c.c.NewRequestContext()
defer cancel()

resp, err := c.c.Client.Adminv2().Size().Delete(ctx, &adminv2.SizeServiceDeleteRequest{Id: id})
if err != nil {
return nil, fmt.Errorf("failed to delete 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) Update(rq *adminv2.SizeServiceUpdateRequest) (*apiv2.Size, error) {
ctx, cancel := c.c.NewRequestContext()
defer cancel()

resp, err := c.c.Client.Adminv2().Size().Update(ctx, rq)
if err != nil {
return nil, fmt.Errorf("failed to update size: %w", err)
}

return resp.Size, nil
}

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,
UpdateMeta: &apiv2.UpdateMeta{
LockingStrategy: apiv2.OptimisticLockingStrategy_OPTIMISTIC_LOCKING_STRATEGY_CLIENT,
UpdatedAt: r.Meta.UpdatedAt,
},
Labels: &apiv2.UpdateLabels{},
}, nil
}
1 change: 1 addition & 0 deletions cmd/api/v2/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func AddCmds(cmd *cobra.Command, c *config.Config) {
cmd.AddCommand(newIPCmd(c))
cmd.AddCommand(newMethodsCmd(c))
cmd.AddCommand(newProjectCmd(c))
cmd.AddCommand(newSizeCmd(c))
cmd.AddCommand(newTenantCmd(c))
cmd.AddCommand(newTokenCmd(c))
cmd.AddCommand(newUserCmd(c))
Expand Down
94 changes: 94 additions & 0 deletions cmd/api/v2/size.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package v2

import (
"fmt"

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 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",
Sorter: sorters.SizeSorter(),
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")
}
19 changes: 19 additions & 0 deletions cmd/completion/size.go
Original file line number Diff line number Diff line change
@@ -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
}
21 changes: 21 additions & 0 deletions cmd/sorters/size.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package sorters

import (
apiv2 "github.com/metal-stack/api/go/metalstack/api/v2"
"github.com/metal-stack/metal-lib/pkg/multisort"
"github.com/metal-stack/metal-lib/pkg/pointer"
)

func SizeSorter() *multisort.Sorter[*apiv2.Size] {
return multisort.New(multisort.FieldMap[*apiv2.Size]{
"id": func(a, b *apiv2.Size, descending bool) multisort.CompareResult {
return multisort.Compare(a.Id, b.Id, descending)
},
"name": func(a, b *apiv2.Size, descending bool) multisort.CompareResult {
return multisort.Compare(pointer.SafeDeref(a.Name), pointer.SafeDeref(b.Name), descending)
},
"description": func(a, b *apiv2.Size, descending bool) multisort.CompareResult {
return multisort.Compare(pointer.SafeDeref(a.Description), pointer.SafeDeref(b.Description), descending)
},
}, multisort.Keys{{ID: "id"}})
}
5 changes: 5 additions & 0 deletions cmd/tableprinters/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ func (t *TablePrinter) ToHeaderAndRows(data any, wide bool) ([]string, [][]strin
case []*apiv2.Health:
return t.HealthTable(d, wide)

case *apiv2.Size:
return t.SizeTable(pointer.WrapInSlice(d), wide)
case []*apiv2.Size:
return t.SizeTable(d, wide)

case []*apiv2.Switch:
return t.SwitchTable(d, wide)
case []SwitchDetail:
Expand Down
44 changes: 44 additions & 0 deletions cmd/tableprinters/size.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
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
}
1 change: 1 addition & 0 deletions docs/metalctlv2.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ cli for managing entities in metal-stack
* [metalctlv2 logout](metalctlv2_logout.md) - logout
* [metalctlv2 markdown](metalctlv2_markdown.md) - create markdown documentation
* [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
Expand Down
Loading
Loading