From 6658eee7273c38bd831fc00d77ae4b52586f36cc Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Tue, 7 Mar 2023 17:54:35 +0000 Subject: [PATCH 01/10] chore: switch to new wgtunnel via tunnelsdk --- cli/server.go | 31 ++--- coderd/devtunnel/servers.go | 22 +++- coderd/devtunnel/tunnel.go | 207 +++++--------------------------- coderd/devtunnel/tunnel_test.go | 2 +- go.mod | 51 ++++---- go.sum | 29 +++++ 6 files changed, 117 insertions(+), 225 deletions(-) diff --git a/cli/server.go b/cli/server.go index 2129b6fca3b6a..389f4c46c99b4 100644 --- a/cli/server.go +++ b/cli/server.go @@ -81,6 +81,7 @@ import ( "github.com/coder/coder/provisionersdk" sdkproto "github.com/coder/coder/provisionersdk/proto" "github.com/coder/coder/tailnet" + "github.com/coder/wgtunnel/tunnelsdk" ) // nolint:gocyclo @@ -347,31 +348,21 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co return xerrors.Errorf("configure http client: %w", err) } - var ( - ctxTunnel, closeTunnel = context.WithCancel(ctx) - tunnel *devtunnel.Tunnel - tunnelErr <-chan error - ) - defer closeTunnel() - // If the access URL is empty, we attempt to run a reverse-proxy // tunnel to make the initial setup really simple. + var tunnel *tunnelsdk.Tunnel if cfg.AccessURL.Value == "" { cmd.Printf("Opening tunnel so workspaces can connect to your deployment. For production scenarios, specify an external access URL\n") - tunnel, tunnelErr, err = devtunnel.New(ctxTunnel, logger.Named("devtunnel")) + tunnel, err = devtunnel.New(ctx, logger.Named("devtunnel")) if err != nil { return xerrors.Errorf("create tunnel: %w", err) } - cfg.AccessURL.Value = tunnel.URL + defer tunnel.Close() + cfg.AccessURL.Value = tunnel.URL.String() if cfg.WildcardAccessURL.Value == "" { - u, err := parseURL(tunnel.URL) - if err != nil { - return xerrors.Errorf("parse tunnel url: %w", err) - } - // Suffixed wildcard access URL. - cfg.WildcardAccessURL.Value = fmt.Sprintf("*--%s", u.Hostname()) + cfg.WildcardAccessURL.Value = fmt.Sprintf("*--%s", tunnel.URL.Hostname()) } } @@ -824,10 +815,8 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co _, _ = fmt.Fprintln(cmd.OutOrStdout(), cliui.Styles.Bold.Render( "Interrupt caught, gracefully exiting. Use ctrl+\\ to force quit", )) - case exitErr = <-tunnelErr: - if exitErr == nil { - exitErr = xerrors.New("dev tunnel closed unexpectedly") - } + case <-tunnel.Wait(): + exitErr = xerrors.New("dev tunnel closed unexpectedly") case exitErr = <-errCh: } if exitErr != nil && !xerrors.Is(exitErr, context.Canceled) { @@ -896,8 +885,8 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co // Close tunnel after we no longer have in-flight connections. if tunnel != nil { cmd.Println("Waiting for tunnel to close...") - closeTunnel() - <-tunnelErr + _ = tunnel.Close() + <-tunnel.Wait() cmd.Println("Done waiting for tunnel") } diff --git a/coderd/devtunnel/servers.go b/coderd/devtunnel/servers.go index 7025fb9c715a6..bdc4b7f8d1453 100644 --- a/coderd/devtunnel/servers.go +++ b/coderd/devtunnel/servers.go @@ -8,6 +8,7 @@ import ( "github.com/go-ping/ping" "golang.org/x/exp/slices" "golang.org/x/sync/errgroup" + "golang.org/x/xerrors" "github.com/coder/coder/cryptorand" ) @@ -44,18 +45,35 @@ var Regions = []Region{ }, } -func FindClosestNode() (Node, error) { +// Nodes returns a list of nodes to use for the tunnel. It will pick a random +// node from each region. +func Nodes() ([]Node, error) { nodes := []Node{} for _, region := range Regions { // Pick a random node from each region. i, err := cryptorand.Intn(len(region.Nodes)) if err != nil { - return Node{}, err + return []Node{}, err } nodes = append(nodes, region.Nodes[i]) } + return nodes, nil +} + +// FindClosestNode pings each node and returns the one with the lowest latency. +func FindClosestNode(nodes []Node) (Node, error) { + if len(nodes) == 0 { + return Node{}, xerrors.New("no wgtunnel nodes") + } + if len(nodes) == 1 { + return nodes[0], nil + } + + // Copy the nodes so we don't mutate the original. + nodes = append([]Node{}, nodes...) + var ( nodesMu sync.Mutex eg = errgroup.Group{} diff --git a/coderd/devtunnel/tunnel.go b/coderd/devtunnel/tunnel.go index d0d8a9f46616e..b43349c116ffe 100644 --- a/coderd/devtunnel/tunnel.go +++ b/coderd/devtunnel/tunnel.go @@ -1,134 +1,49 @@ package devtunnel import ( - "bytes" "context" - "encoding/hex" "encoding/json" "fmt" - "net" "net/http" - "net/netip" + "net/url" "os" "path/filepath" "time" "github.com/briandowns/spinner" "golang.org/x/xerrors" - "golang.zx2c4.com/wireguard/conn" "golang.zx2c4.com/wireguard/device" - "golang.zx2c4.com/wireguard/tun/netstack" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" "cdr.dev/slog" "github.com/coder/coder/cli/cliui" "github.com/coder/coder/cryptorand" + "github.com/coder/wgtunnel/tunnelsdk" ) -type Tunnel struct { - URL string - Listener net.Listener -} - type Config struct { - Version int `json:"version"` - PrivateKey device.NoisePrivateKey `json:"private_key"` - PublicKey device.NoisePublicKey `json:"public_key"` + Version tunnelsdk.TunnelVersion `json:"version"` + PrivateKey device.NoisePrivateKey `json:"private_key"` + PublicKey device.NoisePublicKey `json:"public_key"` Tunnel Node `json:"tunnel"` // Used in testing. Normally this is nil, indicating to use DefaultClient. HTTPClient *http.Client `json:"-"` } -type configExt struct { - Version int `json:"-"` - PrivateKey device.NoisePrivateKey `json:"-"` - PublicKey device.NoisePublicKey `json:"public_key"` - - Tunnel Node `json:"-"` - - // Used in testing. Normally this is nil, indicating to use DefaultClient. - HTTPClient *http.Client `json:"-"` -} // NewWithConfig calls New with the given config. For documentation, see New. -func NewWithConfig(ctx context.Context, logger slog.Logger, cfg Config) (*Tunnel, <-chan error, error) { - server, routineEnd, err := startUpdateRoutine(ctx, logger, cfg) - if err != nil { - return nil, nil, xerrors.Errorf("start update routine: %w", err) - } - - tun, tnet, err := netstack.CreateNetTUN( - []netip.Addr{server.ClientIP}, - []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}, - 1280, - ) - if err != nil { - return nil, nil, xerrors.Errorf("create net TUN: %w", err) - } - - wgip, err := net.ResolveIPAddr("ip", cfg.Tunnel.HostnameWireguard) - if err != nil { - return nil, nil, xerrors.Errorf("resolve endpoint: %w", err) - } - // In IPv6, we need to enclose the address to in [] before passing to wireguard's endpoint key, like - // [2001:abcd::1]:8888. We'll use netip.AddrPort to correctly handle this. - wgAddr, err := netip.ParseAddr(wgip.String()) - if err != nil { - return nil, nil, xerrors.Errorf("parse address: %w", err) - } - wgEndpoint := netip.AddrPortFrom(wgAddr, cfg.Tunnel.WireguardPort) - - dlog := &device.Logger{ - Verbosef: slog.Stdlib(ctx, logger, slog.LevelDebug).Printf, - Errorf: slog.Stdlib(ctx, logger, slog.LevelError).Printf, - } - dev := device.NewDevice(tun, conn.NewDefaultBind(), dlog) - err = dev.IpcSet(fmt.Sprintf(`private_key=%s -public_key=%s -endpoint=%s -persistent_keepalive_interval=21 -allowed_ip=%s/128`, - hex.EncodeToString(cfg.PrivateKey[:]), - server.ServerPublicKey, - wgEndpoint.String(), - server.ServerIP.String(), - )) - if err != nil { - return nil, nil, xerrors.Errorf("configure wireguard ipc: %w", err) - } - - err = dev.Up() - if err != nil { - return nil, nil, xerrors.Errorf("wireguard device up: %w", err) - } - - wgListen, err := tnet.ListenTCP(&net.TCPAddr{Port: 8090}) - if err != nil { - return nil, nil, xerrors.Errorf("wireguard device listen: %w", err) - } - - ch := make(chan error, 1) - go func() { - select { - case <-ctx.Done(): - _ = wgListen.Close() - // We need to remove peers before closing to avoid a race condition between dev.Close() and the peer - // goroutines which results in segfault. - dev.RemoveAllPeers() - dev.Close() - <-routineEnd - close(ch) - - case <-dev.Wait(): - close(ch) - } - }() - - return &Tunnel{ - URL: fmt.Sprintf("https://%s", server.Hostname), - Listener: wgListen, - }, ch, nil +func NewWithConfig(ctx context.Context, logger slog.Logger, cfg Config) (*tunnelsdk.Tunnel, error) { + u := &url.URL{ + Scheme: "https", + Host: cfg.Tunnel.HostnameHTTPS, + } + + c := tunnelsdk.New(u) + return c.LaunchTunnel(ctx, tunnelsdk.TunnelConfig{ + Log: logger, + Version: cfg.Version, + PrivateKey: tunnelsdk.FromNoisePrivateKey(cfg.PrivateKey), + }) } // New creates a tunnel with a public URL and returns a listener for incoming @@ -136,82 +51,18 @@ allowed_ip=%s/128`, // Tunnel configuration is cached in the user's config directory. Successive // calls to New will always use the same URL. If multiple public URLs in // parallel are required, use NewWithConfig. -func New(ctx context.Context, logger slog.Logger) (*Tunnel, <-chan error, error) { +// +// This uses https://github.com/coder/wgtunnel as the server and client +// implementation. +func New(ctx context.Context, logger slog.Logger) (*tunnelsdk.Tunnel, error) { cfg, err := readOrGenerateConfig() if err != nil { - return nil, nil, xerrors.Errorf("read or generate config: %w", err) + return nil, xerrors.Errorf("read or generate config: %w", err) } return NewWithConfig(ctx, logger, cfg) } -func startUpdateRoutine(ctx context.Context, logger slog.Logger, cfg Config) (ServerResponse, <-chan struct{}, error) { - // Ensure we send the first config before spawning in the background. - res, err := sendConfigToServer(ctx, cfg) - if err != nil { - return ServerResponse{}, nil, xerrors.Errorf("send config to server: %w", err) - } - - endCh := make(chan struct{}) - go func() { - defer close(endCh) - ticker := time.NewTicker(10 * time.Second) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return - - case <-ticker.C: - } - - _, err := sendConfigToServer(ctx, cfg) - if err != nil { - logger.Debug(ctx, "send tunnel config to server", slog.Error(err)) - } - } - }() - return res, endCh, nil -} - -type ServerResponse struct { - Hostname string `json:"hostname"` - ServerIP netip.Addr `json:"server_ip"` - ServerPublicKey string `json:"server_public_key"` // hex - ClientIP netip.Addr `json:"client_ip"` -} - -func sendConfigToServer(ctx context.Context, cfg Config) (ServerResponse, error) { - raw, err := json.Marshal(configExt(cfg)) - if err != nil { - return ServerResponse{}, xerrors.Errorf("marshal config: %w", err) - } - - req, err := http.NewRequestWithContext(ctx, "POST", "https://"+cfg.Tunnel.HostnameHTTPS+"/tun", bytes.NewReader(raw)) - if err != nil { - return ServerResponse{}, xerrors.Errorf("new request: %w", err) - } - - client := http.DefaultClient - if cfg.HTTPClient != nil { - client = cfg.HTTPClient - } - res, err := client.Do(req) - if err != nil { - return ServerResponse{}, xerrors.Errorf("do request: %w", err) - } - defer res.Body.Close() - - var resp ServerResponse - err = json.NewDecoder(res.Body).Decode(&resp) - if err != nil { - return ServerResponse{}, xerrors.Errorf("decode response: %w", err) - } - - return resp, nil -} - func cfgPath() (string, error) { cfgDir, err := os.UserConfigDir() if err != nil { @@ -281,11 +132,15 @@ func readOrGenerateConfig() (Config, error) { } func GenerateConfig() (Config, error) { - priv, err := wgtypes.GeneratePrivateKey() + priv, err := tunnelsdk.GeneratePrivateKey() if err != nil { return Config{}, xerrors.Errorf("generate private key: %w", err) } - pub := priv.PublicKey() + privNoisePublicKey, err := priv.NoisePrivateKey() + if err != nil { + return Config{}, xerrors.Errorf("generate noise private key: %w", err) + } + pubNoisePublicKey := priv.NoisePublicKey() spin := spinner.New(spinner.CharSets[39], 350*time.Millisecond) spin.Suffix = " Finding the closest tunnel region..." @@ -309,9 +164,9 @@ func GenerateConfig() (Config, error) { ) return Config{ - Version: 1, - PrivateKey: device.NoisePrivateKey(priv), - PublicKey: device.NoisePublicKey(pub), + Version: tunnelsdk.TunnelVersion2, + PrivateKey: privNoisePublicKey, + PublicKey: pubNoisePublicKey, Tunnel: node, }, nil } diff --git a/coderd/devtunnel/tunnel_test.go b/coderd/devtunnel/tunnel_test.go index 9bf435ce3233a..5b8a26662d318 100644 --- a/coderd/devtunnel/tunnel_test.go +++ b/coderd/devtunnel/tunnel_test.go @@ -67,7 +67,7 @@ func TestTunnel(t *testing.T) { fTunServer := newFakeTunnelServer(t) cfg := fTunServer.config() - tun, errCh, err := devtunnel.NewWithConfig(ctx, slogtest.Make(t, nil).Leveled(slog.LevelDebug), cfg) + tun, errCh, err := devtunnel.New(ctx, slogtest.Make(t, nil).Leveled(slog.LevelDebug), cfg) require.NoError(t, err) t.Log(tun.URL) diff --git a/go.mod b/go.mod index f2d110e5cfca5..8646589a6a702 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ replace github.com/imulab/go-scim/pkg/v2 => github.com/coder/go-scim/pkg/v2 v2.0 require ( cdr.dev/slog v1.4.2-0.20220525200111-18dce5c2cd5f - cloud.google.com/go/compute/metadata v0.2.1 + cloud.google.com/go/compute/metadata v0.2.3 github.com/AlecAivazis/survey/v2 v2.3.5 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/adrg/xdg v0.4.0 @@ -80,7 +80,7 @@ require ( github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/creack/pty v1.1.18 github.com/elastic/go-sysinfo v1.9.0 - github.com/fatih/color v1.13.0 + github.com/fatih/color v1.14.1 github.com/fatih/structs v1.1.0 github.com/fatih/structtag v1.2.0 github.com/fergusstrange/embedded-postgres v1.16.0 @@ -89,7 +89,7 @@ require ( github.com/gliderlabs/ssh v0.3.4 github.com/go-chi/chi v1.5.4 github.com/go-chi/chi/v5 v5.0.7 - github.com/go-chi/httprate v0.7.0 + github.com/go-chi/httprate v0.7.1 github.com/go-chi/render v1.0.1 github.com/go-logr/logr v1.2.3 github.com/go-ping/ping v1.1.0 @@ -145,30 +145,30 @@ require ( github.com/wagslane/go-password-validator v0.3.0 go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 go.nhat.io/otelsql v0.7.0 - go.opentelemetry.io/otel v1.11.1 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 + go.opentelemetry.io/otel v1.13.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.13.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.13.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1 - go.opentelemetry.io/otel/sdk v1.11.1 - go.opentelemetry.io/otel/trace v1.11.1 + go.opentelemetry.io/otel/sdk v1.13.0 + go.opentelemetry.io/otel/trace v1.13.0 go.uber.org/atomic v1.10.0 go.uber.org/goleak v1.2.0 go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf golang.org/x/crypto v0.6.0 golang.org/x/exp v0.0.0-20221205204356-47842c84f3db golang.org/x/mod v0.8.0 - golang.org/x/oauth2 v0.3.0 + golang.org/x/oauth2 v0.5.0 golang.org/x/sync v0.1.0 golang.org/x/sys v0.5.0 golang.org/x/term v0.5.0 golang.org/x/text v0.7.0 golang.org/x/tools v0.6.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 - golang.zx2c4.com/wireguard v0.0.0-20230207233929-ebbd4a433088 - golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220504211119-3d4a969bb56b - google.golang.org/api v0.103.0 - google.golang.org/grpc v1.52.3 - google.golang.org/protobuf v1.28.1 + golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675 + golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde + google.golang.org/api v0.108.0 + google.golang.org/grpc v1.53.0 + google.golang.org/protobuf v1.28.2-0.20230118093459-a9481185b34d gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v3 v3.0.1 @@ -180,6 +180,7 @@ require ( ) require ( + github.com/coder/wgtunnel v0.1.1 // indirect github.com/dgraph-io/badger/v3 v3.2103.5 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/google/flatbuffers v23.1.21+incompatible // indirect @@ -194,7 +195,7 @@ require ( ) require ( - cloud.google.com/go/compute v1.12.1 // indirect + cloud.google.com/go/compute v1.18.0 // indirect cloud.google.com/go/longrunning v0.3.0 // indirect filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect @@ -222,7 +223,7 @@ require ( github.com/containerd/continuity v0.3.0 // indirect github.com/coreos/go-iptables v0.6.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dlclark/regexp2 v1.8.1 // indirect github.com/docker/cli v20.10.17+incompatible // indirect github.com/docker/docker v20.10.17+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -246,13 +247,13 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/btree v1.0.1 // indirect + github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect github.com/gorilla/css v1.0.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect @@ -280,11 +281,11 @@ require ( github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/mailru/easyjson v0.7.6 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mdlayher/genetlink v1.2.0 // indirect - github.com/mdlayher/netlink v1.6.0 // indirect + github.com/mdlayher/netlink v1.6.2 // indirect github.com/mdlayher/sdnotify v1.0.0 // indirect github.com/mdlayher/socket v0.2.3 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect @@ -345,16 +346,16 @@ require ( github.com/zclconf/go-cty v1.10.0 // indirect github.com/zeebo/errs v1.3.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect - go.opentelemetry.io/otel/metric v0.33.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.13.0 // indirect + go.opentelemetry.io/otel/metric v0.36.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect go4.org/mem v0.0.0-20210711025021-927187094b94 // indirect golang.org/x/net v0.7.0 // indirect - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect + golang.org/x/time v0.3.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wireguard/windows v0.5.3 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect + google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect howett.net/plist v1.0.0 // indirect diff --git a/go.sum b/go.sum index 901c2871009fa..62f0da92ee3a6 100644 --- a/go.sum +++ b/go.sum @@ -52,8 +52,10 @@ cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLq cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= @@ -381,6 +383,8 @@ github.com/coder/tailscale v1.1.1-0.20230307022319-1e5e724a3949 h1:8WfMfRTDaEpnm github.com/coder/tailscale v1.1.1-0.20230307022319-1e5e724a3949/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA= github.com/coder/terraform-provider-coder v0.6.15 h1:Llvh4RwxSQ/goy7ToTOeHf3tdEz+79qbyOh61hNnJs0= github.com/coder/terraform-provider-coder v0.6.15/go.mod h1:UIfU3bYNeSzJJvHyJ30tEKjD6Z9utloI+HUM/7n94CY= +github.com/coder/wgtunnel v0.1.1 h1:w9cF5886y31UJAuku+mI82cxl9z2HwRznVLOU5u4xHw= +github.com/coder/wgtunnel v0.1.1/go.mod h1:Cp45q9/LLkPyF2XJqL1d+pu14USYWuh79LI4eJwY7X4= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= @@ -545,6 +549,7 @@ github.com/dhui/dktest v0.3.10/go.mod h1:h5Enh0nG3Qbo9WjNFRrwmKUaePEBhXMOygbz3Ww github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.8.1/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= @@ -606,6 +611,7 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= @@ -658,6 +664,7 @@ github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/httprate v0.7.0 h1:8W0dF7Xa2Duz2p8ncGaehIphrxQGNlOtoGY0+NRRfjQ= github.com/go-chi/httprate v0.7.0/go.mod h1:6GOYBSwnpra4CQfAKXu8sQZg+nZ0M1g9QnyFvxrAB8A= +github.com/go-chi/httprate v0.7.1/go.mod h1:6GOYBSwnpra4CQfAKXu8sQZg+nZ0M1g9QnyFvxrAB8A= github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= github.com/go-critic/go-critic v0.6.1/go.mod h1:SdNCfU0yF3UBjtaZGw6586/WocupMOJuiqgom5DsQxM= @@ -877,6 +884,7 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= @@ -943,6 +951,7 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -998,6 +1007,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqC github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.1/go.mod h1:gYC+WX4YJFarA2ie73G2epzt7TBWpo9pzcBnK1g0MSw= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= @@ -1332,6 +1342,7 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -1381,6 +1392,7 @@ github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcK github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0= github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= +github.com/mdlayher/netlink v1.6.2/go.mod h1:O1HXX2sIWSMJ3Qn1BYZk1yZM+7iMki/uYGGiwGyq/iU= github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= github.com/mdlayher/sdnotify v1.0.0 h1:Ma9XeLVN/l0qpyx1tNeMSeTjCPH6NtuD6/N9XdTlQ3c= @@ -1986,16 +1998,20 @@ go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzox go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= go.opentelemetry.io/otel v1.11.1 h1:4WLLAmcfkmDk2ukNXJyq3/kiz/3UzCaYq6PskJsaou4= go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZMSbUGE= +go.opentelemetry.io/otel v1.13.0/go.mod h1:FH3RtdZCzRkJYFTCsAKDy9l/XYjMdNv6QrkFFB8DvVg= go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 h1:X2GndnMCsUPh6CiY2a+frAbNsXaPLbB0soHRYhAZ5Ig= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1/go.mod h1:i8vjiSzbiUC7wOQplijSXMYUpNM93DtlS5CbUT+C6oQ= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.13.0/go.mod h1:rqbht/LlhVBgn5+k3M5QK96K5Xb0DvXpMJ5SFQpY6uw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 h1:MEQNafcNCB0uQIti/oHgU7CZpUMYQ7qigBwMVKycHvc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1/go.mod h1:19O5I2U5iys38SsmT2uDJja/300woyzE1KPIQxEUBUc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.13.0/go.mod h1:46vAP6RWfNn7EKov73l5KBFlNxz8kYlxR1woU+bJ4ZY= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 h1:LYyG/f1W/jzAix16jbksJfMQFpOH/Ma6T639pVPMgfI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1/go.mod h1:QrRRQiY3kzAoYPNLP0W/Ikg0gR6V3LMc+ODSxr7yyvg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.13.0/go.mod h1:OhH1xvgA5jZW2M/S4PcvtDlFE1VULRRBsibBrKuJQGI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1 h1:tFl63cpAAcD9TOU6U8kZU7KyXuSRYAZlbx1C61aaB74= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1/go.mod h1:X620Jww3RajCJXw/unA+8IRTgxkdS7pi+ZwK9b7KUJk= @@ -2004,11 +2020,13 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.1 h1:3Yvzs7lgOw8Mmbx go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= go.opentelemetry.io/otel/metric v0.33.0 h1:xQAyl7uGEYvrLAiV/09iTJlp1pZnQ9Wl793qbVvED1E= go.opentelemetry.io/otel/metric v0.33.0/go.mod h1:QlTYc+EnYNq/M2mNk1qDDMRLpqCOj2f/r5c7Fd5FYaI= +go.opentelemetry.io/otel/metric v0.36.0/go.mod h1:wKVw57sd2HdSZAzyfOM9gTqqE8v7CbqWsYL6AyrH9qk= go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZpKxs= go.opentelemetry.io/otel/sdk v1.11.1/go.mod h1:/l3FE4SupHJ12TduVjUkZtlfFqDCQJlOlithYrdktys= +go.opentelemetry.io/otel/sdk v1.13.0/go.mod h1:YLKPx5+6Vx/o1TCUYYs+bpymtkmazOMT6zoRrC7AQ7I= go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= go.opentelemetry.io/otel/sdk/metric v0.33.0 h1:oTqyWfksgKoJmbrs2q7O7ahkJzt+Ipekihf8vhpa9qo= @@ -2016,6 +2034,7 @@ go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16g go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ= go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk= +go.opentelemetry.io/otel/trace v1.13.0/go.mod h1:muCvmmO9KKpvuXSf3KKAXXB2ygNYHQ+ZfI5X08d3tds= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= @@ -2229,6 +2248,7 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= @@ -2258,6 +2278,7 @@ golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7Lm golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2271,6 +2292,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2466,6 +2488,7 @@ golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2602,8 +2625,10 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard v0.0.0-20230207233929-ebbd4a433088 h1:AterY3udavhM90Dum0CUGAD5ZuYahpmBuYCPT3Pwe3A= golang.zx2c4.com/wireguard v0.0.0-20230207233929-ebbd4a433088/go.mod h1:whfbyDBt09xhCYQWtO2+3UVjlaq6/9hDZrjg2ZE6SyA= +golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675/go.mod h1:whfbyDBt09xhCYQWtO2+3UVjlaq6/9hDZrjg2ZE6SyA= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220504211119-3d4a969bb56b h1:9JncmKXcUwE918my+H6xmjBdhK2jM/UTUNXxhRG1BAk= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220504211119-3d4a969bb56b/go.mod h1:yp4gl6zOlnDGOZeWeDfMwQcsdOIQnMdhuPx9mwwWBL4= +golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde/go.mod h1:mQqgjkW8GQQcJQsbBvK890TKqUK1DfKWkuBGbOkuMHQ= golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE= golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= @@ -2657,6 +2682,7 @@ google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3 google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ= google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2766,6 +2792,7 @@ google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljW google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -2807,6 +2834,7 @@ google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2824,6 +2852,7 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.2-0.20230118093459-a9481185b34d/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 2faadc511b76e9ec3ac936bc7013d35162923ed5 Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Thu, 9 Mar 2023 18:07:21 +0000 Subject: [PATCH 02/10] chore: update wgtunnel --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 658b6f7a1e8e5..c94baa4488a31 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( github.com/coder/flog v1.0.0 github.com/coder/retry v1.3.1-0.20230210155434-e90a2e1e091d github.com/coder/terraform-provider-coder v0.6.15 - github.com/coder/wgtunnel v0.1.2 + github.com/coder/wgtunnel v0.1.4 github.com/coreos/go-oidc/v3 v3.4.0 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/creack/pty v1.1.18 diff --git a/go.sum b/go.sum index a538905d17592..32f0b6b220509 100644 --- a/go.sum +++ b/go.sum @@ -384,6 +384,8 @@ github.com/coder/terraform-provider-coder v0.6.15 h1:Llvh4RwxSQ/goy7ToTOeHf3tdEz github.com/coder/terraform-provider-coder v0.6.15/go.mod h1:UIfU3bYNeSzJJvHyJ30tEKjD6Z9utloI+HUM/7n94CY= github.com/coder/wgtunnel v0.1.2 h1:mYilWP3WW5HNeY4aj+C2YGaF2Yt7DTQ3S+F/PNRas6U= github.com/coder/wgtunnel v0.1.2/go.mod h1:bokoUrHnUFY4lu9KOeSYiIcHTI2MO1KwqumU4DPDyJI= +github.com/coder/wgtunnel v0.1.4 h1:ftUO0Z8AzPJuDP3ziYznGsMSaOgO4nKlAUhEh2voClA= +github.com/coder/wgtunnel v0.1.4/go.mod h1:bokoUrHnUFY4lu9KOeSYiIcHTI2MO1KwqumU4DPDyJI= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= From efd41a9179b3be9dc2e0ec01a73eb2e4080bd526 Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Thu, 9 Mar 2023 18:50:47 +0000 Subject: [PATCH 03/10] fixup! chore: update wgtunnel --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index c94baa4488a31..cbfa98612aca7 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( github.com/coder/flog v1.0.0 github.com/coder/retry v1.3.1-0.20230210155434-e90a2e1e091d github.com/coder/terraform-provider-coder v0.6.15 - github.com/coder/wgtunnel v0.1.4 + github.com/coder/wgtunnel v0.1.5 github.com/coreos/go-oidc/v3 v3.4.0 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/creack/pty v1.1.18 diff --git a/go.sum b/go.sum index 32f0b6b220509..ccae6a14e398a 100644 --- a/go.sum +++ b/go.sum @@ -386,6 +386,8 @@ github.com/coder/wgtunnel v0.1.2 h1:mYilWP3WW5HNeY4aj+C2YGaF2Yt7DTQ3S+F/PNRas6U= github.com/coder/wgtunnel v0.1.2/go.mod h1:bokoUrHnUFY4lu9KOeSYiIcHTI2MO1KwqumU4DPDyJI= github.com/coder/wgtunnel v0.1.4 h1:ftUO0Z8AzPJuDP3ziYznGsMSaOgO4nKlAUhEh2voClA= github.com/coder/wgtunnel v0.1.4/go.mod h1:bokoUrHnUFY4lu9KOeSYiIcHTI2MO1KwqumU4DPDyJI= +github.com/coder/wgtunnel v0.1.5 h1:WP3sCj/3iJ34eKvpMQEp1oJHvm24RYh0NHbj1kfUKfs= +github.com/coder/wgtunnel v0.1.5/go.mod h1:bokoUrHnUFY4lu9KOeSYiIcHTI2MO1KwqumU4DPDyJI= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= From 1f79acdf56f2266350826fb83afaaaad6636a101 Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Fri, 17 Mar 2023 04:41:29 +0000 Subject: [PATCH 04/10] feat: add --tunnel-host to control wgtunnel server --- cli/server.go | 2 +- coderd/devtunnel/servers.go | 33 +++++++++++++++++++++------------ coderd/devtunnel/tunnel.go | 14 +++++++------- coderd/devtunnel/tunnel_test.go | 6 +++--- codersdk/deployment.go | 14 ++++++++++++-- 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/cli/server.go b/cli/server.go index e758af2f20b6a..2c0c7f5f1b2f2 100644 --- a/cli/server.go +++ b/cli/server.go @@ -547,7 +547,7 @@ flags, and YAML configuration. The precedence is as follows: ) if cfg.AccessURL.String() == "" { cmd.Printf("Opening tunnel so workspaces can connect to your deployment. For production scenarios, specify an external access URL\n") - tunnel, err = devtunnel.New(ctx, logger.Named("devtunnel")) + tunnel, err = devtunnel.New(ctx, logger.Named("devtunnel"), cfg.TunnelHost.String()) if err != nil { return xerrors.Errorf("create tunnel: %w", err) } diff --git a/coderd/devtunnel/servers.go b/coderd/devtunnel/servers.go index bdc4b7f8d1453..2470177cb848c 100644 --- a/coderd/devtunnel/servers.go +++ b/coderd/devtunnel/servers.go @@ -20,13 +20,11 @@ type Region struct { } type Node struct { - ID int `json:"id"` - RegionID int `json:"region_id"` - HostnameHTTPS string `json:"hostname_https"` - HostnameWireguard string `json:"hostname_wireguard"` - WireguardPort uint16 `json:"wireguard_port"` + ID int `json:"id"` + RegionID int `json:"region_id"` + HostnameHTTPS string `json:"hostname_https"` - AvgLatency time.Duration `json:"avg_latency"` + AvgLatency time.Duration `json:"-"` } var Regions = []Region{ @@ -35,11 +33,9 @@ var Regions = []Region{ LocationName: "US East Pittsburgh", Nodes: []Node{ { - ID: 1, - RegionID: 0, - HostnameHTTPS: "pit-1.try.coder.app", - HostnameWireguard: "pit-1.try.coder.app", - WireguardPort: 55551, + ID: 1, + RegionID: 0, + HostnameHTTPS: "pit-1.try.coder.app", }, }, }, @@ -47,9 +43,22 @@ var Regions = []Region{ // Nodes returns a list of nodes to use for the tunnel. It will pick a random // node from each region. -func Nodes() ([]Node, error) { +// +// If a customNode is provided, it will be returned as the only node with ID +// 9999. +func Nodes(customTunnelHost string) ([]Node, error) { nodes := []Node{} + if customTunnelHost != "" { + return []Node{ + { + ID: 9999, + RegionID: 9999, + HostnameHTTPS: customTunnelHost, + }, + }, nil + } + for _, region := range Regions { // Pick a random node from each region. i, err := cryptorand.Intn(len(region.Nodes)) diff --git a/coderd/devtunnel/tunnel.go b/coderd/devtunnel/tunnel.go index 1e1ae896b7929..f31e31e2a6f96 100644 --- a/coderd/devtunnel/tunnel.go +++ b/coderd/devtunnel/tunnel.go @@ -57,8 +57,8 @@ func NewWithConfig(ctx context.Context, logger slog.Logger, cfg Config) (*tunnel // // This uses https://github.com/coder/wgtunnel as the server and client // implementation. -func New(ctx context.Context, logger slog.Logger) (*tunnelsdk.Tunnel, error) { - cfg, err := readOrGenerateConfig() +func New(ctx context.Context, logger slog.Logger, customTunnelHost string) (*tunnelsdk.Tunnel, error) { + cfg, err := readOrGenerateConfig(customTunnelHost) if err != nil { return nil, xerrors.Errorf("read or generate config: %w", err) } @@ -81,7 +81,7 @@ func cfgPath() (string, error) { return filepath.Join(cfgDir, "devtunnel"), nil } -func readOrGenerateConfig() (Config, error) { +func readOrGenerateConfig(customTunnelHost string) (Config, error) { cfgFi, err := cfgPath() if err != nil { return Config{}, xerrors.Errorf("get config path: %w", err) @@ -90,7 +90,7 @@ func readOrGenerateConfig() (Config, error) { fi, err := os.ReadFile(cfgFi) if err != nil { if os.IsNotExist(err) { - cfg, err := GenerateConfig() + cfg, err := GenerateConfig(customTunnelHost) if err != nil { return Config{}, xerrors.Errorf("generate config: %w", err) } @@ -118,7 +118,7 @@ func readOrGenerateConfig() (Config, error) { _, _ = fmt.Println(cliui.Styles.Error.Render("Upgrading you to the new version now. You will need to rebuild running workspaces.")) _, _ = fmt.Println() - cfg, err := GenerateConfig() + cfg, err := GenerateConfig(customTunnelHost) if err != nil { return Config{}, xerrors.Errorf("generate config: %w", err) } @@ -134,7 +134,7 @@ func readOrGenerateConfig() (Config, error) { return cfg, nil } -func GenerateConfig() (Config, error) { +func GenerateConfig(customTunnelHost string) (Config, error) { priv, err := tunnelsdk.GeneratePrivateKey() if err != nil { return Config{}, xerrors.Errorf("generate private key: %w", err) @@ -149,7 +149,7 @@ func GenerateConfig() (Config, error) { spin.Suffix = " Finding the closest tunnel region..." spin.Start() - nodes, err := Nodes() + nodes, err := Nodes(customTunnelHost) if err != nil { return Config{}, xerrors.Errorf("get nodes: %w", err) } diff --git a/coderd/devtunnel/tunnel_test.go b/coderd/devtunnel/tunnel_test.go index b86de36a87dfa..a389001523375 100644 --- a/coderd/devtunnel/tunnel_test.go +++ b/coderd/devtunnel/tunnel_test.go @@ -250,9 +250,9 @@ func (s *tunnelServer) config(t *testing.T, version tunnelsdk.TunnelVersion) dev PrivateKey: privNoise, PublicKey: pubNoise, Tunnel: devtunnel.Node{ - HostnameHTTPS: s.api.BaseURL.Host, - HostnameWireguard: "localhost", - WireguardPort: s.api.WireguardPort, + RegionID: 0, + ID: 1, + HostnameHTTPS: s.api.BaseURL.Host, }, HTTPClient: s.client(), } diff --git a/codersdk/deployment.go b/codersdk/deployment.go index 8b822219cde96..4c1ca48b3a703 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "flag" - "fmt" "math" "net/http" "os" @@ -162,6 +161,7 @@ type DeploymentValues struct { Support SupportConfig `json:"support,omitempty" typescript:",notnull"` GitAuthProviders clibase.Struct[[]GitAuthConfig] `json:"git_auth,omitempty" typescript:",notnull"` SSHConfig SSHConfig `json:"config_ssh,omitempty" typescript:",notnull"` + TunnelHost clibase.String `json:"tunnel_host,omitempty" typescript:",notnull"` Config clibase.String `json:"config,omitempty" typescript:",notnull"` WriteConfig clibase.Bool `json:"write_config,omitempty" typescript:",notnull"` @@ -199,7 +199,7 @@ func ParseSSHConfigOption(opt string) (key string, value string, err error) { return r == ' ' || r == '=' }) if idx == -1 { - return "", "", fmt.Errorf("invalid config-ssh option %q", opt) + return "", "", xerrors.Errorf("invalid config-ssh option %q", opt) } return opt[:idx], opt[idx+1:], nil } @@ -1353,6 +1353,16 @@ Write out the current server configuration to the path specified by --config.`, Value: &c.GitAuthProviders, Hidden: true, }, + { + Name: "Custom Tunnel Host", + Description: `Hostname of HTTPS server that runs https://github.com/coder/wgtunnel. By default, this will pick the best available wgtunnel server hosted by Coder. e.g. "tunnel.example.com".`, + Flag: "tunnel-host", + Env: "TUNNEL_HOST", + YAML: "tunnelHost", + Value: &c.TunnelHost, + Default: "", // empty string means pick best server + Hidden: true, + }, } } From 28d7b9d7127739de44d1c5ceaeb80ac91c45a96b Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Fri, 17 Mar 2023 04:46:14 +0000 Subject: [PATCH 05/10] fixup! feat: add --tunnel-host to control wgtunnel server --- cli/server.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/cli/server.go b/cli/server.go index 2c0c7f5f1b2f2..f20f54c96b5da 100644 --- a/cli/server.go +++ b/cli/server.go @@ -1230,22 +1230,6 @@ flags, and YAML configuration. The precedence is as follows: return root } -// parseURL parses a string into a URL. -func parseURL(u string) (*url.URL, error) { - hasScheme := strings.HasPrefix(u, "http:") || strings.HasPrefix(u, "https:") - - if !hasScheme { - return nil, xerrors.Errorf("URL %q must have a scheme of either http or https", u) - } - - parsed, err := url.Parse(u) - if err != nil { - return nil, err - } - - return parsed, nil -} - // isLocalURL returns true if the hostname of the provided URL appears to // resolve to a loopback address. func isLocalURL(ctx context.Context, u *url.URL) (bool, error) { From f13fbd8930160e5c7f9da78d05ecf642932aaf1a Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Mon, 20 Mar 2023 02:50:56 +0000 Subject: [PATCH 06/10] chore: always ping nodes --- coderd/devtunnel/servers.go | 3 - gcp_audit_logs_to_datadog.sh | 1 + scripts/gcp_audit_logs_to_datadog.sh | 158 +++++++++++++++++++++++++++ 3 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 gcp_audit_logs_to_datadog.sh create mode 100755 scripts/gcp_audit_logs_to_datadog.sh diff --git a/coderd/devtunnel/servers.go b/coderd/devtunnel/servers.go index 2470177cb848c..1ac1b6ce26a7c 100644 --- a/coderd/devtunnel/servers.go +++ b/coderd/devtunnel/servers.go @@ -76,9 +76,6 @@ func FindClosestNode(nodes []Node) (Node, error) { if len(nodes) == 0 { return Node{}, xerrors.New("no wgtunnel nodes") } - if len(nodes) == 1 { - return nodes[0], nil - } // Copy the nodes so we don't mutate the original. nodes = append([]Node{}, nodes...) diff --git a/gcp_audit_logs_to_datadog.sh b/gcp_audit_logs_to_datadog.sh new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/gcp_audit_logs_to_datadog.sh @@ -0,0 +1 @@ + diff --git a/scripts/gcp_audit_logs_to_datadog.sh b/scripts/gcp_audit_logs_to_datadog.sh new file mode 100755 index 0000000000000..4e2e2771fe63e --- /dev/null +++ b/scripts/gcp_audit_logs_to_datadog.sh @@ -0,0 +1,158 @@ +#!/usr/bin/env bash + +# Iterates over all projects owned by the coder.com organization on GCP and +# ensures that audit log forwarding to datadog is enabled. +# +# Usage: DATADOG_API_KEY=<> ./gcp_audit_logs_to_datadog.sh [--verify] [--yes] [project_ids...] +# +# If no project IDs are specified, all projects owned by the coder.com +# organization will be processed. +# +# If --verify is specified, the script will exit with a non-zero status code if +# any project does not have audit log forwarding setup correctly. + +set -euo pipefail +# shellcheck source=scripts/lib.sh +source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" + +ORG_NAME="coder.com" +PUBSUB_TOPIC_ID="audit-logs-to-datadog" +PUBSUB_SUBSCRIPTION_ID="audit-logs-to-datadog-sub" +LOG_ROUTING_SINK_NAME="audit-logs-to-datadog" + +verify=0 +yes=0 + +args="$(getopt -o "" -l verify,yes -- "$@")" +eval set -- "$args" +while true; do + case "$1" in + --verify) + verify=1 + shift + ;; + --yes) + yes=1 + shift + ;; + --) + shift + break + ;; + *) + error "Unrecognized option: $1" + ;; + esac +done + +if [[ -z "${DATADOG_API_KEY:-}" ]]; then + error "DATADOG_API_KEY must be set" +fi + +# Load projects list. +projects=("$@") +if [[ "${#projects[@]}" == 0 ]]; then + log "Finding organization ID for $ORG_NAME" + org_id="$(gcloud organizations list --filter="displayName:$ORG_NAME" --format="value(name)")" + if [[ -z "$org_id" || "$org_id" =~ [^0-9] ]]; then + error "Could not find organization with name $ORG_NAME" + fi + + log "Finding projects in organization $ORG_NAME ($org_id)" + projects=($(gcloud projects list --filter="parent.id:$org_id" --format="value(projectId)")) + if [[ "${#projects[@]}" == 0 ]]; then + error "No projects found in organization $ORG_NAME ($org_id)" + fi +fi + +# Sort the projects list. +readarray -t projects < <(for project in "${projects[@]}"; do echo "$project"; done | sort) + +# Print projects list. +log +log "Projects:" +for project in "${projects[@]}"; do + log "- $project" +done +log +log "Found ${#projects[@]} projects" +log + +# Confirm with the user. +if [[ "$yes" == 0 ]]; then + read -rp "Looks good? [y/N] " read_result + if [[ "$read_result" != "y" ]]; then + error "Aborting" + fi +fi + +fail_verify() { + if [[ "$verify" == 1 ]]; then + error "$*" + fi +} + +setup_project() { + project="$1" + full_pubsub_topic_id="projects/$project/topics/$PUBSUB_TOPIC_ID" + full_pubsub_sub_id="projects/$project/subscriptions/$PUBSUB_SUBSCRIPTION_ID" + + log "Finding existing pubsub topic in project $project" + existing_pubsub_topic_id="$(gcloud pubsub topics list --project="$project" --filter="name:$full_pubsub_topic_id" --format="value(name)")" + if [[ ! -n "$existing_pubsub_topic_id" ]]; then + log "Found existing pubsub topic $existing_pubsub_topic_id" + else + log "Existing topic not found, creating pubsub topic $full_pubsub_topic_id in project $project" + fail_verify "Attempted to create a pubsub topic in project $project" + # TODO: figure this part out + #gcloud pubsub topics create "$full_pubsub_topic_id" --project="$project" 1>&2 + fi + + log "Finding existing pubsub subscription in project $project" + existing_pubsub_subscription_id="$(gcloud pubsub subscriptions list --project="$project" --filter="name:$full_pubsub_sub_id" --format="value(name)")" + if [[ ! -n "$existing_pubsub_subscription_id" ]]; then + log "Found existing pubsub subscription $existing_pubsub_subscription_id" + else + log "Existing subscription not found, creating pubsub subscription $PUBSUB_SUBSCRIPTION_ID in project $project" + fail_verify "Attempted to create a pubsub subscription in project $project" + # TODO: figure this part out + #gcloud pubsub subscriptions create "$PUBSUB_SUBSCRIPTION_ID" --topic="$full_pubsub_topic_id" --project="$project" 1>&2 + fi + + log "Finding existing log routing sink in project $project" + existing_log_routing_sink_name="$(gcloud logging sinks list --project="$project" --filter="name:$LOG_ROUTING_SINK_NAME" --format="value(name)")" + if [[ ! -n "$existing_log_routing_sink_name" ]]; then + log "Found existing log routing sink $existing_log_routing_sink_name" + else + log "Existing log routing sink not found, creating log routing sink $LOG_ROUTING_SINK_NAME in project $project" + fail_verify "Attempted to create a log routing sink in project $project" + # TODO: figure this part out + #gcloud logging sinks create "$LOG_ROUTING_SINK_NAME" pubsub.googleapis.com/projects/"$project"/topics/"$PUBSUB_TOPIC_ID" --project="$project" --log-filter='protoPayload.serviceName="compute.googleapis.com" OR protoPayload.serviceName="cloudresourcemanager.googleapis.com" OR protoPayload.serviceName="cloudsql.googleapis.com" OR protoPayload.serviceName="container.googleapis.com" OR protoPayload.serviceName="dataproc.googleapis.com" OR protoPayload.serviceName="iam.googleapis.com" OR protoPayload.serviceName="storage.googleapis.com"' 1>&2 + fi + + return 0 +} + +failed_projects=() + +for project in "${projects[@]}"; do + log + log "Setting up project $project" + rc=0 + setup_project "$project" || rc=$? + if [[ "$rc" != 0 ]]; then + log + log "Failed to setup project $project" + failed_projects+=("$project") + fi +done + +if [[ "${#failed_projects[@]}" != 0 ]]; then + log + log "Failed to setup/verify projects:" + for project in "${failed_projects[@]}"; do + log "- $project" + done + log + error "Failed to setup/verify ${#failed_projects[@]} projects" +fi From 6c4b02d4f63aa8b0bb3fd39ce18f1fbb7c392a2c Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Mon, 20 Mar 2023 02:52:10 +0000 Subject: [PATCH 07/10] chore: gen --- coderd/apidoc/docs.go | 3 +++ coderd/apidoc/swagger.json | 3 +++ docs/api/general.md | 1 + docs/api/schemas.md | 3 +++ 4 files changed, 10 insertions(+) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 67075e77f6a61..6fc8fbe382782 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -6714,6 +6714,9 @@ const docTemplate = `{ "trace": { "$ref": "#/definitions/codersdk.TraceConfig" }, + "tunnel_host": { + "type": "string" + }, "update_check": { "type": "boolean" }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 2697a8ee2205a..286671deb1733 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -6006,6 +6006,9 @@ "trace": { "$ref": "#/definitions/codersdk.TraceConfig" }, + "tunnel_host": { + "type": "string" + }, "update_check": { "type": "boolean" }, diff --git a/docs/api/general.md b/docs/api/general.md index 23c7ba511fb07..ec9211e420885 100644 --- a/docs/api/general.md +++ b/docs/api/general.md @@ -338,6 +338,7 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \ "enable": true, "honeycomb_api_key": "string" }, + "tunnel_host": "string", "update_check": true, "verbose": true, "wildcard_access_url": { diff --git a/docs/api/schemas.md b/docs/api/schemas.md index cff9081317ba7..7aaf51b978ce8 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -1870,6 +1870,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a "enable": true, "honeycomb_api_key": "string" }, + "tunnel_host": "string", "update_check": true, "verbose": true, "wildcard_access_url": { @@ -2214,6 +2215,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a "enable": true, "honeycomb_api_key": "string" }, + "tunnel_host": "string", "update_check": true, "verbose": true, "wildcard_access_url": { @@ -2280,6 +2282,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a | `telemetry` | [codersdk.TelemetryConfig](#codersdktelemetryconfig) | false | | | | `tls` | [codersdk.TLSConfig](#codersdktlsconfig) | false | | | | `trace` | [codersdk.TraceConfig](#codersdktraceconfig) | false | | | +| `tunnel_host` | string | false | | | | `update_check` | boolean | false | | | | `verbose` | boolean | false | | | | `wildcard_access_url` | [clibase.URL](#clibaseurl) | false | | | From b798f10d6e0873ca4e03185d0338a8f797daee8a Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Mon, 20 Mar 2023 04:05:52 +0000 Subject: [PATCH 08/10] fix: avoid out of range error in --tunnel-host --- coderd/devtunnel/tunnel.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/coderd/devtunnel/tunnel.go b/coderd/devtunnel/tunnel.go index f31e31e2a6f96..42f4ae4225e94 100644 --- a/coderd/devtunnel/tunnel.go +++ b/coderd/devtunnel/tunnel.go @@ -165,9 +165,14 @@ func GenerateConfig(customTunnelHost string) (Config, error) { _, _ = fmt.Println("Defaulting to", Regions[0].LocationName) } + locationName := "Unknown" + if node.RegionID < len(Regions) { + locationName = Regions[node.RegionID].LocationName + } + spin.Stop() _, _ = fmt.Printf("Using tunnel in %s with latency %s.\n", - cliui.Styles.Keyword.Render(Regions[node.RegionID].LocationName), + cliui.Styles.Keyword.Render(locationName), cliui.Styles.Code.Render(node.AvgLatency.String()), ) From 2ba2947993ea293fa1c02bdf124937e1c390c0eb Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Mon, 20 Mar 2023 14:00:22 +0000 Subject: [PATCH 09/10] chore: delete extraneous files --- gcp_audit_logs_to_datadog.sh | 1 - scripts/gcp_audit_logs_to_datadog.sh | 158 --------------------------- 2 files changed, 159 deletions(-) delete mode 100644 gcp_audit_logs_to_datadog.sh delete mode 100755 scripts/gcp_audit_logs_to_datadog.sh diff --git a/gcp_audit_logs_to_datadog.sh b/gcp_audit_logs_to_datadog.sh deleted file mode 100644 index 8b137891791fe..0000000000000 --- a/gcp_audit_logs_to_datadog.sh +++ /dev/null @@ -1 +0,0 @@ - diff --git a/scripts/gcp_audit_logs_to_datadog.sh b/scripts/gcp_audit_logs_to_datadog.sh deleted file mode 100755 index 4e2e2771fe63e..0000000000000 --- a/scripts/gcp_audit_logs_to_datadog.sh +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env bash - -# Iterates over all projects owned by the coder.com organization on GCP and -# ensures that audit log forwarding to datadog is enabled. -# -# Usage: DATADOG_API_KEY=<> ./gcp_audit_logs_to_datadog.sh [--verify] [--yes] [project_ids...] -# -# If no project IDs are specified, all projects owned by the coder.com -# organization will be processed. -# -# If --verify is specified, the script will exit with a non-zero status code if -# any project does not have audit log forwarding setup correctly. - -set -euo pipefail -# shellcheck source=scripts/lib.sh -source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" - -ORG_NAME="coder.com" -PUBSUB_TOPIC_ID="audit-logs-to-datadog" -PUBSUB_SUBSCRIPTION_ID="audit-logs-to-datadog-sub" -LOG_ROUTING_SINK_NAME="audit-logs-to-datadog" - -verify=0 -yes=0 - -args="$(getopt -o "" -l verify,yes -- "$@")" -eval set -- "$args" -while true; do - case "$1" in - --verify) - verify=1 - shift - ;; - --yes) - yes=1 - shift - ;; - --) - shift - break - ;; - *) - error "Unrecognized option: $1" - ;; - esac -done - -if [[ -z "${DATADOG_API_KEY:-}" ]]; then - error "DATADOG_API_KEY must be set" -fi - -# Load projects list. -projects=("$@") -if [[ "${#projects[@]}" == 0 ]]; then - log "Finding organization ID for $ORG_NAME" - org_id="$(gcloud organizations list --filter="displayName:$ORG_NAME" --format="value(name)")" - if [[ -z "$org_id" || "$org_id" =~ [^0-9] ]]; then - error "Could not find organization with name $ORG_NAME" - fi - - log "Finding projects in organization $ORG_NAME ($org_id)" - projects=($(gcloud projects list --filter="parent.id:$org_id" --format="value(projectId)")) - if [[ "${#projects[@]}" == 0 ]]; then - error "No projects found in organization $ORG_NAME ($org_id)" - fi -fi - -# Sort the projects list. -readarray -t projects < <(for project in "${projects[@]}"; do echo "$project"; done | sort) - -# Print projects list. -log -log "Projects:" -for project in "${projects[@]}"; do - log "- $project" -done -log -log "Found ${#projects[@]} projects" -log - -# Confirm with the user. -if [[ "$yes" == 0 ]]; then - read -rp "Looks good? [y/N] " read_result - if [[ "$read_result" != "y" ]]; then - error "Aborting" - fi -fi - -fail_verify() { - if [[ "$verify" == 1 ]]; then - error "$*" - fi -} - -setup_project() { - project="$1" - full_pubsub_topic_id="projects/$project/topics/$PUBSUB_TOPIC_ID" - full_pubsub_sub_id="projects/$project/subscriptions/$PUBSUB_SUBSCRIPTION_ID" - - log "Finding existing pubsub topic in project $project" - existing_pubsub_topic_id="$(gcloud pubsub topics list --project="$project" --filter="name:$full_pubsub_topic_id" --format="value(name)")" - if [[ ! -n "$existing_pubsub_topic_id" ]]; then - log "Found existing pubsub topic $existing_pubsub_topic_id" - else - log "Existing topic not found, creating pubsub topic $full_pubsub_topic_id in project $project" - fail_verify "Attempted to create a pubsub topic in project $project" - # TODO: figure this part out - #gcloud pubsub topics create "$full_pubsub_topic_id" --project="$project" 1>&2 - fi - - log "Finding existing pubsub subscription in project $project" - existing_pubsub_subscription_id="$(gcloud pubsub subscriptions list --project="$project" --filter="name:$full_pubsub_sub_id" --format="value(name)")" - if [[ ! -n "$existing_pubsub_subscription_id" ]]; then - log "Found existing pubsub subscription $existing_pubsub_subscription_id" - else - log "Existing subscription not found, creating pubsub subscription $PUBSUB_SUBSCRIPTION_ID in project $project" - fail_verify "Attempted to create a pubsub subscription in project $project" - # TODO: figure this part out - #gcloud pubsub subscriptions create "$PUBSUB_SUBSCRIPTION_ID" --topic="$full_pubsub_topic_id" --project="$project" 1>&2 - fi - - log "Finding existing log routing sink in project $project" - existing_log_routing_sink_name="$(gcloud logging sinks list --project="$project" --filter="name:$LOG_ROUTING_SINK_NAME" --format="value(name)")" - if [[ ! -n "$existing_log_routing_sink_name" ]]; then - log "Found existing log routing sink $existing_log_routing_sink_name" - else - log "Existing log routing sink not found, creating log routing sink $LOG_ROUTING_SINK_NAME in project $project" - fail_verify "Attempted to create a log routing sink in project $project" - # TODO: figure this part out - #gcloud logging sinks create "$LOG_ROUTING_SINK_NAME" pubsub.googleapis.com/projects/"$project"/topics/"$PUBSUB_TOPIC_ID" --project="$project" --log-filter='protoPayload.serviceName="compute.googleapis.com" OR protoPayload.serviceName="cloudresourcemanager.googleapis.com" OR protoPayload.serviceName="cloudsql.googleapis.com" OR protoPayload.serviceName="container.googleapis.com" OR protoPayload.serviceName="dataproc.googleapis.com" OR protoPayload.serviceName="iam.googleapis.com" OR protoPayload.serviceName="storage.googleapis.com"' 1>&2 - fi - - return 0 -} - -failed_projects=() - -for project in "${projects[@]}"; do - log - log "Setting up project $project" - rc=0 - setup_project "$project" || rc=$? - if [[ "$rc" != 0 ]]; then - log - log "Failed to setup project $project" - failed_projects+=("$project") - fi -done - -if [[ "${#failed_projects[@]}" != 0 ]]; then - log - log "Failed to setup/verify projects:" - for project in "${failed_projects[@]}"; do - log "- $project" - done - log - error "Failed to setup/verify ${#failed_projects[@]} projects" -fi From c90142937e23ef5e573e498a78a16e1c3d7a5317 Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Tue, 21 Mar 2023 03:01:20 +0000 Subject: [PATCH 10/10] chore: rename tunnel-host to wgtunnel-host --- cli/server.go | 2 +- coderd/apidoc/docs.go | 6 +++--- coderd/apidoc/swagger.json | 6 +++--- codersdk/deployment.go | 12 ++++++------ docs/api/general.md | 2 +- docs/api/schemas.md | 6 +++--- site/src/api/typesGenerated.ts | 1 + 7 files changed, 18 insertions(+), 17 deletions(-) diff --git a/cli/server.go b/cli/server.go index f20f54c96b5da..db06f0253d383 100644 --- a/cli/server.go +++ b/cli/server.go @@ -547,7 +547,7 @@ flags, and YAML configuration. The precedence is as follows: ) if cfg.AccessURL.String() == "" { cmd.Printf("Opening tunnel so workspaces can connect to your deployment. For production scenarios, specify an external access URL\n") - tunnel, err = devtunnel.New(ctx, logger.Named("devtunnel"), cfg.TunnelHost.String()) + tunnel, err = devtunnel.New(ctx, logger.Named("devtunnel"), cfg.WgtunnelHost.String()) if err != nil { return xerrors.Errorf("create tunnel: %w", err) } diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 6fc8fbe382782..ef9ac41f376ef 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -6714,15 +6714,15 @@ const docTemplate = `{ "trace": { "$ref": "#/definitions/codersdk.TraceConfig" }, - "tunnel_host": { - "type": "string" - }, "update_check": { "type": "boolean" }, "verbose": { "type": "boolean" }, + "wgtunnel_host": { + "type": "string" + }, "wildcard_access_url": { "$ref": "#/definitions/clibase.URL" }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 286671deb1733..5f7e99ba87974 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -6006,15 +6006,15 @@ "trace": { "$ref": "#/definitions/codersdk.TraceConfig" }, - "tunnel_host": { - "type": "string" - }, "update_check": { "type": "boolean" }, "verbose": { "type": "boolean" }, + "wgtunnel_host": { + "type": "string" + }, "wildcard_access_url": { "$ref": "#/definitions/clibase.URL" }, diff --git a/codersdk/deployment.go b/codersdk/deployment.go index 4c1ca48b3a703..b3b8f7c989454 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -161,7 +161,7 @@ type DeploymentValues struct { Support SupportConfig `json:"support,omitempty" typescript:",notnull"` GitAuthProviders clibase.Struct[[]GitAuthConfig] `json:"git_auth,omitempty" typescript:",notnull"` SSHConfig SSHConfig `json:"config_ssh,omitempty" typescript:",notnull"` - TunnelHost clibase.String `json:"tunnel_host,omitempty" typescript:",notnull"` + WgtunnelHost clibase.String `json:"wgtunnel_host,omitempty" typescript:",notnull"` Config clibase.String `json:"config,omitempty" typescript:",notnull"` WriteConfig clibase.Bool `json:"write_config,omitempty" typescript:",notnull"` @@ -1354,12 +1354,12 @@ Write out the current server configuration to the path specified by --config.`, Hidden: true, }, { - Name: "Custom Tunnel Host", + Name: "Custom wgtunnel Host", Description: `Hostname of HTTPS server that runs https://github.com/coder/wgtunnel. By default, this will pick the best available wgtunnel server hosted by Coder. e.g. "tunnel.example.com".`, - Flag: "tunnel-host", - Env: "TUNNEL_HOST", - YAML: "tunnelHost", - Value: &c.TunnelHost, + Flag: "wg-tunnel-host", + Env: "WGTUNNEL_HOST", + YAML: "wgtunnelHost", + Value: &c.WgtunnelHost, Default: "", // empty string means pick best server Hidden: true, }, diff --git a/docs/api/general.md b/docs/api/general.md index ec9211e420885..ffe3da0e56aa0 100644 --- a/docs/api/general.md +++ b/docs/api/general.md @@ -338,9 +338,9 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \ "enable": true, "honeycomb_api_key": "string" }, - "tunnel_host": "string", "update_check": true, "verbose": true, + "wgtunnel_host": "string", "wildcard_access_url": { "forceQuery": true, "fragment": "string", diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 7aaf51b978ce8..444afefa97384 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -1870,9 +1870,9 @@ CreateParameterRequest is a structure used to create a new parameter value for a "enable": true, "honeycomb_api_key": "string" }, - "tunnel_host": "string", "update_check": true, "verbose": true, + "wgtunnel_host": "string", "wildcard_access_url": { "forceQuery": true, "fragment": "string", @@ -2215,9 +2215,9 @@ CreateParameterRequest is a structure used to create a new parameter value for a "enable": true, "honeycomb_api_key": "string" }, - "tunnel_host": "string", "update_check": true, "verbose": true, + "wgtunnel_host": "string", "wildcard_access_url": { "forceQuery": true, "fragment": "string", @@ -2282,9 +2282,9 @@ CreateParameterRequest is a structure used to create a new parameter value for a | `telemetry` | [codersdk.TelemetryConfig](#codersdktelemetryconfig) | false | | | | `tls` | [codersdk.TLSConfig](#codersdktlsconfig) | false | | | | `trace` | [codersdk.TraceConfig](#codersdktraceconfig) | false | | | -| `tunnel_host` | string | false | | | | `update_check` | boolean | false | | | | `verbose` | boolean | false | | | +| `wgtunnel_host` | string | false | | | | `wildcard_access_url` | [clibase.URL](#clibaseurl) | false | | | | `write_config` | boolean | false | | | diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 7b2c7f7ba208c..24c336d3ebf2e 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -362,6 +362,7 @@ export interface DeploymentValues { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly git_auth?: any readonly config_ssh?: SSHConfig + readonly wgtunnel_host?: string readonly config?: string readonly write_config?: boolean // Named type "github.com/coder/coder/cli/clibase.HostPort" unknown, using "any"