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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.vscode
vendor
dist
.idea/
cp.out
.DS_Store
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ generate: deps
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
mockgen --destination ./internal/mocks/load_balancer_clusters_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/load_balancer_clusters.go
mockgen --destination ./internal/mocks/racks_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/racks.go
mockgen --destination ./internal/mocks/invoices_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/invoices.go
mockgen --destination ./internal/mocks/account_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/accounts.go
Expand All @@ -24,6 +25,7 @@ generate: deps
./internal/mocks/hosts_service.go \
./internal/mocks/ssl_service.go \
./internal/mocks/load_balancers_service.go \
./internal/mocks/load_balancer_clusters_service.go \
./internal/mocks/racks_service.go \
./internal/mocks/invoices_service.go \
./internal/mocks/account_service.go \
Expand Down
39 changes: 39 additions & 0 deletions cmd/entities/load_balancer_clusters/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package loadbalancerclusters

import (
"github.com/serverscom/srvctl/cmd/base"
"github.com/spf13/cobra"
)

func newGetCmd(cmdContext *base.CmdContext) *cobra.Command {
cmd := &cobra.Command{
Use: "get <id>",
Short: "Get LB Cluster",
Long: "Get LB Cluster by id",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
manager := cmdContext.GetManager()

ctx, cancel := base.SetupContext(cmd, manager)
defer cancel()

base.SetupProxy(cmd, manager)

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

id := args[0]
lbCluster, err := scClient.LoadBalancerClusters.GetLoadBalancerCluster(ctx, id)
if err != nil {
return err
}

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

return cmd
}
21 changes: 21 additions & 0 deletions cmd/entities/load_balancer_clusters/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package loadbalancerclusters

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

func newListCmd(cmdContext *base.CmdContext) *cobra.Command {
factory := func(verbose bool, args ...string) serverscom.Collection[serverscom.LoadBalancerCluster] {
scClient := cmdContext.GetClient().SetVerbose(verbose).GetScClient()
return scClient.LoadBalancerClusters.Collection()
}

opts := base.NewListOptions(
&base.BaseListOptions[serverscom.LoadBalancerCluster]{},
&base.SearchPatternOption[serverscom.LoadBalancerCluster]{},
)

return base.NewListCmd("list", "lb-clusters", factory, cmdContext, opts...)
}
38 changes: 38 additions & 0 deletions cmd/entities/load_balancer_clusters/load_balancer_clusters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package loadbalancerclusters

import (
"log"

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

func NewCmd(cmdContext *base.CmdContext) *cobra.Command {
lbClusterEntity, err := entities.Registry.GetEntityFromValue(serverscom.LoadBalancerCluster{})
if err != nil {
log.Fatal(err)
}
entitiesMap := make(map[string]entities.EntityInterface)
entitiesMap["lb-clusters"] = lbClusterEntity
cmd := &cobra.Command{
Use: "lb-clusters",
Short: "Manage LB Clusters",
PersistentPreRunE: base.CombinePreRunE(
base.CheckFormatterFlags(cmdContext, entitiesMap),
base.CheckEmptyContexts(cmdContext),
),
Args: base.NoArgs,
Run: base.UsageRun,
}

cmd.AddCommand(
newListCmd(cmdContext),
newGetCmd(cmdContext),
)

base.AddFormatFlags(cmd)

return cmd
}
245 changes: 245 additions & 0 deletions cmd/entities/load_balancer_clusters/load_balancer_clusters_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
package loadbalancerclusters

import (
"errors"
"fmt"
"path/filepath"
"testing"
"time"

. "github.com/onsi/gomega"
serverscom "github.com/serverscom/serverscom-go-client/pkg"
"github.com/serverscom/srvctl/cmd/testutils"
"github.com/serverscom/srvctl/internal/mocks"
"go.uber.org/mock/gomock"
)

var (
testId = "testId"
fixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "lb-clusters")
fixedTime = time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC)
testLbCluster = serverscom.LoadBalancerCluster{
ID: testId,
Name: "test-lb-cluster",
LocationID: 1,
Status: "active",
Created: fixedTime,
Updated: fixedTime,
}
)

func TestGetLoadBalancerClusterCmd(t *testing.T) {
testCases := []struct {
id string
name string
output string
expectedOutput []byte
expectError bool
}{
{
name: "get LB Cluster in default format",
id: testId,
output: "",
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.txt")),
},
{
name: "get LB Cluster in JSON format",
id: testId,
output: "json",
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.json")),
},
{
name: "get LB Cluster in YAML format",
id: testId,
output: "yaml",
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.yaml")),
},
{
name: "get LB Cluster with error",
id: testId,
expectError: true,
},
}

mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

lbClustersServiceHandler := mocks.NewMockLoadBalancerClustersService(mockCtrl)

scClient := serverscom.NewClientWithEndpoint("", "")
scClient.LoadBalancerClusters = lbClustersServiceHandler

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
g := NewWithT(t)

var err error
if tc.expectError {
err = errors.New("some error")
}
lbClustersServiceHandler.EXPECT().
GetLoadBalancerCluster(gomock.Any(), testId).
Return(&testLbCluster, err)

testCmdContext := testutils.NewTestCmdContext(scClient)
lbClusterCmd := NewCmd(testCmdContext)

args := []string{"lb-clusters", "get", fmt.Sprint(tc.id)}
if tc.output != "" {
args = append(args, "--output", tc.output)
}

builder := testutils.NewTestCommandBuilder().
WithCommand(lbClusterCmd).
WithArgs(args)

cmd := builder.Build()

err = cmd.Execute()

if tc.expectError {
g.Expect(err).To(HaveOccurred())
} else {
g.Expect(err).To(BeNil())
g.Expect(builder.GetOutput()).To(BeEquivalentTo(string(tc.expectedOutput)))
}
})
}
}

