Skip to content

Commit

Permalink
fix: lookup hosts before passing to NewOnAddresses (#5245)
Browse files Browse the repository at this point in the history
* fix: lookup hosts before passing to NewOnAddresses

* fix: propagate lookupErr

* fix: handle `--host '[::1]'` IPv6 literals

* fix: distinguish between address in use and other errors

```
$ tilt up --port 10350
Tilt started on http://localhost:10350/
v0.23.1-dev, built 2021-12-02
Error: Tilt cannot start because you already have another process on port 10350
If you want to run multiple Tilt instances simultaneously,
use the --port flag or TILT_PORT env variable to set a custom port
Original error: listen tcp 127.0.0.1:10350: bind: address already in use

$ tilt up --host '[::1' --port 10351
Tilt started (without browser UI)
v0.23.1-dev, built 2021-12-02
Error: listen tcp: address [::1:10351: missing ']' in address
```

* fix: filter out addresses that can't be listened

* errors: clean up error handling
  • Loading branch information
nicksieger committed Dec 3, 2021
1 parent 763c450 commit 03a51a8
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 5 deletions.
11 changes: 7 additions & 4 deletions internal/hud/server/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,13 @@ func ProvideConfigAccess(dir *dirs.TiltDevDir) clientcmd.ConfigAccess {
func ProvideWebListener(host model.WebHost, port model.WebPort) (WebListener, error) {
webListener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", string(host), int(port)))
if err != nil {
return nil, fmt.Errorf("Tilt cannot start because you already have another process on port %d\n"+
"If you want to run multiple Tilt instances simultaneously,\n"+
"use the --port flag or TILT_PORT env variable to set a custom port\nOriginal error: %v",
port, err)
if strings.HasSuffix(err.Error(), "address already in use") {
return nil, fmt.Errorf("Tilt cannot start because you already have another process on port %d\n"+
"If you want to run multiple Tilt instances simultaneously,\n"+
"use the --port flag or TILT_PORT env variable to set a custom port\nOriginal error: %v",
port, err)
}
return nil, err
}
return WebListener(webListener), nil
}
Expand Down
37 changes: 36 additions & 1 deletion internal/k8s/portforward.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"fmt"
"net"
"net/http"
"net/url"
"strconv"
"strings"

v1 "k8s.io/client-go/kubernetes/typed/core/v1"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // registers gcp auth provider
Expand Down Expand Up @@ -130,7 +132,11 @@ func (c portForwardClient) CreatePortForwarder(ctx context.Context, namespace Na
ports,
readyChan)
} else {
addresses := []string{host}
var addresses []string
addresses, err = getListenableAddresses(host)
if err != nil {
return nil, err
}
pf, err = portforward.NewOnAddresses(
ctx,
dialer,
Expand All @@ -148,6 +154,35 @@ func (c portForwardClient) CreatePortForwarder(ctx context.Context, namespace Na
}, nil
}

func getListenableAddresses(host string) ([]string, error) {
// handle IPv6 literals like `[::1]`
url, err := url.Parse(fmt.Sprintf("http://%s/", host))
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("invalid host %s", host))
}
addresses, err := net.LookupHost(url.Hostname())
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("failed to look up address for %s", host))
}
listenable := make([]string, 0)
for _, addr := range addresses {
var l net.Listener
if ipv6 := strings.Contains(addr, ":"); ipv6 {
l, err = net.Listen("tcp6", fmt.Sprintf("[%s]:0", addr))
} else {
l, err = net.Listen("tcp4", fmt.Sprintf("%s:0", addr))
}
if err == nil {
l.Close()
listenable = append(listenable, addr)
}
}
if len(listenable) == 0 {
return nil, errors.Errorf("host %s: cannot listen on any resolved addresses: %v", host, addresses)
}
return listenable, nil
}

func getAvailablePort() (int, error) {
l, err := net.Listen("tcp", ":0")
if err != nil {
Expand Down

0 comments on commit 03a51a8

Please sign in to comment.