Skip to content

Commit

Permalink
refactor volumes to demonstrate how globals could be avoided
Browse files Browse the repository at this point in the history
  • Loading branch information
displague committed Jul 22, 2020
1 parent 8a57c21 commit b008890
Show file tree
Hide file tree
Showing 19 changed files with 684 additions and 326 deletions.
99 changes: 46 additions & 53 deletions cmd/cli.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,56 @@
package cmd

import (
"encoding/json"
"fmt"
"os"

"github.com/ghodss/yaml"
"github.com/olekukonko/tablewriter"
"github.com/packethost/packngo"
"github.com/spf13/cobra"

"github.com/packethost/packet-cli/cmd/volume"
outputPkg "github.com/packethost/packet-cli/pkg/output"
)

// Cli struct
type Cli struct {
Client *packngo.Client
MainCmd *cobra.Command
Client *packngo.Client
MainCmd *cobra.Command
Outputer outputPkg.Outputer
}

// VERSION build
var (
Version string = "0.0.7"
)

func output(in interface{}, header []string, data *[][]string) {
format := outputPkg.FormatText

// TODO(displague) remove isJSON and isYaml globals
switch {
case isJSON:
format = outputPkg.FormatJSON
case isYaml:
format = outputPkg.FormatYAML
}
output := &outputPkg.Standard{Format: format}
output.Output(in, header, data)
}

func outputMergingCells(in interface{}, header []string, data *[][]string) {
format := outputPkg.FormatText

// TODO(displague) remove isJSON and isYaml globals
switch {
case isJSON:
format = outputPkg.FormatJSON
case isYaml:
format = outputPkg.FormatYAML
}
output := &outputPkg.CellMerging{Format: format}
output.Output(in, header, data)
}

// NewCli struct
func NewCli() *Cli {
var err error
Expand All @@ -31,60 +60,24 @@ func NewCli() *Cli {
fmt.Println("Client error:", err)
return nil
}

cli.MainCmd = rootCmd
cli.Outputer = &outputPkg.Standard{}
cli.RegisterCommands()
rootCmd.Execute()
rootCmd.DisableSuggestions = false
cli.MainCmd = rootCmd
return cli
}

func output(in interface{}, header []string, data *[][]string) {
if !isJSON && !isYaml {

table := tablewriter.NewWriter(os.Stdout)
table.SetAutoWrapText(false)
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetHeader(header)
table.AppendBulk(*data)
table.Render()
} else if isJSON {
output, err := json.MarshalIndent(in, "", " ")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(output))
} else if isYaml {
output, err := yaml.Marshal(in)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(output))
}
type Registrar interface {
Register(*cobra.Command, outputPkg.Outputer)
}

func outputMergingCells(in interface{}, header []string, data *[][]string) {
if !isJSON && !isYaml {

table := tablewriter.NewWriter(os.Stdout)
table.SetAutoMergeCells(true)
table.SetRowLine(true)
table.SetHeader(header)
table.AppendBulk(*data)
table.Render()
} else if isJSON {
output, err := json.MarshalIndent(in, "", " ")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(output))
} else if isYaml {
output, err := yaml.Marshal(in)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(output))
func (cli *Cli) RegisterCommands() {
c := cli.Client
for _, reggie := range []Registrar{
&volume.VolumeClient{VolumeService: c.Volumes, VolumeAttachmentService: c.VolumeAttachments},
} {
reggie.Register(cli.MainCmd, cli.Outputer)
}
}
89 changes: 0 additions & 89 deletions cmd/create_volume.go

This file was deleted.

2 changes: 2 additions & 0 deletions cmd/retrieve_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ packet event get
},
}

var volumeID string

