Skip to content

Commit

Permalink
Size reservations CRUD (#263)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerrit91 authored Sep 30, 2024
1 parent ff31f7d commit 647a984
Show file tree
Hide file tree
Showing 22 changed files with 1,140 additions and 306 deletions.
12 changes: 12 additions & 0 deletions cmd/completion/size.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,15 @@ func (c *Completion) SizeListCompletion(cmd *cobra.Command, args []string, toCom
}
return names, cobra.ShellCompDirectiveNoFileComp
}

func (c *Completion) SizeReservationsListCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
resp, err := c.client.Size().ListSizeReservations(size.NewListSizeReservationsParams(), nil)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
var names []string
for _, s := range resp.Payload {
names = append(names, *s.ID)
}
return names, cobra.ShellCompDirectiveNoFileComp
}
70 changes: 10 additions & 60 deletions cmd/size.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,36 +62,7 @@ func newSizeCmd(c *config) *cobra.Command {
},
}

reservationsCmd := &cobra.Command{
Use: "reservations",
Short: "manage size reservations",
RunE: func(cmd *cobra.Command, args []string) error {
return w.listReverations()
},
}

listReservationsCmd := &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "list size reservations",
RunE: func(cmd *cobra.Command, args []string) error {
return w.listReverations()
},
}

listReservationsCmd.Flags().String("size-id", "", "the size-id to filter")
listReservationsCmd.Flags().String("project", "", "the project to filter")
listReservationsCmd.Flags().String("tenant", "", "the tenant to filter")
listReservationsCmd.Flags().String("partition", "", "the partition to filter")

genericcli.Must(listReservationsCmd.RegisterFlagCompletionFunc("size-id", c.comp.SizeListCompletion))
genericcli.Must(listReservationsCmd.RegisterFlagCompletionFunc("project", c.comp.ProjectListCompletion))
genericcli.Must(listReservationsCmd.RegisterFlagCompletionFunc("tenant", c.comp.TenantListCompletion))
genericcli.Must(listReservationsCmd.RegisterFlagCompletionFunc("partition", c.comp.PartitionListCompletion))

genericcli.AddSortFlag(listReservationsCmd, sorters.SizeReservationsSorter())

reservationsCmd.AddCommand(listReservationsCmd)
reservationsCmd := newSizeReservationsCmd(c)

suggestCmd := &cobra.Command{
Use: "suggest <id>",
Expand Down Expand Up @@ -178,11 +149,10 @@ func sizeResponseToCreate(r *models.V1SizeResponse) *models.V1SizeCreateRequest
})
}
return &models.V1SizeCreateRequest{
Constraints: constraints,
Description: r.Description,
ID: r.ID,
Name: r.Name,
Reservations: r.Reservations,
Constraints: constraints,
Description: r.Description,
ID: r.ID,
Name: r.Name,
}
}

Expand All @@ -197,36 +167,16 @@ func sizeResponseToUpdate(r *models.V1SizeResponse) *models.V1SizeUpdateRequest
})
}
return &models.V1SizeUpdateRequest{
Constraints: constraints,
Description: r.Description,
ID: r.ID,
Name: r.Name,
Labels: r.Labels,
Reservations: r.Reservations,
Constraints: constraints,
Description: r.Description,
ID: r.ID,
Name: r.Name,
Labels: r.Labels,
}
}

// non-generic command handling

func (c sizeCmd) listReverations() error {
resp, err := c.client.Size().ListSizeReservations(size.NewListSizeReservationsParams().WithBody(&models.V1SizeReservationListRequest{
Projectid: viper.GetString("project"),
Sizeid: viper.GetString("size-id"),
Tenant: viper.GetString("tenant"),
Partitionid: viper.GetString("partition"),
}), nil)
if err != nil {
return err
}

err = sorters.SizeReservationsSorter().SortBy(resp.Payload)
if err != nil {
return err
}

return c.listPrinter.Print(resp.Payload)
}

