Skip to content

Commit e75fb3b

Browse files
committed
Merge branch 'main' into callum-cors
Signed-off-by: Callum Styan <callumstyan@gmail.com>
2 parents 432aff6 + 1319ae2 commit e75fb3b

File tree

91 files changed

+3751
-1182
lines changed

Some content is hidden

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

91 files changed

+3751
-1182
lines changed

.github/workflows/release.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,8 @@ jobs:
693693
gsutil -h "Cache-Control:no-cache,max-age=0" cp build/helm/provisioner_helm_${version}.tgz gs://helm.coder.com/v2
694694
gsutil -h "Cache-Control:no-cache,max-age=0" cp build/helm/index.yaml gs://helm.coder.com/v2
695695
gsutil -h "Cache-Control:no-cache,max-age=0" cp helm/artifacthub-repo.yml gs://helm.coder.com/v2
696+
helm push build/coder_helm_${version}.tgz oci://ghcr.io/coder/chart
697+
helm push build/provisioner_helm_${version}.tgz oci://ghcr.io/coder/chart
696698
697699
- name: Upload artifacts to actions (if dry-run)
698700
if: ${{ inputs.dry_run }}

agent/agent.go

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,16 @@ func (a *agent) init() {
336336
// will not report anywhere.
337337
a.scriptRunner.RegisterMetrics(a.prometheusRegistry)
338338

339-
if a.devcontainers {
340-
containerAPIOpts := []agentcontainers.Option{
341-
agentcontainers.WithExecer(a.execer),
342-
agentcontainers.WithCommandEnv(a.sshServer.CommandEnv),
343-
agentcontainers.WithScriptLogger(func(logSourceID uuid.UUID) agentcontainers.ScriptLogger {
344-
return a.logSender.GetScriptLogger(logSourceID)
345-
}),
346-
}
347-
containerAPIOpts = append(containerAPIOpts, a.containerAPIOptions...)
348-
349-
a.containerAPI = agentcontainers.NewAPI(a.logger.Named("containers"), containerAPIOpts...)
339+
containerAPIOpts := []agentcontainers.Option{
340+
agentcontainers.WithExecer(a.execer),
341+
agentcontainers.WithCommandEnv(a.sshServer.CommandEnv),
342+
agentcontainers.WithScriptLogger(func(logSourceID uuid.UUID) agentcontainers.ScriptLogger {
343+
return a.logSender.GetScriptLogger(logSourceID)
344+
}),
350345
}
346+
containerAPIOpts = append(containerAPIOpts, a.containerAPIOptions...)
347+
348+
a.containerAPI = agentcontainers.NewAPI(a.logger.Named("containers"), containerAPIOpts...)
351349

352350
a.reconnectingPTYServer = reconnectingpty.NewServer(
353351
a.logger.Named("reconnecting-pty"),
@@ -1162,7 +1160,7 @@ func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context,
11621160
scripts = manifest.Scripts
11631161
devcontainerScripts map[uuid.UUID]codersdk.WorkspaceAgentScript
11641162
)
1165-
if a.containerAPI != nil {
1163+
if a.devcontainers {
11661164
// Init the container API with the manifest and client so that
11671165
// we can start accepting requests. The final start of the API
11681166
// happens after the startup scripts have been executed to
@@ -1197,7 +1195,7 @@ func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context,
11971195
// autostarted devcontainer will be included in this time.
11981196
err := a.scriptRunner.Execute(a.gracefulCtx, agentscripts.ExecuteStartScripts)
11991197

1200-
if a.containerAPI != nil {
1198+
if a.devcontainers {
12011199
// Start the container API after the startup scripts have
12021200
// been executed to ensure that the required tools can be
12031201
// installed.
@@ -1928,10 +1926,8 @@ func (a *agent) Close() error {
19281926
a.logger.Error(a.hardCtx, "script runner close", slog.Error(err))
19291927
}
19301928

1931-
if a.containerAPI != nil {
1932-
if err := a.containerAPI.Close(); err != nil {
1933-
a.logger.Error(a.hardCtx, "container API close", slog.Error(err))
1934-
}
1929+
if err := a.containerAPI.Close(); err != nil {
1930+
a.logger.Error(a.hardCtx, "container API close", slog.Error(err))
19351931
}
19361932

19371933
// Wait for the graceful shutdown to complete, but don't wait forever so

agent/agent_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,7 +2441,8 @@ func TestAgent_DevcontainersDisabledForSubAgent(t *testing.T) {
24412441

24422442
// Setup the agent with devcontainers enabled initially.
24432443
//nolint:dogsled
2444-
conn, _, _, _, _ := setupAgent(t, manifest, 0, func(*agenttest.Client, *agent.Options) {
2444+
conn, _, _, _, _ := setupAgent(t, manifest, 0, func(_ *agenttest.Client, o *agent.Options) {
2445+
o.Devcontainers = true
24452446
})
24462447

24472448
// Query the containers API endpoint. This should fail because
@@ -2453,8 +2454,8 @@ func TestAgent_DevcontainersDisabledForSubAgent(t *testing.T) {
24532454
require.Error(t, err)
24542455

24552456
// Verify the error message contains the expected text.
2456-
require.Contains(t, err.Error(), "The agent dev containers feature is experimental and not enabled by default.")
2457-
require.Contains(t, err.Error(), "To enable this feature, set CODER_AGENT_DEVCONTAINERS_ENABLE=true in your template.")
2457+
require.Contains(t, err.Error(), "Dev Container feature not supported.")
2458+
require.Contains(t, err.Error(), "Dev Container integration inside other Dev Containers is explicitly not supported.")
24582459
}
24592460

24602461
func TestAgent_Dial(t *testing.T) {

agent/agentcontainers/devcontainercli.go

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -106,63 +106,63 @@ type DevcontainerCLI interface {
106106

107107
// DevcontainerCLIUpOptions are options for the devcontainer CLI Up
108108
// command.
109-
type DevcontainerCLIUpOptions func(*devcontainerCLIUpConfig)
109+
type DevcontainerCLIUpOptions func(*DevcontainerCLIUpConfig)
110110

111-
type devcontainerCLIUpConfig struct {
112-
args []string // Additional arguments for the Up command.
113-
stdout io.Writer
114-
stderr io.Writer
111+
type DevcontainerCLIUpConfig struct {
112+
Args []string // Additional arguments for the Up command.
113+
Stdout io.Writer
114+
Stderr io.Writer
115115
}
116116

117117
// WithRemoveExistingContainer is an option to remove the existing
118118
// container.
119119
func WithRemoveExistingContainer() DevcontainerCLIUpOptions {
120-
return func(o *devcontainerCLIUpConfig) {
121-
o.args = append(o.args, "--remove-existing-container")
120+
return func(o *DevcontainerCLIUpConfig) {
121+
o.Args = append(o.Args, "--remove-existing-container")
122122
}
123123
}
124124

125125
// WithUpOutput sets additional stdout and stderr writers for logs
126126
// during Up operations.
127127
func WithUpOutput(stdout, stderr io.Writer) DevcontainerCLIUpOptions {
128-
return func(o *devcontainerCLIUpConfig) {
129-
o.stdout = stdout
130-
o.stderr = stderr
128+
return func(o *DevcontainerCLIUpConfig) {
129+
o.Stdout = stdout
130+
o.Stderr = stderr
131131
}
132132
}
133133

134134
// DevcontainerCLIExecOptions are options for the devcontainer CLI Exec
135135
// command.
136-
type DevcontainerCLIExecOptions func(*devcontainerCLIExecConfig)
136+
type DevcontainerCLIExecOptions func(*DevcontainerCLIExecConfig)
137137

138-
type devcontainerCLIExecConfig struct {
139-
args []string // Additional arguments for the Exec command.
140-
stdout io.Writer
141-
stderr io.Writer
138+
type DevcontainerCLIExecConfig struct {
139+
Args []string // Additional arguments for the Exec command.
140+
Stdout io.Writer
141+
Stderr io.Writer
142142
}
143143

144144
// WithExecOutput sets additional stdout and stderr writers for logs
145145
// during Exec operations.
146146
func WithExecOutput(stdout, stderr io.Writer) DevcontainerCLIExecOptions {
147-
return func(o *devcontainerCLIExecConfig) {
148-
o.stdout = stdout
149-
o.stderr = stderr
147+
return func(o *DevcontainerCLIExecConfig) {
148+
o.Stdout = stdout
149+
o.Stderr = stderr
150150
}
151151
}
152152

153153
// WithExecContainerID sets the container ID to target a specific
154154
// container.
155155
func WithExecContainerID(id string) DevcontainerCLIExecOptions {
156-
return func(o *devcontainerCLIExecConfig) {
157-
o.args = append(o.args, "--container-id", id)
156+
return func(o *DevcontainerCLIExecConfig) {
157+
o.Args = append(o.Args, "--container-id", id)
158158
}
159159
}
160160

161161
// WithRemoteEnv sets environment variables for the Exec command.
162162
func WithRemoteEnv(env ...string) DevcontainerCLIExecOptions {
163-
return func(o *devcontainerCLIExecConfig) {
163+
return func(o *DevcontainerCLIExecConfig) {
164164
for _, e := range env {
165-
o.args = append(o.args, "--remote-env", e)
165+
o.Args = append(o.Args, "--remote-env", e)
166166
}
167167
}
168168
}
@@ -185,8 +185,8 @@ func WithReadConfigOutput(stdout, stderr io.Writer) DevcontainerCLIReadConfigOpt
185185
}
186186
}
187187

188-
func applyDevcontainerCLIUpOptions(opts []DevcontainerCLIUpOptions) devcontainerCLIUpConfig {
189-
conf := devcontainerCLIUpConfig{stdout: io.Discard, stderr: io.Discard}
188+
func applyDevcontainerCLIUpOptions(opts []DevcontainerCLIUpOptions) DevcontainerCLIUpConfig {
189+
conf := DevcontainerCLIUpConfig{Stdout: io.Discard, Stderr: io.Discard}
190190
for _, opt := range opts {
191191
if opt != nil {
192192
opt(&conf)
@@ -195,8 +195,8 @@ func applyDevcontainerCLIUpOptions(opts []DevcontainerCLIUpOptions) devcontainer
195195
return conf
196196
}
197197

198-
func applyDevcontainerCLIExecOptions(opts []DevcontainerCLIExecOptions) devcontainerCLIExecConfig {
199-
conf := devcontainerCLIExecConfig{stdout: io.Discard, stderr: io.Discard}
198+
func applyDevcontainerCLIExecOptions(opts []DevcontainerCLIExecOptions) DevcontainerCLIExecConfig {
199+
conf := DevcontainerCLIExecConfig{Stdout: io.Discard, Stderr: io.Discard}
200200
for _, opt := range opts {
201201
if opt != nil {
202202
opt(&conf)
@@ -241,7 +241,7 @@ func (d *devcontainerCLI) Up(ctx context.Context, workspaceFolder, configPath st
241241
if configPath != "" {
242242
args = append(args, "--config", configPath)
243243
}
244-
args = append(args, conf.args...)
244+
args = append(args, conf.Args...)
245245
cmd := d.execer.CommandContext(ctx, "devcontainer", args...)
246246

247247
// Capture stdout for parsing and stream logs for both default and provided writers.
@@ -251,14 +251,14 @@ func (d *devcontainerCLI) Up(ctx context.Context, workspaceFolder, configPath st
251251
&devcontainerCLILogWriter{
252252
ctx: ctx,
253253
logger: logger.With(slog.F("stdout", true)),
254-
writer: conf.stdout,
254+
writer: conf.Stdout,
255255
},
256256
)
257257
// Stream stderr logs and provided writer if any.
258258
cmd.Stderr = &devcontainerCLILogWriter{
259259
ctx: ctx,
260260
logger: logger.With(slog.F("stderr", true)),
261-
writer: conf.stderr,
261+
writer: conf.Stderr,
262262
}
263263

264264
if err := cmd.Run(); err != nil {
@@ -293,17 +293,17 @@ func (d *devcontainerCLI) Exec(ctx context.Context, workspaceFolder, configPath
293293
if configPath != "" {
294294
args = append(args, "--config", configPath)
295295
}
296-
args = append(args, conf.args...)
296+
args = append(args, conf.Args...)
297297
args = append(args, cmd)
298298
args = append(args, cmdArgs...)
299299
c := d.execer.CommandContext(ctx, "devcontainer", args...)
300300

301-
c.Stdout = io.MultiWriter(conf.stdout, &devcontainerCLILogWriter{
301+
c.Stdout = io.MultiWriter(conf.Stdout, &devcontainerCLILogWriter{
302302
ctx: ctx,
303303
logger: logger.With(slog.F("stdout", true)),
304304
writer: io.Discard,
305305
})
306-
c.Stderr = io.MultiWriter(conf.stderr, &devcontainerCLILogWriter{
306+
c.Stderr = io.MultiWriter(conf.Stderr, &devcontainerCLILogWriter{
307307
ctx: ctx,
308308
logger: logger.With(slog.F("stderr", true)),
309309
writer: io.Discard,

agent/api.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"time"
77

88
"github.com/go-chi/chi/v5"
9+
"github.com/google/uuid"
910

1011
"github.com/coder/coder/v2/coderd/httpapi"
1112
"github.com/coder/coder/v2/codersdk"
@@ -36,12 +37,19 @@ func (a *agent) apiHandler() http.Handler {
3637
cacheDuration: cacheDuration,
3738
}
3839

39-
if a.containerAPI != nil {
40+
if a.devcontainers {
4041
r.Mount("/api/v0/containers", a.containerAPI.Routes())
42+
} else if manifest := a.manifest.Load(); manifest != nil && manifest.ParentID != uuid.Nil {
43+
r.HandleFunc("/api/v0/containers", func(w http.ResponseWriter, r *http.Request) {
44+
httpapi.Write(r.Context(), w, http.StatusForbidden, codersdk.Response{
45+
Message: "Dev Container feature not supported.",
46+
Detail: "Dev Container integration inside other Dev Containers is explicitly not supported.",
47+
})
48+
})
4149
} else {
4250
r.HandleFunc("/api/v0/containers", func(w http.ResponseWriter, r *http.Request) {
4351
httpapi.Write(r.Context(), w, http.StatusForbidden, codersdk.Response{
44-
Message: "The agent dev containers feature is experimental and not enabled by default.",
52+
Message: "Dev Container feature not enabled.",
4553
Detail: "To enable this feature, set CODER_AGENT_DEVCONTAINERS_ENABLE=true in your template.",
4654
})
4755
})

0 commit comments

Comments
 (0)