func init() {
eventCmd.AddCommand(retrieveEventCmd)
retrieveEventCmd.Flags().StringVarP(&eventID, "id", "i", "", "UUID of the event")
Expand Down
49 changes: 28 additions & 21 deletions cmd/attach_volume.go → cmd/volume/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,49 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package cmd
package volume

import (
"fmt"

"github.com/packethost/packet-cli/pkg/output"
"github.com/packethost/packngo"
"github.com/spf13/cobra"
)

// attachVolumeCmd represents the attachVolume command
var attachVolumeCmd = &cobra.Command{
Use: "attach",
Short: "Attaches a volume to a device.",
Long: `Example:
packet volume attach --id [volume_UUID] --device-id [device_UUID]
`,
Run: func(cmd *cobra.Command, args []string) {
a, _, err := PacknGo.VolumeAttachments.Create(volumeID, deviceID)
func attachCmd(svc packngo.VolumeAttachmentService, out output.Outputer, volumeID, deviceID *string) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
a, _, err := svc.Create(*volumeID, *deviceID)
if err != nil {
fmt.Println("Client error:", err)
return
return fmt.Errorf("Client error: %s", err)
}

header := []string{"ID"}
data := make([][]string, 1)
data[0] = []string{a.ID}

output(a, header, &data)
},
out.Output(a, header, &data)
return nil
}
}

func init() {
attachVolumeCmd.Flags().StringVarP(&volumeID, "id", "i", "", "UUID of the volume")
attachVolumeCmd.Flags().StringVarP(&deviceID, "device-id", "d", "", "UUID of the device")
func Attach(client *VolumeClient, out output.Outputer) *cobra.Command {
var volumeID, deviceID string
attachVolumeCmd := attachCmd(client.VolumeAttachmentService, out, &volumeID, &deviceID)

cmd := &cobra.Command{
Use: "attach",
Short: "Attaches a volume to a device.",
Example: `
packet volume attach --id [volume_UUID] --device-id [device_UUID]`,
RunE: attachVolumeCmd,
}

cmd.Flags().StringVarP(&volumeID, "id", "i", "", "UUID of the volume")
cmd.Flags().StringVarP(&deviceID, "device-id", "d", "", "UUID of the device")

_ = cmd.MarkFlagRequired("id")
_ = cmd.MarkFlagRequired("device-id")

attachVolumeCmd.MarkFlagRequired("id")
attachVolumeCmd.MarkFlagRequired("device-id")
return cmd
}
90 changes: 90 additions & 0 deletions cmd/volume/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright © 2018 Jasmin Gacic <[email protected]>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package volume

import (
"fmt"
"strconv"

"github.com/packethost/packet-cli/pkg/output"
"github.com/packethost/packngo"
"github.com/spf13/cobra"
)

func createCmd(svc packngo.VolumeService, out output.Outputer, facility, plan, projectID, billingCycle, description *string, size *int, locked *bool) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
req := &packngo.VolumeCreateRequest{
BillingCycle: *billingCycle,
PlanID: *plan,
FacilityID: *facility,
Size: *size,
}

if *description != "" {
req.Description = *description
}
if *locked {
req.Locked = *locked
}

v, _, err := svc.Create(req, *projectID)
if err != nil {
fmt.Println("Client error:", err)
return
}

header := []string{"ID", "Name", "Size", "State", "Created"}
data := make([][]string, 1)
data[0] = []string{v.ID, v.Name, strconv.Itoa(v.Size), v.State, v.Created}

out.Output(v, header, &data)
}
}

func Create(client *VolumeClient, out output.Outputer) *cobra.Command {
var (
size int
facility, plan, projectID, billingCycle, description string
locked bool
)

cmd := &cobra.Command{
Use: "create",
Short: "Creates a volume",
Example: `
packet volume create --size [size_in_GB] --plan [plan_UUID]--project-id [project_UUID] --facility [facility_code]`,
Run: createCmd(client.VolumeService, out, &facility, &plan, &projectID, &billingCycle, &description, &size, &locked),
}
cmd.Flags().StringVarP(&projectID, "project-id", "p", "", "UUID of the project")
cmd.Flags().StringVarP(&plan, "plan", "P", "", "Name of the plan")
cmd.Flags().StringVarP(&facility, "facility", "f", "", "Code of the facility where the volume will be created")
cmd.Flags().IntVarP(&size, "size", "s", 0, "Size in GB]")

_ = cmd.MarkFlagRequired("size")
_ = cmd.MarkFlagRequired("facility")
_ = cmd.MarkFlagRequired("plan")
_ = cmd.MarkFlagRequired("project-id")

cmd.Flags().StringVarP(&billingCycle, "billing-cycle", "b", "hourly", "Billing cycle")
cmd.Flags().StringVarP(&description, "description", "d", "", "Description of the volume")
cmd.Flags().BoolVarP(&locked, "locked", "l", false, "Set the volume to be locked")
return cmd
}
Loading

0 comments on commit b008890

Please sign in to comment.