Skip to content

Commit 4059f9f

Browse files
authored
Merge branch 'main' into restructure-new
2 parents a099dc8 + f24cb5c commit 4059f9f

Some content is hidden

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

72 files changed

+1751
-200
lines changed

agent/agent.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1787,7 +1787,7 @@ func (a *agent) HandleHTTPDebugLogs(w http.ResponseWriter, r *http.Request) {
17871787
}
17881788
defer f.Close()
17891789

1790-
// Limit to 10MB.
1790+
// Limit to 10MiB.
17911791
w.WriteHeader(http.StatusOK)
17921792
_, err = io.Copy(w, io.LimitReader(f, 10*1024*1024))
17931793
if err != nil && !errors.Is(err, io.EOF) {

agent/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func (a *agent) apiHandler() http.Handler {
3737
}
3838
promHandler := PrometheusMetricsHandler(a.prometheusRegistry, a.logger)
3939
r.Get("/api/v0/listening-ports", lp.handler)
40+
r.Get("/api/v0/netcheck", a.HandleNetcheck)
4041
r.Get("/debug/logs", a.HandleHTTPDebugLogs)
4142
r.Get("/debug/magicsock", a.HandleHTTPDebugMagicsock)
4243
r.Get("/debug/magicsock/debug-logging/{state}", a.HandleHTTPMagicsockDebugLoggingState)

agent/health.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package agent
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/coder/coder/v2/coderd/healthcheck/health"
7+
"github.com/coder/coder/v2/coderd/httpapi"
8+
"github.com/coder/coder/v2/codersdk"
9+
"github.com/coder/coder/v2/codersdk/healthsdk"
10+
)
11+
12+
func (a *agent) HandleNetcheck(rw http.ResponseWriter, r *http.Request) {
13+
ni := a.TailnetConn().GetNetInfo()
14+
15+
ifReport, err := healthsdk.RunInterfacesReport()
16+
if err != nil {
17+
httpapi.Write(r.Context(), rw, http.StatusInternalServerError, codersdk.Response{
18+
Message: "Failed to run interfaces report",
19+
Detail: err.Error(),
20+
})
21+
return
22+
}
23+
24+
httpapi.Write(r.Context(), rw, http.StatusOK, healthsdk.AgentNetcheckReport{
25+
BaseReport: healthsdk.BaseReport{
26+
Severity: health.SeverityOK,
27+
},
28+
NetInfo: ni,
29+
Interfaces: ifReport,
30+
})
31+
}

cli/cliui/agent.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ import (
1010

1111
"github.com/google/uuid"
1212
"golang.org/x/xerrors"
13+
"tailscale.com/tailcfg"
1314

1415
"github.com/coder/coder/v2/codersdk"
16+
"github.com/coder/coder/v2/codersdk/healthsdk"
17+
"github.com/coder/coder/v2/codersdk/workspacesdk"
1518
"github.com/coder/coder/v2/tailnet"
1619
)
1720

@@ -346,3 +349,55 @@ func PeerDiagnostics(w io.Writer, d tailnet.PeerDiagnostics) {
346349
_, _ = fmt.Fprint(w, "✘ Wireguard is not connected\n")
347350
}
348351
}
352+
353+
type ConnDiags struct {
354+
ConnInfo *workspacesdk.AgentConnectionInfo
355+
PingP2P bool
356+
DisableDirect bool
357+
LocalNetInfo *tailcfg.NetInfo
358+
LocalInterfaces *healthsdk.InterfacesReport
359+
AgentNetcheck *healthsdk.AgentNetcheckReport
360+
// TODO: More diagnostics
361+
}
362+
363+
func ConnDiagnostics(w io.Writer, d ConnDiags) {
364+
if d.AgentNetcheck != nil {
365+
for _, msg := range d.AgentNetcheck.Interfaces.Warnings {
366+
_, _ = fmt.Fprintf(w, "❗ Agent: %s\n", msg.Message)
367+
}
368+
}
369+
370+
if d.LocalInterfaces != nil {
371+
for _, msg := range d.LocalInterfaces.Warnings {
372+
_, _ = fmt.Fprintf(w, "❗ Client: %s\n", msg.Message)
373+
}
374+
}
375+
376+
if d.PingP2P {
377+
_, _ = fmt.Fprint(w, "✔ You are connected directly (p2p)\n")
378+
return
379+
}
380+
_, _ = fmt.Fprint(w, "❗ You are connected via a DERP relay, not directly (p2p)\n")
381+
382+
if d.DisableDirect {
383+
_, _ = fmt.Fprint(w, "❗ Direct connections are disabled locally, by `--disable-direct` or `CODER_DISABLE_DIRECT`\n")
384+
return
385+
}
386+
387+
if d.ConnInfo != nil && d.ConnInfo.DisableDirectConnections {
388+
_, _ = fmt.Fprint(w, "❗ Your Coder administrator has blocked direct connections\n")
389+
return
390+
}
391+
392+
if d.ConnInfo != nil && d.ConnInfo.DERPMap != nil && !d.ConnInfo.DERPMap.HasSTUN() {
393+
_, _ = fmt.Fprint(w, "✘ The DERP map is not configured to use STUN, which will prevent direct connections from starting outside of local networks\n")
394+
}
395+
396+
if d.LocalNetInfo != nil && d.LocalNetInfo.MappingVariesByDestIP.EqualBool(true) {
397+
_, _ = fmt.Fprint(w, "❗ Client is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers\n")
398+
}
399+
400+
if d.AgentNetcheck != nil && d.AgentNetcheck.NetInfo != nil && d.AgentNetcheck.NetInfo.MappingVariesByDestIP.EqualBool(true) {
401+
_, _ = fmt.Fprint(w, "❗ Agent is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers\n")
402+
}
403+
}

cli/cliui/agent_test.go

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ import (
2020

2121
"github.com/coder/coder/v2/cli/clitest"
2222
"github.com/coder/coder/v2/cli/cliui"
23+
"github.com/coder/coder/v2/coderd/healthcheck/health"
2324
"github.com/coder/coder/v2/coderd/util/ptr"
2425
"github.com/coder/coder/v2/codersdk"
26+
"github.com/coder/coder/v2/codersdk/healthsdk"
27+
"github.com/coder/coder/v2/codersdk/workspacesdk"
2528
"github.com/coder/coder/v2/tailnet"
2629
"github.com/coder/coder/v2/testutil"
2730
"github.com/coder/serpent"
@@ -672,3 +675,129 @@ func TestPeerDiagnostics(t *testing.T) {
672675
})
673676
}
674677
}
678+
679+
func TestConnDiagnostics(t *testing.T) {
680+
t.Parallel()
681+
testCases := []struct {
682+
name string
683+
diags cliui.ConnDiags
684+
want []string
685+
}{
686+
{
687+
name: "Direct",
688+
diags: cliui.ConnDiags{
689+
ConnInfo: &workspacesdk.AgentConnectionInfo{},
690+
PingP2P: true,
691+
LocalNetInfo: &tailcfg.NetInfo{},
692+
},
693+
want: []string{
694+
`✔ You are connected directly (p2p)`,
695+
},
696+
},
697+
{
698+
name: "DirectBlocked",
699+
diags: cliui.ConnDiags{
700+
ConnInfo: &workspacesdk.AgentConnectionInfo{
701+
DisableDirectConnections: true,
702+
},
703+
},
704+
want: []string{
705+
`❗ You are connected via a DERP relay, not directly (p2p)`,
706+
`❗ Your Coder administrator has blocked direct connections`,
707+
},
708+
},
709+
{
710+
name: "NoStun",
711+
diags: cliui.ConnDiags{
712+
ConnInfo: &workspacesdk.AgentConnectionInfo{
713+
DERPMap: &tailcfg.DERPMap{},
714+
},
715+
LocalNetInfo: &tailcfg.NetInfo{},
716+
},
717+
want: []string{
718+
`❗ You are connected via a DERP relay, not directly (p2p)`,
719+
`✘ The DERP map is not configured to use STUN, which will prevent direct connections from starting outside of local networks`,
720+
},
721+
},
722+
{
723+
name: "ClientHardNat",
724+
diags: cliui.ConnDiags{
725+
LocalNetInfo: &tailcfg.NetInfo{
726+
MappingVariesByDestIP: "true",
727+
},
728+
},
729+
want: []string{
730+
`❗ You are connected via a DERP relay, not directly (p2p)`,
731+
`❗ Client is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers`,
732+
},
733+
},
734+
{
735+
name: "AgentHardNat",
736+
diags: cliui.ConnDiags{
737+
ConnInfo: &workspacesdk.AgentConnectionInfo{},
738+
PingP2P: false,
739+
LocalNetInfo: &tailcfg.NetInfo{},
740+
AgentNetcheck: &healthsdk.AgentNetcheckReport{
741+
NetInfo: &tailcfg.NetInfo{MappingVariesByDestIP: "true"},
742+
},
743+
},
744+
want: []string{
745+
`❗ You are connected via a DERP relay, not directly (p2p)`,
746+
`❗ Agent is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers`,
747+
},
748+
},
749+
{
750+
name: "AgentInterfaceWarnings",
751+
diags: cliui.ConnDiags{
752+
PingP2P: true,
753+
AgentNetcheck: &healthsdk.AgentNetcheckReport{
754+
Interfaces: healthsdk.InterfacesReport{
755+
BaseReport: healthsdk.BaseReport{
756+
Warnings: []health.Message{
757+
health.Messagef(health.CodeInterfaceSmallMTU, "network interface eth0 has MTU 1280, (less than 1378), which may cause problems with direct connections"),
758+
},
759+
},
760+
},
761+
},
762+
},
763+
want: []string{
764+
`❗ Agent: network interface eth0 has MTU 1280, (less than 1378), which may cause problems with direct connections`,
765+
`✔ You are connected directly (p2p)`,
766+
},
767+
},
768+
{
769+
name: "LocalInterfaceWarnings",
770+
diags: cliui.ConnDiags{
771+
PingP2P: true,
772+
LocalInterfaces: &healthsdk.InterfacesReport{
773+
BaseReport: healthsdk.BaseReport{
774+
Warnings: []health.Message{
775+
health.Messagef(health.CodeInterfaceSmallMTU, "network interface eth1 has MTU 1310, (less than 1378), which may cause problems with direct connections"),
776+
},
777+
},
778+
},
779+
},
780+
want: []string{
781+
`❗ Client: network interface eth1 has MTU 1310, (less than 1378), which may cause problems with direct connections`,
782+
`✔ You are connected directly (p2p)`,
783+
},
784+
},
785+
}
786+
for _, tc := range testCases {
787+
tc := tc
788+
t.Run(tc.name, func(t *testing.T) {
789+
t.Parallel()
790+
r, w := io.Pipe()
791+
go func() {
792+
defer w.Close()
793+
cliui.ConnDiagnostics(w, tc.diags)
794+
}()
795+
bytes, err := io.ReadAll(r)
796+
require.NoError(t, err)
797+
output := string(bytes)
798+
for _, want := range tc.want {
799+
require.Contains(t, output, want)
800+
}
801+
})
802+
}
803+
}

