Skip to content

Commit ebaebc0

Browse files
Migrate metal ports subcommand cli to metal-go from packngo
Signed-off-by: Ayush Rangwala <[email protected]>
1 parent de1378f commit ebaebc0

File tree

8 files changed

+474
-33
lines changed

8 files changed

+474
-33
lines changed

internal/ports/convert.go

+13-17
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ import (
3535
func (c *Client) Convert() *cobra.Command {
3636
var portID string
3737
var bonded, layer2, bulk, force, ipv4, ipv6 bool
38-
// retrievePortCmd represents the retrievePort command
39-
retrievePortCmd := &cobra.Command{
38+
convertPortCmd := &cobra.Command{
4039
Use: `convert -i <port_UUID> [--bonded] [--bulk] --layer2 [--force] [--public-ipv4] [--public-ipv6]`,
4140
Aliases: []string{},
4241
Short: "Converts a list of ports or the details of the specified port.",
@@ -87,7 +86,10 @@ func (c *Client) Convert() *cobra.Command {
8786
return nil, nil, nil
8887
}
8988
}
90-
return c.PortService.ConvertLayer2(context.Background(), portID).Execute()
89+
90+
return c.PortService.ConvertLayer2(context.Background(), portID).
91+
PortAssignInput(*metal.NewPortAssignInput()).
92+
Execute()
9193
}
9294
convToL3 := func(portID string) (*metal.Port, *http.Response, error) {
9395
log.Printf("Converting port %s to layer-3 with addresses %v", portID, addrs)
@@ -105,8 +107,6 @@ func (c *Client) Convert() *cobra.Command {
105107

106108
port, _, err := c.PortService.FindPortById(context.Background(), portID).
107109
Include(c.Servicer.Includes(nil)).
108-
// TODO: uncomment this when metal api supports it
109-
// Exclude(c.Servicer.Excludes(nil)).
110110
Execute()
111111
if err != nil {
112112
return fmt.Errorf("Could not get Port: %w", err)
@@ -121,31 +121,27 @@ func (c *Client) Convert() *cobra.Command {
121121
},
122122
}
123123

124-
retrievePortCmd.Flags().StringVarP(&portID, "port-id", "i", "", "The UUID of a port.")
125-
retrievePortCmd.Flags().BoolVarP(&bonded, "bonded", "b", false, "Convert to layer-2 bonded.")
126-
retrievePortCmd.Flags().BoolVarP(&bulk, "bulk", "", false, "Affect both ports in a bond.")
127-
retrievePortCmd.Flags().BoolVarP(&layer2, "layer2", "2", false, "Convert to layer-2 unbonded.")
128-
retrievePortCmd.Flags().BoolVarP(&force, "force", "f", false, "Force conversion to layer-2 bonded.")
129-
retrievePortCmd.Flags().BoolVarP(&ipv4, "public-ipv4", "4", false, "Convert to layer-2 bonded with public IPv4.")
130-
retrievePortCmd.Flags().BoolVarP(&ipv6, "public-ipv6", "6", false, "Convert to layer-2 bonded with public IPv6.")
124+
convertPortCmd.Flags().StringVarP(&portID, "port-id", "i", "", "The UUID of a port.")
125+
convertPortCmd.Flags().BoolVarP(&bonded, "bonded", "b", false, "Convert to layer-2 bonded.")
126+
convertPortCmd.Flags().BoolVarP(&bulk, "bulk", "", false, "Affect both ports in a bond.")
127+
convertPortCmd.Flags().BoolVarP(&layer2, "layer2", "2", false, "Convert to layer-2 unbonded.")
128+
convertPortCmd.Flags().BoolVarP(&force, "force", "f", false, "Force conversion to layer-2 bonded.")
129+
convertPortCmd.Flags().BoolVarP(&ipv4, "public-ipv4", "4", false, "Convert to layer-2 bonded with public IPv4.")
130+
convertPortCmd.Flags().BoolVarP(&ipv6, "public-ipv6", "6", false, "Convert to layer-2 bonded with public IPv6.")
131131

132-
return retrievePortCmd
132+
return convertPortCmd
133133
}
134134

135135
func portBondingHandler(cmd *cobra.Command, c *Client, portId string) error {
136136
if cmd.Flag("bonded").Changed {
137137
_, _, err := c.PortService.BondPort(context.Background(), portId).
138138
Include(c.Servicer.Includes(nil)).
139-
// TODO: uncomment this when metal api supports it
140-
// Exclude(c.Servicer.Excludes(nil)).
141139
Execute()
142140
return err
143141
}
144142

145143
_, _, err := c.PortService.DisbondPort(context.Background(), portId).
146144
Include(c.Servicer.Includes(nil)).
147-
// TODO: uncomment this when metal api supports it
148-
// Exclude(c.Servicer.Excludes(nil)).
149145
Execute()
150146
return err
151147
}

internal/ports/port.go

-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ type Servicer interface {
6262
MetalAPI(*cobra.Command) *metal.APIClient
6363
Filters() map[string]string
6464
Includes(defaultIncludes []string) (incl []string)
65-
Excludes(defaultExcludes []string) (excl []string)
6665
}
6766

6867
func NewClient(s Servicer, out outputs.Outputer) *Client {

internal/ports/retrieve.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@ func (c *Client) Retrieve() *cobra.Command {
4242
RunE: func(cmd *cobra.Command, args []string) error {
4343
cmd.SilenceUsage = true
4444
port, _, err := c.PortService.FindPortById(context.Background(), portID).
45-
Include(c.Servicer.Excludes(nil)).
46-
// TODO: uncomment this when metal api supports it
47-
// Exclude(c.Servicer.Excludes(nil)).
45+
Include(c.Servicer.Includes(nil)).
4846
Execute()
4947
if err != nil {
5048
return fmt.Errorf("Could not get Port: %w", err)

internal/ports/vlans.go

-2
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ func (c *Client) Vlans() *cobra.Command {
7979
batch, _, err := c.PortService.CreatePortVlanAssignmentBatch(context.Background(), portID).
8080
PortVlanAssignmentBatchCreateInput(*req).
8181
Include(c.Servicer.Includes([]string{"port"})).
82-
// TODO: uncomment this when metal api supports it
83-
// Exclude(c.Servicer.Excludes(nil)).
8482
Execute()
8583
if err != nil {
8684
return fmt.Errorf("Could not update port VLAN assignments: %w", err)
+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package convert
2+
3+
import (
4+
"io"
5+
"os"
6+
"strconv"
7+
"strings"
8+
"testing"
9+
10+
root "github.com/equinix/metal-cli/internal/cli"
11+
outputPkg "github.com/equinix/metal-cli/internal/outputs"
12+
"github.com/equinix/metal-cli/internal/ports"
13+
"github.com/equinix/metal-cli/test/helper"
14+
15+
"github.com/spf13/cobra"
16+
)
17+
18+
func TestPorts_Convert(t *testing.T) {
19+
var projectId, deviceId *string
20+
subCommand := "port"
21+
consumerToken := ""
22+
apiURL := ""
23+
Version := "devel"
24+
rootClient := root.NewClient(consumerToken, apiURL, Version)
25+
tests := []struct {
26+
name string
27+
cmd *cobra.Command
28+
want *cobra.Command
29+
cmdFunc func(*testing.T, *cobra.Command)
30+
}{
31+
{
32+
name: "convert port",
33+
cmd: ports.NewClient(rootClient, outputPkg.Outputer(&outputPkg.Standard{})).NewCommand(),
34+
want: &cobra.Command{},
35+
cmdFunc: func(t *testing.T, c *cobra.Command) {
36+
root := c.Root()
37+
projId, err := helper.CreateTestProject("metal-cli-test-ports-project")
38+
if err != nil {
39+
t.Error(err)
40+
}
41+
projectId = &projId
42+
43+
devId, err := helper.CreateTestDevice(*projectId, "metal-cli-test-ports-device")
44+
if err != nil {
45+
t.Error(err)
46+
}
47+
deviceId = &devId
48+
49+
device, err := helper.GetDeviceById(*deviceId)
50+
if len(device.NetworkPorts) < 3 {
51+
t.Errorf("All 3 ports doesnot exist for the created device: %s", device.GetId())
52+
}
53+
port := device.GetNetworkPorts()[2]
54+
55+
active, err := helper.IsDeviceStateActive(*deviceId)
56+
if err == nil && active {
57+
root.SetArgs([]string{subCommand, "convert", "-i", port.GetId(), "--layer2", "--bonded", "--force"})
58+
59+
rescueStdout := os.Stdout
60+
r, w, _ := os.Pipe()
61+
os.Stdout = w
62+
if err := root.Execute(); err != nil {
63+
t.Error(err)
64+
}
65+
w.Close()
66+
out, _ := io.ReadAll(r)
67+
os.Stdout = rescueStdout
68+
69+
if !strings.Contains(string(out[:]), port.GetId()) {
70+
t.Errorf("cmd output should contain ID of the port: %s", port.GetId())
71+
}
72+
73+
if !strings.Contains(string(out[:]), port.GetName()) {
74+
t.Errorf("cmd output should contain name of the port: %s", port.GetName())
75+
}
76+
77+
if !strings.Contains(string(out[:]), string(port.GetType())) {
78+
t.Errorf("cmd output should contain type of the port: %s", string(port.GetType()))
79+
}
80+
81+
if !strings.Contains(string(out[:]), strconv.FormatBool(port.Data.GetBonded())) {
82+
t.Errorf("cmd output should contain if port is bonded: %s", strconv.FormatBool(port.Data.GetBonded()))
83+
}
84+
85+
if err := helper.DeletePort(port.GetId()); err != nil {
86+
t.Error(err)
87+
}
88+
if err := helper.DeleteVLAN(port.GetId()); err != nil {
89+
t.Error(err)
90+
}
91+
if err := helper.CleanupProjectAndDevice(deviceId, projectId); err != nil {
92+
t.Error(err)
93+
}
94+
}
95+
},
96+
},
97+
}
98+
99+
for _, tt := range tests {
100+
t.Run(tt.name, func(t *testing.T) {
101+
rootCmd := rootClient.NewCommand()
102+
rootCmd.AddCommand(tt.cmd)
103+
tt.cmdFunc(t, tt.cmd)
104+
})
105+
}
106+
}
107+
108+
func cleanup(t *testing.T, deviceId, projectId *string) {
109+
resp, err := helper.IsDeviceStateActive(*deviceId)
110+
if err == nil && resp == true {
111+
err = helper.CleanTestDevice(*deviceId)
112+
if err != nil {
113+
t.Error(err)
114+
}
115+
err = helper.CleanTestProject(*projectId)
116+
if err != nil {
117+
t.Error(err)
118+
}
119+
}
120+
}
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package retrieve
2+
3+
import (
4+
"io"
5+
"os"
6+
"strconv"
7+
"strings"
8+
"testing"
9+
10+
root "github.com/equinix/metal-cli/internal/cli"
11+
outputPkg "github.com/equinix/metal-cli/internal/outputs"
12+
"github.com/equinix/metal-cli/internal/ports"
13+
"github.com/equinix/metal-cli/test/helper"
14+
15+
"github.com/spf13/cobra"
16+
)
17+
18+
func TestPorts_Retrieve(t *testing.T) {
19+
var projectId, deviceId *string
20+
subCommand := "port"
21+
consumerToken := ""
22+
apiURL := ""
23+
Version := "devel"
24+
rootClient := root.NewClient(consumerToken, apiURL, Version)
25+
tests := []struct {
26+
name string
27+
cmd *cobra.Command
28+
want *cobra.Command
29+
cmdFunc func(*testing.T, *cobra.Command)
30+
}{
31+
{
32+
name: "retrieve port",
33+
cmd: ports.NewClient(rootClient, outputPkg.Outputer(&outputPkg.Standard{})).NewCommand(),
34+
want: &cobra.Command{},
35+
cmdFunc: func(t *testing.T, c *cobra.Command) {
36+
root := c.Root()
37+
projId, err := helper.CreateTestProject("metal-cli-test-ports-project")
38+
if err != nil {
39+
t.Error(err)
40+
}
41+
projectId = &projId
42+
43+
devId, err := helper.CreateTestDevice(*projectId, "metal-cli-test-ports-device")
44+
if err != nil {
45+
t.Error(err)
46+
}
47+
deviceId = &devId
48+
49+
device, err := helper.GetDeviceById(*deviceId)
50+
51+
if len(device.NetworkPorts) == 0 {
52+
t.Errorf("ports doesnot exist for the created device: %s", device.GetId())
53+
}
54+
55+
port := device.GetNetworkPorts()[0]
56+
root.SetArgs([]string{subCommand, "get", "-i", port.GetId()})
57+
58+
rescueStdout := os.Stdout
59+
r, w, _ := os.Pipe()
60+
os.Stdout = w
61+
if err := root.Execute(); err != nil {
62+
t.Error(err)
63+
}
64+
w.Close()
65+
out, _ := io.ReadAll(r)
66+
os.Stdout = rescueStdout
67+
68+
if !strings.Contains(string(out[:]), port.GetId()) {
69+
t.Errorf("cmd output should contain ID of the port: %s", port.GetId())
70+
}
71+
72+
if !strings.Contains(string(out[:]), port.GetName()) {
73+
t.Errorf("cmd output should contain name of the port: %s", port.GetName())
74+
}
75+
76+
if !strings.Contains(string(out[:]), string(port.GetType())) {
77+
t.Errorf("cmd output should contain type of the port: %s", string(port.GetType()))
78+
}
79+
80+
if !strings.Contains(string(out[:]), port.Data.GetMac()) {
81+
t.Errorf("cmd output should contain MAC address of the port: %s", port.Data.GetMac())
82+
}
83+
84+
if !strings.Contains(string(out[:]), strconv.FormatBool(port.Data.GetBonded())) {
85+
t.Errorf("cmd output should contain if port is bonded: %s", strconv.FormatBool(port.Data.GetBonded()))
86+
}
87+
88+
if err := helper.CleanupProjectAndDevice(deviceId, projectId); err != nil {
89+
t.Error(err)
90+
}
91+
},
92+
},
93+
}
94+
95+
for _, tt := range tests {
96+
t.Run(tt.name, func(t *testing.T) {
97+
rootCmd := rootClient.NewCommand()
98+
rootCmd.AddCommand(tt.cmd)
99+
tt.cmdFunc(t, tt.cmd)
100+
})
101+
}
102+
}

0 commit comments

Comments
 (0)