Skip to content

Commit 596100c

Browse files
committed
Merge branch 'main' into bq/copy-from-template
2 parents 03d832c + 349bfad commit 596100c

File tree

7 files changed

+91
-78
lines changed

7 files changed

+91
-78
lines changed

cli/configssh.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func (o *sshConfigOptions) addOptions(options ...string) error {
6262
}
6363

6464
func (o *sshConfigOptions) addOption(option string) error {
65-
key, _, err := codersdk.ParseSSHConfigOption(option)
65+
key, value, err := codersdk.ParseSSHConfigOption(option)
6666
if err != nil {
6767
return err
6868
}
@@ -77,11 +77,20 @@ func (o *sshConfigOptions) addOption(option string) error {
7777
continue
7878
}
7979
if strings.EqualFold(existingKey, key) {
80-
o.sshOptions[i] = option
80+
if value == "" {
81+
// Delete existing option.
82+
o.sshOptions = append(o.sshOptions[:i], o.sshOptions[i+1:]...)
83+
} else {
84+
// Override existing option.
85+
o.sshOptions[i] = option
86+
}
8187
return nil
8288
}
8389
}
84-
o.sshOptions = append(o.sshOptions, option)
90+
// Only append the option if it is not empty.
91+
if value != "" {
92+
o.sshOptions = append(o.sshOptions, option)
93+
}
8594
return nil
8695
}
8796

