diff --git a/cli/app/volume.go b/cli/app/volume.go index a78bb65e..a19ab65c 100644 --- a/cli/app/volume.go +++ b/cli/app/volume.go @@ -2,6 +2,7 @@ package app import ( "context" + "fmt" "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" @@ -71,7 +72,7 @@ var AppVolumeListCommand = &cobra.Command{ } var AppVolumeRemoveCommand = &cobra.Command{ - Use: "remove [flags]", + Use: "remove [volume] [flags]", Short: "Remove volume(s) associated with an app", Long: `Remove volumes associated with an app. @@ -83,6 +84,11 @@ 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: ` # delete volumes interactively + abra app volume rm 1312.net + + # delete specific volume + abra app volume rm 1312.net my_volume`, Aliases: []string{"rm"}, Args: cobra.MinimumNArgs(1), ValidArgsFunction: func( @@ -94,6 +100,11 @@ Passing "--force/-f" will select all volumes for removal. Be careful.`, 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) @@ -119,6 +130,30 @@ Passing "--force/-f" will select all volumes for removal. Be careful.`, } 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.Fatalf("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.Fatalf("removing volume %s failed: %s", volumeToDelete, err) + } + + log.Infof("volume %s removed successfully", volumeToDelete) + + return + } + var volumesToRemove []string if !internal.Force && !internal.NoInput { volumesPrompt := &survey.MultiSelect{ diff --git a/tests/integration/app_volume.bats b/tests/integration/app_volume.bats index df41f118..7e764ef8 100644 --- a/tests/integration/app_volume.bats +++ b/tests/integration/app_volume.bats @@ -63,20 +63,24 @@ teardown(){ # bats test_tags=slow @test "remove volumes" { - sleep 3 # NOTE(d1): hack to avoid "network not found" - _deploy_app _undeploy_app + run $ABRA app volume ls "$TEST_APP_DOMAIN" + assert_success + assert_output --partial 'test-volume' + run $ABRA app volume rm "$TEST_APP_DOMAIN" --force assert_success assert_output --partial 'volumes removed successfully' + + run $ABRA app volume ls "$TEST_APP_DOMAIN" + assert_success + assert_output --partial 'no volumes created' } # bats test_tags=slow @test "remove no volumes" { - sleep 3 # NOTE(d1): hack to avoid "network not found" - _deploy_app _undeploy_app @@ -88,3 +92,59 @@ teardown(){ assert_success assert_output --partial 'no volumes removed' } + +# bats test_tags=slow +@test "remove single volume" { + _deploy_app + _undeploy_app + + run $ABRA app volume ls "$TEST_APP_DOMAIN" + assert_success + assert_output --partial 'test-volume' + assert_output --partial 'test-volume-two' + + run $ABRA app volume rm "$TEST_APP_DOMAIN" test-volume-two --force + assert_success + assert_output --partial 'test-volume-two removed successfully' + + run $ABRA app volume ls "$TEST_APP_DOMAIN" + assert_success + assert_output --partial 'test-volume' + refute_output --partial 'test-volume-two' + + run $ABRA app volume rm "$TEST_APP_DOMAIN" --force + assert_success + assert_output --partial 'volumes removed successfully' + + run $ABRA app volume ls "$TEST_APP_DOMAIN" + assert_success + assert_output --partial 'no volumes created' +} + +# bats test_tags=slow +@test "remove single volume incorrect name" { + _deploy_app + _undeploy_app + + run $ABRA app volume rm "$TEST_APP_DOMAIN" DOESNTEXIST --force + assert_failure + assert_output --partial 'no volume with name' +} + +# bats test_tags=slow +@test "remove single volume doesn't delete similar name" { + _deploy_app + _undeploy_app + + run $ABRA app volume ls "$TEST_APP_DOMAIN" + assert_success + assert_output --partial 'test-volume-two' + + run $ABRA app volume rm "$TEST_APP_DOMAIN" test-volume --force + assert_success + assert_output --partial 'test-volume removed successfully' + + run $ABRA app volume ls "$TEST_APP_DOMAIN" + assert_success + assert_output --partial 'test-volume-two' +}