Skip to content

feat(platform, kubernetes): platform-wide defaults for tenant Talos worker settings - #4897

Open
myasnikovdaniil wants to merge 3 commits into
mainfrom
feat/tenant-talos-platform-defaults
Open

myasnikovdaniil wants to merge 3 commits into
mainfrom
feat/tenant-talos-platform-defaults

Conversation

@myasnikovdaniil

@myasnikovdaniil myasnikovdaniil commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does

Adds platform-wide defaults for tenant talos worker pools, closes #3950. It also removes the dead registries platform value and the patch-containerd Secret rendered from it, closes #4006.

Worker image defaults

kubernetesWorkerImage now sets what a new KubernetesNodes starts with, not only the golden image catalog. On create cozystack-api writes into the spec every field it leaves out: osImage.builtin: {} (only when the catalog package is enabled, not for proxmox), talos.imageFactoryURL from imageFactoryURL (not for proxmox) and talos.installerRepository from the new installerRepository. A field the spec already carries is kept, even an empty one, so osImage.factory: {} opts a pool out.

Installer prefix is not derived from imageFactoryURL, because the factory url only says where the OS image is fetched from, and a file server or a caching mirror has no installer.

Defaults go in at create only. Image source and installer are hashed into names the MachineDeployment points at, so a default applied at render or on read would roll every existing pool when an operator first sets it. Existing pools are not touched, moving one onto a golden image is a patch described in the header of the catalog values (it rolls that pool).

Registry mirrors

kubernetesRegistries.mirrors and kubernetesRegistries.config (only tls.ca and tls.insecureSkipVerify) go to _cluster.kubernetes-registries and into every worker pool as RegistryMirrorConfig and RegistryTLSConfig documents. The chart doesn't render deprecated machine.registries anymore. Pool's own talos.registryMirrors replaces the platform mirrors as a whole, config always applies. The documents need talos 1.12, render of an older pool fails with a message when mirrors or config are set.

Credentials and client keys are refused at platform render because the machine config is readable in the tenant namespace. Mirrors with a wrong shape are refused there too, otherwise they would fail every pool that has no mirrors of its own.

What changes on upgrade

  • a pool with its own talos.registryMirrors rolls once, machine config text and TalosConfigTemplate name change
  • setting or changing platform mirrors rolls pools without own mirrors, config rolls every pool
  • on a cluster that already runs the catalog package new pools start on a golden image without any new value set, and a pool whose talos version, schematic or storageClass is not in the catalog fails to render until it sets osImage.factory: {} or the catalog gets the entry
  • kubernetesWorkerImage.imageFactoryURL has to be a plain http(s) URL with no user name or password, platform render refuses anything else, also when the catalog package is off (before the key was dormant then). It is copied to every tenant namespace and into the spec of every new pool
  • new keys in the cozystack-values Secret make every release reconcile once (about 10 minutes on a small test stand, no worker rolls from it)

Dashboard form is not covered. It may submit the full talos block, then nothing is stamped, I didn't look into it here.

How it was checked

Chart tests for platform and kubernetes-nodes, go tests for the stamping, make unit-tests passes. On a test stand with an earlier revision of this branch a new pool without osImage was stored with builtin: {} and the factory and installer values, cloned the golden and its worker joined, a pool with osImage.factory: {} kept it, a pod pulled an image of a nonexistent registry host through the mirror with skipFallback, and the TalosConfigTemplate had no machine.registries. RegistryTLSConfig is checked only with the talos 1.13 config loader, not on a real node.

Screenshots

Downstream repositories

Release note

feat(platform, kubernetes): the platform can set the worker image source, installer prefix and registry mirrors of tenant Kubernetes workers once. `kubernetesWorkerImage.imageFactoryURL`, `kubernetesWorkerImage.installerRepository` and, when the worker image catalog is enabled, a golden image are written into new `KubernetesNodes` pools at creation, existing pools are not changed. `kubernetesRegistries` (mirrors and TLS settings) applies to every worker pool and needs Talos 1.12 or newer. The `registries` platform value and the `patch-containerd` Secret are removed, they had no consumer. `kubernetesWorkerImage.imageFactoryURL` must be a plain http(s) URL without credentials. Setting `kubernetesRegistries` rolls worker pools and a pool that sets `talos.registryMirrors` rolls once on upgrade. New keys in the `cozystack-values` Secret make every release reconcile once.

Summary by CodeRabbit

  • New Features
    • New worker pools can inherit configured image defaults and registry settings from the platform, while preserving values explicitly set for the pool. Existing pools are not changed.
    • Talos registry mirrors and TLS settings are rendered into worker configuration. Pool-level mirrors replace platform mirrors; platform TLS settings apply independently.
  • Bug Fixes
    • Invalid registry settings and registry configuration on Talos versions older than 1.12 are rejected.
    • Registry credentials and client keys are not accepted in platform registry settings.
  • Documentation
    • Clarified worker image defaults, registry behavior, version requirements, and considerations for moving an existing pool to a golden image.

… workers

An operator in a closed or rate-limited environment had no
platform-wide way to send tenant worker image pulls through a mirror.
The platform registries value fed a Secret that nothing read, and
since the Talos rollover every worker pool had to repeat
talos.registryMirrors by hand.

Add kubernetesRegistries to the platform values and carry it through
_cluster, so a pool that sets no mirrors of its own gets the
platform's. Mirrors and the TLS settings of their endpoints are
rendered as the RegistryMirrorConfig and RegistryTLSConfig documents
that Talos 1.12 introduced in place of the deprecated
machine.registries section, which the chart no longer renders. The
switches on them are on only for a true value, so a quoted "false"
cannot turn on skipFallback or skip TLS verification. Drop the
retired registries value and its patch-containerd Secret.

The platform values are copied into every tenant namespace and read
by every pool, so the platform chart checks them where the operator
writes them. Credentials, client keys and keys the chart does not
read are refused, because the machine config is stored in the tenant
namespace and they would be readable there. So is a mirror the nodes
chart could not render, which would otherwise fail every pool that
has none of its own.

A pool that already sets talos.registryMirrors rolls once when it
moves to this release, because the machine config text, and with it
the TalosConfigTemplate name, changes. Pools without mirrors render
exactly as before. Setting the platform mirrors rolls the pools that
have none of their own, and setting the platform tls settings rolls
every pool.

Assisted-by: LLM
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
…rker pools

An operator in a closed environment had to set talos.imageFactoryURL
and talos.installerRepository on every KubernetesNodes by hand, and a
pool created without them went to the public factory, which is the
egress such environments block. The worker image catalog already lets
the platform name the factory the golden images come from, but
nothing made a new pool use it.

Let the kubernetesWorkerImage platform value state the image source
once. Its imageFactoryURL, its installerRepository, and whether the
catalog package is enabled travel to cozystack-api through _cluster.
The installer prefix is never derived from the factory URL, which
only says where the OS image is fetched from: a file server or a
caching mirror serves that and no installer. Both values are copied
into the spec of every new pool, so the platform refuses a factory URL
that is not a plain http(s) URL or carries a user name and password,
whether or not the catalog is enabled, and an installer prefix that is
not a registry path.

When a KubernetesNodes is created, the API fills in the fields its
spec leaves out: osImage.builtin so the pool clones a golden, the
factory URL, and the installer prefix. A proxmox pool takes only the
installer, because its render refuses osImage.

The values are written into the spec on create and read nowhere else.
The image source and the installer are hashed into names the
MachineDeployment points at, so a default applied at render time, or
on read, would re-image every existing pool the first time an operator
set it. A pool that exists is never touched, and a field the spec
already carries, even an empty one, is kept, which is how a pool opts
out.

A cluster that already runs the catalog package gets this without
setting a new value: its new pools start on a golden, and one whose
Talos version, schematic or storage class the catalog does not cover
fails to render until it opts out with osImage.factory or the catalog
gains the entry.

Assisted-by: LLM
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
…mages

The platform now writes the image source and the installer prefix into
the spec of a new worker pool, and does nothing for a pool that
already exists. An operator who wants an existing pool on a golden
image has no document that says how, and the obvious attempts go wrong
in ways that are easy to miss.

