While the backend Bucket is not ready the controller returns an error to
force a requeue, but that error is only logged at klog.V(3) and is
suppressed at default verbosity, so an operator cannot see why the claim
is stuck. Record a WaitingForBucket Warning event on the BucketClaim on
each requeue (event aggregation folds the repetition) and still return
the error so the requeue happens as before. Pin the requeue contract in
the test by asserting the error carries the stable "not ready yet"
substring, not merely that it is non-nil.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit 5991808d28)
The two bucketaccesses waits used the bare jsonpath form, which also
matches the literal "false"; require =true so a never-granted access
fails the wait instead of passing against an ungranted object. Also
print the objectstorage-controller pod status in the bucketReady
failure block so controller-side issues are visible from the test log.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit 0855ff2d1b)
The objectstorage-controller package ships the COSI control plane; its commits
use the objectstorage-controller scope, which had no area mapping and fell back
to area/uncategorized. Map it to area/storage alongside the other COSI/storage
scopes.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit 4f5dcea432)
The bucket suite waited on '{.status.bucketReady}' without an expected value;
a bare jsonpath match is satisfied by the literal "false", so the wait passed
against an unready claim. Both suites also allowed 300s/600s, long enough to
tolerate the propagation race rather than catch it, so they stayed green
whether or not the BucketClaim ever converged.
Assert bucketReady=true on a 120s bound. Convergence is now controller-driven
(the controller requeues the claim until the backend Bucket's readiness
propagates) and completes within tens of seconds; a claim frozen by the
propagation race never converges and now fails the wait fast instead of being
masked.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit 63d14e7487)
The controller and the per-driver sidecar both run single-replica, so leader
election provides no high availability -- it only governs how quickly a freshly
recreated pod takes over. With the upstream 150s lease duration a recreated
provisioner pod stalls reconciliation for up to 150s while it waits out the
stale lease still held by the previous, now-deleted pod. Lower the lease timings
to the standard Kubernetes values (15s/10s/2s) so a recreated pod resumes
reconciliation in roughly 15s.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit 250d92323d)
The dynamic-provisioning path re-reads the live Bucket after create and copies
its readiness onto the BucketClaim, but only during a reconcile. Nothing
re-drives that reconcile afterwards: the controller does not watch Buckets, and
the generic controller drops no-op resync deltas (reflect.DeepEqual), so once
the BucketClaim stops changing the listener is never re-invoked. The Bucket's
false->true transition, performed asynchronously by the sidecar on a different
object, is therefore reflected onto the claim only if the Bucket happened to be
ready during that single reconcile -- a race the sidecar usually loses, leaving
bucketReady frozen at false and BucketAccess never granted.
Return an error while the backend Bucket is not ready so the work queue
requeues the claim with exponential backoff; each retry re-reads the live
Bucket until its readiness has been propagated, converging deterministically
instead of depending on a resync that never fires.
Add a unit test pinning the contract (requeue while not ready, propagate true
once ready) and adjust the existing status-update conflict-retry test, which
pinned the old never-requeue behavior.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit 4437cccaf0)
## What this PR does
Adds the flux CLI to the release-1.5 cache warmer, which #3469 moved
onto the ephemeral runner shape without carrying over the toolchain step
that main's warmer and this branch's `pull-requests.yaml` both have.
`make build` finishes at `packages/core/installer`, whose
`image-packages` target shells out to `flux push artifact`. The
self-hosted runner the warmer used to target had flux baked in; the
ephemeral shape does not.
Confirmed on the first warmer run after #3469 merged ([run
30430753152](https://github.com/cozystack/cozystack/actions/runs/30430753152)):
it failed at 49 minutes with `/bin/sh: 1: flux: not found` on
`Makefile:35`, the last of 28 packages.
The cache itself came out warm, because every package exports its cache
as it builds and installer is last:
| | |
| --- | --- |
| cache export operations | 87 |
| cache manifests written | 70 |
| repos created under `CACHE_REGISTRY` | 34 |
| `ubuntu-container-disk` refs (`v1.30`–`v1.35`, `mode=max`) | all 6 |
| real auth or export failures | 0 |
So the only loss was the `cozystack-packages:release-1.5` artifact push,
and nothing downstream depends on it — PR builds build the installer
themselves with flux present. This also settles the open question from
#3469: the registry credentials can create repositories under the new
`cozystack-cache-release-1.5/*` namespace, so no fallback to a cache-tag
suffix is needed.
Fixing it still matters. A permanently red warmer means a genuine
breakage is indistinguishable from this known-broken tail, and nothing
else reports on that workflow.
The alternative would be teaching the warmer to run the 28 image builds
without the artifact push, but no such target exists and it would
diverge from main's warmer for no gain. Installing the CLI keeps the two
warmers identical in shape, and matches main publishing
`cozystack-packages:main` from its own warmer.
### Release note
```release-note
NONE
```
`make build` finishes at packages/core/installer, whose image-packages
target shells out to `flux push artifact`. The warmer used to target the
self-hosted runner, which had flux baked in; #3469 moved it to the
ephemeral shape without carrying over the toolchain step that main's
warmer and pull-requests.yaml both have for exactly this reason.
Confirmed on the first run after #3469 merged (run 30430753152): it failed
at 49 minutes with `/bin/sh: 1: flux: not found` on Makefile:35, the last
of 28 packages. Everything before it had already exported its cache -- 87
export operations, 70 cache manifests, 34 repos created under
CACHE_REGISTRY, including all six ubuntu-container-disk refs -- so the
cache came out warm and only the cozystack-packages artifact push was
lost. A red warmer is still a broken signal, and nothing else would have
reported it.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
## What this PR does
Nothing has ever warmed `release-1.5`'s build cache, so every PR build
on this branch runs cold end to end and exceeds its 30-minute timeout.
This branch's copy of `build-main.yaml` is dead code. It triggers on
`push: branches: [main]`, which never happens here, and it targets
`[self-hosted]` — the decommissioned cozy-runner-1 (#2937) — so it could
not have run even if it fired. This PR points it at this branch instead.
Both halves of the cold build trace back to 39cdc8866
(`feat(kubernetes): bootstrap tenant workers with Talos via CABPT`)
landing on `main` on 2026-06-16, six days before `release-1.5` was cut
on 2026-06-22:
- That commit dropped `ubuntu-container-disk` from `make image`, so
`main` stopped writing its six `:<minor>-buildcache` refs. `release-1.5`
is now the only branch that still builds the image, and the CI log shows
all six importers failing with `not found`. Serially that was ~28min of
the 30min budget; #3457 parallelises the target down to ~10min.
- Every other cache ref carries `main`'s sources, which have diverged
from this branch, so most of the remaining 28 packages miss too.
Measured on the #3457 run: ~38min across the full build, and no single
hot spot left to attack — `apps/kubernetes` at 15m07s and
`system/linstor` at 5m39s, everything else 20-60s each.
### Changes
| | before | after |
| --- | --- | --- |
| trigger | `push: [main]` | `push: [release-1.5]` |
| runner | `[self-hosted]` (decommissioned) |
`oracle-vm-24cpu-96gb-x86-64` |
| cache namespace | shared `cozystack/` | `cozystack-cache-release-1.5/`
|
| `IMAGE_TAG` | `main` | `release-1.5` |
| warmer timeout | 90 | 120 |
`pull-requests.yaml` gets the same `CACHE_REGISTRY` so PR builds read
what the warmer writes, and its Build timeout goes to 75 minutes.
The cache namespace is branch-scoped on purpose. Writing the shared refs
from here would replace `main`'s layers with this branch's, so `main`'s
next PR build would miss on everything and blow its own 30-minute
timeout until the next `main` push re-warmed it. `CACHE_REGISTRY`
already exists as a knob in `hack/common-envs.mk`, so this is one env
var per job rather than new machinery. Image tags are unaffected — they
still resolve to `cozystack/<image>`, only cache refs move.
The timeout raise is not optional. The new namespace starts empty, so
this PR and the next one still build cold at ~45min, and anything that
later invalidates the cache broadly — a Dockerfile edit, a `go.mod` bump
— costs the same again. 30 minutes only ever fit a warm build, and when
it did not fit, the job reported a timeout rather than whatever actually
went wrong.
### Verification
- Both workflows are asserted to agree on the cache namespace, rather
than eyeballed.
- Confirmed the env split renders as intended: `--tag
iad.ocir.io/…/cozystack/ubuntu-container-disk:v1.35-release-1.5`
alongside `--cache-from`/`--cache-to` on
`…/cozystack-cache-release-1.5/ubuntu-container-disk:v1.35-buildcache`.
- `WRITE_CACHE` stays unset in PR builds, so they remain read-only
against the cache and never race on a manifest.
### Notes for the reviewer
- **Stacked on #3457.** Both PRs edit adjacent lines of
`pull-requests.yaml`, so keeping them independent guaranteed a conflict.
GitHub retargets this to `release-1.5` automatically once #3457 merges.
- **The filename stays `build-main.yaml`** even though it no longer
warms `main`. Renaming it would make any later backport touching
`main`'s copy arrive as a whole new file rather than a modification,
which is the failure mode the backport bot already hits on this branch.
- **One assumption I could not test locally:** the registry credentials
need repo-create permission for the new `cozystack-cache-release-1.5/*`
path. It is the same tenancy namespace that already auto-creates repos
as packages get added, so it should hold — but if it does not,
`--cache-to` fails the warmer, and the fallback is a cache-tag suffix in
`hack/common-envs.mk` instead of a separate namespace.
- **Sequencing:** the merge commit is itself a push to `release-1.5`, so
the warmer fires on merge and takes ~50-60min cold. PR builds after that
should be ~15min. The warmer cannot be triggered manually —
`workflow_dispatch` is only available for workflows present on the
default branch, and this one exists only here.
- **Out of scope, but adjacent:** `tags.yaml`, `release-e2e.yaml` and
`pull-requests-release.yaml` on this branch all still say `runs-on:
[self-hosted]`, so the release and release-e2e lanes are broken the same
way this warmer was.
### Release note
```release-note
NONE
```
Point the Build job at the namespace build-main.yaml now writes for this
branch. Without this the warmer would run and nothing would read it: the
cache-from refs would still resolve to the shared namespace main writes,
whose layers carry main's sources and miss on most of this branch's 28
packages. Builds only read the cache -- WRITE_CACHE defaults to 0, so
concurrent PR builds still never race on a cache manifest, and a miss
degrades to a cold build rather than an error.
Raise the timeout to 75 minutes at the same time. A warm build is ~15min,
but the namespace starts empty, so this PR and the next one run cold at
~45min: six ubuntu-container-disk images plus 28 packages from scratch.
Anything that later invalidates the cache broadly -- a Dockerfile edit, a
go.mod bump -- costs the same again. 30 minutes only ever fit a warm
build, and when it did not fit, the job reported a timeout rather than
whatever actually went wrong.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Nothing has ever warmed this branch's build cache. This workflow is a
copy of main's warmer that still triggers on `push: branches: [main]`, so
on release-1.5 it has never fired once -- and it targets [self-hosted],
the decommissioned cozy-runner-1 (#2937), so it could not have run even
if it did fire.
The consequence is a PR Build that runs cold end to end and exceeds its
30-minute timeout. Two separate reasons, both traceable to 39cdc8866
("bootstrap tenant workers with Talos via CABPT") landing on main six
days before this branch was cut:
* that commit dropped ubuntu-container-disk from `make image`, so main
stopped writing its six :<minor>-buildcache refs. release-1.5 is the
only branch that still builds the image, and the CI log shows all six
importers failing with "not found" -- ~28min serial, cut to ~10min by
parallelising the target in #3457.
* every other ref carries main's sources, which have diverged from this
branch, so most of the remaining 28 packages miss too -- ~38min across
the full build, with no single hot spot left to fix.
Point it at this branch, move it to the ephemeral shape main's warmer
already uses, and write to a branch-scoped CACHE_REGISTRY namespace.
The namespace matters: writing the shared refs from here would replace
main's layers with release-1.5's, so main's next PR build would miss on
everything and blow its own 30-min timeout until the next main push
re-warmed it. pull-requests.yaml has to read the same namespace, which
the following commit does.
The filename stays build-main.yaml even though it no longer warms main.
Renaming it would make any later backport touching main's copy arrive as
a whole new file rather than a modification, which is the failure mode
the backport bot already hits on this branch.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Every release-1.5 PR Build job dies at the 30-minute timeout, and all of
it is spent in one target. `image-ubuntu-container-disk` builds a disk
per Kubernetes minor -- six of them -- and each spends ~4-5min inside a
libguestfs appliance installing that minor's kubelet/kubeadm into its own
copy of the cloud image. Serially that is ~28min of the 30min budget:
v1.35 6:00, v1.34 4:21, v1.33 4:27, v1.32 4:39, v1.31 4:42, v1.30 cancelled
None of it is cached, and no warmer will fix that on its own. Only
build-main.yaml sets WRITE_CACHE=1, and main dropped this image from
`make image` in 39cdc8866 six days before release-1.5 was cut, so the
:*-buildcache refs it reads have never been written -- the CI log shows
all six importers failing with "not found". release-1.5 is now the only
branch that builds this image at all.
The six builds share no per-version work, so run them concurrently
instead. A sub-make carries its own -j, keeping the root `make build`
serial, and buildkit dedups the shared guestfish and cloud-image stages
across the concurrent solves. --output-sync=target groups each version's
log under its target name; six interleaved buildx progress streams have
no per-solve identifier and are unreadable. Verified the per-version
buildx/echo/rm command set is byte-identical to the loop it replaces
across PUBLISH_VERSIONED, PUBLISH_FLOATING and WRITE_CACHE combinations.
Moving off the 4cpu/16gb shape because six concurrent libguestfs
appliances want ~9gb of RAM and a core apiece. The comment justifying
the small shape assumed a warm cache, which no longer holds here.
This also stops swallowing failures. The loop separated versions with
`;`, so make saw only the last version's exit status: a failed build for
any other version left its committed .tag file stale and the job green.
Under the sub-make a failure in any version fails the target.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
The flux-instance template rendered spec.distribution.artifact
unconditionally, unlike the sibling optional fields (artifactPullSecret,
imagePullSecret, variant). The umbrella default is empty to use the
operator's embedded manifests (the air-gapped default from #964), but an
empty value renders as YAML null. In the flux-operator v0.50.0 CRD the
field is optional yet typed 'string' with pattern ^oci://.*$ and is not
nullable, so the rendered null (like an empty string) fails schema
validation and the API rejects the FluxInstance.
Guest Kubernetes clusters with the fluxcd addon enabled could therefore
never install it: the sub-release looped install/uninstall, the parent
kubernetes release stayed InProgress, and the cluster never reached Ready.
Guard the field so an empty value is omitted (the operator falls back to
its embedded manifests, preserving the air-gapped default) while a
non-empty artifact still renders. The template lives in the vendored
subchart, so the change is carried as a patch applied by 'make update'.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
(cherry picked from commit da47b70e2c)
Two related issues caused the dashboard SPA to break with CORS errors
after the kc-access cookie expired:
1. KeycloakClient for dashboard had no webOrigins set, so the operator
never touched the field in Keycloak after initial creation. After
any rootUrl change the existing webOrigins value became stale and
blocked CORS from the SPA. Setting "+" tells Keycloak to derive
allowed origins from redirectUris.
2. oauth2-proxy returned 302 -> Keycloak /auth for unauthenticated
XHR/fetch on /api and /apis. The login page does not emit
Access-Control-Allow-Origin, so the SPA's fetch failed with CORS.
--api-route makes oauth2-proxy answer 401 without redirect, so the
SPA can handle the re-auth itself via top-level navigation.
Signed-off-by: Ivan Okhotnikov <ivan.okhotnikov@aenix.io>
(cherry picked from commit be8f6b4739)
A leftover debug field "foo" in the <release>-urls Secret template
violates the core/v1 Secret schema. It went unnoticed under client-side
apply but breaks Helm upgrades under server-side apply with
".foo: field not declared in schema", leaving the release in
UpgradeFailed state. Drop the debug block.
Signed-off-by: Ivan Okhotnikov <xorokhotnikov@gmail.com>
(cherry picked from commit 70a2284551)
Refresh the vendored virt-operator manifest from v1.8.2 to v1.8.4. The
release backports validation of the VMI checksum status fields as a
uint32 range, required on Kubernetes 1.36 where strict CRD numeric
format validation otherwise leaves VMIs stuck in Scheduled. Remaining
changes are bug fixes and CVE remediations; the embedded CRDs and RBAC
are unchanged, so only the operator image tag moves.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit 192246e8b6)
Reverts #3006. Dropping persistent EFI/TPM was motivated by a live-migration
concern that rested on an outdated assumption — that an RWO Filesystem
backend-storage PVC pins the VM to its node. KubeVirt has migrated
RWO-Filesystem backend storage since v1.4 (kubevirt/kubevirt#12629): on
migration it creates a fresh target state PVC and copies the small state blob,
so persistent-EFI/TPM VMs on the default replicated storage live-migrate fine
(verified: the VM reports LiveMigratable=True and the copy-on-target PVC is
created on migration). Restore upstream's persistent firmware state for the
windows.* preferences.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <andrei.kvapil@aenix.io>
(cherry picked from commit 59f035ff53)
The vendored seaweedfs chart ships connection pool settings only for the
mysql store, which cozystack does not use. The postgres2 store, which is
enabled, has no pool settings, so the Go sql pool keeps zero idle
connections and every filer metadata lookup opens a fresh PostgreSQL
connection (TCP + TLS + SCRAM, ~300ms each). With ~5 path lookups per S3
operation this adds roughly 2 seconds of latency to every S3 request,
regardless of cluster load.
Measured on a production cluster (12 nodes, 2 filers): PUT of a 4KiB
object went from 10s (p50) to 0.28s, HEAD from 2.6s to 0.16s after
setting these values; pg_stat_activity confirmed connections were
previously recycled every ~200ms and are now reused.
max_open is capped at 40 so that two filer replicas stay below the CNPG
default max_connections of 100.
Signed-off-by: mattia-eleuteri <mattia@hidora.io>
(cherry picked from commit 49cbea8c73)
Deleting a Tenant whose etcd DataStore has 0 referencing TenantControlPlanes left the DataStore stuck Terminating (finalizer kamaji.clastix.io/TenantControlPlane), hanging the etcd helm uninstall and wedging the tenant namespace. Backports clastix/kamaji#1122 (fixes clastix/kamaji#1115) as a source patch on the pinned 26.3.6-edge build. Refs #3018.
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
(cherry picked from commit 47638f8569)
The victoria-metrics-operator HelmRelease is gated on
monitoringAgents.enabled but listed cert-manager-crds in dependsOn
unconditionally, while the cert-manager-crds HelmRelease is only
created when certManager.enabled is true. The valid combination
monitoringAgents.enabled=true + certManager.enabled=false therefore
left vmop blocked on a non-existent dependency
("...cert-manager-crds ... not found"), cascading to monitoring-agents
and vertical-pod-autoscaler. Gate the dependency on the same condition
that creates it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
(cherry picked from commit 2b1d3e904d)
## What this PR does
Backport of #3121 to `release-1.5`.
Makes node group `resources` optional, so a node group sized purely by
`instanceType` (with `resources` omitted) passes `values.schema.json`
validation and installs. When a group sets both `instanceType` and
explicit `resources` (both `cpu` and `memory`), the explicit resources
take precedence: the instancetype is omitted from the rendered VM and
the per-group instancetype lookup is skipped, so KubeVirt does not
reject a VM that references an instancetype while overriding
`domain.cpu`/`memory`. A partial spec (only one of `cpu`/`memory`)
alongside an `instanceType` fails fast at render time.
Cherry-picked from `a349c753`; conflicts resolved against the
`release-1.5` tree (the management-cluster Talos worker bootstrap stack
present on `main` is not on this branch, so the schema/template/test
layout differ). Generated files (`values.schema.json`, `README.md`,
cozyrds, API types) regenerated with `make generate` to match. `helm
unittest` passes (134 tests), including the four new node-group sizing
cases adapted to this branch's document layout.
### Release note
```release-note
fix(kubernetes): make node group resources optional when instanceType is set
```
The failure-path dump queried mariadbs.k8s.mariadb.com with $name, but the
operator CR is named after the Helm release ({{ .Release.Name }} = mariadb-$name),
so the dump would hit NotFound instead of showing the rejected CR.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Алексей Артамонов <alexeyartamonov1987@gmail.com>
(cherry picked from commit f8e4222b7d)
PR #2279 made `replication.enabled: true` unconditional so the operator would
always create -primary/-secondary services. But the mariadb-operator validating
webhook (vmariadb-v1alpha1.kb.io) rejects replication when spec.replicas == 1,
so single-replica MariaDB could no longer be created — the HelmRelease never
became Ready.
Re-guard replication on replicas>1 and teach the service-name consumers about
the bare <release> service the operator provisions in both topologies:
- mariadb.yaml: gate `replication` on replicas>1; restore single-replica
external access via `service.type: LoadBalancer` and keep `primaryService`
LoadBalancer for replicas>1 only.
- backup-cronjob.yaml: route single-replica dumps to the bare service
(no -secondary exists without replication).
- dashboard-resourcemap.yaml: always grant RBAC on the bare service, plus
-primary/-secondary when replicas>1, matching the ApplicationDefinition.
- mariadb-rd: list the bare service in services.include so single-replica
installs are visible in the dashboard.
Adds a single-replica e2e test that reproduces the webhook rejection and
guards against regression.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Алексей Артамонов <alexeyartamonov1987@gmail.com>
(cherry picked from commit c7e8f4d975)
The tenant etcd, ingress and monitoring HelmReleases create VM* custom
resources (VMPodScrape directly in etcd/ingress; VMCluster, VMAlert,
VLCluster, VMAlertmanager and VMServiceScrape via the monitoring-system
child of monitoring) guarded by the victoria-metrics-operator validating
webhook with failurePolicy: Fail. On a cold install the operator pod can
be briefly unavailable on :9443, so these releases reconcile before the
webhook backend is serving and are rejected with connection refused. They
carry install.remediation.retries: -1 and would eventually recover, but
the failed-install -> rollback -> retry churn can outlast a cold-install
readiness deadline and surfaces as spurious install failures.
Add a Flux spec.dependsOn from each of these releases to the
victoria-metrics-operator HelmRelease in cozy-victoria-metrics-operator,
so they wait for the operator to be Ready before creating VM* resources.
The system monitoring components gate on the operator the same way, via a
variant-level dependsOn. The cross-shard reference (tenant releases are
sharded, the operator release is not) resolves via helm-controller's
uncached dependency check (APIReader, v1.1.0+).
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit 6db5ae9c6f)
A node group is sized either by instanceType or by explicit resources, but the
generated values schema required resources on every node group. A node group
with instanceType and no resources — or an empty resources dropped during
typed-CR to HelmRelease translation — failed schema validation with "missing
property 'resources'" even though sizing was fully specified.
Mark resources optional in the node group definition and regenerate the schema,
API types, README, and ApplicationDefinition. The chart template emits
domain.cpu/memory only when resources is present, so a node group sized purely
by instanceType now passes validation and installs.
When a node group sets both instanceType and explicit resources, explicit
resources take precedence: the instancetype is omitted from the rendered VM and
the per-group instancetype lookup is skipped, so KubeVirt accepts the explicit
domain.cpu/memory with no instancetype to conflict with. instanceType stays
required and defaulted (no schema change), so the console's required
instanceType dropdown keeps working — sending the default instanceType plus
explicit resources simply sizes the VM by resources. This replaces an earlier
render-time hard failure on the both-set case, which was unreachable to clear
from the dashboard (the required dropdown cannot be emptied).
Explicit resources are all-or-nothing alongside an instanceType: a partial spec
(only cpu, or only memory) on a group that carries a non-empty instanceType
would emit one domain override next to the instancetype — which KubeVirt rejects
— so it now fails at render time with a clear error. Partial resources on a
group without an instanceType (used to tune kubelet reservations) are unaffected.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit a349c753ad)
The seaweedfs COSI driver shipped at v0.1.2 hardcodes read-write S3
actions (Read, Write, List, Tagging) for every BucketAccess and never
reads the accessPolicy parameter. The chart already defines a -readonly
BucketAccessClass carrying parameters.accessPolicy: readonly, but v0.1.2
ignores it, so a credential meant to be read-only can still write
(upload and delete) objects.
Bump the driver to v0.3.1, which honours accessPolicy: readonly by
issuing Read,List-only credentials (read-write and the empty default
stay Read,Write,List,Tagging). The override lives in the package
values.yaml rather than the vendored chart so it survives make update;
the sister extra/seaweedfs chart already runs v0.3.1.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit 0c6426feaa)
The cozy-harbor wrapper never passed storageClass to the jobservice
jobLog PVC, so it was created without a storageClassName and the
default-StorageClass admission stamped the cluster default. Because PVC
storageClassName is immutable, this caused rendered-vs-live drift on
upgrade. Preserve an existing PVC's class via lookup and fall back to the
configured storageClass for fresh installs.
The trivy StatefulSet's volumeClaimTemplate had the same latent drift --
.Values.storageClass was forwarded blindly into a VCT that cannot be
patched at all -- so it gets the same lookup-preserve treatment, keyed
off data-<release>-trivy-0.
A live object pinned to an explicit "" (no dynamic provisioning) now
round-trips through upstream's "-" sentinel instead of collapsing to an
omitted storageClassName, and the spec lookup is guarded with
`| default dict` so a PVC carrying no storageClassName key stays omitted.
Adds a helm-unittest regression suite and wires a test target so
make unit-tests stops skipping packages/apps/harbor.
Fixes#2368
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
(cherry picked from commit bdf520bf74)
The s3-service-name.patch renamed the S3 Service to <name>-s3
(seaweedfs-s3), but several consumers still resolved it through
componentName -> <fullname>-s3. name and fullname only coincide when the
release name equals the chart name; the shipped release is
seaweedfs-system, so they pointed at seaweedfs-system-s3 while the real
service stayed seaweedfs-s3:
- the S3 ingress backend and the iceberg ingress backend, which left
ingress-nginx returning 503 on the external S3 endpoint.
The COSI provisioner in-cluster ENDPOINT was wrong on the same axis and
also on the port. Both the s3-gateway branch and the filer-S3 branch
rendered a portless URL that defaults to 443, while the s3 service only
listens on the S3 port (8333); the filer branch additionally targeted
the filer service, which serves no S3. Both in-cluster branches now
resolve seaweedfs-s3 on the configured S3 port.
The default path (s3.ingress.enabled=true) is repaired by the ingress
fix; the COSI in-cluster paths are latent until an operator disables the
ingress. Resolve every consumer through the same name helper the Service
uses, and pin the contract with unittests rendered under the production
release name so the mismatch cannot recur.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit 8a14de9abf)
backupstrategy-controller creates the cozy-backups Bucket into the
tenant-root namespace, which cozystack-basics provisions. On a fresh
install the Bucket patch can race namespace creation and fail with
`namespaces "tenant-root" not found`, which then races the install
wait deadline and fails the run — on changes that have nothing to do
with backup ordering. Add the cozystack-basics dependsOn edge so the
target namespace exists first, pinned with a helm-unittest regression
guard.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
(cherry picked from commit ee853b00bd)
entityOperator.topicOperator/userOperator carried no resources, so in tenant
namespaces (the LimitRange defaults containers to 128Mi) the JVM topic-operator
and user-operator are OOMKilled on startup. The entity-operator stays in
CrashLoopBackOff, KafkaTopics/KafkaUsers never reconcile, and on teardown topics
get stuck on the strimzi.io/topic-operator finalizer. Set explicit requests/limits
(256Mi/512Mi) so they no longer inherit the namespace default; add a template test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
(cherry picked from commit 1ab5f17cac)