diff --git a/internal/ports/convert.go b/internal/ports/convert.go index 5e603db9..39965133 100644 --- a/internal/ports/convert.go +++ b/internal/ports/convert.go @@ -21,12 +21,14 @@ package ports import ( + "context" "fmt" "log" + "net/http" "strconv" + metal "github.com/equinix-labs/metal-go/metal/v1" "github.com/manifoldco/promptui" - "github.com/packethost/packngo" "github.com/spf13/cobra" ) @@ -54,25 +56,26 @@ func (c *Client) Convert() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true - if f := cmd.Flag("bonded"); f.Changed { - _, _, err := map[bool]func(string, bool) (*packngo.Port, *packngo.Response, error){ - true: c.PortService.Bond, - false: c.PortService.Disbond, - }[bonded](portID, bulk) - if err != nil { - return fmt.Errorf("failed to change port bonding: %w", err) - } + if err := portBondingHandler(cmd, c, portID); err != nil { + return fmt.Errorf("failed to change port bonding: %w", err) } - addrs := []packngo.AddressRequest{{AddressFamily: 4, Public: false}} + + addressFamily := metal.IPAddressAddressFamily(4) + public := false + addrs := []metal.IPAddress{{AddressFamily: &addressFamily, Public: &public}} if f := cmd.Flag("public-ipv4"); f.Changed { - addrs = append(addrs, packngo.AddressRequest{AddressFamily: 4, Public: true}) + addressFamily = metal.IPAddressAddressFamily(4) + public = true + addrs = append(addrs, metal.IPAddress{AddressFamily: &addressFamily, Public: &public}) } if f := cmd.Flag("public-ipv6"); f.Changed { - addrs = append(addrs, packngo.AddressRequest{AddressFamily: 6, Public: true}) + addressFamily = metal.IPAddressAddressFamily(6) + public = true + addrs = append(addrs, metal.IPAddress{AddressFamily: &addressFamily, Public: &public}) } - convToL2 := func(portID string) (*packngo.Port, *packngo.Response, error) { + convToL2 := func(portID string) (*metal.Port, *http.Response, error) { if !force { prompt := promptui.Prompt{ Label: fmt.Sprintf("Are you sure you want to convert Port %s to Layer2 and remove assigned IP addresses: ", portID), @@ -84,14 +87,14 @@ func (c *Client) Convert() *cobra.Command { return nil, nil, nil } } - return c.PortService.ConvertToLayerTwo(portID) + return c.PortService.ConvertLayer2(context.Background(), portID).Execute() } - convToL3 := func(portID string) (*packngo.Port, *packngo.Response, error) { + convToL3 := func(portID string) (*metal.Port, *http.Response, error) { log.Printf("Converting port %s to layer-3 with addresses %v", portID, addrs) - return c.PortService.ConvertToLayerThree(portID, addrs) + return c.PortService.ConvertLayer3(context.Background(), portID).Execute() } if f := cmd.Flag("layer2"); f.Changed { - _, _, err := map[bool]func(string) (*packngo.Port, *packngo.Response, error){ + _, _, err := map[bool]func(string) (*metal.Port, *http.Response, error){ true: convToL2, false: convToL3, }[layer2](portID) @@ -99,17 +102,19 @@ func (c *Client) Convert() *cobra.Command { return fmt.Errorf("failed to change port network mode: %w", err) } } - listOpts := c.Servicer.ListOptions(nil, nil) - getOpts := &packngo.GetOptions{Includes: listOpts.Includes, Excludes: listOpts.Excludes} - port, _, err := c.PortService.Get(portID, getOpts) + port, _, err := c.PortService.FindPortById(context.Background(), portID). + Include(c.Servicer.Includes(nil)). + // TODO: uncomment this when metal api supports it + // Exclude(c.Servicer.Excludes(nil)). + Execute() if err != nil { return fmt.Errorf("Could not get Port: %w", err) } data := make([][]string, 1) - data[0] = []string{port.ID, port.Name, port.Type, port.NetworkType, port.Data.MAC, strconv.FormatBool(port.Data.Bonded)} + data[0] = []string{port.GetId(), port.GetName(), string(port.GetType()), string(port.GetNetworkType()), port.Data.GetMac(), strconv.FormatBool(port.Data.GetBonded())} header := []string{"ID", "Name", "Type", "Network Type", "MAC", "Bonded"} return c.Out.Output(port, header, &data) @@ -126,3 +131,21 @@ func (c *Client) Convert() *cobra.Command { return retrievePortCmd } + +func portBondingHandler(cmd *cobra.Command, c *Client, portId string) error { + if cmd.Flag("bonded").Changed { + _, _, err := c.PortService.BondPort(context.Background(), portId). + Include(c.Servicer.Includes(nil)). + // TODO: uncomment this when metal api supports it + // Exclude(c.Servicer.Excludes(nil)). + Execute() + return err + } + + _, _, err := c.PortService.DisbondPort(context.Background(), portId). + Include(c.Servicer.Includes(nil)). + // TODO: uncomment this when metal api supports it + // Exclude(c.Servicer.Excludes(nil)). + Execute() + return err +} diff --git a/internal/ports/port.go b/internal/ports/port.go index cab7b46f..0ceabe5e 100644 --- a/internal/ports/port.go +++ b/internal/ports/port.go @@ -21,15 +21,15 @@ package ports 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 - PortService packngo.PortService - VLANService packngo.VLANAssignmentService + PortService *metal.PortsApiService + VLANService *metal.VLANsApiService Out outputs.Outputer } @@ -45,8 +45,8 @@ func (c *Client) NewCommand() *cobra.Command { root.PersistentPreRun(cmd, args) } } - c.PortService = c.Servicer.API(cmd).Ports - c.VLANService = c.Servicer.API(cmd).VLANAssignments + c.PortService = c.Servicer.MetalAPI(cmd).PortsApi + c.VLANService = c.Servicer.MetalAPI(cmd).VLANsApi }, } @@ -59,8 +59,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/internal/ports/retrieve.go b/internal/ports/retrieve.go index 89f8c36e..842d2723 100644 --- a/internal/ports/retrieve.go +++ b/internal/ports/retrieve.go @@ -21,10 +21,10 @@ package ports import ( + "context" "fmt" "strconv" - "github.com/packethost/packngo" "github.com/spf13/cobra" ) @@ -41,17 +41,18 @@ func (c *Client) Retrieve() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true - listOpts := c.Servicer.ListOptions(nil, nil) - - getOpts := &packngo.GetOptions{Includes: listOpts.Includes, Excludes: listOpts.Excludes} - port, _, err := c.PortService.Get(portID, getOpts) + port, _, err := c.PortService.FindPortById(context.Background(), portID). + Include(c.Servicer.Excludes(nil)). + // TODO: uncomment this when metal api supports it + // Exclude(c.Servicer.Excludes(nil)). + Execute() if err != nil { return fmt.Errorf("Could not get Port: %w", err) } data := make([][]string, 1) - data[0] = []string{port.ID, port.Name, port.Type, port.NetworkType, port.Data.MAC, strconv.FormatBool(port.Data.Bonded)} + data[0] = []string{port.GetId(), port.GetName(), string(port.GetType()), string(port.GetNetworkType()), port.Data.GetMac(), strconv.FormatBool(port.Data.GetBonded())} header := []string{"ID", "Name", "Type", "Network Type", "MAC", "Bonded"} return c.Out.Output(port, header, &data) diff --git a/internal/ports/vlans.go b/internal/ports/vlans.go index 9ad6b588..cc192b9e 100644 --- a/internal/ports/vlans.go +++ b/internal/ports/vlans.go @@ -21,11 +21,12 @@ package ports import ( + "context" "errors" "fmt" "strconv" - "github.com/packethost/packngo" + metal "github.com/equinix-labs/metal-go/metal/v1" "github.com/spf13/cobra" ) @@ -50,38 +51,47 @@ func (c *Client) Vlans() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true - listOpts := c.Servicer.ListOptions([]string{"port"}, nil) + req := metal.NewPortVlanAssignmentBatchCreateInput() - getOpts := &packngo.GetOptions{Includes: listOpts.Includes, Excludes: listOpts.Excludes} - req := &packngo.VLANAssignmentBatchCreateRequest{} - f := false - t := true for _, vlan := range assignments { - assignment := packngo.VLANAssignmentCreateRequest{VLAN: vlan, State: packngo.VLANAssignmentAssigned, Native: &f} - req.VLANAssignments = append(req.VLANAssignments, assignment) + CreateInputVlanAssignmentsInner := metal.PortVlanAssignmentBatchCreateInputVlanAssignmentsInner{} + CreateInputVlanAssignmentsInner.SetVlan(vlan) + CreateInputVlanAssignmentsInner.SetState(metal.PORTVLANASSIGNMENTBATCHVLANASSIGNMENTSINNERSTATE_ASSIGNED) + req.SetVlanAssignments(append(req.GetVlanAssignments(), CreateInputVlanAssignmentsInner)) } for _, vlan := range unassignments { - assignment := packngo.VLANAssignmentCreateRequest{VLAN: vlan, State: packngo.VLANAssignmentUnassigned} - req.VLANAssignments = append(req.VLANAssignments, assignment) + CreateInputVlanAssignmentsInner := metal.PortVlanAssignmentBatchCreateInputVlanAssignmentsInner{} + CreateInputVlanAssignmentsInner.SetVlan(vlan) + CreateInputVlanAssignmentsInner.SetState(metal.PORTVLANASSIGNMENTBATCHVLANASSIGNMENTSINNERSTATE_UNASSIGNED) + req.SetVlanAssignments(append(req.GetVlanAssignments(), CreateInputVlanAssignmentsInner)) } if native != "" { - assignment := packngo.VLANAssignmentCreateRequest{VLAN: native, State: packngo.VLANAssignmentAssigned, Native: &t} - req.VLANAssignments = append(req.VLANAssignments, assignment) + CreateInputVlanAssignmentsInner := metal.PortVlanAssignmentBatchCreateInputVlanAssignmentsInner{} + CreateInputVlanAssignmentsInner.SetVlan(native) + CreateInputVlanAssignmentsInner.SetState(metal.PORTVLANASSIGNMENTBATCHVLANASSIGNMENTSINNERSTATE_ASSIGNED) + CreateInputVlanAssignmentsInner.SetNative(true) + req.SetVlanAssignments(append(req.GetVlanAssignments(), CreateInputVlanAssignmentsInner)) } - if len(req.VLANAssignments) == 0 { + + if len(req.GetVlanAssignments()) == 0 { return errors.New("no VLAN assignments specified") } - batch, _, err := c.VLANService.CreateBatch(portID, req, getOpts) + batch, _, err := c.PortService.CreatePortVlanAssignmentBatch(context.Background(), portID). + PortVlanAssignmentBatchCreateInput(*req). + Include(c.Servicer.Includes([]string{"port"})). + // TODO: uncomment this when metal api supports it + // Exclude(c.Servicer.Excludes(nil)). + Execute() if err != nil { return fmt.Errorf("Could not update port VLAN assignments: %w", err) } // TODO: should we return the batch? - port := batch.Port + port := batch.GetPort() data := make([][]string, 1) - data[0] = []string{port.ID, port.Name, port.Type, port.NetworkType, port.Data.MAC, strconv.FormatBool(port.Data.Bonded)} + data[0] = []string{port.GetId(), port.GetName(), string(port.GetType()), string(port.GetNetworkType()), port.Data.GetMac(), strconv.FormatBool(port.Data.GetBonded())} header := []string{"ID", "Name", "Type", "Network Type", "MAC", "Bonded"} return c.Out.Output(port, header, &data)