Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit59ab505

Browse files
authored
fix: return error if agent init script fails to download valid binary (#13280)
1 parente176867 commit59ab505

File tree

6 files changed

+153
-29
lines changed

6 files changed

+153
-29
lines changed

‎provisionersdk/agent.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ var (
3939
}
4040
)
4141

42-
// AgentScriptEnv returns a key-pair of scripts that are consumed
43-
//by the Coder Terraform Provider. See:
44-
//https://github.com/coder/terraform-provider-coder/blob/main/internal/provider/provider.go#L97
42+
// AgentScriptEnv returns a key-pair of scripts that are consumed by the Coder Terraform Provider.
43+
//https://github.com/coder/terraform-provider-coder/blob/main/provider/agent.go (updateInitScript)
44+
//performs additional string substitutions.
4545
funcAgentScriptEnv()map[string]string {
4646
env:=map[string]string{}
4747
foroperatingSystem,scripts:=rangeagentScripts {

‎provisionersdk/agent_test.go

Lines changed: 116 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,57 +7,152 @@
77
package provisionersdk_test
88

99
import (
10+
"bytes"
11+
"context"
12+
"errors"
1013
"fmt"
1114
"net/http"
1215
"net/http/httptest"
1316
"net/url"
1417
"os/exec"
1518
"runtime"
1619
"strings"
20+
"sync"
1721
"testing"
22+
"time"
1823

1924
"github.com/go-chi/render"
2025
"github.com/stretchr/testify/require"
2126

27+
"github.com/coder/coder/v2/testutil"
28+
2229
"github.com/coder/coder/v2/provisionersdk"
2330
)
2431

32+
// mimicking the --version output which we use to test the binary (see provisionersdk/scripts/bootstrap_*).
33+
constversionOutput=`Coder v2.11.0+8979bfe Tue May 7 17:30:19 UTC 2024`
34+
2535
// bashEcho is a script that calls the local `echo` with the arguments. This is preferable to
2636
// sending the real `echo` binary since macOS 14.4+ immediately sigkills `echo` if it is copied to
2737
// another directory and run locally.
2838
constbashEcho=`#!/usr/bin/env bash
29-
echo $@`
39+
echo "`+versionOutput+`"`
40+
41+
constunexpectedEcho=`#!/usr/bin/env bash
42+
echo "this is not the agent you are looking for"`
3043

3144
funcTestAgentScript(t*testing.T) {
3245
t.Parallel()
33-
t.Run("Run",func(t*testing.T) {
46+
47+
t.Run("Valid",func(t*testing.T) {
3448
t.Parallel()
35-
srv:=httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter,r*http.Request) {
36-
render.Status(r,http.StatusOK)
37-
render.Data(rw,r, []byte(bashEcho))
38-
}))
39-
defersrv.Close()
40-
srvURL,err:=url.Parse(srv.URL)
41-
require.NoError(t,err)
4249

43-
script,exists:=provisionersdk.AgentScriptEnv()[fmt.Sprintf("CODER_AGENT_SCRIPT_%s_%s",runtime.GOOS,runtime.GOARCH)]
44-
if!exists {
45-
t.Skip("Agent not supported...")
46-
return
47-
}
48-
script=strings.ReplaceAll(script,"${ACCESS_URL}",srvURL.String()+"/")
49-
script=strings.ReplaceAll(script,"${AUTH_TYPE}","token")
50+
script:=serveScript(t,bashEcho)
51+
52+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitShort)
53+
t.Cleanup(cancel)
54+
55+
varoutput bytes.Buffer
5056
// This is intentionally ran in single quotes to mimic how a customer may
5157
// embed our script. Our scripts should not include any single quotes.
5258
// nolint:gosec
53-
output,err:=exec.Command("sh","-c","sh -c '"+script+"'").CombinedOutput()
54-
t.Log(string(output))
59+
cmd:=exec.CommandContext(ctx,"sh","-c","sh -c '"+script+"'")
60+
cmd.Stdout=&output
61+
cmd.Stderr=&output
62+
require.NoError(t,cmd.Start())
63+
64+
err:=cmd.Wait()
65+
iferr!=nil {
66+
varexitErr*exec.ExitError
67+
iferrors.As(err,&exitErr) {
68+
require.Equal(t,0,exitErr.ExitCode())
69+
}else {
70+
t.Fatalf("unexpected err: %s",err)
71+
}
72+
}
73+
74+
t.Log(output.String())
5575
require.NoError(t,err)
5676
// Ignore debug output from `set -x`, we're only interested in the last line.
57-
lines:=strings.Split(strings.TrimSpace(string(output)),"\n")
77+
lines:=strings.Split(strings.TrimSpace(output.String()),"\n")
5878
lastLine:=lines[len(lines)-1]
59-
//Because we use the "echo" binary, we should expect the arguments provided
79+
//When we use the "bashEcho" binary, we should expect the arguments provided
6080
// as the response to executing our script.
61-
require.Equal(t,"agent",lastLine)
81+
require.Equal(t,versionOutput,lastLine)
6282
})
83+
84+
t.Run("Invalid",func(t*testing.T) {
85+
t.Parallel()
86+
87+
script:=serveScript(t,unexpectedEcho)
88+
89+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitShort)
90+
t.Cleanup(cancel)
91+
92+
varoutput bytes.Buffer
93+
// This is intentionally ran in single quotes to mimic how a customer may
94+
// embed our script. Our scripts should not include any single quotes.
95+
// nolint:gosec
96+
cmd:=exec.CommandContext(ctx,"sh","-c","sh -c '"+script+"'")
97+
cmd.WaitDelay=time.Second
98+
cmd.Stdout=&output
99+
cmd.Stderr=&output
100+
require.NoError(t,cmd.Start())
101+
102+
done:=make(chanerror,1)
103+
varwg sync.WaitGroup
104+
wg.Add(1)
105+
gofunc() {
106+
deferwg.Done()
107+
108+
// The bootstrap scripts trap exit codes to allow operators to view the script logs and debug the process
109+
// while it is still running. We do not expect Wait() to complete.
110+
err:=cmd.Wait()
111+
done<-err
112+
}()
113+
114+
select {
115+
case<-ctx.Done():
116+
// Timeout.
117+
break
118+
caseerr:=<-done:
119+
// If done signals before context times out, script behaved in an unexpected way.
120+
iferr!=nil {
121+
t.Fatalf("unexpected err: %s",err)
122+
}
123+
}
124+
125+
// Kill the command, wait for the command to yield.
126+
require.NoError(t,cmd.Cancel())
127+
wg.Wait()
128+
129+
t.Log(output.String())
130+
131+
require.Eventually(t,func()bool {
132+
returnbytes.Contains(output.Bytes(), []byte("ERROR: Downloaded agent binary returned unexpected version output"))
133+
},testutil.WaitShort,testutil.IntervalSlow)
134+
})
135+
}
136+
137+
// serveScript creates a fake HTTP server which serves a requested "agent binary" (which is actually the given input string)
138+
// which will be attempted to run to verify that it is correct.
139+
funcserveScript(t*testing.T,instring)string {
140+
t.Helper()
141+
142+
srv:=httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter,r*http.Request) {
143+
render.Status(r,http.StatusOK)
144+
render.Data(rw,r, []byte(in))
145+
}))
146+
t.Cleanup(srv.Close)
147+
srvURL,err:=url.Parse(srv.URL)
148+
require.NoError(t,err)
149+
150+
script,exists:=provisionersdk.AgentScriptEnv()[fmt.Sprintf("CODER_AGENT_SCRIPT_%s_%s",runtime.GOOS,runtime.GOARCH)]
151+
if!exists {
152+
t.Skip("Agent not supported...")
153+
return""
154+
}
155+
script=strings.ReplaceAll(script,"${ACCESS_URL}",srvURL.String()+"/")
156+
script=strings.ReplaceAll(script,"${AUTH_TYPE}","token")
157+
returnscript
63158
}

‎provisionersdk/scripts/bootstrap_darwin.sh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -eux
44
# This is to allow folks to exec into a failed workspace and poke around to
55
# troubleshoot.
66
waitonexit() {
7-
echo"=== Agent script exited with non-zero code. Sleeping 24h to preserve logs..."
7+
echo"=== Agent script exited with non-zero code ($?). Sleeping 24h to preserve logs..."
88
sleep 86400
99
}
1010
trap waitonexit EXIT
@@ -31,4 +31,12 @@ fi
3131

3232
export CODER_AGENT_AUTH="${AUTH_TYPE}"
3333
export CODER_AGENT_URL="${ACCESS_URL}"
34-
exec ./$BINARY_NAME agent
34+
35+
output=$(./${BINARY_NAME} --version| head -n1)
36+
if!echo"${output}"| grep -q Coder;then
37+
echo>&2"ERROR: Downloaded agent binary returned unexpected version output"
38+
echo>&2"${BINARY_NAME} --version output:\"${output}\""
39+
exit 2
40+
fi
41+
42+
exec ./${BINARY_NAME} agent

‎provisionersdk/scripts/bootstrap_linux.sh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -eux
44
# This is to allow folks to exec into a failed workspace and poke around to
55
# troubleshoot.
66
waitonexit() {
7-
echo"=== Agent script exited with non-zero code. Sleeping 24h to preserve logs..."
7+
echo"=== Agent script exited with non-zero code ($?). Sleeping 24h to preserve logs..."
88
sleep 86400
99
}
1010
trap waitonexit EXIT
@@ -86,4 +86,12 @@ fi
8686

8787
export CODER_AGENT_AUTH="${AUTH_TYPE}"
8888
export CODER_AGENT_URL="${ACCESS_URL}"
89-
exec ./$BINARY_NAME agent
89+
90+
output=$(./${BINARY_NAME} --version| head -n1)
91+
if!echo"${output}"| grep -q Coder;then
92+
echo>&2"ERROR: Downloaded agent binary returned unexpected version output"
93+
echo>&2"${BINARY_NAME} --version output:\"${output}\""
94+
exit 2
95+
fi
96+
97+
exec ./${BINARY_NAME} agent

‎provisionersdk/scripts/bootstrap_windows.ps1

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ if (-not (Get-Command 'Set-MpPreference' -ErrorAction SilentlyContinue)) {
3535
$env:CODER_AGENT_AUTH="${AUTH_TYPE}"
3636
$env:CODER_AGENT_URL="${ACCESS_URL}"
3737

38+
$psi= [System.Diagnostics.ProcessStartInfo]::new("$env:TEMP\sshd.exe",'--version')
39+
$psi.UseShellExecute=$false
40+
$psi.RedirectStandardOutput=$true
41+
$p= [System.Diagnostics.Process]::Start($psi)
42+
$output=$p.StandardOutput.ReadToEnd()
43+
$p.WaitForExit()
44+
45+
if ($output-notlike"*Coder*") {
46+
Write-Output"$env:TEMP\sshd.exe --version output:`"$output"`"
47+
Write-Error"ERROR: Downloaded agent binary returned unexpected version output"
48+
Throw"unexpected binary"
49+
}
50+
3851
# Check if we're running inside a Windows container!
3952
$inContainer=$false
4053
if ((Get-ItemProperty'HKLM:\SYSTEM\CurrentControlSet\Control'-Name'ContainerType'-ErrorAction SilentlyContinue)-ne$null) {

‎scripts/check_site_icons.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/bash
1+
#!/usr/bin/envbash
22

33
set -euo pipefail
44
# shellcheck source=scripts/lib.sh

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp