package app import ( "context" "fmt" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/client" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/i18n" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/upstream/stack" "github.com/AlecAivazis/survey/v2" "github.com/spf13/cobra" ) var AppVolumeListCommand = &cobra.Command{ Use: i18n.G("list [flags]"), Aliases: []string{i18n.G("ls")}, Short: i18n.G("List volumes associated with an app"), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return autocomplete.AppNameComplete() }, Run: func(cmd *cobra.Command, args []string) { app := internal.ValidateApp(args) cl, err := client.New(app.Server) if err != nil { log.Fatal(err) } filters, err := app.Filters(false, true) if err != nil { log.Fatal(err) } volumes, err := client.GetVolumes(cl, context.Background(), app.Server, filters) if err != nil { log.Fatal(err) } headers := []string{i18n.G("NAME"), i18n.G("ON SERVER")} table, err := formatter.CreateTable() if err != nil { log.Fatal(err) } table.Headers(headers...) var rows [][]string for _, volume := range volumes { row := []string{volume.Name, volume.Mountpoint} rows = append(rows, row) } table.Rows(rows...) if len(rows) > 0 { if err := formatter.PrintTable(table); err != nil { log.Fatal(err) } return } log.Warn(i18n.G("no volumes created for %s", app.Name)) }, } var AppVolumeRemoveCommand = &cobra.Command{ Use: i18n.G("remove [volume] [flags]"), Short: i18n.G("Remove volume(s) associated with an app"), Long: i18n.G(`Remove volumes associated with an app. The app in question must be undeployed before you try to remove volumes. See "abra app undeploy " for more. The command is interactive and will show a multiple select input which allows you to make a seclection. Use the "?" key to see more help on navigating this interface. Passing "--force/-f" will select all volumes for removal. Be careful.`), Example: i18n.G(` # delete volumes interactively abra app volume rm 1312.net # delete specific volume abra app volume rm 1312.net my_volume`), Aliases: []string{i18n.G("rm")}, Args: cobra.MinimumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return autocomplete.AppNameComplete() }, Run: func(cmd *cobra.Command, args []string) { app := internal.ValidateApp(args) var volumeToDelete string if len(args) == 2 { volumeToDelete = args[1] } cl, err := client.New(app.Server) if err != nil { log.Fatal(err) } deployMeta, err := stack.IsDeployed(context.Background(), cl, app.StackName()) if err != nil { log.Fatal(err) } if deployMeta.IsDeployed { log.Fatal(i18n.G("%s is still deployed. Run \"abra app undeploy %s\"", app.Name, app.Name)) } filters, err := app.Filters(false, true) if err != nil { log.Fatal(err) } volumeList, err := client.GetVolumes(cl, context.Background(), app.Server, filters) if err != nil { log.Fatal(err) } volumeNames := client.GetVolumeNames(volumeList) if volumeToDelete != "" { var exactMatch bool fullVolumeToDeleteName := fmt.Sprintf("%s_%s", app.StackName(), volumeToDelete) for _, volName := range volumeNames { if volName == fullVolumeToDeleteName { exactMatch = true } } if !exactMatch { log.Fatal(i18n.G("unable to remove volume: no volume with name '%s'?", volumeToDelete)) } err := client.RemoveVolumes(cl, context.Background(), []string{fullVolumeToDeleteName}, internal.Force, 5) if err != nil { log.Fatal(i18n.G("removing volume %s failed: %s", volumeToDelete, err)) } log.Info(i18n.G("volume %s removed successfully", volumeToDelete)) return } var volumesToRemove []string if !internal.Force && !internal.NoInput { volumesPrompt := &survey.MultiSelect{ Message: i18n.G("which volumes do you want to remove?"), Help: i18n.G("'x' indicates selected, enter / return to confirm, ctrl-c to exit, vim mode is enabled"), VimMode: true, Options: volumeNames, Default: volumeNames, } if err := survey.AskOne(volumesPrompt, &volumesToRemove); err != nil { log.Fatal(err) } } if internal.Force || internal.NoInput { volumesToRemove = volumeNames } if len(volumesToRemove) > 0 { err := client.RemoveVolumes(cl, context.Background(), volumesToRemove, internal.Force, 5) if err != nil { log.Fatal(i18n.G("removing volumes failed: %s", err)) } log.Info(i18n.G("%d volumes removed successfully", len(volumesToRemove))) } else { log.Info(i18n.G("no volumes removed")) } }, } var AppVolumeCommand = &cobra.Command{ Use: i18n.G("volume [cmd] [args] [flags]"), Aliases: []string{i18n.G("vl")}, Short: i18n.G("Manage app volumes"), } func init() { AppVolumeRemoveCommand.Flags().BoolVarP( &internal.Force, i18n.G("force"), i18n.G("f"), false, i18n.G("perform action without further prompt"), ) }