cmd/tailscale: allow serve|funnel off to delete an entire port

This PR allows you to do "tailscale serve -bg -https:4545 off" and it
will delete all handlers under it. It will also prompt you for a y/n in case
you wanted to delete a single port.

Updates #8489

Signed-off-by: Marwan Sulaiman <marwan@tailscale.com>
pull/9933/head
Marwan Sulaiman 8 months ago committed by Marwan Sulaiman
parent e561f1ce61
commit 60e768fd14

@ -164,6 +164,7 @@ type serveEnv struct {
tcp string // TCP port
tlsTerminatedTCP string // a TLS terminated TCP port
subcmd serveMode // subcommand
yes bool // update without prompt
lc localServeClient // localClient interface, specific to serve

@ -128,7 +128,7 @@ func newServeV2Command(e *serveEnv, subcmd serveMode) *ffcli.Command {
fs.StringVar(&e.http, "http", "", "Expose an HTTP server at the specified port")
fs.StringVar(&e.tcp, "tcp", "", "Expose a TCP forwarder to forward raw TCP packets at the specified port")
fs.StringVar(&e.tlsTerminatedTCP, "tls-terminated-tcp", "", "Expose a TCP forwarder to forward TLS-terminated TCP packets at the specified port")
fs.BoolVar(&e.yes, "yes", false, "Update without interactive prompts")
}),
UsageFunc: usageFunc,
Subcommands: []*ffcli.Command{
@ -679,13 +679,40 @@ func (e *serveEnv) removeWebServe(sc *ipn.ServeConfig, dnsName string, srvPort u
return errors.New("cannot remove web handler; currently serving TCP")
}
hp := ipn.HostPort(net.JoinHostPort(dnsName, strconv.Itoa(int(srvPort))))
if !sc.WebHandlerExists(hp, mount) {
portStr := strconv.Itoa(int(srvPort))
hp := ipn.HostPort(net.JoinHostPort(dnsName, portStr))
var targetExists bool
var mounts []string
// mount is deduced from e.setPath but it is ambiguous as
// to whether the user explicitly passed "/" or it was defaulted to.
if e.setPath == "" {
targetExists = sc.Web[hp] != nil && len(sc.Web[hp].Handlers) > 0
if targetExists {
for mount := range sc.Web[hp].Handlers {
mounts = append(mounts, mount)
}
}
} else {
targetExists = sc.WebHandlerExists(hp, mount)
mounts = []string{mount}
}
if !targetExists {
return errors.New("error: handler does not exist")
}
if len(mounts) > 1 {
msg := fmt.Sprintf("Are you sure you want to delete %d handlers under port %s?", len(mounts), portStr)
if !e.yes && !promptYesNo(msg) {
return nil
}
}
// delete existing handler, then cascade delete if empty
delete(sc.Web[hp].Handlers, mount)
for _, m := range mounts {
delete(sc.Web[hp].Handlers, m)
}
if len(sc.Web[hp].Handlers) == 0 {
delete(sc.Web, hp)
delete(sc.TCP, srvPort)

@ -725,6 +725,40 @@ func TestServeDevConfigMutations(t *testing.T) {
wantErr: anyErr(),
})
add(step{
command: cmd("serve reset"),
want: &ipn.ServeConfig{},
})
// start two handlers and turn them off in one command
add(step{
command: cmd("serve --https=4545 --set-path=/foo --bg localhost:3000"),
want: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{4545: {HTTPS: true}},
Web: map[ipn.HostPort]*ipn.WebServerConfig{
"foo.test.ts.net:4545": {Handlers: map[string]*ipn.HTTPHandler{
"/foo": {Proxy: "http://127.0.0.1:3000"},
}},
},
},
})
add(step{
command: cmd("serve --https=4545 --set-path=/bar --bg localhost:3000"),
want: &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{4545: {HTTPS: true}},
Web: map[ipn.HostPort]*ipn.WebServerConfig{
"foo.test.ts.net:4545": {Handlers: map[string]*ipn.HTTPHandler{
"/foo": {Proxy: "http://127.0.0.1:3000"},
"/bar": {Proxy: "http://127.0.0.1:3000"},
}},
},
},
})
add(step{
command: cmd("serve --https=4545 --bg --yes localhost:3000 off"),
want: &ipn.ServeConfig{},
})
lc := &fakeLocalServeClient{}
// And now run the steps above.
for i, st := range steps {

@ -82,7 +82,14 @@ func confirmUpdate(ver string) bool {
return false
}
fmt.Printf("This will update Tailscale from %v to %v. Continue? [y/n] ", version.Short(), ver)
msg := fmt.Sprintf("This will update Tailscale from %v to %v. Continue?", version.Short(), ver)
return promptYesNo(msg)
}
// PromptYesNo takes a question and prompts the user to answer the
// question with a yes or no. It appends a [y/n] to the message.
func promptYesNo(msg string) bool {
fmt.Print(msg + " [y/n] ")
var resp string
fmt.Scanln(&resp)
resp = strings.ToLower(resp)

Loading…
Cancel
Save