Skip to content

feat(kubernetes,tenant): copy patch-containerd secret into tenant namespaces - #2927

Closed
Elaugaste (elaugaste) wants to merge 1 commit into
cozystack:mainfrom
elaugaste:fix-patch-containerd-lookup
Closed

feat(kubernetes,tenant): copy patch-containerd secret into tenant namespaces#2927
Elaugaste (elaugaste) wants to merge 1 commit into
cozystack:mainfrom
elaugaste:fix-patch-containerd-lookup

Conversation

@elaugaste

@elaugaste Elaugaste (elaugaste) commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

This PR moves the patch-containerd secret copying logic from the kubernetes chart to the tenant chart. This ensures that the secret is available in each tenant namespace, allowing the kubernetes chart to consume it directly from the namespace rather than maintaining a separate copy.

Release note

feat(kubernetes,tenant): copy `patch-containerd` secret into tenant namespaces

…espaces

Add a Helm template to the tenant chart that copies the patch-containerd
secret from cozy-system into each newly created tenant namespace (when
the secret exists). Update the kubernetes chart to consume the secret
directly from Release.Namespace instead of maintaining its own copy.

Remove the now-redundant copy-patch-containerd.yaml from the kubernetes
chart — the secret is provided by the tenant chart.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Elaugaste <elaugaste@gmail.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the handling of the patch-containerd secret by centralizing its replication within the tenant chart. By moving this logic, the secret is now automatically provisioned in each tenant namespace, allowing the kubernetes chart to reference it locally without needing release-specific naming conventions.

Highlights

  • Secret Management Migration: Migrated the patch-containerd secret replication logic from the kubernetes chart to the tenant chart.
  • Namespace Scoping: Updated the kubernetes chart to consume the patch-containerd secret directly from the local namespace, improving consistency across tenant deployments.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions Bot added area/kubernetes Issues or PRs related to the tenant Kubernetes app kind/feature Categorizes issue or PR as related to a new feature labels Jun 16, 2026
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Two Helm templates are updated to standardize the patch-containerd Secret to a fixed name. The tenant template gains a tenant-root skip guard, sets the Secret name and namespace from fixed values, and rewrites its data rendering. The kubernetes cluster template updates its lookup and contentFrom reference to match the new fixed name.

Changes

patch-containerd Secret name standardization

Layer / File(s) Summary
Tenant template: fixed Secret name and tenant-root guard
packages/apps/tenant/templates/copy-patch-containerd.yaml
Wraps rendering in a guard that skips tenant-root, sets metadata.name to the literal patch-containerd and metadata.namespace to tenant.name, and replaces the printf/indent data block with a direct range over sourceSecret.data emitting key: quoted-value pairs.
Kubernetes cluster template: consume fixed Secret name
packages/apps/kubernetes/templates/cluster.yaml
Updates the Secret lookup and contentFrom.secret.name in the containerd certificate host-file patching block from <release>-patch-containerd to the fixed name patch-containerd.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

Poem

A rabbit once named things by release,
But secrets with long names brought no peace.
Now patch-containerd stands fixed and true,
Skipping root tenants as we pass through.
🐇 Simple names, simpler hops for you!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: relocating the patch-containerd secret copying mechanism from the kubernetes chart to the tenant chart, enabling direct consumption from tenant namespaces.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request updates the kubernetes and tenant packages to use a static secret name 'patch-containerd' instead of prefixing it with the release name, and adjusts the target namespace for the copied secret. It also wraps the secret copying logic in copy-patch-containerd.yaml with a conditional check to exclude the 'tenant-root' tenant. Feedback includes a request to add the required release-note block to the PR description per repository guidelines, and a suggestion to use the more robust 'toYaml' and 'nindent' functions for serializing secret data instead of a manual loop.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@@ -1,13 +1,16 @@
{{- if ne (include "tenant.name" .) "tenant-root" }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The PR body is missing the required ```release-note block as specified in the repository guidelines. Please update the PR description to include a valid release-note block to satisfy the CI/CD and release tracking requirements.

References
  1. PR body must contain a release note block: release-note ... (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

Comment on lines 11 to +14
data:
{{- range $key, $value := $sourceSecret.data }}
{{ printf "%s: %s" $key ($value | quote) | indent 2 }}
{{ $key }}: {{ $value | quote }}
{{- end }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

low

Using a manual range loop to serialize map data can be fragile and prone to whitespace/indentation issues. It is more idiomatic and robust to use the toYaml template function combined with nindent.

data:
  {{- toYaml $sourceSecret.data | nindent 2 }}
References
  1. Helm template correctness: missing quote, incorrect indentation, wrong scope in with/range. (link)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@packages/apps/tenant/templates/copy-patch-containerd.yaml`:
- Around line 12-14: The `range` loop iterating over the `$sourceSecret.data`
map produces non-deterministic output since map iteration order is random in
Go/Helm, causing the rendered data key order to vary between reconciles and
trigger unnecessary Helm upgrades. Fix this by extracting and sorting the map
keys deterministically before rendering, then iterating over the sorted keys in
a stable order to access and render the corresponding values for each key.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 986782b8-2d0b-4cc7-aab2-0ecdc52af90e

📥 Commits

Reviewing files that changed from the base of the PR and between 4996b9d and 8861faa.

📒 Files selected for processing (2)
  • packages/apps/kubernetes/templates/cluster.yaml
  • packages/apps/tenant/templates/copy-patch-containerd.yaml

Comment on lines 12 to +14
{{- range $key, $value := $sourceSecret.data }}
{{ printf "%s: %s" $key ($value | quote) | indent 2 }}
{{ $key }}: {{ $value | quote }}
{{- end }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make Secret data rendering deterministic to avoid reconcile churn.

range over a map is non-deterministic, so the rendered data: key order can flap between reconciles. That can trigger noisy/no-op Helm upgrades in Flux.

Suggested fix
 data:
-{{- range $key, $value := $sourceSecret.data }}
-  {{ $key }}: {{ $value | quote }}
+{{- range $key := keys $sourceSecret.data | sortAlpha }}
+  {{ $key }}: {{ index $sourceSecret.data $key | quote }}
 {{- end }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{{- range $key, $value := $sourceSecret.data }}
{{ printf "%s: %s" $key ($value | quote) | indent 2 }}
{{ $key }}: {{ $value | quote }}
{{- end }}
data:
{{- range $key := keys $sourceSecret.data | sortAlpha }}
{{ $key }}: {{ index $sourceSecret.data $key | quote }}
{{- end }}
🤖 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 `@packages/apps/tenant/templates/copy-patch-containerd.yaml` around lines 12 -
14, The `range` loop iterating over the `$sourceSecret.data` map produces
non-deterministic output since map iteration order is random in Go/Helm, causing
the rendered data key order to vary between reconciles and trigger unnecessary
Helm upgrades. Fix this by extracting and sorting the map keys deterministically
before rendering, then iterating over the sorted keys in a stable order to
access and render the corresponding values for each key.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

NOT LGTM — the fix is the right direction (moving the copy to the tenant chart breaks the same-render-pass lookup chicken-and-egg from #2663), but the tenant-root guard drops patch-containerd for Kubernetes clusters created directly in the root tenant, which the old code covered.

Business context: #2663 — the kubernetes chart copied cozy-system/patch-containerd into its own namespace and looked it up in the same Helm render pass; since lookup reads live cluster state, the secret is nil on first install and the registry-mirror certs.d entries never reach the KubeadmConfigTemplate. This moves the copy to the tenant chart so the secret exists before the kubernetes app renders.

Blockers

B1: tenant-root Kubernetes clusters lose patch-containerd

File: packages/apps/tenant/templates/copy-patch-containerd.yaml:1

Issue: the new {{- if ne (include "tenant.name" .) "tenant-root" }} guard creates the secret only in child tenant namespaces. The kubernetes chart's cluster.yaml now looks up a fixed patch-containerd in its release namespace (packages/apps/kubernetes/templates/cluster.yaml:444). The previous template lived in the kubernetes chart and copied into $.Release.Namespace, so it worked for any namespace — including tenant-root.

Evidence: patch-containerd is created by exactly three templates — core/platform/.../containerd-registry-secret.yaml (source, in cozy-system), the removed kubernetes-chart copy, and this new tenant-chart copy. With the guard, nothing creates it in tenant-root. The kubernetes chart is rendered in tenant-root by its own test suite (packages/apps/kubernetes/tests/admin_kubeconfig_wait_test.yaml:5), so a cluster in the root tenant is a real placement. Result: a Kubernetes cluster in tenant-root with registries.mirrors configured no longer gets the certs.d patch — exactly the air-gap case the secret exists for.

Impact: regresses registry-mirror delivery for root-tenant Kubernetes clusters.

Fix: either copy patch-containerd into tenant-root too (drop/narrow the guard — the source is in cozy-system and the destination namespace exists), or, if root-tenant clusters are intentionally unsupported, state that and confirm nothing relies on it.

Non-blocking follow-ups

  1. The secret is now copied into every non-root tenant namespace, even tenants that never create a Kubernetes cluster. Minor, but it widens where the registry-mirror config lives — worth a line in the PR description.
  2. Both the tenant-chart copy and the kubernetes consumer use lookup, whose result is invisible to Flux's digest-based reconcile (a later change to cozy-system/patch-containerd won't re-render either). Pre-existing, not introduced here, but the design still leans on the source secret being static.
  3. helm-unittest can't exercise this path (lookup returns nil under helm template), so the only real coverage is E2E — make sure a tenant cluster with mirrors is exercised there.

@@ -1,13 +1,16 @@
{{- if ne (include "tenant.name" .) "tenant-root" }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

B1 (blocker): this guard skips tenant-root, so a Kubernetes cluster in the root tenant gets no patch-containerdcluster.yaml looks it up in its own namespace and nothing else creates it there. The old kubernetes-chart copy covered any namespace. Either copy into tenant-root too, or confirm root-tenant clusters are unsupported.

@lexfrei

Copy link
Copy Markdown
Contributor

Same story as #2915: this targets code that was removed. #2931 moved tenant workers to Talos via CABPT and deleted packages/apps/kubernetes/templates/copy-patch-containerd.yaml along with the lookup that read the Secret in cluster.yaml. packages/apps/kubernetes/README.md records that the *-patch-containerd Secret has no consumer in the Talos machineconfig and was dropped.

Sharing one Secret across a tenant's clusters is still a reasonable ask, but it has to be rebuilt on the machineconfig side rather than rebased. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/kubernetes Issues or PRs related to the tenant Kubernetes app kind/feature Categorizes issue or PR as related to a new feature size/S This PR changes 10-29 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants