Three template comments in the control-plane chart still described the
talos-reconcile Job as living here, but the worker split moved it to
the kubernetes-nodes chart (one run per pool release):
- talos-pki.yaml pointed at "the routing note in
talos-reconcile-job.yaml", a file this chart no longer contains.
- cluster.yaml said "the talos-reconcile main-phase Job re-patches
certSANs" as if this chart still runs it; it now also states the
consequence the kubernetes-nodes side already documents -- the
ClusterIP SAN arrives only through a pool and a pool-less cluster
keeps DNS SANs only, a best-effort extra that nothing depends on.
- cilium.yaml credited the /etc/hosts seeding to the same Job without
naming its new home; it also now notes why the entry is always
present wherever Cilium runs (workers only exist through pools).
Comments only ({{/* */}} blocks, stripped at render time); no manifest
output changes, pinned by the chart's unittest suite staying green.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
The pin path composed "kubernetes-<cluster>-<group>" and read it back,
but a group key that cannot form a valid object name (a slash, a space,
an underscore...) provably never had objects applied under it -- the
old chart's apply would have been rejected by the apiserver. Worse,
kubectl rejects a name containing '/' client-side, deterministically,
so pin_keep's fail-closed read classified it as a real failure and the
migration exited 1 on every retry: a permanent fleet-wide pre-upgrade
deadlock over a pool that cannot exist.
Lean on the invariant instead of the read: pin_pool_objects statically
checks the composed name against the DNS-1123 subdomain shape and skips
with a note when it cannot name an object -- nothing to pin, no kubectl
call to misread. Keys that are label-invalid but still valid object
names (e.g. dotted) may have live objects and keep today's pin
behavior; the pin-path transient-error test now uses a dotted key so it
still exercises a genuine read.
The fake kubectl reproduces real kubectl's client-side slash rejection,
and a new bats case pins the skip: a "pool/a" key must warn, pin
nothing, apply nothing, and still reach the version stamp. Red against
the previous script, which deadlocked at the first pin read.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
Same two holes as the migration's read classification, in the unpin
hook. Capturing stderr into $pol (2>&1) contaminated the success path:
kubectl warns on successful reads, so an unannotated object read as
"pinned" and drew a spurious annotate call -- one per named object.
And the *"not found"* pattern classified a transient conversion-webhook
failure as absence, letting the Job report success while the
keep-annotated objects leaked past the uninstall.
--ignore-not-found makes the whole classification unnecessary here:
absence folds into the same empty-output no-op branch as "present but
unannotated", which is exactly the semantics unpin() wants, and any
non-zero exit is a real failure that set -e turns into a failed Job.
The case/esac disappears; stderr stays on the Job log where it is
visible instead of parsed. This also avoids tempfile juggling under the
container's readOnlyRootFilesystem.
The bats suite gains a previously missing failure-path case and
regression tests for both holes, red against the previous commit: a
failed KMT listing must fail the Job (FAKE_LIST_FAIL), a read failure
whose message contains "not found" must fail the Job, and a
success-path stderr warning must not fake a pinned state
(FAKE_WARN_STDERR). Absence is now modeled the way real kubectl
behaves under --ignore-not-found: success with empty output.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
The stderr-based classification this branch introduced had two holes of
its own. Capturing stderr into the data variable (2>&1) contaminates
the SUCCESS path: kubectl prints warnings on successful reads (API
deprecation headers -- deterministic for a deprecated GVK, and CAPI
v1beta1 is one -- plus client-side throttling notices), so the warning
glued onto the owner annotation would trip adopt_one's foreign-owner
refusal on every tenant and permanently deadlock the pre-upgrade hook.
And the *"not found"* pattern over-matches: a transient
conversion-webhook outage fails a read with '... service
"capi-webhook-service" not found', which the classifier would treat as
absence -- skipping the keep pin and re-opening the exact fail-open
prune hazard this branch exists to close.
Detect absence with --ignore-not-found instead: a missing object is
SUCCESS with empty output, so a non-zero exit can only be a real
failure and aborts before the version stamp, with no stderr parsing at
all. adopt_one reads -o json and extracts the owner annotation with jq
(already a dependency), keeping absence distinct from present-but-
unannotated; pin_keep reads -o name. list_kmts still needs stderr for
the one legitimate classification -- the two deterministic missing-CRD
messages -- so it captures stderr to a temp file, never into data, and
no longer accepts NotFound-shaped text for a list.
The fake kubectl honors --ignore-not-found the way real kubectl does,
gains FAKE_WARN_STDERR (success-path stderr warnings) and
FAKE_GET_FAIL_MSG (transient error with arbitrary text). Two new bats
tests, each red against the previous commit: a deprecation warning must
not break adoption or fake a foreign owner, and a failure whose message
contains "not found" must still abort without stamping.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
The pre-delete unpin hook's existence check swallowed every kubectl get
failure (`... >/dev/null 2>&1 || return 0`), four lines below the
comment declaring "Failures are NOT swallowed". kubectl exits 1 for
NotFound and for a transient apiserver error alike, so a timeout during
uninstall read as "object absent": the unpin was skipped, the Job
succeeded, and Helm then skipped the still-keep-annotated
MachineDeployment -- leaking the adopted pool's worker VMs into the
tenant namespace, running and unmanaged, after the pool was deleted.
The KMT-listing path was already hardened for exactly this class; the
existence check was the remaining instance.
Classify by stderr: NotFound (native pool, or already gone) stays a
no-op; any other failure fails the Job, bounded by backoffLimit and
activeDeadlineSeconds, with logs retained. The existence check and the
annotation read fold into a single request.
The embedded script's behavior cannot be asserted from the manifest, so
a new bats suite renders the chart, extracts the Job's script, and
executes it against a fake kubectl: NotFound no-ops and succeeds, a
transient named-get error fails the Job (red against the previous
script, which printed "unpin done" and exited 0), keep-annotated
objects are unpinned with the 6-hex hash anchor respected, and an
unpinned existing object is left untouched.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
kubectl exits 1 for NotFound and for transient server failures (timeout,
429, etcd hiccup) alike, and migration 54 treated every non-zero read as
"object absent". A transient error while reading a worker object would
skip the keep pin and the ownership rewrite, let the migration complete
and stamp version 55 (so it never re-runs), and the parent's
control-plane-only upgrade would then prune the un-pinned live
MachineDeployment -- deleting every running worker VM in the pool. The
doubly-masked KubevirtMachineTemplate listings (2>/dev/null plus
`|| true`) had the same shape: a failed list adopted or pinned zero
KMTs, permanently stranding a preserved older-revision KMT still
referenced by an in-flight MachineSet, since the child chart only
re-emits KMTs already annotated with its own release name. The
`cur=$(... || true)` owner read additionally bypassed the foreign-owner
refusal guard.
Classify reads by stderr, the migration-47 precedent: NotFound means
genuinely absent and is skipped; anything else exits 1 so
run-migrations.sh leaves CURRENT_VERSION at 54 and retries on the next
upgrade. adopt_one and pin_keep fold the existence check into the
annotation read (one request instead of two); KMT listings go through a
capture-first list_kmts helper because `for x in $(...)` discards the
substitution's exit status even under set -e, leaving `|| true` to
cover only the empty-grep-match case, mirroring the unpin hook. The
child-HR existence check stays deliberately tolerant: its fallback is
an idempotent apply that itself fails closed. adopt_one now also stamps
meta.helm.sh/release-namespace so an object whose Helm annotations were
stripped out-of-band cannot fail the child's ownership validation.
The fake kubectl now reports absent objects the way the real apiserver
does (NotFound on stderr, exit 1) and gains FAKE_GET_FAIL to inject
transient errors; four new bats tests pin the classification: NotFound
still completes and stamps, while a transient error on the adopt path,
the KMT listing, or the pin path aborts before the version stamp. Each
red against the previous script.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
The CiliumNetworkPolicy test verified only that the policy selects the
unpin pod, not spec.egress, so an egress regression that left the
uninstall hook unable to reach the apiserver would still pass. Assert the
kube-apiserver egress entity.
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
The pre-delete unpin hook discovered this pool's hash-suffixed
KubevirtMachineTemplates through `kubectl get ... 2>/dev/null | grep ...
|| true`, which turned an API or RBAC failure into an empty result: the
Job then reported success while the keep-annotated templates stayed
pinned and leaked on uninstall (Helm skips keep-annotated resources).
That contradicts the unpin() contract right above it, where annotate
failures are deliberately propagated.
Split the list out of the pipe so its failure fails the Job (set -e,
bounded by backoffLimit/activeDeadlineSeconds, logs retained), while a
successful-but-empty listing still no-ops the loop.
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
The RFC-1123 key guard added in the previous round closed hostile map
keys, but migration 54 still trusted the shape of nodeGroups and of each
group value, and word-split keys on whitespace. Because it runs as the
platform pre-upgrade hook, either gap can deadlock the upgrade for every
tenant off one hand-mangled parent HelmRelease (kubectl edit bypasses the
aggregated API schema, the same vector the key guard addresses).
Shape: a non-object nodeGroups (array/string/number) crashes jq under
set -e (keys[] on an array yields indices, then .[$idx] fails); a
non-object group value aborts the value-mapping jq on `$grp | has(...)`.
Normalize both: skip the cluster for a non-object nodeGroups map, and
route a non-object group value through the same warn + pin + skip path as
an invalid name. {} / null still fall through to the implicit md0 default.
Whitespace: an unquoted `for group in $(... keys[])` word-splits (and
globs) a key like 'my pool' into fragments that each pass the RFC-1123
guard, fabricating garbage child releases. Iterate keys newline-safely so
the intact key reaches the guard. Fail-closed exit semantics are
preserved through the while pipeline.
Covered by three new bats fixtures in migration-54-adopt-path.bats, each
red against the current script and green with this change.
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
Both existing adopt-values cases feed an explicit md0, leaving the DEFAULT_MD0
materialisation (empty nodeGroups) uncovered. Add a case asserting a parent HR
with no nodeGroups yields the child HR kubernetes-nodes-<cluster>-md0 with
minReplicas 0 and the ingress-nginx role. Also correct the header comment: the
jq picks ["version","talos"] and narrows images to {kubectl} separately, not
["version","talos","images"].
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
The PR removed the kubernetes.cpuToMillicores helper but left its documentation
comment dangling at the end of _resources.tpl. Delete it.
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
The doc still claimed the kubernetes-nodes per-pool storageClass is intentionally
not immutable and undefaulted. This branch annotated it immutable (self == oldSelf
XValidation, @immutable in values.yaml) and it defaults to replicated, and the
cluster field is immutable too. Rewrite the paragraph to describe both fields,
add kubernetes-nodes to the covered-apps list, and drop the now-stale
top-level-only caveat on the kubernetes entry.
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
The 53-char overflow branch exists because exiting the migration deadlocks the
platform pre-upgrade hook for every tenant. The equivalent deadlock via name
validity was unguarded: the old nodeGroups map key was never schema-constrained
(map[string]NodeGroup, no propertyNames pattern), so a stored parent HR can
carry a key like 'My_Pool' whose own render already failed at apply time. The
migration then built child_name=kubernetes-nodes-<cluster>-My_Pool, kubectl
apply rejected the RFC-1123-invalid HelmRelease name, the script exited 1 under
set -e, and every subsequent platform upgrade re-ran and re-failed.
Validate child_name against the RFC-1123 label pattern alongside the length
check and route failures through the same warn + pin + skip path. Factor the
pin-and-skip logic shared by both guards into pin_pool_objects. Cover the new
branch in migration-54-adopt-path.bats (the fake kubectl apply now rejects an
invalid metadata.name, so the case fails without the guard).
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
The unpin Job carried only helm.sh/hook-delete-policy: before-hook-creation,
and its comment claimed a successful run is torn down with the release. Helm
does not track hook resources as release members, so after helm uninstall the
succeeded Job and its pod remained in the tenant namespace indefinitely, one
per deleted pool name per namespace — before-hook-creation only fires on a
next pre-delete of a same-named release, which never comes for a deleted pool.
Add spec.ttlSecondsAfterFinished: 86400 so a finished Job is garbage-collected
(a failed run still keeps its logs for a day), and correct the comment.
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
assertParentVersion failed the pool render whenever the pool minor differed
from the parent KamajiControlPlane minor in either direction. A worker minor
lagging the control plane is supported (n-3 upstream) and is the normal state
during a rolling upgrade, where the parent Kubernetes CR is bumped first and
each pool follows. The symmetric check flipped every pool HelmRelease of a
cluster to render-failure the moment the parent was bumped, blocking all pool
operations until each pool version was hand-edited.
Fail only when the pool minor is ahead of the parent minor (semverCompare on
normalized major.minor.0), matching the stated rationale, and cover all four
directions (ahead / lag / equal / no parent) with a helm-unittest suite driven
by a mocked KamajiControlPlane.
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
The Phase-2 worker-pool adoption migration was renumbered 52 -> 54 during
the rebase onto main (main added migrations 52 linstor-scheduler and 53
seaweedfs). Rename the adoption bats tests and their testdata directory,
and update the kubernetes-nodes pre-delete hook comment and the
kubernetes README so they reference migration 54. The bats MIG path
pointed at migrations/52 (now the linstor migration), so without this the
adoption unit tests would exercise the wrong migration.
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
Address review on #3315:
- README breaking-changes: worker pools move to KubernetesNodes (nodeGroups
removed, adopted by migration 52); the parent Kubernetes CR's WorkloadsReady
is now control-plane-only; ingressNginx needs an explicit ingress pool; do
not edit Kubernetes CRs mid platform-upgrade.
- Note that the apiserver ClusterIP certSAN is a best-effort extra — workers
dial by DNS, so a pool-less control plane is fine without it; the merge-patch
array-replace predates the split.
- Confirm the pool VM pod is intentionally attributed to the parent Kubernetes
application (byte-parity + lineage/quota under the owning cluster).
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Address review on #3315:
- Mark cluster and storageClass immutable (self == oldSelf): both feed object
names / the KubevirtMachineTemplate content hash, so editing them on a live
pool would rename everything and delete the running worker VMs.
- Validate the pool's Kubernetes minor against the parent cluster's
KamajiControlPlane at render (skipped offline / when the parent is absent),
so a pool created after the split cannot join workers ahead of the apiserver.
- Note in the snapshot suite header that the instancetype-sized default is not
pinned offline (lookup nil); the e2e exercises it.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Address review on #3315:
- Name-length overflow no longer exits 1 (which would deadlock the platform
pre-upgrade hook for every tenant). Instead pin the pool's worker objects
with resource-policy=keep, skip the child HR, warn loudly, and continue.
- Copy only images.kubectl into the child values, not the parent's whole
images map (waitForKubeconfig/talosCsrSigner are undeclared in the schema).
- Note that the pre-upgrade window is not quiet (a parent HR edit mid-upgrade
renders the old chart and self-heals once the new artifact lands).
- Cover the adoption path directly: annotate keep + release-name, idempotent
skip, unexpected-owner refusal, and the 6-hex KMT anchor rejecting a sibling
pool's template.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Drives migration 52 against a fake kubectl and asserts the adopted
child HelmRelease carries the tenant's non-default talos.version,
version and images (plus group fields and storageClass fallback). Fails
against the pick(o;...) filter-parameter bug that dropped those keys and
rolled live worker VMs; passes against the pick($o;...) fix.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The adoption jq used a filter-parameter helper `def pick(o; ks)`; inside
the `reduce` the `.` context is the accumulator, so `o | has($k)` tested
the accumulator, not the source object, and `pick(.; ["version","talos",
"images"])` deterministically returned {}. The child HelmRelease was
therefore created without the tenant's talos/version, so Helm rendered
the chart defaults; since talos.version feeds the KubevirtMachineTemplate
content-hash, the KMT name changed and the MachineDeployment rolled every
live worker VM on upgrade — the exact churn this migration must avoid.
Caught by e2e on dev3 (reproduced on 2/2 real clusters). Switch pick to
a $-parameter so it is evaluated once at the call site.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The chart split removed the parent pool-render suites and the cross-chart
parity script, leaving the GPU device block, kubelet-reservation math and
maxUnhealthy IntOrString branches (all still in nodegroup.yaml /
talos-reconcile-job.yaml) uncovered. Add GPU and kubelet snapshot cases
so drift renaming the content-hashed KubevirtMachineTemplate fails CI,
and port the behavioral + failure-path assertions (GPU nodeLabels,
kubelet reserved/effective invariants and quantity rejections, MHC
integer/percentage quoting) to the child chart.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The chainsaw harness created a KubernetesNodes CR but never reclaimed it,
leaking the pool CR, its child HelmRelease, release Secret and
WorkloadMonitor into the shared tenant-test namespace and breaking
rerun-in-same-sandbox (the surviving child HR left the MachineDeployment
un-rendered on retry). Delete kubernetesnodeses in all three cleanup
paths, before the parent CR so the pre-delete unpin hook runs.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Remove the orphaned kubernetes.nodeGroups doc comment, the stale kubelet
reservation / nodeGroups storageClass prose in the README, and the inert
nodeGroups blocks in the test value fixtures.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Check the resource-policy annotation before removing it so a native pool
is a clean no-op while a real annotate failure fails the Job (retries
bounded, logs retained) instead of silently re-introducing the keep
leak. Scope the MD/MHC/WorkloadMonitor Role rules with resourceNames.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The chainsaw harness created the Kubernetes CR with spec.nodeGroups,
which the control-plane-only chart now ignores, so no MachineDeployment
was created and the suites timed out. Create a KubernetesNodes CR named
<cluster>-md0 (roles: [ingress-nginx]) so the same MachineDeployment is
produced and the MD/ingress waits pass; this also gives the split its
first e2e coverage.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The render-time fail flipped existing degraded clusters from Ready to
Failed on upgrade, blocking all subsequent control-plane changes.
Restore the prior non-breaking behavior (the DaemonSet schedules nothing
if no ingress-roled node exists) and document the pool requirement in
NOTES.txt instead of enforcing it at render time.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The cross-chart parity script was removed (the parent no longer renders
pools to diff against); the render snapshot under helm unittest is the
drift guard now and already runs in CI.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Remove dead nodeGroups blocks from the CI values fixtures and point the
storage-immutability doc at the kubernetes-nodes per-pool storageClass.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Migration 52 pins adopted worker objects with helm.sh/resource-policy=keep
for the transition window. Left in place it leaks the objects when an
adopted pool is deleted. Add a pre-delete hook that strips the annotation
from the release's own worker objects so Helm deletes them cleanly;
runs on delete only (never on upgrade, so it cannot race the parent
re-render) and is a no-op for natively-created pools.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
types.go dropped NodeGroups/NodeGroup/GPU/Kubelet/NodeHealthCheck but
the generated deepcopy still referenced them, so the api module failed
to build. Regenerated with controller-gen.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Anchor the KubevirtMachineTemplate sweep to the 6-hex content-hash
suffix so a pool name that is a prefix of a sibling (md0 vs md0-large)
no longer mis-adopts the sibling's KMT and deadlocks the migration.
Adopt the worker objects before creating the child HelmRelease so
helm-controller cannot start the child install into un-adopted objects
and fail Helm ownership validation. Emit the same install/upgrade
strategy (RetryOnFailure) and maxHistory cozystack-api sets, add a
pre-flight release-name length check, and document the rollback path.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The parent no longer renders pools to diff against, so the one-shot
extraction parity check is replaced by a self-contained golden snapshot.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
With pools moved out of the chart the ingress-nginx addon can no longer
rely on an auto-provisioned md0; fail the render with a clear message
when addons.ingressNginx.enabled and no pool carries roles: [ingress-nginx].
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Worker pools are now managed via KubernetesNodes resources; existing
pools are adopted by migration 52.
BREAKING CHANGE: the Kubernetes CR no longer accepts spec.nodeGroups.
Create KubernetesNodes resources for worker pools instead.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The KubevirtMachineTemplate/MachineDeployment/MachineHealthCheck/worker
WorkloadMonitor, the preserve-old-KMT block, the talos-reconcile Job and
its RBAC now live in the kubernetes-nodes chart. The kubernetes chart
renders the control plane only.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Pre-upgrade migration for the Phase 2 kubernetes chart split. For every
parent kubernetes-<cluster> HelmRelease it creates one child
kubernetes-nodes-<cluster>-<pool> HelmRelease and re-annotates the
existing worker objects onto it with helm.sh/resource-policy=keep, so
the now control-plane-only parent upgrade does not prune the tenant's
running workers. Byte-identical child render (PR-2a golden parity) keeps
the KubevirtMachineTemplate content-hash stable, so no worker VM churns.
Idempotent and strict (exit 1 on any failure). Bumps targetVersion to 53
(contiguous with main; rebase to 53/54 if another 52 lands first).
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The ephemeralStorage guard could never fire (the pool group is built from a
fixed set of chart values that never includes ephemeralStorage), so it read
as protection that is not there — remove it. Note in the parity script header
that only the four pool objects are compared, not the talos-reconcile Job.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Extend the golden-parity matrix beyond the resources-sized pool to also
diff a GPU pool and a kubelet-override pool against the parent render, so
future drift in those branches (which would roll the content-hash-named
KubevirtMachineTemplate) is caught in CI.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Reference the adoption migration by role (Phase 2b) instead of a number
that does not exist on this branch, and correct the NOTES operational-note
count.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Wire tests/render-parity.sh into the chart's test target so CI verifies
the pool objects stay byte-identical to the parent render.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Restore the inline machineconfig comments (nameservers, GPU node labels)
inside the reconcile Job's data block so the applied TalosConfigTemplate
matches the parent's, avoiding drift on adoption.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The cluster field referenced x-cozystack-options source 'kubernetes',
which has no provider (cozystack-api returns NotFound), so the dashboard
dropdown 404s. Drop the annotation so the field is a plain text input;
a real provider listing Kubernetes CRs is a follow-up.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Replace the collision-prone name-prefix match (pool 'gpu' matched
sibling 'gpu-large-<hash>') with a release-name annotation scope, and
add a render-time guard that fails cleanly when a pool's MachineDeployment
already exists under a different release (e.g. naming a pool after a
parent nodeGroup such as the default md0). Document the naming caveat in
NOTES.txt.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
The preserve-old-KubevirtMachineTemplate block re-emitted any KMT owned
by the CAPI Cluster and referenced by a MachineSet. A kubernetes-nodes
pool's KMT lives in the same namespace under the same Cluster, so the
parent would re-emit it with a foreign meta.helm.sh/release-name and its
next upgrade would fail Helm ownership validation. Restrict the block to
KMTs whose release-name annotation matches the parent release.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Add the kubernetes-nodes-rd package (ApplicationDefinition), the
cozystack.kubernetes-nodes-application PackageSource (kubevirt variant,
kubernetes-nodes + kubernetes-nodes-rd components), and wire it into the
iaas bundle. Mirrors the vm-instance/vm-disk registration precedent.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Unit tests cover naming/selectors, clusterName wiring, autoscaler
annotations, omitted replicas, bootstrap TCT reference, KMT hash name,
worker WorkloadMonitor, and the empty-cluster / mis-prefixed-release
render guards. render-parity.sh diffs the pool objects against the
parent kubernetes chart and asserts byte-identity.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
Introduce the kubernetes-nodes application chart: one HelmRelease per
worker node pool, attached to a parent Kubernetes cluster by name
convention (kubernetes-<cluster>). Renders the KubevirtMachineTemplate,
MachineDeployment, MachineHealthCheck, worker WorkloadMonitor and the
talos-reconcile Job with its RBAC, extracted from the monolithic
kubernetes chart. Pool objects are byte-identical to the parent's render
for the same group, so a later adoption never churns live worker VMs.
This is the additive half of the Phase 2 split (community#8); the parent
kubernetes chart is left unchanged.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>