Skip to content

Commit b359b0f

Browse files
committed
ian/adding_sidecar_image_param
1 parent ca75541 commit b359b0f

9 files changed

Lines changed: 126 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Notes:
8080
- `namespace` selects the namespace inside the chosen cluster; it does not choose the cluster itself, and defaults to `default` when omitted
8181
- `unschedulable_timeout` controls how long a Pod may remain unschedulable before the task is failed early; it defaults to `30s`, and `0s` disables that fail-fast behavior
8282
- `image_pull_policy` defaults to `IfNotPresent`
83+
- `sidecar_image` overrides the warp-agent sidecar image reference sent by the server (e.g. `docker.io/warpdotdev/warp-agent:latest`); set this when cluster nodes cannot pull directly from Docker Hub and must use an internal registry mirror or pull-through cache instead. This only affects the warp-agent sidecar (mounted at `/agent`), not any additional sidecars. When using this override, you are responsible for keeping your mirror in sync with `docker.io/warpdotdev/warp-agent` — the server normally sends the correct version-matched image per task, so a stale mirror may cause version incompatibility
8384
- by default, the Kubernetes backend materializes sidecars with root init containers into `emptyDir` volumes, matching the existing behavior
8485
- set `use_image_volumes: true` to opt into native image volumes for sidecars; in that mode, sidecar mounts are read-only and Kubernetes/runtime support for the built-in `ImageVolume` Pod volume source is required
8586
- Kubernetes `1.35+` is the recommended and tested target for `use_image_volumes: true`; Kubernetes `1.33`-`1.34` may work if `ImageVolume` is enabled and the container runtime supports image volumes

charts/oz-agent-worker/templates/configmap.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ data:
2424
{{- if .Values.kubernetesBackend.preflightImage }}
2525
preflight_image: {{ .Values.kubernetesBackend.preflightImage | quote }}
2626
{{- end }}
27+
{{- if .Values.kubernetesBackend.sidecarImage }}
28+
sidecar_image: {{ .Values.kubernetesBackend.sidecarImage | quote }}
29+
{{- end }}
2730
{{- if .Values.kubernetesBackend.setupCommand }}
2831
setup_command: |-
2932
{{ .Values.kubernetesBackend.setupCommand | indent 10 }}

charts/oz-agent-worker/values.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ kubernetesBackend:
7070
imagePullPolicy: IfNotPresent
7171
useImageVolumes: false
7272
preflightImage: ""
73+
sidecarImage: ""
7374
setupCommand: ""
7475
teardownCommand: ""
7576
extraLabels: {}

internal/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ type KubernetesConfig struct {
6060
ImagePullPolicy string `yaml:"image_pull_policy" validate:"omitempty,oneof=Always Never IfNotPresent"`
6161
UseImageVolumes bool `yaml:"use_image_volumes"`
6262
PreflightImage string `yaml:"preflight_image" validate:"omitempty,no_whitespace"`
63+
SidecarImage string `yaml:"sidecar_image" validate:"omitempty,no_whitespace"`
6364
SetupCommand string `yaml:"setup_command"`
6465
TeardownCommand string `yaml:"teardown_command"`
6566
ExtraLabels map[string]string `yaml:"extra_labels"`

internal/config/config_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,56 @@ backend:
490490
})
491491
}
492492

493+
func TestLoadKubernetesSidecarImage(t *testing.T) {
494+
t.Run("parses sidecar_image when set", func(t *testing.T) {
495+
path := writeTestConfig(t, `
496+
worker_id: "k8s-worker"
497+
backend:
498+
kubernetes:
499+
sidecar_image: "my-registry.io/warpdotdev/warp-agent:latest"
500+
`)
501+
cfg, err := Load(path)
502+
if err != nil {
503+
t.Fatalf("unexpected error: %v", err)
504+
}
505+
if cfg.Backend.Kubernetes == nil {
506+
t.Fatal("expected kubernetes backend to be set")
507+
}
508+
if cfg.Backend.Kubernetes.SidecarImage != "my-registry.io/warpdotdev/warp-agent:latest" {
509+
t.Errorf("sidecar_image = %q, want %q", cfg.Backend.Kubernetes.SidecarImage, "my-registry.io/warpdotdev/warp-agent:latest")
510+
}
511+
})
512+
513+
t.Run("sidecar_image is empty when not set", func(t *testing.T) {
514+
path := writeTestConfig(t, `
515+
worker_id: "k8s-worker"
516+
backend:
517+
kubernetes:
518+
namespace: "agents"
519+
`)
520+
cfg, err := Load(path)
521+
if err != nil {
522+
t.Fatalf("unexpected error: %v", err)
523+
}
524+
if cfg.Backend.Kubernetes.SidecarImage != "" {
525+
t.Errorf("expected sidecar_image to be empty, got %q", cfg.Backend.Kubernetes.SidecarImage)
526+
}
527+
})
528+
529+
t.Run("rejects sidecar_image with whitespace", func(t *testing.T) {
530+
path := writeTestConfig(t, `
531+
worker_id: "k8s-worker"
532+
backend:
533+
kubernetes:
534+
sidecar_image: "my image:latest"
535+
`)
536+
_, err := Load(path)
537+
if err == nil {
538+
t.Fatal("expected error for sidecar_image with whitespace")
539+
}
540+
})
541+
}
542+
493543
func TestLoadLegacyKubernetesFieldRejected(t *testing.T) {
494544
tests := []string{
495545
"image_pull_secret",

internal/worker/kubernetes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ type KubernetesBackendConfig struct {
5555
ImagePullPolicy string
5656
UseImageVolumes bool
5757
PreflightImage string
58+
SidecarImage string
5859
SetupCommand string
5960
TeardownCommand string
6061
NoCleanup bool

internal/worker/worker.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,13 @@ func (w *Worker) prepareTaskParams(assignment *types.TaskAssignmentMessage) *Tas
381381
// entrypoint.sh lives) comes first, followed by any additional sidecars.
382382
var sidecars []types.SidecarMount
383383
if assignment.SidecarImage != "" {
384+
sidecarImage := assignment.SidecarImage
385+
if w.config.Kubernetes != nil && w.config.Kubernetes.SidecarImage != "" {
386+
log.Infof(w.ctx, "Overriding server sidecar image %s with configured sidecar image %s", assignment.SidecarImage, w.config.Kubernetes.SidecarImage)
387+
sidecarImage = w.config.Kubernetes.SidecarImage
388+
}
384389
sidecars = append(sidecars, types.SidecarMount{
385-
Image: assignment.SidecarImage,
390+
Image: sidecarImage,
386391
MountPath: "/agent",
387392
})
388393
}

internal/worker/worker_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,66 @@ func TestDefaultImageForTask(t *testing.T) {
8787
})
8888
}
8989

90+
func TestPrepareTaskParamsSidecarImageOverride(t *testing.T) {
91+
newWorker := func(sidecarImage string) *Worker {
92+
ctx := context.Background()
93+
var k8sConfig *KubernetesBackendConfig
94+
if sidecarImage != "" {
95+
k8sConfig = &KubernetesBackendConfig{SidecarImage: sidecarImage}
96+
} else {
97+
k8sConfig = &KubernetesBackendConfig{}
98+
}
99+
return &Worker{
100+
ctx: ctx,
101+
config: Config{
102+
Kubernetes: k8sConfig,
103+
},
104+
}
105+
}
106+
107+
t.Run("config sidecar_image overrides server-provided image", func(t *testing.T) {
108+
w := newWorker("my-registry.io/warpdotdev/warp-agent:latest")
109+
params := w.prepareTaskParams(&types.TaskAssignmentMessage{
110+
TaskID: "task-1",
111+
Task: &types.Task{ID: "task-1"},
112+
SidecarImage: "docker.io/warpdotdev/warp-agent:latest",
113+
})
114+
if len(params.Sidecars) == 0 {
115+
t.Fatal("expected at least one sidecar")
116+
}
117+
if params.Sidecars[0].Image != "my-registry.io/warpdotdev/warp-agent:latest" {
118+
t.Errorf("sidecar image = %q, want %q", params.Sidecars[0].Image, "my-registry.io/warpdotdev/warp-agent:latest")
119+
}
120+
})
121+
122+
t.Run("server-provided image used when config sidecar_image empty", func(t *testing.T) {
123+
w := newWorker("")
124+
params := w.prepareTaskParams(&types.TaskAssignmentMessage{
125+
TaskID: "task-1",
126+
Task: &types.Task{ID: "task-1"},
127+
SidecarImage: "docker.io/warpdotdev/warp-agent:latest",
128+
})
129+
if len(params.Sidecars) == 0 {
130+
t.Fatal("expected at least one sidecar")
131+
}
132+
if params.Sidecars[0].Image != "docker.io/warpdotdev/warp-agent:latest" {
133+
t.Errorf("sidecar image = %q, want %q", params.Sidecars[0].Image, "docker.io/warpdotdev/warp-agent:latest")
134+
}
135+
})
136+
137+
t.Run("no sidecar when server provides empty sidecar image", func(t *testing.T) {
138+
w := newWorker("my-registry.io/warpdotdev/warp-agent:latest")
139+
params := w.prepareTaskParams(&types.TaskAssignmentMessage{
140+
TaskID: "task-1",
141+
Task: &types.Task{ID: "task-1"},
142+
SidecarImage: "",
143+
})
144+
if len(params.Sidecars) != 0 {
145+
t.Errorf("expected no sidecars when server sidecar image is empty, got %d", len(params.Sidecars))
146+
}
147+
})
148+
}
149+
90150
func TestWorkerShutdownUsesFreshContextForBackendCleanup(t *testing.T) {
91151
workerCtx, cancel := context.WithCancel(context.Background())
92152
backend := &shutdownRecordingBackend{}

main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ func mergeConfig(fileConfig *config.FileConfig) (worker.Config, error) {
158158
imagePullPolicy string
159159
useImageVolumes bool
160160
preflightImage string
161+
sidecarImage string
161162
setupCmd string
162163
teardownCmd string
163164
extraLabels map[string]string
@@ -176,6 +177,7 @@ func mergeConfig(fileConfig *config.FileConfig) (worker.Config, error) {
176177
imagePullPolicy = kc.ImagePullPolicy
177178
useImageVolumes = kc.UseImageVolumes
178179
preflightImage = kc.PreflightImage
180+
sidecarImage = kc.SidecarImage
179181
setupCmd = kc.SetupCommand
180182
teardownCmd = kc.TeardownCommand
181183
extraLabels = copyStringMap(kc.ExtraLabels)
@@ -216,6 +218,7 @@ func mergeConfig(fileConfig *config.FileConfig) (worker.Config, error) {
216218
ImagePullPolicy: imagePullPolicy,
217219
UseImageVolumes: useImageVolumes,
218220
PreflightImage: preflightImage,
221+
SidecarImage: sidecarImage,
219222
SetupCommand: setupCmd,
220223
TeardownCommand: teardownCmd,
221224
NoCleanup: noCleanup,

0 commit comments

Comments
 (0)