From 0f6ad7e6c2071389f00c43952d7248b286e6268e Mon Sep 17 00:00:00 2001 From: Oleg Isakov Date: Fri, 24 Jul 2026 14:19:35 +0300 Subject: [PATCH] reorganize hosts to use separate commands for ebm,kbm,sbm --- cmd/entities/hosts/ebm.go | 43 + cmd/entities/hosts/ebm_test.go | 2213 +++++++++++ cmd/entities/hosts/features_test.go | 295 -- cmd/entities/hosts/hosts.go | 99 +- cmd/entities/hosts/hosts_test.go | 3328 +---------------- cmd/entities/hosts/kbm.go | 26 + cmd/entities/hosts/kbm_test.go | 816 ++++ cmd/entities/hosts/oob_test.go | 100 - cmd/entities/hosts/ptr_test.go | 539 --- cmd/entities/hosts/sbm.go | 35 + cmd/entities/hosts/sbm_test.go | 1335 +++++++ cmd/entities/hosts/services_test.go | 152 - cmd/root.go | 3 + docs/index.md | 46 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 docs/srvctl-ebm-add-network/examples.md | 5 + .../description.md | 0 docs/srvctl-ebm-add-ptr/examples.md | 5 + .../description.md | 0 .../examples.md | 6 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 10 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 .../examples.md | 2 +- .../description.md | 0 docs/srvctl-ebm-schedule-release/examples.md | 5 + .../description.md | 0 docs/srvctl-ebm-update/examples.md | 5 + .../description.md | 0 .../examples.md | 2 +- docs/srvctl-hosts-ebm-add-network/examples.md | 5 - docs/srvctl-hosts-ebm-add-ptr/examples.md | 5 - .../examples.md | 5 - docs/srvctl-hosts-ebm-update/examples.md | 5 - docs/srvctl-hosts/description.md | 2 +- 65 files changed, 4573 insertions(+), 4549 deletions(-) create mode 100644 cmd/entities/hosts/ebm.go create mode 100644 cmd/entities/hosts/ebm_test.go delete mode 100644 cmd/entities/hosts/features_test.go create mode 100644 cmd/entities/hosts/kbm.go create mode 100644 cmd/entities/hosts/kbm_test.go delete mode 100644 cmd/entities/hosts/oob_test.go delete mode 100644 cmd/entities/hosts/ptr_test.go create mode 100644 cmd/entities/hosts/sbm.go create mode 100644 cmd/entities/hosts/sbm_test.go delete mode 100644 cmd/entities/hosts/services_test.go rename docs/{srvctl-hosts-ebm-abort-release => srvctl-ebm-abort-release}/description.md (100%) rename docs/{srvctl-hosts-ebm-abort-release => srvctl-ebm-abort-release}/examples.md (68%) rename docs/{srvctl-hosts-ebm-add-network => srvctl-ebm-add-network}/description.md (100%) create mode 100644 docs/srvctl-ebm-add-network/examples.md rename docs/{srvctl-hosts-ebm-add-ptr => srvctl-ebm-add-ptr}/description.md (100%) create mode 100644 docs/srvctl-ebm-add-ptr/examples.md rename docs/{srvctl-hosts-ebm-add => srvctl-ebm-add}/description.md (100%) rename docs/{srvctl-hosts-ebm-add => srvctl-ebm-add}/examples.md (96%) rename docs/{srvctl-hosts-ebm-delete-network => srvctl-ebm-delete-network}/description.md (100%) rename docs/{srvctl-hosts-ebm-delete-network => srvctl-ebm-delete-network}/examples.md (50%) rename docs/{srvctl-hosts-ebm-delete-ptr => srvctl-ebm-delete-ptr}/description.md (100%) rename docs/{srvctl-hosts-ebm-delete-ptr => srvctl-ebm-delete-ptr}/examples.md (54%) rename docs/{srvctl-hosts-ebm-feature-set => srvctl-ebm-feature-set}/description.md (100%) rename docs/{srvctl-hosts-ebm-feature-set => srvctl-ebm-feature-set}/examples.md (64%) rename docs/{srvctl-hosts-ebm-get-network => srvctl-ebm-get-network}/description.md (100%) rename docs/{srvctl-hosts-ebm-get-network => srvctl-ebm-get-network}/examples.md (54%) rename docs/{srvctl-hosts-ebm-get-oob-credentials => srvctl-ebm-get-oob-credentials}/description.md (100%) rename docs/{srvctl-hosts-ebm-get-oob-credentials => srvctl-ebm-get-oob-credentials}/examples.md (52%) rename docs/{srvctl-hosts-ebm-get => srvctl-ebm-get}/description.md (100%) rename docs/{srvctl-hosts-ebm-get => srvctl-ebm-get}/examples.md (71%) rename docs/{srvctl-hosts-ebm-list-connections => srvctl-ebm-list-connections}/description.md (100%) rename docs/{srvctl-hosts-ebm-list-connections => srvctl-ebm-list-connections}/examples.md (64%) rename docs/{srvctl-hosts-ebm-list-drive-slots => srvctl-ebm-list-drive-slots}/description.md (100%) rename docs/{srvctl-hosts-ebm-list-drive-slots => srvctl-ebm-list-drive-slots}/examples.md (64%) rename docs/{srvctl-hosts-ebm-list-features => srvctl-ebm-list-features}/description.md (100%) rename docs/{srvctl-hosts-ebm-list-features => srvctl-ebm-list-features}/examples.md (64%) rename docs/{srvctl-hosts-ebm-list-networks => srvctl-ebm-list-networks}/description.md (100%) rename docs/{srvctl-hosts-ebm-list-networks => srvctl-ebm-list-networks}/examples.md (64%) rename docs/{srvctl-hosts-ebm-list-power-feeds => srvctl-ebm-list-power-feeds}/description.md (100%) rename docs/{srvctl-hosts-ebm-list-power-feeds => srvctl-ebm-list-power-feeds}/examples.md (64%) rename docs/{srvctl-hosts-ebm-list-ptr => srvctl-ebm-list-ptr}/description.md (100%) rename docs/{srvctl-hosts-ebm-list-ptr => srvctl-ebm-list-ptr}/examples.md (68%) rename docs/{srvctl-hosts-ebm-list-services => srvctl-ebm-list-services}/description.md (100%) rename docs/{srvctl-hosts-ebm-list-services => srvctl-ebm-list-services}/examples.md (64%) rename docs/{srvctl-hosts-ebm-ls => srvctl-ebm-ls}/description.md (100%) rename docs/{srvctl-hosts-ebm-ls => srvctl-ebm-ls}/examples.md (72%) rename docs/{srvctl-hosts-ebm-power => srvctl-ebm-power}/description.md (100%) rename docs/{srvctl-hosts-ebm-power => srvctl-ebm-power}/examples.md (59%) rename docs/{srvctl-hosts-ebm-reinstall => srvctl-ebm-reinstall}/description.md (100%) rename docs/{srvctl-hosts-ebm-reinstall => srvctl-ebm-reinstall}/examples.md (94%) rename docs/{srvctl-hosts-ebm-schedule-release => srvctl-ebm-schedule-release}/description.md (100%) create mode 100644 docs/srvctl-ebm-schedule-release/examples.md rename docs/{srvctl-hosts-ebm-update => srvctl-ebm-update}/description.md (100%) create mode 100644 docs/srvctl-ebm-update/examples.md rename docs/{srvctl-hosts-ebm => srvctl-ebm}/description.md (100%) rename docs/{srvctl-hosts-ebm => srvctl-ebm}/examples.md (73%) delete mode 100644 docs/srvctl-hosts-ebm-add-network/examples.md delete mode 100644 docs/srvctl-hosts-ebm-add-ptr/examples.md delete mode 100644 docs/srvctl-hosts-ebm-schedule-release/examples.md delete mode 100644 docs/srvctl-hosts-ebm-update/examples.md diff --git a/cmd/entities/hosts/ebm.go b/cmd/entities/hosts/ebm.go new file mode 100644 index 0000000..99aeadf --- /dev/null +++ b/cmd/entities/hosts/ebm.go @@ -0,0 +1,43 @@ +package hosts + +import ( + "github.com/serverscom/srvctl/cmd/base" + "github.com/spf13/cobra" +) + +// NewEBMCmd builds the top-level "ebm" command. +func NewEBMCmd(cmdContext *base.CmdContext) *cobra.Command { + return newHostTypeCmd(cmdContext, HostTypeCmd{ + use: "ebm", + shortDesc: "Manage enterprise bare metal servers", + entityName: "Enterprise Bare Metal", + typeFlag: "dedicated_server", + managers: HostManagers{ + getMgr: &EBMGetMgr{}, + powerMgr: &EBMPowerMgr{}, + reinstallMgr: &EBMReinstallMgr{}, + }, + extraCmds: []func(*base.CmdContext) *cobra.Command{ + newAddEBMCmd, + newUpdateEBMCmd, + newListEBMDriveSlotsCmd, + newListEBMConnectionsCmd, + newListEBMPTRCmd, + newCreateEBMPTRCmd, + newDeleteEBMPTRCmd, + newEBMAbortReleaseCmd, + newEBMScheduleReleaseCmd, + newListEBMNetworksCmd, + newGetEBMNetworkCmd, + newAddEBMNetworkCmd, + newDeleteEBMNetworkCmd, + newActivateEBMIPv6NetworkCmd, + newGetEBMNetworkUsageCmd, + newListEBMCmd, + newListEBMServicesCmd, + newListEBMFeaturesCmd, + newEBMFeatureSetCmd, + newGetEBMOOBCredsCmd, + }, + }) +} diff --git a/cmd/entities/hosts/ebm_test.go b/cmd/entities/hosts/ebm_test.go new file mode 100644 index 0000000..1f0022b --- /dev/null +++ b/cmd/entities/hosts/ebm_test.go @@ -0,0 +1,2213 @@ +package hosts + +import ( + "errors" + "path/filepath" + "testing" + + . "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 ( + testDS = serverscom.DedicatedServer{ + ID: testId, + RackID: testId, + Type: "dedicated_server", + Title: "example.aa", + Status: "active", + LocationCode: testLocationCode, + PublicIPv4Address: &testPublicIP, + ConfigurationDetails: testConfigDetails, + Created: fixedTime, + Updated: fixedTime, + } + + servicesFixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "hosts", "services") + testDSService = serverscom.DedicatedServerService{ + ID: testId, + Name: "Test service", + Type: "server_base", + Currency: "USD", + StartedAt: fixedTime, + FinishedAt: fixedTime, + Total: 100.0, + UsageQuantity: 2.0, + Tax: 10.0, + Subtotal: 100.0, + DiscountRate: 5.0, + DateFrom: "2025-11-01", + DateTo: "2025-11-30", + } + + oobFixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "hosts", "oob") + testOobCreds = serverscom.DedicatedServerOOBCredentials{ + Login: "test", + Secret: "secret", + } + + featuresFixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "hosts", "features") + testFeatureResult = serverscom.DedicatedServerFeature{ + Name: "disaggregated_public_ports", + Status: "activation", + } + testPrivateIpxeBootResult = serverscom.DedicatedServerFeature{ + Name: "private_ipxe_boot", + Status: "activation", + } + testHostRescueModeResult = serverscom.DedicatedServerFeature{ + Name: "host_rescue_mode", + Status: "activation", + } +) + +func TestAddEBMCmd(t *testing.T) { + expectedInput := serverscom.DedicatedServerCreateInput{ + ServerModelID: 1234, + LocationID: 5678, + RAMSize: 16, + UplinkModels: serverscom.DedicatedServerUplinkModelsInput{ + Public: &serverscom.DedicatedServerPublicUplinkInput{ + ID: 4321, + BandwidthModelID: 8765, + }, + Private: serverscom.DedicatedServerPrivateUplinkInput{ + ID: 7890, + }, + }, + Drives: serverscom.DedicatedServerDrivesInput{ + Slots: []serverscom.DedicatedServerSlotInput{ + { + Position: 1, + DriveModelID: new(int64(3456)), + }, + { + Position: 2, + DriveModelID: new(int64(3456)), + }, + }, + Layout: []serverscom.DedicatedServerLayoutInput{ + { + SlotPositions: []int{1, 2}, + Raid: new(1), + Partitions: []serverscom.DedicatedServerLayoutPartitionInput{ + { + Target: "/boot", + Size: 500, + Fill: false, + Fs: new("ext4"), + }, + }, + }, + }, + }, + Hosts: []serverscom.DedicatedServerHostInput{ + { + Hostname: "example.aa", + PublicIPv4NetworkID: new("PublicNet123"), + PrivateIPv4NetworkID: new("PrivateNet456"), + Labels: map[string]string{ + "environment": "testing", + }, + }, + }, + } + + testCases := []struct { + name string + output string + args []string + configureMock func(*mocks.MockHostsService) + expectedOutput []byte + expectError bool + }{ + { + name: "create ebm server", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_ebm_resp.json")), + args: []string{"--input", filepath.Join(fixtureBasePath, "create_ebm_input.json")}, + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + CreateDedicatedServers(gomock.Any(), expectedInput). + Return([]serverscom.DedicatedServer{testDS}, nil) + }, + }, + { + name: "create ebm server with merge input with flags", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_ebm_resp.json")), + args: []string{ + "--input", filepath.Join(fixtureBasePath, "create_ebm_input.json"), + "--layout", "slot=3,slot=4,raid=0", + "--partition", "slot=3,slot=4,target=/boot,fs=ext4,size=500", + }, + configureMock: func(mock *mocks.MockHostsService) { + input := expectedInput + input.Drives.Layout = append(input.Drives.Layout, serverscom.DedicatedServerLayoutInput{ + SlotPositions: []int{3, 4}, + Raid: new(0), + Partitions: []serverscom.DedicatedServerLayoutPartitionInput{ + { + Target: "/boot", + Size: 500, + Fill: false, + Fs: new("ext4"), + }, + }, + }) + + mock.EXPECT(). + CreateDedicatedServers(gomock.Any(), input). + Return([]serverscom.DedicatedServer{testDS}, nil) + }, + }, + { + name: "skeleton for ebm server input", + output: "json", + args: []string{"--skeleton"}, + expectedOutput: testutils.ReadFixture(filepath.Join(skeletonTemplatePath, "add_ebm.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + CreateDedicatedServers(gomock.Any(), gomock.Any()). + Times(0) + }, + }, + { + name: "create ebm server with public_ipxe_boot feature and ipxe-config", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_ebm_resp.json")), + args: []string{ + "--input", filepath.Join(fixtureBasePath, "create_ebm_input.json"), + "--feature", "public_ipxe_boot", + "--ipxe-config", "#!ipxe\nboot", + }, + configureMock: func(mock *mocks.MockHostsService) { + input := expectedInput + input.Features = []string{"public_ipxe_boot"} + input.IPXEConfig = new("#!ipxe\nboot") + mock.EXPECT(). + CreateDedicatedServers(gomock.Any(), input). + Return([]serverscom.DedicatedServer{testDS}, nil) + }, + }, + { + name: "create ebm server with ipxe-config flag", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_ebm_resp.json")), + args: []string{ + "--input", filepath.Join(fixtureBasePath, "create_ebm_input.json"), + "--ipxe-config", "#!ipxe\nboot", + }, + configureMock: func(mock *mocks.MockHostsService) { + input := expectedInput + input.IPXEConfig = new("#!ipxe\nboot") + mock.EXPECT(). + CreateDedicatedServers(gomock.Any(), input). + Return([]serverscom.DedicatedServer{testDS}, nil) + }, + }, + { + name: "create ebm server with ipxe-config in input file", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_ebm_resp.json")), + args: []string{ + "--input", filepath.Join(fixtureBasePath, "create_ebm_ipxe_input.json"), + }, + configureMock: func(mock *mocks.MockHostsService) { + input := expectedInput + input.IPXEConfig = new("#!ipxe\nboot") + mock.EXPECT(). + CreateDedicatedServers(gomock.Any(), input). + Return([]serverscom.DedicatedServer{testDS}, nil) + }, + }, + { + name: "create ebm server with error", + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + + if tc.configureMock != nil { + tc.configureMock(hostsServiceHandler) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "add"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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(MatchJSON(tc.expectedOutput)) + } + }) + } +} + +func TestGetEBMCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "get ebm server in default format", + id: testId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm.txt")), + }, + { + name: "get ebm server in JSON format", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm.json")), + }, + { + name: "get ebm server in YAML format", + id: testId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm.yaml")), + }, + { + name: "get ebm server with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + GetDedicatedServer(gomock.Any(), testId). + Return(&testDS, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "get", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestListEBMCmd(t *testing.T) { + testServer1 := testDS + testServer1.Type = "dedicated_server" + testServer2 := testServer1 + testServer2.ID = "testId2" + testServer2.Title = "example.bb" + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.DedicatedServer]) + }{ + { + name: "list all ebm servers", + output: "json", + args: []string{"-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServer]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.DedicatedServer{ + testServer1, + testServer2, + }, nil) + }, + }, + { + name: "list ebm servers", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServer]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.DedicatedServer{ + testServer1, + }, nil) + }, + }, + { + name: "list ebm servers with template", + args: []string{"--template", "{{range .}}Title: {{.Title}} Type: {{.Type}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServer]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.DedicatedServer{ + testServer1, + testServer2, + }, nil) + }, + }, + { + name: "list ebm servers with pageView", + args: []string{"--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServer]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.DedicatedServer{ + testServer1, + testServer2, + }, nil) + }, + }, + { + name: "list ebm servers with error", + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServer]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + collectionHandler := mocks.NewMockCollection[serverscom.DedicatedServer](mockCtrl) + + hostsServiceHandler.EXPECT(). + ListDedicatedServers(). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "list"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestUpdateEBMCmd(t *testing.T) { + newServer := testDS + newServer.Labels = map[string]string{"new": "label"} + + testCases := []struct { + name string + id string + output string + args []string + configureMock func(*mocks.MockHostsService) + expectedOutput []byte + expectError bool + }{ + { + name: "update ebm server", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "update_ebm_resp.json")), + args: []string{"--label", "new=label"}, + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + UpdateDedicatedServer(gomock.Any(), testId, serverscom.DedicatedServerUpdateInput{ + Labels: map[string]string{"new": "label"}, + }). + Return(&newServer, nil) + }, + }, + { + name: "update ebm server with error", + id: testId, + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + UpdateDedicatedServer(gomock.Any(), testId, serverscom.DedicatedServerUpdateInput{ + Labels: make(map[string]string), + }). + Return(nil, errors.New("some error")) + }, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + + if tc.configureMock != nil { + tc.configureMock(hostsServiceHandler) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + sshCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "update", tc.id} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sshCmd). + 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 TestScheduleReleaseEBMCmd(t *testing.T) { + releasedServer := testDS + testCases := []struct { + name string + id string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockHostsService) + }{ + { + name: "release ebm server", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "release_ebm_resp.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + ScheduleReleaseForDedicatedServer(gomock.Any(), testId, serverscom.ScheduleReleaseInput{}). + Return(&releasedServer, nil) + }, + }, + { + name: "release ebm server with --release-after", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "release_ebm_scheduled_resp.json")), + args: []string{"--release-after", "2025-01-01T12:34:56+03:00"}, + configureMock: func(mock *mocks.MockHostsService) { + releasedServer.ScheduledRelease = &fixedTime + mock.EXPECT(). + ScheduleReleaseForDedicatedServer(gomock.Any(), testId, serverscom.ScheduleReleaseInput{ReleaseAfter: "2025-01-01T12:34:56+03:00"}). + Return(&releasedServer, nil) + }, + }, + { + name: "release ebm server with error", + id: testId, + expectError: true, + configureMock: func(mock *mocks.MockHostsService) { + releasedServer.ScheduledRelease = &fixedTime + mock.EXPECT(). + ScheduleReleaseForDedicatedServer(gomock.Any(), testId, serverscom.ScheduleReleaseInput{}). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + + if tc.configureMock != nil { + tc.configureMock(hostsServiceHandler) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "schedule-release", tc.id} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestAbortReleaseEBMCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "abort release ebm server", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm.json")), + }, + { + name: "abort release ebm server with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + AbortReleaseForDedicatedServer(gomock.Any(), testId). + Return(&testDS, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "abort-release", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestGetEBMNetworkCmd(t *testing.T) { + testCases := []struct { + name string + id string + networkID string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "get DS network in default format", + id: testId, + networkID: testNetworkId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.txt")), + }, + { + name: "get DS network in JSON format", + id: testId, + networkID: testNetworkId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.json")), + }, + { + name: "get DS network in YAML format", + id: testId, + networkID: testNetworkId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.yaml")), + }, + { + name: "get DS network with error", + id: testId, + networkID: testNetworkId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + GetDedicatedServerNetwork(gomock.Any(), tc.id, tc.networkID). + Return(&testNetwork, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{ + "ebm", "get-network", tc.id, + "--network-id", tc.networkID, + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestListEBMNetworksCmd(t *testing.T) { + testNetwork1 := testNetwork + testNetwork1.ID = testNetworkId + testNetwork2 := testNetwork1 + testNetwork2.ID = "testNetId2" + netTitle2 := "Another Net" + testNetwork2.Title = &netTitle2 + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.Network]) + }{ + { + name: "list all DS networks", + output: "json", + args: []string{"testServerId", "-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_networks_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + testNetwork2, + }, nil) + }, + }, + { + name: "list DS networks", + output: "json", + args: []string{"testServerId"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_networks.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + }, nil) + }, + }, + { + name: "list DS networks with template", + args: []string{"testServerId", "--template", "{{range .}}Network: {{.ID}} Title: {{.Title}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_networks_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + testNetwork2, + }, nil) + }, + }, + { + name: "list DS networks with pageView", + args: []string{"testServerId", "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_networks_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + testNetwork2, + }, nil) + }, + }, + { + name: "list DS networks with error", + args: []string{"testServerId"}, + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + collectionHandler := mocks.NewMockCollection[serverscom.Network](mockCtrl) + + hostsServiceHandler.EXPECT(). + DedicatedServerNetworks(gomock.Any()). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "list-networks"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestAddEBMNetworkCmd(t *testing.T) { + expectedInputPublic := serverscom.NetworkInput{ + DistributionMethod: "route", + Mask: 32, + } + expectedInputPrivate := serverscom.NetworkInput{ + DistributionMethod: "gateway", + Mask: 29, + } + + testCases := []struct { + name string + output string + args []string + configureMock func(*mocks.MockHostsService) + expectedOutput []byte + expectError bool + }{ + { + name: "add public DS network", + output: "json", + args: []string{ + testId, + "--type", "public", + "--mask", "32", + "--distribution-method", "route", + }, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + AddDedicatedServerPublicIPv4Network(gomock.Any(), testId, expectedInputPublic). + Return(&testNetwork, nil) + }, + }, + { + name: "add private DS network", + output: "json", + args: []string{ + testId, + "--type", "private", + "--mask", "29", + "--distribution-method", "gateway", + }, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + AddDedicatedServerPrivateIPv4Network(gomock.Any(), testId, expectedInputPrivate). + Return(&testNetwork, nil) + }, + }, + { + name: "add DS network with unsupported mask", + args: []string{ + testId, + "--type", "public", + "--mask", "24", + "--distribution-method", "gateway", + }, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + + if tc.configureMock != nil { + tc.configureMock(hostsServiceHandler) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := append([]string{"ebm", "add-network"}, tc.args...) + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestDeleteEBMNetworkCmd(t *testing.T) { + testCases := []struct { + name string + id string + networkID string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "delete DS network", + id: testId, + networkID: testNetworkId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.json")), + }, + { + name: "delete DS network with error", + id: testId, + networkID: testNetworkId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + DeleteDedicatedServerNetwork(gomock.Any(), tc.id, tc.networkID). + Return(&testNetwork, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "delete-network", tc.id, "--network-id", tc.networkID} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestListEBMPowerFeedsCmd(t *testing.T) { + testPowerFeed1 := testPowerFeed + testPowerFeed2 := testPowerFeed1 + + testPowerFeed2.Name = "testPowerFeed2" + testPowerFeed2.Status = "off" + + testCases := []struct { + name string + id string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.HostPowerFeed]) + }{ + { + name: "get ds power_feeds in default format", + id: testId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.txt")), + }, + { + name: "get ds power_feeds", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.json")), + }, + { + name: "get ds power_feeds in YAML format", + id: testId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.yaml")), + }, + { + name: "get ds power_feeds with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + DedicatedServerPowerFeeds(gomock.Any(), testId). + Return([]serverscom.HostPowerFeed{testPowerFeed1, testPowerFeed2}, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "list-power-feeds", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestActivateEBMIPv6NetworkCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "activate DS IPv6 network", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.json")), + }, + { + name: "activate DS IPv6 network with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + ActivateDedicatedServerPubliIPv6Network(gomock.Any(), tc.id). + Return(&testNetwork, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "activate-ipv6-network", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestGetEBMNetworkUsageCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "get DS network usage in default format", + id: testId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network_usage.txt")), + }, + { + name: "get DS network usage in JSON format", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network_usage.json")), + }, + { + name: "get DS network usage in YAML format", + id: testId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network_usage.yaml")), + }, + { + name: "get DS network usage with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + GetDedicatedServerNetworkUsage(gomock.Any(), tc.id). + Return(&testNetworkUsage, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "network-usage", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestListEBMDriveSlotsCmd(t *testing.T) { + testDriveSlot1 := testDriveSlot + testDriveSlot2 := testDriveSlot1 + testDriveSlot2.Position = 2 + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.HostDriveSlot]) + }{ + { + name: "list ds all drive slots", + output: "json", + args: []string{"testServerId", "-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.HostDriveSlot{ + testDriveSlot1, + testDriveSlot2, + }, nil) + }, + }, + { + name: "list ds drive slots", + output: "json", + args: []string{"testServerId"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.HostDriveSlot{ + testDriveSlot1, + }, nil) + }, + }, + { + name: "list ds drive slots with template", + args: []string{"testServerId", "--template", "{{range .}}Position: {{.Position}} Interface: {{.Interface}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.HostDriveSlot{ + testDriveSlot1, + testDriveSlot2, + }, nil) + }, + }, + { + name: "list ds drive slots with pageView", + args: []string{"testServerId", "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.HostDriveSlot{ + testDriveSlot1, + testDriveSlot2, + }, nil) + }, + }, + { + name: "list ds drive slots with error", + args: []string{"testServerId"}, + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + collectionHandler := mocks.NewMockCollection[serverscom.HostDriveSlot](mockCtrl) + + hostsServiceHandler.EXPECT(). + DedicatedServerDriveSlots(gomock.Any()). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "list-drive-slots"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestListEBMServicesCmd(t *testing.T) { + testService1 := testDSService + testService2 := testDSService + testService2.ID += "2" + testService2.Name = "Test service 2" + testService2.Type = "uplink" + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.DedicatedServerService]) + }{ + { + name: "list all ds services", + output: "json", + args: []string{"-A", testServerID}, + expectedOutput: testutils.ReadFixture(filepath.Join(servicesFixtureBasePath, "list_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerService]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.DedicatedServerService{ + testService1, + testService2, + }, nil) + }, + }, + { + name: "list ds services", + output: "json", + args: []string{testServerID}, + expectedOutput: testutils.ReadFixture(filepath.Join(servicesFixtureBasePath, "list.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerService]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.DedicatedServerService{ + testService1, + }, nil) + }, + }, + { + name: "list ds services with template", + args: []string{testServerID, "--template", "{{range .}}ID: {{.ID}} Name: {{.Name}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(servicesFixtureBasePath, "list_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerService]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.DedicatedServerService{ + testService1, + testService2, + }, nil) + }, + }, + { + name: "list ds services with page-view", + args: []string{testServerID, "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(servicesFixtureBasePath, "list_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerService]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.DedicatedServerService{ + testService1, + testService2, + }, nil) + }, + }, + { + name: "list ds services with error", + args: []string{testServerID}, + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerService]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + hostService := mocks.NewMockHostsService(mockCtrl) + collection := mocks.NewMockCollection[serverscom.DedicatedServerService](mockCtrl) + + hostService.EXPECT().DedicatedServerServices(gomock.Any()).Return(collection).AnyTimes() + collection.EXPECT().SetParam(gomock.Any(), gomock.Any()).Return(collection).AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostService + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + if tc.configureMock != nil { + tc.configureMock(collection) + } + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := append([]string{"ebm", "list-services"}, tc.args...) + if tc.output != "" { + args = append(args, "--output", tc.output) + } + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + WithArgs(args) + + c := builder.Build() + err := c.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 TestGetEBMOOBCredsCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "get ebm server oob creds in default format", + id: testId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(oobFixtureBasePath, "get.txt")), + }, + { + name: "get ebm server oob creds in JSON format", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(oobFixtureBasePath, "get.json")), + }, + { + name: "get ebm server oob creds in YAML format", + id: testId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(oobFixtureBasePath, "get.yaml")), + }, + { + name: "get ebm server oob creds with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + GetDedicatedServerOOBCredentials(gomock.Any(), testId, map[string]string{"fingerprint": "test"}). + Return(&testOobCreds, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "get-oob-credentials", tc.id, "--fingerprint", "test"} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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 TestListEBMPTRCmd(t *testing.T) { + testPTR1 := testPTR + testPTR2 := testPTR + testPTR1.ID += "1" + testPTR2.ID += "2" + testPTR2.Domain = "another.example.com" + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.PTRRecord]) + }{ + { + name: "list all ptr records", + output: "json", + args: []string{"-A", testServerID}, + expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.PTRRecord{ + testPTR1, + testPTR2, + }, nil) + }, + }, + { + name: "list ptr records", + output: "json", + args: []string{testServerID}, + expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.PTRRecord{ + testPTR1, + }, nil) + }, + }, + { + name: "list ptr records with template", + args: []string{testServerID, "--template", "{{range .}}ID: {{.ID}} PTR: {{.Domain}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.PTRRecord{ + testPTR1, + testPTR2, + }, nil) + }, + }, + { + name: "list ptr records with page-view", + args: []string{testServerID, "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.PTRRecord{ + testPTR1, + testPTR2, + }, nil) + }, + }, + { + name: "list ptr records with error", + args: []string{testServerID}, + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + hostService := mocks.NewMockHostsService(mockCtrl) + collection := mocks.NewMockCollection[serverscom.PTRRecord](mockCtrl) + + hostService.EXPECT().DedicatedServerPTRRecords(gomock.Any()).Return(collection).AnyTimes() + collection.EXPECT().SetParam(gomock.Any(), gomock.Any()).Return(collection).AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostService + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + if tc.configureMock != nil { + tc.configureMock(collection) + } + testCmdContext := testutils.NewTestCmdContext(scClient) + cmd := NewEBMCmd(testCmdContext) + + args := append([]string{"ebm", "list-ptr"}, tc.args...) + if tc.output != "" { + args = append(args, "--output", tc.output) + } + builder := testutils.NewTestCommandBuilder(). + WithCommand(cmd). + WithArgs(args) + + c := builder.Build() + err := c.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 TestCreateEBMPTRCmd(t *testing.T) { + testCases := []struct { + name string + args []string + output string + expectedOutput []byte + configureMock func(*mocks.MockHostsService) + expectError bool + }{ + { + name: "create ds ptr", + args: []string{testServerID, "--ip", testPTR.IP, "--domain", testPTR.Domain, "--ttl", "300", "--priority", "10"}, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "get.json")), + configureMock: func(mock *mocks.MockHostsService) { + in := serverscom.PTRRecordCreateInput{ + IP: testPTR.IP, + Domain: testPTR.Domain, + TTL: &testPTR.TTL, + Priority: &testPTR.Priority, + } + mock.EXPECT(). + CreatePTRRecordForDedicatedServer(gomock.Any(), testServerID, in). + Return(&testPTR, nil) + }, + }, + { + name: "create ds ptr error", + args: []string{testServerID, "--ip", testPTR.IP, "--domain", testPTR.Domain}, + expectError: true, + configureMock: func(mock *mocks.MockHostsService) { + in := serverscom.PTRRecordCreateInput{ + IP: testPTR.IP, + Domain: testPTR.Domain, + } + mock.EXPECT(). + CreatePTRRecordForDedicatedServer(gomock.Any(), testServerID, in). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + hostService := mocks.NewMockHostsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostService + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + if tc.configureMock != nil { + tc.configureMock(hostService) + } + testCmdContext := testutils.NewTestCmdContext(scClient) + cmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "add-ptr"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + builder := testutils.NewTestCommandBuilder(). + WithCommand(cmd). + WithArgs(args) + + c := builder.Build() + err := c.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 TestDeleteEBMPTRCmd(t *testing.T) { + testCases := []struct { + name string + serverID string + ptrID string + expectError bool + }{ + { + name: "delete ds ptr", + serverID: testServerID, + ptrID: testPTRID, + }, + { + name: "delete ds ptr error", + serverID: testServerID, + ptrID: testPTRID, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + hostService := mocks.NewMockHostsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostService + + 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") + } + hostService.EXPECT(). + DeletePTRRecordForDedicatedServer(gomock.Any(), tc.serverID, tc.ptrID). + Return(err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + cmd := NewEBMCmd(testCmdContext) + + args := []string{"ebm", "delete-ptr", tc.serverID, "--ptr-id", tc.ptrID} + builder := testutils.NewTestCommandBuilder(). + WithCommand(cmd). + WithArgs(args) + + c := builder.Build() + err = c.Execute() + if tc.expectError { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).To(BeNil()) + } + }) + } +} + +func TestListEBMFeaturesCmd(t *testing.T) { + testFeature1 := serverscom.DedicatedServerFeature{ + Name: "disaggregated_public_ports", + Status: "deactivated", + } + testFeature2 := serverscom.DedicatedServerFeature{ + Name: "no_public_network", + Status: "unavailable", + } + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.DedicatedServerFeature]) + }{ + { + name: "list all ds features", + output: "json", + args: []string{"-A", testServerID}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "list_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerFeature]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.DedicatedServerFeature{ + testFeature1, + testFeature2, + }, nil) + }, + }, + { + name: "list ds features", + output: "json", + args: []string{testServerID}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "list.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerFeature]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.DedicatedServerFeature{ + testFeature1, + }, nil) + }, + }, + { + name: "list ds features with template", + args: []string{testServerID, "--template", "{{range .}}Name: {{.Name}} Status: {{.Status}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "list_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerFeature]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.DedicatedServerFeature{ + testFeature1, + testFeature2, + }, nil) + }, + }, + { + name: "list ds features with page-view", + args: []string{testServerID, "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "list_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerFeature]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.DedicatedServerFeature{ + testFeature1, + testFeature2, + }, nil) + }, + }, + { + name: "list ds features with error", + args: []string{testServerID}, + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerFeature]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + hostService := mocks.NewMockHostsService(mockCtrl) + collection := mocks.NewMockCollection[serverscom.DedicatedServerFeature](mockCtrl) + + hostService.EXPECT().DedicatedServerFeatures(gomock.Any()).Return(collection).AnyTimes() + collection.EXPECT().SetParam(gomock.Any(), gomock.Any()).Return(collection).AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostService + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + if tc.configureMock != nil { + tc.configureMock(collection) + } + testCmdContext := testutils.NewTestCmdContext(scClient) + cmd := NewEBMCmd(testCmdContext) + + args := append([]string{"ebm", "list-features"}, tc.args...) + if tc.output != "" { + args = append(args, "--output", tc.output) + } + builder := testutils.NewTestCommandBuilder(). + WithCommand(cmd). + WithArgs(args) + + c := builder.Build() + err := c.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 TestEBMFeatureSetCmd(t *testing.T) { + testCases := []struct { + name string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockHostsService) + }{ + { + name: "activate feature", + args: []string{testServerID, "--feature", "disaggregated_public_ports", "--command", "activate", "--output", "json"}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + ActivateDisaggregatedPublicPortsFeature(gomock.Any(), testServerID). + Return(&testFeatureResult, nil) + }, + }, + { + name: "deactivate feature", + args: []string{testServerID, "--feature", "disaggregated_public_ports", "--command", "deactivate", "--output", "json"}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + DeactivateDisaggregatedPublicPortsFeature(gomock.Any(), testServerID). + Return(&testFeatureResult, nil) + }, + }, + { + name: "activate private_ipxe_boot with ipxe-config", + args: []string{testServerID, "--feature", "private_ipxe_boot", "--command", "activate", "--ipxe-config", "#!ipxe\nchain http://boot.example.com", "--output", "json"}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set_private_ipxe_boot.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + ActivatePrivateIpxeBootFeature(gomock.Any(), testServerID, serverscom.PrivateIpxeBootFeatureInput{ + IPXEConfig: "#!ipxe\nchain http://boot.example.com", + }). + Return(&testPrivateIpxeBootResult, nil) + }, + }, + { + name: "deactivate private_ipxe_boot", + args: []string{testServerID, "--feature", "private_ipxe_boot", "--command", "deactivate", "--output", "json"}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set_private_ipxe_boot.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + DeactivatePrivateIpxeBootFeature(gomock.Any(), testServerID). + Return(&testPrivateIpxeBootResult, nil) + }, + }, + { + name: "activate host_rescue_mode with password auth", + args: []string{testServerID, "--feature", "host_rescue_mode", "--command", "activate", "--auth-method", "password", "--output", "json"}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set_host_rescue_mode.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + ActivateHostRescueModeFeature(gomock.Any(), testServerID, serverscom.HostRescueModeFeatureInput{ + AuthMethods: []string{"password"}, + }). + Return(&testHostRescueModeResult, nil) + }, + }, + { + name: "activate host_rescue_mode with ssh_key auth", + args: []string{testServerID, "--feature", "host_rescue_mode", "--command", "activate", "--auth-method", "ssh_key", "--ssh-key-fingerprint", "aa:bb:cc", "--output", "json"}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set_host_rescue_mode.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + ActivateHostRescueModeFeature(gomock.Any(), testServerID, serverscom.HostRescueModeFeatureInput{ + AuthMethods: []string{"ssh_key"}, + SSHKeyFingerprints: []string{"aa:bb:cc"}, + }). + Return(&testHostRescueModeResult, nil) + }, + }, + { + name: "deactivate host_rescue_mode", + args: []string{testServerID, "--feature", "host_rescue_mode", "--command", "deactivate", "--output", "json"}, + expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set_host_rescue_mode.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + DeactivateHostRescueModeFeature(gomock.Any(), testServerID). + Return(&testHostRescueModeResult, nil) + }, + }, + { + name: "api error", + args: []string{testServerID, "--feature", "disaggregated_public_ports", "--command", "activate"}, + expectError: true, + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + ActivateDisaggregatedPublicPortsFeature(gomock.Any(), testServerID). + Return(nil, errors.New("some error")) + }, + }, + { + name: "invalid command", + args: []string{testServerID, "--feature", "disaggregated_public_ports", "--command", "invalid"}, + expectError: true, + }, + { + name: "unsupported feature", + args: []string{testServerID, "--feature", "unknown_feature", "--command", "activate"}, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + hostService := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostService + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + if tc.configureMock != nil { + tc.configureMock(hostService) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + ebmCmd := NewEBMCmd(testCmdContext) + + args := append([]string{"ebm", "feature-set"}, tc.args...) + builder := testutils.NewTestCommandBuilder(). + WithCommand(ebmCmd). + 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))) + } + }) + } +} diff --git a/cmd/entities/hosts/features_test.go b/cmd/entities/hosts/features_test.go deleted file mode 100644 index 7c2ccd2..0000000 --- a/cmd/entities/hosts/features_test.go +++ /dev/null @@ -1,295 +0,0 @@ -package hosts - -import ( - "errors" - "path/filepath" - "testing" - - . "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 ( - featuresFixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "hosts", "features") - - testFeatureResult = serverscom.DedicatedServerFeature{ - Name: "disaggregated_public_ports", - Status: "activation", - } - testPrivateIpxeBootResult = serverscom.DedicatedServerFeature{ - Name: "private_ipxe_boot", - Status: "activation", - } - testHostRescueModeResult = serverscom.DedicatedServerFeature{ - Name: "host_rescue_mode", - Status: "activation", - } -) - -func TestListEBMFeaturesCmd(t *testing.T) { - testFeature1 := serverscom.DedicatedServerFeature{ - Name: "disaggregated_public_ports", - Status: "deactivated", - } - testFeature2 := serverscom.DedicatedServerFeature{ - Name: "no_public_network", - Status: "unavailable", - } - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.DedicatedServerFeature]) - }{ - { - name: "list all ds features", - output: "json", - args: []string{"-A", testServerID}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "list_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerFeature]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.DedicatedServerFeature{ - testFeature1, - testFeature2, - }, nil) - }, - }, - { - name: "list ds features", - output: "json", - args: []string{testServerID}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "list.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerFeature]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.DedicatedServerFeature{ - testFeature1, - }, nil) - }, - }, - { - name: "list ds features with template", - args: []string{testServerID, "--template", "{{range .}}Name: {{.Name}} Status: {{.Status}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "list_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerFeature]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.DedicatedServerFeature{ - testFeature1, - testFeature2, - }, nil) - }, - }, - { - name: "list ds features with page-view", - args: []string{testServerID, "--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "list_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerFeature]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.DedicatedServerFeature{ - testFeature1, - testFeature2, - }, nil) - }, - }, - { - name: "list ds features with error", - args: []string{testServerID}, - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerFeature]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - hostService := mocks.NewMockHostsService(mockCtrl) - collection := mocks.NewMockCollection[serverscom.DedicatedServerFeature](mockCtrl) - - hostService.EXPECT().DedicatedServerFeatures(gomock.Any()).Return(collection).AnyTimes() - collection.EXPECT().SetParam(gomock.Any(), gomock.Any()).Return(collection).AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostService - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - if tc.configureMock != nil { - tc.configureMock(collection) - } - testCmdContext := testutils.NewTestCmdContext(scClient) - cmd := NewCmd(testCmdContext) - - args := append([]string{"hosts", "ebm", "list-features"}, tc.args...) - if tc.output != "" { - args = append(args, "--output", tc.output) - } - builder := testutils.NewTestCommandBuilder(). - WithCommand(cmd). - WithArgs(args) - - c := builder.Build() - err := c.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 TestEBMFeatureSetCmd(t *testing.T) { - testCases := []struct { - name string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockHostsService) - }{ - { - name: "activate feature", - args: []string{testServerID, "--feature", "disaggregated_public_ports", "--command", "activate", "--output", "json"}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - ActivateDisaggregatedPublicPortsFeature(gomock.Any(), testServerID). - Return(&testFeatureResult, nil) - }, - }, - { - name: "deactivate feature", - args: []string{testServerID, "--feature", "disaggregated_public_ports", "--command", "deactivate", "--output", "json"}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - DeactivateDisaggregatedPublicPortsFeature(gomock.Any(), testServerID). - Return(&testFeatureResult, nil) - }, - }, - { - name: "activate private_ipxe_boot with ipxe-config", - args: []string{testServerID, "--feature", "private_ipxe_boot", "--command", "activate", "--ipxe-config", "#!ipxe\nchain http://boot.example.com", "--output", "json"}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set_private_ipxe_boot.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - ActivatePrivateIpxeBootFeature(gomock.Any(), testServerID, serverscom.PrivateIpxeBootFeatureInput{ - IPXEConfig: "#!ipxe\nchain http://boot.example.com", - }). - Return(&testPrivateIpxeBootResult, nil) - }, - }, - { - name: "deactivate private_ipxe_boot", - args: []string{testServerID, "--feature", "private_ipxe_boot", "--command", "deactivate", "--output", "json"}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set_private_ipxe_boot.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - DeactivatePrivateIpxeBootFeature(gomock.Any(), testServerID). - Return(&testPrivateIpxeBootResult, nil) - }, - }, - { - name: "activate host_rescue_mode with password auth", - args: []string{testServerID, "--feature", "host_rescue_mode", "--command", "activate", "--auth-method", "password", "--output", "json"}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set_host_rescue_mode.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - ActivateHostRescueModeFeature(gomock.Any(), testServerID, serverscom.HostRescueModeFeatureInput{ - AuthMethods: []string{"password"}, - }). - Return(&testHostRescueModeResult, nil) - }, - }, - { - name: "activate host_rescue_mode with ssh_key auth", - args: []string{testServerID, "--feature", "host_rescue_mode", "--command", "activate", "--auth-method", "ssh_key", "--ssh-key-fingerprint", "aa:bb:cc", "--output", "json"}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set_host_rescue_mode.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - ActivateHostRescueModeFeature(gomock.Any(), testServerID, serverscom.HostRescueModeFeatureInput{ - AuthMethods: []string{"ssh_key"}, - SSHKeyFingerprints: []string{"aa:bb:cc"}, - }). - Return(&testHostRescueModeResult, nil) - }, - }, - { - name: "deactivate host_rescue_mode", - args: []string{testServerID, "--feature", "host_rescue_mode", "--command", "deactivate", "--output", "json"}, - expectedOutput: testutils.ReadFixture(filepath.Join(featuresFixtureBasePath, "feature_set_host_rescue_mode.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - DeactivateHostRescueModeFeature(gomock.Any(), testServerID). - Return(&testHostRescueModeResult, nil) - }, - }, - { - name: "api error", - args: []string{testServerID, "--feature", "disaggregated_public_ports", "--command", "activate"}, - expectError: true, - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - ActivateDisaggregatedPublicPortsFeature(gomock.Any(), testServerID). - Return(nil, errors.New("some error")) - }, - }, - { - name: "invalid command", - args: []string{testServerID, "--feature", "disaggregated_public_ports", "--command", "invalid"}, - expectError: true, - }, - { - name: "unsupported feature", - args: []string{testServerID, "--feature", "unknown_feature", "--command", "activate"}, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - hostService := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostService - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - if tc.configureMock != nil { - tc.configureMock(hostService) - } - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := append([]string{"hosts", "ebm", "feature-set"}, tc.args...) - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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))) - } - }) - } -} diff --git a/cmd/entities/hosts/hosts.go b/cmd/entities/hosts/hosts.go index 3c0963a..7dac940 100644 --- a/cmd/entities/hosts/hosts.go +++ b/cmd/entities/hosts/hosts.go @@ -25,89 +25,15 @@ type HostManagers struct { reinstallMgr HostReinstaller } +// NewCmd builds the slim top-level "hosts" command that only exposes the +// cross-type list. The per-type commands (ebm/kbm/sbm) are top-level commands +// of their own, built by NewEBMCmd/NewKBMCmd/NewSBMCmd. func NewCmd(cmdContext *base.CmdContext) *cobra.Command { entitiesMap, err := getHostsEntities() if err != nil { log.Fatal(err) } - hostTypeCmds := []HostTypeCmd{ - { - use: "ebm", - shortDesc: "Manage enterprise bare metal servers", - entityName: "Enterprise Bare Metal", - typeFlag: "dedicated_server", - managers: HostManagers{ - getMgr: &EBMGetMgr{}, - powerMgr: &EBMPowerMgr{}, - reinstallMgr: &EBMReinstallMgr{}, - }, - extraCmds: []func(*base.CmdContext) *cobra.Command{ - newAddEBMCmd, - newUpdateEBMCmd, - newListEBMDriveSlotsCmd, - newListEBMConnectionsCmd, - newListEBMPTRCmd, - newCreateEBMPTRCmd, - newDeleteEBMPTRCmd, - newEBMAbortReleaseCmd, - newEBMScheduleReleaseCmd, - newListEBMNetworksCmd, - newGetEBMNetworkCmd, - newAddEBMNetworkCmd, - newDeleteEBMNetworkCmd, - newActivateEBMIPv6NetworkCmd, - newGetEBMNetworkUsageCmd, - newListEBMCmd, - newListEBMServicesCmd, - newListEBMFeaturesCmd, - newEBMFeatureSetCmd, - newGetEBMOOBCredsCmd, - }, - }, - { - use: "kbm", - shortDesc: "Manage kubernetes baremetal nodes", - entityName: "Kubernetes baremetal nodes", - typeFlag: "kubernetes_baremetal_node", - managers: HostManagers{ - getMgr: &KBMGetMgr{}, - powerMgr: &KBMPowerMgr{}, - }, - extraCmds: []func(*base.CmdContext) *cobra.Command{ - newUpdateKBMCmd, - newListKBMCmd, - newListKBMNetworksCmd, - newListKBMDriveSlotsCmd, - }, - }, - { - use: "sbm", - shortDesc: "Manage scalable baremetal servers", - entityName: "Scalable baremetal servers", - typeFlag: "sbm_server", - managers: HostManagers{ - getMgr: &SBMGetMgr{}, - powerMgr: &SBMPowerMgr{}, - reinstallMgr: &SBMReinstallMgr{}, - }, - extraCmds: []func(*base.CmdContext) *cobra.Command{ - newAddSBMCmd, - newUpdateSBMCmd, - newSBMReleaseCmd, - newListSBMCmd, - newListSBMNetworksCmd, - newGetSBMNetworkCmd, - newAddSBMNetworkCmd, - newDeleteSBMNetworkCmd, - newGetSBMNetworkUsageCmd, - newListSBMPTRCmd, - newCreateSBMPTRCmd, - newDeleteSBMPTRCmd, - }, - }, - } - cmd := &cobra.Command{ Use: "hosts", Short: "Manage hosts", @@ -123,21 +49,26 @@ func NewCmd(cmdContext *base.CmdContext) *cobra.Command { // hosts list cmd cmd.AddCommand(newListCmd(cmdContext)) - for _, ht := range hostTypeCmds { - cmd.AddCommand(newHostTypeCmd(cmdContext, ht)) - } - base.AddFormatFlags(cmd) return cmd } func newHostTypeCmd(cmdContext *base.CmdContext, hostTypeCmd HostTypeCmd) *cobra.Command { + entitiesMap, err := getHostsEntities() + if err != nil { + log.Fatal(err) + } + hostCmd := &cobra.Command{ Use: hostTypeCmd.use, Short: hostTypeCmd.shortDesc, - Args: base.NoArgs, - Run: base.UsageRun, + PersistentPreRunE: base.CombinePreRunE( + base.CheckFormatterFlags(cmdContext, entitiesMap), + base.CheckEmptyContexts(cmdContext), + ), + Args: base.NoArgs, + Run: base.UsageRun, } hostCmd.AddCommand(newGetCmd(cmdContext, &hostTypeCmd)) @@ -154,6 +85,8 @@ func newHostTypeCmd(cmdContext *base.CmdContext, hostTypeCmd HostTypeCmd) *cobra hostCmd.AddCommand(cmdFunc(cmdContext)) } + base.AddFormatFlags(hostCmd) + return hostCmd } diff --git a/cmd/entities/hosts/hosts_test.go b/cmd/entities/hosts/hosts_test.go index 5c772db..5bda324 100644 --- a/cmd/entities/hosts/hosts_test.go +++ b/cmd/entities/hosts/hosts_test.go @@ -3,7 +3,6 @@ package hosts import ( "errors" "path/filepath" - "strings" "testing" "time" @@ -44,60 +43,18 @@ var ( OperatingSystemID: new(int64(5)), OperatingSystemFullName: new("CentOS 7 x86_64"), } - testDS = serverscom.DedicatedServer{ - ID: testId, - RackID: testId, - Type: "dedicated_server", - Title: "example.aa", - Status: "active", - LocationCode: testLocationCode, - PublicIPv4Address: &testPublicIP, - ConfigurationDetails: testConfigDetails, - Created: fixedTime, - Updated: fixedTime, - } - testKBM = serverscom.KubernetesBaremetalNode{ - ID: testId, - RackID: testId, - KubernetesClusterID: testId, - KubernetesClusterNodeID: testId, - KubernetesClusterNodeNumber: 1, - Type: "kubernetes_baremetal_node", - Title: "example.aa", - Status: "active", - LocationCode: testLocationCode, - PublicIPv4Address: &testPublicIP, - ConfigurationDetails: testConfigDetails, - Created: fixedTime, - Updated: fixedTime, - } - testSBM = serverscom.SBMServer{ - ID: testId, - RackID: testId, - Type: "sbm_server", - Title: "example.aa", - Status: "active", - LocationCode: testLocationCode, - PublicIPv4Address: &testPublicIP, - ConfigurationDetails: testConfigDetails, - Created: fixedTime, - Updated: fixedTime, - } - netTitle = "Some Net" - cidr = "100.0.8.0/29" - netFirstIP = "100.0.8.2" - netGateway = "100.0.8.1" + testNetwork = serverscom.Network{ ID: testNetworkId, - Title: &netTitle, + Title: new("Some Net"), Status: "active", - Cidr: &cidr, + Cidr: new("100.0.8.0/29"), Family: "ipv4", InterfaceType: "public", DistributionMethod: "gateway", Additional: false, - FirstIP: &netFirstIP, - Gateway: &netGateway, + FirstIP: new("100.0.8.2"), + Gateway: new("100.0.8.1"), Created: fixedTime, Updated: fixedTime, } @@ -128,6 +85,18 @@ var ( Status: "on", Type: "physical", } + + ptrFixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "ptr") + testServerID = "serverId" + testPTRID = "ptrId" + + testPTR = serverscom.PTRRecord{ + ID: testPTRID, + IP: "192.0.2.5", + Domain: "ptr-test.example.com", + Priority: 10, + TTL: 300, + } ) func TestListHostsCmd(t *testing.T) { @@ -252,3266 +221,3 @@ func TestListHostsCmd(t *testing.T) { }) } } - -func TestAddEBMCmd(t *testing.T) { - expectedInput := serverscom.DedicatedServerCreateInput{ - ServerModelID: 1234, - LocationID: 5678, - RAMSize: 16, - UplinkModels: serverscom.DedicatedServerUplinkModelsInput{ - Public: &serverscom.DedicatedServerPublicUplinkInput{ - ID: 4321, - BandwidthModelID: 8765, - }, - Private: serverscom.DedicatedServerPrivateUplinkInput{ - ID: 7890, - }, - }, - Drives: serverscom.DedicatedServerDrivesInput{ - Slots: []serverscom.DedicatedServerSlotInput{ - { - Position: 1, - DriveModelID: new(int64(3456)), - }, - { - Position: 2, - DriveModelID: new(int64(3456)), - }, - }, - Layout: []serverscom.DedicatedServerLayoutInput{ - { - SlotPositions: []int{1, 2}, - Raid: new(1), - Partitions: []serverscom.DedicatedServerLayoutPartitionInput{ - { - Target: "/boot", - Size: 500, - Fill: false, - Fs: new("ext4"), - }, - }, - }, - }, - }, - Hosts: []serverscom.DedicatedServerHostInput{ - { - Hostname: "example.aa", - PublicIPv4NetworkID: new("PublicNet123"), - PrivateIPv4NetworkID: new("PrivateNet456"), - Labels: map[string]string{ - "environment": "testing", - }, - }, - }, - } - - testCases := []struct { - name string - output string - args []string - configureMock func(*mocks.MockHostsService) - expectedOutput []byte - expectError bool - }{ - { - name: "create ebm server", - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_ebm_resp.json")), - args: []string{"--input", filepath.Join(fixtureBasePath, "create_ebm_input.json")}, - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - CreateDedicatedServers(gomock.Any(), expectedInput). - Return([]serverscom.DedicatedServer{testDS}, nil) - }, - }, - { - name: "create ebm server with merge input with flags", - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_ebm_resp.json")), - args: []string{ - "--input", filepath.Join(fixtureBasePath, "create_ebm_input.json"), - "--layout", "slot=3,slot=4,raid=0", - "--partition", "slot=3,slot=4,target=/boot,fs=ext4,size=500", - }, - configureMock: func(mock *mocks.MockHostsService) { - input := expectedInput - input.Drives.Layout = append(input.Drives.Layout, serverscom.DedicatedServerLayoutInput{ - SlotPositions: []int{3, 4}, - Raid: new(0), - Partitions: []serverscom.DedicatedServerLayoutPartitionInput{ - { - Target: "/boot", - Size: 500, - Fill: false, - Fs: new("ext4"), - }, - }, - }) - - mock.EXPECT(). - CreateDedicatedServers(gomock.Any(), input). - Return([]serverscom.DedicatedServer{testDS}, nil) - }, - }, - { - name: "skeleton for ebm server input", - output: "json", - args: []string{"--skeleton"}, - expectedOutput: testutils.ReadFixture(filepath.Join(skeletonTemplatePath, "add_ebm.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - CreateDedicatedServers(gomock.Any(), gomock.Any()). - Times(0) - }, - }, - { - name: "create ebm server with public_ipxe_boot feature and ipxe-config", - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_ebm_resp.json")), - args: []string{ - "--input", filepath.Join(fixtureBasePath, "create_ebm_input.json"), - "--feature", "public_ipxe_boot", - "--ipxe-config", "#!ipxe\nboot", - }, - configureMock: func(mock *mocks.MockHostsService) { - input := expectedInput - input.Features = []string{"public_ipxe_boot"} - input.IPXEConfig = new("#!ipxe\nboot") - mock.EXPECT(). - CreateDedicatedServers(gomock.Any(), input). - Return([]serverscom.DedicatedServer{testDS}, nil) - }, - }, - { - name: "create ebm server with ipxe-config flag", - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_ebm_resp.json")), - args: []string{ - "--input", filepath.Join(fixtureBasePath, "create_ebm_input.json"), - "--ipxe-config", "#!ipxe\nboot", - }, - configureMock: func(mock *mocks.MockHostsService) { - input := expectedInput - input.IPXEConfig = new("#!ipxe\nboot") - mock.EXPECT(). - CreateDedicatedServers(gomock.Any(), input). - Return([]serverscom.DedicatedServer{testDS}, nil) - }, - }, - { - name: "create ebm server with ipxe-config in input file", - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_ebm_resp.json")), - args: []string{ - "--input", filepath.Join(fixtureBasePath, "create_ebm_ipxe_input.json"), - }, - configureMock: func(mock *mocks.MockHostsService) { - input := expectedInput - input.IPXEConfig = new("#!ipxe\nboot") - mock.EXPECT(). - CreateDedicatedServers(gomock.Any(), input). - Return([]serverscom.DedicatedServer{testDS}, nil) - }, - }, - { - name: "create ebm server with error", - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - - if tc.configureMock != nil { - tc.configureMock(hostsServiceHandler) - } - - testCmdContext := testutils.NewTestCmdContext(scClient) - sshCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "add"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(sshCmd). - 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(MatchJSON(tc.expectedOutput)) - } - }) - } -} - -func TestAddSBMCmd(t *testing.T) { - testCases := []struct { - name string - output string - args []string - configureMock func(*mocks.MockHostsService) - expectedOutput []byte - expectError bool - }{ - { - name: "create SBM server", - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_sbm_resp.json")), - args: []string{"--input", filepath.Join(fixtureBasePath, "create_sbm_input.json")}, - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - CreateSBMServers(gomock.Any(), serverscom.SBMServerCreateInput{ - FlavorModelID: 1234, - LocationID: 5678, - Hosts: []serverscom.SBMServerHostInput{ - { - Hostname: "example.aa", - PublicIPv4NetworkID: new("PublicNetTest123"), - PrivateIPv4NetworkID: new("PrivateNetTest456"), - Labels: map[string]string{ - "environment": "testing", - }, - }, - }, - }). - Return([]serverscom.SBMServer{testSBM}, nil) - }, - }, - { - name: "create SBM server with params", - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_sbm_resp.json")), - args: []string{ - "--location-id", "5678", - "--sbm-flavor-model-id", "1234", - "--operating-system-id", "9999", - "--ssh-key-fingerprint", "48:81:0c:43:99:12:71:5e:ba:fd:e7:2f:20:d7:95:e8", - "example.aa", - }, - configureMock: func(mock *mocks.MockHostsService) { - osID := int64(9999) - mock.EXPECT(). - CreateSBMServers(gomock.Any(), serverscom.SBMServerCreateInput{ - FlavorModelID: 1234, - LocationID: 5678, - OperatingSystemID: &osID, - SSHKeyFingerprints: []string{"48:81:0c:43:99:12:71:5e:ba:fd:e7:2f:20:d7:95:e8"}, - Hosts: []serverscom.SBMServerHostInput{ - { - Hostname: "example.aa", - }, - }, - }). - Return([]serverscom.SBMServer{testSBM}, nil) - }, - }, - { - name: "skeleton for SBM server input", - output: "json", - args: []string{"--skeleton"}, - expectedOutput: testutils.ReadFixture(filepath.Join(skeletonTemplatePath, "add_sbm.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - CreateSBMServers(gomock.Any(), gomock.Any()). - Times(0) - }, - }, - { - name: "create SBM server with error", - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - - if tc.configureMock != nil { - tc.configureMock(hostsServiceHandler) - } - - testCmdContext := testutils.NewTestCmdContext(scClient) - sshCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "add"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(sshCmd). - 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(MatchJSON(tc.expectedOutput)) - } - }) - } -} - -func TestGetEBMCmd(t *testing.T) { - testCases := []struct { - name string - id string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "get ebm server in default format", - id: testId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm.txt")), - }, - { - name: "get ebm server in JSON format", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm.json")), - }, - { - name: "get ebm server in YAML format", - id: testId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm.yaml")), - }, - { - name: "get ebm server with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - GetDedicatedServer(gomock.Any(), testId). - Return(&testDS, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "get", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestGetKBMCmd(t *testing.T) { - testCases := []struct { - name string - id string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "get KBM node in default format", - id: testId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_kbm.txt")), - }, - { - name: "get KBM node in JSON format", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_kbm.json")), - }, - { - name: "get KBM node in YAML format", - id: testId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_kbm.yaml")), - }, - { - name: "get KBM node with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - GetKubernetesBaremetalNode(gomock.Any(), testId). - Return(&testKBM, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "kbm", "get", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestGetSBMCmd(t *testing.T) { - testCases := []struct { - name string - id string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "get SBM server in default format", - id: testId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm.txt")), - }, - { - name: "get SBM server in JSON format", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm.json")), - }, - { - name: "get SBM server in YAML format", - id: testId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm.yaml")), - }, - { - name: "get SBM server with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - GetSBMServer(gomock.Any(), testId). - Return(&testSBM, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "get", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListEBMCmd(t *testing.T) { - testServer1 := testDS - testServer1.Type = "dedicated_server" - testServer2 := testServer1 - testServer2.ID = "testId2" - testServer2.Title = "example.bb" - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.DedicatedServer]) - }{ - { - name: "list all ebm servers", - output: "json", - args: []string{"-A"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServer]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.DedicatedServer{ - testServer1, - testServer2, - }, nil) - }, - }, - { - name: "list ebm servers", - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServer]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.DedicatedServer{ - testServer1, - }, nil) - }, - }, - { - name: "list ebm servers with template", - args: []string{"--template", "{{range .}}Title: {{.Title}} Type: {{.Type}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServer]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.DedicatedServer{ - testServer1, - testServer2, - }, nil) - }, - }, - { - name: "list ebm servers with pageView", - args: []string{"--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServer]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.DedicatedServer{ - testServer1, - testServer2, - }, nil) - }, - }, - { - name: "list ebm servers with error", - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServer]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - collectionHandler := mocks.NewMockCollection[serverscom.DedicatedServer](mockCtrl) - - hostsServiceHandler.EXPECT(). - ListDedicatedServers(). - Return(collectionHandler). - AnyTimes() - - collectionHandler.EXPECT(). - SetParam(gomock.Any(), gomock.Any()). - Return(collectionHandler). - AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "list"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListKBMCmd(t *testing.T) { - testServer1 := testKBM - testServer1.Type = "kubernetes_baremetal_node" - testServer2 := testServer1 - testServer2.ID = "testId2" - testServer2.Title = "example.bb" - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.KubernetesBaremetalNode]) - }{ - { - name: "list all KBM nodes", - output: "json", - args: []string{"-A"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.KubernetesBaremetalNode]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.KubernetesBaremetalNode{ - testServer1, - testServer2, - }, nil) - }, - }, - { - name: "list KBM nodes", - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.KubernetesBaremetalNode]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.KubernetesBaremetalNode{ - testServer1, - }, nil) - }, - }, - { - name: "list KBM nodes with template", - args: []string{"--template", "{{range .}}Title: {{.Title}} Type: {{.Type}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.KubernetesBaremetalNode]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.KubernetesBaremetalNode{ - testServer1, - testServer2, - }, nil) - }, - }, - { - name: "list KBM nodes with pageView", - args: []string{"--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.KubernetesBaremetalNode]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.KubernetesBaremetalNode{ - testServer1, - testServer2, - }, nil) - }, - }, - { - name: "list KBM nodes with error", - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.KubernetesBaremetalNode]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - collectionHandler := mocks.NewMockCollection[serverscom.KubernetesBaremetalNode](mockCtrl) - - hostsServiceHandler.EXPECT(). - ListKubernetesBaremetalNodes(). - Return(collectionHandler). - AnyTimes() - - collectionHandler.EXPECT(). - SetParam(gomock.Any(), gomock.Any()). - Return(collectionHandler). - AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "kbm", "list"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListSBMCmd(t *testing.T) { - testServer1 := testSBM - testServer1.Type = "sbm_server" - testServer2 := testServer1 - testServer2.ID = "testId2" - testServer2.Title = "example.bb" - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.SBMServer]) - }{ - { - name: "list all SBM servers", - output: "json", - args: []string{"-A"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.SBMServer]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.SBMServer{ - testServer1, - testServer2, - }, nil) - }, - }, - { - name: "list SBM servers", - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.SBMServer]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.SBMServer{ - testServer1, - }, nil) - }, - }, - { - name: "list SBM servers with template", - args: []string{"--template", "{{range .}}Title: {{.Title}} Type: {{.Type}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.SBMServer]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.SBMServer{ - testServer1, - testServer2, - }, nil) - }, - }, - { - name: "list SBM servers with pageView", - args: []string{"--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.SBMServer]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.SBMServer{ - testServer1, - testServer2, - }, nil) - }, - }, - { - name: "list SBM servers with error", - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.SBMServer]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - collectionHandler := mocks.NewMockCollection[serverscom.SBMServer](mockCtrl) - - hostsServiceHandler.EXPECT(). - ListSBMServers(). - Return(collectionHandler). - AnyTimes() - - collectionHandler.EXPECT(). - SetParam(gomock.Any(), gomock.Any()). - Return(collectionHandler). - AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "list"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestUpdateEBMCmd(t *testing.T) { - newServer := testDS - newServer.Labels = map[string]string{"new": "label"} - - testCases := []struct { - name string - id string - output string - args []string - configureMock func(*mocks.MockHostsService) - expectedOutput []byte - expectError bool - }{ - { - name: "update ebm server", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "update_ebm_resp.json")), - args: []string{"--label", "new=label"}, - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - UpdateDedicatedServer(gomock.Any(), testId, serverscom.DedicatedServerUpdateInput{ - Labels: map[string]string{"new": "label"}, - }). - Return(&newServer, nil) - }, - }, - { - name: "update ebm server with error", - id: testId, - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - UpdateDedicatedServer(gomock.Any(), testId, serverscom.DedicatedServerUpdateInput{ - Labels: make(map[string]string), - }). - Return(nil, errors.New("some error")) - }, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - - if tc.configureMock != nil { - tc.configureMock(hostsServiceHandler) - } - - testCmdContext := testutils.NewTestCmdContext(scClient) - sshCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "update", tc.id} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(sshCmd). - 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 TestUpdateKBMCmd(t *testing.T) { - newServer := testKBM - newServer.Labels = map[string]string{"new": "label"} - - testCases := []struct { - name string - id string - output string - args []string - configureMock func(*mocks.MockHostsService) - expectedOutput []byte - expectError bool - }{ - { - name: "update KBM node", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "update_kbm_resp.json")), - args: []string{"--label", "new=label"}, - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - UpdateKubernetesBaremetalNode(gomock.Any(), testId, serverscom.KubernetesBaremetalNodeUpdateInput{ - Labels: map[string]string{"new": "label"}, - }). - Return(&newServer, nil) - }, - }, - { - name: "update KBM node with error", - id: testId, - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - UpdateKubernetesBaremetalNode(gomock.Any(), testId, serverscom.KubernetesBaremetalNodeUpdateInput{ - Labels: make(map[string]string), - }). - Return(nil, errors.New("some error")) - }, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - - if tc.configureMock != nil { - tc.configureMock(hostsServiceHandler) - } - - testCmdContext := testutils.NewTestCmdContext(scClient) - sshCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "kbm", "update", tc.id} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(sshCmd). - 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 TestUpdateSBMCmd(t *testing.T) { - newServer := testSBM - newServer.Labels = map[string]string{"new": "label"} - - testCases := []struct { - name string - id string - output string - args []string - configureMock func(*mocks.MockHostsService) - expectedOutput []byte - expectError bool - }{ - { - name: "update SBM server node", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "update_sbm_resp.json")), - args: []string{"--label", "new=label"}, - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - UpdateSBMServer(gomock.Any(), testId, serverscom.SBMServerUpdateInput{ - Labels: map[string]string{"new": "label"}, - }). - Return(&newServer, nil) - }, - }, - { - name: "update SBM server with error", - id: testId, - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - UpdateSBMServer(gomock.Any(), testId, serverscom.SBMServerUpdateInput{ - Labels: make(map[string]string), - }). - Return(nil, errors.New("some error")) - }, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - - if tc.configureMock != nil { - tc.configureMock(hostsServiceHandler) - } - - testCmdContext := testutils.NewTestCmdContext(scClient) - sshCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "update", tc.id} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(sshCmd). - 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 TestScheduleReleaseEBMCmd(t *testing.T) { - releasedServer := testDS - testCases := []struct { - name string - id string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockHostsService) - }{ - { - name: "release ebm server", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "release_ebm_resp.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - ScheduleReleaseForDedicatedServer(gomock.Any(), testId, serverscom.ScheduleReleaseInput{}). - Return(&releasedServer, nil) - }, - }, - { - name: "release ebm server with --release-after", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "release_ebm_scheduled_resp.json")), - args: []string{"--release-after", "2025-01-01T12:34:56+03:00"}, - configureMock: func(mock *mocks.MockHostsService) { - releasedServer.ScheduledRelease = &fixedTime - mock.EXPECT(). - ScheduleReleaseForDedicatedServer(gomock.Any(), testId, serverscom.ScheduleReleaseInput{ReleaseAfter: "2025-01-01T12:34:56+03:00"}). - Return(&releasedServer, nil) - }, - }, - { - name: "release ebm server with error", - id: testId, - expectError: true, - configureMock: func(mock *mocks.MockHostsService) { - releasedServer.ScheduledRelease = &fixedTime - mock.EXPECT(). - ScheduleReleaseForDedicatedServer(gomock.Any(), testId, serverscom.ScheduleReleaseInput{}). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - - if tc.configureMock != nil { - tc.configureMock(hostsServiceHandler) - } - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "schedule-release", tc.id} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestAbortReleaseEBMCmd(t *testing.T) { - testCases := []struct { - name string - id string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "abort release ebm server", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm.json")), - }, - { - name: "abort release ebm server with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - AbortReleaseForDedicatedServer(gomock.Any(), testId). - Return(&testDS, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "abort-release", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestReleaseSBMCmd(t *testing.T) { - testCases := []struct { - name string - id string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "release SBM server", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm.json")), - }, - { - name: "release SBM server with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - ReleaseSBMServer(gomock.Any(), testId). - Return(&testSBM, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "release", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestGetEBMNetworkCmd(t *testing.T) { - testCases := []struct { - name string - id string - networkID string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "get DS network in default format", - id: testId, - networkID: testNetworkId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.txt")), - }, - { - name: "get DS network in JSON format", - id: testId, - networkID: testNetworkId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.json")), - }, - { - name: "get DS network in YAML format", - id: testId, - networkID: testNetworkId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.yaml")), - }, - { - name: "get DS network with error", - id: testId, - networkID: testNetworkId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - GetDedicatedServerNetwork(gomock.Any(), tc.id, tc.networkID). - Return(&testNetwork, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{ - "hosts", "ebm", "get-network", tc.id, - "--network-id", tc.networkID, - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListEBMNetworksCmd(t *testing.T) { - testNetwork1 := testNetwork - testNetwork1.ID = testNetworkId - testNetwork2 := testNetwork1 - testNetwork2.ID = "testNetId2" - netTitle2 := "Another Net" - testNetwork2.Title = &netTitle2 - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.Network]) - }{ - { - name: "list all DS networks", - output: "json", - args: []string{"testServerId", "-A"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_networks_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - testNetwork2, - }, nil) - }, - }, - { - name: "list DS networks", - output: "json", - args: []string{"testServerId"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_networks.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - }, nil) - }, - }, - { - name: "list DS networks with template", - args: []string{"testServerId", "--template", "{{range .}}Network: {{.ID}} Title: {{.Title}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_networks_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - testNetwork2, - }, nil) - }, - }, - { - name: "list DS networks with pageView", - args: []string{"testServerId", "--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_ebm_networks_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - testNetwork2, - }, nil) - }, - }, - { - name: "list DS networks with error", - args: []string{"testServerId"}, - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - collectionHandler := mocks.NewMockCollection[serverscom.Network](mockCtrl) - - hostsServiceHandler.EXPECT(). - DedicatedServerNetworks(gomock.Any()). - Return(collectionHandler). - AnyTimes() - - collectionHandler.EXPECT(). - SetParam(gomock.Any(), gomock.Any()). - Return(collectionHandler). - AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "list-networks"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestAddEBMNetworkCmd(t *testing.T) { - expectedInputPublic := serverscom.NetworkInput{ - DistributionMethod: "route", - Mask: 32, - } - expectedInputPrivate := serverscom.NetworkInput{ - DistributionMethod: "gateway", - Mask: 29, - } - - testCases := []struct { - name string - output string - args []string - configureMock func(*mocks.MockHostsService) - expectedOutput []byte - expectError bool - }{ - { - name: "add public DS network", - output: "json", - args: []string{ - testId, - "--type", "public", - "--mask", "32", - "--distribution-method", "route", - }, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - AddDedicatedServerPublicIPv4Network(gomock.Any(), testId, expectedInputPublic). - Return(&testNetwork, nil) - }, - }, - { - name: "add private DS network", - output: "json", - args: []string{ - testId, - "--type", "private", - "--mask", "29", - "--distribution-method", "gateway", - }, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - AddDedicatedServerPrivateIPv4Network(gomock.Any(), testId, expectedInputPrivate). - Return(&testNetwork, nil) - }, - }, - { - name: "add DS network with unsupported mask", - args: []string{ - testId, - "--type", "public", - "--mask", "24", - "--distribution-method", "gateway", - }, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - - if tc.configureMock != nil { - tc.configureMock(hostsServiceHandler) - } - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := append([]string{"hosts", "ebm", "add-network"}, tc.args...) - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestDeleteEBMNetworkCmd(t *testing.T) { - testCases := []struct { - name string - id string - networkID string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "delete DS network", - id: testId, - networkID: testNetworkId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.json")), - }, - { - name: "delete DS network with error", - id: testId, - networkID: testNetworkId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - DeleteDedicatedServerNetwork(gomock.Any(), tc.id, tc.networkID). - Return(&testNetwork, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "delete-network", tc.id, "--network-id", tc.networkID} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListKBMPowerFeedsCmd(t *testing.T) { - testPowerFeed1 := testPowerFeed - testPowerFeed2 := testPowerFeed1 - - testPowerFeed2.Name = "testPowerFeed2" - testPowerFeed2.Status = "off" - - testCases := []struct { - name string - id string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.HostPowerFeed]) - }{ - { - name: "get KBM node power_feeds in default format", - id: testId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.txt")), - }, - { - name: "get KBM node power_feeds", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.json")), - }, - { - name: "get KBM node power_feeds in YAML format", - id: testId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.yaml")), - }, - { - name: "get KBM node power_feeds with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - KubernetesBaremetalNodePowerFeeds(gomock.Any(), testId). - Return([]serverscom.HostPowerFeed{testPowerFeed1, testPowerFeed2}, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "kbm", "list-power-feeds", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListEBMPowerFeedsCmd(t *testing.T) { - testPowerFeed1 := testPowerFeed - testPowerFeed2 := testPowerFeed1 - - testPowerFeed2.Name = "testPowerFeed2" - testPowerFeed2.Status = "off" - - testCases := []struct { - name string - id string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.HostPowerFeed]) - }{ - { - name: "get ds power_feeds in default format", - id: testId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.txt")), - }, - { - name: "get ds power_feeds", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.json")), - }, - { - name: "get ds power_feeds in YAML format", - id: testId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.yaml")), - }, - { - name: "get ds power_feeds with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - DedicatedServerPowerFeeds(gomock.Any(), testId). - Return([]serverscom.HostPowerFeed{testPowerFeed1, testPowerFeed2}, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "list-power-feeds", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListSBMPowerFeedsCmd(t *testing.T) { - testPowerFeed1 := testPowerFeed - testPowerFeed2 := testPowerFeed1 - - testPowerFeed2.Name = "testPowerFeed2" - testPowerFeed2.Status = "off" - - testCases := []struct { - name string - id string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.HostPowerFeed]) - }{ - { - name: "get sbm power_feeds in default format", - id: testId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.txt")), - }, - { - name: "get sbm power_feeds", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.json")), - }, - { - name: "get sbm power_feeds in YAML format", - id: testId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.yaml")), - }, - { - name: "get sbm power_feeds with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - SBMServerPowerFeeds(gomock.Any(), testId). - Return([]serverscom.HostPowerFeed{testPowerFeed1, testPowerFeed2}, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "list-power-feeds", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListKBMNetworksCmd(t *testing.T) { - testNetwork1 := testNetwork - testNetwork1.ID = testNetworkId - testNetwork2 := testNetwork1 - testNetwork2.ID = "testNetId2" - netTitle2 := "Another Net" - testNetwork2.Title = &netTitle2 - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.Network]) - }{ - { - name: "list KBM node all networks", - output: "json", - args: []string{"testServerId", "-A"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_networks_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - testNetwork2, - }, nil) - }, - }, - { - name: "list KBM node networks", - output: "json", - args: []string{"testServerId"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_networks.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - }, nil) - }, - }, - { - name: "list DS networks with template", - args: []string{"testServerId", "--template", "{{range .}}Network: {{.ID}} Title: {{.Title}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_networks_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - testNetwork2, - }, nil) - }, - }, - { - name: "list DS networks with pageView", - args: []string{"testServerId", "--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_networks_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - testNetwork2, - }, nil) - }, - }, - { - name: "list DS networks with error", - args: []string{"testServerId"}, - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - collectionHandler := mocks.NewMockCollection[serverscom.Network](mockCtrl) - - hostsServiceHandler.EXPECT(). - KubernetesBaremetalNodeNetworks(gomock.Any()). - Return(collectionHandler). - AnyTimes() - - collectionHandler.EXPECT(). - SetParam(gomock.Any(), gomock.Any()). - Return(collectionHandler). - AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "kbm", "list-networks"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestGetSBMNetworkCmd(t *testing.T) { - testCases := []struct { - name string - id string - networkID string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "get SBM network in default format", - id: testId, - networkID: testNetworkId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network.txt")), - }, - { - name: "get SBM network in JSON format", - id: testId, - networkID: testNetworkId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network.json")), - }, - { - name: "get SBM network in YAML format", - id: testId, - networkID: testNetworkId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network.yaml")), - }, - { - name: "get SBM network with error", - id: testId, - networkID: testNetworkId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - GetSBMServerNetwork(gomock.Any(), tc.id, tc.networkID). - Return(&testNetwork, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{ - "hosts", "sbm", "get-network", tc.id, - "--network-id", tc.networkID, - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListSBMNetworksCmd(t *testing.T) { - testNetwork1 := testNetwork - testNetwork1.ID = testNetworkId - testNetwork2 := testNetwork1 - testNetwork2.ID = "testNetId2" - netTitle2 := "Another Net" - testNetwork2.Title = &netTitle2 - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.Network]) - }{ - { - name: "list all SBM networks", - output: "json", - args: []string{"testServerId", "-A"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_networks_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - testNetwork2, - }, nil) - }, - }, - { - name: "list SBM networks", - output: "json", - args: []string{"testServerId"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_networks.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - }, nil) - }, - }, - { - name: "list SBM networks with template", - args: []string{"testServerId", "--template", "{{range .}}Network: {{.ID}} Title: {{.Title}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_networks_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - testNetwork2, - }, nil) - }, - }, - { - name: "list SBM networks with pageView", - args: []string{"testServerId", "--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_networks_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.Network{ - testNetwork1, - testNetwork2, - }, nil) - }, - }, - { - name: "list SBM networks with error", - args: []string{"testServerId"}, - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - collectionHandler := mocks.NewMockCollection[serverscom.Network](mockCtrl) - - hostsServiceHandler.EXPECT(). - SBMServerNetworks(gomock.Any()). - Return(collectionHandler). - AnyTimes() - - collectionHandler.EXPECT(). - SetParam(gomock.Any(), gomock.Any()). - Return(collectionHandler). - AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "list-networks"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestAddSBMNetworkCmd(t *testing.T) { - expectedInputPrivate := serverscom.NetworkInput{ - DistributionMethod: "gateway", - Mask: 29, - } - - testCases := []struct { - name string - output string - args []string - configureMock func(*mocks.MockHostsService) - expectedOutput []byte - expectError bool - }{ - { - name: "add private SBM network", - output: "json", - args: []string{ - testId, - "--type", "private", - "--mask", "29", - "--distribution-method", "gateway", - }, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network.json")), - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - AddSBMServerPrivateIPv4Network(gomock.Any(), testId, expectedInputPrivate). - Return(&testNetwork, nil) - }, - }, - { - name: "add public SBM network is not supported", - args: []string{ - testId, - "--type", "public", - "--mask", "29", - }, - expectError: true, - }, - { - name: "add SBM network with unsupported mask", - args: []string{ - testId, - "--type", "private", - "--mask", "24", - }, - expectError: true, - }, - { - name: "add SBM network with error", - output: "json", - args: []string{ - testId, - "--type", "private", - "--mask", "29", - }, - expectError: true, - configureMock: func(mock *mocks.MockHostsService) { - mock.EXPECT(). - AddSBMServerPrivateIPv4Network(gomock.Any(), testId, expectedInputPrivate). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - - if tc.configureMock != nil { - tc.configureMock(hostsServiceHandler) - } - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := append([]string{"hosts", "sbm", "add-network"}, tc.args...) - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestDeleteSBMNetworkCmd(t *testing.T) { - testCases := []struct { - name string - id string - networkID string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "delete SBM network", - id: testId, - networkID: testNetworkId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network.json")), - }, - { - name: "delete SBM network with error", - id: testId, - networkID: testNetworkId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - DeleteSBMServerNetwork(gomock.Any(), tc.id, tc.networkID). - Return(&testNetwork, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "delete-network", tc.id, "--network-id", tc.networkID} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestActivateEBMIPv6NetworkCmd(t *testing.T) { - testCases := []struct { - name string - id string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "activate DS IPv6 network", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network.json")), - }, - { - name: "activate DS IPv6 network with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - ActivateDedicatedServerPubliIPv6Network(gomock.Any(), tc.id). - Return(&testNetwork, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "activate-ipv6-network", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestGetEBMNetworkUsageCmd(t *testing.T) { - testCases := []struct { - name string - id string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "get DS network usage in default format", - id: testId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network_usage.txt")), - }, - { - name: "get DS network usage in JSON format", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network_usage.json")), - }, - { - name: "get DS network usage in YAML format", - id: testId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_ebm_network_usage.yaml")), - }, - { - name: "get DS network usage with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - GetDedicatedServerNetworkUsage(gomock.Any(), tc.id). - Return(&testNetworkUsage, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "network-usage", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestGetSBMNetworkUsageCmd(t *testing.T) { - testCases := []struct { - name string - id string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "get SBM network usage in default format", - id: testId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network_usage.txt")), - }, - { - name: "get SBM network usage in JSON format", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network_usage.json")), - }, - { - name: "get SBM network usage in YAML format", - id: testId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network_usage.yaml")), - }, - { - name: "get SBM network usage with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - GetSBMServerNetworkUsage(gomock.Any(), tc.id). - Return(&testNetworkUsage, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "network-usage", tc.id} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListEBMDriveSlotsCmd(t *testing.T) { - testDriveSlot1 := testDriveSlot - testDriveSlot2 := testDriveSlot1 - testDriveSlot2.Position = 2 - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.HostDriveSlot]) - }{ - { - name: "list ds all drive slots", - output: "json", - args: []string{"testServerId", "-A"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.HostDriveSlot{ - testDriveSlot1, - testDriveSlot2, - }, nil) - }, - }, - { - name: "list ds drive slots", - output: "json", - args: []string{"testServerId"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.HostDriveSlot{ - testDriveSlot1, - }, nil) - }, - }, - { - name: "list ds drive slots with template", - args: []string{"testServerId", "--template", "{{range .}}Position: {{.Position}} Interface: {{.Interface}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.HostDriveSlot{ - testDriveSlot1, - testDriveSlot2, - }, nil) - }, - }, - { - name: "list ds drive slots with pageView", - args: []string{"testServerId", "--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.HostDriveSlot{ - testDriveSlot1, - testDriveSlot2, - }, nil) - }, - }, - { - name: "list ds drive slots with error", - args: []string{"testServerId"}, - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - collectionHandler := mocks.NewMockCollection[serverscom.HostDriveSlot](mockCtrl) - - hostsServiceHandler.EXPECT(). - DedicatedServerDriveSlots(gomock.Any()). - Return(collectionHandler). - AnyTimes() - - collectionHandler.EXPECT(). - SetParam(gomock.Any(), gomock.Any()). - Return(collectionHandler). - AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "list-drive-slots"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestListKBMDriveSlotsCmd(t *testing.T) { - testDriveSlot1 := testDriveSlot - testDriveSlot2 := testDriveSlot1 - testDriveSlot2.Position = 2 - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.HostDriveSlot]) - }{ - { - name: "list KBM node all drive slots", - output: "json", - args: []string{"testServerId", "-A"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.HostDriveSlot{ - testDriveSlot1, - testDriveSlot2, - }, nil) - }, - }, - { - name: "list KBM node drive slots", - output: "json", - args: []string{"testServerId"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.HostDriveSlot{ - testDriveSlot1, - }, nil) - }, - }, - { - name: "list KBM node drive slots with template", - args: []string{"testServerId", "--template", "{{range .}}Position: {{.Position}} Interface: {{.Interface}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.HostDriveSlot{ - testDriveSlot1, - testDriveSlot2, - }, nil) - }, - }, - { - name: "list KBM node drive slots with pageView", - args: []string{"testServerId", "--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.HostDriveSlot{ - testDriveSlot1, - testDriveSlot2, - }, nil) - }, - }, - { - name: "list KBM node drive slots with error", - args: []string{"testServerId"}, - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - collectionHandler := mocks.NewMockCollection[serverscom.HostDriveSlot](mockCtrl) - - hostsServiceHandler.EXPECT(). - KubernetesBaremetalNodeDriveSlots(gomock.Any()). - Return(collectionHandler). - AnyTimes() - - collectionHandler.EXPECT(). - SetParam(gomock.Any(), gomock.Any()). - Return(collectionHandler). - AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "kbm", "list-drive-slots"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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 TestKBMPowerCmd(t *testing.T) { - testServer := testKBM - testServer.Labels = map[string]string{"new": "label"} - - testCases := []struct { - name string - id string - output string - args []string - expectedOutput []byte - expectError bool - }{ - { - name: "power on kbm node", - id: testId, - args: []string{"hosts", "kbm", "power", testId, "--command=on"}, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "set_kbm_power.json")), - }, - { - name: "power off kbm node", - id: testId, - args: []string{"hosts", "kbm", "power", testId, "--command=off"}, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "set_kbm_power.json")), - }, - { - name: "power cycle kbm node", - id: testId, - args: []string{"hosts", "kbm", "power", testId, "--command=cycle"}, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "set_kbm_power.json")), - }, - { - name: "power on kbm node with error", - id: testId, - args: []string{"hosts", "kbm", "power", testId, "--command=on"}, - expectError: true, - }, - { - name: "power on kbm node without flag error", - id: testId, - args: []string{"hosts", "kbm", "power", testId}, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - - var powerVal string - if tc.args != nil { - powerVal = strings.TrimPrefix(tc.args[len(tc.args)-1], "--command=") - } - expectPowerCall(hostsServiceHandler, powerVal, testId, &testServer, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - if tc.output != "" { - tc.args = append(tc.args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - WithArgs(tc.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 expectPowerCall(m *mocks.MockHostsService, action string, id string, s *serverscom.KubernetesBaremetalNode, err error) { - calls := map[string]func() *gomock.Call{ - "on": func() *gomock.Call { return m.EXPECT().PowerOnKubernetesBaremetalNode(gomock.Any(), id) }, - "off": func() *gomock.Call { return m.EXPECT().PowerOffKubernetesBaremetalNode(gomock.Any(), id) }, - "cycle": func() *gomock.Call { return m.EXPECT().PowerCycleKubernetesBaremetalNode(gomock.Any(), id) }, - } - - if action == "" { - m.EXPECT(). - PowerOnKubernetesBaremetalNode(gomock.Any(), id). - Times(0) - m.EXPECT(). - PowerOffKubernetesBaremetalNode(gomock.Any(), id). - Times(0) - m.EXPECT(). - PowerCycleKubernetesBaremetalNode(gomock.Any(), id). - Times(0) - - gomock.InOrder( - calls["on"]().Times(0), - calls["off"]().Times(0), - calls["cycle"]().Times(0), - ) - - return - } - - if h, ok := calls[action]; ok { - h().Return(s, err).Times(1) - } -} diff --git a/cmd/entities/hosts/kbm.go b/cmd/entities/hosts/kbm.go new file mode 100644 index 0000000..d02c46d --- /dev/null +++ b/cmd/entities/hosts/kbm.go @@ -0,0 +1,26 @@ +package hosts + +import ( + "github.com/serverscom/srvctl/cmd/base" + "github.com/spf13/cobra" +) + +// NewKBMCmd builds the top-level "kbm" command. +func NewKBMCmd(cmdContext *base.CmdContext) *cobra.Command { + return newHostTypeCmd(cmdContext, HostTypeCmd{ + use: "kbm", + shortDesc: "Manage kubernetes baremetal nodes", + entityName: "Kubernetes baremetal nodes", + typeFlag: "kubernetes_baremetal_node", + managers: HostManagers{ + getMgr: &KBMGetMgr{}, + powerMgr: &KBMPowerMgr{}, + }, + extraCmds: []func(*base.CmdContext) *cobra.Command{ + newUpdateKBMCmd, + newListKBMCmd, + newListKBMNetworksCmd, + newListKBMDriveSlotsCmd, + }, + }) +} diff --git a/cmd/entities/hosts/kbm_test.go b/cmd/entities/hosts/kbm_test.go new file mode 100644 index 0000000..e917c88 --- /dev/null +++ b/cmd/entities/hosts/kbm_test.go @@ -0,0 +1,816 @@ +package hosts + +import ( + "errors" + "path/filepath" + "strings" + "testing" + + . "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 ( + testKBM = serverscom.KubernetesBaremetalNode{ + ID: testId, + RackID: testId, + KubernetesClusterID: testId, + KubernetesClusterNodeID: testId, + KubernetesClusterNodeNumber: 1, + Type: "kubernetes_baremetal_node", + Title: "example.aa", + Status: "active", + LocationCode: testLocationCode, + PublicIPv4Address: &testPublicIP, + ConfigurationDetails: testConfigDetails, + Created: fixedTime, + Updated: fixedTime, + } +) + +func TestGetKBMCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "get KBM node in default format", + id: testId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_kbm.txt")), + }, + { + name: "get KBM node in JSON format", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_kbm.json")), + }, + { + name: "get KBM node in YAML format", + id: testId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_kbm.yaml")), + }, + { + name: "get KBM node with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + GetKubernetesBaremetalNode(gomock.Any(), testId). + Return(&testKBM, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + kbmCmd := NewKBMCmd(testCmdContext) + + args := []string{"kbm", "get", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(kbmCmd). + 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 TestListKBMCmd(t *testing.T) { + testServer1 := testKBM + testServer1.Type = "kubernetes_baremetal_node" + testServer2 := testServer1 + testServer2.ID = "testId2" + testServer2.Title = "example.bb" + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.KubernetesBaremetalNode]) + }{ + { + name: "list all KBM nodes", + output: "json", + args: []string{"-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.KubernetesBaremetalNode]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.KubernetesBaremetalNode{ + testServer1, + testServer2, + }, nil) + }, + }, + { + name: "list KBM nodes", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.KubernetesBaremetalNode]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.KubernetesBaremetalNode{ + testServer1, + }, nil) + }, + }, + { + name: "list KBM nodes with template", + args: []string{"--template", "{{range .}}Title: {{.Title}} Type: {{.Type}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.KubernetesBaremetalNode]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.KubernetesBaremetalNode{ + testServer1, + testServer2, + }, nil) + }, + }, + { + name: "list KBM nodes with pageView", + args: []string{"--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.KubernetesBaremetalNode]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.KubernetesBaremetalNode{ + testServer1, + testServer2, + }, nil) + }, + }, + { + name: "list KBM nodes with error", + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.KubernetesBaremetalNode]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + collectionHandler := mocks.NewMockCollection[serverscom.KubernetesBaremetalNode](mockCtrl) + + hostsServiceHandler.EXPECT(). + ListKubernetesBaremetalNodes(). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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) + kbmCmd := NewKBMCmd(testCmdContext) + + args := []string{"kbm", "list"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(kbmCmd). + 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 TestUpdateKBMCmd(t *testing.T) { + newServer := testKBM + newServer.Labels = map[string]string{"new": "label"} + + testCases := []struct { + name string + id string + output string + args []string + configureMock func(*mocks.MockHostsService) + expectedOutput []byte + expectError bool + }{ + { + name: "update KBM node", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "update_kbm_resp.json")), + args: []string{"--label", "new=label"}, + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + UpdateKubernetesBaremetalNode(gomock.Any(), testId, serverscom.KubernetesBaremetalNodeUpdateInput{ + Labels: map[string]string{"new": "label"}, + }). + Return(&newServer, nil) + }, + }, + { + name: "update KBM node with error", + id: testId, + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + UpdateKubernetesBaremetalNode(gomock.Any(), testId, serverscom.KubernetesBaremetalNodeUpdateInput{ + Labels: make(map[string]string), + }). + Return(nil, errors.New("some error")) + }, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + + if tc.configureMock != nil { + tc.configureMock(hostsServiceHandler) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + sshCmd := NewKBMCmd(testCmdContext) + + args := []string{"kbm", "update", tc.id} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sshCmd). + 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 TestListKBMPowerFeedsCmd(t *testing.T) { + testPowerFeed1 := testPowerFeed + testPowerFeed2 := testPowerFeed1 + + testPowerFeed2.Name = "testPowerFeed2" + testPowerFeed2.Status = "off" + + testCases := []struct { + name string + id string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.HostPowerFeed]) + }{ + { + name: "get KBM node power_feeds in default format", + id: testId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.txt")), + }, + { + name: "get KBM node power_feeds", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.json")), + }, + { + name: "get KBM node power_feeds in YAML format", + id: testId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.yaml")), + }, + { + name: "get KBM node power_feeds with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + KubernetesBaremetalNodePowerFeeds(gomock.Any(), testId). + Return([]serverscom.HostPowerFeed{testPowerFeed1, testPowerFeed2}, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + kbmCmd := NewKBMCmd(testCmdContext) + + args := []string{"kbm", "list-power-feeds", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(kbmCmd). + 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 TestListKBMNetworksCmd(t *testing.T) { + testNetwork1 := testNetwork + testNetwork1.ID = testNetworkId + testNetwork2 := testNetwork1 + testNetwork2.ID = "testNetId2" + netTitle2 := "Another Net" + testNetwork2.Title = &netTitle2 + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.Network]) + }{ + { + name: "list KBM node all networks", + output: "json", + args: []string{"testServerId", "-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_networks_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + testNetwork2, + }, nil) + }, + }, + { + name: "list KBM node networks", + output: "json", + args: []string{"testServerId"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_networks.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + }, nil) + }, + }, + { + name: "list DS networks with template", + args: []string{"testServerId", "--template", "{{range .}}Network: {{.ID}} Title: {{.Title}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_networks_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + testNetwork2, + }, nil) + }, + }, + { + name: "list DS networks with pageView", + args: []string{"testServerId", "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_kbm_networks_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + testNetwork2, + }, nil) + }, + }, + { + name: "list DS networks with error", + args: []string{"testServerId"}, + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + collectionHandler := mocks.NewMockCollection[serverscom.Network](mockCtrl) + + hostsServiceHandler.EXPECT(). + KubernetesBaremetalNodeNetworks(gomock.Any()). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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) + kbmCmd := NewKBMCmd(testCmdContext) + + args := []string{"kbm", "list-networks"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(kbmCmd). + 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 TestListKBMDriveSlotsCmd(t *testing.T) { + testDriveSlot1 := testDriveSlot + testDriveSlot2 := testDriveSlot1 + testDriveSlot2.Position = 2 + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.HostDriveSlot]) + }{ + { + name: "list KBM node all drive slots", + output: "json", + args: []string{"testServerId", "-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.HostDriveSlot{ + testDriveSlot1, + testDriveSlot2, + }, nil) + }, + }, + { + name: "list KBM node drive slots", + output: "json", + args: []string{"testServerId"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.HostDriveSlot{ + testDriveSlot1, + }, nil) + }, + }, + { + name: "list KBM node drive slots with template", + args: []string{"testServerId", "--template", "{{range .}}Position: {{.Position}} Interface: {{.Interface}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.HostDriveSlot{ + testDriveSlot1, + testDriveSlot2, + }, nil) + }, + }, + { + name: "list KBM node drive slots with pageView", + args: []string{"testServerId", "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_drive_slots_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.HostDriveSlot{ + testDriveSlot1, + testDriveSlot2, + }, nil) + }, + }, + { + name: "list KBM node drive slots with error", + args: []string{"testServerId"}, + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.HostDriveSlot]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + collectionHandler := mocks.NewMockCollection[serverscom.HostDriveSlot](mockCtrl) + + hostsServiceHandler.EXPECT(). + KubernetesBaremetalNodeDriveSlots(gomock.Any()). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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) + kbmCmd := NewKBMCmd(testCmdContext) + + args := []string{"kbm", "list-drive-slots"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(kbmCmd). + 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 TestKBMPowerCmd(t *testing.T) { + testServer := testKBM + testServer.Labels = map[string]string{"new": "label"} + + testCases := []struct { + name string + id string + output string + args []string + expectedOutput []byte + expectError bool + }{ + { + name: "power on kbm node", + id: testId, + args: []string{"kbm", "power", testId, "--command=on"}, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "set_kbm_power.json")), + }, + { + name: "power off kbm node", + id: testId, + args: []string{"kbm", "power", testId, "--command=off"}, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "set_kbm_power.json")), + }, + { + name: "power cycle kbm node", + id: testId, + args: []string{"kbm", "power", testId, "--command=cycle"}, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "set_kbm_power.json")), + }, + { + name: "power on kbm node with error", + id: testId, + args: []string{"kbm", "power", testId, "--command=on"}, + expectError: true, + }, + { + name: "power on kbm node without flag error", + id: testId, + args: []string{"kbm", "power", testId}, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + + var powerVal string + if tc.args != nil { + powerVal = strings.TrimPrefix(tc.args[len(tc.args)-1], "--command=") + } + expectPowerCall(hostsServiceHandler, powerVal, testId, &testServer, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + kbmCmd := NewKBMCmd(testCmdContext) + + if tc.output != "" { + tc.args = append(tc.args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(kbmCmd). + WithArgs(tc.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 expectPowerCall(m *mocks.MockHostsService, action string, id string, s *serverscom.KubernetesBaremetalNode, err error) { + calls := map[string]func() *gomock.Call{ + "on": func() *gomock.Call { return m.EXPECT().PowerOnKubernetesBaremetalNode(gomock.Any(), id) }, + "off": func() *gomock.Call { return m.EXPECT().PowerOffKubernetesBaremetalNode(gomock.Any(), id) }, + "cycle": func() *gomock.Call { return m.EXPECT().PowerCycleKubernetesBaremetalNode(gomock.Any(), id) }, + } + + if action == "" { + m.EXPECT(). + PowerOnKubernetesBaremetalNode(gomock.Any(), id). + Times(0) + m.EXPECT(). + PowerOffKubernetesBaremetalNode(gomock.Any(), id). + Times(0) + m.EXPECT(). + PowerCycleKubernetesBaremetalNode(gomock.Any(), id). + Times(0) + + gomock.InOrder( + calls["on"]().Times(0), + calls["off"]().Times(0), + calls["cycle"]().Times(0), + ) + + return + } + + if h, ok := calls[action]; ok { + h().Return(s, err).Times(1) + } +} diff --git a/cmd/entities/hosts/oob_test.go b/cmd/entities/hosts/oob_test.go deleted file mode 100644 index 5112e79..0000000 --- a/cmd/entities/hosts/oob_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package hosts - -import ( - "errors" - "path/filepath" - "testing" - - . "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 ( - oobFixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "hosts", "oob") - testOobCreds = serverscom.DedicatedServerOOBCredentials{ - Login: "test", - Secret: "secret", - } -) - -func TestGetEBMOOBCredsCmd(t *testing.T) { - testCases := []struct { - name string - id string - output string - expectedOutput []byte - expectError bool - }{ - { - name: "get ebm server oob creds in default format", - id: testId, - output: "", - expectedOutput: testutils.ReadFixture(filepath.Join(oobFixtureBasePath, "get.txt")), - }, - { - name: "get ebm server oob creds in JSON format", - id: testId, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(oobFixtureBasePath, "get.json")), - }, - { - name: "get ebm server oob creds in YAML format", - id: testId, - output: "yaml", - expectedOutput: testutils.ReadFixture(filepath.Join(oobFixtureBasePath, "get.yaml")), - }, - { - name: "get ebm server oob creds with error", - id: testId, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostsServiceHandler - - 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") - } - hostsServiceHandler.EXPECT(). - GetDedicatedServerOOBCredentials(gomock.Any(), testId, map[string]string{"fingerprint": "test"}). - Return(&testOobCreds, err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - hostsCmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "get-oob-credentials", tc.id, "--fingerprint", "test"} - if tc.output != "" { - args = append(args, "--output", tc.output) - } - - builder := testutils.NewTestCommandBuilder(). - WithCommand(hostsCmd). - 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))) - } - }) - } -} diff --git a/cmd/entities/hosts/ptr_test.go b/cmd/entities/hosts/ptr_test.go deleted file mode 100644 index b631b7e..0000000 --- a/cmd/entities/hosts/ptr_test.go +++ /dev/null @@ -1,539 +0,0 @@ -package hosts - -import ( - "errors" - "path/filepath" - "testing" - - . "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 ( - ptrFixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "ptr") - testServerID = "serverId" - testPTRID = "ptrId" - - testPTR = serverscom.PTRRecord{ - ID: testPTRID, - IP: "192.0.2.5", - Domain: "ptr-test.example.com", - Priority: 10, - TTL: 300, - } -) - -func TestListEBMPTRCmd(t *testing.T) { - testPTR1 := testPTR - testPTR2 := testPTR - testPTR1.ID += "1" - testPTR2.ID += "2" - testPTR2.Domain = "another.example.com" - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.PTRRecord]) - }{ - { - name: "list all ptr records", - output: "json", - args: []string{"-A", testServerID}, - expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.PTRRecord{ - testPTR1, - testPTR2, - }, nil) - }, - }, - { - name: "list ptr records", - output: "json", - args: []string{testServerID}, - expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.PTRRecord{ - testPTR1, - }, nil) - }, - }, - { - name: "list ptr records with template", - args: []string{testServerID, "--template", "{{range .}}ID: {{.ID}} PTR: {{.Domain}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.PTRRecord{ - testPTR1, - testPTR2, - }, nil) - }, - }, - { - name: "list ptr records with page-view", - args: []string{testServerID, "--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.PTRRecord{ - testPTR1, - testPTR2, - }, nil) - }, - }, - { - name: "list ptr records with error", - args: []string{testServerID}, - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - hostService := mocks.NewMockHostsService(mockCtrl) - collection := mocks.NewMockCollection[serverscom.PTRRecord](mockCtrl) - - hostService.EXPECT().DedicatedServerPTRRecords(gomock.Any()).Return(collection).AnyTimes() - collection.EXPECT().SetParam(gomock.Any(), gomock.Any()).Return(collection).AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostService - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - if tc.configureMock != nil { - tc.configureMock(collection) - } - testCmdContext := testutils.NewTestCmdContext(scClient) - cmd := NewCmd(testCmdContext) - - args := append([]string{"hosts", "ebm", "list-ptr"}, tc.args...) - if tc.output != "" { - args = append(args, "--output", tc.output) - } - builder := testutils.NewTestCommandBuilder(). - WithCommand(cmd). - WithArgs(args) - - c := builder.Build() - err := c.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 TestCreateEBMPTRCmd(t *testing.T) { - testCases := []struct { - name string - args []string - output string - expectedOutput []byte - configureMock func(*mocks.MockHostsService) - expectError bool - }{ - { - name: "create ds ptr", - args: []string{testServerID, "--ip", testPTR.IP, "--domain", testPTR.Domain, "--ttl", "300", "--priority", "10"}, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "get.json")), - configureMock: func(mock *mocks.MockHostsService) { - in := serverscom.PTRRecordCreateInput{ - IP: testPTR.IP, - Domain: testPTR.Domain, - TTL: &testPTR.TTL, - Priority: &testPTR.Priority, - } - mock.EXPECT(). - CreatePTRRecordForDedicatedServer(gomock.Any(), testServerID, in). - Return(&testPTR, nil) - }, - }, - { - name: "create ds ptr error", - args: []string{testServerID, "--ip", testPTR.IP, "--domain", testPTR.Domain}, - expectError: true, - configureMock: func(mock *mocks.MockHostsService) { - in := serverscom.PTRRecordCreateInput{ - IP: testPTR.IP, - Domain: testPTR.Domain, - } - mock.EXPECT(). - CreatePTRRecordForDedicatedServer(gomock.Any(), testServerID, in). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - hostService := mocks.NewMockHostsService(mockCtrl) - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostService - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - if tc.configureMock != nil { - tc.configureMock(hostService) - } - testCmdContext := testutils.NewTestCmdContext(scClient) - cmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "add-ptr"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - builder := testutils.NewTestCommandBuilder(). - WithCommand(cmd). - WithArgs(args) - - c := builder.Build() - err := c.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 TestDeleteEBMPTRCmd(t *testing.T) { - testCases := []struct { - name string - serverID string - ptrID string - expectError bool - }{ - { - name: "delete ds ptr", - serverID: testServerID, - ptrID: testPTRID, - }, - { - name: "delete ds ptr error", - serverID: testServerID, - ptrID: testPTRID, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - hostService := mocks.NewMockHostsService(mockCtrl) - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostService - - 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") - } - hostService.EXPECT(). - DeletePTRRecordForDedicatedServer(gomock.Any(), tc.serverID, tc.ptrID). - Return(err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - cmd := NewCmd(testCmdContext) - - args := []string{"hosts", "ebm", "delete-ptr", tc.serverID, "--ptr-id", tc.ptrID} - builder := testutils.NewTestCommandBuilder(). - WithCommand(cmd). - WithArgs(args) - - c := builder.Build() - err = c.Execute() - if tc.expectError { - g.Expect(err).To(HaveOccurred()) - } else { - g.Expect(err).To(BeNil()) - } - }) - } -} - -func TestListSBMPTRCmd(t *testing.T) { - testPTR1 := testPTR - testPTR2 := testPTR - testPTR1.ID += "1" - testPTR2.ID += "2" - testPTR2.Domain = "another.example.com" - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.PTRRecord]) - }{ - { - name: "list all ptr records", - output: "json", - args: []string{"-A", testServerID}, - expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.PTRRecord{ - testPTR1, - testPTR2, - }, nil) - }, - }, - { - name: "list ptr records", - output: "json", - args: []string{testServerID}, - expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.PTRRecord{ - testPTR1, - }, nil) - }, - }, - { - name: "list ptr records with template", - args: []string{testServerID, "--template", "{{range .}}ID: {{.ID}} PTR: {{.Domain}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.PTRRecord{ - testPTR1, - testPTR2, - }, nil) - }, - }, - { - name: "list ptr records with page-view", - args: []string{testServerID, "--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.PTRRecord{ - testPTR1, - testPTR2, - }, nil) - }, - }, - { - name: "list ptr records with error", - args: []string{testServerID}, - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - hostService := mocks.NewMockHostsService(mockCtrl) - collection := mocks.NewMockCollection[serverscom.PTRRecord](mockCtrl) - - hostService.EXPECT().SBMServerPTRRecords(gomock.Any()).Return(collection).AnyTimes() - collection.EXPECT().SetParam(gomock.Any(), gomock.Any()).Return(collection).AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostService - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - if tc.configureMock != nil { - tc.configureMock(collection) - } - testCmdContext := testutils.NewTestCmdContext(scClient) - cmd := NewCmd(testCmdContext) - - args := append([]string{"hosts", "sbm", "list-ptr"}, tc.args...) - if tc.output != "" { - args = append(args, "--output", tc.output) - } - builder := testutils.NewTestCommandBuilder(). - WithCommand(cmd). - WithArgs(args) - - c := builder.Build() - err := c.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 TestCreateSBMPTRCmd(t *testing.T) { - testCases := []struct { - name string - args []string - output string - expectedOutput []byte - configureMock func(*mocks.MockHostsService) - expectError bool - }{ - { - name: "create sbm ptr", - args: []string{testServerID, "--ip", testPTR.IP, "--domain", testPTR.Domain, "--ttl", "300", "--priority", "10"}, - output: "json", - expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "get.json")), - configureMock: func(mock *mocks.MockHostsService) { - in := serverscom.PTRRecordCreateInput{ - IP: testPTR.IP, - Domain: testPTR.Domain, - TTL: &testPTR.TTL, - Priority: &testPTR.Priority, - } - mock.EXPECT(). - CreatePTRRecordForSBMServer(gomock.Any(), testServerID, in). - Return(&testPTR, nil) - }, - }, - { - name: "create sbm ptr error", - args: []string{testServerID, "--ip", testPTR.IP, "--domain", testPTR.Domain}, - expectError: true, - configureMock: func(mock *mocks.MockHostsService) { - in := serverscom.PTRRecordCreateInput{ - IP: testPTR.IP, - Domain: testPTR.Domain, - } - mock.EXPECT(). - CreatePTRRecordForSBMServer(gomock.Any(), testServerID, in). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - hostService := mocks.NewMockHostsService(mockCtrl) - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostService - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - if tc.configureMock != nil { - tc.configureMock(hostService) - } - testCmdContext := testutils.NewTestCmdContext(scClient) - cmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "add-ptr"} - if len(tc.args) > 0 { - args = append(args, tc.args...) - } - if tc.output != "" { - args = append(args, "--output", tc.output) - } - builder := testutils.NewTestCommandBuilder(). - WithCommand(cmd). - WithArgs(args) - - c := builder.Build() - err := c.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 TestDeleteSBMPTRCmd(t *testing.T) { - testCases := []struct { - name string - serverID string - ptrID string - expectError bool - }{ - { - name: "delete ds ptr", - serverID: testServerID, - ptrID: testPTRID, - }, - { - name: "delete ds ptr error", - serverID: testServerID, - ptrID: testPTRID, - expectError: true, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - hostService := mocks.NewMockHostsService(mockCtrl) - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostService - - 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") - } - hostService.EXPECT(). - DeletePTRRecordForSBMServer(gomock.Any(), tc.serverID, tc.ptrID). - Return(err) - - testCmdContext := testutils.NewTestCmdContext(scClient) - cmd := NewCmd(testCmdContext) - - args := []string{"hosts", "sbm", "delete-ptr", tc.serverID, "--ptr-id", tc.ptrID} - builder := testutils.NewTestCommandBuilder(). - WithCommand(cmd). - WithArgs(args) - - c := builder.Build() - err = c.Execute() - if tc.expectError { - g.Expect(err).To(HaveOccurred()) - } else { - g.Expect(err).To(BeNil()) - } - }) - } -} diff --git a/cmd/entities/hosts/sbm.go b/cmd/entities/hosts/sbm.go new file mode 100644 index 0000000..9d3bf12 --- /dev/null +++ b/cmd/entities/hosts/sbm.go @@ -0,0 +1,35 @@ +package hosts + +import ( + "github.com/serverscom/srvctl/cmd/base" + "github.com/spf13/cobra" +) + +// NewSBMCmd builds the top-level "sbm" command. +func NewSBMCmd(cmdContext *base.CmdContext) *cobra.Command { + return newHostTypeCmd(cmdContext, HostTypeCmd{ + use: "sbm", + shortDesc: "Manage scalable baremetal servers", + entityName: "Scalable baremetal servers", + typeFlag: "sbm_server", + managers: HostManagers{ + getMgr: &SBMGetMgr{}, + powerMgr: &SBMPowerMgr{}, + reinstallMgr: &SBMReinstallMgr{}, + }, + extraCmds: []func(*base.CmdContext) *cobra.Command{ + newAddSBMCmd, + newUpdateSBMCmd, + newSBMReleaseCmd, + newListSBMCmd, + newListSBMNetworksCmd, + newGetSBMNetworkCmd, + newAddSBMNetworkCmd, + newDeleteSBMNetworkCmd, + newGetSBMNetworkUsageCmd, + newListSBMPTRCmd, + newCreateSBMPTRCmd, + newDeleteSBMPTRCmd, + }, + }) +} diff --git a/cmd/entities/hosts/sbm_test.go b/cmd/entities/hosts/sbm_test.go new file mode 100644 index 0000000..7a2a500 --- /dev/null +++ b/cmd/entities/hosts/sbm_test.go @@ -0,0 +1,1335 @@ +package hosts + +import ( + "errors" + "path/filepath" + "testing" + + . "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 ( + testSBM = serverscom.SBMServer{ + ID: testId, + RackID: testId, + Type: "sbm_server", + Title: "example.aa", + Status: "active", + LocationCode: testLocationCode, + PublicIPv4Address: &testPublicIP, + ConfigurationDetails: testConfigDetails, + Created: fixedTime, + Updated: fixedTime, + } +) + +func TestAddSBMCmd(t *testing.T) { + testCases := []struct { + name string + output string + args []string + configureMock func(*mocks.MockHostsService) + expectedOutput []byte + expectError bool + }{ + { + name: "create SBM server", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_sbm_resp.json")), + args: []string{"--input", filepath.Join(fixtureBasePath, "create_sbm_input.json")}, + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + CreateSBMServers(gomock.Any(), serverscom.SBMServerCreateInput{ + FlavorModelID: 1234, + LocationID: 5678, + Hosts: []serverscom.SBMServerHostInput{ + { + Hostname: "example.aa", + PublicIPv4NetworkID: new("PublicNetTest123"), + PrivateIPv4NetworkID: new("PrivateNetTest456"), + Labels: map[string]string{ + "environment": "testing", + }, + }, + }, + }). + Return([]serverscom.SBMServer{testSBM}, nil) + }, + }, + { + name: "create SBM server with params", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "create_sbm_resp.json")), + args: []string{ + "--location-id", "5678", + "--sbm-flavor-model-id", "1234", + "--operating-system-id", "9999", + "--ssh-key-fingerprint", "48:81:0c:43:99:12:71:5e:ba:fd:e7:2f:20:d7:95:e8", + "example.aa", + }, + configureMock: func(mock *mocks.MockHostsService) { + osID := int64(9999) + mock.EXPECT(). + CreateSBMServers(gomock.Any(), serverscom.SBMServerCreateInput{ + FlavorModelID: 1234, + LocationID: 5678, + OperatingSystemID: &osID, + SSHKeyFingerprints: []string{"48:81:0c:43:99:12:71:5e:ba:fd:e7:2f:20:d7:95:e8"}, + Hosts: []serverscom.SBMServerHostInput{ + { + Hostname: "example.aa", + }, + }, + }). + Return([]serverscom.SBMServer{testSBM}, nil) + }, + }, + { + name: "skeleton for SBM server input", + output: "json", + args: []string{"--skeleton"}, + expectedOutput: testutils.ReadFixture(filepath.Join(skeletonTemplatePath, "add_sbm.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + CreateSBMServers(gomock.Any(), gomock.Any()). + Times(0) + }, + }, + { + name: "create SBM server with error", + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + + if tc.configureMock != nil { + tc.configureMock(hostsServiceHandler) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "add"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + 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(MatchJSON(tc.expectedOutput)) + } + }) + } +} + +func TestGetSBMCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "get SBM server in default format", + id: testId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm.txt")), + }, + { + name: "get SBM server in JSON format", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm.json")), + }, + { + name: "get SBM server in YAML format", + id: testId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm.yaml")), + }, + { + name: "get SBM server with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + GetSBMServer(gomock.Any(), testId). + Return(&testSBM, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "get", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + 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 TestListSBMCmd(t *testing.T) { + testServer1 := testSBM + testServer1.Type = "sbm_server" + testServer2 := testServer1 + testServer2.ID = "testId2" + testServer2.Title = "example.bb" + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.SBMServer]) + }{ + { + name: "list all SBM servers", + output: "json", + args: []string{"-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.SBMServer]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.SBMServer{ + testServer1, + testServer2, + }, nil) + }, + }, + { + name: "list SBM servers", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.SBMServer]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.SBMServer{ + testServer1, + }, nil) + }, + }, + { + name: "list SBM servers with template", + args: []string{"--template", "{{range .}}Title: {{.Title}} Type: {{.Type}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.SBMServer]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.SBMServer{ + testServer1, + testServer2, + }, nil) + }, + }, + { + name: "list SBM servers with pageView", + args: []string{"--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.SBMServer]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.SBMServer{ + testServer1, + testServer2, + }, nil) + }, + }, + { + name: "list SBM servers with error", + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.SBMServer]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + collectionHandler := mocks.NewMockCollection[serverscom.SBMServer](mockCtrl) + + hostsServiceHandler.EXPECT(). + ListSBMServers(). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "list"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + 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 TestUpdateSBMCmd(t *testing.T) { + newServer := testSBM + newServer.Labels = map[string]string{"new": "label"} + + testCases := []struct { + name string + id string + output string + args []string + configureMock func(*mocks.MockHostsService) + expectedOutput []byte + expectError bool + }{ + { + name: "update SBM server node", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "update_sbm_resp.json")), + args: []string{"--label", "new=label"}, + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + UpdateSBMServer(gomock.Any(), testId, serverscom.SBMServerUpdateInput{ + Labels: map[string]string{"new": "label"}, + }). + Return(&newServer, nil) + }, + }, + { + name: "update SBM server with error", + id: testId, + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + UpdateSBMServer(gomock.Any(), testId, serverscom.SBMServerUpdateInput{ + Labels: make(map[string]string), + }). + Return(nil, errors.New("some error")) + }, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + + if tc.configureMock != nil { + tc.configureMock(hostsServiceHandler) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + sshCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "update", tc.id} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sshCmd). + 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 TestReleaseSBMCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "release SBM server", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm.json")), + }, + { + name: "release SBM server with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + ReleaseSBMServer(gomock.Any(), testId). + Return(&testSBM, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "release", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + 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 TestListSBMPowerFeedsCmd(t *testing.T) { + testPowerFeed1 := testPowerFeed + testPowerFeed2 := testPowerFeed1 + + testPowerFeed2.Name = "testPowerFeed2" + testPowerFeed2.Status = "off" + + testCases := []struct { + name string + id string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.HostPowerFeed]) + }{ + { + name: "get sbm power_feeds in default format", + id: testId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.txt")), + }, + { + name: "get sbm power_feeds", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.json")), + }, + { + name: "get sbm power_feeds in YAML format", + id: testId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_power_feeds.yaml")), + }, + { + name: "get sbm power_feeds with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + SBMServerPowerFeeds(gomock.Any(), testId). + Return([]serverscom.HostPowerFeed{testPowerFeed1, testPowerFeed2}, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "list-power-feeds", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + 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 TestGetSBMNetworkCmd(t *testing.T) { + testCases := []struct { + name string + id string + networkID string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "get SBM network in default format", + id: testId, + networkID: testNetworkId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network.txt")), + }, + { + name: "get SBM network in JSON format", + id: testId, + networkID: testNetworkId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network.json")), + }, + { + name: "get SBM network in YAML format", + id: testId, + networkID: testNetworkId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network.yaml")), + }, + { + name: "get SBM network with error", + id: testId, + networkID: testNetworkId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + GetSBMServerNetwork(gomock.Any(), tc.id, tc.networkID). + Return(&testNetwork, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{ + "sbm", "get-network", tc.id, + "--network-id", tc.networkID, + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + 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 TestListSBMNetworksCmd(t *testing.T) { + testNetwork1 := testNetwork + testNetwork1.ID = testNetworkId + testNetwork2 := testNetwork1 + testNetwork2.ID = "testNetId2" + netTitle2 := "Another Net" + testNetwork2.Title = &netTitle2 + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.Network]) + }{ + { + name: "list all SBM networks", + output: "json", + args: []string{"testServerId", "-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_networks_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + testNetwork2, + }, nil) + }, + }, + { + name: "list SBM networks", + output: "json", + args: []string{"testServerId"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_networks.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + }, nil) + }, + }, + { + name: "list SBM networks with template", + args: []string{"testServerId", "--template", "{{range .}}Network: {{.ID}} Title: {{.Title}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_networks_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + testNetwork2, + }, nil) + }, + }, + { + name: "list SBM networks with pageView", + args: []string{"testServerId", "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_sbm_networks_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{ + testNetwork1, + testNetwork2, + }, nil) + }, + }, + { + name: "list SBM networks with error", + args: []string{"testServerId"}, + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + collectionHandler := mocks.NewMockCollection[serverscom.Network](mockCtrl) + + hostsServiceHandler.EXPECT(). + SBMServerNetworks(gomock.Any()). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "list-networks"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + 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 TestAddSBMNetworkCmd(t *testing.T) { + expectedInputPrivate := serverscom.NetworkInput{ + DistributionMethod: "gateway", + Mask: 29, + } + + testCases := []struct { + name string + output string + args []string + configureMock func(*mocks.MockHostsService) + expectedOutput []byte + expectError bool + }{ + { + name: "add private SBM network", + output: "json", + args: []string{ + testId, + "--type", "private", + "--mask", "29", + "--distribution-method", "gateway", + }, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network.json")), + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + AddSBMServerPrivateIPv4Network(gomock.Any(), testId, expectedInputPrivate). + Return(&testNetwork, nil) + }, + }, + { + name: "add public SBM network is not supported", + args: []string{ + testId, + "--type", "public", + "--mask", "29", + }, + expectError: true, + }, + { + name: "add SBM network with unsupported mask", + args: []string{ + testId, + "--type", "private", + "--mask", "24", + }, + expectError: true, + }, + { + name: "add SBM network with error", + output: "json", + args: []string{ + testId, + "--type", "private", + "--mask", "29", + }, + expectError: true, + configureMock: func(mock *mocks.MockHostsService) { + mock.EXPECT(). + AddSBMServerPrivateIPv4Network(gomock.Any(), testId, expectedInputPrivate). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + + if tc.configureMock != nil { + tc.configureMock(hostsServiceHandler) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := append([]string{"sbm", "add-network"}, tc.args...) + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + 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 TestDeleteSBMNetworkCmd(t *testing.T) { + testCases := []struct { + name string + id string + networkID string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "delete SBM network", + id: testId, + networkID: testNetworkId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network.json")), + }, + { + name: "delete SBM network with error", + id: testId, + networkID: testNetworkId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + DeleteSBMServerNetwork(gomock.Any(), tc.id, tc.networkID). + Return(&testNetwork, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "delete-network", tc.id, "--network-id", tc.networkID} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + 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 TestGetSBMNetworkUsageCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "get SBM network usage in default format", + id: testId, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network_usage.txt")), + }, + { + name: "get SBM network usage in JSON format", + id: testId, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network_usage.json")), + }, + { + name: "get SBM network usage in YAML format", + id: testId, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get_sbm_network_usage.yaml")), + }, + { + name: "get SBM network usage with error", + id: testId, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + hostsServiceHandler := mocks.NewMockHostsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostsServiceHandler + + 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") + } + hostsServiceHandler.EXPECT(). + GetSBMServerNetworkUsage(gomock.Any(), tc.id). + Return(&testNetworkUsage, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "network-usage", tc.id} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + 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 TestListSBMPTRCmd(t *testing.T) { + testPTR1 := testPTR + testPTR2 := testPTR + testPTR1.ID += "1" + testPTR2.ID += "2" + testPTR2.Domain = "another.example.com" + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.PTRRecord]) + }{ + { + name: "list all ptr records", + output: "json", + args: []string{"-A", testServerID}, + expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.PTRRecord{ + testPTR1, + testPTR2, + }, nil) + }, + }, + { + name: "list ptr records", + output: "json", + args: []string{testServerID}, + expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.PTRRecord{ + testPTR1, + }, nil) + }, + }, + { + name: "list ptr records with template", + args: []string{testServerID, "--template", "{{range .}}ID: {{.ID}} PTR: {{.Domain}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.PTRRecord{ + testPTR1, + testPTR2, + }, nil) + }, + }, + { + name: "list ptr records with page-view", + args: []string{testServerID, "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.PTRRecord{ + testPTR1, + testPTR2, + }, nil) + }, + }, + { + name: "list ptr records with error", + args: []string{testServerID}, + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + hostService := mocks.NewMockHostsService(mockCtrl) + collection := mocks.NewMockCollection[serverscom.PTRRecord](mockCtrl) + + hostService.EXPECT().SBMServerPTRRecords(gomock.Any()).Return(collection).AnyTimes() + collection.EXPECT().SetParam(gomock.Any(), gomock.Any()).Return(collection).AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostService + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + if tc.configureMock != nil { + tc.configureMock(collection) + } + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := append([]string{"sbm", "list-ptr"}, tc.args...) + if tc.output != "" { + args = append(args, "--output", tc.output) + } + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + WithArgs(args) + + c := builder.Build() + err := c.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 TestCreateSBMPTRCmd(t *testing.T) { + testCases := []struct { + name string + args []string + output string + expectedOutput []byte + configureMock func(*mocks.MockHostsService) + expectError bool + }{ + { + name: "create sbm ptr", + args: []string{testServerID, "--ip", testPTR.IP, "--domain", testPTR.Domain, "--ttl", "300", "--priority", "10"}, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "get.json")), + configureMock: func(mock *mocks.MockHostsService) { + in := serverscom.PTRRecordCreateInput{ + IP: testPTR.IP, + Domain: testPTR.Domain, + TTL: &testPTR.TTL, + Priority: &testPTR.Priority, + } + mock.EXPECT(). + CreatePTRRecordForSBMServer(gomock.Any(), testServerID, in). + Return(&testPTR, nil) + }, + }, + { + name: "create sbm ptr error", + args: []string{testServerID, "--ip", testPTR.IP, "--domain", testPTR.Domain}, + expectError: true, + configureMock: func(mock *mocks.MockHostsService) { + in := serverscom.PTRRecordCreateInput{ + IP: testPTR.IP, + Domain: testPTR.Domain, + } + mock.EXPECT(). + CreatePTRRecordForSBMServer(gomock.Any(), testServerID, in). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + hostService := mocks.NewMockHostsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostService + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + if tc.configureMock != nil { + tc.configureMock(hostService) + } + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "add-ptr"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + WithArgs(args) + + c := builder.Build() + err := c.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 TestDeleteSBMPTRCmd(t *testing.T) { + testCases := []struct { + name string + serverID string + ptrID string + expectError bool + }{ + { + name: "delete ds ptr", + serverID: testServerID, + ptrID: testPTRID, + }, + { + name: "delete ds ptr error", + serverID: testServerID, + ptrID: testPTRID, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + hostService := mocks.NewMockHostsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.Hosts = hostService + + 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") + } + hostService.EXPECT(). + DeletePTRRecordForSBMServer(gomock.Any(), tc.serverID, tc.ptrID). + Return(err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + sbmCmd := NewSBMCmd(testCmdContext) + + args := []string{"sbm", "delete-ptr", tc.serverID, "--ptr-id", tc.ptrID} + builder := testutils.NewTestCommandBuilder(). + WithCommand(sbmCmd). + WithArgs(args) + + c := builder.Build() + err = c.Execute() + if tc.expectError { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).To(BeNil()) + } + }) + } +} diff --git a/cmd/entities/hosts/services_test.go b/cmd/entities/hosts/services_test.go deleted file mode 100644 index 8284192..0000000 --- a/cmd/entities/hosts/services_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package hosts - -import ( - "errors" - "path/filepath" - "testing" - - . "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 ( - servicesFixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "hosts", "services") - testDSService = serverscom.DedicatedServerService{ - ID: testId, - Name: "Test service", - Type: "server_base", - Currency: "USD", - StartedAt: fixedTime, - FinishedAt: fixedTime, - Total: 100.0, - UsageQuantity: 2.0, - Tax: 10.0, - Subtotal: 100.0, - DiscountRate: 5.0, - DateFrom: "2025-11-01", - DateTo: "2025-11-30", - } -) - -func TestListEBMServicesCmd(t *testing.T) { - testService1 := testDSService - testService2 := testDSService - testService2.ID += "2" - testService2.Name = "Test service 2" - testService2.Type = "uplink" - - testCases := []struct { - name string - output string - args []string - expectedOutput []byte - expectError bool - configureMock func(*mocks.MockCollection[serverscom.DedicatedServerService]) - }{ - { - name: "list all ds services", - output: "json", - args: []string{"-A", testServerID}, - expectedOutput: testutils.ReadFixture(filepath.Join(servicesFixtureBasePath, "list_all.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerService]) { - mock.EXPECT(). - Collect(gomock.Any()). - Return([]serverscom.DedicatedServerService{ - testService1, - testService2, - }, nil) - }, - }, - { - name: "list ds services", - output: "json", - args: []string{testServerID}, - expectedOutput: testutils.ReadFixture(filepath.Join(servicesFixtureBasePath, "list.json")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerService]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.DedicatedServerService{ - testService1, - }, nil) - }, - }, - { - name: "list ds services with template", - args: []string{testServerID, "--template", "{{range .}}ID: {{.ID}} Name: {{.Name}}\n{{end}}"}, - expectedOutput: testutils.ReadFixture(filepath.Join(servicesFixtureBasePath, "list_template.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerService]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.DedicatedServerService{ - testService1, - testService2, - }, nil) - }, - }, - { - name: "list ds services with page-view", - args: []string{testServerID, "--page-view"}, - expectedOutput: testutils.ReadFixture(filepath.Join(servicesFixtureBasePath, "list_pageview.txt")), - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerService]) { - mock.EXPECT(). - List(gomock.Any()). - Return([]serverscom.DedicatedServerService{ - testService1, - testService2, - }, nil) - }, - }, - { - name: "list ds services with error", - args: []string{testServerID}, - expectError: true, - configureMock: func(mock *mocks.MockCollection[serverscom.DedicatedServerService]) { - mock.EXPECT(). - List(gomock.Any()). - Return(nil, errors.New("some error")) - }, - }, - } - - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - hostService := mocks.NewMockHostsService(mockCtrl) - collection := mocks.NewMockCollection[serverscom.DedicatedServerService](mockCtrl) - - hostService.EXPECT().DedicatedServerServices(gomock.Any()).Return(collection).AnyTimes() - collection.EXPECT().SetParam(gomock.Any(), gomock.Any()).Return(collection).AnyTimes() - - scClient := serverscom.NewClientWithEndpoint("", "") - scClient.Hosts = hostService - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - g := NewWithT(t) - if tc.configureMock != nil { - tc.configureMock(collection) - } - testCmdContext := testutils.NewTestCmdContext(scClient) - cmd := NewCmd(testCmdContext) - - args := append([]string{"hosts", "ebm", "list-services"}, tc.args...) - if tc.output != "" { - args = append(args, "--output", tc.output) - } - builder := testutils.NewTestCommandBuilder(). - WithCommand(cmd). - WithArgs(args) - - c := builder.Build() - err := c.Execute() - if tc.expectError { - g.Expect(err).To(HaveOccurred()) - } else { - g.Expect(err).To(BeNil()) - g.Expect(builder.GetOutput()).To(BeEquivalentTo(string(tc.expectedOutput))) - } - }) - } -} diff --git a/cmd/root.go b/cmd/root.go index 709067c..99c7228 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -61,6 +61,9 @@ func NewRootCmd(version string) *cobra.Command { // resources comands cmd.AddCommand(sshkeys.NewCmd(cmdContext)) cmd.AddCommand(hosts.NewCmd(cmdContext)) + cmd.AddCommand(hosts.NewEBMCmd(cmdContext)) + cmd.AddCommand(hosts.NewKBMCmd(cmdContext)) + cmd.AddCommand(hosts.NewSBMCmd(cmdContext)) cmd.AddCommand(ssl.NewCmd(cmdContext)) cmd.AddCommand(loadbalancerclusters.NewCmd(cmdContext)) cmd.AddCommand(loadbalancers.NewCmd(cmdContext)) diff --git a/docs/index.md b/docs/index.md index 9233225..4a3135a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,29 +5,29 @@ | Command | Type | Description | |---------|------|-------------| | [srvctl hosts](srvctl-hosts/description.md) | Hosts | A host is a bare metal-based service that includes enterprise bare metal servers, Kubernetes bare metal nodes and scalable bare metal. (ebm, kbm, sbm) | -| [srvctl hosts ebm](srvctl-hosts-ebm/description.md) | Hosts / Enterprise Bare Metal | This command allows to manage enterprise bare metal servers. | -| [srvctl hosts ebm abort-release](srvctl-hosts-ebm-abort-release/description.md) | Hosts / Enterprise Bare Metal | This command cancels the scheduled release for the selected enterprise bare metal server. | -| [srvctl hosts ebm add](srvctl-hosts-ebm-add/description.md) | Hosts / Enterprise Bare Metal | A command to create an enterprise bare metal server. | -| [srvctl hosts ebm add-network](srvctl-hosts-ebm-add-network/description.md) | Hosts / Enterprise Bare Metal | This command adds a network to the selected server. | -| [srvctl hosts ebm add-ptr](srvctl-hosts-ebm-add-ptr/description.md) | Hosts / Enterprise Bare Metal | This command adds a PTR record to the selected server. | -| [srvctl hosts ebm delete-network](srvctl-hosts-ebm-delete-network/description.md) | Hosts / Enterprise Bare Metal | This command deletes a specified network for the selected server. | -| [srvctl hosts ebm delete-ptr](srvctl-hosts-ebm-delete-ptr/description.md) | Hosts / Enterprise Bare Metal | This command deletes a specified PTR record for the selected server. | -| [srvctl hosts ebm get](srvctl-hosts-ebm-get/description.md) | Hosts / Enterprise Bare Metal | This command provides information for the selected server. | -| [srvctl hosts ebm get-network](srvctl-hosts-ebm-get-network/description.md) | Hosts / Enterprise Bare Metal | This command provides information about a specified network of the selected server. | -| [srvctl hosts ebm get-oob-credentials](srvctl-hosts-ebm-get-oob-credentials/description.md) | Hosts / Enterprise Bare Metal | This command provides OOB credentials for the selected server. | -| [srvctl hosts ebm list-connections](srvctl-hosts-ebm-list-connections/description.md) | Hosts / Enterprise Bare Metal | This command lists connections for the selected enterprise bare metal server. | -| [srvctl hosts ebm list-drive-slots](srvctl-hosts-ebm-list-drive-slots/description.md) | Hosts / Enterprise Bare Metal | This command lists drive slots for the selected enterprise bare metal server. | -| [srvctl hosts ebm feature-set](srvctl-hosts-ebm-feature-set/description.md) | Hosts / Enterprise Bare Metal | This command activates or deactivates a feature on the selected enterprise bare metal server. | -| [srvctl hosts ebm list-features](srvctl-hosts-ebm-list-features/description.md) | Hosts / Enterprise Bare Metal | This command lists features for the selected enterprise bare metal server. | -| [srvctl hosts ebm list-networks](srvctl-hosts-ebm-list-networks/description.md) | Hosts / Enterprise Bare Metal | This command lists networks for the selected enterprise bare metal server. | -| [srvctl hosts ebm list-power-feeds](srvctl-hosts-ebm-list-power-feeds/description.md) | Hosts / Enterprise Bare Metal | This command lists power feeds for the selected enterprise bare metal server. | -| [srvctl hosts ebm list-ptr](srvctl-hosts-ebm-list-ptr/description.md) | Hosts / Enterprise Bare Metal | This command lists PTR records for the selected enterprise bare metal server. | -| [srvctl hosts ebm list-services](srvctl-hosts-ebm-list-services/description.md) | Hosts / Enterprise Bare Metal | This command lists services for the selected enterprise bare metal server. | -| [srvctl hosts ebm ls](srvctl-hosts-ebm-ls/description.md) | Hosts / Enterprise Bare Metal | This command lists enterprise bare metal servers of the account. | -| [srvctl hosts ebm power](srvctl-hosts-ebm-power/description.md) | Hosts / Enterprise Bare Metal | This command manages power operations for the selected enterprise bare metal server. | -| [srvctl hosts ebm reinstall](srvctl-hosts-ebm-reinstall/description.md) | Hosts / Enterprise Bare Metal | This command reinstalls an operating system for the selected enterprise bare metal server. | -| [srvctl hosts ebm schedule-release](srvctl-hosts-ebm-schedule-release/description.md) | Hosts / Enterprise Bare Metal | This command schedules release on YYYY-MM-DDTHH:MM:SS+HH:MM (dateTtime+time zone from UTC) for the selected enterprise bare metal server. | -| [srvctl hosts ebm update](srvctl-hosts-ebm-update/description.md) | Hosts / Enterprise Bare Metal | This command updates parameters and labels for the selected enterprise bare metal server. | +| [srvctl ebm](srvctl-ebm/description.md) | Enterprise Bare Metal | This command allows to manage enterprise bare metal servers. | +| [srvctl ebm abort-release](srvctl-ebm-abort-release/description.md) | Enterprise Bare Metal | This command cancels the scheduled release for the selected enterprise bare metal server. | +| [srvctl ebm add](srvctl-ebm-add/description.md) | Enterprise Bare Metal | A command to create an enterprise bare metal server. | +| [srvctl ebm add-network](srvctl-ebm-add-network/description.md) | Enterprise Bare Metal | This command adds a network to the selected server. | +| [srvctl ebm add-ptr](srvctl-ebm-add-ptr/description.md) | Enterprise Bare Metal | This command adds a PTR record to the selected server. | +| [srvctl ebm delete-network](srvctl-ebm-delete-network/description.md) | Enterprise Bare Metal | This command deletes a specified network for the selected server. | +| [srvctl ebm delete-ptr](srvctl-ebm-delete-ptr/description.md) | Enterprise Bare Metal | This command deletes a specified PTR record for the selected server. | +| [srvctl ebm get](srvctl-ebm-get/description.md) | Enterprise Bare Metal | This command provides information for the selected server. | +| [srvctl ebm get-network](srvctl-ebm-get-network/description.md) | Enterprise Bare Metal | This command provides information about a specified network of the selected server. | +| [srvctl ebm get-oob-credentials](srvctl-ebm-get-oob-credentials/description.md) | Enterprise Bare Metal | This command provides OOB credentials for the selected server. | +| [srvctl ebm list-connections](srvctl-ebm-list-connections/description.md) | Enterprise Bare Metal | This command lists connections for the selected enterprise bare metal server. | +| [srvctl ebm list-drive-slots](srvctl-ebm-list-drive-slots/description.md) | Enterprise Bare Metal | This command lists drive slots for the selected enterprise bare metal server. | +| [srvctl ebm feature-set](srvctl-ebm-feature-set/description.md) | Enterprise Bare Metal | This command activates or deactivates a feature on the selected enterprise bare metal server. | +| [srvctl ebm list-features](srvctl-ebm-list-features/description.md) | Enterprise Bare Metal | This command lists features for the selected enterprise bare metal server. | +| [srvctl ebm list-networks](srvctl-ebm-list-networks/description.md) | Enterprise Bare Metal | This command lists networks for the selected enterprise bare metal server. | +| [srvctl ebm list-power-feeds](srvctl-ebm-list-power-feeds/description.md) | Enterprise Bare Metal | This command lists power feeds for the selected enterprise bare metal server. | +| [srvctl ebm list-ptr](srvctl-ebm-list-ptr/description.md) | Enterprise Bare Metal | This command lists PTR records for the selected enterprise bare metal server. | +| [srvctl ebm list-services](srvctl-ebm-list-services/description.md) | Enterprise Bare Metal | This command lists services for the selected enterprise bare metal server. | +| [srvctl ebm ls](srvctl-ebm-ls/description.md) | Enterprise Bare Metal | This command lists enterprise bare metal servers of the account. | +| [srvctl ebm power](srvctl-ebm-power/description.md) | Enterprise Bare Metal | This command manages power operations for the selected enterprise bare metal server. | +| [srvctl ebm reinstall](srvctl-ebm-reinstall/description.md) | Enterprise Bare Metal | This command reinstalls an operating system for the selected enterprise bare metal server. | +| [srvctl ebm schedule-release](srvctl-ebm-schedule-release/description.md) | Enterprise Bare Metal | This command schedules release on YYYY-MM-DDTHH:MM:SS+HH:MM (dateTtime+time zone from UTC) for the selected enterprise bare metal server. | +| [srvctl ebm update](srvctl-ebm-update/description.md) | Enterprise Bare Metal | This command updates parameters and labels for the selected enterprise bare metal server. | | [srvctl l2-segments](srvctl-l2-segments/description.md) | L2 Segments | This command allows to manage L2 segments. | | [srvctl l2-segments list](srvctl-l2-segments-list/description.md) | L2 Segments | This command lists L2 segments of the account. | | [srvctl l2-segments list-groups](srvctl-l2-segments-list-groups/description.md) | L2 Segments | This command lists L2 segment location groups. | diff --git a/docs/srvctl-hosts-ebm-abort-release/description.md b/docs/srvctl-ebm-abort-release/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-abort-release/description.md rename to docs/srvctl-ebm-abort-release/description.md diff --git a/docs/srvctl-hosts-ebm-abort-release/examples.md b/docs/srvctl-ebm-abort-release/examples.md similarity index 68% rename from docs/srvctl-hosts-ebm-abort-release/examples.md rename to docs/srvctl-ebm-abort-release/examples.md index 875aa2e..9f501da 100644 --- a/docs/srvctl-hosts-ebm-abort-release/examples.md +++ b/docs/srvctl-ebm-abort-release/examples.md @@ -1,5 +1,5 @@ A comand to cancel the scheduled release for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm abort-release ex4mp1eID +srvctl ebm abort-release ex4mp1eID ``` diff --git a/docs/srvctl-hosts-ebm-add-network/description.md b/docs/srvctl-ebm-add-network/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-add-network/description.md rename to docs/srvctl-ebm-add-network/description.md diff --git a/docs/srvctl-ebm-add-network/examples.md b/docs/srvctl-ebm-add-network/examples.md new file mode 100644 index 0000000..2365497 --- /dev/null +++ b/docs/srvctl-ebm-add-network/examples.md @@ -0,0 +1,5 @@ +A command to add a network to the server with the "ex4mp1eID" ID. + +``` +srvctl ebm add-network ex4mp1eID --distribution-method route --mask 32 --type private +``` diff --git a/docs/srvctl-hosts-ebm-add-ptr/description.md b/docs/srvctl-ebm-add-ptr/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-add-ptr/description.md rename to docs/srvctl-ebm-add-ptr/description.md diff --git a/docs/srvctl-ebm-add-ptr/examples.md b/docs/srvctl-ebm-add-ptr/examples.md new file mode 100644 index 0000000..cef1c86 --- /dev/null +++ b/docs/srvctl-ebm-add-ptr/examples.md @@ -0,0 +1,5 @@ +A commands to add a PTR record for the server with the "ex4mp1eID" ID. + +``` +srvctl ebm add-ptr ex4mp1eID --domain example.com --ip X.X.X.X --priority 1 --ttl 360 +``` diff --git a/docs/srvctl-hosts-ebm-add/description.md b/docs/srvctl-ebm-add/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-add/description.md rename to docs/srvctl-ebm-add/description.md diff --git a/docs/srvctl-hosts-ebm-add/examples.md b/docs/srvctl-ebm-add/examples.md similarity index 96% rename from docs/srvctl-hosts-ebm-add/examples.md rename to docs/srvctl-ebm-add/examples.md index e06d19f..d0e470a 100644 --- a/docs/srvctl-hosts-ebm-add/examples.md +++ b/docs/srvctl-ebm-add/examples.md @@ -2,7 +2,7 @@ An example of a command for a file in the same directory with srvctl: ``` -srvctl hosts ebm add --input +srvctl ebm add --input ``` An example of the file's content: @@ -78,7 +78,7 @@ An example of the file's content: This is an example of a command to create an enterprise bare metal server via flags: ``` -srvctl hosts ebm add \ +srvctl ebm add \ --location-id 2 \ --server-model-id 10515 \ --ram-size 32 \ @@ -101,7 +101,7 @@ srvctl hosts ebm add \ Pass an inline iPXE script via the `--ipxe-config` flag: ``` -srvctl hosts ebm add \ +srvctl ebm add \ --location-id 2 \ --server-model-id 10515 \ --ram-size 32 \ diff --git a/docs/srvctl-hosts-ebm-delete-network/description.md b/docs/srvctl-ebm-delete-network/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-delete-network/description.md rename to docs/srvctl-ebm-delete-network/description.md diff --git a/docs/srvctl-hosts-ebm-delete-network/examples.md b/docs/srvctl-ebm-delete-network/examples.md similarity index 50% rename from docs/srvctl-hosts-ebm-delete-network/examples.md rename to docs/srvctl-ebm-delete-network/examples.md index 4db72e6..c18374c 100644 --- a/docs/srvctl-hosts-ebm-delete-network/examples.md +++ b/docs/srvctl-ebm-delete-network/examples.md @@ -1,5 +1,5 @@ A command that deletes a network for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm delete-network ex4mp1eID_server --network-id ex4mp1eID_network +srvctl ebm delete-network ex4mp1eID_server --network-id ex4mp1eID_network ``` diff --git a/docs/srvctl-hosts-ebm-delete-ptr/description.md b/docs/srvctl-ebm-delete-ptr/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-delete-ptr/description.md rename to docs/srvctl-ebm-delete-ptr/description.md diff --git a/docs/srvctl-hosts-ebm-delete-ptr/examples.md b/docs/srvctl-ebm-delete-ptr/examples.md similarity index 54% rename from docs/srvctl-hosts-ebm-delete-ptr/examples.md rename to docs/srvctl-ebm-delete-ptr/examples.md index fac2dc5..8a52724 100644 --- a/docs/srvctl-hosts-ebm-delete-ptr/examples.md +++ b/docs/srvctl-ebm-delete-ptr/examples.md @@ -1,5 +1,5 @@ A command to delete a PTR record for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm delete-ptr ex4mp1eID_server --ptr-id ex4mp1eID_ptr +srvctl ebm delete-ptr ex4mp1eID_server --ptr-id ex4mp1eID_ptr ``` diff --git a/docs/srvctl-hosts-ebm-feature-set/description.md b/docs/srvctl-ebm-feature-set/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-feature-set/description.md rename to docs/srvctl-ebm-feature-set/description.md diff --git a/docs/srvctl-hosts-ebm-feature-set/examples.md b/docs/srvctl-ebm-feature-set/examples.md similarity index 64% rename from docs/srvctl-hosts-ebm-feature-set/examples.md rename to docs/srvctl-ebm-feature-set/examples.md index 2f461be..f449761 100644 --- a/docs/srvctl-hosts-ebm-feature-set/examples.md +++ b/docs/srvctl-ebm-feature-set/examples.md @@ -1,19 +1,19 @@ A command to activate disaggregated public ports on the server with the "ex4mp1eID" ID: ``` -srvctl hosts ebm feature-set ex4mp1eID --feature disaggregated_public_ports --command activate +srvctl ebm feature-set ex4mp1eID --feature disaggregated_public_ports --command activate ``` A command to deactivate disaggregated public ports on the server with the "ex4mp1eID" ID: ``` -srvctl hosts ebm feature-set ex4mp1eID --feature disaggregated_public_ports --command deactivate +srvctl ebm feature-set ex4mp1eID --feature disaggregated_public_ports --command deactivate ``` A command to activate rescue mode with password and SSH key authentication: ``` -srvctl hosts ebm feature-set ex4mp1eID \ +srvctl ebm feature-set ex4mp1eID \ --feature host_rescue_mode \ --command activate \ --auth-method password \ @@ -24,7 +24,7 @@ srvctl hosts ebm feature-set ex4mp1eID \ A command to activate private iPXE boot with a custom script: ``` -srvctl hosts ebm feature-set ex4mp1eID \ +srvctl ebm feature-set ex4mp1eID \ --feature private_ipxe_boot \ --command activate \ --ipxe-config "#!ipxe\nchain http://boot.example.com/script.ipxe" @@ -33,5 +33,5 @@ srvctl hosts ebm feature-set ex4mp1eID \ A command to deactivate rescue mode: ``` -srvctl hosts ebm feature-set ex4mp1eID --feature host_rescue_mode --command deactivate +srvctl ebm feature-set ex4mp1eID --feature host_rescue_mode --command deactivate ``` \ No newline at end of file diff --git a/docs/srvctl-hosts-ebm-get-network/description.md b/docs/srvctl-ebm-get-network/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-get-network/description.md rename to docs/srvctl-ebm-get-network/description.md diff --git a/docs/srvctl-hosts-ebm-get-network/examples.md b/docs/srvctl-ebm-get-network/examples.md similarity index 54% rename from docs/srvctl-hosts-ebm-get-network/examples.md rename to docs/srvctl-ebm-get-network/examples.md index 97e8b71..6df87d4 100644 --- a/docs/srvctl-hosts-ebm-get-network/examples.md +++ b/docs/srvctl-ebm-get-network/examples.md @@ -1,5 +1,5 @@ A command to get information about a network for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm get-network ex4mp1eID_server --network-id ex4mp1eID_network +srvctl ebm get-network ex4mp1eID_server --network-id ex4mp1eID_network ``` diff --git a/docs/srvctl-hosts-ebm-get-oob-credentials/description.md b/docs/srvctl-ebm-get-oob-credentials/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-get-oob-credentials/description.md rename to docs/srvctl-ebm-get-oob-credentials/description.md diff --git a/docs/srvctl-hosts-ebm-get-oob-credentials/examples.md b/docs/srvctl-ebm-get-oob-credentials/examples.md similarity index 52% rename from docs/srvctl-hosts-ebm-get-oob-credentials/examples.md rename to docs/srvctl-ebm-get-oob-credentials/examples.md index ae36a75..377df0d 100644 --- a/docs/srvctl-hosts-ebm-get-oob-credentials/examples.md +++ b/docs/srvctl-ebm-get-oob-credentials/examples.md @@ -1,5 +1,5 @@ A command to get OOB credentials for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm get-oob-credentials ex4mp1eID --fingerprint GPGKEYEX4MP1E +srvctl ebm get-oob-credentials ex4mp1eID --fingerprint GPGKEYEX4MP1E ``` diff --git a/docs/srvctl-hosts-ebm-get/description.md b/docs/srvctl-ebm-get/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-get/description.md rename to docs/srvctl-ebm-get/description.md diff --git a/docs/srvctl-hosts-ebm-get/examples.md b/docs/srvctl-ebm-get/examples.md similarity index 71% rename from docs/srvctl-hosts-ebm-get/examples.md rename to docs/srvctl-ebm-get/examples.md index 08ea485..0cbe1fd 100644 --- a/docs/srvctl-hosts-ebm-get/examples.md +++ b/docs/srvctl-ebm-get/examples.md @@ -1,4 +1,4 @@ A command to get information for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm get ex4mp1eID +srvctl ebm get ex4mp1eID ``` diff --git a/docs/srvctl-hosts-ebm-list-connections/description.md b/docs/srvctl-ebm-list-connections/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-list-connections/description.md rename to docs/srvctl-ebm-list-connections/description.md diff --git a/docs/srvctl-hosts-ebm-list-connections/examples.md b/docs/srvctl-ebm-list-connections/examples.md similarity index 64% rename from docs/srvctl-hosts-ebm-list-connections/examples.md rename to docs/srvctl-ebm-list-connections/examples.md index 697d2bf..1f02f9b 100644 --- a/docs/srvctl-hosts-ebm-list-connections/examples.md +++ b/docs/srvctl-ebm-list-connections/examples.md @@ -1,5 +1,5 @@ A command to list connections for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm list-connections ex4mp1eID +srvctl ebm list-connections ex4mp1eID ``` diff --git a/docs/srvctl-hosts-ebm-list-drive-slots/description.md b/docs/srvctl-ebm-list-drive-slots/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-list-drive-slots/description.md rename to docs/srvctl-ebm-list-drive-slots/description.md diff --git a/docs/srvctl-hosts-ebm-list-drive-slots/examples.md b/docs/srvctl-ebm-list-drive-slots/examples.md similarity index 64% rename from docs/srvctl-hosts-ebm-list-drive-slots/examples.md rename to docs/srvctl-ebm-list-drive-slots/examples.md index 39447fb..621c310 100644 --- a/docs/srvctl-hosts-ebm-list-drive-slots/examples.md +++ b/docs/srvctl-ebm-list-drive-slots/examples.md @@ -1,5 +1,5 @@ A command to list drive slots for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm list-drive-slots ex4mp1eID +srvctl ebm list-drive-slots ex4mp1eID ``` diff --git a/docs/srvctl-hosts-ebm-list-features/description.md b/docs/srvctl-ebm-list-features/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-list-features/description.md rename to docs/srvctl-ebm-list-features/description.md diff --git a/docs/srvctl-hosts-ebm-list-features/examples.md b/docs/srvctl-ebm-list-features/examples.md similarity index 64% rename from docs/srvctl-hosts-ebm-list-features/examples.md rename to docs/srvctl-ebm-list-features/examples.md index d2d6e1e..6e6be56 100644 --- a/docs/srvctl-hosts-ebm-list-features/examples.md +++ b/docs/srvctl-ebm-list-features/examples.md @@ -1,5 +1,5 @@ A command to list features for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm list-features ex4mp1eID +srvctl ebm list-features ex4mp1eID ``` diff --git a/docs/srvctl-hosts-ebm-list-networks/description.md b/docs/srvctl-ebm-list-networks/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-list-networks/description.md rename to docs/srvctl-ebm-list-networks/description.md diff --git a/docs/srvctl-hosts-ebm-list-networks/examples.md b/docs/srvctl-ebm-list-networks/examples.md similarity index 64% rename from docs/srvctl-hosts-ebm-list-networks/examples.md rename to docs/srvctl-ebm-list-networks/examples.md index b008c3d..a038027 100644 --- a/docs/srvctl-hosts-ebm-list-networks/examples.md +++ b/docs/srvctl-ebm-list-networks/examples.md @@ -1,5 +1,5 @@ A command to list networks for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm list-networks ex4mp1eID +srvctl ebm list-networks ex4mp1eID ``` diff --git a/docs/srvctl-hosts-ebm-list-power-feeds/description.md b/docs/srvctl-ebm-list-power-feeds/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-list-power-feeds/description.md rename to docs/srvctl-ebm-list-power-feeds/description.md diff --git a/docs/srvctl-hosts-ebm-list-power-feeds/examples.md b/docs/srvctl-ebm-list-power-feeds/examples.md similarity index 64% rename from docs/srvctl-hosts-ebm-list-power-feeds/examples.md rename to docs/srvctl-ebm-list-power-feeds/examples.md index cba5b98..49dbd89 100644 --- a/docs/srvctl-hosts-ebm-list-power-feeds/examples.md +++ b/docs/srvctl-ebm-list-power-feeds/examples.md @@ -1,5 +1,5 @@ A command to list power feeds for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm list-power-feeds ex4mp1eID +srvctl ebm list-power-feeds ex4mp1eID ``` diff --git a/docs/srvctl-hosts-ebm-list-ptr/description.md b/docs/srvctl-ebm-list-ptr/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-list-ptr/description.md rename to docs/srvctl-ebm-list-ptr/description.md diff --git a/docs/srvctl-hosts-ebm-list-ptr/examples.md b/docs/srvctl-ebm-list-ptr/examples.md similarity index 68% rename from docs/srvctl-hosts-ebm-list-ptr/examples.md rename to docs/srvctl-ebm-list-ptr/examples.md index 1240758..3fe7096 100644 --- a/docs/srvctl-hosts-ebm-list-ptr/examples.md +++ b/docs/srvctl-ebm-list-ptr/examples.md @@ -1,5 +1,5 @@ A command to list PTR records for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm list-ptr ex4mp1eID +srvctl ebm list-ptr ex4mp1eID ``` diff --git a/docs/srvctl-hosts-ebm-list-services/description.md b/docs/srvctl-ebm-list-services/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-list-services/description.md rename to docs/srvctl-ebm-list-services/description.md diff --git a/docs/srvctl-hosts-ebm-list-services/examples.md b/docs/srvctl-ebm-list-services/examples.md similarity index 64% rename from docs/srvctl-hosts-ebm-list-services/examples.md rename to docs/srvctl-ebm-list-services/examples.md index b09016e..5a3c89b 100644 --- a/docs/srvctl-hosts-ebm-list-services/examples.md +++ b/docs/srvctl-ebm-list-services/examples.md @@ -1,5 +1,5 @@ A command to list services for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm list-services ex4mp1eID +srvctl ebm list-services ex4mp1eID ``` diff --git a/docs/srvctl-hosts-ebm-ls/description.md b/docs/srvctl-ebm-ls/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-ls/description.md rename to docs/srvctl-ebm-ls/description.md diff --git a/docs/srvctl-hosts-ebm-ls/examples.md b/docs/srvctl-ebm-ls/examples.md similarity index 72% rename from docs/srvctl-hosts-ebm-ls/examples.md rename to docs/srvctl-ebm-ls/examples.md index 0c74630..7a89dd3 100644 --- a/docs/srvctl-hosts-ebm-ls/examples.md +++ b/docs/srvctl-ebm-ls/examples.md @@ -1,5 +1,5 @@ A command to list all enterprise bare metal servers for the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm list ex4mp1eID --all +srvctl ebm list ex4mp1eID --all ``` diff --git a/docs/srvctl-hosts-ebm-power/description.md b/docs/srvctl-ebm-power/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-power/description.md rename to docs/srvctl-ebm-power/description.md diff --git a/docs/srvctl-hosts-ebm-power/examples.md b/docs/srvctl-ebm-power/examples.md similarity index 59% rename from docs/srvctl-hosts-ebm-power/examples.md rename to docs/srvctl-ebm-power/examples.md index 3fcae4c..0823838 100644 --- a/docs/srvctl-hosts-ebm-power/examples.md +++ b/docs/srvctl-ebm-power/examples.md @@ -1,5 +1,5 @@ A command to switch off the server with the "ex4mp1eID" ID. ``` -srvctl hosts ebm power ex4mp1eID --command off +srvctl ebm power ex4mp1eID --command off ``` diff --git a/docs/srvctl-hosts-ebm-reinstall/description.md b/docs/srvctl-ebm-reinstall/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-reinstall/description.md rename to docs/srvctl-ebm-reinstall/description.md diff --git a/docs/srvctl-hosts-ebm-reinstall/examples.md b/docs/srvctl-ebm-reinstall/examples.md similarity index 94% rename from docs/srvctl-hosts-ebm-reinstall/examples.md rename to docs/srvctl-ebm-reinstall/examples.md index 49e48f1..82e35ff 100644 --- a/docs/srvctl-hosts-ebm-reinstall/examples.md +++ b/docs/srvctl-ebm-reinstall/examples.md @@ -1,7 +1,7 @@ An example of a command for the server with the "ex4mp1eID" ID to reinstall OS using a file in the same directory with srvctl: ``` -srvctl hosts ebm reinstall ex4mp1eID --input +srvctl ebm reinstall ex4mp1eID --input ``` An example of the file's content: diff --git a/docs/srvctl-hosts-ebm-schedule-release/description.md b/docs/srvctl-ebm-schedule-release/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-schedule-release/description.md rename to docs/srvctl-ebm-schedule-release/description.md diff --git a/docs/srvctl-ebm-schedule-release/examples.md b/docs/srvctl-ebm-schedule-release/examples.md new file mode 100644 index 0000000..419bda2 --- /dev/null +++ b/docs/srvctl-ebm-schedule-release/examples.md @@ -0,0 +1,5 @@ +A command to schedule release for the server with the "ex4mp1eID" ID. + +``` +srvctl ebm schedule-release ex4mp1eID --release-after 2022-05-24T12:48:00+03:00 +``` diff --git a/docs/srvctl-hosts-ebm-update/description.md b/docs/srvctl-ebm-update/description.md similarity index 100% rename from docs/srvctl-hosts-ebm-update/description.md rename to docs/srvctl-ebm-update/description.md diff --git a/docs/srvctl-ebm-update/examples.md b/docs/srvctl-ebm-update/examples.md new file mode 100644 index 0000000..75db487 --- /dev/null +++ b/docs/srvctl-ebm-update/examples.md @@ -0,0 +1,5 @@ +A command to assign labels for the server with the "ex4mp1eID" ID. + +``` +srvctl ebm update ex4mp1eID --label environment=production --label team=frontend +``` diff --git a/docs/srvctl-hosts-ebm/description.md b/docs/srvctl-ebm/description.md similarity index 100% rename from docs/srvctl-hosts-ebm/description.md rename to docs/srvctl-ebm/description.md diff --git a/docs/srvctl-hosts-ebm/examples.md b/docs/srvctl-ebm/examples.md similarity index 73% rename from docs/srvctl-hosts-ebm/examples.md rename to docs/srvctl-ebm/examples.md index dda9671..e07f611 100644 --- a/docs/srvctl-hosts-ebm/examples.md +++ b/docs/srvctl-ebm/examples.md @@ -1,5 +1,5 @@ A command to list all enterprise bare metal servers for the account: ``` -srvctl hosts ebm list --all +srvctl ebm list --all ``` diff --git a/docs/srvctl-hosts-ebm-add-network/examples.md b/docs/srvctl-hosts-ebm-add-network/examples.md deleted file mode 100644 index 4cefaef..0000000 --- a/docs/srvctl-hosts-ebm-add-network/examples.md +++ /dev/null @@ -1,5 +0,0 @@ -A command to add a network to the server with the "ex4mp1eID" ID. - -``` -srvctl hosts ebm add-network ex4mp1eID --distribution-method route --mask 32 --type private -``` diff --git a/docs/srvctl-hosts-ebm-add-ptr/examples.md b/docs/srvctl-hosts-ebm-add-ptr/examples.md deleted file mode 100644 index 760edae..0000000 --- a/docs/srvctl-hosts-ebm-add-ptr/examples.md +++ /dev/null @@ -1,5 +0,0 @@ -A commands to add a PTR record for the server with the "ex4mp1eID" ID. - -``` -srvctl hosts ebm add-ptr ex4mp1eID --domain example.com --ip X.X.X.X --priority 1 --ttl 360 -``` diff --git a/docs/srvctl-hosts-ebm-schedule-release/examples.md b/docs/srvctl-hosts-ebm-schedule-release/examples.md deleted file mode 100644 index 9ea2c9e..0000000 --- a/docs/srvctl-hosts-ebm-schedule-release/examples.md +++ /dev/null @@ -1,5 +0,0 @@ -A command to schedule release for the server with the "ex4mp1eID" ID. - -``` -srvctl hosts ebm schedule-release ex4mp1eID --release-after 2022-05-24T12:48:00+03:00 -``` diff --git a/docs/srvctl-hosts-ebm-update/examples.md b/docs/srvctl-hosts-ebm-update/examples.md deleted file mode 100644 index 4db994c..0000000 --- a/docs/srvctl-hosts-ebm-update/examples.md +++ /dev/null @@ -1,5 +0,0 @@ -A command to assign labels for the server with the "ex4mp1eID" ID. - -``` -srvctl hosts ebm update ex4mp1eID --label environment=production --label team=frontend -``` diff --git a/docs/srvctl-hosts/description.md b/docs/srvctl-hosts/description.md index de84fde..1eaa2cf 100644 --- a/docs/srvctl-hosts/description.md +++ b/docs/srvctl-hosts/description.md @@ -1 +1 @@ -A host is a bare metal-based service that includes enterprise bare metal, kubernetes bare metal nodes and scalable bare metal. It has subcommands for each specific service. +A host is a bare metal-based service that includes enterprise bare metal, kubernetes bare metal nodes and scalable bare metal. Use `srvctl hosts list` to list hosts of all types; manage a specific type with the dedicated `ebm`, `kbm` and `sbm` commands.