func (c *sizeCmd) suggest(args []string) error {
sizeid, _ := genericcli.GetExactlyOneArg(args)

Expand Down
235 changes: 235 additions & 0 deletions cmd/size_reservations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
package cmd

import (
"errors"
"fmt"

sizemodel "github.com/metal-stack/metal-go/api/client/size"
"github.com/metal-stack/metal-go/api/models"
"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/metal-stack/metalctl/cmd/sorters"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

type sizeReservationsCmd struct {
*config
}

func newSizeReservationsCmd(c *config) *cobra.Command {
w := sizeReservationsCmd{
config: c,
}

cmdsConfig := &genericcli.CmdsConfig[*models.V1SizeReservationCreateRequest, *models.V1SizeReservationUpdateRequest, *models.V1SizeReservationResponse]{
BinaryName: binaryName,
GenericCLI: genericcli.NewGenericCLI(w).WithFS(c.fs),
Singular: "reservation",
Plural: "reservations",
Description: "manage size reservations",
Aliases: []string{"rs"},
Sorter: sorters.SizeReservationsSorter(),
ValidArgsFn: c.comp.SizeReservationsListCompletion,
DescribePrinter: func() printers.Printer { return c.describePrinter },
ListPrinter: func() printers.Printer { return c.listPrinter },
CreateRequestFromCLI: func() (*models.V1SizeReservationCreateRequest, error) {
labels, err := genericcli.LabelsToMap(viper.GetStringSlice("labels"))
if err != nil {
return nil, err
}

return &models.V1SizeReservationCreateRequest{
Amount: pointer.PointerOrNil(int32(viper.GetInt32("amount"))),
Description: viper.GetString("description"),
ID: pointer.PointerOrNil(viper.GetString("id")),
Labels: labels,
Partitionids: viper.GetStringSlice("partitions"),
Projectid: pointer.PointerOrNil(viper.GetString("project")),
Sizeid: pointer.PointerOrNil(viper.GetString("size")),
}, nil
},
CreateCmdMutateFn: func(cmd *cobra.Command) {
cmd.Flags().Int32("amount", 0, "the amount to associate with this reservation")
cmd.Flags().String("id", "", "the id to associate with this reservation")
cmd.Flags().String("size", "", "the size id to associate with this reservation")
cmd.Flags().String("project", "", "the project id to associate with this reservation")
cmd.Flags().StringSlice("partitions", nil, "the partition ids to associate with this reservation")
cmd.Flags().StringSlice("labels", nil, "the labels to associate with this reservation")
cmd.Flags().String("description", "", "the description to associate with this reservation")

genericcli.Must(cmd.RegisterFlagCompletionFunc("size", c.comp.SizeListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("project", c.comp.ProjectListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("partitions", c.comp.PartitionListCompletion))
},
UpdateRequestFromCLI: func(args []string) (*models.V1SizeReservationUpdateRequest, error) {
id, err := genericcli.GetExactlyOneArg(args)
if err != nil {
return nil, err
}

labels, err := genericcli.LabelsToMap(viper.GetStringSlice("labels"))
if err != nil {
return nil, err
}

return &models.V1SizeReservationUpdateRequest{ //nolint:exhaustruct
Amount: pointer.PointerOrNil(int32(viper.GetInt32("amount"))),
Description: viper.GetString("description"),
ID: &id,
Labels: labels,
Partitionids: viper.GetStringSlice("partitions"),
}, nil
},
UpdateCmdMutateFn: func(cmd *cobra.Command) {
cmd.Flags().Int32("amount", 0, "the amount to associate with this reservation")
cmd.Flags().StringSlice("partitions", nil, "the partition ids to associate with this reservation")
cmd.Flags().StringSlice("labels", nil, "the labels to associate with this reservation")
cmd.Flags().String("description", "", "the description to associate with this reservation")

genericcli.Must(cmd.RegisterFlagCompletionFunc("partitions", c.comp.PartitionListCompletion))
},
ListCmdMutateFn: func(cmd *cobra.Command) {
cmd.Flags().String("id", "", "the id to filter")
cmd.Flags().String("size", "", "the size id to filter")
cmd.Flags().String("project", "", "the project id to filter")
cmd.Flags().String("partition", "", "the partition id to filter")

genericcli.Must(cmd.RegisterFlagCompletionFunc("id", c.comp.SizeReservationsListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("size", c.comp.SizeListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("project", c.comp.ProjectListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("partition", c.comp.PartitionListCompletion))
},
}

usageCmd := &cobra.Command{
Use: "usage",
Short: "see current usage of size reservations",
RunE: func(cmd *cobra.Command, args []string) error {
return w.usage()
},
}

usageCmd.Flags().String("size-id", "", "the size-id to filter")
usageCmd.Flags().String("project", "", "the project to filter")
usageCmd.Flags().String("partition", "", "the partition to filter")

genericcli.Must(usageCmd.RegisterFlagCompletionFunc("size-id", c.comp.SizeListCompletion))
genericcli.Must(usageCmd.RegisterFlagCompletionFunc("project", c.comp.ProjectListCompletion))
genericcli.Must(usageCmd.RegisterFlagCompletionFunc("partition", c.comp.PartitionListCompletion))

genericcli.AddSortFlag(usageCmd, sorters.SizeReservationsUsageSorter())

return genericcli.NewCmds(cmdsConfig, usageCmd)
}

func (c sizeReservationsCmd) Get(id string) (*models.V1SizeReservationResponse, error) {
resp, err := c.client.Size().GetSizeReservation(sizemodel.NewGetSizeReservationParams().WithID(id), nil)
if err != nil {
return nil, err
}

return resp.Payload, nil
}

func (c sizeReservationsCmd) List() ([]*models.V1SizeReservationResponse, error) {
resp, err := c.client.Size().FindSizeReservations(sizemodel.NewFindSizeReservationsParams().WithBody(&models.V1SizeReservationListRequest{
ID: viper.GetString("id"),
Partitionid: viper.GetString("parition"),
Projectid: viper.GetString("project"),
Sizeid: viper.GetString("size"),
}), nil)
if err != nil {
return nil, err
}

return resp.Payload, nil
}

func (c sizeReservationsCmd) Delete(id string) (*models.V1SizeReservationResponse, error) {
resp, err := c.client.Size().DeleteSizeReservation(sizemodel.NewDeleteSizeReservationParams().WithID(id), nil)
if err != nil {
return nil, err
}

return resp.Payload, nil
}

func (c sizeReservationsCmd) Create(rq *models.V1SizeReservationCreateRequest) (*models.V1SizeReservationResponse, error) {
resp, err := c.client.Size().CreateSizeReservation(sizemodel.NewCreateSizeReservationParams().WithBody(rq), nil)
if err != nil {
var r *sizemodel.CreateSizeReservationConflict
if errors.As(err, &r) {
return nil, genericcli.AlreadyExistsError()
}
return nil, err
}

return resp.Payload, nil
}

func (c sizeReservationsCmd) Update(rq *models.V1SizeReservationUpdateRequest) (*models.V1SizeReservationResponse, error) {
resp, err := c.client.Size().UpdateSizeReservation(sizemodel.NewUpdateSizeReservationParams().WithBody(rq), nil)
if err != nil {
return nil, err
}

return resp.Payload, nil
}

func (c sizeReservationsCmd) Convert(r *models.V1SizeReservationResponse) (string, *models.V1SizeReservationCreateRequest, *models.V1SizeReservationUpdateRequest, error) {
if r.ID == nil {
return "", nil, nil, fmt.Errorf("id is nil")
}
return *r.ID, sizeReservationResponseToCreate(r), sizeReservationResponseToUpdate(r), nil
}

func sizeReservationResponseToCreate(r *models.V1SizeReservationResponse) *models.V1SizeReservationCreateRequest {
return &models.V1SizeReservationCreateRequest{
Amount: r.Amount,
Description: r.Description,
ID: r.ID,
Labels: r.Labels,
Name: r.Name,
Partitionids: r.Partitionids,
Projectid: r.Projectid,
Sizeid: r.Sizeid,
}
}

func sizeReservationResponseToUpdate(r *models.V1SizeReservationResponse) *models.V1SizeReservationUpdateRequest {
return &models.V1SizeReservationUpdateRequest{
Amount: r.Amount,
Description: r.Description,
ID: r.ID,
Labels: r.Labels,
Name: r.Name,
Partitionids: r.Partitionids,
}
}

// non-generic command handling

func (c *sizeReservationsCmd) usage() error {
sortKeys, err := genericcli.ParseSortFlags()
if err != nil {
return err
}

resp, err := c.client.Size().SizeReservationsUsage(sizemodel.NewSizeReservationsUsageParams().WithBody(&models.V1SizeReservationListRequest{
Partitionid: viper.GetString("parition"),
Projectid: viper.GetString("project"),
Sizeid: viper.GetString("size"),
}), nil)
if err != nil {
return err
}

err = sorters.SizeReservationsUsageSorter().SortBy(resp.Payload, sortKeys...)
if err != nil {
return err
}

return c.listPrinter.Print(resp.Payload)
}
Loading

0 comments on commit 647a984

Please sign in to comment.