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
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ generate: deps
mockgen --destination ./internal/mocks/hosts_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/hosts.go
mockgen --destination ./internal/mocks/ssh_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/ssh_keys.go
mockgen --destination ./internal/mocks/ssl_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/ssl_certificates.go
mockgen --destination ./internal/mocks/load_balancers_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/load_balancers.go
sed -i '' 's|github.com/serverscom/srvctl/vendor/github.com/serverscom/serverscom-go-client/pkg|github.com/serverscom/serverscom-go-client/pkg|g' \
./internal/mocks/ssh_service.go \
./internal/mocks/hosts_service.go \
./internal/mocks/ssl_service.go \
./internal/mocks/load_balancers_service.go \
./internal/mocks/collection.go

90 changes: 0 additions & 90 deletions cmd/base/list.go
Original file line number Diff line number Diff line change
@@ -1,105 +1,15 @@
package base

import (
"log"
"strings"

serverscom "github.com/serverscom/serverscom-go-client/pkg"
"github.com/spf13/cobra"
)

type ListOptions[T any] interface {
AddFlags(*cobra.Command)
ApplyToCollection(serverscom.Collection[T])
}

type AllPager interface {
AllPages() bool
}

func NewListOptions[T any](opts ...ListOptions[T]) []ListOptions[T] {
return opts
}

// CollectionFactory is a function type that creates a typed resource collection
// with configurable verbosity level
// type CollectionFactory[T any] func(verbose bool) serverscom.Collection[T]
type CollectionFactory[T any] func(verbose bool, args ...string) serverscom.Collection[T]

// BaseListOptions is a base options struct for list commands
type BaseListOptions[T any] struct {
perPage int
page int
sorting string
direction string
allPages bool
}

// AddFlags adds common list flags to the command
func (o *BaseListOptions[T]) AddFlags(cmd *cobra.Command) {
flags := cmd.Flags()
flags.IntVar(&o.perPage, "per-page", 0, "Number of items per page")
flags.IntVar(&o.page, "page", 0, "Page number")
flags.StringVar(&o.sorting, "sorting", "", "Sort field")
flags.StringVar(&o.direction, "direction", "", "Sort direction (ASC or DESC)")
flags.BoolVarP(&o.allPages, "all", "A", false, "Get all pages of resources")

flags.String("type", "", "")
if err := flags.MarkHidden("type"); err != nil {
log.Fatal(err)
}
}

// ApplyToCollection applies the options to a collection
func (o *BaseListOptions[T]) ApplyToCollection(collection serverscom.Collection[T]) {

if o.sorting != "" {
collection.SetParam("sort", o.sorting)
}
if o.direction != "" {
collection.SetParam("direction", strings.ToUpper(o.direction))
}
if o.perPage > 0 {
collection.SetPerPage(o.perPage)
}
if o.page > 0 {
collection.SetPage(o.page)
}
}

// AllPages returns true if all pages should be retrieved
func (o *BaseListOptions[T]) AllPages() bool {
return o.allPages
}

type LabelSelectorOption[T any] struct {
labelSelector string
}

func (o *LabelSelectorOption[T]) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.labelSelector, "label-selector", "", "Filter results by labels")
}

func (o *LabelSelectorOption[T]) ApplyToCollection(collection serverscom.Collection[T]) {
if o.labelSelector != "" {
collection.SetParam("label_selector", o.labelSelector)
}
}

type SearchPatternOption[T any] struct {
searchPattern string
}

func (o *SearchPatternOption[T]) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.searchPattern, "search-pattern", "", "Return resources containing the parameter value in its name")
}

func (o *SearchPatternOption[T]) ApplyToCollection(collection serverscom.Collection[T]) {
if o.searchPattern != "" {
collection.SetParam("search_pattern", o.searchPattern)
}
}

// NewListCmd base list command for different collections
func NewListCmd[T any](use string, entityName string, colFactory CollectionFactory[T], cmdContext *CmdContext, opts ...ListOptions[T]) *cobra.Command {
aliases := []string{}
Expand Down
128 changes: 128 additions & 0 deletions cmd/base/list_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package base

import (
"log"
"strings"

serverscom "github.com/serverscom/serverscom-go-client/pkg"
"github.com/spf13/cobra"
)

type ListOptions[T any] interface {
AddFlags(*cobra.Command)
ApplyToCollection(serverscom.Collection[T])
}

type AllPager interface {
AllPages() bool
}

func NewListOptions[T any](opts ...ListOptions[T]) []ListOptions[T] {
return opts
}

// BaseListOptions is a base options struct for list commands
type BaseListOptions[T any] struct {
perPage int
page int
sorting string
direction string
allPages bool
}

// AddFlags adds common list flags to the command
func (o *BaseListOptions[T]) AddFlags(cmd *cobra.Command) {
flags := cmd.Flags()
flags.IntVar(&o.perPage, "per-page", 0, "Number of items per page")
flags.IntVar(&o.page, "page", 0, "Page number")
flags.StringVar(&o.sorting, "sorting", "", "Sort field")
flags.StringVar(&o.direction, "direction", "", "Sort direction (ASC or DESC)")
flags.BoolVarP(&o.allPages, "all", "A", false, "Get all pages of resources")

flags.String("type", "", "")
if err := flags.MarkHidden("type"); err != nil {
log.Fatal(err)
}
}

// ApplyToCollection applies the options to a collection
func (o *BaseListOptions[T]) ApplyToCollection(collection serverscom.Collection[T]) {

if o.sorting != "" {
collection.SetParam("sort", o.sorting)
}
if o.direction != "" {
collection.SetParam("direction", strings.ToUpper(o.direction))
}
if o.perPage > 0 {
collection.SetPerPage(o.perPage)
}
if o.page > 0 {
collection.SetPage(o.page)
}
}

// AllPages returns true if all pages should be retrieved
func (o *BaseListOptions[T]) AllPages() bool {
return o.allPages
}

// label selector option
type LabelSelectorOption[T any] struct {
labelSelector string
}

func (o *LabelSelectorOption[T]) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.labelSelector, "label-selector", "", "Filter results by labels")
}

