Skip to content

Commit 7cb54a0

Browse files
authored
Merge pull request #29 from serverscom/implement-lb-clusters-commands
Implement lb clusters commands
2 parents a42baf7 + 5e4fd37 commit 7cb54a0

File tree

16 files changed

+507
-0
lines changed

16 files changed

+507
-0
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ generate: deps
1212
mockgen --destination ./internal/mocks/ssh_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/ssh_keys.go
1313
mockgen --destination ./internal/mocks/ssl_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/ssl_certificates.go
1414
mockgen --destination ./internal/mocks/load_balancers_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/load_balancers.go
15+
mockgen --destination ./internal/mocks/load_balancer_clusters_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/load_balancer_clusters.go
1516
mockgen --destination ./internal/mocks/racks_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/racks.go
1617
mockgen --destination ./internal/mocks/invoices_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/invoices.go
1718
mockgen --destination ./internal/mocks/account_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/accounts.go
@@ -24,6 +25,7 @@ generate: deps
2425
./internal/mocks/hosts_service.go \
2526
./internal/mocks/ssl_service.go \
2627
./internal/mocks/load_balancers_service.go \
28+
./internal/mocks/load_balancer_clusters_service.go \
2729
./internal/mocks/racks_service.go \
2830
./internal/mocks/invoices_service.go \
2931
./internal/mocks/account_service.go \
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package loadbalancerclusters
2+
3+
import (
4+
"github.com/serverscom/srvctl/cmd/base"
5+
"github.com/spf13/cobra"
6+
)
7+
8+
func newGetCmd(cmdContext *base.CmdContext) *cobra.Command {
9+
cmd := &cobra.Command{
10+
Use: "get <id>",
11+
Short: "Get LB Cluster",
12+
Long: "Get LB Cluster by id",
13+
Args: cobra.ExactArgs(1),
14+
RunE: func(cmd *cobra.Command, args []string) error {
15+
manager := cmdContext.GetManager()
16+
17+
ctx, cancel := base.SetupContext(cmd, manager)
18+
defer cancel()
19+
20+
base.SetupProxy(cmd, manager)
21+
22+
scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient()
23+
24+
id := args[0]
25+
lbCluster, err := scClient.LoadBalancerClusters.GetLoadBalancerCluster(ctx, id)
26+
if err != nil {
27+
return err
28+
}
29+
30+
if lbCluster != nil {
31+
formatter := cmdContext.GetOrCreateFormatter(cmd)
32+
return formatter.Format(lbCluster)
33+
}
34+
return nil
35+
},
36+
}
37+
38+
return cmd
39+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package loadbalancerclusters
2+
3+
import (
4+
serverscom "github.com/serverscom/serverscom-go-client/pkg"
5+
"github.com/serverscom/srvctl/cmd/base"
6+
"github.com/spf13/cobra"
7+
)
8+
9+
func newListCmd(cmdContext *base.CmdContext) *cobra.Command {
10+
factory := func(verbose bool, args ...string) serverscom.Collection[serverscom.LoadBalancerCluster] {
11+
scClient := cmdContext.GetClient().SetVerbose(verbose).GetScClient()
12+
return scClient.LoadBalancerClusters.Collection()
13+
}
14+
15+
opts := base.NewListOptions(
16+
&base.BaseListOptions[serverscom.LoadBalancerCluster]{},
17+
&base.SearchPatternOption[serverscom.LoadBalancerCluster]{},
18+
)
19+
20+
return base.NewListCmd("list", "lb-clusters", factory, cmdContext, opts...)
21+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package loadbalancerclusters
2+
3+
import (
4+
"log"
5+
6+
serverscom "github.com/serverscom/serverscom-go-client/pkg"
7+
"github.com/serverscom/srvctl/cmd/base"
8+
"github.com/serverscom/srvctl/internal/output/entities"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
func NewCmd(cmdContext *base.CmdContext) *cobra.Command {
13+
lbClusterEntity, err := entities.Registry.GetEntityFromValue(serverscom.LoadBalancerCluster{})
14+
if err != nil {
15+
log.Fatal(err)
16+
}
17+
entitiesMap := make(map[string]entities.EntityInterface)
18+
entitiesMap["lb-clusters"] = lbClusterEntity
19+
cmd := &cobra.Command{
20+
Use: "lb-clusters",
21+
Short: "Manage LB Clusters",
22+
PersistentPreRunE: base.CombinePreRunE(
23+
base.CheckFormatterFlags(cmdContext, entitiesMap),
24+
base.CheckEmptyContexts(cmdContext),
25+
),
26+
Args: base.NoArgs,
27+
Run: base.UsageRun,
28+
}
29+
30+
cmd.AddCommand(
31+
newListCmd(cmdContext),
32+
newGetCmd(cmdContext),
33+
)
34+
35+
base.AddFormatFlags(cmd)
36+
37+
return cmd
38+
}
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
package loadbalancerclusters
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"path/filepath"
7+
"testing"
8+
"time"
9+
10+
. "github.com/onsi/gomega"
11+
serverscom "github.com/serverscom/serverscom-go-client/pkg"
12+
"github.com/serverscom/srvctl/cmd/testutils"
13+
"github.com/serverscom/srvctl/internal/mocks"
14+
"go.uber.org/mock/gomock"
15+
)
16+
17+
var (
18+
testId = "testId"
19+
fixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "lb-clusters")
20+
fixedTime = time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC)
21+
testLbCluster = serverscom.LoadBalancerCluster{
22+
ID: testId,
23+
Name: "test-lb-cluster",
24+
LocationID: 1,
25+
Status: "active",
26+
Created: fixedTime,
27+
Updated: fixedTime,
28+
}
29+
)
30+
31+
func TestGetLoadBalancerClusterCmd(t *testing.T) {
32+
testCases := []struct {
33+
id string
34+
name string
35+
output string
36+
expectedOutput []byte
37+
expectError bool
38+
}{
39+
{
40+
name: "get LB Cluster in default format",
41+
id: testId,
42+
output: "",
43+
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.txt")),
44+
},
45+
{
46+
name: "get LB Cluster in JSON format",
47+
id: testId,
48+
output: "json",
49+
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.json")),
50+
},
51+
{
52+
name: "get LB Cluster in YAML format",
53+
id: testId,
54+
output: "yaml",
55+
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.yaml")),
56+
},
57+
{
58+
name: "get LB Cluster with error",
59+
id: testId,
60+
expectError: true,
61+
},
62+
}
63+
64+
mockCtrl := gomock.NewController(t)
65+
defer mockCtrl.Finish()
66+
67+
lbClustersServiceHandler := mocks.NewMockLoadBalancerClustersService(mockCtrl)
68+
69+
scClient := serverscom.NewClientWithEndpoint("", "")
70+
scClient.LoadBalancerClusters = lbClustersServiceHandler
71+
72+
for _, tc := range testCases {
73+
t.Run(tc.name, func(t *testing.T) {
74+
g := NewWithT(t)
75+
76+
var err error
77+
if tc.expectError {
78+
err = errors.New("some error")
79+
}
80+
lbClustersServiceHandler.EXPECT().
81+
GetLoadBalancerCluster(gomock.Any(), testId).
82+
Return(&testLbCluster, err)
83+
84+
testCmdContext := testutils.NewTestCmdContext(scClient)
85+
lbClusterCmd := NewCmd(testCmdContext)
86+
87+
args := []string{"lb-clusters", "get", fmt.Sprint(tc.id)}
88+
if tc.output != "" {
89+
args = append(args, "--output", tc.output)
90+
}
91+
92+
builder := testutils.NewTestCommandBuilder().
93+
WithCommand(lbClusterCmd).
94+
WithArgs(args)
95+
96+
cmd := builder.Build()
97+
98+
err = cmd.Execute()
99+
100+
if tc.expectError {
101+
g.Expect(err).To(HaveOccurred())
102+
} else {
103+
g.Expect(err).To(BeNil())
104+
g.Expect(builder.GetOutput()).To(BeEquivalentTo(string(tc.expectedOutput)))
105+
}
106+
})
107+
}
108+
}
109+
110+
func TestListLoadBalancerClustersCmd(t *testing.T) {
111+
testLbCluster1 := testLbCluster
112+
testLbCluster2 := testLbCluster
113+
114+
testLbCluster1.ID += "1"
115+
testLbCluster1.Name = "test-lb-cluster-1"
116+
117+
testLbCluster2.ID += "2"
118+
testLbCluster2.Name = "test-lb-cluster-2"
119+
120+
testCases := []struct {
121+
name string
122+
output string
123+
args []string
124+
expectedOutput []byte
125+
expectError bool
126+
configureMock func(*mocks.MockCollection[serverscom.LoadBalancerCluster])
127+
}{
128+
{
129+
name: "list all LB Clusters",
130+
output: "json",
131+
args: []string{"-A"},
132+
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_all.json")),
133+
configureMock: func(mock *mocks.MockCollection[serverscom.LoadBalancerCluster]) {
134+
mock.EXPECT().
135+
Collect(gomock.Any()).
136+
Return([]serverscom.LoadBalancerCluster{
137+
testLbCluster1,
138+
testLbCluster2,
139+
}, nil)
140+
},
141+
},
142+
{
143+
name: "list LB Clusters",
144+
output: "json",
145+
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list.json")),
146+
configureMock: func(mock *mocks.MockCollection[serverscom.LoadBalancerCluster]) {
147+
mock.EXPECT().
148+
List(gomock.Any()).
149+
Return([]serverscom.LoadBalancerCluster{
150+
testLbCluster1,
151+
}, nil)
152+
},
153+
},
154+
{
155+
name: "list LB Clusters with template",
156+
args: []string{"--template", "{{range .}}Name: {{.Name}}\n{{end}}"},
157+
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_template.txt")),
158+
configureMock: func(mock *mocks.MockCollection[serverscom.LoadBalancerCluster]) {
159+
mock.EXPECT().
160+
List(gomock.Any()).
161+
Return([]serverscom.LoadBalancerCluster{
162+
testLbCluster1,
163+
testLbCluster2,
164+
}, nil)
165+
},
166+
},
167+
{
168+
name: "list LB Clusters with pageView",
169+
args: []string{"--page-view"},
170+
expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_pageview.txt")),
171+
configureMock: func(mock *mocks.MockCollection[serverscom.LoadBalancerCluster]) {
172+
mock.EXPECT().
173+
List(gomock.Any()).
174+
Return([]serverscom.LoadBalancerCluster{
175+
testLbCluster1,
176+
testLbCluster2,
177+
}, nil)
178+
},
179+
},
180+
{
181+
name: "list LB Clusters with error",
182+
expectError: true,
183+
configureMock: func(mock *mocks.MockCollection[serverscom.LoadBalancerCluster]) {
184+
mock.EXPECT().
185+
List(gomock.Any()).
186+
Return(nil, errors.New("some error"))
187+
},
188+
},
189+
}
190+
191+
mockCtrl := gomock.NewController(t)
192+
defer mockCtrl.Finish()
193+
194+
lbClustersServiceHandler := mocks.NewMockLoadBalancerClustersService(mockCtrl)
195+
collectionHandler := mocks.NewMockCollection[serverscom.LoadBalancerCluster](mockCtrl)
196+
197+
lbClustersServiceHandler.EXPECT().
198+
Collection().
199+
Return(collectionHandler).
200+
AnyTimes()
201+
202+
collectionHandler.EXPECT().
203+
SetParam(gomock.Any(), gomock.Any()).
204+
Return(collectionHandler).
205+
AnyTimes()
206+
207+
scClient := serverscom.NewClientWithEndpoint("", "")
208+
scClient.LoadBalancerClusters = lbClustersServiceHandler
209+
210+
for _, tc := range testCases {
211+
t.Run(tc.name, func(t *testing.T) {
212+
g := NewWithT(t)
213+
214+
if tc.configureMock != nil {
215+
tc.configureMock(collectionHandler)
216+
}
217+
218+
testCmdContext := testutils.NewTestCmdContext(scClient)
219+
lbClusterCmd := NewCmd(testCmdContext)
220+
221+
args := []string{"lb-clusters", "list"}
222+
if len(tc.args) > 0 {
223+
args = append(args, tc.args...)
224+
}
225+
if tc.output != "" {
226+
args = append(args, "--output", tc.output)
227+
}
228+
229+
builder := testutils.NewTestCommandBuilder().
230+
WithCommand(lbClusterCmd).
231+
WithArgs(args)
232+
233+
cmd := builder.Build()
234+
235+
err := cmd.Execute()
236+
237+
if tc.expectError {
238+
g.Expect(err).To(HaveOccurred())
239+
} else {
240+
g.Expect(err).To(BeNil())
241+
g.Expect(builder.GetOutput()).To(BeEquivalentTo(string(tc.expectedOutput)))
242+
}
243+
})
244+
}
245+
}

