Sitelet https://github.com/NodeOps-app/createos-cli/commit/66881d6d83d0ba4743247f84c8e184b645bb8613
Skip to content

Commit 66881d6

Browse files
fix: cosvpn cleanup
1 parent fe59753 commit 66881d6

1 file changed

Lines changed: 24 additions & 7 deletions

File tree

‎cmd/sandbox/vpn.go‎

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/urfave/cli/v2"
2020

2121
"github.com/NodeOps-app/createos-cli/internal/api"
22+
"github.com/NodeOps-app/createos-cli/internal/terminal"
2223
)
2324

2425
func newVPNCommand() *cli.Command {
@@ -109,16 +110,32 @@ func runVPNUp(c *cli.Context) error {
109110
or remove the conflicting route, then re-run 'createos sb vpn up'`, conflict)
110111
}
111112

112-
// Defensive startup recovery: a prior CLI run that was killed (OOM,
113-
// kernel panic, force-quit) leaves the cosvpn iface in the kernel
114-
// without a matching server-side session. wg-quick up would then
115-
// fail with "RTNETLINK answers: File exists". Wipe any stale iface
116-
// before proceeding so the user doesn't have to manually intervene.
117-
if out, _ := exec.CommandContext(c.Context, "ip", "link", "show", "cosvpn").Output(); len(out) > 0 { //nolint:errcheck // best-effort stale-iface probe; absent iface yields empty out
113+
// Detect a stale cosvpn iface left by a prior run (OOM, kernel panic,
114+
// force-quit). Presence check works cross-platform via `wg show`,
115+
// which ships with wg-quick on both Linux and macOS (unlike
116+
// `ip link show`, which doesn't exist on macOS). If it's up, ask
117+
// before tearing it down — silent removal could kill an intentional
118+
// tunnel the user set up manually.
119+
if probe := exec.CommandContext(c.Context, "wg", "show", "cosvpn").Run(); probe == nil {
120+
msg := "A WireGuard interface named 'cosvpn' is already up on this machine."
121+
if !terminal.IsInteractive() {
122+
return fmt.Errorf("%s Bring it down first with 'sudo wg-quick down cosvpn' and re-run", msg)
123+
}
124+
pterm.Warning.Println(msg)
125+
ok, cErr := pterm.DefaultInteractiveConfirm.
126+
WithDefaultText("Reset it and continue?").
127+
WithDefaultValue(false).
128+
Show()
129+
if cErr != nil {
130+
return fmt.Errorf("could not read confirmation: %w", cErr)
131+
}
132+
if !ok {
133+
return fmt.Errorf("cancelled — leaving existing cosvpn tunnel in place")
134+
}
118135
cleanup := sudoCommand(c.Context, "wg-quick", "down", confPath)
119136
var cleanupBuf bytes.Buffer
120137
cleanup.Stdout, cleanup.Stderr = pickWGOutputs(debug, &cleanupBuf)
121-
_ = cleanup.Run() //nolint:errcheck // best-effort; if cosvpn was never up, this is a no-op
138+
_ = cleanup.Run() //nolint:errcheck // best-effort teardown
122139
}
123140

124141
// Bring the tunnel up. wg-quick echoes every shell command it runs

0 commit comments

Comments
 (0)