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/sirupsen/logrus" "github.com/urfave/cli/v2" ) // Volumes stores the variable from VolumesFlag var Volumes bool // VolumesFlag is used to specify if volumes should be deleted when deleting an app var VolumesFlag = &cli.BoolFlag{ Name: "volumes", Value: false, Destination: &Volumes, } var appRemoveCommand = &cli.Command{ Name: "remove", Usage: "Remove an already undeployed app", Aliases: []string{"rm", "delete"}, Flags: []cli.Flag{ VolumesFlag, internal.ForceFlag, }, Action: func(c *cli.Context) error { appName := c.Args().First() if appName == "" { internal.ShowSubcommandHelpAndError(c, errors.New("no app name provided")) } if !internal.Force { response := false prompt := &survey.Confirm{ Message: fmt.Sprintf("About to delete %s, are you sure", appName), } if err := survey.AskOne(prompt, &response); err != nil { logrus.Fatal(err) } if !response { return errors.New("User aborted app removal") } } appFiles, err := config.LoadAppFiles("") if err != nil { logrus.Fatal(err) } appPath := appFiles[appName].Path server := appFiles[appName].Server ctx := context.Background() cl, err := client.New(server) if err != nil { logrus.Fatal(err) } fs := filters.NewArgs() fs.Add("name", appName) secretList, err := cl.SecretList(ctx, types.SecretListOptions{Filters: fs}) if err != nil { logrus.Fatal(err) } secrets := make(map[string]string) if len(secrets) > 0 { var 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) } var secretNamesToRemove []string if !internal.Force { secretsPrompt := &survey.MultiSelect{ Message: "Which secrets do you want to remove?", Options: secretNames, Default: secretNames, } if err := survey.AskOne(secretsPrompt, &secretNamesToRemove); err != nil { logrus.Fatal(err) } } for _, name := range secretNamesToRemove { err := cl.SecretRemove(ctx, secrets[name]) if err != nil { logrus.Fatal(err) } logrus.Info(fmt.Sprintf("Secret: %s removed", name)) } } else { logrus.Info("No secrets to remove") } volumeListOKBody, err := cl.VolumeList(ctx, fs) volumeList := volumeListOKBody.Volumes if err != nil { logrus.Fatal(err) } var vols []string if len(vols) > 0 { for _, vol := range volumeList { vols = append(vols, vol.Name) } if Volumes { var removeVols []string if !internal.Force { volumesPrompt := &survey.MultiSelect{ Message: "Which volumes do you want to remove?", Options: vols, Default: vols, } if err := survey.AskOne(volumesPrompt, &removeVols); err != nil { logrus.Fatal(err) } } for _, vol := range removeVols { err := cl.VolumeRemove(ctx, vol, internal.Force) // last argument is for force removing if err != nil { logrus.Fatal(err) } logrus.Info(fmt.Sprintf("Volume %s removed", vol)) } } else { logrus.Info("No volumes were removed") } } else { logrus.Info("No volumes to remove") } err = os.Remove(appPath) if err != nil { logrus.Fatal(err) } logrus.Info(fmt.Sprintf("File: %s removed", appPath)) return nil }, }