Skip to content

CRW-9373-run-77683332#17

Open
akurinnoy wants to merge 13 commits into
mainfrom
supervisor/77683332-7987-4a32-8dee-2f30b9737c38
Open

CRW-9373-run-77683332#17
akurinnoy wants to merge 13 commits into
mainfrom
supervisor/77683332-7987-4a32-8dee-2f30b9737c38

Conversation

@akurinnoy

@akurinnoy akurinnoy commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

This PR adds support for operator-level custom init containers that are injected into all workspace pods via the DevWorkspaceOperatorConfig (DWOC). It also introduces an override mechanism for the built-in init-persistent-home init container, command validation, and image inheritance behavior.

Feature Description

New field: config.workspace.initContainers

A new field InitContainers []corev1.Container is added to WorkspaceConfig in the DWOC. Any init containers defined here are automatically injected into every workspace pod before startup.

Example DWOC configuration:

spec:
  config:
    workspace:
      initContainers:
        - name: my-org-init
          image: quay.io/my-org/init-tools:latest
          command: ["/bin/sh", "-c"]
          args: ["setup-org-defaults.sh"]

Pattern 1 — Generic init container injection

Any named init container defined in config.workspace.initContainers (other than init-persistent-home) is merged into the workspace pod's init containers using Kubernetes strategic merge patch semantics (pkg/library/initcontainers/merge.go). This allows cluster administrators to inject tooling, configuration, or environment initialization into every workspace without modifying DevWorkspace definitions.

Pattern 2 — Overriding init-persistent-home

When an init container named init-persistent-home is present in config.workspace.initContainers, it overrides the default home-persistence init container behavior. This pattern enables custom home initialization scripts for ephemeral storage workspaces, or for replacing the built-in stow-based initialization entirely.

The override is applied after the default init component is generated (if not disabled via persistUserHome.disableInitContainer). The DWOC-supplied container fields are merged on top of the generated container using strategic merge patch.

Ephemeral workspaces: NeedsPersistentHomeDirectory now returns true for ephemeral-storage workspaces when init-persistent-home is present in config.workspace.initContainers, enabling consistent behavior between ephemeral and non-ephemeral workspaces when a custom init is configured.

Key Behaviors

Command validation (/bin/sh -c requirement)

EnsureHomeInitContainerFields in pkg/library/home/persistentHome.go enforces that the init-persistent-home container uses ["/bin/sh", "-c"] as its command if no command is already set. If the container already specifies a command, that value is preserved. This means an override container must either omit command (to accept the default) or provide a valid shell-compatible command.

Image inheritance

When an init-persistent-home override is provided in config.workspace.initContainers without specifying an image, the image is inherited from the first non-imported container component in the workspace. This mirrors the behavior of the auto-generated init container (inferInitContainer) so that the override does not need to repeat the workspace image.

Merge semantics

Init container merging (pkg/library/initcontainers/merge.go) uses strategicpatch.StrategicMergePatch over a corev1.PodSpec structure with name as the merge key. Containers matching by name in the DWOC are merged field-by-field into the base set; new containers are appended. Order is preserved: base containers come first in their original order, then new containers from the DWOC in their original order.

Backward Compatibility

Backward compatibility is preserved. All changes are additive:

  • If config.workspace.initContainers is empty or absent, behavior is identical to previous releases.
  • The init-persistent-home init container injection behavior is unchanged when no override is present in the DWOC.
  • The persistUserHome.disableInitContainer field continues to work as before.
  • Existing workspaces with non-ephemeral storage are unaffected.

Changed Files

File Change
apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go Added InitContainers []corev1.Container field to WorkspaceConfig; updated godoc
pkg/library/home/persistentHome.go Added EnsureHomeInitContainerFields, hasInitPersistentHomeInConfig; updated NeedsPersistentHomeDirectory for ephemeral storage
pkg/library/initcontainers/merge.go New package: strategic merge patch for init containers
controllers/workspace/devworkspace_controller.go Injects and merges DWOC init containers into workspace pod additions
pkg/library/home/custom_init_test.go Unit tests for AddPersistentHomeVolume, InferWorkspaceImage, custom init behavior
test/e2e/pkg/tests/custom_init_container_tests.go End-to-end tests for DWOC init container injection

Test Plan

  • Unit tests in pkg/library/home cover:
    • Default init container is added when persistUserHome.enabled=true
    • Default init container is skipped when disableInitContainer=true
    • EnsureHomeInitContainerFields sets ["/bin/sh", "-c"] command when none is provided
    • EnsureHomeInitContainerFields preserves existing command
    • Image inheritance from workspace container when init container image is empty
    • hasInitPersistentHomeInConfig returns true/false correctly
  • Unit tests in pkg/library/initcontainers cover:
    • Strategic merge: existing containers are updated, new containers are appended
    • Order is preserved after merge
    • Empty patch returns base unchanged
  • E2E tests in test/e2e/pkg/tests/custom_init_container_tests.go cover:
    • DWOC init containers are injected into workspace pods
    • init-persistent-home override replaces default behavior
    • DWOC configuration is restored after tests (BeforeAll/AfterAll guards)
  • Run go build ./... — no compilation errors
  • Run go test ./pkg/library/... ./pkg/provision/... ./webhook/... — all tests pass

akurinnoy and others added 13 commits July 1, 2026 19:57
Document injection order, init-persistent-home override behavior
(must use command: [/bin/sh, -c]), automatic image and volume mount
inheritance for init-persistent-home, and explicit requirements
for all other custom init containers.
Add isValidInitPersistentHomeCommand helper and command validation to
EnsureHomeInitContainerFields. When Command is non-empty and not exactly
[/bin/sh, -c], returns error: "Invalid init-persistent-home container:
command must be exactly [/bin/sh, -c]". Empty Command still defaults to
[/bin/sh, -c]. VolumeMounts always overwritten with persistent-home mount.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…-persistent-home)

Add three new test cases to TestMergeInitContainers covering DWOC init
container injection scenarios beyond init-persistent-home overrides:
- Single custom DWOC container (custom-setup) is appended after the
  built-in init-persistent-home in the merged list
- Multiple custom DWOC containers are appended in the order they appear
  in the DWOC spec
- A DWOC container whose name matches an existing devfile-level init
  container is merged (fields overridden) rather than duplicated

No production code changes — tests only. All eight test cases pass.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ContainerFields

Extend EnsureHomeInitContainerFields to accept a workspace parameter and
infer the init-persistent-home container image from the workspace's primary
container when the DWOC spec does not specify an image. Non-empty DWOC images
are preserved. Update the call site in devworkspace_controller.go accordingly.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…o prevent silent override

Previously, EnsureHomeInitContainerFields validated c.Command but never
reset c.Args, creating a silent-success path where a DWOC container with
Command=[/bin/sh, -c] and custom Args could replace the initScript payload
without any error or log. Now c.Args is always overwritten with initScript
regardless of operator config, ensuring the init behavior cannot be
silently replaced via strategic merge.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ommand validation

Tests cover: no command (defaults to [/bin/sh, -c]), explicit valid command,
invalid commands (/bin/bash, missing -c, extra args), and VolumeMounts overwrite.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Add TestEnsureHomeInitContainerFieldsImageInheritance covering three scenarios:
- init-persistent-home container with empty image gets image inferred from workspace primary container (InferWorkspaceImage)
- init-persistent-home container with image already set preserves it unchanged
- non-init-persistent-home container with image set also preserves it (function does not overwrite non-empty images)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant