From 5663659d236792dbbdfdd50a8037cb66b774a302 Mon Sep 17 00:00:00 2001 From: knoflook Date: Thu, 12 Aug 2021 13:11:03 +0200 Subject: [PATCH 1/2] feat: initial commit for abra app volume ls/rm --- cli/app/app.go | 1 + cli/app/volume.go | 120 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 cli/app/volume.go diff --git a/cli/app/app.go b/cli/app/app.go index 28c1fa56..db075ab4 100644 --- a/cli/app/app.go +++ b/cli/app/app.go @@ -29,5 +29,6 @@ scaling apps up and spinning them down. appRunCommand, appRollbackCommand, appSecretCommand, + appVolumeCommand, }, } diff --git a/cli/app/volume.go b/cli/app/volume.go new file mode 100644 index 00000000..89cdf96c --- /dev/null +++ b/cli/app/volume.go @@ -0,0 +1,120 @@ +package app + +import ( + "context" + "errors" + "fmt" + + "coopcloud.tech/abra/cli/internal" + "coopcloud.tech/abra/client" + "coopcloud.tech/abra/config" + "github.com/AlecAivazis/survey/v2" + "github.com/docker/docker/api/types/filters" + "github.com/sirupsen/logrus" + "github.com/urfave/cli/v2" +) + +var appVolumeListCommand = &cli.Command{ + Name: "list", + Usage: "list volumes associated with an app", + Aliases: []string{"ls"}, + Action: func(c *cli.Context) error { + appName := c.Args().First() + if appName == "" { + internal.ShowSubcommandHelpAndError(c, errors.New("No app name provided!")) + } + appFiles, err := config.LoadAppFiles("") + if err != nil { + logrus.Fatal(err) + } + host := appFiles[appName].Server + ctx := context.Background() + cl, err := client.NewClientWithContext(host) + if err != nil { + logrus.Fatal(err) + } + + fs := filters.NewArgs() + fs.Add("name", appName) + + volumeListOKBody, err := cl.VolumeList(ctx, fs) + volumeList := volumeListOKBody.Volumes + if err != nil { + logrus.Fatal(err) + } + fmt.Println("DRIVER\t\t\tVOLUME NAME") + for _, volume := range volumeList { + fmt.Printf("%s\t\t\t%s\n", volume.Driver, volume.Name) + } + return nil + }, +} + +var appVolumeRemoveCommand = &cli.Command{ + Name: "remove", + Usage: "remove volume(s) associated with an app", + Aliases: []string{"rm", "delete"}, + Flags: []cli.Flag{ + internal.ForceFlag, + }, + Action: func(c *cli.Context) error { + appName := c.Args().First() + if appName == "" { + internal.ShowSubcommandHelpAndError(c, errors.New("No app name provided!")) + } + appFiles, err := config.LoadAppFiles("") + if err != nil { + logrus.Fatal(err) + } + host := appFiles[appName].Server + ctx := context.Background() + cl, err := client.NewClientWithContext(host) + if err != nil { + logrus.Fatal(err) + } + + fs := filters.NewArgs() + fs.Add("name", appName) + + volumeListOKBody, err := cl.VolumeList(ctx, fs) + volumeList := volumeListOKBody.Volumes + if err != nil { + logrus.Fatal(err) + } + var volumeNames []string + for _, volume := range volumeList { + volumeNames = append(volumeNames, volume.Name) + } + var volumesToRemove []string + if !internal.Force { + volumesPrompt := &survey.MultiSelect{ + Message: "Which volumes do you want to remove?", + Options: volumeNames, + Default: volumeNames, + } + if err := survey.AskOne(volumesPrompt, &volumesToRemove); err != nil { + logrus.Fatal(err) + } + } else { + volumesToRemove = volumeNames + } + for _, vol := range volumesToRemove { + err := cl.VolumeRemove(ctx, vol, internal.Force) + if err != nil { + logrus.Fatal(err) + } + logrus.Info(fmt.Sprintf("Volume %s removed.", vol)) + } + return nil + }, +} + +var appVolumeCommand = &cli.Command{ + Name: "volume", + Usage: "List or remove volumes associated with app", + ArgsUsage: "", + Subcommands: []*cli.Command{ + appVolumeListCommand, + appVolumeRemoveCommand, + }, +} -- 2.47.2 From c3088a5158e8cc4892630fe6b4583ffafd0903bf Mon Sep 17 00:00:00 2001 From: knoflook Date: Tue, 17 Aug 2021 20:36:46 +0200 Subject: [PATCH 2/2] refactor: create functions in client for removing and listing volumes --- cli/app/volume.go | 83 ++++++++++++++++++++++------------------------- client/volumes.go | 51 +++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 45 deletions(-) create mode 100644 client/volumes.go diff --git a/cli/app/volume.go b/cli/app/volume.go index 89cdf96c..72a683ea 100644 --- a/cli/app/volume.go +++ b/cli/app/volume.go @@ -3,17 +3,31 @@ package app import ( "context" "errors" - "fmt" + abraFormatter "coopcloud.tech/abra/cli/formatter" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/client" "coopcloud.tech/abra/config" "github.com/AlecAivazis/survey/v2" - "github.com/docker/docker/api/types/filters" "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) +func getAppsHost(appName string) string { + appFiles, err := config.LoadAppFiles("") + if err != nil { + logrus.Fatal(err) + } + + var host string + if app, ok := appFiles[appName]; ok { + host = app.Server + } else { + logrus.Fatalf(`app "%s" does not exist`, appName) + } + return host +} + var appVolumeListCommand = &cli.Command{ Name: "list", Usage: "list volumes associated with an app", @@ -21,31 +35,26 @@ var appVolumeListCommand = &cli.Command{ Action: func(c *cli.Context) error { appName := c.Args().First() if appName == "" { - internal.ShowSubcommandHelpAndError(c, errors.New("No app name provided!")) + internal.ShowSubcommandHelpAndError(c, errors.New("no app name provided!")) } - appFiles, err := config.LoadAppFiles("") - if err != nil { - logrus.Fatal(err) - } - host := appFiles[appName].Server + host := getAppsHost(appName) + ctx := context.Background() - cl, err := client.NewClientWithContext(host) + volumeList, err := client.GetVolumes(ctx, host, appName) if err != nil { logrus.Fatal(err) } - - fs := filters.NewArgs() - fs.Add("name", appName) - - volumeListOKBody, err := cl.VolumeList(ctx, fs) - volumeList := volumeListOKBody.Volumes - if err != nil { - logrus.Fatal(err) - } - fmt.Println("DRIVER\t\t\tVOLUME NAME") + table := abraFormatter.CreateTable([]string{"DRIVER", "VOLUME NAME"}) + var volTable [][]string for _, volume := range volumeList { - fmt.Printf("%s\t\t\t%s\n", volume.Driver, volume.Name) + volRow := []string{ + volume.Driver, + volume.Name, + } + volTable = append(volTable, volRow) } + table.AppendBulk(volTable) + table.Render() return nil }, } @@ -60,31 +69,16 @@ var appVolumeRemoveCommand = &cli.Command{ Action: func(c *cli.Context) error { appName := c.Args().First() if appName == "" { - internal.ShowSubcommandHelpAndError(c, errors.New("No app name provided!")) + internal.ShowSubcommandHelpAndError(c, errors.New("no app name provided!")) } - appFiles, err := config.LoadAppFiles("") - if err != nil { - logrus.Fatal(err) - } - host := appFiles[appName].Server + host := getAppsHost(appName) ctx := context.Background() - cl, err := client.NewClientWithContext(host) + volumeList, err := client.GetVolumes(ctx, host, appName) if err != nil { logrus.Fatal(err) } + volumeNames := client.GetVolumeNames(volumeList) - fs := filters.NewArgs() - fs.Add("name", appName) - - volumeListOKBody, err := cl.VolumeList(ctx, fs) - volumeList := volumeListOKBody.Volumes - if err != nil { - logrus.Fatal(err) - } - var volumeNames []string - for _, volume := range volumeList { - volumeNames = append(volumeNames, volume.Name) - } var volumesToRemove []string if !internal.Force { volumesPrompt := &survey.MultiSelect{ @@ -98,13 +92,12 @@ var appVolumeRemoveCommand = &cli.Command{ } else { volumesToRemove = volumeNames } - for _, vol := range volumesToRemove { - err := cl.VolumeRemove(ctx, vol, internal.Force) - if err != nil { - logrus.Fatal(err) - } - logrus.Info(fmt.Sprintf("Volume %s removed.", vol)) + + err = client.RemoveVolumes(ctx, host, volumesToRemove, internal.Force) + if err != nil { + logrus.Fatal(err) } + logrus.Info("Volumes removed successfully.") return nil }, } diff --git a/client/volumes.go b/client/volumes.go new file mode 100644 index 00000000..9b7dc13e --- /dev/null +++ b/client/volumes.go @@ -0,0 +1,51 @@ +package client + +import ( + "context" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/sirupsen/logrus" +) + +func GetVolumes(ctx context.Context, server string, appName string) ([]*types.Volume, error) { + + cl, err := NewClientWithContext(server) + if err != nil { + return nil, err + } + + fs := filters.NewArgs() + fs.Add("name", appName) + + volumeListOKBody, err := cl.VolumeList(ctx, fs) + volumeList := volumeListOKBody.Volumes + if err != nil { + logrus.Fatal(err) + } + + return volumeList, nil +} + +func GetVolumeNames(volumes []*types.Volume) []string { + var volumeNames []string + for _, vol := range volumes { + volumeNames = append(volumeNames, vol.Name) + } + return volumeNames +} + +func RemoveVolumes(ctx context.Context, server string, volumeNames []string, force bool) error { + cl, err := NewClientWithContext(server) + if err != nil { + return err + } + for _, volName := range volumeNames { + err := cl.VolumeRemove(ctx, volName, force) + if err != nil { + return err + } + } + return nil + +} -- 2.47.2