From edaedeac3a112f3373d6f09a4e9b5bdbd6c01aec Mon Sep 17 00:00:00 2001 From: knoflook Date: Thu, 5 Aug 2021 12:02:13 +0200 Subject: [PATCH 1/4] context does not exist --- cli/app/remove.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/cli/app/remove.go b/cli/app/remove.go index b211afbf..bdefb0c9 100644 --- a/cli/app/remove.go +++ b/cli/app/remove.go @@ -1,7 +1,16 @@ 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" + "github.com/docker/docker/api/types/filters" "github.com/urfave/cli/v2" ) @@ -16,9 +25,56 @@ var VolumesFlag = &cli.BoolFlag{ } var appRemoveCommand = &cli.Command{ - Name: "remove", + Name: "remove", + Aliases: []string{"rm", "delete"}, Flags: []cli.Flag{ VolumesFlag, internal.SecretsFlag, }, + Action: func(c *cli.Context) error { + // Check if app name was provided by user + AppName := c.Args().First() + if AppName == "" { + internal.ShowSubcommandHelpAndError(c, errors.New("No app name provided!")) + } + // Make sure that the user really wants to delete the app + response := false + prompt := &survey.Confirm{ + Message: "About to delete " + AppName + ", are you sure?", + } + survey.AskOne(prompt, &response) + if response == false { + return errors.New("User aborted app removal") + } + // Remove the file + AppFiles, err := config.LoadAppFiles("") + if err != nil { + return err + } + AppPath := AppFiles[AppName].Path + host := AppFiles[AppName].Server + // Initialize docker client + ctx := context.Background() + cl, err := client.NewClientWithContext(host) + if err != nil { + return err + } + + fmt.Println(AppPath) //to be replaced by a remove method + + // Check if the app has secrets and remove them too + if internal.Secrets { + fs := filters.NewArgs() + fs.Add("name", AppName) + SecretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: fs}) + if err != nil { + return err + } + fmt.Println(SecretList) + } + + // Remove the volumes if desired + + return nil + }, } -- 2.47.2 From f528cf4cfa5aa9824db7b17f8908685f1977e776 Mon Sep 17 00:00:00 2001 From: knoflook Date: Thu, 5 Aug 2021 13:48:17 +0200 Subject: [PATCH 2/4] Initial commit for abra app rm --- cli/app/remove.go | 64 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/cli/app/remove.go b/cli/app/remove.go index bdefb0c9..1b594cd6 100644 --- a/cli/app/remove.go +++ b/cli/app/remove.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "os" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/client" @@ -29,7 +30,6 @@ var appRemoveCommand = &cli.Command{ Aliases: []string{"rm", "delete"}, Flags: []cli.Flag{ VolumesFlag, - internal.SecretsFlag, }, Action: func(c *cli.Context) error { // Check if app name was provided by user @@ -59,21 +59,69 @@ var appRemoveCommand = &cli.Command{ if err != nil { return err } - - fmt.Println(AppPath) //to be replaced by a remove method + err = os.Remove(AppPath) + if err != nil { + return err + } // Check if the app has secrets and remove them too - if internal.Secrets { - fs := filters.NewArgs() - fs.Add("name", AppName) - SecretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: fs}) + fs := filters.NewArgs() + fs.Add("name", AppName) + SecretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: fs}) + if err != nil { + return err + } + // TODO: Actually remove secrets + Secrets := make(map[string]string) + SecretNames := []string{} + for _, cont := range SecretList { + Secrets[cont.Spec.Annotations.Name] = cont.ID //we have to map the names to ID's + SecretNames = append(SecretNames, cont.Spec.Annotations.Name) + //cl.SecretRemove(ctx, cont.ID) + } + SecretNamesToRemove := []string{} + SecretsPrompt := &survey.MultiSelect{ + Message: "Which secrets do you want to remove?", + Options: SecretNames, + Default: SecretNames, + } + survey.AskOne(SecretsPrompt, &SecretNamesToRemove) + for _, name := range SecretNamesToRemove { + err := cl.SecretRemove(ctx, Secrets[name]) if err != nil { return err } - fmt.Println(SecretList) + // SecretIDsToRemove = append(SecretIDsToRemove, Secrets[name]) } // Remove the volumes if desired + if Volumes == true { + VolumeListOKBody, err := cl.VolumeList(ctx, fs) + VolumeList := VolumeListOKBody.Volumes + if err != nil { + return err + } + Vols := []string{} + for _, vol := range VolumeList { + Vols = append(Vols, vol.Name) + } + RemoveVols := []string{} + VolumesPrompt := &survey.MultiSelect{ + Message: "Which volumes do you want to remove?", + Options: Vols, + Default: Vols, + } + survey.AskOne(VolumesPrompt, &RemoveVols) + fmt.Println("Volumes to remove: ", RemoveVols) //TODO: Replace with a remove method + for _, vol := range RemoveVols { + err := cl.VolumeRemove(ctx, vol, false) // false is for force removing + if err != nil { + return err + } + } + } else { + fmt.Println("Volumes will not be removed") + } return nil }, -- 2.47.2 From 7dad9895eb834b0d16245d4c7551b53aa1f5c30c Mon Sep 17 00:00:00 2001 From: knoflook Date: Thu, 5 Aug 2021 16:45:07 +0200 Subject: [PATCH 3/4] Add --force flag, use MultiSelect for volumes and secrets --- cli/app/remove.go | 102 ++++++++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 35 deletions(-) diff --git a/cli/app/remove.go b/cli/app/remove.go index 1b594cd6..35ad16ef 100644 --- a/cli/app/remove.go +++ b/cli/app/remove.go @@ -3,8 +3,8 @@ package app import ( "context" "errors" - "fmt" "os" + "strings" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/client" @@ -12,6 +12,7 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" + "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -25,11 +26,20 @@ var VolumesFlag = &cli.BoolFlag{ Destination: &Volumes, } +var Force bool + +var ForceFlag = &cli.BoolFlag{ + Name: "force", + Value: false, + Destination: &Force, +} + var appRemoveCommand = &cli.Command{ Name: "remove", Aliases: []string{"rm", "delete"}, Flags: []cli.Flag{ VolumesFlag, + ForceFlag, }, Action: func(c *cli.Context) error { // Check if app name was provided by user @@ -38,15 +48,17 @@ var appRemoveCommand = &cli.Command{ internal.ShowSubcommandHelpAndError(c, errors.New("No app name provided!")) } // Make sure that the user really wants to delete the app - response := false - prompt := &survey.Confirm{ - Message: "About to delete " + AppName + ", are you sure?", + if !Force { + response := false + prompt := &survey.Confirm{ + Message: "About to delete " + AppName + ", are you sure?", + } + survey.AskOne(prompt, &response) + if response == false { + return errors.New("User aborted app removal") + } } - survey.AskOne(prompt, &response) - if response == false { - return errors.New("User aborted app removal") - } - // Remove the file + // Get app list AppFiles, err := config.LoadAppFiles("") if err != nil { return err @@ -59,68 +71,88 @@ var appRemoveCommand = &cli.Command{ if err != nil { return err } + // Remove the file err = os.Remove(AppPath) if err != nil { return err + } else { + logrus.Info("File :" + AppPath + " removed.") } - // Check if the app has secrets and remove them too + // Check if the app has secrets fs := filters.NewArgs() fs.Add("name", AppName) SecretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: fs}) if err != nil { return err } - // TODO: Actually remove secrets Secrets := make(map[string]string) SecretNames := []string{} for _, cont := range SecretList { Secrets[cont.Spec.Annotations.Name] = cont.ID //we have to map the names to ID's SecretNames = append(SecretNames, cont.Spec.Annotations.Name) - //cl.SecretRemove(ctx, cont.ID) } SecretNamesToRemove := []string{} - SecretsPrompt := &survey.MultiSelect{ - Message: "Which secrets do you want to remove?", - Options: SecretNames, - Default: SecretNames, + + // Ask if the user really wants to remove the apps + if Force { + SecretNamesToRemove = SecretNames + } else { + SecretsPrompt := &survey.MultiSelect{ + Message: "Which secrets do you want to remove?", + Options: SecretNames, + Default: SecretNames, + } + survey.AskOne(SecretsPrompt, &SecretNamesToRemove) } - survey.AskOne(SecretsPrompt, &SecretNamesToRemove) + + // Actually remove the secrets for _, name := range SecretNamesToRemove { + // DEBUG: SecretIDsToRemove = append(SecretIDsToRemove, Secrets[name]) err := cl.SecretRemove(ctx, Secrets[name]) if err != nil { return err + } else { + logrus.Info("Secret: " + name + " removed") } - // SecretIDsToRemove = append(SecretIDsToRemove, Secrets[name]) } + // Get volumes associated with the app + VolumeListOKBody, err := cl.VolumeList(ctx, fs) + VolumeList := VolumeListOKBody.Volumes + if err != nil { + return err + } + Vols := []string{} + for _, vol := range VolumeList { + Vols = append(Vols, vol.Name) + } // Remove the volumes if desired if Volumes == true { - VolumeListOKBody, err := cl.VolumeList(ctx, fs) - VolumeList := VolumeListOKBody.Volumes - if err != nil { - return err - } - Vols := []string{} - for _, vol := range VolumeList { - Vols = append(Vols, vol.Name) - } + RemoveVols := []string{} - VolumesPrompt := &survey.MultiSelect{ - Message: "Which volumes do you want to remove?", - Options: Vols, - Default: Vols, + // If there's no --force, ask if the user wants to remove + if Force { + RemoveVols = Vols + } else { + VolumesPrompt := &survey.MultiSelect{ + Message: "Which volumes do you want to remove?", + Options: Vols, + Default: Vols, + } + survey.AskOne(VolumesPrompt, &RemoveVols) } - survey.AskOne(VolumesPrompt, &RemoveVols) - fmt.Println("Volumes to remove: ", RemoveVols) //TODO: Replace with a remove method + // Remove the volumes for _, vol := range RemoveVols { - err := cl.VolumeRemove(ctx, vol, false) // false is for force removing + err := cl.VolumeRemove(ctx, vol, Force) // false is for force removing if err != nil { return err + } else { + logrus.Info("Volume " + vol + " removed") } } } else { - fmt.Println("Volumes will not be removed") + logrus.Info("No volumes were removed. Volumes left: " + strings.Join(Vols, ", ")) } return nil -- 2.47.2 From 09a06997e157dda35e6ef7215fbed7ed7d07468f Mon Sep 17 00:00:00 2001 From: knoflook Date: Thu, 5 Aug 2021 18:53:01 +0200 Subject: [PATCH 4/4] Code cleanup for app remove --- cli/app/remove.go | 125 +++++++++++++++++------------------------ cli/internal/common.go | 9 +++ 2 files changed, 62 insertions(+), 72 deletions(-) diff --git a/cli/app/remove.go b/cli/app/remove.go index 35ad16ef..9bc4d0dd 100644 --- a/cli/app/remove.go +++ b/cli/app/remove.go @@ -3,6 +3,7 @@ package app import ( "context" "errors" + "fmt" "os" "strings" @@ -26,133 +27,113 @@ var VolumesFlag = &cli.BoolFlag{ Destination: &Volumes, } -var Force bool - -var ForceFlag = &cli.BoolFlag{ - Name: "force", - Value: false, - Destination: &Force, -} - var appRemoveCommand = &cli.Command{ Name: "remove", Aliases: []string{"rm", "delete"}, Flags: []cli.Flag{ VolumesFlag, - ForceFlag, + internal.ForceFlag, }, Action: func(c *cli.Context) error { - // Check if app name was provided by user - AppName := c.Args().First() - if AppName == "" { + appName := c.Args().First() + if appName == "" { internal.ShowSubcommandHelpAndError(c, errors.New("No app name provided!")) } - // Make sure that the user really wants to delete the app - if !Force { + if !internal.Force { response := false prompt := &survey.Confirm{ - Message: "About to delete " + AppName + ", are you sure?", + Message: fmt.Sprintf("About to delete %s, are you sure", appName), } survey.AskOne(prompt, &response) - if response == false { + if !response { return errors.New("User aborted app removal") } } - // Get app list - AppFiles, err := config.LoadAppFiles("") + appFiles, err := config.LoadAppFiles("") if err != nil { - return err + logrus.Fatal(err) } - AppPath := AppFiles[AppName].Path - host := AppFiles[AppName].Server - // Initialize docker client + appPath := appFiles[appName].Path + fmt.Println(appFiles) + host := appFiles[appName].Server ctx := context.Background() cl, err := client.NewClientWithContext(host) if err != nil { - return err + logrus.Fatal(err) } - // Remove the file - err = os.Remove(AppPath) + err = os.Remove(appPath) if err != nil { - return err + logrus.Fatal(err) } else { - logrus.Info("File :" + AppPath + " removed.") + logrus.Info(fmt.Sprintf("File: %s removed", appPath)) } - // Check if the app has secrets fs := filters.NewArgs() - fs.Add("name", AppName) - SecretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: fs}) + fs.Add("name", appName) + secretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: fs}) if err != nil { - return err + logrus.Fatal(err) } - Secrets := make(map[string]string) - SecretNames := []string{} - for _, cont := range SecretList { - Secrets[cont.Spec.Annotations.Name] = cont.ID //we have to map the names to ID's - SecretNames = append(SecretNames, cont.Spec.Annotations.Name) + secrets := make(map[string]string) + secretNames := []string{} + for _, cont := range secretList { + secrets[cont.Spec.Annotations.Name] = cont.ID //we have to map the names to ID's + secretNames = append(secretNames, cont.Spec.Annotations.Name) } - SecretNamesToRemove := []string{} + secretNamesToRemove := []string{} - // Ask if the user really wants to remove the apps - if Force { - SecretNamesToRemove = SecretNames + if internal.Force { + secretNamesToRemove = secretNames } else { - SecretsPrompt := &survey.MultiSelect{ + secretsPrompt := &survey.MultiSelect{ Message: "Which secrets do you want to remove?", - Options: SecretNames, - Default: SecretNames, + Options: secretNames, + Default: secretNames, } - survey.AskOne(SecretsPrompt, &SecretNamesToRemove) + survey.AskOne(secretsPrompt, &secretNamesToRemove) } - // Actually remove the secrets - for _, name := range SecretNamesToRemove { - // DEBUG: SecretIDsToRemove = append(SecretIDsToRemove, Secrets[name]) - err := cl.SecretRemove(ctx, Secrets[name]) + for _, name := range secretNamesToRemove { + err := cl.SecretRemove(ctx, secrets[name]) if err != nil { - return err + logrus.Fatal(err) } else { - logrus.Info("Secret: " + name + " removed") + logrus.Info(fmt.Sprintf("Secret: %s removed", name)) } } - // Get volumes associated with the app - VolumeListOKBody, err := cl.VolumeList(ctx, fs) - VolumeList := VolumeListOKBody.Volumes + volumeListOKBody, err := cl.VolumeList(ctx, fs) + volumeList := volumeListOKBody.Volumes if err != nil { - return err + logrus.Fatal(err) } - Vols := []string{} - for _, vol := range VolumeList { - Vols = append(Vols, vol.Name) + vols := []string{} + for _, vol := range volumeList { + vols = append(vols, vol.Name) } - // Remove the volumes if desired - if Volumes == true { - RemoveVols := []string{} - // If there's no --force, ask if the user wants to remove - if Force { - RemoveVols = Vols + if Volumes { + removeVols := []string{} + if internal.Force { + removeVols = vols } else { - VolumesPrompt := &survey.MultiSelect{ + volumesPrompt := &survey.MultiSelect{ Message: "Which volumes do you want to remove?", - Options: Vols, - Default: Vols, + Options: vols, + Default: vols, } - survey.AskOne(VolumesPrompt, &RemoveVols) + survey.AskOne(volumesPrompt, &removeVols) } - // Remove the volumes - for _, vol := range RemoveVols { - err := cl.VolumeRemove(ctx, vol, Force) // false is for force removing + for _, vol := range removeVols { + err := cl.VolumeRemove(ctx, vol, internal.Force) // last argument is for force removing if err != nil { - return err + logrus.Fatal(err) } else { logrus.Info("Volume " + vol + " removed") } } } else { - logrus.Info("No volumes were removed. Volumes left: " + strings.Join(Vols, ", ")) + logrus.Info("No volumes were removed. Volumes left: " + strings.Join(vols, ", ")) } return nil diff --git a/cli/internal/common.go b/cli/internal/common.go index a0366162..a77784f9 100644 --- a/cli/internal/common.go +++ b/cli/internal/common.go @@ -42,3 +42,12 @@ var ContextFlag = &cli.StringFlag{ Aliases: []string{"c"}, Destination: &Context, } + +var Force bool + +var ForceFlag = &cli.BoolFlag{ + Name: "force", + Value: false, + Aliases: []string{"f"}, + Destination: &Force, +} -- 2.47.2