diff --git a/Makefile b/Makefile index 8c130f8..92e7787 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ generate: deps mockgen --destination ./internal/mocks/account_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/accounts.go mockgen --destination ./internal/mocks/locations_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/locations.go mockgen --destination ./internal/mocks/kubernetes_clusters_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/kubernetes_clusters.go + mockgen --destination ./internal/mocks/l2_segment_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/l2_segments.go sed -i '' 's|github.com/serverscom/srvctl/vendor/github.com/serverscom/serverscom-go-client/pkg|github.com/serverscom/serverscom-go-client/pkg|g' \ ./internal/mocks/ssh_service.go \ ./internal/mocks/hosts_service.go \ @@ -27,5 +28,5 @@ generate: deps ./internal/mocks/account_service.go \ ./internal/mocks/collection.go \ ./internal/mocks/locations_service.go \ - ./internal/mocks/kubernetes_clusters_service.go - + ./internal/mocks/kubernetes_clusters_service.go \ + ./internal/mocks/l2_segment_service.go \ No newline at end of file diff --git a/cmd/base/list_options.go b/cmd/base/list_options.go index cbd13ef..b486631 100644 --- a/cmd/base/list_options.go +++ b/cmd/base/list_options.go @@ -401,3 +401,18 @@ func (o *SBMFlavorsShowAllOption[T]) ApplyToCollection(collection serverscom.Col collection.SetParam("show_all", "true") } } + +type L2SegmentGroupTypeOption[T any] struct { + group string +} + +func (o *L2SegmentGroupTypeOption[T]) AddFlags(cmd *cobra.Command) { + cmd.Flags().StringVar(&o.group, "group-type", "", + "Filter l2 location groups by type (public, private)") +} + +func (o *L2SegmentGroupTypeOption[T]) ApplyToCollection(collection serverscom.Collection[T]) { + if o.group != "" { + collection.SetParam("group_type", o.group) + } +} diff --git a/cmd/entities/hosts/hosts.go b/cmd/entities/hosts/hosts.go index eb5a0f5..249f888 100644 --- a/cmd/entities/hosts/hosts.go +++ b/cmd/entities/hosts/hosts.go @@ -164,5 +164,11 @@ func getHostsEntities() (map[string]entities.EntityInterface, error) { } result["sbm"] = sbmEntity + hostNetworkEntity, err := entities.Registry.GetEntityFromValue(serverscom.Network{}) + if err != nil { + return nil, err + } + result["list-networks"] = hostNetworkEntity + return result, nil } diff --git a/cmd/entities/l2_segments/add.go b/cmd/entities/l2_segments/add.go new file mode 100644 index 0000000..e31b739 --- /dev/null +++ b/cmd/entities/l2_segments/add.go @@ -0,0 +1,52 @@ +package l2segments + +import ( + "log" + + serverscom "github.com/serverscom/serverscom-go-client/pkg" + "github.com/serverscom/srvctl/cmd/base" + "github.com/spf13/cobra" +) + +func newAddCmd(cmdContext *base.CmdContext) *cobra.Command { + var path string + + cmd := &cobra.Command{ + Use: "add --input ", + Short: "Add a new L2 segment", + Long: "Add a new L2 segment", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + manager := cmdContext.GetManager() + + ctx, cancel := base.SetupContext(cmd, manager) + defer cancel() + + base.SetupProxy(cmd, manager) + + input := &serverscom.L2SegmentCreateInput{} + if err := base.ReadInputJSON(path, cmd.InOrStdin(), input); err != nil { + return err + } + + scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient() + l2Segment, err := scClient.L2Segments.Create(ctx, *input) + if err != nil { + return err + } + + if l2Segment != nil { + formatter := cmdContext.GetOrCreateFormatter(cmd) + return formatter.Format(l2Segment) + } + return nil + }, + } + + cmd.Flags().StringVarP(&path, "input", "i", "", "path to input file or '-' to read from stdin") + if err := cmd.MarkFlagRequired("input"); err != nil { + log.Fatal(err) + } + + return cmd +} diff --git a/cmd/entities/l2_segments/delete.go b/cmd/entities/l2_segments/delete.go new file mode 100644 index 0000000..d7f7d4d --- /dev/null +++ b/cmd/entities/l2_segments/delete.go @@ -0,0 +1,30 @@ +package l2segments + +import ( + "github.com/serverscom/srvctl/cmd/base" + "github.com/spf13/cobra" +) + +func newDeleteCmd(cmdContext *base.CmdContext) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete ", + Short: "Delete an L2 segment", + Long: "Delete an L2 segment by id", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + manager := cmdContext.GetManager() + + ctx, cancel := base.SetupContext(cmd, manager) + defer cancel() + + base.SetupProxy(cmd, manager) + + scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient() + + l2SegmentID := args[0] + return scClient.L2Segments.Delete(ctx, l2SegmentID) + }, + } + + return cmd +} diff --git a/cmd/entities/l2_segments/get.go b/cmd/entities/l2_segments/get.go new file mode 100644 index 0000000..7660d15 --- /dev/null +++ b/cmd/entities/l2_segments/get.go @@ -0,0 +1,40 @@ +package l2segments + +import ( + "github.com/serverscom/srvctl/cmd/base" + "github.com/spf13/cobra" +) + +func newGetCmd(cmdContext *base.CmdContext) *cobra.Command { + cmd := &cobra.Command{ + Use: "get ", + Short: "Get an L2 segment", + Long: "Get an L2 segment by id", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + manager := cmdContext.GetManager() + + ctx, cancel := base.SetupContext(cmd, manager) + defer cancel() + + base.SetupProxy(cmd, manager) + + scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient() + + l2SegmentID := args[0] + + model, err := scClient.L2Segments.Get(ctx, l2SegmentID) + if err != nil { + return err + } + + if model != nil { + formatter := cmdContext.GetOrCreateFormatter(cmd) + return formatter.Format(model) + } + return nil + }, + } + + return cmd +} diff --git a/cmd/entities/l2_segments/l2_segments.go b/cmd/entities/l2_segments/l2_segments.go new file mode 100644 index 0000000..af081b7 --- /dev/null +++ b/cmd/entities/l2_segments/l2_segments.go @@ -0,0 +1,45 @@ +package l2segments + +import ( + "log" + + serverscom "github.com/serverscom/serverscom-go-client/pkg" + "github.com/serverscom/srvctl/cmd/base" + "github.com/serverscom/srvctl/internal/output/entities" + "github.com/spf13/cobra" +) + +func NewCmd(cmdContext *base.CmdContext) *cobra.Command { + l2Entity, err := entities.Registry.GetEntityFromValue(serverscom.L2Segment{}) + if err != nil { + log.Fatal(err) + } + entitiesMap := make(map[string]entities.EntityInterface) + entitiesMap["l2-segments"] = l2Entity + cmd := &cobra.Command{ + Use: "l2-segments", + Short: "Manage L2 segments", + PersistentPreRunE: base.CombinePreRunE( + base.CheckFormatterFlags(cmdContext, entitiesMap), + base.CheckEmptyContexts(cmdContext), + ), + Args: base.NoArgs, + Run: base.UsageRun, + } + + cmd.AddCommand( + newListCmd(cmdContext), + newListGroupsCmd(cmdContext), + newListMembersCmd(cmdContext), + newListNetworksCmd(cmdContext), + newGetCmd(cmdContext), + newAddCmd(cmdContext), + newUpdateL2Cmd(cmdContext), + newUpdateL2NetworksCmd(cmdContext), + newDeleteCmd(cmdContext), + ) + + base.AddFormatFlags(cmd) + + return cmd +} diff --git a/cmd/entities/l2_segments/l2_segments_test.go b/cmd/entities/l2_segments/l2_segments_test.go new file mode 100644 index 0000000..9d17bf3 --- /dev/null +++ b/cmd/entities/l2_segments/l2_segments_test.go @@ -0,0 +1,918 @@ +package l2segments + +import ( + "errors" + "fmt" + "path/filepath" + "testing" + "time" + + . "github.com/onsi/gomega" + serverscom "github.com/serverscom/serverscom-go-client/pkg" + "github.com/serverscom/srvctl/cmd/testutils" + "github.com/serverscom/srvctl/internal/mocks" + "go.uber.org/mock/gomock" +) + +var ( + fixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "l2-segments") + testID = "testId" + testL2SegmentName = "testName" + fixedTime = time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC) + + testL2Segment = serverscom.L2Segment{ + ID: testID, + Name: testL2SegmentName, + Type: "public", + Status: "pending", + LocationGroupID: 58, + LocationGroupCode: "location1565", + Labels: map[string]string{ + "environment": "testing", + }, + Created: fixedTime, + Updated: fixedTime, + } + + testL2LocationGroup = serverscom.L2LocationGroup{ + ID: 10, + Name: testL2SegmentName, + Code: "testCode", + GroupType: "public", + LocationIDs: []int64{1, 2, 3}, + } + + testL2Member = serverscom.L2Member{ + ID: testID, + Title: "member-title", + Mode: "native", + Status: "new", + Labels: map[string]string{ + "environment": "testing", + }, + Created: fixedTime, + Updated: fixedTime, + } + + cidr = "127.1.182.0/24" + title = "testNetwork" + testNetwork = serverscom.Network{ + ID: testID, + Title: &title, + Status: "new", + Cidr: &cidr, + Family: "ipv4", + InterfaceType: "public", + DistributionMethod: "route", + Additional: true, + Created: fixedTime, + Updated: fixedTime, + } +) + +func TestGetL2SegmentCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + expectedOutput []byte + expectError bool + }{ + { + name: "get l2 segment in default format", + id: testID, + output: "", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.txt")), + }, + { + name: "get l2 segment in JSON format", + id: testID, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.json")), + }, + { + name: "get l2 segment in YAML format", + id: testID, + output: "yaml", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.yaml")), + }, + { + name: "get l2 segment with error", + id: testID, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + l2ServiceHandler := mocks.NewMockL2SegmentsService(mockCtrl) + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.L2Segments = l2ServiceHandler + + 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") + } + + l2ServiceHandler.EXPECT(). + Get(gomock.Any(), testID). + Return(&testL2Segment, err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + l2Cmd := NewCmd(testCmdContext) + + args := []string{"l2-segments", "get", fmt.Sprint(tc.id)} + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(l2Cmd). + 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 TestListL2SegmentsCmd(t *testing.T) { + testL2Segment1 := testL2Segment + testL2Segment2 := testL2Segment + testL2Segment1.ID += "1" + testL2Segment2.Name = "other-segment" + testL2Segment2.ID += "2" + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.L2Segment]) + }{ + { + name: "list all l2 segments", + output: "json", + args: []string{"-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2Segment]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.L2Segment{ + testL2Segment1, + testL2Segment2, + }, nil) + }, + }, + { + name: "list l2 segments", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2Segment]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.L2Segment{ + testL2Segment1, + }, nil) + }, + }, + { + name: "list l2 segments with template", + args: []string{"--template", "{{range .}}Name: {{.Name}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2Segment]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.L2Segment{ + testL2Segment1, + testL2Segment2, + }, nil) + }, + }, + { + name: "list l2 segments with pageView", + args: []string{"--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2Segment]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.L2Segment{ + testL2Segment1, + testL2Segment2, + }, nil) + }, + }, + { + name: "list l2 segments with error", + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.L2Segment]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + l2ServiceHandler := mocks.NewMockL2SegmentsService(mockCtrl) + collectionHandler := mocks.NewMockCollection[serverscom.L2Segment](mockCtrl) + + l2ServiceHandler.EXPECT(). + Collection(). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.L2Segments = l2ServiceHandler + + 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) + l2Cmd := NewCmd(testCmdContext) + + args := []string{"l2-segments", "list"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(l2Cmd). + 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 TestAddL2SegmentCmd(t *testing.T) { + testCases := []struct { + name string + output string + args []string + configureMock func(*mocks.MockL2SegmentsService) + expectedOutput []byte + expectError bool + }{ + { + name: "create l2 segment", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.json")), + args: []string{"--input", filepath.Join(fixtureBasePath, "create.json")}, + configureMock: func(mock *mocks.MockL2SegmentsService) { + mock.EXPECT(). + Create(gomock.Any(), gomock.AssignableToTypeOf(serverscom.L2SegmentCreateInput{})). + Return(&testL2Segment, nil) + }, + }, + { + name: "create l2 segment with error", + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + l2ServiceHandler := mocks.NewMockL2SegmentsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.L2Segments = l2ServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + + if tc.configureMock != nil { + tc.configureMock(l2ServiceHandler) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + l2Cmd := NewCmd(testCmdContext) + + args := []string{"l2-segments", "add"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(l2Cmd). + 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 TestUpdateL2SegmentCmd(t *testing.T) { + updatedSeg := testL2Segment + updatedSeg.Labels = map[string]string{"new": "label"} + + testCases := []struct { + name string + id string + output string + args []string + configureMock func(*mocks.MockL2SegmentsService) + expectedOutput []byte + expectError bool + }{ + { + name: "update l2 segment", + id: testID, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "update.json")), + args: []string{"--input", filepath.Join(fixtureBasePath, "update_input.json")}, + configureMock: func(mock *mocks.MockL2SegmentsService) { + mock.EXPECT(). + Update(gomock.Any(), testID, gomock.AssignableToTypeOf(serverscom.L2SegmentUpdateInput{})). + Return(&updatedSeg, nil) + }, + }, + { + name: "update l2 segment with error", + id: testID, + args: []string{"--input", filepath.Join(fixtureBasePath, "update_input.json")}, + configureMock: func(mock *mocks.MockL2SegmentsService) { + mock.EXPECT(). + Update(gomock.Any(), testID, gomock.AssignableToTypeOf(serverscom.L2SegmentUpdateInput{})). + Return(nil, errors.New("some error")) + }, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + l2ServiceHandler := mocks.NewMockL2SegmentsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.L2Segments = l2ServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + if tc.configureMock != nil { + tc.configureMock(l2ServiceHandler) + } + testCmdContext := testutils.NewTestCmdContext(scClient) + l2Cmd := NewCmd(testCmdContext) + + args := []string{"l2-segments", "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(l2Cmd). + 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 TestDeleteL2SegmentCmd(t *testing.T) { + testCases := []struct { + name string + id string + expectError bool + }{ + { + name: "delete l2 segment", + id: testID, + }, + { + name: "delete l2 segment with error", + id: testID, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + l2ServiceHandler := mocks.NewMockL2SegmentsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.L2Segments = l2ServiceHandler + + 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") + } + + l2ServiceHandler.EXPECT(). + Delete(gomock.Any(), testID). + Return(err) + + testCmdContext := testutils.NewTestCmdContext(scClient) + l2Cmd := NewCmd(testCmdContext) + + args := []string{"l2-segments", "delete", tc.id} + builder := testutils.NewTestCommandBuilder(). + WithCommand(l2Cmd). + WithArgs(args) + + cmd := builder.Build() + err = cmd.Execute() + + if tc.expectError { + g.Expect(err).To(HaveOccurred()) + } else { + g.Expect(err).To(BeNil()) + } + }) + } +} + +func TestUpdateL2NetworksCmd(t *testing.T) { + testCases := []struct { + name string + id string + output string + args []string + configureMock func(*mocks.MockL2SegmentsService) + expectedOutput []byte + expectError bool + }{ + { + name: "update l2 segment networks", + id: testID, + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "get.json")), + args: []string{"--input", filepath.Join(fixtureBasePath, "update_networks_input.json")}, + configureMock: func(mock *mocks.MockL2SegmentsService) { + mock.EXPECT(). + ChangeNetworks(gomock.Any(), testID, gomock.AssignableToTypeOf(serverscom.L2SegmentChangeNetworksInput{})). + Return(&testL2Segment, nil) + }, + }, + { + name: "update l2 segment networks with error", + id: testID, + args: []string{"--input", filepath.Join(fixtureBasePath, "update_networks_input.json")}, + configureMock: func(mock *mocks.MockL2SegmentsService) { + mock.EXPECT(). + ChangeNetworks(gomock.Any(), testID, gomock.AssignableToTypeOf(serverscom.L2SegmentChangeNetworksInput{})). + Return(nil, errors.New("some error")) + }, + expectError: true, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + l2ServiceHandler := mocks.NewMockL2SegmentsService(mockCtrl) + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.L2Segments = l2ServiceHandler + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + if tc.configureMock != nil { + tc.configureMock(l2ServiceHandler) + } + + testCmdContext := testutils.NewTestCmdContext(scClient) + l2Cmd := NewCmd(testCmdContext) + + args := []string{"l2-segments", "update-networks", 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(l2Cmd). + 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 TestListL2GroupsCmd(t *testing.T) { + g1 := testL2LocationGroup + g2 := testL2LocationGroup + g2.ID += 1 + g2.Name += "2" + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.L2LocationGroup]) + }{ + { + name: "list all l2 groups", + output: "json", + args: []string{"-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_groups_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2LocationGroup]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.L2LocationGroup{g1, g2}, nil) + }, + }, + { + name: "list l2 groups", + output: "json", + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_groups.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2LocationGroup]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.L2LocationGroup{g1}, nil) + }, + }, + { + name: "list l2 groups with template", + args: []string{"--template", "{{range .}}ID: {{.ID}} Name: {{.Name}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_groups_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2LocationGroup]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.L2LocationGroup{g1, g2}, nil) + }, + }, + { + name: "list l2 groups with pageView", + args: []string{"--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_groups_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2LocationGroup]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.L2LocationGroup{g1, g2}, nil) + }, + }, + { + name: "list l2 groups with error", + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.L2LocationGroup]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + collectionHandler := mocks.NewMockCollection[serverscom.L2LocationGroup](mockCtrl) + l2ServiceHandler := mocks.NewMockL2SegmentsService(mockCtrl) + l2ServiceHandler.EXPECT(). + LocationGroups(). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.L2Segments = l2ServiceHandler + + 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) + l2Cmd := NewCmd(testCmdContext) + + args := []string{"l2-segments", "list-groups"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(l2Cmd). + 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 TestListL2MembersCmd(t *testing.T) { + m1 := testL2Member + m2 := testL2Member + m1.ID += "1" + m2.ID += "2" + vlan := 100 + m2.Vlan = &vlan + m2.Title = "other-member" + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.L2Member]) + }{ + { + name: "list all l2 members", + output: "json", + args: []string{testID, "-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_members_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2Member]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.L2Member{m1, m2}, nil) + }, + }, + { + name: "list l2 members", + output: "json", + args: []string{testID}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_members.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2Member]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.L2Member{m1}, nil) + }, + }, + { + name: "list l2 members with template", + args: []string{testID, "--template", "{{range .}}ID: {{.ID}} Title: {{.Title}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_members_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2Member]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.L2Member{m1, m2}, nil) + }, + }, + { + name: "list l2 members with pageView", + args: []string{testID, "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_members_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.L2Member]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.L2Member{m1, m2}, nil) + }, + }, + { + name: "list l2 members error", + args: []string{testID}, + expectError: true, + configureMock: func(mock *mocks.MockCollection[serverscom.L2Member]) { + mock.EXPECT(). + List(gomock.Any()). + Return(nil, errors.New("some error")) + }, + }, + } + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + collectionHandler := mocks.NewMockCollection[serverscom.L2Member](mockCtrl) + l2ServiceHandler := mocks.NewMockL2SegmentsService(mockCtrl) + l2ServiceHandler.EXPECT(). + Members(testID). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.L2Segments = l2ServiceHandler + + 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) + l2Cmd := NewCmd(testCmdContext) + + args := []string{"l2-segments", "list-members"} + if len(tc.args) > 0 { + args = append(args, tc.args...) + } + if tc.output != "" { + args = append(args, "--output", tc.output) + } + + builder := testutils.NewTestCommandBuilder(). + WithCommand(l2Cmd). + 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 TestListL2NetworksCmd(t *testing.T) { + n1 := testNetwork + n2 := testNetwork + n1.ID += "1" + n2.ID += "2" + title := "other-network" + n2.Title = &title + + testCases := []struct { + name string + output string + args []string + expectedOutput []byte + expectError bool + configureMock func(*mocks.MockCollection[serverscom.Network]) + }{ + { + name: "list all l2 networks", + output: "json", + args: []string{testID, "-A"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_networks_all.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + Collect(gomock.Any()). + Return([]serverscom.Network{n1, n2}, nil) + }, + }, + { + name: "list l2 networks", + output: "json", + args: []string{testID}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_networks.json")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{n1}, nil) + }, + }, + { + name: "list l2 networks with template", + args: []string{testID, "--template", "{{range .}}ID: {{.ID}} Title: {{.Title}}\n{{end}}"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_networks_template.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{n1, n2}, nil) + }, + }, + { + name: "list l2 networks with pageView", + args: []string{testID, "--page-view"}, + expectedOutput: testutils.ReadFixture(filepath.Join(fixtureBasePath, "list_networks_pageview.txt")), + configureMock: func(mock *mocks.MockCollection[serverscom.Network]) { + mock.EXPECT(). + List(gomock.Any()). + Return([]serverscom.Network{n1, n2}, nil) + }, + }, + { + name: "list l2 networks error", + args: []string{testID}, + 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() + + collectionHandler := mocks.NewMockCollection[serverscom.Network](mockCtrl) + l2ServiceHandler := mocks.NewMockL2SegmentsService(mockCtrl) + l2ServiceHandler.EXPECT(). + Networks(testID). + Return(collectionHandler). + AnyTimes() + + collectionHandler.EXPECT(). + SetParam(gomock.Any(), gomock.Any()). + Return(collectionHandler). + AnyTimes() + + scClient := serverscom.NewClientWithEndpoint("", "") + scClient.L2Segments = l2ServiceHandler + + 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) + l2Cmd := NewCmd(testCmdContext) + + args := []string{"l2-segments", "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(l2Cmd). + 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/entities/l2_segments/list.go b/cmd/entities/l2_segments/list.go new file mode 100644 index 0000000..94d238f --- /dev/null +++ b/cmd/entities/l2_segments/list.go @@ -0,0 +1,64 @@ +package l2segments + +import ( + serverscom "github.com/serverscom/serverscom-go-client/pkg" + "github.com/serverscom/srvctl/cmd/base" + "github.com/spf13/cobra" +) + +func newListCmd(cmdContext *base.CmdContext) *cobra.Command { + factory := func(verbose bool, args ...string) serverscom.Collection[serverscom.L2Segment] { + scClient := cmdContext.GetClient().SetVerbose(verbose).GetScClient() + return scClient.L2Segments.Collection() + } + + opts := base.NewListOptions( + &base.BaseListOptions[serverscom.L2Segment]{}, + &base.LabelSelectorOption[serverscom.L2Segment]{}, + ) + + return base.NewListCmd("list", "l2 segments", factory, cmdContext, opts...) +} + +func newListGroupsCmd(cmdContext *base.CmdContext) *cobra.Command { + factory := func(verbose bool, args ...string) serverscom.Collection[serverscom.L2LocationGroup] { + scClient := cmdContext.GetClient().SetVerbose(verbose).GetScClient() + return scClient.L2Segments.LocationGroups() + } + + opts := base.NewListOptions( + &base.BaseListOptions[serverscom.L2LocationGroup]{}, + &base.L2SegmentGroupTypeOption[serverscom.L2LocationGroup]{}, + ) + + return base.NewListCmd("list-groups", "l2 segment location groups", factory, cmdContext, opts...) +} + +func newListMembersCmd(cmdContext *base.CmdContext) *cobra.Command { + factory := func(verbose bool, args ...string) serverscom.Collection[serverscom.L2Member] { + scClient := cmdContext.GetClient().SetVerbose(verbose).GetScClient() + return scClient.L2Segments.Members(args[0]) + } + + opts := base.NewListOptions( + &base.BaseListOptions[serverscom.L2Member]{}, + &base.L2SegmentGroupTypeOption[serverscom.L2Member]{}, + ) + + return base.NewListCmd("list-members", "l2 segment members", factory, cmdContext, opts...) +} + +func newListNetworksCmd(cmdContext *base.CmdContext) *cobra.Command { + + factory := func(verbose bool, args ...string) serverscom.Collection[serverscom.Network] { + scClient := cmdContext.GetClient().SetVerbose(verbose).GetScClient() + return scClient.L2Segments.Networks(args[0]) + } + + opts := base.NewListOptions( + &base.BaseListOptions[serverscom.Network]{}, + &base.L2SegmentGroupTypeOption[serverscom.Network]{}, + ) + + return base.NewListCmd("list-networks", "l2 segment networks", factory, cmdContext, opts...) +} diff --git a/cmd/entities/l2_segments/update.go b/cmd/entities/l2_segments/update.go new file mode 100644 index 0000000..2be8c60 --- /dev/null +++ b/cmd/entities/l2_segments/update.go @@ -0,0 +1,99 @@ +package l2segments + +import ( + "log" + + serverscom "github.com/serverscom/serverscom-go-client/pkg" + "github.com/serverscom/srvctl/cmd/base" + "github.com/spf13/cobra" +) + +func newUpdateL2Cmd(cmdContext *base.CmdContext) *cobra.Command { + var path string + + cmd := &cobra.Command{ + Use: "update ", + Short: "Update an L2 segment", + Long: "Update an L2 segment by id", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + manager := cmdContext.GetManager() + + ctx, cancel := base.SetupContext(cmd, manager) + defer cancel() + + base.SetupProxy(cmd, manager) + + input := &serverscom.L2SegmentUpdateInput{} + if err := base.ReadInputJSON(path, cmd.InOrStdin(), input); err != nil { + return err + } + + scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient() + + l2SegmentId := args[0] + l2Segment, err := scClient.L2Segments.Update(ctx, l2SegmentId, *input) + if err != nil { + return err + } + + if l2Segment != nil { + formatter := cmdContext.GetOrCreateFormatter(cmd) + return formatter.Format(l2Segment) + } + return nil + }, + } + + cmd.Flags().StringVarP(&path, "input", "i", "", "path to input file or '-' to read from stdin") + if err := cmd.MarkFlagRequired("input"); err != nil { + log.Fatal(err) + } + + return cmd +} + +func newUpdateL2NetworksCmd(cmdContext *base.CmdContext) *cobra.Command { + var path string + + cmd := &cobra.Command{ + Use: "update-networks ", + Short: "Update an L2 segment networks", + Long: "Update an L2 segment networks by id", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + manager := cmdContext.GetManager() + + ctx, cancel := base.SetupContext(cmd, manager) + defer cancel() + + base.SetupProxy(cmd, manager) + + input := &serverscom.L2SegmentChangeNetworksInput{} + if err := base.ReadInputJSON(path, cmd.InOrStdin(), input); err != nil { + return err + } + + scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient() + + l2SegmentId := args[0] + l2Segment, err := scClient.L2Segments.ChangeNetworks(ctx, l2SegmentId, *input) + if err != nil { + return err + } + + if l2Segment != nil { + formatter := cmdContext.GetOrCreateFormatter(cmd) + return formatter.Format(l2Segment) + } + return nil + }, + } + + cmd.Flags().StringVarP(&path, "input", "i", "", "path to input file or '-' to read from stdin") + if err := cmd.MarkFlagRequired("input"); err != nil { + log.Fatal(err) + } + + return cmd +} diff --git a/cmd/root.go b/cmd/root.go index 6133e26..8b5a62e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -9,9 +9,14 @@ import ( "github.com/serverscom/srvctl/cmd/entities/hosts" "github.com/serverscom/srvctl/cmd/entities/invoices" "github.com/serverscom/srvctl/cmd/entities/k8s" + l2segments "github.com/serverscom/srvctl/cmd/entities/l2_segments" loadbalancers "github.com/serverscom/srvctl/cmd/entities/load_balancers" "github.com/serverscom/srvctl/cmd/entities/locations" "github.com/serverscom/srvctl/cmd/entities/racks" + sbmmodels "github.com/serverscom/srvctl/cmd/entities/sbm_models" + sbmosoptions "github.com/serverscom/srvctl/cmd/entities/sbm_os_options" + serverosoptions "github.com/serverscom/srvctl/cmd/entities/server_os_options" + serverramoptions "github.com/serverscom/srvctl/cmd/entities/server_ram_options" "github.com/serverscom/srvctl/cmd/entities/servermodels" sshkeys "github.com/serverscom/srvctl/cmd/entities/ssh-keys" "github.com/serverscom/srvctl/cmd/entities/ssl" @@ -60,6 +65,11 @@ func NewRootCmd(version string) *cobra.Command { cmd.AddCommand(uplinkbandwidths.NewCmd(cmdContext)) cmd.AddCommand(servermodels.NewCmd(cmdContext)) cmd.AddCommand(drivemodels.NewCmd(cmdContext)) + cmd.AddCommand(serverosoptions.NewCmd(cmdContext)) + cmd.AddCommand(serverramoptions.NewCmd(cmdContext)) + cmd.AddCommand(sbmosoptions.NewCmd(cmdContext)) + cmd.AddCommand(sbmmodels.NewCmd(cmdContext)) + cmd.AddCommand(l2segments.NewCmd(cmdContext)) return cmd } diff --git a/internal/mocks/l2_segment_service.go b/internal/mocks/l2_segment_service.go new file mode 100644 index 0000000..68b8b75 --- /dev/null +++ b/internal/mocks/l2_segment_service.go @@ -0,0 +1,172 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./vendor/github.com/serverscom/serverscom-go-client/pkg/l2_segments.go +// +// Generated by this command: +// +// mockgen --destination ./internal/mocks/l2_segment_service.go --package=mocks --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/l2_segments.go +// + +// Package mocks is a generated GoMock package. +package mocks + +import ( + context "context" + reflect "reflect" + + serverscom "github.com/serverscom/serverscom-go-client/pkg" + gomock "go.uber.org/mock/gomock" +) + +// MockL2SegmentsService is a mock of L2SegmentsService interface. +type MockL2SegmentsService struct { + ctrl *gomock.Controller + recorder *MockL2SegmentsServiceMockRecorder + isgomock struct{} +} + +// MockL2SegmentsServiceMockRecorder is the mock recorder for MockL2SegmentsService. +type MockL2SegmentsServiceMockRecorder struct { + mock *MockL2SegmentsService +} + +// NewMockL2SegmentsService creates a new mock instance. +func NewMockL2SegmentsService(ctrl *gomock.Controller) *MockL2SegmentsService { + mock := &MockL2SegmentsService{ctrl: ctrl} + mock.recorder = &MockL2SegmentsServiceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockL2SegmentsService) EXPECT() *MockL2SegmentsServiceMockRecorder { + return m.recorder +} + +// ChangeNetworks mocks base method. +func (m *MockL2SegmentsService) ChangeNetworks(ctx context.Context, segmentID string, input serverscom.L2SegmentChangeNetworksInput) (*serverscom.L2Segment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChangeNetworks", ctx, segmentID, input) + ret0, _ := ret[0].(*serverscom.L2Segment) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ChangeNetworks indicates an expected call of ChangeNetworks. +func (mr *MockL2SegmentsServiceMockRecorder) ChangeNetworks(ctx, segmentID, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeNetworks", reflect.TypeOf((*MockL2SegmentsService)(nil).ChangeNetworks), ctx, segmentID, input) +} + +// Collection mocks base method. +func (m *MockL2SegmentsService) Collection() serverscom.Collection[serverscom.L2Segment] { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Collection") + ret0, _ := ret[0].(serverscom.Collection[serverscom.L2Segment]) + return ret0 +} + +// Collection indicates an expected call of Collection. +func (mr *MockL2SegmentsServiceMockRecorder) Collection() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Collection", reflect.TypeOf((*MockL2SegmentsService)(nil).Collection)) +} + +// Create mocks base method. +func (m *MockL2SegmentsService) Create(ctx context.Context, input serverscom.L2SegmentCreateInput) (*serverscom.L2Segment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Create", ctx, input) + ret0, _ := ret[0].(*serverscom.L2Segment) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Create indicates an expected call of Create. +func (mr *MockL2SegmentsServiceMockRecorder) Create(ctx, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockL2SegmentsService)(nil).Create), ctx, input) +} + +// Delete mocks base method. +func (m *MockL2SegmentsService) Delete(ctx context.Context, segmentID string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, segmentID) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockL2SegmentsServiceMockRecorder) Delete(ctx, segmentID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockL2SegmentsService)(nil).Delete), ctx, segmentID) +} + +// Get mocks base method. +func (m *MockL2SegmentsService) Get(ctx context.Context, segmentID string) (*serverscom.L2Segment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", ctx, segmentID) + ret0, _ := ret[0].(*serverscom.L2Segment) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockL2SegmentsServiceMockRecorder) Get(ctx, segmentID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockL2SegmentsService)(nil).Get), ctx, segmentID) +} + +// LocationGroups mocks base method. +func (m *MockL2SegmentsService) LocationGroups() serverscom.Collection[serverscom.L2LocationGroup] { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LocationGroups") + ret0, _ := ret[0].(serverscom.Collection[serverscom.L2LocationGroup]) + return ret0 +} + +// LocationGroups indicates an expected call of LocationGroups. +func (mr *MockL2SegmentsServiceMockRecorder) LocationGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LocationGroups", reflect.TypeOf((*MockL2SegmentsService)(nil).LocationGroups)) +} + +// Members mocks base method. +func (m *MockL2SegmentsService) Members(segmentID string) serverscom.Collection[serverscom.L2Member] { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Members", segmentID) + ret0, _ := ret[0].(serverscom.Collection[serverscom.L2Member]) + return ret0 +} + +// Members indicates an expected call of Members. +func (mr *MockL2SegmentsServiceMockRecorder) Members(segmentID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Members", reflect.TypeOf((*MockL2SegmentsService)(nil).Members), segmentID) +} + +// Networks mocks base method. +func (m *MockL2SegmentsService) Networks(segmentID string) serverscom.Collection[serverscom.Network] { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Networks", segmentID) + ret0, _ := ret[0].(serverscom.Collection[serverscom.Network]) + return ret0 +} + +// Networks indicates an expected call of Networks. +func (mr *MockL2SegmentsServiceMockRecorder) Networks(segmentID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Networks", reflect.TypeOf((*MockL2SegmentsService)(nil).Networks), segmentID) +} + +// Update mocks base method. +func (m *MockL2SegmentsService) Update(ctx context.Context, segmentID string, input serverscom.L2SegmentUpdateInput) (*serverscom.L2Segment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, segmentID, input) + ret0, _ := ret[0].(*serverscom.L2Segment) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockL2SegmentsServiceMockRecorder) Update(ctx, segmentID, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockL2SegmentsService)(nil).Update), ctx, segmentID, input) +} diff --git a/internal/output/entities/handlers.go b/internal/output/entities/handlers.go index 0861ffa..48b166d 100644 --- a/internal/output/entities/handlers.go +++ b/internal/output/entities/handlers.go @@ -121,15 +121,20 @@ func slicePvHandler(w io.Writer, v any, indent string, _ *Field) error { return err } - slice, ok := v.([]string) - if !ok || len(slice) == 0 { + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Slice { + _, err := fmt.Fprintf(w, "%s", indent, v) + return err + } + + if rv.Len() == 0 { _, err := fmt.Fprintf(w, "%s", indent) return err } - lines := make([]string, 0, len(slice)) - for _, item := range slice { - lines = append(lines, fmt.Sprintf("%s%s", indent, item)) + lines := make([]string, 0, rv.Len()) + for i := range rv.Len() { + lines = append(lines, fmt.Sprintf("%s%v", indent, rv.Index(i).Interface())) } _, err := fmt.Fprint(w, strings.Join(lines, "\n")) diff --git a/internal/output/entities/hosts.go b/internal/output/entities/hosts.go index 9fcedea..21245eb 100644 --- a/internal/output/entities/hosts.go +++ b/internal/output/entities/hosts.go @@ -18,9 +18,7 @@ var ( HostPTRRecordType = reflect.TypeOf(serverscom.PTRRecord{}) HostNetworkType = reflect.TypeOf(serverscom.Network{}) HostListDefaultFields = []string{"ID", "Type", "Title", "Status"} - CmdDefaultFields = map[string][]string{ - "list": HostListDefaultFields, - } + NetworkListDefaultFields = []string{"ID", "Title", "Status", "CIDR", "Family", "InterfaceType", "DistributionMethod", "Additional"} ) func getConfigurationDetailsField() Field { @@ -89,8 +87,10 @@ func RegisterHostDefinition() { {ID: "Created", Name: "Created", Path: "Created", ListHandlerFunc: timeHandler, PageViewHandlerFunc: timeHandler, Default: true}, {ID: "Updated", Name: "Updated", Path: "Updated", ListHandlerFunc: timeHandler, PageViewHandlerFunc: timeHandler, Default: true}, }, - cmdDefaultFields: CmdDefaultFields, - eType: HostType, + cmdDefaultFields: map[string][]string{ + "list": HostListDefaultFields, + }, + eType: HostType, } if err := Registry.Register(hostEntity); err != nil { log.Fatal(err) @@ -251,13 +251,15 @@ func RegisterHostsSubDefinitions() { {ID: "InterfaceType", Name: "InterfaceType", Path: "InterfaceType", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, {ID: "DistributionMethod", Name: "DistributionMethod", Path: "DistributionMethod", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, {ID: "Additional", Name: "Additional", Path: "Additional", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, - {ID: "Updated", Name: "Updated", Path: "Updated", ListHandlerFunc: timeHandler, PageViewHandlerFunc: timeHandler, Default: true}, {ID: "Created", Name: "Created", Path: "Created", ListHandlerFunc: timeHandler, PageViewHandlerFunc: timeHandler, Default: true}, + {ID: "Updated", Name: "Updated", Path: "Updated", ListHandlerFunc: timeHandler, PageViewHandlerFunc: timeHandler, Default: true}, }, eType: HostNetworkType, + cmdDefaultFields: map[string][]string{ + "list-networks": NetworkListDefaultFields, + }, } if err := Registry.Register(hostNetworkEntity); err != nil { log.Fatal(err) } - } diff --git a/internal/output/entities/init.go b/internal/output/entities/init.go index cb0495f..d16e4ea 100644 --- a/internal/output/entities/init.go +++ b/internal/output/entities/init.go @@ -29,4 +29,5 @@ func init() { RegisterSBMModelOptionDefinition() RegisterOperatingSystemOptionDefinition() RegisterRAMOptionDefinition() + RegisterL2SegmentDefinitions() } diff --git a/internal/output/entities/l2_segments.go b/internal/output/entities/l2_segments.go new file mode 100644 index 0000000..82a1372 --- /dev/null +++ b/internal/output/entities/l2_segments.go @@ -0,0 +1,78 @@ +package entities + +import ( + "log" + "reflect" + + serverscom "github.com/serverscom/serverscom-go-client/pkg" +) + +var ( + L2SegmentType = reflect.TypeOf(serverscom.L2Segment{}) + L2SegmentLocationGroupType = reflect.TypeOf(serverscom.L2LocationGroup{}) + L2SegmentMemberType = reflect.TypeOf(serverscom.L2Member{}) + L2SegmentNetworkType = reflect.TypeOf(serverscom.Network{}) + L2SegmentListDefaultFields = []string{"ID", "Name", "Type", "Status", "LocationGroupID", "LocationGroupCode"} + L2SegmentMemberListDefaultFields = []string{"ID", "Title", "Mode", "VLAN", "Status"} +) + +func RegisterL2SegmentDefinitions() { + l2SegmentEntity := &Entity{ + fields: []Field{ + {ID: "ID", Name: "ID", Path: "ID", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "Name", Name: "Name", Path: "Name", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "Type", Name: "Type", Path: "Type", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "Status", Name: "Status", Path: "Status", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "LocationGroupID", Name: "LocationGroupID", Path: "LocationGroupID", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "LocationGroupCode", Name: "LocationGroupCode", Path: "LocationGroupCode", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "Labels", Name: "Labels", Path: "Labels", PageViewHandlerFunc: mapPvHandler}, + {ID: "Created", Name: "Created", Path: "Created", ListHandlerFunc: timeHandler, PageViewHandlerFunc: timeHandler, Default: true}, + {ID: "Updated", Name: "Updated", Path: "Updated", ListHandlerFunc: timeHandler, PageViewHandlerFunc: timeHandler, Default: true}, + }, + + cmdDefaultFields: map[string][]string{ + "list": L2SegmentListDefaultFields, + }, + eType: L2SegmentType, + } + if err := Registry.Register(l2SegmentEntity); err != nil { + log.Fatal(err) + } + + l2SegmentLocationGroupEntity := &Entity{ + fields: []Field{ + {ID: "ID", Name: "ID", Path: "ID", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "Name", Name: "Name", Path: "Name", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "Code", Name: "Code", Path: "Code", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "GroupType", Name: "GroupType", Path: "GroupType", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "LocationIDs", Name: "LocationIDs", Path: "LocationIDs", PageViewHandlerFunc: slicePvHandler}, + // TODO field missing in go client + // {ID: "Hyperscalers", Name: "Hyperscalers", Path: "Hyperscalers", PageViewHandlerFunc: slicePvHandler}, + }, + eType: L2SegmentLocationGroupType, + } + if err := Registry.Register(l2SegmentLocationGroupEntity); err != nil { + log.Fatal(err) + } + + l2SegmentMemberEntity := &Entity{ + fields: []Field{ + {ID: "ID", Name: "ID", Path: "ID", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "Title", Name: "Title", Path: "Title", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "Mode", Name: "Mode", Path: "Mode", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "VLAN", Name: "VLAN", Path: "VLAN", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "Status", Name: "Status", Path: "Status", ListHandlerFunc: stringHandler, PageViewHandlerFunc: stringHandler, Default: true}, + {ID: "Labels", Name: "Labels", Path: "Labels", PageViewHandlerFunc: mapPvHandler}, + {ID: "Created", Name: "Created", Path: "Created", ListHandlerFunc: timeHandler, PageViewHandlerFunc: timeHandler, Default: true}, + {ID: "Updated", Name: "Updated", Path: "Updated", ListHandlerFunc: timeHandler, PageViewHandlerFunc: timeHandler, Default: true}, + }, + + cmdDefaultFields: map[string][]string{ + "list-members": L2SegmentMemberListDefaultFields, + }, + eType: L2SegmentMemberType, + } + if err := Registry.Register(l2SegmentMemberEntity); err != nil { + log.Fatal(err) + } +} diff --git a/testdata/entities/hosts/get_ds_network.txt b/testdata/entities/hosts/get_ds_network.txt index 92698fb..87fcf6f 100644 --- a/testdata/entities/hosts/get_ds_network.txt +++ b/testdata/entities/hosts/get_ds_network.txt @@ -1,2 +1,2 @@ -ID Title Status CIDR Family InterfaceType DistributionMethod Additional Updated Created +ID Title Status CIDR Family InterfaceType DistributionMethod Additional Created Updated testNetId Some Net active 100.0.8.0/29 ipv4 public gateway false 2025-01-01T12:00:00Z 2025-01-01T12:00:00Z diff --git a/testdata/entities/hosts/list_ds_networks_pageview.txt b/testdata/entities/hosts/list_ds_networks_pageview.txt index fa89faa..a98985d 100644 --- a/testdata/entities/hosts/list_ds_networks_pageview.txt +++ b/testdata/entities/hosts/list_ds_networks_pageview.txt @@ -6,8 +6,8 @@ Family: ipv4 InterfaceType: public DistributionMethod: gateway Additional: false -Updated: 2025-01-01T12:00:00Z Created: 2025-01-01T12:00:00Z +Updated: 2025-01-01T12:00:00Z --- ID: testNetId2 Title: Another Net @@ -17,5 +17,5 @@ Family: ipv4 InterfaceType: public DistributionMethod: gateway Additional: false -Updated: 2025-01-01T12:00:00Z Created: 2025-01-01T12:00:00Z +Updated: 2025-01-01T12:00:00Z diff --git a/testdata/entities/l2-segments/create.json b/testdata/entities/l2-segments/create.json new file mode 100644 index 0000000..4a070e2 --- /dev/null +++ b/testdata/entities/l2-segments/create.json @@ -0,0 +1,14 @@ +{ + "name": "testName", + "type": "public", + "location_group_id": 58, + "members": [ + { + "id": "LDdwmwa1", + "mode": "native" + } + ], + "labels": { + "environment": "testing" + } +} \ No newline at end of file diff --git a/testdata/entities/l2-segments/get.json b/testdata/entities/l2-segments/get.json new file mode 100644 index 0000000..a050763 --- /dev/null +++ b/testdata/entities/l2-segments/get.json @@ -0,0 +1,13 @@ +{ + "id": "testId", + "name": "testName", + "type": "public", + "status": "pending", + "location_group_id": 58, + "location_group_code": "location1565", + "labels": { + "environment": "testing" + }, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z" +} \ No newline at end of file diff --git a/testdata/entities/l2-segments/get.txt b/testdata/entities/l2-segments/get.txt new file mode 100644 index 0000000..10d7cb7 --- /dev/null +++ b/testdata/entities/l2-segments/get.txt @@ -0,0 +1,2 @@ +ID Name Type Status LocationGroupID LocationGroupCode Created Updated +testId testName public pending 58 location1565 2025-01-01T12:00:00Z 2025-01-01T12:00:00Z diff --git a/testdata/entities/l2-segments/get.yaml b/testdata/entities/l2-segments/get.yaml new file mode 100644 index 0000000..3154a62 --- /dev/null +++ b/testdata/entities/l2-segments/get.yaml @@ -0,0 +1,10 @@ +id: testId +name: testName +type: public +status: pending +locationgroupid: 58 +locationgroupcode: location1565 +labels: + environment: testing +created: 2025-01-01T12:00:00Z +updated: 2025-01-01T12:00:00Z diff --git a/testdata/entities/l2-segments/list.json b/testdata/entities/l2-segments/list.json new file mode 100644 index 0000000..1476bbf --- /dev/null +++ b/testdata/entities/l2-segments/list.json @@ -0,0 +1,15 @@ +[ + { + "id": "testId1", + "name": "testName", + "type": "public", + "status": "pending", + "location_group_id": 58, + "location_group_code": "location1565", + "labels": { + "environment": "testing" + }, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z" + } +] \ No newline at end of file diff --git a/testdata/entities/l2-segments/list_all.json b/testdata/entities/l2-segments/list_all.json new file mode 100644 index 0000000..73eb414 --- /dev/null +++ b/testdata/entities/l2-segments/list_all.json @@ -0,0 +1,28 @@ +[ + { + "id": "testId1", + "name": "testName", + "type": "public", + "status": "pending", + "location_group_id": 58, + "location_group_code": "location1565", + "labels": { + "environment": "testing" + }, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z" + }, + { + "id": "testId2", + "name": "other-segment", + "type": "public", + "status": "pending", + "location_group_id": 58, + "location_group_code": "location1565", + "labels": { + "environment": "testing" + }, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z" + } +] \ No newline at end of file diff --git a/testdata/entities/l2-segments/list_groups.json b/testdata/entities/l2-segments/list_groups.json new file mode 100644 index 0000000..3b3394b --- /dev/null +++ b/testdata/entities/l2-segments/list_groups.json @@ -0,0 +1,13 @@ +[ + { + "id": 10, + "name": "testName", + "code": "testCode", + "group_type": "public", + "location_ids": [ + 1, + 2, + 3 + ] + } +] \ No newline at end of file diff --git a/testdata/entities/l2-segments/list_groups_all.json b/testdata/entities/l2-segments/list_groups_all.json new file mode 100644 index 0000000..228cbb5 --- /dev/null +++ b/testdata/entities/l2-segments/list_groups_all.json @@ -0,0 +1,24 @@ +[ + { + "id": 10, + "name": "testName", + "code": "testCode", + "group_type": "public", + "location_ids": [ + 1, + 2, + 3 + ] + }, + { + "id": 11, + "name": "testName2", + "code": "testCode", + "group_type": "public", + "location_ids": [ + 1, + 2, + 3 + ] + } +] \ No newline at end of file diff --git a/testdata/entities/l2-segments/list_groups_pageview.txt b/testdata/entities/l2-segments/list_groups_pageview.txt new file mode 100644 index 0000000..3c302e2 --- /dev/null +++ b/testdata/entities/l2-segments/list_groups_pageview.txt @@ -0,0 +1,15 @@ +ID: 10 +Name: testName +Code: testCode +GroupType: public +LocationIDs: 1 + 2 + 3 +--- +ID: 11 +Name: testName2 +Code: testCode +GroupType: public +LocationIDs: 1 + 2 + 3 diff --git a/testdata/entities/l2-segments/list_groups_template.txt b/testdata/entities/l2-segments/list_groups_template.txt new file mode 100644 index 0000000..9a8af40 --- /dev/null +++ b/testdata/entities/l2-segments/list_groups_template.txt @@ -0,0 +1,2 @@ +ID: 10 Name: testName +ID: 11 Name: testName2 diff --git a/testdata/entities/l2-segments/list_members.json b/testdata/entities/l2-segments/list_members.json new file mode 100644 index 0000000..5443b23 --- /dev/null +++ b/testdata/entities/l2-segments/list_members.json @@ -0,0 +1,14 @@ +[ + { + "id": "testId1", + "title": "member-title", + "mode": "native", + "vlan": null, + "status": "new", + "labels": { + "environment": "testing" + }, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z" + } +] \ No newline at end of file diff --git a/testdata/entities/l2-segments/list_members_all.json b/testdata/entities/l2-segments/list_members_all.json new file mode 100644 index 0000000..59e194a --- /dev/null +++ b/testdata/entities/l2-segments/list_members_all.json @@ -0,0 +1,26 @@ +[ + { + "id": "testId1", + "title": "member-title", + "mode": "native", + "vlan": null, + "status": "new", + "labels": { + "environment": "testing" + }, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z" + }, + { + "id": "testId2", + "title": "other-member", + "mode": "native", + "vlan": 100, + "status": "new", + "labels": { + "environment": "testing" + }, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z" + } +] \ No newline at end of file diff --git a/testdata/entities/l2-segments/list_members_pageview.txt b/testdata/entities/l2-segments/list_members_pageview.txt new file mode 100644 index 0000000..f9c4405 --- /dev/null +++ b/testdata/entities/l2-segments/list_members_pageview.txt @@ -0,0 +1,17 @@ +ID: testId1 +Title: member-title +Mode: native +VLAN: +Status: new +Labels: environment=testing +Created: 2025-01-01T12:00:00Z +Updated: 2025-01-01T12:00:00Z +--- +ID: testId2 +Title: other-member +Mode: native +VLAN: +Status: new +Labels: environment=testing +Created: 2025-01-01T12:00:00Z +Updated: 2025-01-01T12:00:00Z diff --git a/testdata/entities/l2-segments/list_members_template.txt b/testdata/entities/l2-segments/list_members_template.txt new file mode 100644 index 0000000..585a379 --- /dev/null +++ b/testdata/entities/l2-segments/list_members_template.txt @@ -0,0 +1,2 @@ +ID: testId1 Title: member-title +ID: testId2 Title: other-member diff --git a/testdata/entities/l2-segments/list_networks.json b/testdata/entities/l2-segments/list_networks.json new file mode 100644 index 0000000..1c82fa5 --- /dev/null +++ b/testdata/entities/l2-segments/list_networks.json @@ -0,0 +1,15 @@ +[ + { + "id": "testId1", + "title": "testNetwork", + "status": "new", + "cidr": "127.1.182.0/24", + "family": "ipv4", + "interface_type": "public", + "distribution_method": "route", + "additional": true, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z", + "state": "" + } +] \ No newline at end of file diff --git a/testdata/entities/l2-segments/list_networks_all.json b/testdata/entities/l2-segments/list_networks_all.json new file mode 100644 index 0000000..ae7faaa --- /dev/null +++ b/testdata/entities/l2-segments/list_networks_all.json @@ -0,0 +1,28 @@ +[ + { + "id": "testId1", + "title": "testNetwork", + "status": "new", + "cidr": "127.1.182.0/24", + "family": "ipv4", + "interface_type": "public", + "distribution_method": "route", + "additional": true, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z", + "state": "" + }, + { + "id": "testId2", + "title": "other-network", + "status": "new", + "cidr": "127.1.182.0/24", + "family": "ipv4", + "interface_type": "public", + "distribution_method": "route", + "additional": true, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z", + "state": "" + } +] \ No newline at end of file diff --git a/testdata/entities/l2-segments/list_networks_pageview.txt b/testdata/entities/l2-segments/list_networks_pageview.txt new file mode 100644 index 0000000..27ef624 --- /dev/null +++ b/testdata/entities/l2-segments/list_networks_pageview.txt @@ -0,0 +1,21 @@ +ID: testId1 +Title: testNetwork +Status: new +CIDR: 127.1.182.0/24 +Family: ipv4 +InterfaceType: public +DistributionMethod: route +Additional: true +Created: 2025-01-01T12:00:00Z +Updated: 2025-01-01T12:00:00Z +--- +ID: testId2 +Title: other-network +Status: new +CIDR: 127.1.182.0/24 +Family: ipv4 +InterfaceType: public +DistributionMethod: route +Additional: true +Created: 2025-01-01T12:00:00Z +Updated: 2025-01-01T12:00:00Z diff --git a/testdata/entities/l2-segments/list_networks_template.txt b/testdata/entities/l2-segments/list_networks_template.txt new file mode 100644 index 0000000..dd3a958 --- /dev/null +++ b/testdata/entities/l2-segments/list_networks_template.txt @@ -0,0 +1,2 @@ +ID: testId1 Title: testNetwork +ID: testId2 Title: other-network diff --git a/testdata/entities/l2-segments/list_pageview.txt b/testdata/entities/l2-segments/list_pageview.txt new file mode 100644 index 0000000..c3fcfd5 --- /dev/null +++ b/testdata/entities/l2-segments/list_pageview.txt @@ -0,0 +1,19 @@ +ID: testId1 +Name: testName +Type: public +Status: pending +LocationGroupID: 58 +LocationGroupCode: location1565 +Labels: environment=testing +Created: 2025-01-01T12:00:00Z +Updated: 2025-01-01T12:00:00Z +--- +ID: testId2 +Name: other-segment +Type: public +Status: pending +LocationGroupID: 58 +LocationGroupCode: location1565 +Labels: environment=testing +Created: 2025-01-01T12:00:00Z +Updated: 2025-01-01T12:00:00Z diff --git a/testdata/entities/l2-segments/list_template.txt b/testdata/entities/l2-segments/list_template.txt new file mode 100644 index 0000000..9bd7b09 --- /dev/null +++ b/testdata/entities/l2-segments/list_template.txt @@ -0,0 +1,2 @@ +Name: testName +Name: other-segment diff --git a/testdata/entities/l2-segments/update.json b/testdata/entities/l2-segments/update.json new file mode 100644 index 0000000..e280eea --- /dev/null +++ b/testdata/entities/l2-segments/update.json @@ -0,0 +1,13 @@ +{ + "id": "testId", + "name": "testName", + "type": "public", + "status": "pending", + "location_group_id": 58, + "location_group_code": "location1565", + "labels": { + "new": "label" + }, + "created_at": "2025-01-01T12:00:00Z", + "updated_at": "2025-01-01T12:00:00Z" +} \ No newline at end of file diff --git a/testdata/entities/l2-segments/update_input.json b/testdata/entities/l2-segments/update_input.json new file mode 100644 index 0000000..2c1449f --- /dev/null +++ b/testdata/entities/l2-segments/update_input.json @@ -0,0 +1,11 @@ +{ + "members": [ + { + "id": "y5eVP1bE", + "mode": "native" + } + ], + "labels": { + "new": "label" + } +} \ No newline at end of file diff --git a/testdata/entities/l2-segments/update_networks_input.json b/testdata/entities/l2-segments/update_networks_input.json new file mode 100644 index 0000000..3f24b9e --- /dev/null +++ b/testdata/entities/l2-segments/update_networks_input.json @@ -0,0 +1,11 @@ +{ + "create": [ + { + "mask": 32, + "distribution_method": "route" + } + ], + "delete": [ + "8mepW2dM" + ] +} \ No newline at end of file