Skip to content

Commit d0526ed

Browse files
committed
Merge branch 'main' into entfactor
2 parents aad7be4 + e847e73 commit d0526ed

File tree

151 files changed

+2240
-1013
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+2240
-1013
lines changed

.devcontainer/Dockerfile

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
FROM ubuntu
2+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
3+
4+
ENV EDITOR=vim
5+
6+
RUN apt-get update && apt-get upgrade
7+
8+
RUN apt-get install --yes \
9+
ca-certificates \
10+
bash-completion \
11+
build-essential \
12+
curl \
13+
cmake \
14+
direnv \
15+
emacs-nox \
16+
gnupg \
17+
htop \
18+
jq \
19+
less \
20+
lsb-release \
21+
lsof \
22+
man-db \
23+
nano \
24+
neovim \
25+
ssl-cert \
26+
sudo \
27+
unzip \
28+
xz-utils \
29+
zip
30+
31+
# configure locales to UTF8
32+
RUN apt-get install locales && locale-gen en_US.UTF-8
33+
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8'
34+
35+
# configure direnv
36+
RUN direnv hook bash >> $HOME/.bashrc
37+
38+
# install nix
39+
RUN sh <(curl -L https://nixos.org/nix/install) --daemon
40+
41+
RUN mkdir -p $HOME/.config/nix $HOME/.config/nixpkgs \
42+
&& echo 'sandbox = false' >> $HOME/.config/nix/nix.conf \
43+
&& echo '{ allowUnfree = true; }' >> $HOME/.config/nixpkgs/config.nix \
44+
&& echo '. $HOME/.nix-profile/etc/profile.d/nix.sh' >> $HOME/.bashrc
45+
46+
47+
# install docker and configure daemon to use vfs as GitHub codespaces requires vfs
48+
# https://github.com/moby/moby/issues/13742#issuecomment-725197223
49+
RUN mkdir -p /etc/apt/keyrings \
50+
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
51+
&& echo \
52+
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
53+
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null \
54+
&& apt-get update \
55+
&& apt-get install --yes docker-ce docker-ce-cli containerd.io docker-compose-plugin \
56+
&& mkdir -p /etc/docker \
57+
&& echo '{"cgroup-parent":"/actions_job","storage-driver":"vfs"}' >> /etc/docker/daemon.json
58+
59+
# install golang and language tooling
60+
ENV GO_VERSION=1.19
61+
ENV GOPATH=$HOME/go-packages
62+
ENV GOROOT=$HOME/go
63+
ENV PATH=$GOROOT/bin:$GOPATH/bin:$PATH
64+
RUN curl -fsSL https://dl.google.com/go/go$GO_VERSION.linux-amd64.tar.gz | tar xzs
65+
RUN echo 'export PATH=$GOPATH/bin:$PATH' >> $HOME/.bashrc
66+
67+
RUN bash -c ". $HOME/.bashrc \
68+
go install -v golang.org/x/tools/gopls@latest \
69+
&& go install -v mvdan.cc/sh/v3/cmd/shfmt@latest \
70+
"
71+
72+
# install nodejs
73+
RUN bash -c "$(curl -fsSL https://deb.nodesource.com/setup_14.x)" \
74+
&& apt-get install -y nodejs
75+
76+
# install zstd
77+
RUN bash -c "$(curl -fsSL https://raw.githubusercontent.com/horta/zstd.install/main/install)"
78+
79+
# install nfpm
80+
RUN echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | sudo tee /etc/apt/sources.list.d/goreleaser.list \
81+
&& apt update \
82+
&& apt install nfpm
83+

.devcontainer/devcontainer.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// For format details, see https://aka.ms/devcontainer.json
2+
{
3+
"name": "Development environments on your infrastructure",
4+
5+
// Sets the run context to one level up instead of the .devcontainer folder.
6+
"context": ".",
7+
8+
// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
9+
"dockerFile": "Dockerfile",
10+
11+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
12+
// "forwardPorts": [],
13+
14+
"postStartCommand": "dockerd",
15+
16+
// privileged is required by GitHub codespaces - https://github.com/microsoft/vscode-dev-containers/issues/727
17+
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined", "--privileged", "--init" ]
18+
}

agent/agent_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ func TestAgent(t *testing.T) {
559559
DERPMap: derpMap,
560560
}, 0)
561561
defer conn.Close()
562-
res, err := conn.Speedtest(speedtest.Upload, speedtest.MinDuration)
562+
res, err := conn.Speedtest(speedtest.Upload, 250*time.Millisecond)
563563
require.NoError(t, err)
564564
t.Logf("%.2f MBits/s", res[len(res)-1].MBitsPerSecond())
565565
})

cli/agent_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func TestWorkspaceAgent(t *testing.T) {
4747
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
4848
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
4949

50-
cmd, _ := clitest.New(t, "agent", "--auth", "azure-instance-identity", "--agent-url", client.URL.String(), "--wireguard=false")
50+
cmd, _ := clitest.New(t, "agent", "--auth", "azure-instance-identity", "--agent-url", client.URL.String())
5151
ctx, cancelFunc := context.WithCancel(context.Background())
5252
defer cancelFunc()
5353
errC := make(chan error)
@@ -105,7 +105,7 @@ func TestWorkspaceAgent(t *testing.T) {
105105
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
106106
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
107107

108-
cmd, _ := clitest.New(t, "agent", "--auth", "aws-instance-identity", "--agent-url", client.URL.String(), "--wireguard=false")
108+
cmd, _ := clitest.New(t, "agent", "--auth", "aws-instance-identity", "--agent-url", client.URL.String())
109109
ctx, cancelFunc := context.WithCancel(context.Background())
110110
defer cancelFunc()
111111
errC := make(chan error)
@@ -163,7 +163,7 @@ func TestWorkspaceAgent(t *testing.T) {
163163
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
164164
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
165165

166-
cmd, _ := clitest.New(t, "agent", "--auth", "google-instance-identity", "--agent-url", client.URL.String(), "--wireguard=false")
166+
cmd, _ := clitest.New(t, "agent", "--auth", "google-instance-identity", "--agent-url", client.URL.String())
167167
ctx, cancelFunc := context.WithCancel(context.Background())
168168
defer cancelFunc()
169169
errC := make(chan error)

cli/configssh.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ func configSSH() *cobra.Command {
374374
cmd.Flags().BoolVarP(&skipProxyCommand, "skip-proxy-command", "", false, "Specifies whether the ProxyCommand option should be skipped. Useful for testing.")
375375
_ = cmd.Flags().MarkHidden("skip-proxy-command")
376376
cliflag.BoolVarP(cmd.Flags(), &usePreviousOpts, "use-previous-options", "", "CODER_SSH_USE_PREVIOUS_OPTIONS", false, "Specifies whether or not to keep options from previous run of config-ssh.")
377-
cliflag.BoolVarP(cmd.Flags(), &wireguard, "wireguard", "", "CODER_CONFIG_SSH_WIREGUARD", false, "Whether to use Wireguard for SSH tunneling.")
377+
cliflag.BoolVarP(cmd.Flags(), &wireguard, "wireguard", "", "CODER_CONFIG_SSH_WIREGUARD", true, "Whether to use Wireguard for SSH tunneling.")
378378
_ = cmd.Flags().MarkHidden("wireguard")
379379

380380
cliui.AllowSkipPrompt(cmd)

cli/login.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func login() *cobra.Command {
8383

8484
hasInitialUser, err := client.HasFirstUser(cmd.Context())
8585
if err != nil {
86-
return xerrors.Errorf("has initial user: %w", err)
86+
return xerrors.Errorf("Failed to check server %q for first user, is the URL correct and is coder accessible from your browser? Error - has initial user: %w", serverURL.String(), err)
8787
}
8888
if !hasInitialUser {
8989
_, _ = fmt.Fprintf(cmd.OutOrStdout(), caret+"Your Coder deployment hasn't been set up!\n")

cli/login_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cli_test
22

33
import (
44
"context"
5+
"fmt"
56
"testing"
67

78
"github.com/stretchr/testify/assert"
@@ -23,6 +24,15 @@ func TestLogin(t *testing.T) {
2324
require.Error(t, err)
2425
})
2526

27+
t.Run("InitialUserBadLoginURL", func(t *testing.T) {
28+
t.Parallel()
29+
badLoginURL := "https://fcca2077f06e68aaf9"
30+
root, _ := clitest.New(t, "login", badLoginURL)
31+
err := root.Execute()
32+
errMsg := fmt.Sprintf("Failed to check server %q for first user, is the URL correct and is coder accessible from your browser?", badLoginURL)
33+
require.ErrorContains(t, err, errMsg)
34+
})
35+
2636
t.Run("InitialUserTTY", func(t *testing.T) {
2737
t.Parallel()
2838
client := coderdtest.New(t, nil)

cli/portforward.go

Lines changed: 32 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,29 @@ import (
66
"net"
77
"os"
88
"os/signal"
9-
"runtime"
109
"strconv"
1110
"strings"
1211
"sync"
1312
"syscall"
13+
"time"
1414

1515
"github.com/pion/udp"
1616
"github.com/spf13/cobra"
1717
"golang.org/x/xerrors"
1818

1919
"cdr.dev/slog"
20+
"cdr.dev/slog/sloggers/sloghuman"
2021
"github.com/coder/coder/agent"
22+
"github.com/coder/coder/cli/cliflag"
2123
"github.com/coder/coder/cli/cliui"
2224
"github.com/coder/coder/codersdk"
2325
)
2426

2527
func portForward() *cobra.Command {
2628
var (
27-
tcpForwards []string // <port>:<port>
28-
udpForwards []string // <port>:<port>
29-
unixForwards []string // <path>:<path> OR <port>:<path>
30-
wireguard bool
29+
tcpForwards []string // <port>:<port>
30+
udpForwards []string // <port>:<port>
31+
wireguard bool
3132
)
3233
cmd := &cobra.Command{
3334
Use: "port-forward <workspace>",
@@ -43,14 +44,6 @@ func portForward() *cobra.Command {
4344
Description: "Port forward a single UDP port from port 9000 to port 9000 on your local machine",
4445
Command: "coder port-forward <workspace> --udp 9000",
4546
},
46-
example{
47-
Description: "Forward a Unix socket in the workspace to a local Unix socket",
48-
Command: "coder port-forward <workspace> --unix ./local.sock:~/remote.sock",
49-
},
50-
example{
51-
Description: "Forward a Unix socket in the workspace to a local TCP port",
52-
Command: "coder port-forward <workspace> --unix 8080:~/remote.sock",
53-
},
5447
example{
5548
Description: "Port forward multiple TCP ports and a UDP port",
5649
Command: "coder port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53",
@@ -60,7 +53,7 @@ func portForward() *cobra.Command {
6053
ctx, cancel := context.WithCancel(cmd.Context())
6154
defer cancel()
6255

63-
specs, err := parsePortForwards(tcpForwards, udpForwards, unixForwards)
56+
specs, err := parsePortForwards(tcpForwards, udpForwards)
6457
if err != nil {
6558
return xerrors.Errorf("parse port-forward specs: %w", err)
6659
}
@@ -105,7 +98,11 @@ func portForward() *cobra.Command {
10598
if !wireguard {
10699
conn, err = client.DialWorkspaceAgent(ctx, workspaceAgent.ID, nil)
107100
} else {
108-
conn, err = client.DialWorkspaceAgentTailnet(ctx, slog.Logger{}, workspaceAgent.ID)
101+
logger := slog.Logger{}
102+
if cliflag.IsSetBool(cmd, varVerbose) {
103+
logger = slog.Make(sloghuman.Sink(cmd.ErrOrStderr())).Named("tailnet").Leveled(slog.LevelDebug)
104+
}
105+
conn, err = client.DialWorkspaceAgentTailnet(ctx, logger, workspaceAgent.ID)
109106
}
110107
if err != nil {
111108
return err
@@ -157,6 +154,22 @@ func portForward() *cobra.Command {
157154
closeAllListeners()
158155
}()
159156

157+
ticker := time.NewTicker(250 * time.Millisecond)
158+
defer ticker.Stop()
159+
for {
160+
select {
161+
case <-ctx.Done():
162+
return ctx.Err()
163+
case <-ticker.C:
164+
}
165+
166+
_, err = conn.Ping()
167+
if err != nil {
168+
continue
169+
}
170+
break
171+
}
172+
ticker.Stop()
160173
_, _ = fmt.Fprintln(cmd.OutOrStderr(), "Ready!")
161174
wg.Wait()
162175
return closeErr
@@ -165,8 +178,7 @@ func portForward() *cobra.Command {
165178

166179
cmd.Flags().StringArrayVarP(&tcpForwards, "tcp", "p", []string{}, "Forward a TCP port from the workspace to the local machine")
167180
cmd.Flags().StringArrayVar(&udpForwards, "udp", []string{}, "Forward a UDP port from the workspace to the local machine. The UDP connection has TCP-like semantics to support stateful UDP protocols")
168-
cmd.Flags().StringArrayVar(&unixForwards, "unix", []string{}, "Forward a Unix socket in the workspace to a local Unix socket or TCP port")
169-
cmd.Flags().BoolVarP(&wireguard, "wireguard", "", false, "Specifies whether to use wireguard networking or not.")
181+
cmd.Flags().BoolVarP(&wireguard, "wireguard", "", true, "Specifies whether to use wireguard networking or not.")
170182
_ = cmd.Flags().MarkHidden("wireguard")
171183
return cmd
172184
}
@@ -198,8 +210,6 @@ func listenAndPortForward(ctx context.Context, cmd *cobra.Command, conn agent.Co
198210
IP: net.ParseIP(host),
199211
Port: portInt,
200212
})
201-
case "unix":
202-
l, err = net.Listen(spec.listenNetwork, spec.listenAddress)
203213
default:
204214
return nil, xerrors.Errorf("unknown listen network %q", spec.listenNetwork)
205215
}
@@ -236,14 +246,14 @@ func listenAndPortForward(ctx context.Context, cmd *cobra.Command, conn agent.Co
236246
}
237247

238248
type portForwardSpec struct {
239-
listenNetwork string // tcp, udp, unix
249+
listenNetwork string // tcp, udp
240250
listenAddress string // <ip>:<port> or path
241251

242-
dialNetwork string // tcp, udp, unix
252+
dialNetwork string // tcp, udp
243253
dialAddress string // <ip>:<port> or path
244254
}
245255

246-
func parsePortForwards(tcpSpecs, udpSpecs, unixSpecs []string) ([]portForwardSpec, error) {
256+
func parsePortForwards(tcpSpecs, udpSpecs []string) ([]portForwardSpec, error) {
247257
specs := []portForwardSpec{}
248258

249259
for _, spec := range tcpSpecs {
@@ -274,29 +284,6 @@ func parsePortForwards(tcpSpecs, udpSpecs, unixSpecs []string) ([]portForwardSpe
274284
})
275285
}
276286

277-
for _, specStr := range unixSpecs {
278-
localPath, localTCP, remotePath, err := parseUnixUnix(specStr)
279-
if err != nil {
280-
return nil, xerrors.Errorf("failed to parse Unix port-forward specification %q: %w", specStr, err)
281-
}
282-
283-
spec := portForwardSpec{
284-
dialNetwork: "unix",
285-
dialAddress: remotePath,
286-
}
287-
if localPath == "" {
288-
spec.listenNetwork = "tcp"
289-
spec.listenAddress = fmt.Sprintf("127.0.0.1:%v", localTCP)
290-
} else {
291-
if runtime.GOOS == "windows" {
292-
return nil, xerrors.Errorf("Unix port-forwarding is not supported on Windows")
293-
}
294-
spec.listenNetwork = "unix"
295-
spec.listenAddress = localPath
296-
}
297-
specs = append(specs, spec)
298-
}
299-
300287
// Check for duplicate entries.
301288
locals := map[string]struct{}{}
302289
for _, spec := range specs {
@@ -322,15 +309,6 @@ func parsePort(in string) (uint16, error) {
322309
return uint16(port), nil
323310
}
324311

325-
func parseUnixPath(in string) (string, error) {
326-
path, err := agent.ExpandRelativeHomePath(strings.TrimSpace(in))
327-
if err != nil {
328-
return "", xerrors.Errorf("tidy path %q: %w", in, err)
329-
}
330-
331-
return path, nil
332-
}
333-
334312
func parsePortPort(in string) (local uint16, remote uint16, err error) {
335313
parts := strings.Split(in, ":")
336314
if len(parts) > 2 {
@@ -352,37 +330,3 @@ func parsePortPort(in string) (local uint16, remote uint16, err error) {
352330

353331
return local, remote, nil
354332
}
355-
356-
func parsePortOrUnixPath(in string) (string, uint16, error) {
357-
port, err := parsePort(in)
358-
if err == nil {
359-
return "", port, nil
360-
}
361-
362-
path, err := parseUnixPath(in)
363-
if err != nil {
364-
return "", 0, xerrors.Errorf("could not parse port or unix path %q: %w", in, err)
365-
}
366-
367-
return path, 0, nil
368-
}
369-
370-
func parseUnixUnix(in string) (string, uint16, string, error) {
371-
parts := strings.Split(in, ":")
372-
if len(parts) > 2 {
373-
return "", 0, "", xerrors.Errorf("invalid port-forward specification %q", in)
374-
}
375-
if len(parts) == 1 {
376-
// Duplicate the single part
377-
parts = append(parts, parts[0])
378-
}
379-
380-
localPath, localPort, err := parsePortOrUnixPath(parts[0])
381-
if err != nil {
382-
return "", 0, "", xerrors.Errorf("parse local part of spec %q: %w", in, err)
383-
}
384-
385-
// We don't really touch the remote path at all since it gets cleaned
386-
// up/expanded on the remote.
387-
return localPath, localPort, parts[1], nil
388-
}

0 commit comments

Comments
 (0)