Defaults are applied when a pool is read and written back by its first
edit, so the pool already carries the public installer prefix
explicitly and keeps it unless the same patch replaces it. And a pool
that opted out of the golden, or pinned a factory version, carries
osImage.factory: a merge patch that only adds osImage.builtin leaves
both set, and the pool stops rendering with "set only one of". The
same patch has to null the factory, and so does the way back.

Put the procedure in the header of the worker image catalog, where an
operator looks for everything about goldens, with the checks that make
the pool render and the cost of the roll. Say in the pool's field docs
that these values are filled in at creation and that an older pool
keeps what it has.

Assisted-by: LLM
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
@github-actions github-actions Bot added area/kubernetes Issues or PRs related to the tenant Kubernetes app area/platform Issues or PRs related to platform infrastructure (bundle, flux, talos, installer) kind/feature Categorizes issue or PR as related to a new feature size/XXL This PR changes 1000+ lines, ignoring generated files labels Oct 13, 2026
@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: cozystack/cozystack/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3c75bdd8-d69c-43cf-a447-1328fd70a5f3
📥 Commits

Reviewing files that changed from the base of the PR and between 3a46360 and 154c4ff.

📒 Files selected for processing (19)
  • api/apps/v1alpha1/kubernetesnodes/types.go
  • packages/apps/kubernetes-nodes/README.md
  • packages/apps/kubernetes-nodes/templates/_talosconfigtemplate.tpl
  • packages/apps/kubernetes-nodes/tests/registry_mirrors_test.yaml
  • packages/apps/kubernetes-nodes/values.schema.json
  • packages/apps/kubernetes-nodes/values.yaml
  • packages/apps/kubernetes/README.md
  • packages/core/platform/templates/apps.yaml
  • packages/core/platform/templates/bundles/iaas.yaml
  • packages/core/platform/templates/containerd-registry-secret.yaml
  • packages/core/platform/tests/apps_kubernetes_registries_wiring_test.yaml
  • packages/core/platform/tests/apps_worker_image_defaults_wiring_test.yaml
  • packages/core/platform/tests/bundles_worker_image_wiring_test.yaml
  • packages/core/platform/values.yaml
  • packages/system/kubernetes-nodes-rd/cozyrds/kubernetes-nodes.yaml
  • packages/system/kubernetes-worker-image/values.yaml
  • pkg/registry/apps/application/rest.go
  • pkg/registry/apps/application/rest_create_defaults.go
  • pkg/registry/apps/application/rest_create_defaults_test.go
💤 Files with no reviewable changes (1)
  • packages/core/platform/templates/containerd-registry-secret.yaml

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

📝 Walkthrough

The platform now provides worker-image defaults and Kubernetes registry settings. KubernetesNodes creation applies eligible worker-image defaults, while the Kubernetes chart validates registry settings and renders Talos registry documents.

Changes: Kubernetes worker pool platform settings

