Skip to content

feat: mount ConfigMaps/Secrets/PVCs only to a specific DevWorkspace#1619

Open
tolusha wants to merge 3 commits intomainfrom
23829
Open

feat: mount ConfigMaps/Secrets/PVCs only to a specific DevWorkspace#1619
tolusha wants to merge 3 commits intomainfrom
23829

Conversation

@tolusha
Copy link
Copy Markdown
Contributor

@tolusha tolusha commented May 6, 2026

What does this PR do?

  • Introduces two new annotations for include/exclude filtering:
    • controller.devfile.io/devworkspace-include — mount the resource only to workspaces whose names match
    • controller.devfile.io/devworkspace-exclude — mount the resource to all workspaces except those whose names match
    • Updates the automount logic in pkg/provision/automount/ (ConfigMaps, Secrets, PVCs, and gitconfig) to check these annotations before mounting resources.
    • Adds a watch/event handler so that changes to annotated ConfigMaps/Secrets trigger reconciliation of the targeted workspaces.
    • Includes tests covering include, exclude, both-at-once, and non-matching scenarios.
    • Documents the new annotations in docs/additional-configuration.adoc.

What issues does this PR fix or reference?

eclipse-che/che#23829

Is it tested? How?

  1. Start a workspace
  2. Create automount resources, ensure workspace is not restarted
oc apply -f - <<EOF             
apiVersion: v1  
data:
  CM: data
kind: ConfigMap
metadata:
  annotations:
    controller.devfile.io/mount-as: env
    controller.devfile.io/mount-to-devworkspace-include: "test"
  labels:
    controller.devfile.io/mount-to-devworkspace: "true"
    controller.devfile.io/watch-configmap: "true"
  name: test
---
apiVersion: v1  
stringData:
  SECRET: data
kind: Secret
metadata:
  annotations:
    controller.devfile.io/mount-as: file
    controller.devfile.io/mount-path: "/tmp/secret"
    controller.devfile.io/mount-to-devworkspace-include: "test"
  labels:
    controller.devfile.io/mount-to-devworkspace: "true"
    controller.devfile.io/watch-secret: "true"
  name: test
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc
  labels:
    controller.devfile.io/mount-to-devworkspace: 'true'
  annotations:
    controller.devfile.io/mount-path: /tmp/pvc
    controller.devfile.io/mount-to-devworkspace-include: "test"
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi
  volumeMode: Filesystem
EOF
  1. Update annotations in the resources one by one to include the running workspace, for instance:
 controller.devfile.io/mount-to-devworkspace-include: "empty-*"

Ensure, that workspace is restarted every time.

PR Checklist

  • E2E tests pass (when PR is ready, comment /test v8-devworkspace-operator-e2e, v8-che-happy-path to trigger)
    • v8-devworkspace-operator-e2e: DevWorkspace e2e test
    • v8-che-happy-path: Happy path for verification integration with Che

Summary by CodeRabbit

  • New Features

    • Added include/exclude annotations to control which workspaces receive automounted resources by name patterns.
    • Workspace-scoped automounting: Git configuration, credentials, and persistent volumes now respect per-workspace targeting and mount rules.
  • Documentation

    • Expanded DevWorkspace configuration guidance with examples for annotations, mount include/exclude, base gitconfig, SSH key mounting, and sparse checkout.

@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 6, 2026

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 6, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: tolusha
Once this PR has been reviewed and has the lgtm label, please assign dkwon17 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

This PR threads workspace identity into automount provisioning, adds include/exclude annotations for per-workspace targeting, updates automount APIs and helpers to use workspace-scoped discovery, and filters/queues reconciles so only matching started DevWorkspaces receive automounted ConfigMaps, Secrets, and PVCs.

Changes

Workspace-Scoped Automount Targeting

