From 190cc8a6ea3d41269d068c3ed71b4e2dca6448b9 Mon Sep 17 00:00:00 2001 From: Vasubabu <3358152+vasubabu@users.noreply.github.com> Date: Thu, 3 Aug 2023 21:41:31 +0530 Subject: [PATCH] Updated metal-go client for sub-commands Virtual Network --- internal/vlan/create.go | 27 +++++----- internal/vlan/delete.go | 5 +- internal/vlan/retrieve.go | 23 ++++++--- internal/vlan/vlan.go | 12 +++-- test/e2e/vlan/vlan_creat_test.go | 80 +++++++++++++++++++++++++++++ test/e2e/vlan/vlan_delete_test.go | 78 ++++++++++++++++++++++++++++ test/e2e/vlan/vlan_get_test.go | 85 +++++++++++++++++++++++++++++++ test/helper/helper.go | 27 +++++++++- 8 files changed, 310 insertions(+), 27 deletions(-) create mode 100644 test/e2e/vlan/vlan_creat_test.go create mode 100644 test/e2e/vlan/vlan_delete_test.go create mode 100644 test/e2e/vlan/vlan_get_test.go diff --git a/internal/vlan/create.go b/internal/vlan/create.go index f3476714..4318f026 100644 --- a/internal/vlan/create.go +++ b/internal/vlan/create.go @@ -21,10 +21,11 @@ package vlan import ( + "context" "fmt" "strconv" - "github.com/packethost/packngo" + metal "github.com/equinix-labs/metal-go/metal/v1" "github.com/spf13/cobra" ) @@ -45,28 +46,30 @@ func (c *Client) Create() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true - - req := &packngo.VirtualNetworkCreateRequest{ - ProjectID: projectID, - Metro: metro, - Facility: facility, - VXLAN: vxlan, + virtualNetworkCreateInput := metal.NewVirtualNetworkCreateInput() + if metro != "" { + virtualNetworkCreateInput.SetMetro(metro) + } + if facility != "" { + virtualNetworkCreateInput.SetFacility(facility) } + virtualNetworkCreateInput.SetVxlan(int32(vxlan)) + if description != "" { - req.Description = description + virtualNetworkCreateInput.Description = &description } - n, _, err := c.Service.Create(req) + n, _, err := c.Service.CreateVirtualNetwork(context.Background(), projectID).VirtualNetworkCreateInput(*virtualNetworkCreateInput).Execute() if err != nil { - return fmt.Errorf("Could not create ProjectVirtualNetwork: %w", err) + return fmt.Errorf("could not create ProjectVirtualNetwork: %w", err) } data := make([][]string, 1) // TODO(displague) metro is not in the response - data[0] = []string{n.ID, n.Description, strconv.Itoa(n.VXLAN), n.MetroCode, n.FacilityCode, n.CreatedAt} + data[0] = []string{n.GetId(), n.GetDescription(), strconv.Itoa(int(n.GetVxlan())), n.GetMetroCode(), n.CreatedAt.String()} - header := []string{"ID", "Description", "VXLAN", "Metro", "Facility", "Created"} + header := []string{"ID", "Description", "VXLAN", "Metro", "Created"} return c.Out.Output(n, header, &data) }, diff --git a/internal/vlan/delete.go b/internal/vlan/delete.go index 0156908a..e975a6ea 100644 --- a/internal/vlan/delete.go +++ b/internal/vlan/delete.go @@ -21,6 +21,7 @@ package vlan import ( + "context" "fmt" "github.com/manifoldco/promptui" @@ -34,7 +35,7 @@ func (c *Client) Delete() *cobra.Command { ) deleteVnet := func(id string) error { - _, err := c.Service.Delete(id) + _, _, err := c.Service.DeleteVirtualNetwork(context.Background(), vnetID).Execute() if err != nil { return err } @@ -70,7 +71,7 @@ func (c *Client) Delete() *cobra.Command { } } if err := deleteVnet(vnetID); err != nil { - return fmt.Errorf("Could not delete Virtual Network: %w", err) + return fmt.Errorf("could not delete Virtual Network: %w", err) } return nil }, diff --git a/internal/vlan/retrieve.go b/internal/vlan/retrieve.go index adfb211b..39d2945d 100644 --- a/internal/vlan/retrieve.go +++ b/internal/vlan/retrieve.go @@ -41,19 +41,28 @@ func (c *Client) Retrieve() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true - vnets, _, err := c.Service.List(projectID, c.Servicer.ListOptions(nil, nil)) + request := c.Service.FindVirtualNetworks(cmd.Context(), projectID).Include(c.Servicer.Includes(nil)).Exclude(c.Servicer.Excludes(nil)) + filters := c.Servicer.Filters() + if filters["facility"] != "" { + request = request.Facility(filters["facility"]) + } + + if filters["metro"] != "" { + request = request.Metro(filters["metro"]) + } + virtualNetworksList, _, err := request.Execute() if err != nil { return fmt.Errorf("Could not list Project Virtual Networks: %w", err) } + virtualNetworks := virtualNetworksList.GetVirtualNetworks() + data := make([][]string, len(virtualNetworks)) - data := make([][]string, len(vnets.VirtualNetworks)) - - for i, n := range vnets.VirtualNetworks { - data[i] = []string{n.ID, n.Description, strconv.Itoa(n.VXLAN), n.FacilityCode, n.CreatedAt} + for i, n := range virtualNetworks { + data[i] = []string{n.GetId(), n.GetDescription(), strconv.Itoa(int(n.GetVxlan())), n.GetMetroCode(), n.GetCreatedAt().String()} } - header := []string{"ID", "Description", "VXLAN", "Facility", "Created"} + header := []string{"ID", "Description", "VXLAN", "Metro", "Created"} - return c.Out.Output(vnets, header, &data) + return c.Out.Output(virtualNetworksList, header, &data) }, } retrieveVirtualNetworksCmd.Flags().StringVarP(&projectID, "project-id", "p", "", "The project's UUID. This flag is required, unless specified in the config created by metal init or set as METAL_PROJECT_ID environment variable.") diff --git a/internal/vlan/vlan.go b/internal/vlan/vlan.go index 2de94730..adbdd4c9 100644 --- a/internal/vlan/vlan.go +++ b/internal/vlan/vlan.go @@ -21,14 +21,14 @@ package vlan import ( + metal "github.com/equinix-labs/metal-go/metal/v1" "github.com/equinix/metal-cli/internal/outputs" - "github.com/packethost/packngo" "github.com/spf13/cobra" ) type Client struct { Servicer Servicer - Service packngo.ProjectVirtualNetworkService + Service metal.VLANsApiService Out outputs.Outputer } @@ -45,7 +45,7 @@ func (c *Client) NewCommand() *cobra.Command { root.PersistentPreRun(cmd, args) } } - c.Service = c.Servicer.API(cmd).ProjectVirtualNetworks + c.Service = *c.Servicer.MetalAPI(cmd).VLANsApi }, } @@ -58,8 +58,10 @@ func (c *Client) NewCommand() *cobra.Command { } type Servicer interface { - API(*cobra.Command) *packngo.Client - ListOptions(defaultIncludes, defaultExcludes []string) *packngo.ListOptions + MetalAPI(*cobra.Command) *metal.APIClient + Filters() map[string]string + Includes(defaultIncludes []string) (incl []string) + Excludes(defaultExcludes []string) (excl []string) } func NewClient(s Servicer, out outputs.Outputer) *Client { diff --git a/test/e2e/vlan/vlan_creat_test.go b/test/e2e/vlan/vlan_creat_test.go new file mode 100644 index 00000000..f244e044 --- /dev/null +++ b/test/e2e/vlan/vlan_creat_test.go @@ -0,0 +1,80 @@ +package vlan + +import ( + "io" + "os" + "strings" + "testing" + + root "github.com/equinix/metal-cli/internal/cli" + outputPkg "github.com/equinix/metal-cli/internal/outputs" + "github.com/equinix/metal-cli/internal/vlan" + "github.com/equinix/metal-cli/test/helper" + "github.com/spf13/cobra" +) + +func TestCli_Vlan_Create(t *testing.T) { + var projectId string + var err error + subCommand := "vlan" + consumerToken := "" + apiURL := "" + Version := "metal" + rootClient := root.NewClient(consumerToken, apiURL, Version) + type fields struct { + MainCmd *cobra.Command + Outputer outputPkg.Outputer + } + tests := []struct { + name string + fields fields + want *cobra.Command + cmdFunc func(*testing.T, *cobra.Command) + }{ + { + name: "create_virtual_network", + fields: fields{ + MainCmd: vlan.NewClient(rootClient, outputPkg.Outputer(&outputPkg.Standard{})).NewCommand(), + Outputer: outputPkg.Outputer(&outputPkg.Standard{}), + }, + want: &cobra.Command{}, + cmdFunc: func(t *testing.T, c *cobra.Command) { + root := c.Root() + projectId, err = helper.CreateTestProject("metal-cli-vlan-create-pro") + if err != nil { + t.Error(err) + } + if len(projectId) != 0 { + root.SetArgs([]string{subCommand, "create", "-p", projectId, "-m", "da", "--vxlan", "2023", "-d", "metal-cli-vlan-test"}) + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + if err := root.Execute(); err != nil { + t.Error(err) + } + w.Close() + out, _ := io.ReadAll(r) + os.Stdout = rescueStdout + if !strings.Contains(string(out[:]), "metal-cli-vlan-test") && + !strings.Contains(string(out[:]), "da") && + !strings.Contains(string(out[:]), "2023") { + t.Error("expected output should include metal-cli-vlan-test, da and 2023 strings in the out string") + } + + err = helper.CleanTestProject(projectId) + if err != nil { + t.Error(err) + } + } + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rootCmd := rootClient.NewCommand() + rootCmd.AddCommand(tt.fields.MainCmd) + tt.cmdFunc(t, tt.fields.MainCmd) + }) + } +} diff --git a/test/e2e/vlan/vlan_delete_test.go b/test/e2e/vlan/vlan_delete_test.go new file mode 100644 index 00000000..653274a1 --- /dev/null +++ b/test/e2e/vlan/vlan_delete_test.go @@ -0,0 +1,78 @@ +package vlan + +import ( + "io" + "os" + "strings" + "testing" + + root "github.com/equinix/metal-cli/internal/cli" + outputPkg "github.com/equinix/metal-cli/internal/outputs" + "github.com/equinix/metal-cli/internal/vlan" + "github.com/equinix/metal-cli/test/helper" + "github.com/spf13/cobra" +) + +func TestCli_Vlan_Clean(t *testing.T) { + var projectId, vlanId string + var err error + subCommand := "vlan" + consumerToken := "" + apiURL := "" + Version := "metal" + rootClient := root.NewClient(consumerToken, apiURL, Version) + type fields struct { + MainCmd *cobra.Command + Outputer outputPkg.Outputer + } + tests := []struct { + name string + fields fields + want *cobra.Command + cmdFunc func(*testing.T, *cobra.Command) + }{ + { + name: "delete_virtual_network", + fields: fields{ + MainCmd: vlan.NewClient(rootClient, outputPkg.Outputer(&outputPkg.Standard{})).NewCommand(), + Outputer: outputPkg.Outputer(&outputPkg.Standard{}), + }, + want: &cobra.Command{}, + cmdFunc: func(t *testing.T, c *cobra.Command) { + root := c.Root() + projectId, err = helper.CreateTestProject("metal-cli-vlan-get-pro") + if err != nil { + t.Error(err) + } + vlanId, err = helper.CreateTestVlan(projectId, 2023, "metal-cli-vlan-get-test") + if len(projectId) != 0 && len(vlanId) != 0 { + root.SetArgs([]string{subCommand, "delete", "-f", "-i", vlanId}) + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + if err := root.Execute(); err != nil { + t.Error(err) + } + w.Close() + out, _ := io.ReadAll(r) + os.Stdout = rescueStdout + if !strings.Contains(string(out[:]), "Virtual Network "+vlanId+" successfully deleted.") { + t.Error("expected output should include Virtual Network " + vlanId + "successfully deleted." + "in the out string") + } + err = helper.CleanTestProject(projectId) + if err != nil { + t.Error(err) + } + } + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rootCmd := rootClient.NewCommand() + rootCmd.AddCommand(tt.fields.MainCmd) + tt.cmdFunc(t, tt.fields.MainCmd) + }) + } +} diff --git a/test/e2e/vlan/vlan_get_test.go b/test/e2e/vlan/vlan_get_test.go new file mode 100644 index 00000000..c06c5862 --- /dev/null +++ b/test/e2e/vlan/vlan_get_test.go @@ -0,0 +1,85 @@ +package vlan + +import ( + "io" + "os" + "strings" + "testing" + + root "github.com/equinix/metal-cli/internal/cli" + outputPkg "github.com/equinix/metal-cli/internal/outputs" + "github.com/equinix/metal-cli/internal/vlan" + "github.com/equinix/metal-cli/test/helper" + "github.com/spf13/cobra" +) + +func TestCli_Vlan_Get(t *testing.T) { + var projectId, vlanId string + var err error + subCommand := "vlan" + consumerToken := "" + apiURL := "" + Version := "metal" + rootClient := root.NewClient(consumerToken, apiURL, Version) + type fields struct { + MainCmd *cobra.Command + Outputer outputPkg.Outputer + } + tests := []struct { + name string + fields fields + want *cobra.Command + cmdFunc func(*testing.T, *cobra.Command) + }{ + { + name: "get_virtual_network", + fields: fields{ + MainCmd: vlan.NewClient(rootClient, outputPkg.Outputer(&outputPkg.Standard{})).NewCommand(), + Outputer: outputPkg.Outputer(&outputPkg.Standard{}), + }, + want: &cobra.Command{}, + cmdFunc: func(t *testing.T, c *cobra.Command) { + root := c.Root() + projectId, err = helper.CreateTestProject("metal-cli-vlan-delete-pro") + if err != nil { + t.Error(err) + } + vlanId, err = helper.CreateTestVlan(projectId, 2023, "metal-cli-vlan-delete-test") + if len(projectId) != 0 && len(vlanId) != 0 { + root.SetArgs([]string{subCommand, "get", "-p", projectId}) + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + if err := root.Execute(); err != nil { + t.Error(err) + } + w.Close() + out, _ := io.ReadAll(r) + os.Stdout = rescueStdout + if !strings.Contains(string(out[:]), "metal-cli-vlan-get-test") && + !strings.Contains(string(out[:]), "da") && + !strings.Contains(string(out[:]), "2023") { + t.Error("expected output should include metal-cli-vlan-get-test, da and 2023 strings in the out string") + } + + err = helper.CleanTestVlan(vlanId) + if err != nil { + t.Error(err) + } + err = helper.CleanTestProject(projectId) + if err != nil { + t.Error(err) + } + } + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rootCmd := rootClient.NewCommand() + rootCmd.AddCommand(tt.fields.MainCmd) + tt.cmdFunc(t, tt.fields.MainCmd) + }) + } +} diff --git a/test/helper/helper.go b/test/helper/helper.go index 3bbb2f5f..0cb143dc 100644 --- a/test/helper/helper.go +++ b/test/helper/helper.go @@ -128,7 +128,7 @@ func CreateTestIps(projectId string, quantity int, ipType string) (string, error ipsresp, _, err := TestApiClient.IPAddressesApi.RequestIPReservation(context.Background(), projectId).RequestIPReservationRequest(*requestIPReservationRequest).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `VLANsApi.CreateVirtualNetwork``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `IPAddressesApi.FindIPReservations``: %v\n", err) return "", err } return ipsresp.IPReservation.GetId(), nil @@ -143,3 +143,28 @@ func CleanTestIps(ipsId string) error { } return nil } + +func CreateTestVlan(projectId string, Id int, desc string) (string, error) { + TestApiClient := TestClient() + virtualNetworkCreateInput := *openapiclient.NewVirtualNetworkCreateInput() + virtualNetworkCreateInput.SetDescription(desc) + virtualNetworkCreateInput.SetMetro("da") + virtualNetworkCreateInput.SetVxlan(int32(Id)) + + vlanresp, _, err := TestApiClient.VLANsApi.CreateVirtualNetwork(context.Background(), projectId).VirtualNetworkCreateInput(virtualNetworkCreateInput).Execute() + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `VLANsApi.CreateVirtualNetwork``: %v\n", err) + return "", err + } + return vlanresp.GetId(), nil +} + +func CleanTestVlan(vlanId string) error { + TestApiClient := TestClient() + _, _, err := TestApiClient.VLANsApi.DeleteVirtualNetwork(context.Background(), vlanId).Execute() + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `VLANsApi.DeleteVirtualNetwork``: %v\n", err) + return err + } + return nil +}