cmd/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/serverscom/srvctl/cmd/entities/invoices"
1111
"github.com/serverscom/srvctl/cmd/entities/k8s"
1212
l2segments "github.com/serverscom/srvctl/cmd/entities/l2_segments"
13+
loadbalancerclusters "github.com/serverscom/srvctl/cmd/entities/load_balancer_clusters"
1314
loadbalancers "github.com/serverscom/srvctl/cmd/entities/load_balancers"
1415
"github.com/serverscom/srvctl/cmd/entities/locations"
1516
networkpools "github.com/serverscom/srvctl/cmd/entities/network-pools"
@@ -56,6 +57,7 @@ func NewRootCmd(version string) *cobra.Command {
5657
cmd.AddCommand(sshkeys.NewCmd(cmdContext))
5758
cmd.AddCommand(hosts.NewCmd(cmdContext))
5859
cmd.AddCommand(ssl.NewCmd(cmdContext))
60+
cmd.AddCommand(loadbalancerclusters.NewCmd(cmdContext))
5961
cmd.AddCommand(loadbalancers.NewCmd(cmdContext))
6062
cmd.AddCommand(racks.NewCmd(cmdContext))
6163
cmd.AddCommand(invoices.NewCmd(cmdContext))

0 commit comments

Comments
 (0)