cli/configssh_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,15 @@ func TestConfigSSH(t *testing.T) {
6666

6767
const hostname = "test-coder."
6868
const expectedKey = "ConnectionAttempts"
69+
const removeKey = "ConnectionTimeout"
6970
client := coderdtest.New(t, &coderdtest.Options{
7071
IncludeProvisionerDaemon: true,
7172
ConfigSSH: codersdk.SSHConfigResponse{
7273
HostnamePrefix: hostname,
7374
SSHConfigOptions: map[string]string{
7475
// Something we can test for
7576
expectedKey: "3",
77+
removeKey: "",
7678
},
7779
},
7880
})
@@ -176,6 +178,7 @@ func TestConfigSSH(t *testing.T) {
176178
fileContents, err := os.ReadFile(sshConfigFile)
177179
require.NoError(t, err, "read ssh config file")
178180
require.Contains(t, string(fileContents), expectedKey, "ssh config file contains expected key")
181+
require.NotContains(t, string(fileContents), removeKey, "ssh config file should not have removed key")
179182

180183
home := filepath.Dir(filepath.Dir(sshConfigFile))
181184
// #nosec

cli/root.go

Lines changed: 40 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package cli
22

33
import (
4-
"bufio"
54
"context"
65
"errors"
76
"flag"
@@ -14,14 +13,11 @@ import (
1413
"os"
1514
"os/signal"
1615
"path/filepath"
17-
"regexp"
1816
"runtime"
1917
"strings"
2018
"syscall"
2119
"time"
22-
"unicode/utf8"
2320

24-
"golang.org/x/crypto/ssh/terminal"
2521
"golang.org/x/exp/slices"
2622
"golang.org/x/xerrors"
2723

@@ -822,89 +818,61 @@ func isConnectionError(err error) bool {
822818
}
823819

824820
type prettyErrorFormatter struct {
825-
level int
826-
w io.Writer
827-
}
828-
829-
func (prettyErrorFormatter) prefixLines(spaces int, s string) string {
830-
twidth, _, err := terminal.GetSize(0)
831-
if err != nil {
832-
twidth = 80
833-
}
834-
835-
s = lipgloss.NewStyle().Width(twidth - spaces).Render(s)
836-
837-
var b strings.Builder
838-
scanner := bufio.NewScanner(strings.NewReader(s))
839-
for i := 0; scanner.Scan(); i++ {
840-
// The first line is already padded.
841-
if i == 0 {
842-
_, _ = fmt.Fprintf(&b, "%s\n", scanner.Text())
843-
continue
844-
}
845-
_, _ = fmt.Fprintf(&b, "%s%s\n", strings.Repeat(" ", spaces), scanner.Text())
846-
}
847-
return strings.TrimSuffix(strings.TrimSuffix(b.String(), "\n"), " ")
821+
w io.Writer
848822
}
849823

850824
func (p *prettyErrorFormatter) format(err error) {
851-
underErr := errors.Unwrap(err)
852-
853-
arrowStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#515151"))
825+
errTail := errors.Unwrap(err)
854826

855827
//nolint:errorlint
856-
if _, ok := err.(*clibase.RunCommandError); ok && p.level == 0 && underErr != nil {
857-
// We can do a better job now.
858-
p.format(underErr)
828+
if _, ok := err.(*clibase.RunCommandError); ok && errTail != nil {
829+
// Avoid extra nesting.
830+
p.format(errTail)
859831
return
860832
}
861833

862-
var (
863-
padding string
864-
arrowWidth int
865-
)
866-
if p.level > 0 {
867-
const arrow = "┗━ "
868-
arrowWidth = utf8.RuneCount([]byte(arrow))
869-
padding = strings.Repeat(" ", arrowWidth*p.level)
870-
_, _ = fmt.Fprintf(p.w, "%v%v", padding, arrowStyle.Render(arrow))
871-
}
872-
873-
if underErr != nil {
874-
header := strings.TrimSuffix(err.Error(), ": "+underErr.Error())
875-
_, _ = fmt.Fprintf(p.w, "%s\n", p.prefixLines(len(padding)+arrowWidth, header))
876-
p.level++
877-
p.format(underErr)
878-
return
834+
var headErr string
835+
if errTail != nil {
836+
headErr = strings.TrimSuffix(err.Error(), ": "+errTail.Error())
837+
} else {
838+
headErr = err.Error()
879839
}
880840

881-
{
882-
style := lipgloss.NewStyle().Foreground(lipgloss.Color("#D16644")).Background(lipgloss.Color("#000000")).Bold(false)
883-
// This is the last error in a tree.
884-
p.wrappedPrintf(
885-
"%s\n",
886-
p.prefixLines(
887-
len(padding)+arrowWidth,
888-
fmt.Sprintf(
889-
"%s%s%s",
890-
lipgloss.NewStyle().Inherit(style).Underline(true).Render("ERROR"),
891-
lipgloss.NewStyle().Inherit(style).Foreground(arrowStyle.GetForeground()).Render(" ► "),
892-
style.Render(err.Error()),
893-
),
894-
),
895-
)
841+
var msg string
842+
var sdkError *codersdk.Error
843+
if errors.As(err, &sdkError) {
844+
// We don't want to repeat the same error message twice, so we
845+
// only show the SDK error on the top of the stack.
846+
msg = sdkError.Message
847+
if sdkError.Helper != "" {
848+
msg = msg + "\n" + sdkError.Helper
849+
}
850+
// The SDK error is usually good enough, and we don't want to overwhelm
851+
// the user with output.
852+
errTail = nil
853+
} else {
854+
msg = headErr
896855
}
897-
}
898856

899-
func (p *prettyErrorFormatter) wrappedPrintf(format string, a ...interface{}) {
900-
s := lipgloss.NewStyle().Width(ttyWidth()).Render(
901-
fmt.Sprintf(format, a...),
857+
headStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#D16644"))
858+
p.printf(
859+
headStyle,
860+
"%s",
861+
msg,
902862
)
903863

904-
// Not sure why, but lipgloss is adding extra spaces we need to remove.
905-
excessSpaceRe := regexp.MustCompile(`[[:blank:]]*\n[[:blank:]]*$`)
906-
s = excessSpaceRe.ReplaceAllString(s, "\n")
864+
tailStyle := headStyle.Copy().Foreground(lipgloss.Color("#969696"))
865+
866+
if errTail != nil {
867+
p.printf(headStyle, ": ")
868+
// Grey out the less important, deep errors.
869+
p.printf(tailStyle, "%s", errTail.Error())
870+
}
871+
p.printf(tailStyle, "\n")
872+
}
907873

874+
func (p *prettyErrorFormatter) printf(style lipgloss.Style, format string, a ...interface{}) {
875+
s := style.Render(fmt.Sprintf(format, a...))
908876
_, _ = p.w.Write(
909877
[]byte(
910878
s,

docs/admin/git-providers.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,35 @@ To support regex matching for paths (e.g. github.com/orgname), you'll need to ad
9090
```console
9191
git config --global credential.useHttpPath true
9292
```
93+
94+
## Require git authentication in templates
95+
96+
If your template requires git authentication (e.g. running `git clone` in the [startup_script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)), you can require users authenticate via git prior to creating a workspace:
97+
98+
![Git authentication in template](../images/admin/git-auth-template.png)
99+
100+
The following example will require users authenticate via GitHub and auto-clone a repo
101+
into the `~/coder` directory.
102+
103+
```hcl
104+
data "coder_git_auth" "github" {
105+
# Matches the ID of the git auth provider in Coder.
106+
id = "github"
107+
}
108+
109+
resource "coder_agent" "dev" {
110+
os = "linux"
111+
arch = "amd64"
112+
dir = "~/coder"
113+
env = {
114+
GITHUB_TOKEN : data.coder_git_auth.github.access_token
115+
}
116+
startup_script = <<EOF
117+
if [ ! -d ~/coder ]; then
118+
git clone https://github.com/coder/coder
119+
fi
120+
EOF
121+
}
122+
```
123+
124+
See the [Terraform provider documentation](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/git_auth) for all available options.
279 KB
Loading

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ require (
299299
github.com/olekukonko/tablewriter v0.0.5 // indirect
300300
github.com/opencontainers/go-digest v1.0.0 // indirect
301301
github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 // indirect
302-
github.com/opencontainers/runc v1.1.2 // indirect
302+
github.com/opencontainers/runc v1.1.5 // indirect
303303
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
304304
github.com/pion/transport v0.14.1 // indirect
305305
github.com/pkg/errors v0.9.1 // indirect

go.sum

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,8 +1550,8 @@ github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rm
15501550
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
15511551
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
15521552
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
1553-
github.com/opencontainers/runc v1.1.2 h1:2VSZwLx5k/BfsBxMMipG/LYUnmqOD/BPkIVgQUcTlLw=
1554-
github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
1553+
github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs=
1554+
github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
15551555
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
15561556
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
15571557
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -1708,6 +1708,7 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg
17081708
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
17091709
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
17101710
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
1711+
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
17111712
github.com/securego/gosec/v2 v2.9.1/go.mod h1:oDcDLcatOJxkCGaCaq8lua1jTnYf6Sou4wdiJ1n4iHc=
17121713
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
17131714
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=

0 commit comments

Comments
 (0)