cli/dotfiles.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"errors"
66
"fmt"
7-
"io/fs"
87
"os"
98
"os/exec"
109
"path/filepath"
@@ -184,7 +183,7 @@ func (r *RootCmd) dotfiles() *serpent.Command {
184183
}
185184
}
186185

187-
script := findScript(installScriptSet, files)
186+
script := findScript(installScriptSet, dotfilesDir)
188187
if script != "" {
189188
_, err = cliui.Prompt(inv, cliui.PromptOptions{
190189
Text: fmt.Sprintf("Running install script %s.\n\n Continue?", script),
@@ -361,15 +360,12 @@ func dirExists(name string) (bool, error) {
361360
}
362361

363362
// findScript will find the first file that matches the script set.
364-
func findScript(scriptSet []string, files []fs.DirEntry) string {
363+
func findScript(scriptSet []string, directory string) string {
365364
for _, i := range scriptSet {
366-
for _, f := range files {
367-
if f.Name() == i {
368-
return f.Name()
369-
}
365+
if _, err := os.Stat(filepath.Join(directory, i)); err == nil {
366+
return i
370367
}
371368
}
372-
373369
return ""
374370
}
375371

cli/dotfiles_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,41 @@ func TestDotfiles(t *testing.T) {
142142
require.NoError(t, err)
143143
require.Equal(t, string(b), "wow\n")
144144
})
145+
146+
t.Run("NestedInstallScript", func(t *testing.T) {
147+
t.Parallel()
148+
if runtime.GOOS == "windows" {
149+
t.Skip("install scripts on windows require sh and aren't very practical")
150+
}
151+
_, root := clitest.New(t)
152+
testRepo := testGitRepo(t, root)
153+
154+
scriptPath := filepath.Join("script", "setup")
155+
err := os.MkdirAll(filepath.Join(testRepo, "script"), 0o750)
156+
require.NoError(t, err)
157+
// nolint:gosec
158+
err = os.WriteFile(filepath.Join(testRepo, scriptPath), []byte("#!/bin/bash\necho wow > "+filepath.Join(string(root), ".bashrc")), 0o750)
159+
require.NoError(t, err)
160+
161+
c := exec.Command("git", "add", scriptPath)
162+
c.Dir = testRepo
163+
err = c.Run()
164+
require.NoError(t, err)
165+
166+
c = exec.Command("git", "commit", "-m", `"add script"`)
167+
c.Dir = testRepo
168+
err = c.Run()
169+
require.NoError(t, err)
170+
171+
inv, _ := clitest.New(t, "dotfiles", "--global-config", string(root), "--symlink-dir", string(root), "-y", testRepo)
172+
err = inv.Run()
173+
require.NoError(t, err)
174+
175+
b, err := os.ReadFile(filepath.Join(string(root), ".bashrc"))
176+
require.NoError(t, err)
177+
require.Equal(t, string(b), "wow\n")
178+
})
179+
145180
t.Run("InstallScriptChangeBranch", func(t *testing.T) {
146181
t.Parallel()
147182
if runtime.GOOS == "windows" {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy