diff --git a/cli/app/remove.go b/cli/app/remove.go index b211afbf..1b594cd6 100644 --- a/cli/app/remove.go +++ b/cli/app/remove.go @@ -1,7 +1,17 @@ package app import ( + "context" + "errors" + "fmt" + "os" + "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 +26,103 @@ 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 + } + err = os.Remove(AppPath) + if err != nil { + return err + } + + // Check if the app has secrets and remove them too + 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 + } + // 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 }, }