func (o *LabelSelectorOption[T]) ApplyToCollection(collection serverscom.Collection[T]) {
if o.labelSelector != "" {
collection.SetParam("label_selector", o.labelSelector)
}
}

// search pattern option
type SearchPatternOption[T any] struct {
searchPattern string
}

func (o *SearchPatternOption[T]) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.searchPattern, "search-pattern", "", "Return resources containing the parameter value in its name")
}

func (o *SearchPatternOption[T]) ApplyToCollection(collection serverscom.Collection[T]) {
if o.searchPattern != "" {
collection.SetParam("search_pattern", o.searchPattern)
}
}

// location id option
type LocationIDOption[T any] struct {
locationID string
}

func (o *LocationIDOption[T]) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.locationID, "location-id", "", "Filter results by location ID")
}

func (o *LocationIDOption[T]) ApplyToCollection(collection serverscom.Collection[T]) {
if o.locationID != "" {
collection.SetParam("location_id", o.locationID)
}
}

// cluster id option
type ClusterIDOption[T any] struct {
clusterID string
}

func (o *ClusterIDOption[T]) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.clusterID, "cluster-id", "", "Filter results by cluster ID")
}

func (o *ClusterIDOption[T]) ApplyToCollection(collection serverscom.Collection[T]) {
if o.clusterID != "" {
collection.SetParam("cluster_id", o.clusterID)
}
}
5 changes: 2 additions & 3 deletions cmd/entities/hosts/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,8 @@ func newHostTypeCmd(cmdContext *base.CmdContext, hostTypeCmd HostTypeCmd) *cobra
hostCmd := &cobra.Command{
Use: hostTypeCmd.use,
Short: hostTypeCmd.shortDesc,
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
Args: base.NoArgs,
Run: base.UsageRun,
}

hostCmd.AddCommand(newListCmd(cmdContext, &hostTypeCmd))
Expand Down
87 changes: 87 additions & 0 deletions cmd/entities/load_balancers/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package loadbalancers

import (
"context"
"fmt"
"log"

serverscom "github.com/serverscom/serverscom-go-client/pkg"
"github.com/serverscom/srvctl/cmd/base"
"github.com/spf13/cobra"
)

type LBCreator interface {
Create(ctx context.Context, client *serverscom.Client, input any) (any, error)
NewCreateInput() any
}

type LBL4CreateMgr struct{}

func (c *LBL4CreateMgr) Create(ctx context.Context, client *serverscom.Client, input any) (any, error) {
lbInput, ok := input.(*serverscom.L4LoadBalancerCreateInput)
if !ok {
return nil, fmt.Errorf("invalid input type for L4 LB")
}
return client.LoadBalancers.CreateL4LoadBalancer(ctx, *lbInput)
}

func (c *LBL4CreateMgr) NewCreateInput() any {
return &serverscom.L4LoadBalancerCreateInput{}
}

type LBL7CreateMgr struct{}

func (c *LBL7CreateMgr) Create(ctx context.Context, client *serverscom.Client, input any) (any, error) {
lbInput, ok := input.(*serverscom.L7LoadBalancerCreateInput)
if !ok {
return nil, fmt.Errorf("invalid input type for L7 LB")
}
return client.LoadBalancers.CreateL7LoadBalancer(ctx, *lbInput)
}

func (c *LBL7CreateMgr) NewCreateInput() any {
return &serverscom.L7LoadBalancerCreateInput{}
}

func newAddCmd(cmdContext *base.CmdContext, lbType *LBTypeCmd) *cobra.Command {
var path string
cmd := &cobra.Command{
Use: "add --input <path>",
Short: fmt.Sprintf("Create %s", lbType.entityName),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
manager := cmdContext.GetManager()
ctx, cancel := base.SetupContext(cmd, manager)
defer cancel()

base.SetupProxy(cmd, manager)

input := lbType.managers.createMgr.NewCreateInput()

if err := base.ReadInputJSON(path, cmd.InOrStdin(), input); err != nil {
return err
}

scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient()

lb, err := lbType.managers.createMgr.Create(ctx, scClient, input)
if err != nil {
return err
}

if lb != nil {
formatter := cmdContext.GetOrCreateFormatter(cmd)
return formatter.Format(lb)
}

return nil
},
}

cmd.Flags().StringVarP(&path, "input", "i", "", "path to input file or '-' to read from stdin")
if err := cmd.MarkFlagRequired("input"); err != nil {
log.Fatal(err)
}

return cmd
}
Loading
Loading