Layer / File(s) Summary
Constants & Annotations
pkg/constants/metadata.go
Added DevWorkspaceMountIncludeAnnotation and DevWorkspaceMountExcludeAnnotation constants for per-workspace automount control.
Core API Signature Updates
pkg/provision/automount/common.go
ProvisionAutoMountResourcesInto and getAutomountResources signatures expanded to accept workspaceNamespace and workspaceName; callers updated accordingly.
Workspace Filtering Logic
pkg/provision/automount/common.go
Added exported MatchesWorkspaceTarget(obj k8sclient.Object, workspaceName string) bool and internal matchesAnyPattern; renamed/refactored isAllowedToMountcanMountWithoutRestart.
Gitconfig Provisioning
pkg/provision/automount/gitconfig.go
ProvisionGitConfiguration and getGitResources now accept workspace-scoped params; secrets/configmaps filtered by MatchesWorkspaceTarget; restart-aware mount helpers added.
ConfigMap & Secret Filtering
pkg/provision/automount/configmap.go, pkg/provision/automount/secret.go
getDevWorkspaceConfigmaps / getDevWorkspaceSecrets accept workspaceNamespace and workspaceName; skip non-matching items with logs; use canMountWithoutRestart.
PVC Automount Filtering
pkg/provision/automount/pvcs.go
getAutoMountPVCs updated to accept workspace context; PVCs filtered via MatchesWorkspaceTarget and skip mounts needing restart.
Controller Call Sites & Event Handling
controllers/workspace/devworkspace_controller.go, controllers/workspace/eventhandlers.go
Call site updated to pass workspace name to ProvisionAutoMountResourcesInto; runningWorkspacesHandler refactored to list started workspaces and only enqueue those matching automount criteria (imports automount).
Tests
pkg/provision/automount/*_test.go
Updated tests to new signatures; added comprehensive TestMatchesWorkspaceTarget and many gitconfig tests validating include/exclude behavior; testdata YAML files added for include/exclude scenarios; persistent-home test updated.
Documentation
docs/additional-configuration.adoc
Documented mount-to-devworkspace-include / -exclude annotations, base gitconfig behavior, and updated Git credential mounting guidance.

Sequence Diagram

sequenceDiagram
    actor Event as Resource/Event
    participant Handler as runningWorkspacesHandler
    participant Matcher as automount.MatchesWorkspaceTarget
    participant Reconciler as DevWorkspaceReconciler
    participant Provision as automount.ProvisionAutoMountResourcesInto
    participant Finder as Resource Finder<br/>(ConfigMap/Secret/PVC)

    Event->>Handler: trigger
    Handler->>Handler: list started DevWorkspaces
    loop per workspace
        Handler->>Matcher: matches workspace?
        alt matches
            Matcher-->>Handler: yes
            Handler->>Reconciler: enqueue reconcile
        else no
            Matcher-->>Handler: no (skip)
        end
    end

    Reconciler->>Provision: call with workspaceName
    Provision->>Finder: list resources in workspaceNamespace
    Finder->>Matcher: evaluate include/exclude vs workspaceName
    alt resource matches
        Matcher-->>Finder: include resource
        Finder-->>Provision: return resource for mount
    else does not match
        Matcher-->>Finder: skip resource
    end
    Provision-->>Reconciler: PodAdditions with filtered mounts
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

ok-to-test, lgtm

Suggested reviewers

  • ibuziuk
  • dkwon17
  • akurinnoy

Poem

🐰 I hopped through code with eager paws,

Patterns matched with gentle laws,
Workspaces called by name at last,
Automounts come — selective, fast! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main feature: enabling targeted mounting of ConfigMaps/Secrets/PVCs to specific DevWorkspaces through include/exclude filtering.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 23829

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Signed-off-by: Anatolii Bazko <[email protected]>
@tolusha tolusha marked this pull request as ready for review May 6, 2026 10:07
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
pkg/constants/metadata.go (1)

52-72: ⚡ Quick win

Document precedence when both include and exclude annotations are present.

The testdata testBothIncludeAndExcludeAnnotations.yaml shows that when both annotations match the workspace, the resource is not mounted (exclude wins). This precedence behavior is not captured in either docstring and is non-obvious to consumers — please call it out explicitly on at least one of the two annotation comments. Also, the bullet suffix match *name, has a stray trailing comma in both blocks (lines 58 and 69).

📝 Proposed doc tweaks
 	// DevWorkspaceMountIncludeAnnotation is an annotation to configure which DevWorkspaces an automount
 	// resource should be mounted to. The value is a comma-separated list of patterns matched against
 	// the DevWorkspace name. The resource is only mounted to workspaces whose name matches at least one pattern.
 	// Supported patterns:
 	// - exact match `name`
 	// - prefix match `name*`
-	// - suffix match `*name`,
+	// - suffix match `*name`
 	// - contains match `*name*`
 	// - matches all workspaces `*`
+	// If both DevWorkspaceMountIncludeAnnotation and DevWorkspaceMountExcludeAnnotation are set and the workspace
+	// name matches a pattern in both, the exclude annotation takes precedence and the resource is NOT mounted.
 	DevWorkspaceMountIncludeAnnotation = "controller.devfile.io/mount-to-devworkspace-include"

 	// DevWorkspaceMountExcludeAnnotation is an annotation to configure which DevWorkspaces an automount
 	// resource should NOT be mounted to. The value is a comma-separated list of patterns matched against
 	// the DevWorkspace name. The resource is not mounted to workspaces whose name matches any pattern.
 	// Supported patterns:
 	// - exact match `name`
 	// - prefix match `name*`
-	// - suffix match `*name`,
+	// - suffix match `*name`
 	// - contains match `*name*`
 	// - matches all workspaces `*`
 	DevWorkspaceMountExcludeAnnotation = "controller.devfile.io/mount-to-devworkspace-exclude"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/constants/metadata.go` around lines 52 - 72, Update the comments for
DevWorkspaceMountIncludeAnnotation and DevWorkspaceMountExcludeAnnotation to
explicitly document precedence when both annotations match (state that exclude
takes precedence and the resource will not be mounted if both match), and remove
the stray trailing comma in the "suffix match `*name`" bullet in both docblocks;
reference the symbols DevWorkspaceMountIncludeAnnotation and
DevWorkspaceMountExcludeAnnotation when making these edits so reviewers can find
the exact comment blocks to update.
pkg/provision/automount/secret.go (1)

48-52: ⚡ Quick win

Silent skips at V(1) may mask user-facing configuration issues.

Both skip paths (annotation-based filter at lines 48-52 and restart-required at lines 68-71) only log at verbosity 1, so a user who annotated a Secret expecting it to mount and gets nothing will have no visible feedback unless they raise the log level. Two suggestions:

  • Surface at least the "requires restart" skip (line 69) as a warning/event on the DevWorkspace via the existing warning aggregation (dwerrors.WarningError) so operators can act on it.
  • Log message casing is inconsistent across the two sites — "skip Secret mount, ..." vs "Skipping Secret mount: ...". Pick one form for grep-ability.

Also applies to: 68-71

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/provision/automount/secret.go` around lines 48 - 52, The Secret mount
code currently silently skips in two places (the MatchesWorkspaceTarget filter
and the restart-required check) with V(1) logs; change both log messages to the
consistent wording "Skipping Secret mount: ..." and, for the restart-required
skip, also record a DevWorkspace-level warning via the existing warning
aggregation (use the dwerrors.WarningError path/utility you have in repo)
including namespace, name and workspaceName so operators see the issue; locate
the checks around MatchesWorkspaceTarget(&secret, workspaceName) and the
restart-required check in secret.go and update the log text and add a
dwerrors.WarningError entry when the restart-required branch is taken.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/additional-configuration.adoc`:
- Around line 255-266: Replace the incorrect example label
"controller.devfile.io/automount: true" with the same automount label/annotation
set used elsewhere in this document (the one used for ConfigMaps/Secrets) so the
example matches the actual code path; update the paragraph that references
"controller.devfile.io/automount: true" to use the canonical automount
label/annotations and ensure the text still explains that such a resource
mounted as subpath resolving to /etc/gitconfig will be used as the base git
configuration (keep the references to
controller.devfile.io/mount-to-devworkspace-include and
controller.devfile.io/mount-to-devworkspace-exclude intact).

In `@pkg/provision/automount/common.go`:
- Around line 480-512: The current matchesAnyPattern incorrectly handles
patterns with '*' in middle; replace the manual wildcard branches by iterating
the comma-separated, trimmed patterns and for each non-empty pattern call
path.Match(pattern, workspaceName), treating a true match as success; if
path.Match returns an error for a pattern, skip that pattern (or continue) and
do not panic, finally return false if no pattern matched — update the body of
matchesAnyPattern to implement this behavior (path is already imported).

---

Nitpick comments:
In `@pkg/constants/metadata.go`:
- Around line 52-72: Update the comments for DevWorkspaceMountIncludeAnnotation
and DevWorkspaceMountExcludeAnnotation to explicitly document precedence when
both annotations match (state that exclude takes precedence and the resource
will not be mounted if both match), and remove the stray trailing comma in the
"suffix match `*name`" bullet in both docblocks; reference the symbols
DevWorkspaceMountIncludeAnnotation and DevWorkspaceMountExcludeAnnotation when
making these edits so reviewers can find the exact comment blocks to update.

In `@pkg/provision/automount/secret.go`:
- Around line 48-52: The Secret mount code currently silently skips in two
places (the MatchesWorkspaceTarget filter and the restart-required check) with
V(1) logs; change both log messages to the consistent wording "Skipping Secret
mount: ..." and, for the restart-required skip, also record a DevWorkspace-level
warning via the existing warning aggregation (use the dwerrors.WarningError
path/utility you have in repo) including namespace, name and workspaceName so
operators see the issue; locate the checks around
MatchesWorkspaceTarget(&secret, workspaceName) and the restart-required check in
secret.go and update the log text and add a dwerrors.WarningError entry when the
restart-required branch is taken.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 546b9dcc-a7c1-45ff-9690-bca5798913b3

📥 Commits

Reviewing files that changed from the base of the PR and between fa371eb and e73f0b0.

📒 Files selected for processing (17)
  • controllers/workspace/devworkspace_controller.go
  • controllers/workspace/eventhandlers.go
  • docs/additional-configuration.adoc
  • pkg/constants/metadata.go
  • pkg/provision/automount/common.go
  • pkg/provision/automount/common_persistenthome_test.go
  • pkg/provision/automount/common_test.go
  • pkg/provision/automount/configmap.go
  • pkg/provision/automount/gitconfig.go
  • pkg/provision/automount/gitconfig_test.go
  • pkg/provision/automount/pvcs.go
  • pkg/provision/automount/secret.go
  • pkg/provision/automount/testdata/testBothIncludeAndExcludeAnnotations.yaml
  • pkg/provision/automount/testdata/testExcludeAnnotationDoesNotMatch.yaml
  • pkg/provision/automount/testdata/testExcludeAnnotationMatches.yaml
  • pkg/provision/automount/testdata/testIncludeAnnotationDoesNotMatch.yaml
  • pkg/provision/automount/testdata/testIncludeAnnotationMatches.yaml

Comment thread docs/additional-configuration.adoc
Comment thread pkg/provision/automount/common.go
@tolusha
Copy link
Copy Markdown
Contributor Author

tolusha commented May 6, 2026

/retest

Comment thread pkg/provision/automount/gitconfig.go
Comment thread pkg/provision/automount/common.go
Comment thread pkg/provision/automount/configmap.go
Comment thread controllers/workspace/eventhandlers.go
Comment thread pkg/provision/automount/common.go
Comment thread pkg/constants/metadata.go
Comment thread docs/additional-configuration.adoc
Comment thread pkg/provision/automount/common_test.go
Signed-off-by: Anatolii Bazko <[email protected]>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
pkg/provision/automount/common.go (1)

492-505: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wildcard matching is still incomplete for * in middle positions.

Line 492 through Line 505 only handles * at the start/end, so patterns like prefix*suffix or a*b*c are misinterpreted, which can cause incorrect workspace targeting for automounts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/provision/automount/common.go` around lines 492 - 505, The current switch
over startsWithWildcard/endsWithWildcard only handles leading/trailing '*' and
misses patterns like "prefix*suffix" or multiple '*' (variables pattern and
workspaceName in the shown block); replace this special-case logic with a
generic wildcard matcher: split pattern by '*' into parts, ensure the first part
matches the workspaceName prefix when pattern doesn't start with '*', ensure the
last part matches the workspaceName suffix when pattern doesn't end with '*',
and verify all intermediate parts occur in order within workspaceName (each
found after the previous match). Implement this matching where matched is set
(replacing the switch) so patterns such as "a*b*c" and "prefix*suffix" are
handled correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@pkg/provision/automount/common.go`:
- Around line 492-505: The current switch over
startsWithWildcard/endsWithWildcard only handles leading/trailing '*' and misses
patterns like "prefix*suffix" or multiple '*' (variables pattern and
workspaceName in the shown block); replace this special-case logic with a
generic wildcard matcher: split pattern by '*' into parts, ensure the first part
matches the workspaceName prefix when pattern doesn't start with '*', ensure the
last part matches the workspaceName suffix when pattern doesn't end with '*',
and verify all intermediate parts occur in order within workspaceName (each
found after the previous match). Implement this matching where matched is set
(replacing the switch) so patterns such as "a*b*c" and "prefix*suffix" are
handled correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 105a8981-6b5e-4f4a-9818-e98e1138545e

📥 Commits

Reviewing files that changed from the base of the PR and between e73f0b0 and 76a4732.

📒 Files selected for processing (9)
  • controllers/workspace/eventhandlers.go
  • docs/additional-configuration.adoc
  • pkg/constants/metadata.go
  • pkg/provision/automount/common.go
  • pkg/provision/automount/common_test.go
  • pkg/provision/automount/configmap.go
  • pkg/provision/automount/gitconfig.go
  • pkg/provision/automount/pvcs.go
  • pkg/provision/automount/secret.go

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.

2 participants