Layer / File(s) Summary
Validate and wire platform settings
packages/core/platform/templates/apps.yaml, packages/core/platform/templates/bundles/iaas.yaml, packages/core/platform/templates/containerd-registry-secret.yaml, packages/core/platform/values.yaml, packages/core/platform/tests/*
Platform templates validate and wire registry and worker-image values. The worker-image chart no longer receives installerRepository, and the obsolete patch-containerd Secret template is removed. Tests cover the accepted inputs and validation failures.
Apply worker-image defaults at creation
pkg/registry/apps/application/rest.go, pkg/registry/apps/application/rest_create_defaults.go, pkg/registry/apps/application/rest_create_defaults_test.go, api/apps/v1alpha1/kubernetesnodes/types.go, packages/apps/kubernetes-nodes/README.md, packages/apps/kubernetes-nodes/values.schema.json, packages/apps/kubernetes-nodes/values.yaml, packages/system/kubernetes-nodes-rd/cozyrds/kubernetes-nodes.yaml, packages/system/kubernetes-worker-image/values.yaml
Creation applies configured defaults to eligible new KubernetesNodes specs before null normalization and admission validation. Tests cover defaulting and value preservation. Schema descriptions and documentation describe the defaults and the documented pool migration procedure.
Render registry settings in Talos configuration
packages/apps/kubernetes-nodes/templates/_talosconfigtemplate.tpl, packages/apps/kubernetes-nodes/tests/registry_mirrors_test.yaml, api/apps/v1alpha1/kubernetesnodes/types.go, packages/apps/kubernetes-nodes/README.md, packages/apps/kubernetes-nodes/values.schema.json, packages/apps/kubernetes/README.md
The template resolves pool and platform registry settings and emits Talos mirror and TLS documents. Tests cover precedence, rendered fields, input validation, Talos version checks, and shell escaping. Documentation describes the configuration and compatibility requirements.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant PlatformAppsTemplate as platform apps.yaml
  participant ValuesSecret as kubernetes-registries Secret
  participant TalosTemplate as _talosconfigtemplate.tpl
  participant MachineConfig as Talos machine config
  PlatformAppsTemplate->>ValuesSecret: validate and write registry settings
  ValuesSecret->>TalosTemplate: provide platform mirrors and TLS settings
  TalosTemplate->>MachineConfig: append RegistryMirrorConfig and RegistryTLSConfig documents
Loading
Merge Risk: ⚪ Minimal · up to 154c4

The change adds platform-wide worker image and registry defaults for new pools and leaves existing pools untouched. Tests cover the defaulting and rendering paths. Nothing found blocks merging, though registry TLS behavior has not been confirmed on a real Talos node.

Pre-merge checks · Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 4 files. (14 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed 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 change: platform-wide defaults for tenant Talos worker settings.
Linked Issues check Passed The PR meets the coding requirements for [#3950] and [#4006]. For [#3950], platform worker-image values are copied to the platform Secret, create-time API logic fills omitted KubernetesNodes fields,…
Out of Scope Changes check Passed The changes stay within the linked issue scope. Installer repository and catalog-based worker defaults support the platform-wide worker defaults in [#3950]. Registry TLS handling, validation, document…
Full details: Docstring Coverage

Explanation

Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 4 files. (14 skipped: 14 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@IvanHunters IvanHunters left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Verdict

NOT LGTM

A sub-1.12 worker pool that already sets talos.registryMirrors renders today but fails outright after this change, which blocks the pool's whole HelmRelease on a default upgrade; a few smaller issues ride along.

Findings

  • [MAJOR] packages/apps/kubernetes-nodes/templates/_talosconfigtemplate.tpl:141, Talos-1.12 render gate breaks existing sub-1.12 pools and over-fires on empty platform config
  • [MINOR] packages/core/platform/templates/apps.yaml:55, mirror-endpoint guard lets a query-string credential into every tenant's Secret
  • [MINOR] pkg/registry/apps/application/rest_create_defaults.go:105, transient read of cozystack-values silently stores a pool on a different image source
  • [NIT] packages/core/platform/templates/apps.yaml:57, dead urlParse result; opaque panic on a URL that passes the regex but not net/url

Caveats

  • Catalog stamping writes osImage.builtin: {} into any create that omits osImage, including pools whose talos.version / schematicID / storageClass the catalog does not carry: the create succeeds and the HelmRelease then fails to render. Documented in the PR body, so noted not blocked; consider skipping the stamp when the spec overrides those fields.
  • Pools built outside cozystack-api (packages/extra/computeplane, migration 56) never receive the stamped defaults yet still pick up platform mirrors via _cluster; undocumented mismatch.
  • No e2e names installerRepository / osImage / kubernetesRegistries (new-values-field-no-e2e); the RegistryMirrorConfig / RegistryTLSConfig documents are only checked offline, never on a booted node.

Recommended follow-ups

  • cozystack-pr-test on a dev stand: replay the opt-in roll paths and a sub-1.12 proxmox pool to confirm a worker boots pulling through a mirror and that the version gate behaves on the proxmox substrate.

{{- $registryConfig := $clusterRegistries.config | default dict }}
{{- $registryDocuments := "" }}
{{- if or $registryMirrors $registryConfig }}
{{- if not (semverCompare ">=1.12.0-0" $talosVersion) }}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[MAJOR] Talos-1.12 render gate breaks existing sub-1.12 pools and over-fires on empty platform config

The gate {{- if or $registryMirrors $registryConfig }} then {{- if not (semverCompare ">=1.12.0-0" $talosVersion) }} fail turns a working upgrade into a failed render.

Proven with helm unittest on this chart (talos.version v1.11.5):

# merge-base 3a46360: pool with its own talos.registryMirrors RENDERS (emits machine.registries.mirrors)
helm unittest -f tests/<probe>.yaml packages/apps/kubernetes-nodes   # PASS, matchRegex 'mirrors:'
# head 154c4ff: the same pool FAILS
#   nodeGroup ... registry mirrors ... Talos has only since 1.12 ... resolves to Talos v1.11.5
  1. Upgrade regression. A pool pinned below Talos 1.12 that already set talos.registryMirrors worked (it rendered machine.registries.mirrors, valid on 1.11). After this change its whole HelmRelease fails to render, so the pool stops reconciling at all (no scale, no version bump). The PR body's "a pool with its own talos.registryMirrors rolls once" is false for such a pool: it fails rather than rolls. Talos pins below 1.12 are the operator's call and pass unchecked (README), and air-gapped setups that use mirrors are exactly where an older pinned Talos is plausible.
  2. Over-broad gate. The fail fires on the mere presence of $registryMirrors/$registryConfig, before any document is built. A platform kubernetesRegistries.config entry with an empty tls produces zero RegistryTLSConfig documents (the if gt (len $doc) 3 guard drops it) yet still fails every sub-1.12 pool in every tenant, including pools that use no mirror. So enabling platform registry TLS silently breaks unrelated sub-1.12 pools cluster-wide, contradicting the values.yaml note that "nothing is rendered while both are empty, so a pool without mirrors keeps the machine config".
  3. On substrate proxmox $talosVersion is talos.version, the in-guest installer target only; the booted OS is the VM template's Talos. A sub-1.12 template with talos.version at the 1.13.6 default passes the gate, and the documents then reach a node that rejects them (needs a cluster to confirm the boot failure).

Fix direction: fail only when a document is actually produced for that pool, or keep emitting machine.registries for Talos below 1.12.

{{- fail (printf "kubernetesRegistries.mirrors[%q].endpoints must hold URL strings, got %v" $host .) -}}
{{- end -}}
{{- if not (regexMatch "(?i)^https?://[^/@[:space:]]+(/[^[:space:]]*)?$" .) -}}
{{- fail (printf "kubernetesRegistries.mirrors[%q].endpoints entry %q must be an http(s) URL with no user name or password in it: the mirrors are copied into the cozystack-values Secret of every tenant." $host .) -}}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[MINOR] mirror-endpoint guard lets a query-string credential into every tenant's Secret

The guard regexMatch "(?i)^https?://[^/@[:space:]]+(/[^[:space:]]*)?$" exists to keep credentials out of the cozystack-values Secret copied into every tenant namespace, but it only blocks userinfo (user:pass@host). A credential in the query string passes: https://mirror.example.org?token=SECRET matches, because the host class [^/@[:space:]]+ accepts ?, = and the token, and so does an @ placed in the path. The sibling kubernetesWorkerImage.imageFactoryURL check (^https?://[^/]*@) has the same gap. A platform operator pointing a mirror at an authenticated pull-through endpoint with a query token leaks it to every tenant. Parse the URL and reject a non-empty query / userinfo (urlParse is already called one line below), or state in the message that endpoints must carry no secrets at all.

secret := &corev1.Secret{}
key := client.ObjectKey{Namespace: platformValuesNamespace, Name: platformValuesSecret}
if err := r.c.Get(ctx, key, secret); err != nil {
klog.Warningf("Not applying worker pool defaults: cannot read Secret %s: %v", key, err)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[MINOR] transient read of cozystack-values silently stores a pool on a different image source

loadWorkerPoolDefaults returns (_, false) on ANY error reading or unmarshalling the cozystack-values Secret, and applyCreateDefaults then stores the KubernetesNodes with no defaults, logging only a klog warning the tenant never sees. A transient GET (apiserver blip, RBAC hiccup) or a momentarily malformed Secret therefore changes what is persisted: the pool is created on the HTTP image-factory path instead of osImage.builtin, and without the platform installer prefix. Because the image source is hashed into the MachineDeployment name, correcting it later re-images the pool. Distinguish a real NotFound (skip quietly, legitimate) from any other error (fail the create, or surface a warning to the caller) so a silently diverging default does not reach storage unnoticed.

{{- if not (regexMatch "(?i)^https?://[^/@[:space:]]+(/[^[:space:]]*)?$" .) -}}
{{- fail (printf "kubernetesRegistries.mirrors[%q].endpoints entry %q must be an http(s) URL with no user name or password in it: the mirrors are copied into the cozystack-values Secret of every tenant." $host .) -}}
{{- end -}}
{{- $parsed := urlParse . -}}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[NIT] dead urlParse result; opaque panic on a URL that passes the regex but not net/url

{{- $parsed := urlParse . -}} assigns a variable that is never read. Its only effect is a side channel: urlParse panics on a URL that passes the regex above but is not parseable by net/url (for example http://[bad), surfacing as an opaque Helm panic rather than the legible fail the surrounding guards give. Either drop the dead line, or actually use it to validate and emit a readable fail on a parse error.

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.

myasnikovdaniil NOT LGTM. The Talos 1.12 gate in the nodes chart is the one blocker, and I agree with Ivan on it.

The gate fails a pool when mirrors or TLS config are merely present, before any document is built. kubernetes.talosRegistryDocuments drops a TLS entry with neither ca nor insecureSkipVerify: true, and your test "a tls entry that sets nothing renders no document" pins that. A pool below 1.12 still fails on that entry. So a platform entry that renders nothing for anyone stops every sub-1.12 pool in every tenant, including pools that use no mirror. The fix that keeps your design is to build the documents first and fail only when $registryDocuments is non-empty. For a pool with its own talos.registryMirrors, the cleaner option is to keep rendering machine.registries below 1.12, since that is what main does today and it works there.

If you keep the refusal, the upgrade notes need to say so. The "What changes on upgrade" list in the PR body and the last paragraph of 4232739 both say a pool with its own talos.registryMirrors "rolls once". Below 1.12 that pool stops rendering instead, and the PR body becomes the merge commit message.

On Ivan's other points. The query-string credential and the dead urlParse are real. I don't think the transient-read case can happen: cozystack-api starts a cluster-wide Secret informer and waits for its sync before serving (pkg/apiserver/apiserver.go, mustGetInformers). r.c.Get is answered from that cache, so there is no network read to fail. What is left is NotFound, which is the legitimate skip, and a Secret the platform chart itself rendered wrong. His computeplane caveat holds: packages/extra/computeplane/templates/cluster.yaml renders the HelmRelease directly and never goes through Create.

Non-blocking:

  • A pool can't opt out of the platform mirrors. registryMirrors defaults to {} in the CRD, and {} falls through to the platform map, so "unset" and "empty" look the same. A pool that has to pull directly while the platform sets skipFallback has no way to do it. Worth one sentence in the field doc.
  • packages/apps/kubernetes/values.yaml:365 (and the schema in kubernetes-rd) still calls the parent cluster's talos.registryMirrors a "machine.registries.mirrors passthrough". Nothing in the kubernetes templates reads it, and after this PR the description is wrong about the format too.

Checked on 154c4ff with a trial merge onto current main: the Go tests and both helm suites pass (245 and 348). Removing the absent checks, the proxmox exclusion, the applyCreateDefaults call in Create, the disabledPackages check, or swapping the pool/platform mirror precedence turns them red.

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 area/platform Issues or PRs related to platform infrastructure (bundle, flux, talos, installer) kind/feature Categorizes issue or PR as related to a new feature size/XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

3 participants