Skip to content

Commit 5460ab4

Browse files
authored
chore: switch to new wgtunnel via tunnelsdk (#6489)
1 parent e85a17b commit 5460ab4

File tree

12 files changed

+388
-455
lines changed

12 files changed

+388
-455
lines changed

cli/server.go

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ import (
8585
"github.com/coder/coder/provisionersdk"
8686
sdkproto "github.com/coder/coder/provisionersdk/proto"
8787
"github.com/coder/coder/tailnet"
88+
"github.com/coder/wgtunnel/tunnelsdk"
8889
)
8990

9091
// ReadGitAuthProvidersFromEnv is provided for compatibility purposes with the
@@ -538,34 +539,25 @@ flags, and YAML configuration. The precedence is as follows:
538539
return xerrors.Errorf("configure http client: %w", err)
539540
}
540541

541-
var (
542-
ctxTunnel, closeTunnel = context.WithCancel(ctx)
543-
tunnel *devtunnel.Tunnel
544-
tunnelErr <-chan error
545-
)
546-
defer closeTunnel()
547-
548542
// If the access URL is empty, we attempt to run a reverse-proxy
549543
// tunnel to make the initial setup really simple.
544+
var (
545+
tunnel *tunnelsdk.Tunnel
546+
tunnelDone <-chan struct{} = make(chan struct{}, 1)
547+
)
550548
if cfg.AccessURL.String() == "" {
551549
cmd.Printf("Opening tunnel so workspaces can connect to your deployment. For production scenarios, specify an external access URL\n")
552-
tunnel, tunnelErr, err = devtunnel.New(ctxTunnel, logger.Named("devtunnel"))
550+
tunnel, err = devtunnel.New(ctx, logger.Named("devtunnel"), cfg.WgtunnelHost.String())
553551
if err != nil {
554552
return xerrors.Errorf("create tunnel: %w", err)
555553
}
556-
err = cfg.AccessURL.Set(tunnel.URL)
557-
if err != nil {
558-
return xerrors.Errorf("set access url: %w", err)
559-
}
554+
defer tunnel.Close()
555+
tunnelDone = tunnel.Wait()
556+
cfg.AccessURL = clibase.URL(*tunnel.URL)
560557

561558
if cfg.WildcardAccessURL.String() == "" {
562-
u, err := parseURL(tunnel.URL)
563-
if err != nil {
564-
return xerrors.Errorf("parse tunnel url: %w", err)
565-
}
566-
567559
// Suffixed wildcard access URL.
568-
u, err = url.Parse(fmt.Sprintf("*--%s", u.Hostname()))
560+
u, err := url.Parse(fmt.Sprintf("*--%s", tunnel.URL.Hostname()))
569561
if err != nil {
570562
return xerrors.Errorf("parse wildcard url: %w", err)
571563
}
@@ -1090,10 +1082,8 @@ flags, and YAML configuration. The precedence is as follows:
10901082
_, _ = fmt.Fprintln(cmd.OutOrStdout(), cliui.Styles.Bold.Render(
10911083
"Interrupt caught, gracefully exiting. Use ctrl+\\ to force quit",
10921084
))
1093-
case exitErr = <-tunnelErr:
1094-
if exitErr == nil {
1095-
exitErr = xerrors.New("dev tunnel closed unexpectedly")
1096-
}
1085+
case <-tunnelDone:
1086+
exitErr = xerrors.New("dev tunnel closed unexpectedly")
10971087
case exitErr = <-errCh:
10981088
}
10991089
if exitErr != nil && !xerrors.Is(exitErr, context.Canceled) {
@@ -1162,8 +1152,8 @@ flags, and YAML configuration. The precedence is as follows:
11621152
// Close tunnel after we no longer have in-flight connections.
11631153
if tunnel != nil {
11641154
cmd.Println("Waiting for tunnel to close...")
1165-
closeTunnel()
1166-
<-tunnelErr
1155+
_ = tunnel.Close()
1156+
<-tunnel.Wait()
11671157
cmd.Println("Done waiting for tunnel")
11681158
}
11691159

@@ -1241,22 +1231,6 @@ flags, and YAML configuration. The precedence is as follows:
12411231
return root
12421232
}
12431233

1244-
// parseURL parses a string into a URL.
1245-
func parseURL(u string) (*url.URL, error) {
1246-
hasScheme := strings.HasPrefix(u, "http:") || strings.HasPrefix(u, "https:")
1247-
1248-
if !hasScheme {
1249-
return nil, xerrors.Errorf("URL %q must have a scheme of either http or https", u)
1250-
}
1251-
1252-
parsed, err := url.Parse(u)
1253-
if err != nil {
1254-
return nil, err
1255-
}
1256-
1257-
return parsed, nil
1258-
}
1259-
12601234
// isLocalURL returns true if the hostname of the provided URL appears to
12611235
// resolve to a loopback address.
12621236
func isLocalURL(ctx context.Context, u *url.URL) (bool, error) {

coderd/apidoc/docs.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/devtunnel/servers.go

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/go-ping/ping"
99
"golang.org/x/exp/slices"
1010
"golang.org/x/sync/errgroup"
11+
"golang.org/x/xerrors"
1112

1213
"github.com/coder/coder/cryptorand"
1314
)
@@ -19,13 +20,11 @@ type Region struct {
1920
}
2021

2122
type Node struct {
22-
ID int `json:"id"`
23-
RegionID int `json:"region_id"`
24-
HostnameHTTPS string `json:"hostname_https"`
25-
HostnameWireguard string `json:"hostname_wireguard"`
26-
WireguardPort uint16 `json:"wireguard_port"`
23+
ID int `json:"id"`
24+
RegionID int `json:"region_id"`
25+
HostnameHTTPS string `json:"hostname_https"`
2726

28-
AvgLatency time.Duration `json:"avg_latency"`
27+
AvgLatency time.Duration `json:"-"`
2928
}
3029

3130
var Regions = []Region{
@@ -34,28 +33,53 @@ var Regions = []Region{
3433
LocationName: "US East Pittsburgh",
3534
Nodes: []Node{
3635
{
37-
ID: 1,
38-
RegionID: 0,
39-
HostnameHTTPS: "pit-1.try.coder.app",
40-
HostnameWireguard: "pit-1.try.coder.app",
41-
WireguardPort: 55551,
36+
ID: 1,
37+
RegionID: 0,
38+
HostnameHTTPS: "pit-1.try.coder.app",
4239
},
4340
},
4441
},
4542
}
4643

47-
func FindClosestNode() (Node, error) {
44+
// Nodes returns a list of nodes to use for the tunnel. It will pick a random
45+
// node from each region.
46+
//
47+
// If a customNode is provided, it will be returned as the only node with ID
48+
// 9999.
49+
func Nodes(customTunnelHost string) ([]Node, error) {
4850
nodes := []Node{}
4951

52+
if customTunnelHost != "" {
53+
return []Node{
54+
{
55+
ID: 9999,
56+
RegionID: 9999,
57+
HostnameHTTPS: customTunnelHost,
58+
},
59+
}, nil
60+
}
61+
5062
for _, region := range Regions {
5163
// Pick a random node from each region.
5264
i, err := cryptorand.Intn(len(region.Nodes))
5365
if err != nil {
54-
return Node{}, err
66+
return []Node{}, err
5567
}
5668
nodes = append(nodes, region.Nodes[i])
5769
}
5870

71+
return nodes, nil
72+
}
73+
74+
// FindClosestNode pings each node and returns the one with the lowest latency.
75+
func FindClosestNode(nodes []Node) (Node, error) {
76+
if len(nodes) == 0 {
77+
return Node{}, xerrors.New("no wgtunnel nodes")
78+
}
79+
80+
// Copy the nodes so we don't mutate the original.
81+
nodes = append([]Node{}, nodes...)
82+
5983
var (
6084
nodesMu sync.Mutex
6185
eg = errgroup.Group{}

0 commit comments

Comments
 (0)