Skip to content

Commit 9936923

Browse files
committed
Merge branch 'main' into fixtest
2 parents 80f9cda + 95ff29c commit 9936923

File tree

123 files changed

+1183
-593
lines changed

Some content is hidden

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

123 files changed

+1183
-593
lines changed

.github/workflows/release.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,11 @@ jobs:
333333
# For gh CLI. We need a real token since we're commenting on a PR in a
334334
# different repo.
335335
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }}
336+
337+
- name: Start Packer builds
338+
uses: peter-evans/repository-dispatch@v2
339+
with:
340+
token: ${{ secrets.CDRCI_GITHUB_TOKEN }}
341+
repository: coder/packages
342+
event-type: coder-release
343+
client-payload: '{"coder_version": "${{ needs.release.outputs.version }}"}'

cli/configssh.go

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,11 @@ func configSSH() *cobra.Command {
206206
// Parse the previous configuration only if config-ssh
207207
// has been run previously.
208208
var lastConfig *sshConfigOptions
209-
if section, ok := sshConfigGetCoderSection(configRaw); ok {
209+
section, ok, err := sshConfigGetCoderSection(configRaw)
210+
if err != nil {
211+
return err
212+
}
213+
if ok {
210214
c := sshConfigParseLastOptions(bytes.NewReader(section))
211215
lastConfig = &c
212216
}
@@ -249,7 +253,10 @@ func configSSH() *cobra.Command {
249253
configModified := configRaw
250254

251255
buf := &bytes.Buffer{}
252-
before, after := sshConfigSplitOnCoderSection(configModified)
256+
before, _, after, err := sshConfigSplitOnCoderSection(configModified)
257+
if err != nil {
258+
return err
259+
}
253260
// Write the first half of the users config file to buf.
254261
_, _ = buf.Write(before)
255262

@@ -418,22 +425,39 @@ func sshConfigParseLastOptions(r io.Reader) (o sshConfigOptions) {
418425
return o
419426
}
420427

421-
func sshConfigGetCoderSection(data []byte) (section []byte, ok bool) {
422-
startIndex := bytes.Index(data, []byte(sshStartToken))
423-
endIndex := bytes.Index(data, []byte(sshEndToken))
424-
if startIndex != -1 && endIndex != -1 {
425-
return data[startIndex : endIndex+len(sshEndToken)], true
428+
// sshConfigGetCoderSection is a helper function that only returns the coder
429+
// section of the SSH config and a boolean if it exists.
430+
func sshConfigGetCoderSection(data []byte) (section []byte, ok bool, err error) {
431+
_, section, _, err = sshConfigSplitOnCoderSection(data)
432+
if err != nil {
433+
return nil, false, err
426434
}
427-
return nil, false
435+
436+
return section, len(section) > 0, nil
428437
}
429438

430-
// sshConfigSplitOnCoderSection splits the SSH config into two sections,
431-
// before contains the lines before sshStartToken and after contains the
432-
// lines after sshEndToken.
433-
func sshConfigSplitOnCoderSection(data []byte) (before, after []byte) {
439+
// sshConfigSplitOnCoderSection splits the SSH config into 3 sections.
440+
// All lines before sshStartToken, the coder section, and all lines after
441+
// sshEndToken.
442+
func sshConfigSplitOnCoderSection(data []byte) (before, section []byte, after []byte, err error) {
443+
startCount := bytes.Count(data, []byte(sshStartToken))
444+
endCount := bytes.Count(data, []byte(sshEndToken))
445+
if startCount > 1 || endCount > 1 {
446+
return nil, nil, nil, xerrors.New("Malformed config: ssh config has multiple coder sections, please remove all but one")
447+
}
448+
434449
startIndex := bytes.Index(data, []byte(sshStartToken))
435450
endIndex := bytes.Index(data, []byte(sshEndToken))
451+
if startIndex == -1 && endIndex != -1 {
452+
return nil, nil, nil, xerrors.New("Malformed config: ssh config has end header, but missing start header")
453+
}
454+
if startIndex != -1 && endIndex == -1 {
455+
return nil, nil, nil, xerrors.New("Malformed config: ssh config has start header, but missing end header")
456+
}
436457
if startIndex != -1 && endIndex != -1 {
458+
if startIndex > endIndex {
459+
return nil, nil, nil, xerrors.New("Malformed config: ssh config has coder section, but it is malformed and the END header is before the START header")
460+
}
437461
// We use -1 and +1 here to also include the preceding
438462
// and trailing newline, where applicable.
439463
start := startIndex
@@ -444,10 +468,10 @@ func sshConfigSplitOnCoderSection(data []byte) (before, after []byte) {
444468
if end < len(data) {
445469
end++
446470
}
447-
return data[:start], data[end:]
471+
return data[:start], data[start:end], data[end:], nil
448472
}
449473

450-
return data, nil
474+
return data, nil, nil, nil
451475
}
452476

453477
// writeWithTempFileAndMove writes to a temporary file in the same

cli/configssh_internal_test.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,125 @@ import (
1111
"github.com/stretchr/testify/require"
1212
)
1313

14+
func Test_sshConfigSplitOnCoderSection(t *testing.T) {
15+
t.Parallel()
16+
17+
testCases := []struct {
18+
Name string
19+
Input string
20+
Before string
21+
Section string
22+
After string
23+
Err bool
24+
}{
25+
{
26+
Name: "Empty",
27+
Input: "",
28+
Before: "",
29+
Section: "",
30+
After: "",
31+
Err: false,
32+
},
33+
{
34+
Name: "JustSection",
35+
Input: strings.Join([]string{sshStartToken, sshEndToken}, "\n"),
36+
Before: "",
37+
Section: strings.Join([]string{sshStartToken, sshEndToken}, "\n"),
38+
After: "",
39+
Err: false,
40+
},
41+
{
42+
Name: "NoSection",
43+
Input: strings.Join([]string{"# Some content"}, "\n"),
44+
Before: "# Some content",
45+
Section: "",
46+
After: "",
47+
Err: false,
48+
},
49+
{
50+
Name: "Normal",
51+
Input: strings.Join([]string{
52+
"# Content before the section",
53+
sshStartToken,
54+
sshEndToken,
55+
"# Content after the section",
56+
}, "\n"),
57+
Before: "# Content before the section",
58+
Section: strings.Join([]string{"", sshStartToken, sshEndToken, ""}, "\n"),
59+
After: "# Content after the section",
60+
Err: false,
61+
},
62+
{
63+
Name: "OutOfOrder",
64+
Input: strings.Join([]string{
65+
"# Content before the section",
66+
sshEndToken,
67+
sshStartToken,
68+
"# Content after the section",
69+
}, "\n"),
70+
Err: true,
71+
},
72+
{
73+
Name: "MissingStart",
74+
Input: strings.Join([]string{
75+
"# Content before the section",
76+
sshEndToken,
77+
"# Content after the section",
78+
}, "\n"),
79+
Err: true,
80+
},
81+
{
82+
Name: "MissingEnd",
83+
Input: strings.Join([]string{
84+
"# Content before the section",
85+
sshEndToken,
86+
"# Content after the section",
87+
}, "\n"),
88+
Err: true,
89+
},
90+
{
91+
Name: "ExtraStart",
92+
Input: strings.Join([]string{
93+
"# Content before the section",
94+
sshStartToken,
95+
sshEndToken,
96+
sshStartToken,
97+
"# Content after the section",
98+
}, "\n"),
99+
Err: true,
100+
},
101+
{
102+
Name: "ExtraEnd",
103+
Input: strings.Join([]string{
104+
"# Content before the section",
105+
sshStartToken,
106+
sshEndToken,
107+
sshEndToken,
108+
"# Content after the section",
109+
}, "\n"),
110+
Err: true,
111+
},
112+
}
113+
114+
for _, tc := range testCases {
115+
tc := tc
116+
t.Run(tc.Name, func(t *testing.T) {
117+
t.Parallel()
118+
119+
before, section, after, err := sshConfigSplitOnCoderSection([]byte(tc.Input))
120+
if tc.Err {
121+
require.Error(t, err)
122+
return
123+
}
124+
125+
require.NoError(t, err)
126+
require.Equal(t, tc.Before, string(before), "before")
127+
require.Equal(t, tc.Section, string(section), "section")
128+
require.Equal(t, tc.After, string(after), "after")
129+
})
130+
}
131+
}
132+
14133
// This test tries to mimic the behavior of OpenSSH
15134
// when executing e.g. a ProxyCommand.
16135
func Test_sshConfigExecEscape(t *testing.T) {

cli/configssh_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,36 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
529529
"--yes",
530530
},
531531
},
532+
{
533+
name: "Start/End out of order",
534+
matches: []match{
535+
//{match: "Continue?", write: "yes"},
536+
},
537+
writeConfig: writeConfig{
538+
ssh: strings.Join([]string{
539+
"# Content before coder block",
540+
headerEnd,
541+
headerStart,
542+
"# Content after coder block",
543+
}, "\n"),
544+
},
545+
wantErr: true,
546+
},
547+
{
548+
name: "Multiple sections",
549+
matches: []match{
550+
//{match: "Continue?", write: "yes"},
551+
},
552+
writeConfig: writeConfig{
553+
ssh: strings.Join([]string{
554+
headerStart,
555+
headerEnd,
556+
headerStart,
557+
headerEnd,
558+
}, "\n"),
559+
},
560+
wantErr: true,
561+
},
532562
}
533563
for _, tt := range tests {
534564
tt := tt

cli/root_test.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ var updateGoldenFiles = flag.Bool("update", false, "update .golden files")
3131
//nolint:tparallel,paralleltest // These test sets env vars.
3232
func TestCommandHelp(t *testing.T) {
3333
commonEnv := map[string]string{
34-
"CODER_CONFIG_DIR": "/tmp/coder-cli-test-config",
34+
"HOME": "~",
35+
"CODER_CONFIG_DIR": "~/.config/coderv2",
3536
}
3637

3738
type testCase struct {
@@ -48,7 +49,7 @@ func TestCommandHelp(t *testing.T) {
4849
name: "coder server --help",
4950
cmd: []string{"server", "--help"},
5051
env: map[string]string{
51-
"CODER_CACHE_DIRECTORY": "/tmp/coder-cli-test-cache",
52+
"CODER_CACHE_DIRECTORY": "~/.cache/coder",
5253
},
5354
},
5455
{
@@ -104,19 +105,27 @@ ExtractCommandPathsLoop:
104105

105106
ctx, _ := testutil.Context(t)
106107

108+
tmpwd := "/"
109+
if runtime.GOOS == "windows" {
110+
tmpwd = "C:\\"
111+
}
112+
err := os.Chdir(tmpwd)
107113
var buf bytes.Buffer
108114
root, _ := clitest.New(t, tt.cmd...)
109115
root.SetOut(&buf)
110-
err := root.ExecuteContext(ctx)
116+
assert.NoError(t, err)
117+
err = root.ExecuteContext(ctx)
118+
err2 := os.Chdir(wd)
111119
require.NoError(t, err)
120+
require.NoError(t, err2)
112121

113122
got := buf.Bytes()
114123
// Remove CRLF newlines (Windows).
115124
// got = bytes.ReplaceAll(got, []byte{'\r', '\n'}, []byte{'\n'})
116125

117126
// The `coder templates create --help` command prints the path
118127
// to the working directory (--directory flag default value).
119-
got = bytes.ReplaceAll(got, []byte(wd), []byte("/tmp/coder-cli-test-workdir"))
128+
got = bytes.ReplaceAll(got, []byte(fmt.Sprintf("%q", tmpwd)), []byte("\"[current directory]\""))
120129

121130
gf := filepath.Join("testdata", strings.Replace(tt.name, " ", "_", -1)+".golden")
122131
if *updateGoldenFiles {

cli/server.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ import (
6161
"github.com/coder/coder/coderd"
6262
"github.com/coder/coder/coderd/autobuild/executor"
6363
"github.com/coder/coder/coderd/database"
64-
"github.com/coder/coder/coderd/database/databasefake"
64+
"github.com/coder/coder/coderd/database/dbfake"
6565
"github.com/coder/coder/coderd/database/migrations"
6666
"github.com/coder/coder/coderd/devtunnel"
6767
"github.com/coder/coder/coderd/gitauth"
@@ -461,7 +461,7 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
461461
AppHostname: appHostname,
462462
AppHostnameRegex: appHostnameRegex,
463463
Logger: logger.Named("coderd"),
464-
Database: databasefake.New(),
464+
Database: dbfake.New(),
465465
DERPMap: derpMap,
466466
Pubsub: database.NewPubsubInMemory(),
467467
CacheDir: cacheDir,
@@ -560,7 +560,7 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
560560
}
561561

562562
if cfg.InMemoryDatabase.Value {
563-
options.Database = databasefake.New()
563+
options.Database = dbfake.New()
564564
options.Pubsub = database.NewPubsubInMemory()
565565
} else {
566566
logger.Debug(ctx, "connecting to postgresql")

cli/testdata/coder_--help.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Workspace Commands:
4848

4949
Flags:
5050
--global-config coder Path to the global coder config directory.
51-
Consumes $CODER_CONFIG_DIR (default "/tmp/coder-cli-test-config")
51+
Consumes $CODER_CONFIG_DIR (default "~/.config/coderv2")
5252
--header stringArray HTTP headers added to all requests. Provide as "Key=Value".
5353
Consumes $CODER_HEADER
5454
-h, --help help for coder

cli/testdata/coder_agent_--help.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Flags:
1313

1414
Global Flags:
1515
--global-config coder Path to the global coder config directory.
16-
Consumes $CODER_CONFIG_DIR (default "/tmp/coder-cli-test-config")
16+
Consumes $CODER_CONFIG_DIR (default "~/.config/coderv2")
1717
--header stringArray HTTP headers added to all requests. Provide as "Key=Value".
1818
Consumes $CODER_HEADER
1919
--no-feature-warning Suppress warnings about unlicensed features.

cli/testdata/coder_config-ssh_--help.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Flags:
2727

2828
Global Flags:
2929
--global-config coder Path to the global coder config directory.
30-
Consumes $CODER_CONFIG_DIR (default "/tmp/coder-cli-test-config")
30+
Consumes $CODER_CONFIG_DIR (default "~/.config/coderv2")
3131
--header stringArray HTTP headers added to all requests. Provide as "Key=Value".
3232
Consumes $CODER_HEADER
3333
--no-feature-warning Suppress warnings about unlicensed features.

cli/testdata/coder_create_--help.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Flags:
2323

2424
Global Flags:
2525
--global-config coder Path to the global coder config directory.
26-
Consumes $CODER_CONFIG_DIR (default "/tmp/coder-cli-test-config")
26+
Consumes $CODER_CONFIG_DIR (default "~/.config/coderv2")
2727
--header stringArray HTTP headers added to all requests. Provide as "Key=Value".
2828
Consumes $CODER_HEADER
2929
--no-feature-warning Suppress warnings about unlicensed features.

0 commit comments

Comments
 (0)