diff --git a/README.md b/README.md index 6f63308..3ee45ed 100644 --- a/README.md +++ b/README.md @@ -170,12 +170,17 @@ harness get gateways [-o table|json|yaml] harness describe Detailed status for a specific sandbox (phase, gateway, providers). +harness delete [...] + Delete specific sandboxes by name. + +harness delete --all + Delete all sandboxes, providers, and k8s resources. + +harness delete --providers / --k8s + Delete providers or k8s resources selectively. + harness stop [NAME] / harness start [NAME] Stop or start a sandbox without deleting it. - -harness teardown [--sandboxes] [--providers] [--k8s] - Tear down resources. At least one flag required. - (Deprecated: will be replaced by 'harness delete') ``` For sandbox connect/logs, use openshell directly: diff --git a/SPEC.md b/SPEC.md index 9078b47..191c0f4 100644 --- a/SPEC.md +++ b/SPEC.md @@ -114,6 +114,10 @@ These are convenience wrappers. For full details, use `openshell sandbox list`, Show detailed status for a specific sandbox: phase, active gateway, and registered providers. +### `harness delete [NAME...] [--all] [--providers] [--k8s]` + +Delete sandboxes by name, or use flags for bulk operations. `--all` deletes sandboxes, providers, and k8s resources. Reuses the same teardown functions as the old `teardown` command. + ### `harness deploy [local|ocp|kind]` Deploy or verify the gateway for a target. Reads `profiles/gateways/.yaml`. @@ -128,7 +132,7 @@ These commands still work but will be removed in a future release: | Old command | Replacement | Notes | |-------------|-------------|-------| -| `harness teardown` | `harness delete` (planned) | Flags: `--sandboxes`, `--providers`, `--k8s` | +| `harness teardown` | `harness delete` | Same flags: `--sandboxes`, `--providers`, `--k8s` | | `harness status` | `harness get agents` | | ## Config Files diff --git a/cmd/delete.go b/cmd/delete.go new file mode 100644 index 0000000..5ec8b3e --- /dev/null +++ b/cmd/delete.go @@ -0,0 +1,85 @@ +package cmd + +import ( + "fmt" + + "github.com/robbycochran/harness-openshell/internal/gateway" + "github.com/robbycochran/harness-openshell/internal/k8s" + "github.com/robbycochran/harness-openshell/internal/status" + "github.com/spf13/cobra" +) + +func NewDeleteCmd(harnessDir, cli string) *cobra.Command { + var ( + all bool + sandboxes bool + providers bool + k8sFlag bool + ) + + cmd := &cobra.Command{ + Use: "delete [NAME...] [--all] [--providers] [--k8s]", + Short: "Delete sandboxes, providers, or k8s resources", + Long: `Delete specific sandboxes by name, or use flags for bulk operations. + +Examples: + harness delete my-sandbox Delete a specific sandbox + harness delete agent test Delete multiple sandboxes + harness delete --all Delete all sandboxes, providers, and k8s resources + harness delete --providers Delete all providers (no running sandboxes allowed) + harness delete --k8s Delete k8s resources (helm, namespace, SCCs)`, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 && !all && !sandboxes && !providers && !k8sFlag { + return fmt.Errorf("specify sandbox name(s) or use --all, --sandboxes, --providers, --k8s") + } + + gw := gateway.New(cli) + + // Targeted sandbox deletion + if len(args) > 0 { + for _, name := range args { + if err := gw.SandboxDelete(name); err != nil { + status.Failf("%s: %v", name, err) + } else { + status.OKf("Deleted sandbox %s", name) + } + } + if !all && !providers && !k8sFlag { + return nil + } + } + + activeGW := gw.ActiveGateway() + if activeGW != "" { + status.Infof("Active gateway: %s", activeGW) + } else { + status.Info("Active gateway: none") + } + fmt.Println() + + if all || sandboxes { + teardownSandboxes(gw, activeGW) + } + if all || providers { + if err := teardownProviders(gw, activeGW); err != nil { + return err + } + } + if all || k8sFlag { + ns := k8s.DefaultNamespace() + gwCfg, _ := resolveGatewayConfig(harnessDir, "ocp") + teardownK8s(gw, gwCfg, k8s.New("", ns), k8s.New("", "")) + } + + status.Done("Done.") + return nil + }, + } + + cmd.Flags().BoolVar(&all, "all", false, "Delete all sandboxes, providers, and k8s resources") + cmd.Flags().BoolVar(&sandboxes, "sandboxes", false, "Delete all sandboxes") + cmd.Flags().BoolVar(&providers, "providers", false, "Delete all providers") + cmd.Flags().BoolVar(&k8sFlag, "k8s", false, "Delete k8s resources") + + return cmd +} diff --git a/main.go b/main.go index 9b1bf9c..35c60b2 100644 --- a/main.go +++ b/main.go @@ -64,6 +64,7 @@ func main() { cmd.NewApplyCmd(harnessDir, cli), cmd.NewGetCmd(harnessDir, cli), cmd.NewDescribeCmd(harnessDir, cli), + cmd.NewDeleteCmd(harnessDir, cli), cmd.NewDeployCmd(harnessDir, cli), cmd.NewStopCmd(harnessDir, cli), cmd.NewStartCmd(harnessDir, cli), @@ -72,7 +73,7 @@ func main() { // Deprecated aliases teardownCmd := cmd.NewTeardownCmd(harnessDir, cli) teardownCmd.Hidden = true - teardownCmd.Deprecated = "will be replaced by 'harness delete' in a future release" + teardownCmd.Deprecated = "use 'harness delete' instead" statusCmd := cmd.NewStatusCmd(harnessDir, cli) statusCmd.Hidden = true statusCmd.Deprecated = "use 'harness get agents' instead" diff --git a/test/test-flow.sh b/test/test-flow.sh index 0900796..27a3c53 100755 --- a/test/test-flow.sh +++ b/test/test-flow.sh @@ -182,11 +182,11 @@ test_errors() { step_fail "nonexistent profile" harness apply --gateway local --agent nonexistent if $REUSE_GATEWAY; then - step "teardown (first)" harness teardown --sandboxes --providers - step "teardown (second)" harness teardown --sandboxes --providers + step "teardown (first)" harness delete --sandboxes --providers + step "teardown (second)" harness delete --sandboxes --providers else - step "teardown (first)" harness teardown --sandboxes --providers --k8s - step "teardown (second)" harness teardown --sandboxes --providers --k8s + step "teardown (first)" harness delete --sandboxes --providers --k8s + step "teardown (second)" harness delete --sandboxes --providers --k8s fi echo "" @@ -199,7 +199,7 @@ test_local() { $NO_PROVIDERS && mode="$mode, no-providers" echo "=== test-flow: local ($mode) ===" - step "teardown" harness teardown --sandboxes --providers + step "teardown" harness delete --sandboxes --providers step "deploy" harness deploy local step "gateway reachable" "$CLI" inference get @@ -217,12 +217,12 @@ test_local() { if ! $NO_PROVIDERS; then echo "" echo "=== test: missing providers ===" - step "teardown providers" harness teardown --providers + step "teardown providers" harness delete --providers step "up with no providers" harness apply --gateway local --name test-noprov - step "cleanup" harness teardown --sandboxes + step "cleanup" harness delete --sandboxes fi - step "teardown (clean)" harness teardown --sandboxes --providers + step "teardown (clean)" harness delete --sandboxes --providers } # ── GWS lifecycle test ─────────────────────────────────────────────── @@ -259,7 +259,7 @@ test_kind() { return fi - step "teardown" harness teardown --sandboxes --providers --k8s + step "teardown" harness delete --sandboxes --providers --k8s step "deploy" harness deploy kind step "gateway reachable" "$CLI" inference get @@ -273,7 +273,7 @@ test_kind() { step "sandbox delete" "$CLI" sandbox delete "$sandbox_name" - step "teardown (clean)" harness teardown --sandboxes --providers --k8s + step "teardown (clean)" harness delete --sandboxes --providers --k8s echo "" } @@ -288,14 +288,14 @@ test_ocp() { OCP_GW=$("$CLI" gateway list 2>/dev/null | strip_ansi | awk '/-remote-/ {gsub(/^\*/, ""); print $1; exit}') [[ -n "$OCP_GW" ]] && "$CLI" gateway select "$OCP_GW" 2>/dev/null || true - step "teardown sandboxes+providers" harness teardown --sandboxes --providers + step "teardown sandboxes+providers" harness delete --sandboxes --providers if ! "$CLI" inference get &>/dev/null; then step "deploy" harness deploy ocp else step "gateway reachable" "$CLI" inference get fi else - step "teardown" harness teardown --sandboxes --providers --k8s + step "teardown" harness delete --sandboxes --providers --k8s step "deploy" harness deploy ocp fi @@ -312,9 +312,9 @@ test_ocp() { step "sandbox delete" "$CLI" sandbox delete "$sandbox_name" if $REUSE_GATEWAY; then - step "teardown (sandboxes+providers)" harness teardown --sandboxes --providers + step "teardown (sandboxes+providers)" harness delete --sandboxes --providers else - step "teardown (clean)" harness teardown --sandboxes --providers --k8s + step "teardown (clean)" harness delete --sandboxes --providers --k8s fi }