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>
This commit is contained in:
parent
e561f1ce61
commit
60e768fd14
|
@ -164,6 +164,7 @@ type serveEnv struct {
|
||||||
tcp string // TCP port
|
tcp string // TCP port
|
||||||
tlsTerminatedTCP string // a TLS terminated TCP port
|
tlsTerminatedTCP string // a TLS terminated TCP port
|
||||||
subcmd serveMode // subcommand
|
subcmd serveMode // subcommand
|
||||||
|
yes bool // update without prompt
|
||||||
|
|
||||||
lc localServeClient // localClient interface, specific to serve
|
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.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.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.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,
|
UsageFunc: usageFunc,
|
||||||
Subcommands: []*ffcli.Command{
|
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")
|
return errors.New("cannot remove web handler; currently serving TCP")
|
||||||
}
|
}
|
||||||
|
|
||||||
hp := ipn.HostPort(net.JoinHostPort(dnsName, strconv.Itoa(int(srvPort))))
|
portStr := strconv.Itoa(int(srvPort))
|
||||||
if !sc.WebHandlerExists(hp, mount) {
|
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")
|
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 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 {
|
if len(sc.Web[hp].Handlers) == 0 {
|
||||||
delete(sc.Web, hp)
|
delete(sc.Web, hp)
|
||||||
delete(sc.TCP, srvPort)
|
delete(sc.TCP, srvPort)
|
||||||
|
|
|
@ -725,6 +725,40 @@ func TestServeDevConfigMutations(t *testing.T) {
|
||||||
wantErr: anyErr(),
|
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{}
|
lc := &fakeLocalServeClient{}
|
||||||
// And now run the steps above.
|
// And now run the steps above.
|
||||||
for i, st := range steps {
|
for i, st := range steps {
|
||||||
|
|
|
@ -82,7 +82,14 @@ func confirmUpdate(ver string) bool {
|
||||||
return false
|
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
|
var resp string
|
||||||
fmt.Scanln(&resp)
|
fmt.Scanln(&resp)
|
||||||
resp = strings.ToLower(resp)
|
resp = strings.ToLower(resp)
|
||||||
|
|
Loading…
Reference in New Issue