func TestListLoadBalancerClustersCmd(t *testing.T) {
testLbCluster1 := testLbCluster
testLbCluster2 := testLbCluster

testLbCluster1.ID += "1"
testLbCluster1.Name = "test-lb-cluster-1"

testLbCluster2.ID += "2"
testLbCluster2.Name = "test-lb-cluster-2"

testCases := []struct {
name string
output string
args []string
expectedOutput []byte
expectError bool
configureMock func(*mocks.MockCollection[serverscom.LoadBalancerCluster])
}{
{
name: "list all LB Clusters",
output: "json",
args: []string{"-A"},
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_all.json")),
configureMock: func(mock *mocks.MockCollection[serverscom.LoadBalancerCluster]) {
mock.EXPECT().
Collect(gomock.Any()).
Return([]serverscom.LoadBalancerCluster{
testLbCluster1,
testLbCluster2,
}, nil)
},
},
{
name: "list LB Clusters",
output: "json",
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list.json")),
configureMock: func(mock *mocks.MockCollection[serverscom.LoadBalancerCluster]) {
mock.EXPECT().
List(gomock.Any()).
Return([]serverscom.LoadBalancerCluster{
testLbCluster1,
}, nil)
},
},
{
name: "list LB Clusters with template",
args: []string{"--template", "{{range .}}Name: {{.Name}}\n{{end}}"},
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_template.txt")),
configureMock: func(mock *mocks.MockCollection[serverscom.LoadBalancerCluster]) {
mock.EXPECT().
List(gomock.Any()).
Return([]serverscom.LoadBalancerCluster{
testLbCluster1,
testLbCluster2,
}, nil)
},
},
{
name: "list LB Clusters with pageView",
args: []string{"--page-view"},
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_pageview.txt")),
configureMock: func(mock *mocks.MockCollection[serverscom.LoadBalancerCluster]) {
mock.EXPECT().
List(gomock.Any()).
Return([]serverscom.LoadBalancerCluster{
testLbCluster1,
testLbCluster2,
}, nil)
},
},
{
name: "list LB Clusters with error",
expectError: true,
configureMock: func(mock *mocks.MockCollection[serverscom.LoadBalancerCluster]) {
mock.EXPECT().
List(gomock.Any()).
Return(nil, errors.New("some error"))
},
},
}

mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

lbClustersServiceHandler := mocks.NewMockLoadBalancerClustersService(mockCtrl)
collectionHandler := mocks.NewMockCollection[serverscom.LoadBalancerCluster](mockCtrl)

lbClustersServiceHandler.EXPECT().
Collection().
Return(collectionHandler).
AnyTimes()

collectionHandler.EXPECT().
SetParam(gomock.Any(), gomock.Any()).
Return(collectionHandler).
AnyTimes()

scClient := serverscom.NewClientWithEndpoint("", "")
scClient.LoadBalancerClusters = lbClustersServiceHandler

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
g := NewWithT(t)

if tc.configureMock != nil {
tc.configureMock(collectionHandler)
}

testCmdContext := testutils.NewTestCmdContext(scClient)
lbClusterCmd := NewCmd(testCmdContext)

args := []string{"lb-clusters", "list"}
if len(tc.args) > 0 {
args = append(args, tc.args...)
}
if tc.output != "" {
args = append(args, "--output", tc.output)
}

builder := testutils.NewTestCommandBuilder().
WithCommand(lbClusterCmd).
WithArgs(args)

cmd := builder.Build()

err := cmd.Execute()

if tc.expectError {
g.Expect(err).To(HaveOccurred())
} else {
g.Expect(err).To(BeNil())
g.Expect(builder.GetOutput()).To(BeEquivalentTo(string(tc.expectedOutput)))
}
})
}
}
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/serverscom/srvctl/cmd/entities/invoices"
"github.com/serverscom/srvctl/cmd/entities/k8s"
l2segments "github.com/serverscom/srvctl/cmd/entities/l2_segments"
loadbalancerclusters "github.com/serverscom/srvctl/cmd/entities/load_balancer_clusters"
loadbalancers "github.com/serverscom/srvctl/cmd/entities/load_balancers"
"github.com/serverscom/srvctl/cmd/entities/locations"
networkpools "github.com/serverscom/srvctl/cmd/entities/network-pools"
Expand Down Expand Up @@ -56,6 +57,7 @@ func NewRootCmd(version string) *cobra.Command {
cmd.AddCommand(sshkeys.NewCmd(cmdContext))
cmd.AddCommand(hosts.NewCmd(cmdContext))
cmd.AddCommand(ssl.NewCmd(cmdContext))
cmd.AddCommand(loadbalancerclusters.NewCmd(cmdContext))
cmd.AddCommand(loadbalancers.NewCmd(cmdContext))
cmd.AddCommand(racks.NewCmd(cmdContext))
cmd.AddCommand(invoices.NewCmd(cmdContext))
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/creack/pty v1.1.24
github.com/jmespath/go-jmespath v0.4.0
github.com/onsi/gomega v1.38.0
github.com/serverscom/serverscom-go-client v1.0.20
github.com/serverscom/serverscom-go-client v1.0.21
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.7
github.com/spf13/viper v1.20.1
Expand Down
Loading
Loading