Compare commits

..

260 Commits

Author SHA1 Message Date
Andrei Kvapil
d2ac669b29 fix(platform): correct cozy-proxy releaseName to avoid conflict with installer (#2127)
## What this PR does

Fixes cozy-proxy `releaseName` from `cozystack` to `cozy-proxy` in
paas-full and
distro-full bundles.

The cozy-proxy component was incorrectly configured with `releaseName:
cozystack`,
which is the same name used by the installer helm release. During
upgrade to v1.0,
the cozy-proxy HelmRelease reconciles and overwrites the installer
release, deleting
the cozystack-operator deployment.

### Release note

```release-note
[platform] Fix cozy-proxy releaseName collision with installer that caused operator deletion during v1.0 upgrade
```
2026-03-02 12:57:26 +01:00
Andrei Kvapil
e7bfa9b138 fix(platform): correct cozy-proxy releaseName to avoid conflict with installer
The cozy-proxy component was incorrectly configured with
releaseName: cozystack, which collides with the installer helm release
name. This causes the cozy-proxy HelmRelease to overwrite the installer
release during upgrade to v1.0, deleting the cozystack-operator.

Change releaseName from "cozystack" to "cozy-proxy" in both paas-full
and distro-full bundles.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-03-02 12:55:22 +01:00
Andrei Kvapil
d5a5d31354 Release v0.41.9 (#2078)
This PR prepares the release `v0.41.9`.
2026-02-21 21:48:10 +01:00
cozystack-bot
dd67bd56c4 Prepare release v0.41.9
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-02-21 01:37:37 +00:00
Andrei Kvapil
513b2e20df Update Kube-OVN to v1.15.3
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-02-20 10:51:09 +01:00
Andrei Kvapil
8d8f7defd7 fix(cozystack-basics) Deny resourcequotas deletion for tenant admin (#2076)
<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
Fixed cozy:tenant:admin:base ClusterRole to deny deletion of tenant ResourceQuotas for the tenant admin and superadmin
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

* **Bug Fixes**
* Removed resource quota management permissions from tenant admin role
to reduce unnecessary administrative access.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-20 10:28:12 +01:00
Andrei Kvapil
7bcc3a3d01 Release v0.41.8 (#2029)
This PR prepares the release `v0.41.8`.
2026-02-11 17:09:01 +01:00
cozystack-bot
ff10d684da Prepare release v0.41.8
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-02-11 11:20:45 +00:00
Andrei Kvapil
dfb280d091 [Backport release-0.41] [dashboard] Add startupProbe to prevent container restarts on slow hardware (#2014)
# Description
Backport of #1996 to `release-0.41`.
2026-02-10 12:30:39 +01:00
Andrei Kvapil
32b1bc843a [Backport release-0.41] [vm] allow switching between instancetype and custom resources (#2013)
# Description
Backport of #2008 to `release-0.41`.
2026-02-10 12:30:11 +01:00
Andrei Kvapil
2c87a83949 [Backport release-0.41] feat(kubernetes): auto-enable Gateway API support in cert-manager (#2012)
# Description
Backport of #1997 to `release-0.41`.
2026-02-10 12:29:57 +01:00
Andrei Kvapil
a53df5eb90 fix(dashboard): add startupProbe to prevent container restarts on slow hardware
Kubelet kills bff and web containers on slow hardware because the
livenessProbe only allows 33 seconds for startup. Add startupProbe
with failureThreshold=30 and periodSeconds=2, giving containers up
to 60 seconds to start before livenessProbe kicks in.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
(cherry picked from commit 330cbe70d4)
2026-02-10 11:22:41 +00:00
Kirill Ilin
b212dc02f3 [vm] add validation for resources
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit 13d848efc3)
2026-02-10 11:20:54 +00:00
Kirill Ilin
ec50052ea4 [vm] allow switching between instancetype and custom resources
Implemented by upgrade hook atomically patching VM resource

Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit cf2c6bc15f)
2026-02-10 11:20:54 +00:00
Andrei Kvapil
9b61d1318c feat(kubernetes): auto-enable Gateway API support in cert-manager
When the Gateway API addon is enabled, automatically configure
cert-manager with enableGatewayAPI: true. Uses the same default
values + mergeOverwrite pattern as Cilium for consistency.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
(cherry picked from commit 90ac6de475)
2026-02-10 11:20:04 +00:00
Andrei Kvapil
1c3a5f721c Release v0.41.7 (#1995)
This PR prepares the release `v0.41.7`.
2026-02-06 08:56:31 +01:00
cozystack-bot
6274f91c74 Prepare release v0.41.7
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-02-06 01:40:42 +00:00
Andrei Kvapil
f347b4fd70 [Backport release-0.41] fix(postgres-operator): correct PromQL syntax in CNPGClusterOffline alert (#1989)
# Description
Backport of #1981 to `release-0.41`.
2026-02-05 20:34:33 +01:00
mattia-eleuteri
40d51f4f92 fix(postgres-operator): correct PromQL syntax in CNPGClusterOffline alert
Remove extra closing parenthesis in the CNPGClusterOffline alert expression
that causes vmalert pods to crash with "bad prometheus expr" error.

Signed-off-by: mattia-eleuteri <mattia@hidora.io>
(cherry picked from commit 2cb299e602)
2026-02-05 19:25:36 +00:00
Andrei Kvapil
38c73ae3bd [Backport release-0.41] [dashboard] Verify JWT token (#1983)
# Description
Backport of #1980 to `release-0.41`.
2026-02-05 09:39:31 +01:00
Timofei Larkin
0496a1b0e8 [dashboard] Verify JWT token
## What this PR does

When OIDC is disabled, the dashboard's token-proxy now properly
validates bearer tokens against the k8s API's JWKS url.

### Release note

```release-note
[dashboard] Verify bearer tokens against the issuer's JWKS url.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
(cherry picked from commit 23e399bd9a)
2026-02-04 15:11:15 +00:00
Andrei Kvapil
b49a6d1152 Release v0.41.6 (#1979)
This PR prepares the release `v0.41.6`.
2026-02-04 04:02:38 +01:00
cozystack-bot
0dac208d43 Prepare release v0.41.6
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-02-04 01:41:27 +00:00
Andrei Kvapil
30adc52ce3 [Backport release-0.41] fix coredns serviceaccount to match kubernetes bootstrap rbac (#1978)
# Description
Backport of #1958 to `release-0.41`.
2026-02-04 02:04:27 +01:00
mattia-eleuteri
044dae0d1e fix coredns serviceaccount to match kubernetes bootstrap rbac
The Kubernetes bootstrap creates a ClusterRoleBinding 'system:kube-dns'
that references ServiceAccount 'kube-dns' in 'kube-system'. However,
the coredns chart was using the 'default' ServiceAccount because
serviceAccount.create was not enabled.

This caused CoreDNS pods to fail with 'Failed to watch' errors after
restarts, as they lacked RBAC permissions to watch the Kubernetes API.

Configure the chart to create the 'kube-dns' ServiceAccount, which
matches the expected binding from Kubernetes bootstrap.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: mattia-eleuteri <mattia@hidora.io>
(cherry picked from commit 7320edd71d)
2026-02-04 01:02:13 +00:00
Andrei Kvapil
26e083a71e [Backport release-0.41] [1.0][branding] Separate values for keycloak (#1963)
# Description
Backport of #1947 to `release-0.41`.
2026-02-03 13:05:54 +01:00
Andrei Kvapil
8468711545 [Backport release-0.41] [vm] allow changing field external after creation (#1962)
# Description
Backport of #1956 to `release-0.41`.
2026-02-03 13:05:44 +01:00
Andrei Kvapil
462ab1bdcb Release v0.41.5 (#1936)
This PR prepares the release `v0.41.5`.
2026-02-03 08:35:52 +01:00
cozystack-bot
a3821162af Prepare release v0.41.5
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-02-03 01:39:08 +00:00
Andrei Kvapil
0838bafdb9 [Backport release-0.41] fix manifests for kubernetes deployment (#1945)
# Description
Backport of #1943 to `release-0.41`.
2026-02-02 22:08:03 +01:00
Andrei Kvapil
9723992410 [0.41][branding] Separate values for keycloak (#1946)
## What this PR does
Adds separate values to keycloak branding.

### Release note
```release-note
Added separate values to keycloak branding
```
2026-02-02 22:07:08 +01:00
nbykov0
3b904d83a8 [branding] Separate values for keycloak
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
(cherry picked from commit 8a034c58b1)
2026-02-02 21:06:57 +00:00
Kirill Ilin
96b801b06b [vm] allow changing field external after creation
Service will be recreated

Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit 3a8e8fc290)
2026-02-02 21:05:22 +00:00
Andrei Kvapil
4048234b9d [Backport release-0.41] Add instance profile label to workload monitor (#1957)
# Description
Backport of #1954 to `release-0.41`.
2026-02-02 22:04:28 +01:00
Timofei Larkin
b8d32fb894 Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
(cherry picked from commit 09cd9e05c3)
2026-02-02 14:15:16 +00:00
Matthieu ROBIN
eae630ffb5 Update internal/controller/workloadmonitor_controller.go
Co-authored-by: Timofei Larkin <lllamnyp@gmail.com>
Signed-off-by: Matthieu ROBIN <info@matthieurobin.com>
(cherry picked from commit 3f59ce4876)
2026-02-02 14:15:16 +00:00
Matthieu ROBIN
c514d7525b Add instance profile label to workload monitor
Signed-off-by: Matthieu ROBIN <info@matthieurobin.com>
(cherry picked from commit 1e8da1fca4)
2026-02-02 14:15:16 +00:00
nbykov0
d0bb00f3cd [branding] Separate values for keycloak
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2026-02-02 12:51:05 +03:00
IvanHunters
6db4bb15d2 fix manifests for kubernetes deployment
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
(cherry picked from commit 281715b365)
2026-02-02 09:33:24 +00:00
Andrei Kvapil
4f3502456f [Backport release-0.41] [dashboard] Add resource quota usage to tenant details page (#1932)
# Description
Backport of #1929 to `release-0.41`.
2026-01-29 10:31:39 +01:00
Andrei Kvapil
8d803cd619 [Backport release-0.41] [dashboard] Add "Edit" button to all resources (#1931)
# Description
Backport of #1928 to `release-0.41`.
2026-01-29 10:31:28 +01:00
Kirill Ilin
7ebcc0d264 [dashboard] Add resource quota usage to tenant info resource
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit 9e63bd533c)
2026-01-29 09:30:42 +00:00
Kirill Ilin
21e7183375 [dashboard] Add "Edit" button to all resources
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit a56fc00c5c)
2026-01-29 09:29:12 +00:00
Andrei Kvapil
760c732ed6 Release v0.41.4 (#1926)
This PR prepares the release `v0.41.4`.
2026-01-29 10:08:40 +01:00
cozystack-bot
c7e54262f1 Prepare release v0.41.4
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-01-29 01:39:21 +00:00
Andrei Kvapil
6d772811dd Update cozyhr v1.6.1
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-01-27 23:10:34 +01:00
Andrei Kvapil
c8dbad7dc9 Release v0.41.3 (#1916)
This PR prepares the release `v0.41.3`.
2026-01-27 18:56:59 +01:00
Andrei Kvapil
f54a1e6911 [Backport release-0.41] [dashboard] Improve dashboard session params (#1920)
# Description
Backport of #1913 to `release-0.41`.
2026-01-27 18:56:38 +01:00
Timofei Larkin
ca3d5e1a5b [dashboard] Improve dashboard session params
## What this PR does

This patch enables the `offline_access` scope for the dashbord keycloak
client, so that users get a refresh token which gatekeeper can use to
automatically refresh an expiring access token. Also session timeouts
were increased.

### Release note

```release-note
[dashboard] Increase session timeouts, add the offline_access scope,
enable refresh tokens to improve the overall user experience when
working with the dashboard.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
(cherry picked from commit 7cebafbafd)
2026-01-27 17:18:43 +00:00
cozystack-bot
e67aed0e6c Prepare release v0.41.3
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-01-27 01:37:01 +00:00
Andrei Kvapil
0129f20ae4 [Backport release-0.41] [kubernetes] show Service and Ingress resources for kubernetes app in… (#1915)
# Description
Backport of #1912 to `release-0.41`.
2026-01-26 18:36:14 +01:00
Andrei Kvapil
58e2b4c632 [Backport release-0.41] [dashboard] Fix filtering on Pods tab for Service (#1914)
# Description
Backport of #1909 to `release-0.41`.
2026-01-26 18:36:05 +01:00
Kirill Ilin
056a0d801e [kubernetes] show Service and Ingress resources for kubernetes app in dashboard
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit befbdf0964)
2026-01-26 17:35:10 +00:00
Kirill Ilin
f8b2aa8343 [dashboard] Fix filtering on Pods tab for Service
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit ee759dd11e)
2026-01-26 17:33:29 +00:00
Andrei Kvapil
f1f1ff5681 Release v0.41.2 (#1907)
This PR prepares the release `v0.41.2`.
2026-01-23 09:07:49 +01:00
cozystack-bot
d4ffce1ff6 Prepare release v0.41.2
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-01-23 01:34:38 +00:00
Andrei Kvapil
a24174a0c3 [Backport release-0.41] [monitoring-agents] Set minReplicas to 1 for VPA for VMAgent (#1905)
# Description
Backport of #1894 to `release-0.41`.
2026-01-22 23:18:11 +01:00
Kirill Ilin
d91f1f1882 [monitoring-agents] Set minReplicas to 1 for VPA for VMAgent
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit 207a5171f0)
2026-01-22 22:17:25 +00:00
Andrei Kvapil
e38b7a0afd [Backport release-0.41] [mongodb] Remove user-configurable images from MongoDB chart (#1904)
# Description
Backport of #1901 to `release-0.41`.
2026-01-22 23:16:34 +01:00
Andrei Kvapil
247e19252f [mongodb] Remove user-configurable images from MongoDB chart
Remove the ability for users to specify custom container images
(images.pmm and images.backup) in the MongoDB application values.

This is a security hardening measure - allowing users to specify
arbitrary container images could lead to running malicious or
compromised images, supply chain attacks, or privilege escalation.

The images are now hardcoded in the template:
- percona/pmm-client:2.44.1
- percona/percona-backup-mongodb:2.11.0

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
(cherry picked from commit beb6e1a0ba)
2026-01-22 22:15:29 +00:00
Andrei Kvapil
211d57b17a Release v0.41.1 (#1900)
This PR prepares the release `v0.41.1`.
2026-01-22 09:14:27 +01:00
cozystack-bot
6d3f5bbc60 Prepare release v0.41.1
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-01-22 01:34:35 +00:00
Andrei Kvapil
4532603bbd [Backport release-0.41] [kubernetes] Add enum validation for IngressNginx exposeMethod (#1897)
# Description
Backport of #1895 to `release-0.41`.
2026-01-21 13:55:36 +01:00
Kirill Ilin
73cd3edbb7 [kubernetes] Add enum validation for IngressNginx exposeMethod
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit 0b95a72fa3)
2026-01-21 12:55:19 +00:00
Andrei Kvapil
ea466820fc Release v0.41.0 (#1889)
This PR prepares the release `v0.41.0`.
2026-01-20 03:32:28 +01:00
cozystack-bot
31422aba38 Prepare release v0.41.0
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-01-20 01:21:24 +00:00
Andrei Kvapil
8f6a09bca5 [Backport release-0.41][apps] Add MongoDB managed application (#1881)
# Description
Backport of #1822 to `release-0.40`.
2026-01-20 02:15:08 +01:00
Andrei Kvapil
d13a45c8d6 Update Talos Linux v1.11.6 (#1879)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does

This PR updates Talos Linux which includes DRBD fixes:
- https://github.com/LINBIT/drbd/releases/tag/drbd-9.2.15
- https://github.com/LINBIT/drbd/releases/tag/drbd-9.2.16

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
Update Talos Linux v1.11.
```
2026-01-20 01:54:40 +01:00
Andrei Kvapil
6b3cd40ba5 [Backport release-0.40] [fix] Fix view of loadbalancer ip in services window (#1887)
# Description
Backport of #1884 to `release-0.40`.
2026-01-20 01:54:17 +01:00
IvanHunters
838d1abff6 [fix] Fix view of loadbalancer ip in services window
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
(cherry picked from commit 5c7c3359b3)
2026-01-20 00:48:39 +00:00
Andrei Kvapil
4cdd1113d1 [Backport release-0.40] fix(kubernetes): increase kube-apiserver startup probe threshold (#1883)
# Description
Backport of #1876 to `release-0.40`.
2026-01-19 20:13:03 +01:00
Andrei Kvapil
4d7ee809e5 [Backport release-0.40] [kubernetes] Increase default apiServer resourcesPreset to large (#1882)
# Description
Backport of #1875 to `release-0.40`.
2026-01-19 20:12:53 +01:00
Andrei Kvapil
125a57eb97 fix(kubernetes): increase kube-apiserver startup probe threshold
Increase startupProbe.failureThreshold from 3 to 30 for kube-apiserver
container. The default 30 seconds (3 failures * 10s period) is often
insufficient for apiserver to complete RBAC bootstrap, especially under
load or with slower etcd connections.

This change gives kube-apiserver up to 300 seconds to initialize,
preventing unnecessary CrashLoopBackOff cycles.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
(cherry picked from commit 8261ea4fcf)
2026-01-19 19:12:43 +00:00
Andrei Kvapil
d33a2357ed fix(kubernetes): increase default apiServer resourcesPreset to large
Change the default resourcesPreset for kube-apiserver from "medium" to
"large" to prevent OOM kills during normal operation. The "medium"
preset provides insufficient memory for clusters with moderate workloads.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
(cherry picked from commit 6256893040)
2026-01-19 19:12:33 +00:00
Aleksei Sviridkin
6ce60917c7 feat(apps): add MongoDB managed application
Add MongoDB managed service based on Percona Operator for MongoDB with:

- Replica set mode (default) and sharded cluster mode
- Configurable replicas, storage, and resource presets
- Custom users with role-based access control
- S3-compatible backup with PITR support
- Bootstrap/restore from backup
- External access support
- WorkloadMonitor integration for dashboard
- Comprehensive helm-unittest test coverage (91 tests)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-01-19 13:45:57 +01:00
Andrei Kvapil
a8a7e510ac [Backport release-0.40] [etcd] Increase probe thresholds for better recovery (#1878)
# Description
Backport of #1874 to `release-0.40`.
2026-01-19 13:13:49 +01:00
Andrei Kvapil
cf0598bcf1 Update Talos Linux v1.11.6
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-01-19 11:01:48 +01:00
Andrei Kvapil
6169220317 fix(etcd): increase probe thresholds for better recovery
Increase startup probe failureThreshold to 300 (25 minutes) to allow
etcd members more time to sync with the cluster after restart or
recovery. This prevents pods from being killed during initial
synchronization when VPA assigns minimal resources.

Also increase liveness probe failureThreshold to 10 to reduce
unnecessary restarts during temporary network issues.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
(cherry picked from commit c58c959df6)
2026-01-19 09:56:16 +00:00
Andrei Kvapil
fbe33e1191 Release v0.40.3 (#1871)
This PR prepares the release `v0.40.3`.
2026-01-19 09:04:37 +01:00
cozystack-bot
9507f24332 Prepare release v0.40.3
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-01-19 01:34:56 +00:00
Andrei Kvapil
2aa839b68f [Backport release-0.40] [cilium] Update cilium to v1.18.6 (#1870)
# Description
Backport of #1868 to `release-0.40`.
2026-01-16 20:49:18 +01:00
Kirill Ilin
40683e28a7 [cilium] Update cilium to v1.18.6
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit 464b6b3bb6)
2026-01-16 19:15:21 +00:00
Andrei Kvapil
4ddb374680 [apiserver] Fix Watch resourceVersion and bookmark handling (#1860)
Fixes aggregated API server Watch implementation to properly work with
controller-runtime informers. External controllers watching Tenant
resources via the aggregated API were experiencing issues with cache
sync timeouts and missing reconciliations on startup.

**ResourceVersion handling in List:**
- Compute ResourceVersion from items when the cached client doesn't set
it on the list itself

**Bookmark handling:**
- Pass through bookmark events with converted types for proper informer
sync

**ADDED event filtering (main fix):**
- Simplified the filtering logic that was incorrectly skipping initial
events
- Only skip ADDED events when `startingRV > 0` AND `objRV <= startingRV`
(client already has from List)
- When `startingRV == 0`, always send ADDED events (client wants full
state)
- Removed the complex `initialSyncComplete` tracking that had inverted
logic

When a controller starts watching resources, controller-runtime may call
Watch with `resourceVersion=""`. The server should send all existing
objects as ADDED events. The previous `initialSyncComplete` logic was
inverted and could skip these events, causing objects (like Tenants with
lock annotations) to not be reconciled on controller startup.

```release-note
[apiserver] Fix Watch resourceVersion and bookmark handling for controller-runtime compatibility
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

* **Improvements**
* Enhanced resource watching and synchronization with Kubernetes 1.27+
compatibility, including proper handling of initial events and
bookmarks.
* Optimized event filtering and resource version tracking for
applications, tenant modules, tenant namespaces, and tenant secrets to
reduce unnecessary event noise.
* Improved list metadata consistency by deriving accurate resource
versions when unavailable in responses.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-16 17:23:38 +01:00
Andrei Kvapil
e07fafb393 Release v0.40.2 (#1858)
This PR prepares the release `v0.40.2`.
2026-01-13 17:22:13 +01:00
cozystack-bot
7b932a400d Prepare release v0.40.2
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-01-13 12:32:18 +00:00
Andrei Kvapil
8f317c9065 [Backport release-0.40] [linstor] Refactor node-level RWX validation (#1857)
# Description
Backport of #1856 to `release-0.40`.
2026-01-13 13:28:11 +01:00
Andrei Kvapil
e73bf9905d [linstor] Refactor node-level RWX validation
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
(cherry picked from commit 3c4f0cd952)
2026-01-13 12:27:52 +00:00
Andrei Kvapil
c5222aae97 [linstor] Remove node-level RWX validation (#1851)
## What this PR does

Removes node-level RWX block validation from linstor-csi as
controller-level check is sufficient. The controller already validates
that all pods attached to RWX block volume belong to the same VM by
extracting vmName from pod owner references (VirtualMachineInstance).

This simplifies the validation logic and fixes VM live migration issues.

### Release note

```release-note
[linstor] Remove node-level RWX block validation to fix VM live migration
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Improvements**
* Enhanced RWX (read-write-many) block validation with VM-aware checks
across node and controller flows, including support for hotplug-disk
pods and stricter prevention of cross-VM block sharing.
* Improved propagation and resolution of VM identity for attachments to
ensure consistent validation.

* **Tests**
* Added comprehensive unit tests covering single/multiple pod scenarios,
VM ownership, hotplug disks, upgrade paths, and legacy volumes.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-13 11:28:03 +01:00
Andrei Kvapil
e176cdec87 feat(linstor): add linstor-csi image build with RWX validation
Add custom linstor-csi image build to packages/system/linstor:

- Add Dockerfile based on upstream linstor-csi
- Import patch from upstream PR #403 for RWX block volume validation
  (prevents misuse of allow-two-primaries in KubeVirt live migration)
- Update Makefile to build both piraeus-server and linstor-csi images
- Configure LinstorCluster CR to use custom linstor-csi image in
  CSI controller and node pods

The RWX validation patch ensures that RWX block volumes with
allow-two-primaries are only used by pods belonging to the same
KubeVirt VM during live migration.

Upstream PR: https://github.com/piraeusdatastore/linstor-csi/pull/403

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-01-13 11:27:55 +01:00
Andrei Kvapil
477d391440 Release v0.40.1 (#1855)
This PR prepares the release `v0.40.1`.
2026-01-13 08:04:35 +01:00
cozystack-bot
9ba76d4839 Prepare release v0.40.1
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-01-13 01:39:20 +00:00
Andrei Kvapil
f5ccbe94f9 [Backport release-0.40] [linstor] Update piraeus-server patches with critical fixes (#1852)
# Description
Backport of #1850 to `release-0.40`.
2026-01-12 23:23:59 +01:00
Andrei Kvapil
f900db6338 [linstor] Update piraeus-server patches with critical fixes
Update piraeus-server patches to address critical production issues:

- Add fix-duplicate-tcp-ports.diff to prevent duplicate TCP ports
  after toggle-disk operations (upstream PR #476)

- Update skip-adjust-when-device-inaccessible.diff with comprehensive
  fixes for resources stuck in StandAlone after reboot, Unknown state
  race condition, and encrypted LUKS resource deletion (upstream PR #477)

```release-note
[linstor] Fix DRBD resources stuck in StandAlone state after reboot and encrypted resource deletion issues
```

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
(cherry picked from commit dc2773ba26)
2026-01-12 22:23:42 +00:00
Andrei Kvapil
3bcc0e5cc0 Release v0.40.0 (#1840)
This PR prepares the release `v0.40.0`.
2026-01-10 03:06:55 +01:00
cozystack-bot
2a8317291d Prepare release v0.40.0
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2026-01-10 00:57:35 +00:00
Andrei Kvapil
acc6ed26bb fix(platform): fix migrations for v0.40 release (#1846)
## What this PR does

Fixes migration scripts for v0.40 release to ensure smooth upgrade
process.

Changes:
- **Migration 20**: Replace `helm upgrade --install` with `cozyhr apply`
for cozystack-controller and lineage-controller-webhook
- **Migration 21**: Improve Flux instance removal process:
  - Disable reconciliation on FluxInstance before deletion
  - Delete Flux deployments before HelmReleases
  - Add `--wait=false` flags to prevent hanging
  - Fix CRD grep pattern to properly match `fluxcd.io` domains
- **Migration 22**: Add new migration tasks:
- Migrate Victoria Metrics Operator CRDs to prometheus-operator-crds
Helm release
  - Remove CozyStack Resource Definitions HelmRelease
- Add default version v17 to PostgreSQL HelmReleases without explicit
version

### Release note

```release-note
[platform] Fix migration scripts for v0.40 release: improve Flux removal, add VictoriaMetrics CRD migration, set default PostgreSQL version
```
2026-01-10 01:52:12 +01:00
Andrei Kvapil
3af7430074 fix(registry): implement field selector filtering for label-based resources (#1845)
## What this PR does

Fixes field selector filtering for registry resources (Applications,
TenantModules, TenantSecrets) when using kubectl with field selectors
like `--field-selector=metadata.namespace=tenant-kvaps` or
`metadata.name=test`.

Controller-runtime cache doesn't support field selectors natively, which
caused incorrect filtering behavior. This PR implements manual filtering
for `metadata.name` and `metadata.namespace` field selectors in List()
and Watch() methods.

Changes:
- Created `pkg/registry/fields` package with `ParseFieldSelector`
utility for common field selector parsing
- Refactored field selector logic in application, tenantmodule, and
tenantsecret registries to use the common implementation
- Implemented manual post-processing filtering after label-based queries
- Removed `Raw` field usage and field selectors from
`client.ListOptions`

### Release note

```release-note
[registry] Fix field selector filtering for kubectl queries with metadata.name and metadata.namespace selectors
```
2026-01-10 01:52:08 +01:00
Andrei Kvapil
800ca3b3d2 [main][paas-full] Add multus dependencies similar to other CNIs (#1842)
Adds multus as a dependency as other CNIs

```release-note
Adds multus as a dependency as other CNIs
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

* **Chores**
* Updated component initialization ordering to ensure more consistent
and reliable platform startup sequencing.
* Streamlined dependency requirements for several core system components
to improve deployment reliability and reduce startup complexity.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-10 01:50:06 +01:00
Andrei Kvapil
4a83d2c7c8 [platform] fix migration for removing fluxcd-operator
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-01-09 16:24:42 +01:00
Andrei Kvapil
c0b1539d3e [kube-ovn] Update to v1.14.25 (#1819)
## What this PR does

Update kube-ovn from v1.14.11 to v1.14.25.

Changes synced from upstream include:
- Updated chart templates
- New configuration options in values

### Release note

```release-note
[kube-ovn] Update to v1.14.25
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Added tolerations support for VpcNatGateway resources
* Added automatic VLAN subinterface creation capability for provider
networks
* Enhanced installation documentation with OCI Registry and Talos Linux
deployment examples

* **Security Improvements**
  * Applied runtime-default seccomp profiles across deployments
* Configured service account token mounting behavior for improved pod
security

* **Chores**
  * Updated Kube-OVN to v1.14.25
  * Updated Helm chart metadata and dependencies

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:03 +01:00
Andrei Kvapil
1c42f8bd10 [linstor] fix: prevent DRBD device race condition in updateDiscGran (#1829)
## Problem

After satellite restart with patched linstor-server, some DRBD resources
ended up in **Unknown** state. Investigation revealed a race condition
between `drbdadm adjust` completion and `updateDiscGran()` lsblk check:

1. `drbdadm adjust` completes successfully (21:53:49.791) - brings
devices up
2. `updateDiscGran()` immediately tries to check discard granularity
(21:53:49.799)
3. `/dev/drbd*` device node doesn't exist yet - kernel hasn't created it
4. `lsblk` fails with exit code 32: "not a block device"  
5. `StorageException` interrupts DeviceManager cycle (21:53:50.811)
6. DRBD device remains in incomplete state → **Unknown**

### Timeline from logs

```
21:53:49.791 - [DeviceManager] Resource 'pvc-aafbd92a' [DRBD] adjusted ✓
21:53:49.799 - [lsblk_parser] ERROR: /dev/drbd1169 not a block device
21:53:49.804-50.807 - [lsblk_parser] 10+ retry errors (every ~100ms)
21:53:50.811 - [DeviceManager] ERROR: Error executing lsblk
21:53:50.878 - [DeviceManager] End cycle 9 (WITH ERROR!)
```

## Solution

Update `skip-adjust-when-device-inaccessible.diff` patch to add physical
device path existence check before calling `lsblk`:

- Check `Files.exists(devicePath)` in `updateDiscGran()` before lsblk
- If device doesn't exist yet → skip check, set `discGran =
UNINITIALIZED_SIZE`
- Next DeviceManager cycle (few seconds later) → device node available →
lsblk succeeds

This complements the existing patch which checks **child layer** devices
(LUKS/Storage) for deletion scenarios, while this fix addresses the
**DRBD device itself** during adjust operations.

## Testing

Manual `drbdadm up` on affected devices confirmed they were in down
state and brought them back to UpToDate, proving the issue was
incomplete device initialization.

## Related

- Upstream linstor-server PR:
https://github.com/LINBIT/linstor-server/pull/471#issuecomment-3723392917

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Enhanced robustness for storage operations by adding device
accessibility validation. Operations now gracefully skip when device
paths are unavailable or invalid, preventing unnecessary failures and
improving system resilience during device access issues.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:03 +01:00
Timofei Larkin
de2bbd35c2 [keycloak] Make kubernetes client public (#1802)
## What this PR does

By its nature, the kubernetes client provisioned in keycloak is public:
anyone can read the client secret. Therefore the secret is not necessary
and the client should be explicitly provisioned as a public client, not
as a confidential client.

### Release note

```release-note
[keycloak] Change the kubernetes client to be public, without a client
secret.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Add OIDC enablement flag and optional host derivation from tenant
release; allow explicit management kubeconfig endpoint override.

* **Refactor**
* Convert Keycloak client to public mode and remove reliance on a
Kubernetes client secret, simplifying authentication configuration.
* Remove secret-based credential plumbing from deployment templates,
streamlining kubeconfig generation.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:03 +01:00
Andrei Kvapil
fe82f66330 [linstor] Enable auto-diskful for diskless nodes (#1826)
## What this PR does

Enable DRBD auto-diskful options to automatically convert diskless nodes
to diskful when they remain in Primary state for an extended period.

### How it works

When LINSTOR is integrated with Kubernetes, the platform may schedule
workloads on nodes that don't have local storage replicas. In such
cases, DRBD operates in "diskless" mode, accessing data over the network
from nodes that have actual disk replicas.

The `auto-diskful` feature addresses this by:

1. **Monitoring Primary state duration**: When a diskless node holds a
DRBD resource in Primary state (actively using the volume) for more than
the configured time (30 minutes), LINSTOR automatically creates a local
disk replica on that node.

2. **Automatic cleanup**: With `auto-diskful-allow-cleanup` enabled,
when the resource is no longer in Primary state on that node, LINSTOR
can automatically remove the disk replica that was created, freeing up
storage space.

### Configuration

- `DrbdOptions/auto-diskful: 30` — Convert diskless to diskful after 30
minutes in Primary state
- `DrbdOptions/auto-diskful-allow-cleanup: true` — Allow automatic
removal of auto-created replicas when no longer needed

### Benefits

- Improves I/O performance for long-running workloads by creating local
replicas
- Reduces network traffic for frequently accessed data
- Automatic cleanup prevents storage waste from temporary replicas

### Release note

```release-note
[linstor] Enable auto-diskful to automatically create local replicas on diskless nodes that hold volumes in Primary state for more than 30 minutes, improving I/O performance for long-running workloads.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Introduced an "auto diskful" option to automatically manage diskful
resources with configurable interval and optional cleanup.
* **Chores**
* Added default configuration values to enable and time the auto-diskful
behavior and to control automatic cleanup.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:03 +01:00
Andrei Kvapil
c4bf72b44f [linstor] Add linstor-scheduler package (#1824)
## What this PR does

Add linstor-scheduler-extender for optimal pod placement on nodes with
LINSTOR storage.

### How it works

The linstor-scheduler consists of two components:

#### 1. Scheduler Extender
A custom Kubernetes scheduler that works alongside the default
kube-scheduler. When a pod requests LINSTOR-backed storage, the
scheduler extender communicates with the LINSTOR controller to find
nodes that have local replicas of the requested volumes, prioritizing
placement on nodes with existing data to minimize network traffic.

#### 2. Admission Webhook
A MutatingWebhookConfiguration that automatically sets `schedulerName:
linstor-scheduler` on pods that use LINSTOR CSI driver volumes. This
ensures that only pods with LINSTOR PVCs are routed through the custom
scheduler, while all other pods continue using the default scheduler.

The webhook inspects pod creation requests and checks if any of the
pod's PVCs use a StorageClass with the LINSTOR CSI provisioner
(`linstor.csi.linbit.com`). If so, it mutates the pod spec to use the
linstor-scheduler.

### Components

- `linstor-scheduler` package in `packages/system/linstor-scheduler/`
- PackageSource definition in
`packages/core/platform/sources/linstor-scheduler.yaml`
- Integration into `paas-full` and `distro-full` bundles

### Upstream PRs

- https://github.com/piraeusdatastore/helm-charts/pull/67 — fix:
KubeSchedulerConfiguration v1 support for Kubernetes 1.25+
- https://github.com/piraeusdatastore/helm-charts/pull/68 — feat:
admission webhook support with cert-manager
- https://github.com/piraeusdatastore/helm-charts/pull/69 — fix chart
template issues

### Release note

```release-note
[linstor] Add linstor-scheduler for optimal pod placement on nodes with local LINSTOR replicas. Includes admission webhook that automatically routes pods using LINSTOR CSI volumes to the custom scheduler.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added LINSTOR scheduler component to the platform, packaged as a Helm
chart and installable package.
* Includes admission webhook, scheduler extender, autoscaling support,
pod disruption budget, RBAC and service account integration, and Helm
test hooks.
* **Documentation**
* Added chart README and default configuration values for easy
deployment and customization.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:02 +01:00
Nikita
33452d65e5 [seaweedfs] Traffic locality (#1748)
## What this PR does
Addes traffic locality capabilities to Seaweedfs.

### Release note
```release-note
Added traffic locality capabilities to Seaweedfs
2026-01-09 14:54:02 +01:00
Andrei Kvapil
9039011252 [api, lineage] Tolerate all taints (#1781)
## What this PR does
Cozystack-api and lineage-webhook tolerate all taints, so they are able
to run on masters no matter what.
Needed for unschedulable control-plane setup, quorum nodes, etc.

### Release note
```release-note
Cozystack-api and lineage-webhook tolerate all taints.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated pod scheduling tolerations to improve deployment flexibility
and compatibility across diverse cluster configurations.
* Enhanced workload distribution by making pods more resilient to
cluster taints, enabling better resource utilization in various
environments.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:02 +01:00
Andrei Kvapil
2bbeb1b474 fix(linstor): prevent orphaned DRBD devices during toggle-disk retry (#1823)
## Summary

Fix bug in toggle-disk retry logic that left orphaned DRBD devices in
kernel.

## Problem

When toggle-disk retry was triggered (e.g., user retries after a failed
operation), the code called `removeLayerData()` to clean up and recreate
the layer stack. However, `removeLayerData()` only removes data from the
controller's database — it does NOT call `drbdadm down` on the
satellite.

This caused DRBD devices to remain in the kernel (visible in `drbdsetup`
but not managed by LINSTOR), occupying ports and blocking subsequent
operations.

## Solution

Changed retry logic to simply repeat the operation with existing layer
data intact. The satellite handles this idempotently without creating
orphaned resources.

## Upstream

- https://github.com/LINBIT/linstor-server/pull/475 (updated)

```release-note
[linstor] Fix orphaned DRBD devices during toggle-disk retry
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Added cancel and retry capabilities for disk addition operations
  * Added cancel and retry capabilities for disk removal operations
* Improved cleanup handling for diskless resources with orphaned storage
layers

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:02 +01:00
Andrei Kvapil
a51e2078a8 [linstor] Build linstor-server with custom patches (#1726)
## What this PR does

Build piraeus-server (linstor-server) from source with custom patches:

- **adjust-on-resfile-change.diff** — Use actual device path in res file
during toggle-disk; fix LUKS data offset
- Upstream: [#473](https://github.com/LINBIT/linstor-server/pull/473),
[#472](https://github.com/LINBIT/linstor-server/pull/472)
- **allow-toggle-disk-retry.diff** — Allow retry and cancellation of
failed toggle-disk operations
  - Upstream: [#475](https://github.com/LINBIT/linstor-server/pull/475)
- **force-metadata-check-on-disk-add.diff** — Create metadata during
toggle-disk from diskless to diskful
  - Upstream: [#474](https://github.com/LINBIT/linstor-server/pull/474)
- **skip-adjust-when-device-inaccessible.diff** — Skip DRBD adjust/res
file regeneration when child layer device is inaccessible
  - Upstream: [#471](https://github.com/LINBIT/linstor-server/pull/471)

Also updates plunger-satellite script and values.yaml for the new build.

### Release note

```release-note
[linstor] Build linstor-server with custom patches for improved disk handling
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added automatic DRBD stall detection and recovery, improving storage
resync resilience without manual intervention.
* Introduced configurable container image references via Helm values for
streamlined deployment.

* **Bug Fixes**
* Enhanced disk toggle operations with retry and cancellation support
for better error handling.
  * Improved metadata creation during disk state transitions.
* Added device accessibility checks to prevent errors when underlying
storage devices are unavailable.
* Fixed LUKS encryption header sizing for consistent deployment across
nodes.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:02 +01:00
Timofei Larkin
e40a95849d [testing] Add aliases and autocomplete (#1803)
## What this PR does

Adds a `k=kubectl` alias and bash completion for kubectl to the
e2e-testing sandbox container to maintainers have an easier time
exec'ing into the CI container when something needs to be debugged.

### Release note

```release-note
[testing] Add k=kubectl alias and enable kubectl completion in the CI
container.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Enhanced the e2e sandbox image to enable shell bash-completion and
kubectl command completion.
* Added an alias (k) and completion wiring for kubectl to improve
interactive command use.
* These changes augment the test environment shell during image build to
provide a smoother developer/testing experience.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:02 +01:00
Andrei Kvapil
31bcbbd5bf [kubernetes] Fix endpoints for cilium-gateway (#1729)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does

Integrate fix
- https://github.com/kubevirt/cloud-provider-kubevirt/pull/379

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[kubernetes] Fix endpoints for cilium-gateway
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved handling of incomplete endpoint data by introducing fallback
detection mechanisms.
* Enhanced service discovery to gather endpoints from all available
resources when standard detection fails.
* Updated logging to provide better visibility into fallback operations
and current resource status.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:01 +01:00
Andrei Kvapil
e7b62ca3c8 [platform] Replace Helm lookup with valuesFrom mechanism (#1787)
## What this PR does

Replaces Helm lookup functions with FluxCD valuesFrom mechanism for
passing configuration to HelmReleases. This provides cleaner config
propagation and eliminates the need for force reconcile controllers.

### Changes:

**Platform/Tenant charts:**
- Add Secret `cozystack-values` creation in platform chart (for
tenant-root and system namespaces)
- Add Secret `cozystack-values` creation in tenant chart (for child
namespaces)

**cozystack-api:**
- Add `valuesFrom` references to HelmRelease when creating applications
- Filter keys starting with `_` when returning Application specs
- Validate that user values don't contain `_` prefixed keys

**cozystack-controller:**
- Add validation that HelmRelease contains correct valuesFrom
configuration
- Remove `CozystackConfigReconciler` (no longer needed)
- Remove `TenantHelmReconciler` (no longer needed)

**Helm charts (40+ files):**
- Add helper templates in cozy-lib for `_cluster`/`_namespace` access
- Replace ConfigMap lookups with `.Values._cluster.*`
- Replace Namespace annotation lookups with `.Values._namespace.*`

### Architecture:

```
Secret cozystack-values (in each namespace)
├── _cluster: YAML with data from ConfigMaps (cozystack, cozystack-branding, cozystack-scheduling)
└── _namespace: YAML with namespace service references (etcd, host, ingress, monitoring, seaweedfs)

HelmRelease
└── spec.valuesFrom:
    ├── Secret/cozystack-values → _namespace → .Values._namespace
    └── Secret/cozystack-values → _cluster → .Values._cluster
```

### Release note

```release-note
[platform] Replace Helm lookup functions with FluxCD valuesFrom mechanism for configuration propagation
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Helm releases and namespaces now source centralized cluster/namespace
configuration via a new secret (cozystack-values), and many templates
read values from chart-provided _cluster/_namespace entries.

* **Bug Fixes**
* API now rejects application specs containing reserved keys prefixed
with "_" to prevent invalid configurations.

* **Refactor**
* Two background reconciler controllers were removed from startup,
simplifying controller initialization.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:01 +01:00
Andrei Kvapil
868a7497d0 fix(ci): ensure correct latest release after backport publishing (#1800)
## What this PR does

Fixes an issue where backport releases incorrectly became marked as
"Latest" despite passing `make_latest: 'false'` to the GitHub API.

**Root cause:** The `getLatestRelease()` API returns the release with
the "Latest" flag, not the highest semver version. Combined with race
conditions during parallel release publishing and GitHub API potentially
ignoring `make_latest: 'false'`, backport releases were incorrectly
marked as latest.

**Solution:**
- Replace `getLatestRelease()` with semver-based max version detection
across all published releases
- After publishing a backport release, explicitly restore the latest
flag on the highest semver release
- Remove unused dead code from `tags.yaml` workflow

### Release note

```release-note
[ci] Fix latest release detection to use semver comparison instead of GitHub's "Latest" flag
```
2026-01-09 14:54:01 +01:00
Aleksei Sviridkin
666eeffa47 [kubevirt-operator] Revert incorrect case change in VM alerts (#1804)
## What this PR does

Reverts PR #1770 which incorrectly changed status/phase checks from
lowercase to uppercase.

The actual KubeVirt metrics use **lowercase**:
- `kubevirt_vm_info` uses `status="running"` (not `"Running"`)
- `kubevirt_vmi_info` uses `phase="running"` (not `"Running"`)

### Verification

Queried virt-controller metrics directly in the instories cluster:

```
kubevirt_vm_info{...,status="running",status_group="running",...} 1
kubevirt_vmi_info{...,phase="running",...} 1
```

Note: `kubectl get vm` shows `STATUS: Running` with capital R, but this
is display formatting — the actual metric labels use lowercase.

### Release note

```release-note
[kubevirt-operator] Fix VM alert rules to use correct lowercase status values
```
2026-01-09 14:54:01 +01:00
Andrei Kvapil
8d166e0754 [platform] refactor: split cozystack-resource-definitions into separate packages (#1778)
## What this PR does

This PR splits the monolithic `cozystack-resource-definitions` package
into 25 individual resource definition packages (`*-rd`) for better
modularity and independent versioning.

**Changes:**
- Created 25 separate `*-rd` packages (bootbox-rd, bucket-rd,
clickhouse-rd, etcd-rd, ferretdb-rd, foundationdb-rd, http-cache-rd,
info-rd, ingress-rd, kafka-rd, kubernetes-rd, monitoring-rd, mysql-rd,
nats-rd, postgres-rd, rabbitmq-rd, redis-rd, seaweedfs-rd,
tcp-balancer-rd, tenant-rd, virtual-machine-rd, virtualprivatecloud-rd,
vm-disk-rd, vm-instance-rd, vpn-rd)
- Removed `packages/system/cozystack-resource-definitions`
- Updated platform bundles (paas-hosted, paas-full, distro-full) to
reference individual -rd packages
- Updated `hack/update-crd.sh` to use package-specific directories

Each `*-rd` package contains:
- `Chart.yaml` - package metadata
- `values.yaml` - default values
- `Makefile` - build instructions
- `cozyrds/<name>.yaml` - CRD definition
- `templates/cozyrd.yaml` - Helm template

**Benefits:**
- **Modularity**: Each resource definition is now a standalone package
- **Independent versioning**: Resources can be versioned independently
- **Maintainability**: Easier to update individual resources
- **Build efficiency**: Parallel building of resource packages

### Release note

```release-note
[platform] Split cozystack-resource-definitions into 25 separate *-rd packages for better modularity and independent versioning. Each resource definition is now a standalone package.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **Refactor**
  * Split the monolithic resource-definitions into many independent resource-definition packages (e.g., bootbox-rd, bucket-rd, clickhouse-rd, etc.) for modular deployment and finer-grained management
  * Updated deployment bundles to reference the new per-resource releases with uniform cozy-system namespace and CRD dependency

* **Chores**
  * Added packaging/Helm stubs (Chart.yaml, Makefile, values, templates) for each new resource-definition
* **Bug Fixes**
  * Made CRD path resolution dynamic (NAME validated before assignment)

<sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:01 +01:00
Andrei Kvapil
967f0bdc9f [kubernetes] Add lb tests for tenant k8s (#1783)
<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[kubernetes] Add lb tests for tenant k8s
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Tests**
  * Increased readiness and port-forward timeouts to improve stability.
* Added full end-to-end provisioning and validation: automated namespace
and backend deployment, load balancer provisioning, health checks with
retries, reachability validation, and cleanup.
* Provisioning sequence now runs earlier and is duplicated within the
test flow, altering execution order and adding extra validation/cleanup
steps.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:00 +01:00
Andrei Kvapil
30c1041e7a feat(ci): add /retest command to rerun tests from Prepare environment
Allows maintainers to trigger test rerun by commenting /retest on a PR.
The workflow finds the latest run for the PR and reruns starting from
the "Prepare environment" job, skipping the build step.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-01-09 14:54:00 +01:00
Andrei Kvapil
68a639b32c fix(ci): remove GITHUB_TOKEN extraheader to trigger workflows
actions/checkout configures http.extraheader with GITHUB_TOKEN which
takes priority over URL credentials. This caused tag pushes to
authenticate as github-actions instead of cozystack-bot, preventing
the Versioned Tag workflow from being triggered.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-01-09 14:54:00 +01:00
Andrei Kvapil
2bf1168dcf [system] Add resource requests and limits to etcd-defrag (#1785)
## What this PR does
Added resource requests and limits for etcd-defrag container.

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[system] Add resource requests and limits to etcd-defrag
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Enhanced resource configurations for the etcd defragmentation process
to ensure optimal performance and system stability.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:54:00 +01:00
Andrei Kvapil
526af29459 [ci] Fix auto-release workflow
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-01-09 14:54:00 +01:00
Andrei Kvapil
b65fc64e17 [tenant] Run cleanup job from system namespace (#1774)
## What this PR does

The Helm hook that creates a job deleting all applications in a tenant
before deleting the tenant itself now runs this job from the cozy-system
namespace. This prevents conflicts with resource quotas (not enough
resources to run cleanup job) without temporary increases of the quota
or similar vulnerability-introducing hacks.

### Release note

```release-note
[tenant] Run cleanup job in system namespace to avoid conflicts on
resource quotas.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Infrastructure Updates**
* Updated cleanup job namespace targeting to use a fixed system
configuration
  * Adjusted cleanup job execution priority level

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:59 +01:00
Andrei Kvapil
9a2d39a4b0 [tenant] Allow egress to parent ingress pods (#1765)
## What this PR does

Fixes egress policy for nested Kubernetes clusters using `exposeMethod:
Proxied`.

The clusterwide egress policy blocks traffic from tenant pods to ingress
pods in parent namespaces. This breaks:
- cert-manager HTTP-01 self-check
- Any scenario where pods need to access services exposed through parent
ingress

Adds egress rule allowing traffic to ingress pods
(`cozystack.io/service: ingress`) in parent namespaces, following the
same pattern as existing vminsert and etcd rules.

### Release note

```release-note
[tenant] Fixed tenant egress policy to allow traffic to parent ingress pods, enabling cert-manager HTTP-01 challenges and external domain access for nested clusters with exposeMethod: Proxied
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Enhanced network policies for multi-tenant environments with improved
traffic routing based on namespace hierarchies, enabling more granular
egress control.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:59 +01:00
Andrei Kvapil
fe565aff4a [kubevirt-operator] Fix typo in VMNotRunningFor10Minutes alert (#1770)
## What this PR does

Fix case sensitivity in status check for VMNotRunningFor10Minutes alert
rule.

The metric `kubevirt_vm_info` uses `status="Running"` (capital R), but
the alert rule was checking for `status!="running"` (lowercase), causing
false alerts for running VMs.

Fixes https://github.com/cozystack/cozystack/issues/1552

### Release note

```release-note
[kubevirt-operator] Fix VMNotRunningFor10Minutes alert false positives
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed alert rule condition for virtual machine status detection to
ensure proper matching of running VMs.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:59 +01:00
Andrei Kvapil
29bd12d52d [installer,dx] Rename cozypkg to cozyhr (#1763)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


This PR renames cozypkg to cozyhr
https://github.com/cozystack/cozyhr

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[installer,dx] Rename cozypkg to cozyhr
```
2026-01-09 14:53:59 +01:00
Nikita
12023b7f02 [multus] Increase memory limit (#1773)
## What this PR does
Increases multus memory limit.
Based on multiple community reports stating that multus tend to consume
a lot of memory during startup after a node reboot.

### Release note
```release-note
Multus memory limit increased.
```
2026-01-09 14:53:59 +01:00
Aleksei Sviridkin
f3c178e30d [cilium] Update Cilium to v1.18.5 (#1769)
## What this PR does

- Update Cilium from v1.17.8 to v1.18.5
- Add `SED_INPLACE` variable to `scripts/common-envs.mk` for macOS
compatibility
- Remove deprecated `enableRuntimeDeviceDetection` option (now default
behavior in 1.18)

Cilium 1.18 requires Linux kernel 5.10+ (compatible with Talos).

References:
- [Cilium 1.18 Upgrade
Guide](https://docs.cilium.io/en/stable/operations/upgrade/)
- [Cilium 1.18 Release
Blog](https://isovalent.com/blog/post/cilium-1-18/)

### Release note

```release-note
[cilium] Update Cilium to v1.18.5
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added configurable Kubernetes service discovery with ConfigMap-based
endpoint source
* Introduced exponential backoff settings for Kubernetes API client
connections
* Added metrics sampling interval configuration for internal agent
metrics
* Implemented identity management mode options for endpoint slices and
DNS proxy pre-allocation
* Enhanced Prometheus scrape timeout configuration across monitoring
components

* **Improvements**
  * Upgraded core components to v1.18.5
* Strengthened security defaults by disabling privilege escalation
across pods
* Added startup and liveness probe configurations for improved health
monitoring
  * Extended network policy correlation capabilities in Hubble

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:59 +01:00
Andrei Kvapil
654eb7c3f9 [cozystack-controller] Fix: move crds to definitions (#1759)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[cozystack-controller] Fix: move crds to definitions
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated the Custom Resource Definition generation template to source
files from a new location, ensuring consistent configuration management.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:58 +01:00
Timofei Larkin
ffd10e99f1 [platform] Add alphabetical sorting to registry resource lists (#1764)
## What this PR does

Adds deterministic alphabetical sorting to all registry resource lists:
- TenantNamespace (sorted by name)
- TenantSecret (sorted by namespace/name)
- TenantModule (sorted by namespace/name)
- Application (sorted by namespace/name)

Introduces a new `pkg/registry/sorting` package with generic helper
functions
to avoid code duplication.

Also fixes pre-existing linter errors:
- Unused `helmReleaseGVR` variables
- Non-constant format strings in `klog.Errorf` calls
- Redundant embedded field selectors

### Release note

```release-note
[platform] Registry resource lists are now returned in alphabetical order
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a reusable alphabetical sorting utility and applied consistent
sorting across list endpoints.

* **Bug Fixes**
* Ensured ResourceVersion/UID are sourced correctly for accurate
list/table responses.
* Simplified and improved error logging and table ResourceVersion
handling.
  * Made schema defaulting behavior more consistent.

* **Tests**
* Added unit tests validating alphabetical sorting for multiple resource
types.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:58 +01:00
Andrei Kvapil
f400310f28 [agents] Add instructions for working with unresolved code review comments (#1710)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[agents] Add instructions for working with unresolved code review comments
```
2026-01-09 14:53:58 +01:00
Andrei Kvapil
9ab7430cec [workflow] Push tags as cozystack-bot to trigger GitHub workflows
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-01-09 14:53:58 +01:00
Andrei Kvapil
87fa8c93fc [workflows] Add auto patch release workflow (#1754)
This PR adds a new GitHub workflow that automatically creates patch
releases for maintenance branches.

## What it does

- Runs daily at 2:00 AM CET (1:00 UTC)
- Checks all `release-X.Y` branches
- For each branch, finds the latest published release with tag `vX.Y.Z`
(without suffixes like -rc, -alpha, -beta)
- If new commits exist after the release, creates a new tag `vX.Y.Z+1`
and force-pushes it
- This triggers the existing tag workflow to build and create a release
PR

## Why releases instead of tags

The workflow checks published releases (not just tags) because if a
release PR hasn't been merged yet, the workflow should run again the
next day and move the tag to newer commits if they exist.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Automated patch release workflow configured for release branches,
enabling automatic version tagging when new commits are detected.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:58 +01:00
Andrei Kvapil
d1c0af1db4 [workflow] Add GitHub Action to update release notes from changelogs (#1752)
This PR adds a GitHub Actions workflow that automatically updates
release notes from changelog files when changes are merged to main.

The workflow:
- Triggers on push to main branch
- Processes up to 30 releases from the first page
- For each release, checks if a corresponding changelog file exists in
`docs/changelogs/`
- Updates the release notes with the changelog content if it exists and
differs from the current content
- Skips releases that are already up to date to avoid unnecessary API
calls

This automates the process of keeping release notes synchronized with
changelog files.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Automated workflow added to synchronize GitHub releases with local
changelog files, updating release notes only when content differs.

* **Documentation**
* Changelogs and release notes reorganized and expanded with improved
sectioning and new tooling/documentation entries.

* **New Features**
  * Added VM disk SVG icon entry under Features/Improvements.

* **Bug Fixes**
  * Pinned CoreDNS image tag for reproducible deployments.
* Fixed a documentation typo that prevented a component from displaying
in the web UI.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:57 +01:00
Andrei Kvapil
eb042b4ef1 [core] Extract Talos package from installer (#1724)
## What this PR does

Extract Talos-related functionality from `packages/core/installer` into
a separate `packages/core/talos` package.

This refactoring separates concerns:
- The `installer` package now focuses solely on the Cozystack installer
- The `talos` package handles all Talos Linux image building and assets
generation

Changes:
- Created new `packages/core/talos` package with Chart.yaml, Makefile,
and values.yaml
- Moved Talos profiles (initramfs, kernel, iso, installer, metal,
nocloud) to talos package
- Moved matchbox configuration and Dockerfile to talos package
- Moved `hack/gen-profiles.sh` and `hack/gen-versions.sh` scripts to
talos package
- Updated installer Makefile to remove all Talos-related targets
- Updated root Makefile to build talos package separately
- Updated matchbox Dockerfile paths to reference talos package

### Release note

```release-note
[core] Extract Talos package from installer into separate packages/core/talos package
```



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Reorganized build system to add a dedicated Talos package with its own
image and asset build workflow
* Switched asset generation to the new Talos packaging path and
simplified build dependency chain
* Added Helm chart manifest and streamlined image build/publishing steps
for Talos-related artifacts

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:57 +01:00
Andrei Kvapil
ecb9a223aa Add changelogs to v.0.39.1 (#1750)
<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
Add changelogs for v.0.39.0 and v.0.39.1
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Topology-aware routing for services
  * Automatic pod rollouts on configuration changes
  * Windows VM scheduling support
  * SLACK_SEVERITY_FILTER for notification filtering
  * VMAgent resource for metrics scraping

* **Improvements**
  * Enhanced networking and storage capabilities
  * Configuration management enhancements
  * Updated dependencies

* **Bug Fixes**
  * Schema nesting and resizing validation
  * Namespace deletion regression

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:57 +01:00
Andrei Kvapil
77de2bdda0 Update go modules (#1736)
This change is extracted from
- https://github.com/cozystack/cozystack/pull/1641

and reworked to work standalone

Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[cozystack] Update go modules
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

* **Chores**
* Updated Go toolchain to 1.25.0 and upgraded core Kubernetes libraries,
OpenTelemetry, Prometheus, gRPC/protobuf and many indirect dependencies.
Bumped builder base images to golang:1.25-alpine across multiple
components.

* **Refactor**
* Removed legacy component versioning/emulation and simplified server
startup and configuration paths.

* **Tests**
  * Removed tests related to the legacy versioning/emulation behavior.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:53:08 +01:00
Timofei Larkin
b3179d032a [vm] Always expose VMs with a service (#1738)
## What this PR does

When VMs are created without a public IP, no service is created for them
and they have no in-cluster DNS name. This PR fixes this and resolves
#1731.

### Release note

```release-note
[vm] Always expose VMs with at least a ClusterIP service.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Improvements**
* Service templates now conditionally enable external-specific
annotations and settings when external mode is enabled.
* External LoadBalancer deployments support richer port configuration
(including whole-IP fallback), while internal services retain a single
default port (65535).
* External traffic policy and node port allocation are applied only in
external mode to preserve internal behavior.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:42 +01:00
Andrei Kvapil
a939b2bbd0 [registry] Add application labels and update filtering mechanism (#1707)
This change is extracted from
- https://github.com/cozystack/cozystack/pull/1641

and reworked to work standalone

## What this PR does

This PR extracts changes from the
https://github.com/cozystack/cozystack/pull/1641. It adds application
metadata labels to HelmReleases and updates the filtering mechanism to
use labels instead of chart/sourceRef matching.

Changes:
- Add three application metadata labels
(`apps.cozystack.io/application.kind`,
`apps.cozystack.io/application.group`,
`apps.cozystack.io/application.name`) when creating/updating HelmRelease
via Cozystack-API
- Replace `shouldIncludeHelmRelease` filtering with label-based
filtering in Get, List, and Update methods
- Always add kind and group label requirements in List for precise
filtering
- Update CozystackResourceDefinitionController to watch only
HelmReleases with `cozystack.io/ui=true` label
- Update LineageControllerWebhook to extract metadata directly from
HelmRelease labels instead of using chart mapping configuration
- Add functionality to update HelmRelease chart from
CozystackResourceDefinition using label selectors

### Release note

```release-note
[registry] Add application labels and update filtering mechanism to use label-based filtering instead of chart/sourceRef matching
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added application metadata labels (kind, group, name) and exported
label keys for HelmRelease identification.
* New reconciler keeps HelmRelease charts in sync with application CRDs.

* **Refactor**
* Mapping, listing and selection moved to label-driven logic;
reconciliation responsibilities split so core reconciler focuses on
restart/debounce while a separate reconciler updates HelmReleases.

* **Chores**
* Migration script to backfill application labels on existing
HelmReleases.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:42 +01:00
Nikita
682f83e71c [system/cilium] Enable topology-aware routing for services (#1734) 2026-01-09 14:52:41 +01:00
Timofei Larkin
66cfbe7c0e Add changelogs for v0.38.3 and v.0.38.4 (#1743) 2026-01-09 14:52:41 +01:00
Nikita
67109c33b1 [cilium] Enable automatic pod rollout on configmap updates (#1728)
Enable automatic restart of cilium and cilium-operator pods when
cilium-config ConfigMap is updated.

This change adds:
- `rollOutCiliumPods: true` - enables automatic rollout of cilium-agent
pods
- `operator.rollOutPods: true` - enables automatic rollout of
cilium-operator pods

When the ConfigMap is updated, pods will automatically restart due to
the `cilium.io/cilium-configmap-checksum` annotation that contains the
SHA256 hash of the configmap.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated Cilium configuration settings to enable pod rollout behavior
for Cilium and operator pods by default.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:41 +01:00
Nikita
f9bfcfd125 [virtual-machine,vm-instance] Add nodeAffinity for Windows VMs based on scheduling config (#1693)
This PR adds nodeAffinity configuration to virtual-machine and
vm-instance charts to support dedicated nodes for Windows VMs.

## Changes
- Added logic to check `cozystack-scheduling` ConfigMap in `cozy-system`
namespace
- If `dedicatedNodesForWindowsVMs` is enabled, adds appropriate
nodeAffinity:
- **Windows VMs**: Strong affinity (required) to nodes with label
`scheduling.cozystack.io/vm-windows=true`
- **Non-Windows VMs**: Soft affinity (preferred) to nodes without the
Windows label

## Implementation
- Windows detection based on `instanceProfile` value starting with
"windows"
- Strong affinity uses `requiredDuringSchedulingIgnoredDuringExecution`
- Soft affinity uses `preferredDuringSchedulingIgnoredDuringExecution`
with weight 100

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added configurable node-affinity for VM scheduling: when the cluster
scheduling flag is enabled, Windows VMs are placed on dedicated Windows
nodes (required rule), while non-Windows VMs are preferred to avoid
those nodes (soft preference).
* Change is gated by the cluster scheduling configuration and only
affects placement rules; no other VM specs were altered.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:41 +01:00
Andrei Kvapil
1beb11a6a9 Add Cloupard to ADOPTERS.md (#1733)
<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does
This PR adds Cloupard as new adopter to the list.

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
Add Cloupard to ADOPTERS.md
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
  * Updated the list of project adopters with recent entries.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:41 +01:00
Nikita
f7c6a54b0c Update SeaweedFS v4.02 (#1725)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does

This PR includes new seaweedfs with improved perfomance for S3 daemon

and fixes issue https://github.com/seaweedfs/seaweedfs/issues/7757

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
Update SeaweedFS v4.02
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added all-in-one deployment mode with configurable replicas and update
strategy
* Expanded storage configuration supporting PersistentVolumeClaims with
customizable access modes and size
  * Introduced configurable certificate duration and renewal periods
* Enhanced monitoring configuration with gateway host/port and
additional labels

* **Bug Fixes**
  * Fixed probe endpoint scheme references across components

* **Chores**
  * Updated to SeaweedFS 4.02
  * Updated default ingress class configuration
  * S3 disabled by default

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:40 +01:00
Andrei Kvapil
35c57798a6 [monitoring] Add SLACK_SEVERITY_FILTER field and VMAgent for tenant monitoring (#1712)
[monitoring] Add SLACK_SEVERITY_FILTER field and VMAgent for tenant
monitoring
What this PR does
This PR introduces the SLACK_SEVERITY_FILTER environment variable in the
Alerta deployment to enable
filtering of alert severities for Slack notifications based on the
disabledSeverity configuration.
Additionally, it adds a VMAgent resource template for scraping metrics
within tenant namespaces, improving
monitoring granularity and control.

```release-note
[monitoring] Add SLACK_SEVERITY_FILTER for filtering Slack alert severities and VMAgent configuration for
tenant-specific metrics scraping.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Added configurable severity filtering for Telegram alerts.
  * Extended Slack severity filtering to accept lists of severities.

* **Bug Fixes / Behavior**
* Severity settings now accept arrays (multiple severities) instead of
single comma-separated strings.

* **Documentation**
* Updated configuration docs and examples to show list-style severity
settings.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:40 +01:00
Andrei Kvapil
aba147571b [fluxcd] Add flux-aio module and migration (#1698)
This change is extracted from
- https://github.com/cozystack/cozystack/pull/1641

and reworked to work standalone

requires:

- https://github.com/cozystack/cozystack/pull/1705


## What this PR does

Adds a new `flux-aio` module and migration script to upgrade FluxCD to
version 22. This introduces a new modular approach to FluxCD
installation using the flux-aio OCI module.

Changes:
- Created new `flux-aio` package with Chart.yaml, Makefile, and CUE
configuration
- Added flux-aio module configuration using OCI module from
`ghcr.io/stefanprodan/modules/flux-aio`
- Generated large fluxcd.yaml template (11956+ lines) for FluxCD
resources
- Added migration script (migrations/21) to handle upgrade from version
21 to 22
- Updated installer to include flux-aio module
- Added script `issue-flux-certificates.sh` for managing TLS
certificates for cozystack-assets
- Updated platform templates to support flux-aio module
- Updated cozystack-assets service references

### Release note

```release-note
[fluxcd] Add flux-aio module and migration
```



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added TLS certificate support for Helm package repositories with
automatic certificate provisioning.

* **Chores**
  * Refactored FluxCD integration using Helm chart-based deployment.
  * Updated system to version 22 with automatic migration support.
  * Enhanced security dependencies (OpenSSL).

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:40 +01:00
Andrei Kvapil
17138d825d [fluxcd] Enable source-watcher (#1706)
This change is extracted from
- https://github.com/cozystack/cozystack/pull/1641

and reworked to work standalone

Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[fluxcd] Enable source-watcher
```
2026-01-09 14:52:40 +01:00
Andrei Kvapil
f5eb211312 [platform] Separate assets server into dedicated deployment (#1705)
## What this PR does

Separates the assets server from the main cozystack installer into a
dedicated StatefulSet deployment. This improves separation of concerns
and allows the assets server to run independently from the installer.

Changes:
- Created new `cozystack-assets` StatefulSet in the platform package
- Added dedicated Dockerfile for assets server image
(`packages/core/platform/images/cozystack-assets/Dockerfile`)
- Removed assets server container and Service from installer deployment
- Updated HelmRepository URLs to point to new `cozystack-assets` service
- Updated dashboard URLs in monitoring package to use new service
- Added image build target to platform Makefile
- Configured assets server with hostNetwork and proper RBAC permissions

### Release note

```release-note
[platform] Separate assets server into dedicated StatefulSet deployment
```
2026-01-09 14:52:40 +01:00
Andrei Kvapil
c44b198a60 [apps] Refactor apiserver to use typed objects and fix UnstructuredList GVK (#1679)
## What this PR does

This PR refactors the apiserver REST handlers to use typed objects
(`appsv1alpha1.Application`) instead of `unstructured.Unstructured`,
eliminating
the need for runtime conversions and simplifying the codebase.

Additionally, it fixes an issue where `UnstructuredList` objects were
using
the first registered kind from `typeToGVK` instead of the kind from the
object's field when multiple kinds are registered with the same Go type.

This is a more comprehensive fix for the problem addressed in
https://github.com/cozystack/cozystack/pull/1630, which was reverted in
https://github.com/cozystack/cozystack/pull/1677.

The fix includes the upstream fix from kubernetes/kubernetes#135537,
which enables short-circuit path for `UnstructuredList` similar to
regular
`Unstructured` objects, using GVK from the object field instead of
`typeToGVK`.

### Changes
- Refactored `rest.go` handlers to use typed `Application` objects
- Removed `unstructured.Unstructured` conversions
- Fixed `UnstructuredList` GVK handling
- Updated dependencies in `go.mod`/`go.sum`
- Added e2e test for OpenAPI validation
- Updated Dockerfile

### Release note

```release-note
[apps] Refactor apiserver to use typed objects and fix UnstructuredList GVK handling

This change refactors the apiserver REST handlers to use typed Application objects instead of unstructured.Unstructured, eliminating runtime conversions and simplifying the codebase. Additionally, it fixes an issue where UnstructuredList objects were incorrectly using the first registered kind from typeToGVK instead of the kind from the object's field when multiple kinds are registered with the same Go type. This fix includes the upstream fix from kubernetes/kubernetes#135537.
```



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Added a module replacement in dependency configuration to ensure
reproducible builds.

* **Refactor**
* REST internals now use strongly-typed Application and TenantModule
resources and return typed API objects with consistent metadata.

* **Tests**
* Strengthened end-to-end checks for resource kinds and added a
create/delete namespace scenario.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:39 +01:00
Andrei Kvapil
9b5f3726b6 [virtual-machine] Improve check for resizing job (#1688)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does

PVC resizing now only occurs when storage is being increased, preventing
unintended storage reduction operations

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[virtual-machine] Improve check for resizing job
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* PVC resizing now only triggers when the requested storage increases,
preventing unintended shrink attempts.

* **Enhancements**
* More robust storage-size comparison and validation to accurately
detect growth.
* Resize operations now run only when needed, reducing unnecessary jobs.

* **New Features**
* Added conditional pre-install/pre-upgrade hook workflow to perform
controlled PVC resize jobs.

* **Chores**
  * Minor template formatting cleanup.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:39 +01:00
Andrei Kvapil
66b68e3798 [dashboard] Fix CustomFormsOverride schema to nest properties under spec.properties (#1692)
## What this PR does

Fixes the logic for generating CustomFormsOverride schema to properly
nest properties under `spec.properties` instead of directly under
`properties`.

Changes:
- Updated `buildMultilineStringSchema` to check for `spec` property in
OpenAPI schema
- Process `spec.properties` instead of root `properties`
- Create schema structure as `schema.properties.spec.properties.*`
- Updated tests to reflect the new nested structure

### Release note

```release-note
[dashboard] Fix CustomFormsOverride schema generation to nest properties under spec.properties
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Updated custom form schema generation to organize form fields within a
nested structure for improved organization.

* **Tests**
* Expanded test coverage to validate the new schema organization and
field type handling across nested levels.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:39 +01:00
Andrei Kvapil
bd443bd578 [linstor] Update piraeus-operator v2.10.2 (#1689)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does

This release updates LINSTOR CSI to fix issues with the new fsck
behaviour.

```
MountVolume.SetUp failed for volume "pvc-37245cc3-bf28-4da4-a127-e5c9c03cc088" : rpc error: code = Internal desc = NodePublishVolume failed for pvc-37245cc3-bf28-4da4-a127-e5c9c03cc088: failed to run fsck on device '/dev/zvol/data/pvc-37245cc3-bf28-4da4-a127-e5c9c03cc088_00000': failed to run fsck: output: "fsck from util-linux 2.41
/dev/zd832 is mounted.
e2fsck: Cannot continue, aborting.
```

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[linstor] Update piraeus-operator v2.10.2
```
2026-01-09 14:52:39 +01:00
Andrei Kvapil
2c37611136 [ci] Update korthout/backport-action@v3.2.1
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-01-09 14:52:39 +01:00
Andrei Kvapil
a4a432e2aa [ci] Improve backport workflow with merge_commits skip and conflict resolution (#1694)
This PR improves the backport workflow by:

- Adding `merge_commits: skip` to skip merge commits during backport
- Adding `conflict_resolution: draft_commit_conflicts` to create draft
PRs when conflicts occur instead of failing
- Removing the 'Report if backport failed' step as it's no longer needed
with the new conflict resolution strategy

These changes ensure that backports handle merge commits and conflicts
more gracefully.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Enhanced the backport workflow to support simultaneous backporting to
current and previous release branches based on PR labels
* Added validation to ensure target branches exist before attempting
backports
* Improved workflow reliability by separating preparation and execution
stages

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:38 +01:00
Andrei Kvapil
da6c053d3f Fix: Add missing components to distro-full bundle (#1620)
The `distro-full` bundle was missing critical components that exist in
paas-full, causing multiple pod failures during installation. This PR
adds the missing packages and fixes dependency issues.

When installing cozystack with bundle-name: "distro-full", several pods
failed to start:

  1. CozystackResourceDefinition CRD missing
    - cozystack-controller pod: CrashLoopBackOff
    - lineage-controller-webhook pods: CrashLoopBackOff
- Error: no matches for kind "CozystackResourceDefinition" in version
"cozystack.io/v1alpha1"


a861814c24/packages/system/cozystack-resource-definition-crd/definition/cozystack.io_cozystackresourcedefinitions.yaml (L1-L14)

  2. selfsigned-cluster-issuer ClusterIssuer missing
- snapshot-validation-webhook pods: ContainerCreating (waiting for TLS
secret)
    - snapshot-controller HelmRelease: Failed to install (timeout)
- Error: clusterissuer.cert-manager.io "selfsigned-cluster-issuer" not
found


a861814c24/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml (L52-L57)


a861814c24/packages/system/snapshot-controller/template/clusterissuer.yaml (L1-L8)

  3. Cascading failures
    - linstor HelmRelease: Blocked (depends on snapshot-controller)
    



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added two new resource-definition components to the platform
distribution for enhanced configuration management.

* **Improvements**
* Made certificate issuer components required during deployment (no
longer optional).
* Adjusted snapshot controller startup order to wait for certificate
issuers, improving startup reliability.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-09 14:52:37 +01:00
Timofei Larkin
38d6b98a70 [kubeovn] Package from external repo (#1535)
## What this PR does

Previously, all system charts have had their versions bumped with every
update of Cozystack, even if the underlying images and templates did not
change. Additionally, some components would have their docker images
rebuilt and get updated digests because of a changed docker context,
even though no relevant code had been changed. This would cause an
upgrade of several HelmReleases on every upgrade of Cozystack, even when
in practice nothing had changed. This is especially noticeable for
charts, such as kubeovn, which is a dependency for almost all other
system HelmReleases. By moving kubeovn out of the monorepo and
decoupling its release cycle from the release cycle of Cozystack, this
issue can be resolved and is another step towards decomposing Cozystack.

### Release note

```release-note
[kubeovn] Decouple the release cycle of kubeovn from Cozystack's release
cycle, preventing unnecessary redeployments of all Helm releases, when
upgrading Cozystack.
```
2025-12-05 23:33:50 +04:00
Timofei Larkin
28c933161a Merge branch 'main' into feat/external-kubeovn-build
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-12-05 18:47:08 +04:00
Timofei Larkin
e50950b7a1 [kubeovn] Bump versions, drop build from Makefile
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-12-05 17:46:04 +03:00
Andrei Kvapil
b1a55f5a38 Granular kubernetes application extensions dependencies (#1683)
## What this PR does
More granular k8s app extensions dependencies.

As a part of the change, packages were updated:
- monitoring-agents: metrics-server moved to a separate package
- monitoring-agents: prometheus-operator-crds moved to a separate
package

Main Cozystack bundles were updated to reflect packages changes. 

### Release note
```release-note
Granular k8s extensions dependencies.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a standalone metrics-server release and a
prometheus-operator-crds release.

* **Improvements**
* Expanded Prometheus-related CRDs with new configuration options and
status subresources.
* Adjusted monitoring orchestration so components (cilium, metrics,
CRDs) install in a clearer order.

* **Refactor**
* Split metrics-server out of the monitoring-agents bundle and moved
Prometheus CRDs into a dedicated package.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-12-05 14:44:53 +01:00
Andrei Kvapil
1ee6eb8482 Update Flux Operator (v0.33.0) (#1649)
https://github.com/fluxcd/flux2/discussions/5572

There are some upgrade instructions for Flux 2.7, but I don't think that
they apply to Cozystack.

They might be relevant for some users though, depending on how they are
using Flux in their clusters - Cozystack only uses HelmReleases AFAIK
(and now gitrepository and helmrelease for external apps) so there is no
problem with the Flux 2.7 upgrade, which brings Image APIs to GA (v1)

That change has no impact on Cozystack because we don't depend on the
Flux Image APIs yet.

I haven't tested the upgrade to Flux 2.7, but I will include the bump in
the FluxInstance definition since Flux 2.7 has been out for a while
already, has had several patch releases, and is probably stable for the
next CozyStack release now!

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added distribution variant option for FluxInstance (upstream-alpine,
enterprise-alpine, enterprise-distroless)
* Added status fields to improve tracking of force and reconcile
annotation handling across resources

* **Chores**
* Bumped Flux Operator and Flux Instance charts to 0.33.0 (appVersion
v0.33.0)
  * Upgraded Flux distribution to 2.7.x
  * Added/cleaned up network policy templates and README badges

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-12-05 14:42:43 +01:00
Andrei Kvapil
cbfa99148b [monitoring] Improve tenant metrics collection (#1684)
This patch introduces vmagent support inside tenant-level monitoring
stacks, ensuring that all tenant workloads have consistent and reliable
metrics scraping. By deploying a vmagent per tenant and wiring it to the
configured VictoriaMetrics short- and long-term storage, metrics are now
properly collected, labeled, and remote-written. This resolves gaps
where tenant environments previously missed metrics due to the absence
of dedicated agents.

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note
```release-note
[monitoring,platform] Add vmagent integration into tenant monitoring
stacks to ensure complete and correct metrics collection for all tenants.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added VictoriaMetrics Agent (Vmagent) support in monitoring:
configurable external labels and remote-write endpoints for metric
collection.

* **Documentation**
* Added README documentation for the new Vmagent configuration options
and example defaults.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-12-05 14:41:10 +01:00
Andrei Kvapil
54d0f52245 [postgres] Add version management system with automated version updates (#1671)
This PR adds a version management system for PostgreSQL that
automatically fetches and updates supported versions from the
CloudNativePG PostgreSQL container registry.

## Changes
- Added `hack/update-versions.sh` script to fetch and update PostgreSQL
versions
- Added `files/versions.yaml` to store version mappings
- Added `templates/_versions.tpl` template for version handling
- Updated `values.yaml` with version enum and parameter
- Updated `templates/db.yaml` and `templates/init-job.yaml` to use
version management
- Updated `Makefile` to include version update workflow

## Features
- Automatically fetches supported major versions from GitHub
- Queries container registry for latest minor versions
- Updates version enum in values.yaml
- Maintains version mappings in versions.yaml

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added PostgreSQL version selection (v13–v18) with default v18; images
now follow the selected version via a resolved version map.

* **Chores**
* Added an automated update workflow to refresh supported PostgreSQL
versions and regenerate mappings.
  * Packaging ignore updated to exclude hack tooling.

* **Schema**
* Exposed a version property in chart and resource schemas for
validation and ordering.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-12-05 14:38:50 +01:00
Andrei Kvapil
d0bfb6e2fc [kubernetes] Add version management system with automated version updates (#1672)
This PR adds a version management system for Kubernetes that
automatically fetches and updates supported versions based on kamaji.

## Changes
- Added `hack/update-versions.sh` script to fetch and update Kubernetes
versions
- Updated `files/versions.yaml` with version mappings
- Updated `values.yaml` with version enum and parameter
- Updated `Makefile` to include version update workflow
- Added `hack` directory to `.helmignore`

## Features
- Automatically fetches Kubernetes version from kamaji repository
- Gets latest patch version for the supported minor version
- Queries container registry for available versions
- Updates version enum in values.yaml using reliable awk-based approach
- Updates KUBERNETES_VERSION in Makefile
- Maintains version mappings in versions.yaml

## Workflow
- Reads kamaji version from Dockerfile
- Fetches Kubernetes version from kamaji's kubeadm_version.go
- Finds latest patch version for that minor version
- Includes supported version + 5 previous minor versions
- Updates all configuration files automatically

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Kubernetes version parameter now uses an enum constraint to limit
selection to supported versions (v1.33, v1.32, v1.31, v1.30, v1.29,
v1.28).

* **Documentation**
  * Simplified Kubernetes version field description for clarity.

* **Chores**
* Updated Kubernetes patch version mappings (v1.32→v1.32.10,
v1.31→v1.31.14).
  * Relaxed add-on schema validation requirements.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-12-05 14:38:22 +01:00
Andrei Kvapil
f86896eceb [redis] Add version management system with automated version updates (#1681)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[redis] Add version management system with automated version updates
```
2025-12-05 14:37:56 +01:00
Andrei Kvapil
cb320f9d48 [mariadb] Add version management system with automated version updates (#1680)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[mariadb] Add version management system with automated version updates
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added configurable MariaDB version selection for deployments.
Supported versions: v11.8, v11.4, v10.11, and v10.6 (default: v11.8).

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-12-05 14:37:30 +01:00
nbykov0
b1a7e9560e [apps:kubernetes] dont delete cleanup job on fail
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-04 12:10:56 +03:00
nbykov0
fe9d334880 [apps:kubernetes] update dependencies
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-04 12:10:56 +03:00
nbykov0
1e2b66131c [apps:kubernetes] separate prometheus-operator-crds
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-04 12:10:56 +03:00
nbykov0
8d14bcb598 [system:victoria-metrics-operator] separate prometheus-operator-crds
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-04 12:10:56 +03:00
nbykov0
825390c209 [core:bundles] separate prometheus-operator-crds
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-04 12:10:46 +03:00
IvanHunters
09fd7c4094 fix crd
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-12-03 22:30:29 +03:00
IvanHunters
8928731abf [monitoring] Improve tenant metrics collection
This patch introduces vmagent support inside tenant-level monitoring
stacks, ensuring that all tenant workloads have consistent and reliable
metrics scraping. By deploying a vmagent per tenant and wiring it to the
configured VictoriaMetrics short- and long-term storage, metrics are now
properly collected, labeled, and remote-written. This resolves gaps
where tenant environments previously missed metrics due to the absence
of dedicated agents.

```release-note
[monitoring,platform] Add vmagent integration into tenant monitoring
stacks to ensure complete and correct metrics collection for all tenants.
```

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-12-03 22:18:19 +03:00
nbykov0
153635379a [system] separate prometheus-operator-crds
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-03 16:36:14 +03:00
nbykov0
fbb2ea095a [apps:kubernetes] separate metrics-server
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-03 16:36:03 +03:00
nbykov0
50c1d1a067 [core:bundles] separate metrics-server
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-02 21:02:39 +03:00
Nikita
52ebcae8a2 [core:installer] Address buildx warnings (#1682)
## What this PR does
Buildx is worried about Dockerfile syntax, this pr fixes it.
```
 - FromAsCasing: 'as' and 'FROM' keywords' casing do not match (line 1)
 - FromAsCasing: 'as' and 'FROM' keywords' casing do not match (line 16)
```

### Release note
```release-note
Buildx warnings addressed.
```
2025-12-02 18:10:26 +03:00
nbykov0
5314d61987 [core:installer] Fix buildx warnings
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-02 17:34:07 +03:00
Nikita
8b29c53a45 [system:coredns] update coredns app labels to match Talos coredns labels (#1675)
## What this PR does
Updates coredns app labels to match Talos coredns labels

### Release note

```release-note
Coredns app labels updated to match Talos coredns labels.
```
2025-12-02 14:48:34 +03:00
Nikita
4e4a5606d7 [system:monitoring-agents] rename coredns metrics service (#1676)
## What this PR does
Renames coredns metrics service

### Release note
```release-note
Renamed coredns metrics service not to interfere with coredns service used for name resolution in tenant k8s clusters.
```
2025-12-02 12:55:29 +03:00
nbykov0
f2a4f1b1c8 [system:coredns] rename service to kube-dns
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-02 12:54:36 +03:00
Andrei Kvapil
33128748e6 [mariadb] Add version management system with automated version updates
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-12-02 00:36:00 +01:00
Andrei Kvapil
7e1cad26e7 [redis] Add version management system with automated version updates
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-12-02 00:34:52 +01:00
Andrei Kvapil
3d5118f5b3 [postgres] Add version management system with automated version updates
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-12-01 23:56:55 +01:00
Andrei Kvapil
06a25c1c45 [kubernetes] Add version management system with automated version updates
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-12-01 23:55:27 +01:00
Andrei Kvapil
13e0501acd Add changelogs for v0.38.2
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-12-01 22:15:24 +01:00
Andrei Kvapil
c7f478fc7d Release v0.38.2 (#1678)
This PR prepares the release `v0.38.2`.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated container image versions from v0.38.1 to v0.38.2 across system
packages with corresponding digest updates. All image references have
been bumped to the latest version with new SHA256 hashes.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-12-01 20:49:26 +01:00
cozystack-bot
d53506ae2a Prepare release v0.38.2
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2025-12-01 19:14:15 +00:00
Andrei Kvapil
8bc62d4c71 Revert [api] Fix representation of dynamic list kinds (fixes namespace deletion regression from #1630) (#1677)
## Problem

This PR reverts the changes introduced in #1630 that caused a regression
affecting namespace deletion and upgrades from previous versions,
particularly when running migration 20.

### Symptoms

Users are experiencing issues with namespace deletion and upgrades. The
namespace controller reports:

```
NamespaceDeletionContentFailure: True
ContentDeletionFailed: Failed to delete all resource types, 25 remaining: 
content is not a list: []unstructured.Unstructured
```

The error indicates that Kubernetes API server expects a proper list
type, but receives `[]unstructured.Unstructured` instead, which breaks
namespace finalization.

### Root Cause

The changes in #1630 modified how dynamic list kinds are represented,
switching from `unstructured.UnstructuredList` to typed
`ApplicationList`. While this was intended to fix kind representation
issues, it introduced a compatibility problem:

1. The namespace deletion controller expects resources to implement the
standard Kubernetes list interface
2. The typed lists may not be properly recognized during namespace
finalization
3. This breaks upgrades from previous versions where resources were
stored as unstructured

### Solution

This PR reverts the problematic changes to restore compatibility with
namespace deletion and upgrade scenarios. We are planning a more
comprehensive fix that will address both the original kind
representation issue and namespace deletion compatibility.

### Related Issues

- Fixes namespace deletion failures
- Fixes upgrade issues from previous versions (migration 20)
- Reverts regression introduced in #1630

### Next Steps

A more comprehensive fix is being prepared that will:
- Properly handle kind representation for dynamic types
- Ensure compatibility with namespace deletion controller
- Support upgrades from previous versions
2025-12-01 20:08:13 +01:00
Andrei Kvapil
0b27f634c0 Revert [api] Fix representation of dynamic list kinds
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-12-01 20:07:06 +01:00
nbykov0
67e47256e2 [system:monitoring-agents] separate metrics-server
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-01 20:51:26 +03:00
nbykov0
df277b350c [system:coredns] update app coredns labels to match Talos coredns labels
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-01 17:51:27 +03:00
nbykov0
644d71eef7 [system:monitoring-agents] rename coredns metrics service
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-12-01 17:50:02 +03:00
Andrei Kvapil
9d1fb4ccf2 Add changelogs for v0.37.9 and v0.38.1
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-11-27 16:04:27 +01:00
Andrei Kvapil
27efd3ad5e Release v0.38.1 (#1668)
This PR prepares the release `v0.38.1`.
2025-11-27 15:53:53 +01:00
Andrei Kvapil
7b20e3f4cc [seaweedfs] Extended CA certificate duration to reduce disruptive CA rotations. (#1657)
**Chores**
* Updated SeaweedFS Helm chart templates with configurable certificate
duration and renewal settings.

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
 - Extended CA certificate duration to reduce disruptive CA rotations.
 - Added mechanism to sync SeaweedFS client certificates across clusters.
 - Enhanced certificate management to ensure Hikube provisioner always receives up-to-date client certificates.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Enhanced CA certificate configuration for SeaweedFS by extending the
validity duration and adjusting the renewal window to improve long-term
certificate management and system stability.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-27 14:34:31 +01:00
IvanHunters
5d354a07d6 add patch for long term ca
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-11-27 14:34:14 +01:00
Andrei Kvapil
aa8062c41c [tenant][kubernetes] Introduce better cleanup logic (#1661)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[tenant][kubernetes] Introduce better cleanup logic
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added an automated pre-delete cleanup job for tenant namespaces to
remove tenant-related releases during uninstall.

* **Improvements**
* Cleanup now runs early in the uninstall sequence with a clearer,
stepwise orchestration for resource removal.
* Expanded permissions and execution allowances to enable the cleanup
workflow.
* Deployment annotations now use a content checksum to better detect
config changes.

* **Removals**
* Previous teardown sequence for certain release types was removed and
replaced by the new workflow.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-27 14:32:54 +01:00
Andrei Kvapil
9ceb59e74c [dashboard] Fix loading arrays in forms when editing existing objects
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-11-27 14:31:05 +01:00
Andrei Kvapil
0df528a89d [dashboard] Add config hash annotations to restart pods on config changes (#1662)
## What this PR does

This PR adds config hash annotations to the dashboard deployment
templates to ensure pods are automatically restarted when their
configuration changes.

Changes:
- Added `checksum/config` annotation to `nginx.yaml` deployment that
computes a hash of `nginx-config.yaml`
- Added `checksum/config` annotation to `web.yaml` deployment that
computes a hash of `configmap.yaml`

This replaces the hardcoded checksum in nginx.yaml with a dynamically
computed one, and adds a new checksum for the web deployment.

### Release note

```release-note
[dashboard] Add config hash annotations to automatically restart pods when configuration changes
```
2025-11-27 12:21:29 +01:00
Andrei Kvapil
d70197c825 Add changelogs for v0.37.* and v0.38.0 (#1658)
<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
Add changelogs for v0.37.* and v0.38.0
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* VPC with Multus CNI, dashboard VNC, configurable worker versions,
dedicated lineage webhook daemonset, tenant workload listing

* **Bug Fixes**
* RBAC and namespace listing fixes (including non‑OIDC/system:masters),
dashboard logout, migration/readiness checks, load balancer cleanup,
various chart/config fixes

* **Security**
* Redis image update, stricter ingress HTTPS enforcement, flux operator
hardening

* **Documentation**
* Kubernetes troubleshooting, backup/recovery, migration guidance,
website and mobile updates

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-26 20:19:33 +01:00
Andrei Kvapil
f2f8da0be1 Add AI-agent for changelogs generation (#1659)
<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
Add AI-agent for changelogs generation
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
  * Updated agent documentation to include changelog generation guidance
* Added comprehensive changelog generation guide with workflow
procedures and validation steps

* **Chores**
* New scripts added for optional repository management and release notes
publishing
  * Project configuration updated to exclude additional directories
  * Removed outdated changelog entry

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-26 20:19:00 +01:00
Andrei Kvapil
094ee6da55 Add AI-agent for changelogs generation
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-11-26 20:18:43 +01:00
Andrei Kvapil
f256575fce [docs] Add instructions for addressing AI bot reviewer comments (#1664)
## What this PR does

This PR adds instructions for AI agents on how to handle comments from
AI bot reviewers (like Qodo, Copilot, etc.).

Changes:
- Added new section "Addressing AI Bot Reviewer Comments" to
`docs/agents/contributing.md`
- Instructions on how to get PR comments using `gh pr view --comments`
- Guidelines on evaluating each comment carefully (don't blindly apply
all suggestions)
- Clear criteria for when to apply and when to skip AI bot suggestions
- Emphasis on leaving changes uncommitted for user review

Key principles:
- Evaluate each suggestion based on context, project conventions, and
impact
- Apply legitimate fixes but skip over-engineering or style mismatches
- Leave changes uncommitted so the user can review and decide

### Release note

```release-note
[docs] Add instructions for AI agents on handling AI bot reviewer comments
```



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Added guidance for addressing AI bot reviewer comments in the
contributor guide.
  * Introduced comprehensive changelog generation procedures.

* **Chores**
  * Finalized v0.37.0 release.
* Enhanced release automation infrastructure with new tooling scripts
for repository checks and release note uploads.
  * Updated project documentation index.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-26 20:15:00 +01:00
Andrei Kvapil
d1ad38dd01 [docs] Add instructions for addressing AI bot reviewer comments
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-11-26 20:12:24 +01:00
Andrei Kvapil
bc1fed4079 [docs] Add AI agent documentation structure (#1663)
## What this PR does

This PR adds AI agent documentation structure to help AI coding
assistants work more effectively with the Cozystack codebase.

Changes:
- Added `AGENTS.md` in the root with an overview and agent documentation
table
- Created `docs/agents/` directory with specialized agent instructions:
  - `overview.md` - Project structure and conventions
  - `contributing.md` - Git workflow, commits, and pull requests
  - `releasing.md` - Release process (references `docs/release.md`)
- Organized documentation to make it easy for AI agents to find relevant
instructions

### Release note

```release-note
[docs] Add AI agent documentation structure with instructions for contributing, releasing, and project overview
```
2025-11-26 19:55:33 +01:00
Andrei Kvapil
0b29ffefe0 [docs] Add AI agent documentation structure
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-11-26 19:54:24 +01:00
Andrei Kvapil
c72a9333e9 [dashboard] Add config hash annotations to restart pods on config changes
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-11-26 19:22:01 +01:00
Andrei Kvapil
d46cccda71 Introduce better cleanup logic
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-11-26 19:01:03 +01:00
Andrei Kvapil
b5b12d0684 Add changelogs for v0.37.* and v0.38.0
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-11-26 17:08:42 +01:00
IvanHunters
8283714930 * **Improvements**
* Extended CA certificate duration to reduce disruptive CA rotations.
  * Added mechanism to sync SeaweedFS client certificates across clusters.
  * Enhanced certificate management to ensure Hikube provisioner always receives up-to-date client certificates.

* **Chores**
  * Updated SeaweedFS Helm chart templates with configurable certificate duration and renewal settings.

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-11-26 15:34:49 +03:00
Andrei Kvapil
aa428457db Release v0.38.0 (#1656)
This PR prepares the release `v0.38.0`.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Chores
* Updated image references and digests across multiple packages from
alpha prerelease versions to stable v0.38.0 releases, including updates
to kubevirt-csi-driver, cozystack-api, cozystack-controller, dashboard
components, kamaji, kubeovn modules, s3manager, and other system
packages.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-25 17:34:23 +01:00
cozystack-bot
975011e04e Prepare release v0.38.0
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2025-11-25 15:59:42 +00:00
Nikita
0d88aa394a scripts: fix 20 migration (#1653)
## What this PR does
Fixes wait conditions for 20 migration

### Release note
```release-note
Fixed wait condition for 20 migration
```
2025-11-25 18:34:03 +03:00
nbykov0
ec1a150d2c scripts: fix 20 migration
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-11-25 17:37:16 +03:00
Nikita
cbc6cd2567 [extra] ingress: rm spaces from external ip list (#1652)
## What this PR does
Remove spaces while processing exposed-external-ips list in cozystack
configmap as they 1) are user-specified and 2) lead to an incorrect
resource being created from it.

### Release note
```release-note
Remove spaces while processing exposed-external-ips list in cozystack configmap
```
2025-11-25 16:48:26 +03:00
Andrei Kvapil
fb7e39eaab [cozy-lib] Improve flatten function (#1647)
This patch breaks introduces a helper function in cozy-lib to correctly
handle special case resources when transforming a nested map of limits
and requests to a flat map suitable for use in resourceQuotas. As a
result, admins can now specify any types of resources as resource quotas
for tenants, and they will be correctly transformed to the correct
format for the underlying kubernetes ResourceQuota. In addition to the
previously supported compute resources, such as CPU, memory, and custom
resources, like GPUs, special quota strings such as
"services.loadbalancers" are now correctly handled.

```release-note
[cozy-lib,platform] Support resource quotas for special kubernetes
quotas, such as service.loadbalncer count and others.
```

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[]
```
2025-11-25 14:48:03 +01:00
Andrei Kvapil
9cc348733f [ci,dx] Bump MariaDB operator version (#1646)
Update MariaDB operator to a new version.

```release-note
[ci,dx] Update MariaDB operator version
```

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[]
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Support for external MariaDB instances and physical backups management
  * Validation webhook added for physical backups
  * New config option to specify MariaDB image registry/name

* **Updates**
  * MariaDB operator bumped to 25.10.2
  * Default MariaDB version updated from 11.4 to 11.8
* Expanded Kubernetes permissions for endpoint slices and volume
snapshots
  * Pod metadata label added to MariaDB pods

* **Documentation**
  * Updated docs links and version badges in charts README

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-25 14:46:50 +01:00
Nikita
00e0f45de3 Increase strimzi memory limit (#1651)
## What this PR does
Increase strimzi memory limit

### Release note
```release-note
Increased strimzi memory limit
```
2025-11-25 16:46:07 +03:00
Andrei Kvapil
b5c264de7d [cozy-lib] Fix malformed ResourceQuota rendering for LoadBalancer services (#1642)
This patch adds special handling for raw Kubernetes ResourceQuota
fields, such as `services.loadbalancers`, preventing them from being
wrapped as `limits.*` or `requests.*` keys by the flatten helper. This
ensures that LoadBalancer quotas render correctly in tenant
specifications.

```release-note
[cozy-lib] Correctly render services.loadbalancers in ResourceQuota without limits.* or requests.* prefixes.
```

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Resource flattening now handles compute and quota keys separately:
compute values are sanitized/flattened, quota-like inputs are emitted
directly as plain YAML.

* **Documentation**
* Added in-template comments and clarified examples for resource
processing behavior.

* **New Features**
* CI now runs unit tests; new test targets and test harnesses added
along with a test chart and test cases for quota handling.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-25 14:45:50 +01:00
Andrei Kvapil
4ff60e4539 [linstor] Update Piraeus Operator to v2.10.1 to enable RWX support (#1650)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does

This PR updates Piraeus Operator to enable RWX support released in
https://github.com/piraeusdatastore/piraeus-operator/releases/tag/v2.10.0

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[linstor] Update Piraeus Operator to v2.10.1 to enable RWX support
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added NFS server component and affinity controller support for
enhanced storage configuration
* Expanded kubectl output with additional status columns for improved
cluster visibility
* Added support for pod labels, annotations, and security context
customization

* **Chores**
  * Updated Helm chart to version 2.10.1
* Updated multiple component versions including CSI provisioner,
snapshotter, DRBD reactor, and other dependencies

* **Documentation**
* Updated README to reference external Helm-based deployment guidelines

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-25 14:44:39 +01:00
Andrei Kvapil
294458e7c4 [ci,dx] Add unit tests for cozy-lib (#1643)
## What this PR does

The cozy-lib library package got complicated enough to warrant its own
unit tests. Since unit tests are a "good thing" (tm), a somewhat generic
framework for running all kinds of unit tests was introduced into the CI
pipeline and Makefile targets. For now all it runs is `make test`
against the `packages/{library,apps,system,extra}/*` directories,
wherever a `test` target is present in the Makefile, and for now this is
only for the `cozy-lib` Helm library chart.

### Release note

```release-note
[ci,dx] Introduce a scaffold for running unit tests locally and in CI
and add the first unit tests for the cozy-lib helper Helm chart.
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Tests**
* Integrated Helm chart unit tests into the CI/CD pipeline for automated
validation.
* Established test infrastructure for cozy-lib package with test cases
for quota configuration and resource validation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-25 14:43:55 +01:00
nbykov0
42cb0e6974 [extra] ingress: nospaces for external ip list
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-11-24 20:31:34 +03:00
nbykov0
73bf0e5f7e Increase strimzi memory limit
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-11-24 19:57:57 +03:00
IvanHunters
f512061a1c add access to kubeapi from mysql agent
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-11-24 19:46:21 +03:00
Andrei Kvapil
12db4fc520 [linstor] Update Piraeus Operator to v2.10.1 to enable RWX support
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-11-24 10:51:21 +01:00
Kingdon B
8e351f1827 Upgrade Flux to 2.7 series
Flux 2.7.3 is currently the latest release, (I think Flux 2.7.4 is still
just around the corner.)

Signed-off-by: Kingdon B <kingdon@urmanac.com>
2025-11-23 19:40:08 -05:00
Kingdon B
38a4adfaa3 update flux-instance chart as well (v0.33.0)
Signed-off-by: Kingdon B <kingdon@urmanac.com>
2025-11-23 19:39:57 -05:00
Timofei Larkin
91ddbb06ef [cozy-lib] Improve flatten function
This patch breaks introduces a helper function in cozy-lib to correctly
handle special case resources when transforming a nested map of limits
and requests to a flat map suitable for use in resourceQuotas. As a
result, admins can now specify any types of resources as resource quotas
for tenants, and they will be correctly transformed to the correct
format for the underlying kubernetes ResourceQuota. In addition to the
previously supported compute resources, such as CPU, memory, and custom
resources, like GPUs, special quota strings such as
"services.loadbalancers" are now correctly handled.

```release-note
[cozy-lib,platform] Support resource quotas for special kubernetes
quotas, such as service.loadbalncer count and others.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-11-21 17:41:21 +03:00
IvanHunters
7d2250be4d [ci,dx] Bump MariaDB operator version
Update MariaDB operator to a new version.

```release-note
[ci,dx] Update MariaDB operator version
```

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-11-21 14:50:25 +03:00
IvanHunters
a070573af9 fix flatten for tests
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-11-20 12:01:49 +03:00
IvanHunters
492aef93f5 fix flatten with rabbit recomendation
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-11-20 10:55:47 +03:00
IvanHunters
23e6cf735a fix flatten with rabbit recomendation
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-11-20 10:55:47 +03:00
IvanHunters
c5b1177149 fix flatten with rabbit recomendation
Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-11-20 10:55:47 +03:00
IvanHunters
84133ef2d3 [cozy-lib] Fix malformed ResourceQuota rendering for LoadBalancer services
This patch adds special handling for raw Kubernetes ResourceQuota fields,
such as `services.loadbalancers`, preventing them from being wrapped as
`limits.*` or `requests.*` keys by the flatten helper. This ensures that
LoadBalancer quotas render correctly in tenant specifications.

```release-note
[cozy-lib] Correctly render services.loadbalancers in ResourceQuota without limits.* or requests.* prefixes.
```

Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
2025-11-20 10:55:47 +03:00
Timofei Larkin
1c9ae2bec5 [ci,dx] Add unit tests for cozy-lib
## What this PR does

The cozy-lib library package got complicated enough to warrant its own
unit tests. Since unit tests are a "good thing" (tm), a somewhat generic
framework for running all kinds of unit tests was introduced into the CI
pipeline and Makefile targets. For now all it runs is `make test`
against the `packages/{library,apps,system,extra}/*` directories,
wherever a `test` target is present in the Makefile, and for now this is
only for the `cozy-lib` Helm library chart.

### Release note

```release-note
[ci,dx] Introduce a scaffold for running unit tests locally and in CI
and add the first unit tests for the cozy-lib helper Helm chart.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-11-19 17:56:17 +03:00
Timofei Larkin
03885f5ae2 Merge branch 'main' into feat/external-kubeovn-build 2025-11-19 07:46:51 +03:00
Timofei Larkin
bdff61eaed Release v0.38.0-alpha.2 (#1639)
This PR prepares the release `v0.38.0-alpha.2`.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated container image references across system components from
v0.38.0-alpha.1 to v0.38.0-alpha.2, including kubevirt-csi-driver,
cozystack-api, cozystack-controller, dashboard, kamaji, kubeovn, and
related services.
  * Updated corresponding image digests to reflect new component builds.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-18 12:26:44 +04:00
cozystack-bot
3d4ad39bce Prepare release v0.38.0-alpha.2
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2025-11-18 07:46:42 +00:00
Timofei Larkin
f2f575b450 [dashboard] Introduce VNC console (#1627)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>

<!-- Thank you for making a contribution! Here are some tips for you:
- Start the PR title with the [label] of Cozystack component:
- For system components: [platform], [system], [linstor], [cilium],
[kube-ovn], [dashboard], [cluster-api], etc.
- For managed apps: [apps], [tenant], [kubernetes], [postgres],
[virtual-machine] etc.
- For development and maintenance: [tests], [ci], [docs], [maintenance].
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does


### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same [label] as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
[dashboard] Introduce VNC console
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added VNC tab for accessing VirtualMachine and VMInstance resources
directly from the dashboard

* **Chores**
  * Updated base images and builder references
* Enhanced proxy configuration with improved header handling and
extended connection timeouts

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-18 11:39:58 +04:00
Timofei Larkin
aba4d2c977 Merge branch 'main' into vnc
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-11-18 11:39:34 +04:00
Timofei Larkin
e4021bbf57 [vpc] Fix access to subnet details configmap (#1638)
## What this PR does

The VPC chart incorrectly used the wrong template for the subjects that
should have access to the configmap info resource. This patch grants
this access to all subjects at or above a certain access level, rather
than just at a specific level.

### Release note

```release-note
[vpc] Grant read access to the subnets configmap to all users inside a
tenant.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Enhanced role binding generation to better incorporate access level
information in subject configuration and access control setup.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-17 20:39:03 +04:00
Timofei Larkin
ef8612e882 [vpc] Fix access to subnet details configmap
## What this PR does

The VPC chart incorrectly used the wrong template for the subjects that
should have access to the configmap info resource. This patch grants
this access to all subjects at or above a certain access level, rather
than just at a specific level.

### Release note

```release-note
[vpc] Grant read access to the subnets configmap to all users inside a
tenant.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-11-17 19:00:41 +03:00
Nikita
32b58dec5f [apps] vpc: fix typo in README (#1637)
## What this PR does
VPC: fixed a typo in README

### Release note

```release-note
VPC: fixed a typo in README
```
2025-11-17 14:51:56 +03:00
Nikita
1bafb7fb4f [apps] vpc: fix typo in README
VPC: fixed a typo in README

Signed-off-by: Nikita <166552198+nbykov0@users.noreply.github.com>
2025-11-17 13:23:45 +03:00
Timofei Larkin
bc61d13ad3 Release v0.38.0-alpha.1 (#1635)
This PR prepares the release `v0.38.0-alpha.1`.
2025-11-14 14:17:36 +04:00
cozystack-bot
972548cab4 Prepare release v0.38.0-alpha.1
Signed-off-by: cozystack-bot <217169706+cozystack-bot@users.noreply.github.com>
2025-11-14 08:45:28 +00:00
Timofei Larkin
bb8d07d384 [vpc,dashboard] Print subnet details as table (#1621)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* VPC subnets are now displayed in the dashboard details view with
dedicated information blocks
* Subnet data is presented with improved formatting and structured
columns for better visibility
  * Access controls updated to support proper subnet data permissions
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-14 03:53:17 +04:00
Timofei Larkin
6fdc9b0bad [vpc,dashboard] Expose subnet details in dashboard
## What this PR does

To use the new VPC feature, users need to pass the subnet ID to the VMs
they wish to launch in a given VPC/subnet. As the dashboard cannot
compute the subnet ID in the same manner as the Helm template, a helper
configmap is created, containing the details of the subnets attached to
a given VPC. This configmap is queried by the dashboard frontend to
render those details to the user.

### Release note

```release-note
[vpc,dashboard] Expose subnet details to end-user in the dashboard.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-11-13 19:10:22 +03:00
Timofei Larkin
9c040cd42f [api] Fix representation of dynamic list kinds (#1630)
## What this PR does

This patch fixes an issue with the Cozystack API server that causes it
to respond with the first registered dynamic list kind when listing
dynamic resources. E.g., when running `k get postgreses`, the raw JSON
response from the cozystack API would be

```json
{
  "apiVersion":"apps.cozystack.io/v1alpha1",
  "kind":"BootBoxList",
  "items": [
    {
      "apiVersion":"apps.cozystack.io/v1alpha1",
      "kind":"Postgres",
      ...
    },
    ...
  ],
  ...
}
```

The root cause is the way the `Typer` interface is implemented for the
`runtime.Scheme` where the dynamic types are registered. Since the base
type for all dynamic types is a `&cozyv1alpha1.Application{}`, all types
are registered under the same key and the `Typer` defaults to the first
`GroupVersionKind` that was registered. Only when a correctly formed
`&unstructured.Unstructured{}` is returned by the API, is this resolving
logic circumvented and the `GroupVersionKind` is instead inferred from
the fields of the returned object. Even an `UnstructuredList` is not
acceptable as a return type, instead the `items` key should be directly
set on the underlying `map[string]interface{}`.

This patch implements the changes detailed above. Additionally, the
following features, fixes, and improvements are added:

* Makefile targets to build and run the Cozystack API locally, against a
Kubernetes server in the environment's KUBECONFIG. Debugging with Delve
is also supported.
* CI tests are added to verify the new changes.
* A bug in the registration of the corev1alpha1 types is fixed.
* Updated the `ConvertToTable` function to properly handle list kinds
which might be of the `&unstructured.Unstructured{}` concrete type (not
an `UnstructuredList`).
* The scheme used by the API server's Client and WatchClient is
separated from the scheme used to serve dynamic types.
* The client config for reading the runtime configuration now uses the
controller-runtime, which handles flags and environment variables
properly, unlike `clientcmd`.

### Release note

```release-note
[api] Fix incorrect list kind for list requests to the Cozystack API for
dynamic resources. Add Makefile targets for local testing. Minor schema
building improvements.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Tests**
* Added an end-to-end test validating Kubernetes API kinds for tenants
and ingresses.

* **Chores**
* Improved local development: ignore local API server config, added
run/debug targets with local TLS tooling, and added an OpenSSL config
for CSR generation.

* **Refactor**
* Internal API server and registry storage reworked; may affect
integrations expecting concrete resource types.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-13 19:52:50 +04:00
Timofei Larkin
5414d37376 [api] Fix representation of dynamic list kinds
## What this PR does

This patch fixes an issue with the Cozystack API server that causes it
to respond with the first registered dynamic list kind when listing
dynamic resources. E.g., when running `k get postgreses`, the raw JSON
response from the cozystack API would be

```json
{
  "apiVersion":"apps.cozystack.io/v1alpha1",
  "kind":"BootBoxList",
  "items": [
    {
      "apiVersion":"apps.cozystack.io/v1alpha1",
      "kind":"Postgres",
      ...
    },
    ...
  ],
  ...
}
```

The root cause is the way the `Typer` interface is implemented for the
`runtime.Scheme` where the dynamic types are registered. Since the base
type for all dynamic types is a `&cozyv1alpha1.Application{}`, all types
are registered under the same key and the `Typer` defaults to the first
`GroupVersionKind` that was registered. Only when a correctly formed
`&unstructured.Unstructured{}` is returned by the API, is this resolving
logic circumvented and the `GroupVersionKind` is instead inferred from
the fields of the returned object. Even an `UnstructuredList` is not
acceptable as a return type, instead the `items` key should be directly
set on the underlying `map[string]interface{}`.

This patch implements the changes detailed above. Additionally, the
following features, fixes, and improvements are added:

* Makefile targets to build and run the Cozystack API locally, against a
  Kubernetes server in the environment's KUBECONFIG. Debugging with
  Delve is also supported.
* CI tests are added to verify the new changes.
* A bug in the registration of the corev1alpha1 types is fixed.
* Updated the `ConvertToTable` function to properly handle list kinds
  which might be of the `&unstructured.Unstructured{}` concrete type
  (not an `UnstructuredList`).
* The scheme used by the API server's Client and WatchClient is
  separated from the scheme used to serve dynamic types.
* The client config for reading the runtime configuration now uses the
  controller-runtime, which handles flags and environment variables
  properly, unlike `clientcmd`.

### Release note

```release-note
[api] Fix incorrect list kind for list requests to the Cozystack API for
dynamic resources. Add Makefile targets for local testing. Minor schema
building improvements.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-11-13 18:04:33 +03:00
Timofei Larkin
a9818a7ce7 [kubernetes] Cleanup loadbalancer services (#1631)
## What this PR does

Similar to an earlier issue with DataVolumes remaining after deleting
the tenant k8s cluster using them, a similar problem is observed with
LoadBalancer services consuming external IPs. This patch adds another
step to the cleanup Helm hook to delete any such services.

### Release note

```release-note
[kubernetes] Add a cleanup hook to delete LoadBalancer services after
deleting the tenant Kubernetes cluster that they were servicing.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added automatic cleanup of LoadBalancer services during resource
deletion workflows.

* **Chores**
  * Updated resource naming conventions for consistency.
* Extended service management permissions in access control
configurations.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-13 18:16:58 +04:00
Timofei Larkin
1651d94291 [kubernetes] Cleanup loadbalancer services
## What this PR does

Similar to an earlier issue with DataVolumes remaining after deleting
the tenant k8s cluster using them, a similar problem is observed with
LoadBalancer services consuming external IPs. This patch adds another
step to the cleanup Helm hook to delete any such services.

### Release note

```release-note
[kubernetes] Add a cleanup hook to delete LoadBalancer services after
deleting the tenant Kubernetes cluster that they were servicing.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-11-13 16:27:34 +03:00
Nikita
2b4afde373 [system] multus: update to the latest version (#1628)
## What this PR does
Fixes #1623 

### Release note
```release-note
Multus updated to the latest version to address race condition during startup.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
  * Updated kube-multus container to version v4.2.3-thick.
* Increased memory resource allocation from 100Mi to 300Mi for improved
stability and performance.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-13 16:13:55 +03:00
Nikita
a5c9bfabee [system] kubeovn: increase limits (#1629)
## What this PR does
Increases kube-ovn-cni limits

### Release note
```release-note
Increased kube-ovn-cni limits so that it is not oomkilled during startup on busy nodes.
```
2025-11-13 16:13:23 +03:00
nbykov0
143832c0b4 [system] kubeovn: increase limits
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-11-13 14:50:11 +03:00
nbykov0
298206efc7 [system] multus: update to the latest version
Signed-off-by: nbykov0 <166552198+nbykov0@users.noreply.github.com>
2025-11-13 14:24:52 +03:00
Andrei Kvapil
c81b222cf6 [dashboard] Introduce VNC console
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-11-13 00:57:40 -05:00
Andrei Kvapil
9d6af84449 [rbac] Fix permissions for high-privilege users (#1622)
## What this PR does

This patch grants "admin" permissions to super-admins, "use" permissions
to admins and super-admins, "view" permissions to "use"-privileged
users, admins, and super-admins. Previously lower-privileged roles were
not assigned to higher-privileged users, so a viewer could excercise
their basic read-only permissions which were not available to
high-privilege users. This patch corrects the template function used to
generate subjects in rolebindings, fixing the issue.

### Release note

```release-note
[rbac] Fix issue of privileged users not having low-privilege read-only
permissions.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Updated access level handling in role-based authorization to ensure
proper permission evaluation across tenant environments.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-12 09:46:18 -05:00
Timofei Larkin
7ddd9cf4a8 [rbac] Fix permissions for high-privilege users
## What this PR does

This patch grants "admin" permissions to super-admins, "use" permissions
to admins and super-admins, "view" permissions to "use"-privileged
users, admins, and super-admins. Previously lower-privileged roles were
not assigned to higher-privileged users, so a viewer could excercise
their basic read-only permissions which were not available to
high-privilege users. This patch corrects the template function used to
generate subjects in rolebindings, fixing the issue.

### Release note

```release-note
[rbac] Fix issue of privileged users not having low-privilege read-only
permissions.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-11-12 14:09:40 +03:00
Timofei Larkin
a861814c24 [kubernetes] Make worker version configurable (#1619)
## What this PR does

The kubelet version of tenant k8s clusters is baked into the worker VM
image. Previously, selecting any version of tenant k8s had an impact
only on the controlplane, the workers were fixed at v1.33. This patch
modifies the KubeadmConfigTemplate to attempt to download the
user-selected versions of kubelet and kubeadm and replace the baked-in
versions with those. If failing, the bootstrap continues with the
baked-in versions.

### Release note

```release-note
[kubernetes] Make kubelet versions on tenant k8s clusters' worker nodes
user-configurable.
```

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Automated Kubernetes component update during bootstrap with x86_64 and
ARM64 support; invoked as part of pre-bootstrap steps to ensure
kubelet/kubeadm versions.

* **Tests**
  * Per-test isolated kubeconfig filenames to avoid conflicts.
* Simplified, stricter per-node version validation and alignment of
readiness checks; increased machine deployment readiness timeout to 10
minutes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-11-09 12:55:13 +04:00
Timofei Larkin
d65d293fbc [kubernetes] Make worker version configurable
## What this PR does

The kubelet version of tenant k8s clusters is baked into the worker VM
image. Previously, selecting any version of tenant k8s had an impact
only on the controlplane, the workers were fixed at v1.33. This patch
modifies the KubeadmConfigTemplate to attempt to download the
user-selected versions of kubelet and kubeadm and replace the baked-in
versions with those. If failing, the bootstrap continues with the
baked-in versions.

### Release note

```release-note
[kubernetes] Make kubelet versions on tenant k8s clusters' worker nodes
user-configurable.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-11-08 15:25:18 +03:00
Timofei Larkin
d26d3e1f40 [kubeovn] Package from external repo
Previously, all system charts have had their versions bumped with every
update of Cozystack, even if the underlying images and templates did not
change. Additionally, some components would have their docker images
rebuilt and get updated digests because of a changed docker context,
even though no relevant code had been changed. This would cause an
upgrade of several HelmReleases on every upgrade of Cozystack, even when
in practice nothing had changed. This is especially noticeable for
charts, such as kubeovn, which is a dependency for almost all other
system HelmReleases. By moving kubeovn out of the monorepo and
decoupling its release cycle from the release cycle of Cozystack, this
issue can be resolved and is another step towards decomposing Cozystack.

```release-note
[kubeovn] Decouple the release cycle of kubeovn from Cozystack's release
cycle, preventing unnecessary redeployments of all Helm releases, when
upgrading Cozystack.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
2025-10-19 16:00:56 +03:00
749 changed files with 63770 additions and 6711 deletions

188
.github/workflows/auto-release.yaml vendored Normal file
View File

@@ -0,0 +1,188 @@
name: Auto Patch Release
on:
schedule:
# Run daily at 2:00 AM CET (1:00 UTC in winter, 0:00 UTC in summer)
# Using 1:00 UTC to approximate 2:00 AM CET
- cron: '0 1 * * *'
workflow_dispatch: # Allow manual trigger
concurrency:
group: auto-release-${{ github.workflow }}
cancel-in-progress: false
jobs:
auto-release:
name: Auto Patch Release
runs-on: [self-hosted]
permissions:
contents: write
pull-requests: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Configure git
env:
GH_PAT: ${{ secrets.GH_PAT }}
run: |
git config user.name "cozystack-bot"
git config user.email "217169706+cozystack-bot@users.noreply.github.com"
git remote set-url origin https://cozystack-bot:${GH_PAT}@github.com/${GITHUB_REPOSITORY}
git config --unset-all http.https://github.com/.extraheader || true
- name: Process release branches
uses: actions/github-script@v7
env:
GH_PAT: ${{ secrets.GH_PAT }}
with:
github-token: ${{ secrets.GH_PAT }}
script: |
const { execSync } = require('child_process');
// Configure git to use PAT for authentication
execSync('git config user.name "cozystack-bot"', { encoding: 'utf8' });
execSync('git config user.email "217169706+cozystack-bot@users.noreply.github.com"', { encoding: 'utf8' });
execSync(`git remote set-url origin https://cozystack-bot:${process.env.GH_PAT}@github.com/${process.env.GITHUB_REPOSITORY}`, { encoding: 'utf8' });
// Remove GITHUB_TOKEN extraheader to ensure PAT is used (needed to trigger other workflows)
execSync('git config --unset-all http.https://github.com/.extraheader || true', { encoding: 'utf8' });
// Get all release-X.Y branches
const branches = execSync('git branch -r | grep -E "origin/release-[0-9]+\\.[0-9]+$" | sed "s|origin/||" | tr -d " "', { encoding: 'utf8' })
.split('\n')
.filter(b => b.trim())
.filter(b => /^release-\d+\.\d+$/.test(b));
console.log(`Found ${branches.length} release branches: ${branches.join(', ')}`);
// Get all published releases (not draft)
const allReleases = await github.rest.repos.listReleases({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100
});
// Filter to only published releases (not draft) with tags matching vX.Y.Z (no suffixes)
const publishedReleases = allReleases.data
.filter(r => !r.draft)
.filter(r => /^v\d+\.\d+\.\d+$/.test(r.tag_name));
console.log(`Found ${publishedReleases.length} published releases without suffixes`);
for (const branch of branches) {
console.log(`\n=== Processing branch: ${branch} ===`);
// Extract X.Y from branch name (release-X.Y)
const match = branch.match(/^release-(\d+\.\d+)$/);
if (!match) {
console.log(` ⚠️ Branch ${branch} doesn't match pattern, skipping`);
continue;
}
const [major, minor] = match[1].split('.');
const versionPrefix = `v${major}.${minor}.`;
console.log(` Looking for releases with prefix: ${versionPrefix}`);
// Find the latest published release for this branch (vX.Y.Z without suffixes)
const branchReleases = publishedReleases
.filter(r => r.tag_name.startsWith(versionPrefix))
.filter(r => /^v\d+\.\d+\.\d+$/.test(r.tag_name)); // Ensure no suffixes
if (branchReleases.length === 0) {
console.log(` ⚠️ No published releases found for ${branch}, skipping`);
continue;
}
// Sort by version (descending) to get the latest
branchReleases.sort((a, b) => {
const aVersion = a.tag_name.match(/^v(\d+)\.(\d+)\.(\d+)$/);
const bVersion = b.tag_name.match(/^v(\d+)\.(\d+)\.(\d+)$/);
if (!aVersion || !bVersion) return 0;
const aNum = parseInt(aVersion[1]) * 10000 + parseInt(aVersion[2]) * 100 + parseInt(aVersion[3]);
const bNum = parseInt(bVersion[1]) * 10000 + parseInt(bVersion[2]) * 100 + parseInt(bVersion[3]);
return bNum - aNum;
});
const latestRelease = branchReleases[0];
console.log(` ✅ Latest published release: ${latestRelease.tag_name}`);
// Get the commit SHA for this release tag
let releaseCommitSha;
try {
releaseCommitSha = execSync(`git rev-list -n 1 ${latestRelease.tag_name}`, { encoding: 'utf8' }).trim();
console.log(` Release commit SHA: ${releaseCommitSha}`);
} catch (error) {
console.log(` ⚠️ Could not find commit for tag ${latestRelease.tag_name}, skipping`);
continue;
}
// Checkout the branch
execSync(`git fetch origin ${branch}:${branch}`, { encoding: 'utf8' });
execSync(`git checkout ${branch}`, { encoding: 'utf8' });
// Get the latest commit on the branch
const latestBranchCommit = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim();
console.log(` Latest branch commit: ${latestBranchCommit}`);
// Check if there are new commits after the release
const commitsAfterRelease = execSync(
`git rev-list ${releaseCommitSha}..HEAD --oneline`,
{ encoding: 'utf8' }
).trim();
if (!commitsAfterRelease) {
console.log(` No new commits after ${latestRelease.tag_name}, skipping`);
continue;
}
console.log(` ✅ Found new commits after release:`);
console.log(commitsAfterRelease);
// Calculate next version (Z+1)
const versionMatch = latestRelease.tag_name.match(/^v(\d+)\.(\d+)\.(\d+)$/);
if (!versionMatch) {
console.log(` ❌ Could not parse version from ${latestRelease.tag_name}, skipping`);
continue;
}
const nextPatch = parseInt(versionMatch[3]) + 1;
const nextTag = `v${versionMatch[1]}.${versionMatch[2]}.${nextPatch}`;
console.log(` 🏷️ Creating new tag: ${nextTag} on commit ${latestBranchCommit}`);
// Create and push the tag with base_ref for workflow triggering
try {
// Delete local tag if exists to force update
try {
execSync(`git tag -d ${nextTag}`, { encoding: 'utf8' });
} catch (e) {
// Tag doesn't exist locally, that's fine
}
// Delete remote tag if exists
try {
execSync(`git push origin :refs/tags/${nextTag}`, { encoding: 'utf8' });
} catch (e) {
// Tag doesn't exist remotely, that's fine
}
// Create tag locally
execSync(`git tag ${nextTag} ${latestBranchCommit}`, { encoding: 'utf8' });
// Push tag with HEAD reference to preserve base_ref
execSync(`git push origin HEAD:refs/tags/${nextTag}`, { encoding: 'utf8' });
console.log(` ✅ Successfully created and pushed tag ${nextTag}`);
} catch (error) {
console.log(` ❌ Error creating/pushing tag ${nextTag}: ${error.message}`);
core.setFailed(`Failed to create tag ${nextTag} for branch ${branch}`);
}
}
console.log(`\n✅ Finished processing all release branches`);

View File

@@ -2,7 +2,7 @@ name: Automatic Backport
on:
pull_request_target:
types: [closed] # fires when PR is closed (merged)
types: [closed, labeled] # fires when PR is closed (merged) or labeled
concurrency:
group: backport-${{ github.workflow }}-${{ github.event.pull_request.number }}
@@ -13,22 +13,46 @@ permissions:
pull-requests: write
jobs:
backport:
# Determine which backports are needed
prepare:
if: |
github.event.pull_request.merged == true &&
contains(github.event.pull_request.labels.*.name, 'backport')
(
contains(github.event.pull_request.labels.*.name, 'backport') ||
contains(github.event.pull_request.labels.*.name, 'backport-previous') ||
(github.event.action == 'labeled' && (github.event.label.name == 'backport' || github.event.label.name == 'backport-previous'))
)
runs-on: [self-hosted]
outputs:
backport_current: ${{ steps.labels.outputs.backport }}
backport_previous: ${{ steps.labels.outputs.backport_previous }}
current_branch: ${{ steps.branches.outputs.current_branch }}
previous_branch: ${{ steps.branches.outputs.previous_branch }}
steps:
# 1. Decide which maintenance branch should receive the backport
- name: Determine target maintenance branch
id: target
- name: Check which labels are present
id: labels
uses: actions/github-script@v7
with:
script: |
let rel;
const pr = context.payload.pull_request;
const labels = pr.labels.map(l => l.name);
const isBackport = labels.includes('backport');
const isBackportPrevious = labels.includes('backport-previous');
core.setOutput('backport', isBackport ? 'true' : 'false');
core.setOutput('backport_previous', isBackportPrevious ? 'true' : 'false');
console.log(`backport label: ${isBackport}, backport-previous label: ${isBackportPrevious}`);
- name: Determine target branches
id: branches
uses: actions/github-script@v7
with:
script: |
// Get latest release
let latestRelease;
try {
rel = await github.rest.repos.getLatestRelease({
latestRelease = await github.rest.repos.getLatestRelease({
owner: context.repo.owner,
repo: context.repo.repo
});
@@ -36,18 +60,70 @@ jobs:
core.setFailed('No existing releases found; cannot determine backport target.');
return;
}
const [maj, min] = rel.data.tag_name.replace(/^v/, '').split('.');
const branch = `release-${maj}.${min}`;
core.setOutput('branch', branch);
console.log(`Latest release ${rel.data.tag_name}; backporting to ${branch}`);
const [maj, min] = latestRelease.data.tag_name.replace(/^v/, '').split('.');
const currentBranch = `release-${maj}.${min}`;
const prevMin = parseInt(min) - 1;
const previousBranch = prevMin >= 0 ? `release-${maj}.${prevMin}` : '';
core.setOutput('current_branch', currentBranch);
core.setOutput('previous_branch', previousBranch);
console.log(`Current branch: ${currentBranch}, Previous branch: ${previousBranch || 'N/A'}`);
// Verify previous branch exists if we need it
if (previousBranch && '${{ steps.labels.outputs.backport_previous }}' === 'true') {
try {
await github.rest.repos.getBranch({
owner: context.repo.owner,
repo: context.repo.repo,
branch: previousBranch
});
console.log(`Previous branch ${previousBranch} exists`);
} catch (e) {
core.setFailed(`Previous branch ${previousBranch} does not exist.`);
return;
}
}
backport:
needs: prepare
if: |
github.event.pull_request.merged == true &&
(needs.prepare.outputs.backport_current == 'true' || needs.prepare.outputs.backport_previous == 'true')
runs-on: [self-hosted]
strategy:
matrix:
backport_type: [current, previous]
steps:
# 1. Determine target branch based on matrix
- name: Set target branch
id: target
if: |
(matrix.backport_type == 'current' && needs.prepare.outputs.backport_current == 'true') ||
(matrix.backport_type == 'previous' && needs.prepare.outputs.backport_previous == 'true')
run: |
if [ "${{ matrix.backport_type }}" == "current" ]; then
echo "branch=${{ needs.prepare.outputs.current_branch }}" >> $GITHUB_OUTPUT
echo "Target branch: ${{ needs.prepare.outputs.current_branch }}"
else
echo "branch=${{ needs.prepare.outputs.previous_branch }}" >> $GITHUB_OUTPUT
echo "Target branch: ${{ needs.prepare.outputs.previous_branch }}"
fi
# 2. Checkout (required by backportaction)
- name: Checkout repository
if: steps.target.outcome == 'success'
uses: actions/checkout@v4
# 3. Create the backport pull request
- name: Create backport PR
uses: korthout/backport-action@v3
id: backport
if: steps.target.outcome == 'success'
uses: korthout/backport-action@v3.2.1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
label_pattern: '' # don't read labels for targets
target_branches: ${{ steps.target.outputs.branch }}
merge_commits: skip
conflict_resolution: draft_commit_conflicts

View File

@@ -28,7 +28,7 @@ jobs:
- name: Install generate
run: |
curl -sSL https://github.com/cozystack/cozyvalues-gen/releases/download/v1.0.5/cozyvalues-gen-linux-amd64.tar.gz | tar -xzvf- -C /usr/local/bin/ cozyvalues-gen
curl -sSL https://github.com/cozystack/cozyvalues-gen/releases/download/v1.0.6/cozyvalues-gen-linux-amd64.tar.gz | tar -xzvf- -C /usr/local/bin/ cozyvalues-gen
- name: Run pre-commit hooks
run: |

View File

@@ -46,7 +46,12 @@ jobs:
fetch-depth: 0
- name: Create tag on merge commit
env:
GH_PAT: ${{ secrets.GH_PAT }}
run: |
git config user.name "cozystack-bot"
git config user.email "217169706+cozystack-bot@users.noreply.github.com"
git remote set-url origin https://cozystack-bot:${GH_PAT}@github.com/${GITHUB_REPOSITORY}
git tag -f ${{ steps.get_tag.outputs.tag }} ${{ github.sha }}
git push -f origin ${{ steps.get_tag.outputs.tag }}
@@ -105,67 +110,95 @@ jobs:
}
}
# Get the latest published release
- name: Get the latest published release
id: latest_release
uses: actions/github-script@v7
with:
script: |
try {
const rel = await github.rest.repos.getLatestRelease({
owner: context.repo.owner,
repo: context.repo.repo
});
core.setOutput('tag', rel.data.tag_name);
} catch (_) {
core.setOutput('tag', '');
}
# Compare current tag vs latest using semver-utils
- name: Semver compare
id: semver
uses: madhead/semver-utils@v4.3.0
with:
version: ${{ steps.get_tag.outputs.tag }}
compare-to: ${{ steps.latest_release.outputs.tag }}
# Derive flags: prerelease? make_latest?
- name: Calculate publish flags
id: flags
uses: actions/github-script@v7
with:
script: |
const tag = '${{ steps.get_tag.outputs.tag }}'; // v0.31.5-rc.1
const m = tag.match(/^v(\d+\.\d+\.\d+)(-(?:alpha|beta|rc)\.\d+)?$/);
if (!m) {
core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-(alpha|beta|rc).N'`);
return;
}
const version = m[1] + (m[2] ?? ''); // 0.31.5-rc.1
const isRc = Boolean(m[2]);
core.setOutput('is_rc', isRc);
const outdated = '${{ steps.semver.outputs.comparison-result }}' === '<';
core.setOutput('make_latest', isRc || outdated ? 'false' : 'legacy');
# Publish draft release with correct flags
# Publish draft release and ensure correct latest flag
- name: Publish draft release
uses: actions/github-script@v7
with:
script: |
const tag = '${{ steps.get_tag.outputs.tag }}';
const m = tag.match(/^v(\d+\.\d+\.\d+)(-(?:alpha|beta|rc)\.\d+)?$/);
if (!m) {
core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-(alpha|beta|rc).N'`);
return;
}
const isRc = Boolean(m[2]);
// Parse semver string to comparable numbers
function parseSemver(v) {
const match = v.replace(/^v/, '').match(/^(\d+)\.(\d+)\.(\d+)/);
if (!match) return null;
return {
major: parseInt(match[1]),
minor: parseInt(match[2]),
patch: parseInt(match[3])
};
}
// Compare two semver objects
function compareSemver(a, b) {
if (a.major !== b.major) return a.major - b.major;
if (a.minor !== b.minor) return a.minor - b.minor;
return a.patch - b.patch;
}
const currentSemver = parseSemver(tag);
// Get all releases
const releases = await github.rest.repos.listReleases({
owner: context.repo.owner,
repo: context.repo.repo
});
const draft = releases.data.find(r => r.tag_name === tag && r.draft);
if (!draft) throw new Error(`Draft release for ${tag} not found`);
await github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: draft.id,
draft: false,
prerelease: ${{ steps.flags.outputs.is_rc }},
make_latest: '${{ steps.flags.outputs.make_latest }}'
repo: context.repo.repo,
per_page: 100
});
console.log(`🚀 Published release for ${tag}`);
// Find draft release to publish
const draft = releases.data.find(r => r.tag_name === tag && r.draft);
if (!draft) throw new Error(`Draft release for ${tag} not found`);
// Find max semver among published releases (excluding current draft)
const publishedReleases = releases.data
.filter(r => !r.draft && !r.prerelease)
.filter(r => /^v\d+\.\d+\.\d+$/.test(r.tag_name))
.map(r => ({ id: r.id, tag: r.tag_name, semver: parseSemver(r.tag_name) }))
.filter(r => r.semver !== null);
let maxRelease = null;
for (const rel of publishedReleases) {
if (!maxRelease || compareSemver(rel.semver, maxRelease.semver) > 0) {
maxRelease = rel;
}
}
// Determine if this release should be latest
const isOutdated = maxRelease && compareSemver(currentSemver, maxRelease.semver) < 0;
const makeLatest = (isRc || isOutdated) ? 'false' : 'true';
if (isRc) {
console.log(`🏷️ ${tag} is a prerelease, make_latest: false`);
} else if (isOutdated) {
console.log(`🏷️ ${tag} < ${maxRelease.tag} (max semver), make_latest: false`);
} else {
console.log(`🏷️ ${tag} is the highest version, make_latest: true`);
}
// Publish the release
await github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: draft.id,
draft: false,
prerelease: isRc,
make_latest: makeLatest
});
console.log(`🚀 Published release ${tag}`);
// If this is a backport/outdated release, ensure the correct release is marked as latest
if (isOutdated && maxRelease) {
console.log(`🔧 Ensuring ${maxRelease.tag} remains the latest release...`);
await github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: maxRelease.id,
make_latest: 'true'
});
console.log(`✅ Restored ${maxRelease.tag} as latest release`);
}

View File

@@ -33,6 +33,9 @@ jobs:
fetch-depth: 0
fetch-tags: true
- name: Run unit tests
run: make unit-tests
- name: Set up Docker config
run: |
if [ -d ~/.docker ]; then
@@ -55,7 +58,7 @@ jobs:
DOCKER_CONFIG: ${{ runner.temp }}/.docker
- name: Build Talos image
run: make -C packages/core/installer talos-nocloud
run: make -C packages/core/talos talos-nocloud
- name: Save git diff as patch
if: "!contains(github.event.pull_request.labels.*.name, 'release')"

78
.github/workflows/retest.yaml vendored Normal file
View File

@@ -0,0 +1,78 @@
name: Retest
on:
issue_comment:
types: [created]
jobs:
retest:
name: Retest PR
runs-on: ubuntu-latest
if: |
github.event.issue.pull_request &&
contains(github.event.comment.body, '/retest')
permissions:
actions: write
pull-requests: read
steps:
- name: Rerun from Prepare environment
uses: actions/github-script@v7
with:
script: |
const prNumber = context.issue.number;
// Get the PR to find the head SHA
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
// Find the latest workflow run for this PR
const runs = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'pull-requests.yaml',
head_sha: pr.data.head.sha
});
if (runs.data.workflow_runs.length === 0) {
core.setFailed('No workflow runs found for this PR');
return;
}
const latestRun = runs.data.workflow_runs[0];
console.log(`Found workflow run: ${latestRun.id} (${latestRun.status})`);
// Check if workflow is waiting for approval (fork PRs)
if (latestRun.conclusion === 'action_required') {
core.setFailed('Workflow is waiting for approval. A maintainer must approve the workflow first.');
return;
}
// Get jobs for this run
const jobs = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: latestRun.id
});
// Find "Prepare environment" job
const prepareJob = jobs.data.jobs.find(j => j.name === 'Prepare environment');
if (!prepareJob) {
core.setFailed('Could not find "Prepare environment" job');
return;
}
console.log(`Found job: ${prepareJob.name} (id: ${prepareJob.id}, status: ${prepareJob.status})`);
// Rerun the job
await github.rest.actions.reRunJobForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
job_id: prepareJob.id
});
console.log(`✅ Triggered rerun of job "${prepareJob.name}" (${prepareJob.id})`);

View File

@@ -123,32 +123,6 @@ jobs:
git commit -m "Prepare release ${GITHUB_REF#refs/tags/}" -s || echo "No changes to commit"
git push origin HEAD || true
# Get `latest_version` from latest published release
- name: Get latest published release
if: steps.check_release.outputs.skip == 'false'
id: latest_release
uses: actions/github-script@v7
with:
script: |
try {
const rel = await github.rest.repos.getLatestRelease({
owner: context.repo.owner,
repo: context.repo.repo
});
core.setOutput('tag', rel.data.tag_name);
} catch (_) {
core.setOutput('tag', '');
}
# Compare tag (A) with latest (B)
- name: Semver compare
if: steps.check_release.outputs.skip == 'false'
id: semver
uses: madhead/semver-utils@v4.3.0
with:
version: ${{ steps.tag.outputs.tag }} # A
compare-to: ${{ steps.latest_release.outputs.tag }} # B
# Create or reuse draft release
- name: Create / reuse draft release
if: steps.check_release.outputs.skip == 'false'

View File

@@ -0,0 +1,92 @@
name: Update Release Notes
on:
push:
branches:
- main
concurrency:
group: update-releasenotes-${{ github.workflow }}
cancel-in-progress: false
jobs:
update-releasenotes:
name: Update Release Notes
runs-on: [self-hosted]
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Update release notes from changelogs
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const changelogDir = 'docs/changelogs';
// Get releases from first page
const releases = await github.rest.repos.listReleases({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 30
});
console.log(`Found ${releases.data.length} releases (first page only)`);
// Process each release
for (const release of releases.data) {
const tag = release.tag_name;
const changelogFile = `${tag}.md`;
const changelogPath = path.join(changelogDir, changelogFile);
console.log(`\nProcessing release: ${tag}`);
// Check if changelog file exists
if (!fs.existsSync(changelogPath)) {
console.log(` ⚠️ Changelog file ${changelogFile} does not exist, skipping...`);
continue;
}
// Read changelog file content
let changelogContent;
try {
changelogContent = fs.readFileSync(changelogPath, 'utf8');
} catch (error) {
console.log(` ❌ Error reading file ${changelogPath}: ${error.message}`);
continue;
}
if (!changelogContent.trim()) {
console.log(` ⚠️ Changelog file ${changelogFile} is empty, skipping...`);
continue;
}
// Check if content is already up to date
const currentBody = release.body || '';
if (currentBody.trim() === changelogContent.trim()) {
console.log(` ✓ Content is already up to date, skipping...`);
continue;
}
// Update release notes
try {
await github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release.id,
body: changelogContent
});
console.log(` ✅ Successfully updated release notes for ${tag}`);
} catch (error) {
console.log(` ❌ Error updating release ${tag}: ${error.message}`);
core.setFailed(`Failed to update release notes for ${tag}`);
}
}

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
_out
_repos
.git
.idea
.vscode

View File

@@ -32,4 +32,4 @@ This list is sorted in chronological order, based on the submission date.
| [Urmanac](https://urmanac.com) | @kingdonb | 2024-12-04 | Urmanac is the future home of a hosting platform for the knowledge base of a community of personal server enthusiasts. We use Cozystack to provide support services for web sites hosted using both conventional deployments and on SpinKube, with WASM. |
| [Hidora](https://hikube.cloud) | @matthieu-robin | 2025-09-17 | Hidora is a Swiss cloud provider delivering managed services and infrastructure solutions through datacenters located in Switzerland, ensuring data sovereignty and reliability. Its sovereign cloud platform, Hikube, is designed to run workloads with high availability across multiple datacenters, providing enterprises with a secure and scalable foundation for their applications based on Cozystack. |
| [QOSI](https://qosi.kz) | @tabu-a | 2025-10-04 | QOSI is a non-profit organization driving open-source adoption and digital sovereignty across Kazakhstan and Central Asia. We use Cozystack as a platform for deploying sovereign, GPU-enabled clouds and educational environments under the National AI Program. Our goal is to accelerate the regions transition toward open, self-hosted cloud-native technologies |
|
| [Cloupard](https://cloupard.kz/) | @serjiott | 2025-12-18 | Cloupard is a public cloud provider offering IaaS and PaaS services via datacenters in Kazakhstan and Uzbekistan. Uses CozyStack on bare metal to extend its managed PaaS offerings. |

499
AGENTS.md
View File

@@ -1,449 +1,62 @@
# AGENTS.md
# AI Agents Overview
This file provides structured guidance for AI coding assistants and agents
working with the **Cozystack** project.
## Activation
**CRITICAL**: When the user asks you to do something that matches the scope of a documented process, you MUST read the corresponding documentation file and follow the instructions exactly as written.
- **Commits, PRs, git operations** (e.g., "create a commit", "make a PR", "fix review comments", "rebase", "cherry-pick")
- Read: [`contributing.md`](./docs/agents/contributing.md)
- Action: Read the entire file and follow ALL instructions step-by-step
- **Changelog generation** (e.g., "generate changelog", "create changelog", "prepare changelog for version X")
- Read: [`changelog.md`](./docs/agents/changelog.md)
- Action: Read the entire file and follow ALL steps in the checklist. Do NOT skip any mandatory steps
- **Release creation** (e.g., "create release", "prepare release", "tag release", "make a release")
- Read: [`releasing.md`](./docs/agents/releasing.md)
- Action: Read the file and follow the referenced release process in `docs/release.md`
- **Project structure, conventions, code layout** (e.g., "where should I put X", "what's the convention for Y", "how is the project organized")
- Read: [`overview.md`](./docs/agents/overview.md)
- Action: Read relevant sections to understand project structure and conventions
- **General questions about contributing**
- Read: [`contributing.md`](./docs/agents/contributing.md)
- Action: Read the file to understand git workflow, commit format, PR process
**Important rules:**
-**ONLY read the file if the task matches the documented process scope** - do not read files for tasks that don't match their purpose
-**ALWAYS read the file FIRST** before starting the task (when applicable)
-**Follow instructions EXACTLY** as written in the documentation
-**Do NOT skip mandatory steps** (especially in changelog.md)
-**Do NOT assume** you know the process - always check the documentation when the task matches
-**Do NOT read files** for tasks that are outside their documented scope
- 📖 **Note**: [`overview.md`](./docs/agents/overview.md) can be useful as a reference to understand project structure and conventions, even when not explicitly required by the task
## Project Overview
Cozystack is an open-source Kubernetes-based platform and framework for building cloud infrastructure. It provides:
- **Managed Services**: Databases, VMs, Kubernetes clusters, object storage, and more
- **Multi-tenancy**: Full isolation and self-service for tenants
- **GitOps-driven**: FluxCD-based continuous delivery
- **Modular Architecture**: Extensible with custom packages and services
- **Developer Experience**: Simplified local development with cozypkg tool
The platform exposes infrastructure services via the Kubernetes API with ready-made configs, built-in monitoring, and alerts.
## Code Layout
```
.
├── packages/ # Main directory for cozystack packages
│ ├── core/ # Core platform logic charts (installer, platform)
│ ├── system/ # System charts (CSI, CNI, operators, etc.)
│ ├── apps/ # User-facing charts shown in dashboard catalog
│ └── extra/ # Tenant-specific applications
├── dashboards/ # Grafana dashboards for monitoring
├── hack/ # Helper scripts for local development
│ └── e2e-apps/ # End-to-end application tests
├── scripts/ # Scripts used by cozystack container
│ └── migrations/ # Version migration scripts
├── docs/ # Documentation
│ └── changelogs/ # Release changelogs
├── cmd/ # Go command entry points
│ ├── cozystack-api/
│ ├── cozystack-controller/
│ └── cozystack-assets-server/
├── internal/ # Internal Go packages
│ ├── controller/ # Controller implementations
│ └── lineagecontrollerwebhook/
├── pkg/ # Public Go packages
│ ├── apis/
│ ├── apiserver/
│ └── registry/
└── api/ # Kubernetes API definitions (CRDs)
└── v1alpha1/
```
### Package Structure
Every package is a Helm chart following the umbrella chart pattern:
```
packages/<category>/<package-name>/
├── Chart.yaml # Chart definition and parameter docs
├── Makefile # Development workflow targets
├── charts/ # Vendored upstream charts
├── images/ # Dockerfiles and image build context
├── patches/ # Optional upstream chart patches
├── templates/ # Additional manifests
├── templates/dashboard-resourcemap.yaml # Dashboard resource mapping
├── values.yaml # Override values for upstream
└── values.schema.json # JSON schema for validation and UI
```
## Conventions
### Helm Charts
- Follow **umbrella chart** pattern for system components
- Include upstream charts in `charts/` directory (vendored, not referenced)
- Override configuration in root `values.yaml`
- Use `values.schema.json` for input validation and dashboard UI rendering
### Go Code
- Follow standard **Go conventions** and idioms
- Use **controller-runtime** patterns for Kubernetes controllers
- Namespaces follow pattern: `github.com/cozystack/cozystack/<path>`
- Add proper error handling and structured logging
- Use `declare(strict_types=1)` equivalent (Go's type safety)
### Git Commits
- Use format: `[component] Description`
- Reference PR numbers when available
- Keep commits atomic and focused
- Follow conventional commit format for changelogs
### Documentation
- Keep README files current
- Document breaking changes clearly
- Update relevant docs when making changes
- Use clear, concise language with code examples
## Development Workflow
### Standard Make Targets
Every package includes a `Makefile` with these targets:
```bash
make update # Update Helm chart and versions from upstream
make image # Build Docker images used in the package
make show # Show rendered Helm templates
make diff # Diff Helm release against live cluster objects
make apply # Apply Helm release to Kubernetes cluster
```
### Using cozypkg
The `cozypkg` tool wraps Helm and Flux for local development:
```bash
cozypkg show # Render manifests (helm template)
cozypkg diff # Show live vs desired manifests
cozypkg apply # Upgrade/install HelmRelease and sync
cozypkg suspend # Suspend Flux reconciliation
cozypkg resume # Resume Flux reconciliation
cozypkg get # Get HelmRelease resources
cozypkg list # List all HelmReleases
cozypkg delete # Uninstall release
cozypkg reconcile # Trigger Flux reconciliation
```
### Example: Updating a Component
```bash
cd packages/system/cilium # Navigate to package
make update # Pull latest upstream
make image # Build images
git diff . # Review manifest changes
make diff # Compare with cluster
make apply # Deploy to cluster
kubectl get pod -n cozy-cilium # Verify deployment
git commit -m "[cilium] Update to vX.Y.Z"
```
## Adding New Packages
### For System Components (operators, CNI, CSI, etc.)
1. Create directory: `packages/system/<component-name>/`
2. Create `Chart.yaml` with component metadata
3. Add upstream chart to `charts/` directory
4. Create `values.yaml` with overrides
5. Generate `values.schema.json` using `readme-generator`
6. Add `Makefile` using `scripts/package.mk`
7. Create `images/` directory if custom images needed
8. Add to bundle configuration in `packages/core/platform/`
9. Write tests in `hack/e2e-apps/`
10. Update documentation
### For User Applications (apps catalog)
1. Create directory: `packages/apps/<app-name>/`
2. Define minimal user-facing parameters in `values.schema.json`
3. Use Cozystack API for high-level resources
4. Add `templates/dashboard-resourcemap.yaml` for UI display
5. Keep business logic in system operators, not in app charts
6. Test deployment through dashboard
7. Document usage in README
### For Extra/Tenant Applications
1. Create in `packages/extra/<app-name>/`
2. Follow same structure as apps
3. Not shown in catalog
4. Installable only as tenant component
5. One application type per tenant namespace
## Tests and CI
### Local Testing
- **Unit tests**: Go tests in `*_test.go` files
- **Integration tests**: BATS scripts in `hack/e2e-apps/`
- **E2E tests**: Full platform tests via `hack/e2e.sh`
### Running E2E Tests
```bash
cd packages/core/testing
make apply # Create testing sandbox in cluster
make test # Run end-to-end tests
make delete # Remove testing sandbox
# Or locally with QEMU VMs:
./hack/e2e.sh
```
### CI Pipeline
- Automated tests run on every PR
- Image builds for changed packages
- Manifest diff generation
- E2E tests on full platform
- Release packaging and publishing
### Testing Environment Commands
```bash
make exec # Interactive shell in sandbox
make login # Download kubeconfig (requires mirrord)
make proxy # Enable SOCKS5 proxy (requires mirrord + gost)
```
## Things Agents Should Not Do
### Never Edit These
- Do not modify files in `/vendor/` (Go dependencies)
- Do not edit generated files: `zz_generated.*.go`
- Do not change `go.mod`/`go.sum` manually (use `go get`)
- Do not edit upstream charts in `packages/*/charts/` directly (use patches)
- Do not modify image digests in `values.yaml` (generated by build)
### Version Control
- Do not commit built artifacts from `packages/*/build/`
- Do not commit generated dashboards
- Do not commit test artifacts or temporary files
### Git Operations
- Do not force push to main/master
- Do not skip hooks (--no-verify, --no-gpg-sign)
- Do not update git config
- Do not perform destructive operations without explicit request
### Changelogs
- Do not manually edit `docs/changelogs/*.md` outside of changelog workflow
- Follow changelog agent rules in `.cursor/changelog-agent.md`
- Use structured format from templates
### Core Components
- Do not modify `packages/core/installer/installer.sh` without understanding migration impact
- Do not change `packages/core/platform/` logic without testing full bootstrap
- Do not alter FluxCD configurations without considering reconciliation loops
## Special Workflows
### Changelog Generation
When working with changelogs (see `.cursor/changelog-agent.md` for details):
1. **Activation**: Automatic when user mentions "changelog" or works in `docs/changelogs/`
2. **Commands**:
- "Create changelog for vX.Y.Z" → Generate from git history
- "Review changelog vX.Y.Z" → Analyze quality
- "Update changelog with PR #XXXX" → Add entry
3. **Process**:
- Extract version and range
- Run git log between versions
- Categorize by BMAD framework
- Generate structured output
- Validate against checklist
4. **Templates**: Use `patch-template.md` or `template.md`
### Building Cozystack Container
```bash
cd packages/core/installer
make image-cozystack # Build cozystack image
make apply # Apply to cluster
kubectl get pod -n cozy-system
kubectl get hr -A # Check HelmRelease objects
```
### Building with Custom Registry
```bash
export REGISTRY=my-registry.example.com/cozystack
cd packages/system/component-name
make image
make apply
```
## Buildx Configuration
Install and configure Docker buildx for multi-arch builds:
```bash
# Kubernetes driver (build in cluster)
docker buildx create \
--bootstrap \
--name=buildkit \
--driver=kubernetes \
--driver-opt=namespace=tenant-kvaps,replicas=2 \
--platform=linux/amd64 \
--platform=linux/arm64 \
--use
# Or use local Docker (omit --driver* options)
docker buildx create --bootstrap --name=local --use
```
## References
- [Cozystack Documentation](https://cozystack.io/docs/)
- [Developer Guide](https://cozystack.io/docs/development/)
- [GitHub Repository](https://github.com/cozystack/cozystack)
- [Helm Documentation](https://helm.sh/docs/)
- [FluxCD Documentation](https://fluxcd.io/flux/)
- [cozypkg Tool](https://github.com/cozystack/cozypkg)
- [Kubernetes Operator Patterns](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)
- [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime)
## Community
- [Telegram](https://t.me/cozystack)
- [Slack](https://kubernetes.slack.com/archives/C06L3CPRVN1)
- [Community Calendar](https://calendar.google.com/calendar?cid=ZTQzZDIxZTVjOWI0NWE5NWYyOGM1ZDY0OWMyY2IxZTFmNDMzZTJlNjUzYjU2ZGJiZGE3NGNhMzA2ZjBkMGY2OEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t)
---
## Machine-Readable Summary
```yaml
project: Cozystack
type: kubernetes-platform
description: Open-source platform for building cloud infrastructure
architecture: kubernetes-based, gitops-driven, multi-tenant
layout:
packages/:
core/: platform bootstrap and configuration
system/: cluster-wide components (CSI, CNI, operators)
apps/: user-facing applications (catalog)
extra/: tenant-specific applications
dashboards/: grafana monitoring dashboards
hack/: development scripts and e2e tests
scripts/: runtime scripts and migrations
cmd/: go command entry points
internal/: internal go packages
pkg/: public go packages
api/: kubernetes api definitions (CRDs)
docs/: documentation and changelogs
package_structure:
Chart.yaml: helm chart definition
Makefile: development workflow targets
charts/: vendored upstream charts
images/: docker image sources
patches/: upstream chart patches
templates/: additional manifests
values.yaml: configuration overrides
values.schema.json: validation schema and UI hints
workflow:
development_tool: cozypkg
commands:
- update: pull upstream charts
- image: build docker images
- show: render manifests
- diff: compare with cluster
- apply: deploy to cluster
gitops_engine: FluxCD
package_manager: Helm
conventions:
helm:
pattern: umbrella chart
upstream: vendored in charts/
overrides: root values.yaml
go:
style: standard go conventions
framework: controller-runtime
namespace: github.com/cozystack/cozystack
git:
commit_format: "[component] Description"
reference_prs: true
atomic_commits: true
testing:
unit: go test
integration: bats scripts (hack/e2e-apps/)
e2e: hack/e2e.sh
sandbox:
location: packages/core/testing
commands: [apply, test, delete, exec, login, proxy]
ci:
triggers: every PR
checks:
- automated tests
- image builds
- manifest diffs
- e2e tests
- packaging
special_agents:
changelog:
activation:
- files in docs/changelogs/
- user mentions "changelog"
- changelog-related requests
config_file: .cursor/changelog-agent.md
templates:
- docs/changelogs/patch-template.md
- docs/changelogs/template.md
framework: BMAD categorization
do_not_edit:
- vendor/
- zz_generated.*.go
- packages/*/charts/* (use patches)
- go.mod manually
- go.sum manually
- image digests in values.yaml
- built artifacts
tools:
required:
- kubectl
- helm
- docker buildx
- make
- go
recommended:
- cozypkg
- mirrord
- gost
- readme-generator
core_components:
bootstrap:
- packages/core/installer (installer.sh, assets server)
- packages/core/platform (flux config, reconciliation)
api:
- cmd/cozystack-api (api server)
- cmd/cozystack-controller (main controller)
- api/v1alpha1 (CRD definitions)
delivery:
- FluxCD Helm Controller
- HelmRelease custom resources
bundle_system:
definition: packages/core/platform/
components_from: packages/system/
user_applications: packages/apps/ + packages/extra/
tenant_isolation: namespace-based
one_app_type_per_tenant: true
image_management:
location: packages/*/images/
build: make image
injection: automatic to values.yaml
format: path + digest
registry: configurable via REGISTRY env var
multi_arch:
tool: docker buildx
platforms: [linux/amd64, linux/arm64]
driver_options: [kubernetes, docker]
```
**Cozystack** is a Kubernetes-based platform for building cloud infrastructure with managed services (databases, VMs, K8s clusters), multi-tenancy, and GitOps delivery.
## Quick Reference
### Code Structure
- `packages/core/` - Core platform charts (installer, platform)
- `packages/system/` - System components (CSI, CNI, operators)
- `packages/apps/` - User-facing applications in catalog
- `packages/extra/` - Tenant-specific modules
- `cmd/`, `internal/`, `pkg/` - Go code
- `api/` - Kubernetes CRDs
### Conventions
- **Helm Charts**: Umbrella pattern, vendored upstream charts in `charts/`
- **Go Code**: Controller-runtime patterns, kubebuilder style
- **Git Commits**: `[component] Description` format with `--signoff`
### What NOT to Do
- ❌ Edit `/vendor/`, `zz_generated.*.go`, upstream charts directly
- ❌ Modify `go.mod`/`go.sum` manually (use `go get`)
- ❌ Force push to main/master
- ❌ Commit built artifacts from `_out`

View File

@@ -1,4 +1,4 @@
.PHONY: manifests repos assets
.PHONY: manifests repos assets unit-tests helm-unit-tests
build-deps:
@command -V find docker skopeo jq gh helm > /dev/null
@@ -17,7 +17,7 @@ build: build-deps
make -C packages/system/cozystack-controller image
make -C packages/system/lineage-controller-webhook image
make -C packages/system/cilium image
make -C packages/system/kubeovn image
make -C packages/system/linstor image
make -C packages/system/kubeovn-webhook image
make -C packages/system/kubeovn-plunger image
make -C packages/system/dashboard image
@@ -26,6 +26,8 @@ build: build-deps
make -C packages/system/bucket image
make -C packages/system/objectstorage-controller image
make -C packages/core/testing image
make -C packages/core/talos image
make -C packages/core/platform image
make -C packages/core/installer image
make manifests
@@ -40,12 +42,17 @@ manifests:
(cd packages/core/installer/; helm template -n cozy-installer installer .) > _out/assets/cozystack-installer.yaml
assets:
make -C packages/core/installer assets
make -C packages/core/talos assets
test:
make -C packages/core/testing apply
make -C packages/core/testing test
unit-tests: helm-unit-tests
helm-unit-tests:
hack/helm-unit-tests.sh
prepare-env:
make -C packages/core/testing apply
make -C packages/core/testing prepare-cluster

View File

@@ -200,22 +200,6 @@ func main() {
os.Exit(1)
}
if err = (&controller.TenantHelmReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "TenantHelmReconciler")
os.Exit(1)
}
if err = (&controller.CozystackConfigReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "CozystackConfigReconciler")
os.Exit(1)
}
cozyAPIKind := "DaemonSet"
if reconcileDeployment {
cozyAPIKind = "Deployment"
@@ -229,6 +213,14 @@ func main() {
os.Exit(1)
}
if err = (&controller.CozystackResourceDefinitionHelmReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "CozystackResourceDefinitionHelmReconciler")
os.Exit(1)
}
dashboardManager := &dashboard.Manager{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),

666
docs/agents/changelog.md Normal file
View File

@@ -0,0 +1,666 @@
# Changelog Generation Instructions
This file contains detailed instructions for AI-powered IDE on how to generate changelogs for Cozystack releases.
## When to use these instructions
Follow these instructions when the user explicitly asks to generate a changelog.
## Required Tools
Before generating changelogs, ensure you have access to `gh` (GitHub CLI) tool, which is used to fetch commit and PR author information. The GitHub CLI is used to correctly identify PR authors from commits and pull requests.
## Changelog Generation Process
When the user asks to generate a changelog, follow these steps in the specified order:
**CHECKLIST - All actions that must be completed:**
- [ ] Step 1: Update information from remote (git fetch)
- [ ] Step 2: Check current branch (must be main)
- [ ] Step 3: Determine release type and previous version (minor vs patch release)
- [ ] Step 4: Determine versions and analyze existing changelogs
- [ ] Step 5: Get the list of commits for the release period
- [ ] Step 6: Check additional repositories (website is REQUIRED, optional repos if tags exist)
- [ ] **MANDATORY**: Check website repository for documentation changes WITH authors and PR links via GitHub CLI
- [ ] **MANDATORY**: Check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy) for tags during release period
- [ ] **MANDATORY**: For ALL commits from additional repos, get GitHub username via CLI, prioritizing PR author over commit author.
- [ ] Step 7: Analyze commits (extract PR numbers, authors, user impact)
- [ ] **MANDATORY**: For EVERY PR in main repo, get PR author via `gh pr view <PR_NUMBER> --json author --jq .author.login` (do NOT skip this step)
- [ ] **MANDATORY**: Extract PR numbers from commit messages, then use `gh pr view` for each PR to get the PR author. Do NOT use commit author. Only for commits without PR numbers (rare), fall back to `gh api repos/cozystack/cozystack/commits/<hash> --jq '.author.login'`
- [ ] Step 8: Form new changelog (structure, format, generate contributors list)
- [ ] Step 9: Verify completeness and save
### 1. Updating information from remote
```bash
git fetch --tags --force --prune
```
This is necessary to get up-to-date information about tags and commits from the remote repository.
### 2. Checking current branch
Make sure we are on the `main` branch:
```bash
git branch --show-current
```
### 3. Determining release type and previous version
**Important**: Determine if you're generating a changelog for a **minor release** (vX.Y.0) or a **patch release** (vX.Y.Z where Z > 0).
**For minor releases (vX.Y.0):**
- Each minor version lives and evolves in its own branch (`release-X.Y`)
- You MUST compare with the **previous minor version** (v(X-1).Y.0), not the last patch release
- This ensures you capture all changes from the entire minor version cycle, including all patch releases
- Example: For v0.38.0, compare with v0.37.0 (not v0.37.8)
- Run a separate cycle to check the diff with the zero version of the previous minor release
**For patch releases (vX.Y.Z where Z > 0):**
- Compare with the previous patch version (vX.Y.(Z-1))
- Example: For v0.37.2, compare with v0.37.1
### 4. Determining versions and analyzing existing changelogs
**Determine the last published version:**
1. Get the list of version tags:
```bash
git tag -l 'v[0-9]*.[0-9]*.[0-9]*' | sort -V
```
2. Get the last tag:
```bash
git tag -l 'v[0-9]*.[0-9]*.[0-9]*' | sort -V | tail -1
```
3. Compare tags with existing changelog files in `docs/changelogs/` to determine the last published version (the newest file `vX.Y.Z.md`)
**Study existing changelog format:**
- Review recent changelog files to understand the format and structure
- Pay attention to:
- **Feature Highlights format** (for minor releases): Use `## Feature Highlights` with `### Feature Name` subsections containing detailed descriptions (2-4 paragraphs each). See v0.35.0 and v0.36.0 for examples.
- Section structure (Major Features and Improvements, Security, Fixes, Dependencies, etc.)
- PR link format (e.g., `[**@username**](https://github.com/username) in #1234`)
- Change description style
- Presence of Breaking changes sections, etc.
### 5. Getting the list of commits
**Important**: Determine if you're generating a changelog for a **minor release** (vX.Y.0) or a **patch release** (vX.Y.Z where Z > 0).
**For patch releases (vX.Y.Z where Z > 0):**
Get the list of commits starting from the previous patch version to HEAD:
**⚠️ CRITICAL: Do NOT use --first-parent flag! It will skip merge commits including backports!**
```bash
# Get all commits including merge commits (backports)
git log <previous_version>..HEAD --pretty=format:"%h - %s (%an, %ar)"
```
For example, if generating changelog for `v0.37.2`:
```bash
git log v0.37.1..HEAD --pretty=format:"%h - %s (%an, %ar)"
```
**⚠️ IMPORTANT: Check for backports:**
- Look for commits with "[Backport release-X.Y]" in the commit message
- For backport PRs, find the original PR number mentioned in the backport commit message or PR description
- Use the original PR author (not the backport PR author) when creating changelog entries
- Include both the original PR number and backport PR number in the changelog entry (e.g., `#1606, #1609`)
**For minor releases (vX.Y.0):**
Minor releases must include **all changes** from patch releases of the previous minor version. Get commits from the previous minor release:
**⚠️ CRITICAL: Do NOT use --first-parent flag! It will skip merge commits including backports!**
```bash
# For v0.38.0, get all commits since v0.37.0 (including all patch releases v0.37.1, v0.37.2, etc.)
git log v<previous_minor_version>..HEAD --pretty=format:"%h - %s (%an, %ar)"
```
For example, if generating changelog for `v0.38.0`:
```bash
git log v0.37.0..HEAD --pretty=format:"%h - %s (%an, %ar)"
```
This will include all commits from v0.37.1, v0.37.2, v0.37.3, etc., up to v0.38.0.
**⚠️ IMPORTANT: Always check merge commits:**
- Merge commits may contain backports that need to be included
- Check all commits in the range, including merge commits
- For backports, always find and reference the original PR
### 6. Analyzing additional repositories
**⚠️ CRITICAL: This step is MANDATORY and must NOT be skipped!**
Cozystack release may include changes from related repositories. Check and include commits from these repositories if tags were released during the release period:
**Required repositories:**
- **Documentation**: [https://github.com/cozystack/website](https://github.com/cozystack/website)
- **MANDATORY**: Always check this repository for documentation changes during the release period
- **MANDATORY**: Get GitHub username for EVERY commit. Extract PR number from commit message, then use `gh pr view <PR_NUMBER> --repo cozystack/website --json author --jq .author.login` to get PR author. Only if no PR number, fall back to `gh api repos/cozystack/website/commits/<hash> --jq '.author.login'`
**Optional repositories (MUST check ALL of them for tags during release period):**
- [https://github.com/cozystack/talm](https://github.com/cozystack/talm)
- [https://github.com/cozystack/boot-to-talos](https://github.com/cozystack/boot-to-talos)
- [https://github.com/cozystack/cozyhr](https://github.com/cozystack/cozyhr)
- [https://github.com/cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy)
**⚠️ IMPORTANT**: You MUST check ALL optional repositories for tags created during the release period. Do NOT skip this step even if you think there might not be any tags. Use the process below to verify.
**Process for each repository:**
1. **Get release period dates:**
```bash
# Get dates for the release period
cd /path/to/cozystack
RELEASE_START=$(git log -1 --format=%ai v<previous_version>)
RELEASE_END=$(git log -1 --format=%ai HEAD)
```
2. **Check for commits in website repository (always required):**
```bash
# Ensure website repository is cloned and up-to-date
mkdir -p _repos
if [ ! -d "_repos/website" ]; then
cd _repos && git clone https://github.com/cozystack/website.git && cd ..
fi
cd _repos/website
git fetch --all --tags --force
git checkout main 2>/dev/null || git checkout master
git pull
# Get commits between release dates (with some buffer)
git log --since="$RELEASE_START" --until="$RELEASE_END" --format="%H|%s|%an" | while IFS='|' read -r commit_hash subject author_name; do
# Extract PR number from commit message
PR_NUMBER=$(git log -1 --format="%B" "$commit_hash" | grep -oE '#[0-9]+' | head -1 | tr -d '#')
# ALWAYS use PR author if PR number found, not commit author
if [ -n "$PR_NUMBER" ]; then
GITHUB_USERNAME=$(gh pr view "$PR_NUMBER" --repo cozystack/website --json author --jq '.author.login // empty' 2>/dev/null)
echo "$commit_hash|$subject|$author_name|$GITHUB_USERNAME|cozystack/website#$PR_NUMBER"
else
# Only fallback to commit author if no PR number found (rare)
GITHUB_USERNAME=$(gh api repos/cozystack/website/commits/$commit_hash --jq '.author.login // empty')
echo "$commit_hash|$subject|$author_name|$GITHUB_USERNAME|cozystack/website@${commit_hash:0:7}"
fi
done
# Look for documentation updates, new pages, or significant content changes
# Include these in the "Documentation" section of the changelog WITH authors and PR links
```
3. **For optional repositories, check if tags exist during release period:**
**⚠️ MANDATORY: You MUST check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy). Do NOT skip any repository!**
**Use the helper script:**
```bash
# Get release period dates
RELEASE_START=$(git log -1 --format=%ai v<previous_version>)
RELEASE_END=$(git log -1 --format=%ai HEAD)
# Run the script to check all optional repositories
./docs/changelogs/hack/check-optional-repos.sh "$RELEASE_START" "$RELEASE_END"
```
The script will:
- Check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy)
- Look for tags created during the release period
- Get commits between tags (if tags exist) or by date range (if no tags)
- Extract PR numbers from commit messages
- For EVERY commit with PR number, get PR author via CLI: `gh pr view <PR_NUMBER> --repo cozystack/<repo> --json author --jq .author.login` (ALWAYS use PR author, not commit author)
- For commits without PR numbers (rare), fallback to: `gh api repos/cozystack/<repo>/commits/<hash> --jq '.author.login'`
- Output results in format: `commit_hash|subject|author_name|github_username|cozystack/repo#PR_NUMBER` or `cozystack/repo@commit_hash`
4. **Extract PR numbers and authors using GitHub CLI:**
- **ALWAYS use PR author, not commit author** for commits from additional repositories
- For each commit, extract PR number from commit message first: Extract `#123` pattern from commit message
- If PR number found, use `gh pr view <PR_NUMBER> --repo cozystack/<repo> --json author --jq .author.login` to get PR author (the person who wrote the code)
- Only if no PR number found (rare), fallback to commit author: `gh api repos/cozystack/<repo>/commits/<hash> --jq '.author.login'`
- **Prefer PR numbers**: Use format `cozystack/website#123` if PR number found in commit message
- **Fallback to commit hash**: Use format `cozystack/website@abc1234` if no PR number
- **ALWAYS include author**: Every entry from additional repositories MUST include author in format `([**@username**](https://github.com/username) in cozystack/repo#123)`
- Determine user impact and categorize appropriately
- Format entries with repository prefix: `[website]`, `[talm]`, etc.
**Example entry format for additional repositories:**
```markdown
# If PR number found in commit message (REQUIRED format):
* **[website] Update installation documentation**: Improved installation guide with new examples ([**@username**](https://github.com/username) in cozystack/website#123).
# If no PR number (fallback, use commit hash):
* **[website] Update installation documentation**: Improved installation guide with new examples ([**@username**](https://github.com/username) in cozystack/website@abc1234).
# For optional repositories:
* **[talm] Add new feature**: Description of the change ([**@username**](https://github.com/username) in cozystack/talm#456).
```
**CRITICAL**:
- **ALWAYS include author** for every entry from additional repositories
- **ALWAYS include PR link or commit hash** for every entry
- Never add entries without author and PR/commit reference
- **ALWAYS use PR author, not commit author**: Extract PR number from commit message, then use `gh pr view <PR_NUMBER> --repo cozystack/<repo> --json author --jq .author.login` to get the PR author (the person who wrote the code)
- Only if no PR number found (rare), fallback to commit author: `gh api repos/cozystack/<repo>/commits/<hash> --jq '.author.login'`
- The commit author (especially for squash/merge commits) is usually the person who merged the PR, not the person who wrote the code
### 7. Analyzing commits and PRs
**⚠️ CRITICAL: You MUST get the author from PR, not from commit! Always use `gh pr view` to get the PR author. Do NOT use commit author!**
**Get all PR numbers from commits:**
**⚠️ CRITICAL: Do NOT use --no-merges flag! It will skip merge commits including backports!**
```bash
# Extract all PR numbers from commit messages in the release range (including merge commits)
git log <previous_version>..<new_version> --format="%s%n%b" | grep -oE '#[0-9]+' | sort -u | tr -d '#'
```
**⚠️ IMPORTANT: Handle backports correctly:**
- Backport PRs have format: `[Backport release-X.Y] <original title> (#BACKPORT_PR_NUMBER)`
- The backport commit message or PR description usually mentions the original PR number
- For backport entries in changelog, use the original PR author (not the backport PR author)
- Include both original and backport PR numbers in the changelog entry (e.g., `#1606, #1609`)
- To find original PR from backport: Check the backport PR description or commit message for "Backport of #ORIGINAL_PR"
**For each PR number, get the author:**
**CRITICAL**: The commit author (especially for squash/merge commits) is usually the person who merged the PR (or GitHub bot), NOT the person who wrote the code. **ALWAYS use the PR author**, not the commit author.
**⚠️ MANDATORY: ALWAYS use `gh pr view` to get the PR author. Do NOT use commit author!**
**ALWAYS use GitHub CLI** to get the PR author:
```bash
# Usage: Get PR author - MANDATORY for EVERY PR
# Loop through ALL PR numbers and get PR author (including backports)
git log <previous_version>..<new_version> --format="%s%n%b" | grep -oE '#[0-9]+' | sort -u | tr -d '#' | while read PR_NUMBER; do
# Check if this is a backport PR
BACKPORT_INFO=$(gh pr view "$PR_NUMBER" --json body --jq '.body' 2>/dev/null | grep -i "backport of #" || echo "")
if [ -n "$BACKPORT_INFO" ]; then
# Extract original PR number from backport description
ORIGINAL_PR=$(echo "$BACKPORT_INFO" | grep -oE 'backport of #([0-9]+)' | grep -oE '[0-9]+' | head -1)
if [ -n "$ORIGINAL_PR" ]; then
# Use original PR author
GITHUB_USERNAME=$(gh pr view "$ORIGINAL_PR" --json author --jq '.author.login // empty')
PR_TITLE=$(gh pr view "$ORIGINAL_PR" --json title --jq '.title // empty')
echo "$PR_NUMBER|$ORIGINAL_PR|$GITHUB_USERNAME|$PR_TITLE|BACKPORT"
else
# Fallback to backport PR author if original not found
GITHUB_USERNAME=$(gh pr view "$PR_NUMBER" --json author --jq '.author.login // empty')
PR_TITLE=$(gh pr view "$PR_NUMBER" --json title --jq '.title // empty')
echo "$PR_NUMBER||$GITHUB_USERNAME|$PR_TITLE|BACKPORT"
fi
else
# Regular PR
GITHUB_USERNAME=$(gh pr view "$PR_NUMBER" --json author --jq '.author.login // empty')
PR_TITLE=$(gh pr view "$PR_NUMBER" --json title --jq '.title // empty')
echo "$PR_NUMBER||$GITHUB_USERNAME|$PR_TITLE|REGULAR"
fi
done
```
**⚠️ IMPORTANT**: You must run this for EVERY PR in the release period. Do NOT skip any PRs or assume the GitHub username based on the git author name.
**CRITICAL**: Always use `gh pr view <PR_NUMBER> --json author --jq .author.login` to get the PR author. This correctly identifies the person who wrote the code, not the person who merged it (which is especially important for squash merges).
**Why this matters**: Using the wrong author in changelogs gives incorrect credit and can confuse contributors. The merge/squash commit is created by the person who clicks "Merge" in GitHub, not the PR author.
**For commits without PR numbers (rare):**
- Only if a commit has no PR number, fall back to commit author: `gh api repos/cozystack/cozystack/commits/<hash> --jq '.author.login'`
- But this should be very rare - most commits should have PR numbers
**Extract PR number from commit messages:**
- Check commit message subject (`%s`) and body (`%b`) for PR references: `#1234` or `(#1234)`
- **Primary method**: Extract from commit message format `(#PR_NUMBER)` or `in #PR_NUMBER` or `Merge pull request #1234`
- Use regex: `grep -oE '#[0-9]+'` to find all PR numbers
**⚠️ CRITICAL: Verify PR numbers match commit messages!**
- Always verify that the PR number in the changelog matches the PR number in the commit message
- Common mistake: Using wrong PR number (e.g., #1614 instead of #1617) when multiple similar commits exist
- To verify: Check the actual commit message: `git log <commit_hash> -1 --format="%s%n%b" | grep -oE '#[0-9]+'`
- If multiple PR numbers appear in a commit, use the one that matches the PR title/description
- For merge commits, check the merged branch commits, not just the merge commit message
3. **Understand the change:**
```bash
# Get PR details (preferred method)
gh pr view <PR_NUMBER> --json title,body,url
# Or get commit details if no PR number
git show <commit_hash> --stat
git show <commit_hash>
```
- Review PR description and changed files
- Understand functionality added/changed/fixed
- **Determine user impact**: What can users do now? What problems are fixed? What improvements do users experience?
4. **For release branches (backports):**
- If commit is from `release-X.Y` branch, check if it's a backport
- Find original commit in `main` to get correct PR number:
```bash
git log origin/main --grep="<part of commit message>" --oneline
```
### 8. Forming a new changelog
Create a new changelog file in the format matching previous versions:
1. **Determine the release type:**
- **Minor release (vX.Y.0)** - use full format with **Feature Highlights** section. **Must include all changes from patch releases of the previous minor version** (e.g., v0.38.0 should include changes from v0.37.1, v0.37.2, v0.37.3, etc.)
- **Patch release (vX.Y.Z, where Z > 0)** - use more compact format, includes only changes since the previous patch release
**Feature Highlights format for minor releases:**
- Use section header: `## Feature Highlights`
- Include 3-6 major features as subsections with `### Feature Name` headers
- Each feature subsection should contain:
- **Detailed description** (2-4 paragraphs) explaining:
- What the feature is and what problem it solves
- How it works and what users can do with it
- How to use it (if applicable)
- Benefits and impact for users
- **Links to documentation** when available (use markdown links)
- **Code examples or configuration snippets** if helpful
- Focus on user value and practical implications, not just technical details
- Each feature should be substantial enough to warrant its own subsection
- Order features by importance/impact (most important first)
- Example format:
```markdown
## Feature Highlights
### Feature Name
Detailed description paragraph explaining what the feature is...
Another paragraph explaining how it works and what users can do...
Learn more in the [documentation](https://cozystack.io/docs/...).
```
**Important for minor releases**: After collecting all commits, **systematically verify** that all PRs from patch releases are included:
```bash
# Extract all PR numbers from patch release changelogs
grep -h "#[0-9]\+" docs/changelogs/v<previous_minor>.*.md | sort -u
# Extract all PR numbers from the new minor release changelog
grep -h "#[0-9]\+" docs/changelogs/v<new_minor>.0.md | sort -u
# Compare and identify missing PRs
# Ensure every PR from patch releases appears in the minor release changelog
```
2. **Structure changes by categories:**
**For minor releases (vX.Y.0):**
- **Feature Highlights** (required) - see format above
- **Major Features and Improvements** - detailed list of all major features and improvements
- **Improvements (minor)** - smaller improvements and enhancements
- **Bug fixes** - all bug fixes
- **Security** - security-related changes
- **Dependencies & version updates** - dependency updates
- **System Configuration** - system-level configuration changes
- **Development, Testing, and CI/CD** - development and testing improvements
- **Documentation** (include changes from website repository here - **MUST include authors and PR links for all entries**)
- **Breaking changes & upgrade notes** (if any)
- **Refactors & chores** (if any)
**For patch releases (vX.Y.Z where Z > 0):**
- **Features and Improvements** - new features and improvements
- **Fixes** - bug fixes
- **Security** - security-related changes
- **Dependencies** - dependency updates
- **System Configuration** - system-level configuration changes
- **Development, Testing, and CI/CD** - development and testing improvements
- **Documentation** (include changes from website repository here - **MUST include authors and PR links for all entries**)
- **Migration and Upgrades** (if applicable)
**Note**: When including changes from additional repositories, group them logically with main repository changes, or create separate subsections if there are many changes from a specific repository.
3. **Entry format:**
- Use the format: `* **Brief description**: detailed description ([**@username**](https://github.com/username) in #PR_NUMBER)`
- **CRITICAL - Get authorship correctly**:
- **ALWAYS use PR author, not commit author**: Extract PR number from commit message, then use `gh pr view` to get the PR author. The commit author (especially for squash/merge commits) is usually the person who merged the PR (or GitHub bot), NOT the person who wrote the code.
```bash
# Get PR author from GitHub CLI (correct method)
# Step 1: Extract PR number from commit message
PR_NUMBER=$(git log <commit_hash> -1 --format="%s%n%b" | grep -oE '#[0-9]+' | head -1 | tr -d '#')
# Step 2: Get PR author (the person who wrote the code)
if [ -n "$PR_NUMBER" ]; then
GITHUB_USERNAME=$(gh pr view "$PR_NUMBER" --json author --jq '.author.login')
else
# Only fallback to commit author if no PR number found (rare)
GITHUB_USERNAME=$(gh api repos/cozystack/cozystack/commits/<commit_hash> --jq '.author.login')
fi
```
**Example**: For PR #1507, the squash commit has author "kvaps" (who merged), but the PR author is "lllamnyp" (who wrote the code). Using `gh pr view 1507 --json author --jq .author.login` correctly returns "lllamnyp".
- **For regular commits**: Use the commit author directly:
```bash
git log <commit_hash> -1 --format="%an|%ae"
```
- **Validation**: Before adding to changelog, verify the author by checking:
- For merge commits: Compare merge commit author vs PR author (they should be different)
- Check existing changelogs for author name to GitHub username mappings
- Verify with: `git log <merge_commit>^1..<merge_commit>^2 --format="%an" --no-merges`
- **Map author name to GitHub username**: Check existing changelogs for author name mappings, or extract from PR links in commit messages
- **Always include user impact**: Each entry must explain how the change affects users
- For new features: explain what users can now do
- For bug fixes: explain what problem is solved for users
- For improvements: explain what users will experience better
- For breaking changes: clearly state what users need to do
- Group related changes
- Use bold font for important components/modules
- Focus on user value, not just technical details
4. **Add a link to the full changelog:**
**For patch releases (vX.Y.Z where Z > 0):**
```markdown
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v<previous_patch_version>...v<new_version>
```
Example: For v0.37.2, use `v0.37.1...v0.37.2`
**For minor releases (vX.Y.0):**
```markdown
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v<previous_minor_version>...v<new_version>
```
Example: For v0.38.0, use `v0.37.0...v0.38.0` (NOT `v0.37.8...v0.38.0`)
**Important**: Minor releases must reference the previous minor release (vX.Y.0), not the last patch release, to include all changes from the entire minor version cycle.
5. **Generate contributors list:**
**⚠️ SIMPLIFIED APPROACH: Extract contributors from the generated changelog itself!**
Since you've already generated the changelog with all PR authors correctly identified, simply extract GitHub usernames from the changelog entries:
```bash
# Extract all GitHub usernames from the current release changelog
# This method is simpler and more reliable than extracting from git history
# For patch releases: extract from the current changelog file
grep -oE '\[@[a-zA-Z0-9_-]+\]' docs/changelogs/v<version>.md | \
sed 's/\[@/@/' | sed 's/\]//' | \
sort -u
# For minor releases: extract from the current changelog file
grep -oE '\[@[a-zA-Z0-9_-]+\]' docs/changelogs/v<version>.md | \
sed 's/\[@/@/' | sed 's/\]//' | \
sort -u
```
**Get all previous contributors (to identify new ones):**
```bash
# Extract GitHub usernames from all previous changelogs
grep -hE '\[@[a-zA-Z0-9_-]+\]' docs/changelogs/v*.md | \
grep -oE '@[a-zA-Z0-9_-]+' | \
sort -u > /tmp/previous_contributors.txt
```
**Identify new contributors (first-time contributors):**
```bash
# Get current release contributors from the changelog
grep -oE '@[a-zA-Z0-9_-]+' docs/changelogs/v<version>.md | \
sort -u > /tmp/current_contributors.txt
# Get all previous contributors
grep -hE '@[a-zA-Z0-9_-]+' docs/changelogs/v*.md | \
grep -oE '@[a-zA-Z0-9_-]+' | \
sort -u > /tmp/all_previous_contributors.txt
# Find new contributors (those in current but not in previous)
comm -23 <(sort /tmp/current_contributors.txt) <(sort /tmp/all_previous_contributors.txt)
```
**Why this approach is better:**
- ✅ Uses the already-verified PR authors from the changelog (no need to query GitHub API again)
- ✅ Automatically handles backports correctly (original PR authors are already in the changelog)
- ✅ Simpler and faster (no git log parsing or API calls)
- ✅ More reliable (matches exactly what's in the changelog)
- ✅ Works for both patch and minor releases
**Add contributors section to changelog:**
Place the contributors section at the end of the changelog, before the "Full Changelog" link:
```markdown
## Contributors
We'd like to thank all contributors who made this release possible:
* [**@username1**](https://github.com/username1)
* [**@username2**](https://github.com/username2)
* [**@username3**](https://github.com/username3)
* ...
### New Contributors
We're excited to welcome our first-time contributors:
* [**@newuser1**](https://github.com/newuser1) - First contribution!
* [**@newuser2**](https://github.com/newuser2) - First contribution!
```
**Formatting guidelines:**
- List contributors in alphabetical order by GitHub username
- Use the format: `* [**@username**](https://github.com/username)`
- For new contributors, add " - First contribution!" note
- If GitHub username cannot be determined, you can skip that contributor or use their git author name
**When to include:**
- **For patch releases**: Contributors section is optional, but can be included for significant releases
- **For minor releases (vX.Y.0)**: Contributors section is required - you must generate and include the contributors list
- Always verify GitHub usernames by checking commit messages, PR links in changelog entries, or by examining PR details
6. **Add a comment with a link to the GitHub release:**
```markdown
<!--
https://github.com/cozystack/cozystack/releases/tag/v<new_version>
-->
```
### 9. Verification and saving
**Before saving, verify completeness:**
**For ALL releases:**
- [ ] Step 5 completed: **ALL commits included** (including merge commits and backports) - do not skip any commits
- [ ] Step 5 completed: **Backports identified and handled correctly** - original PR author used, both original and backport PR numbers included
- [ ] Step 6 completed: Website repository checked for documentation changes WITH authors and PR links via GitHub CLI
- [ ] Step 6 completed: **ALL** optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy) checked for tags during release period
- [ ] Step 6 completed: For ALL commits from additional repos, GitHub username obtained via GitHub CLI (not skipped). For commits with PR numbers, PR author used via `gh pr view` (not commit author)
- [ ] Step 7 completed: For EVERY PR in main repo (including backports), PR author obtained via `gh pr view <PR_NUMBER> --json author --jq .author.login` (not skipped or assumed). Commit author NOT used - always use PR author
- [ ] Step 7 completed: **Backports verified** - for each backport PR, original PR found and original PR author used in changelog
- [ ] Step 8 completed: Contributors list generated
- [ ] All commits from main repository included (including merge commits)
- [ ] User impact described for each change
- [ ] Format matches existing changelogs
**For patch releases:**
- [ ] All commits from the release period are included (including merge commits with backports)
- [ ] PR numbers match commit messages
- [ ] Backports are properly identified and linked to original PRs
**For minor releases (vX.Y.0):**
- [ ] All changes from patch releases (vX.Y.1, vX.Y.2, etc.) are included
- [ ] Contributors section is present and complete
- [ ] Full Changelog link references previous minor version (vX.Y.0), not last patch
- [ ] Verify all PRs from patch releases are included:
```bash
# Extract and compare PR numbers
PATCH_PRS=$(grep -hE "#[0-9]+" docs/changelogs/v<previous_minor>.*.md | grep -oE "#[0-9]+" | sort -u)
MINOR_PRS=$(grep -hE "#[0-9]+" docs/changelogs/v<new_minor>.0.md | grep -oE "#[0-9]+" | sort -u)
MISSING=$(comm -23 <(echo "$PATCH_PRS") <(echo "$MINOR_PRS"))
if [ -n "$MISSING" ]; then
echo "Missing PRs from patch releases:"
echo "$MISSING"
# For each missing PR, check if it's a backport and verify change is included by description
fi
```
**Only proceed to save after all checkboxes are verified!**
**Save the changelog:**
Save the changelog to file `docs/changelogs/v<version>.md` according to the version for which the changelog is being generated.
### Important notes
- **After fetch with --force** local tags are up-to-date, use them for work
- **For release branches** always check original commits in `main` to get correct PR numbers
- **Preserve the format** of existing changelog files
- **Group related changes** logically
- **Be accurate** in describing changes, based on actual commit diffs
- **Check for PR numbers** and commit authors
- **CRITICAL - Get authorship from PR, not from commit**:
- **ALWAYS use PR author**: Extract PR number from commit message, then use `gh pr view <PR_NUMBER> --json author --jq .author.login` to get the PR author
- Do NOT use commit author - the commit author (especially for squash/merge commits) is usually the person who merged the PR, not the person who wrote the code
- For commits without PR numbers (rare), fall back to commit author: `gh api repos/cozystack/cozystack/commits/<commit_hash> --jq '.author.login'`
- **Workflow**: Extract PR numbers from commits → Use `gh pr view` for each PR → Get PR author (the person who wrote the code)
- Example: For PR #1507, the commit author is `@kvaps` (who merged), but `gh pr view 1507 --json author --jq .author.login` correctly returns `@lllamnyp` (who wrote the code)
- Check existing changelogs for author name to GitHub username mappings
- **Validation**: Before adding to changelog, always verify the author using `gh pr view` - never use commit author for PRs
- **MANDATORY**: Always describe user impact: Every changelog entry must explain how the change affects end users, not just what was changed technically. Focus on user value and practical implications.
**Required steps:**
- **Additional repositories (Step 6) - MANDATORY**:
- **⚠️ CRITICAL**: Always check the **website** repository for documentation changes during the release period. This is a required step and MUST NOT be skipped.
- **⚠️ CRITICAL**: You MUST check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy) for tags during the release period. Do NOT skip any repository even if you think there might not be tags.
- **CRITICAL**: For ALL entries from additional repositories (website and optional), you MUST:
- **MANDATORY**: Extract PR number from commit message first
- **MANDATORY**: For commits with PR numbers, ALWAYS use `gh pr view <PR_NUMBER> --repo cozystack/<repo> --json author --jq .author.login` to get PR author (not commit author)
- **MANDATORY**: Only for commits without PR numbers (rare), fallback to: `gh api repos/cozystack/<repo>/commits/<hash> --jq '.author.login'`
- **MANDATORY**: Do NOT skip getting GitHub username via CLI - do this for EVERY commit
- **MANDATORY**: Do NOT use commit author for PRs - always use PR author
- Include PR link or commit hash reference
- Format: `* **[repo] Description**: details ([**@username**](https://github.com/username) in cozystack/repo#123)`
- For **optional repositories** (talm, boot-to-talos, cozyhr, cozy-proxy), you MUST check ALL of them for tags during the release period. Use the loop provided in Step 6 to check each repository systematically.
- When including changes from additional repositories, use the format: `[repo-name] Description` and link to the repository's PR/issue if available
- **Prefer PR numbers over commit hashes**: For commits from additional repositories, extract PR number from commit message using GitHub API. Use PR format (`cozystack/website#123`) instead of commit hash (`cozystack/website@abc1234`) when available
- **Never add entries without author and PR/commit reference**: Every entry from additional repositories must have both author and link
- Group changes from additional repositories with main repository changes, or create separate subsections if there are many changes from a specific repository
- **PR author verification (Step 7) - MANDATORY**:
- **⚠️ CRITICAL**: You MUST get the author from PR using `gh pr view`, NOT from commit
- **⚠️ CRITICAL**: Extract PR numbers from commit messages, then use `gh pr view <PR_NUMBER> --json author --jq .author.login` for each PR
- **⚠️ CRITICAL**: Do NOT use commit author - commit author is usually the person who merged, not the person who wrote the code
- **⚠️ CRITICAL**: Do NOT skip this step for any PR, even if the author seems obvious
- For commits without PR numbers (rare), fall back to: `gh api repos/cozystack/cozystack/commits/<hash> --jq '.author.login'`
- This ensures correct attribution and prevents errors in changelog entries (especially important for squash/merge commits)
- **Contributors list (Step 8)**:
- For minor releases (vX.Y.0): You must generate a list of all contributors and identify first-time contributors.
- For patch releases: Contributors section is optional, but recommended for significant releases
- Extract GitHub usernames from PR links in commit messages or changelog entries
- This helps recognize community contributions and welcome new contributors
- **Minor releases (vX.Y.0)**:
- Must include **all changes** from patch releases of the previous minor version (e.g., v0.38.0 includes all changes from v0.37.1, v0.37.2, v0.37.3, etc.)
- The "Full Changelog" link must reference the previous minor release (v0.37.0...v0.38.0), NOT the last patch release (v0.37.8...v0.38.0)
- This ensures users can see the complete set of changes for the entire minor version cycle
- **Verification step**: After creating the changelog, extract all PR numbers from patch release changelogs and verify they all appear in the minor release changelog to prevent missing entries
- **Backport handling**: Patch releases may contain backports with different PR numbers (e.g., #1624 in patch release vs #1622 in main). For minor releases, use original PR numbers from main when available, but verify that all changes from patch releases are included regardless of PR number differences
- **Content verification**: Don't rely solely on PR number matching - verify that change descriptions from patch releases appear in the minor release changelog, as backports may have different PR numbers

275
docs/agents/contributing.md Normal file
View File

@@ -0,0 +1,275 @@
# Instructions for AI Agents
Guidelines for AI agents contributing to Cozystack.
## Checklist for Creating a Pull Request
- [ ] Changes are made and tested
- [ ] Commit message uses correct `[component]` prefix
- [ ] Commit is signed off with `--signoff`
- [ ] Branch is rebased on `upstream/main` (no extra commits)
- [ ] PR body includes description and release note
- [ ] PR is pushed and created with `gh pr create`
## How to Commit and Create Pull Requests
### 1. Make Your Changes
Edit the necessary files in the codebase.
### 2. Commit with Proper Format
Use the `[component]` prefix and `--signoff` flag:
```bash
git commit --signoff -m "[component] Brief description of changes"
```
**Component prefixes:**
- System: `[dashboard]`, `[platform]`, `[cilium]`, `[kube-ovn]`, `[linstor]`, `[fluxcd]`, `[cluster-api]`
- Apps: `[postgres]`, `[mysql]`, `[redis]`, `[kafka]`, `[clickhouse]`, `[virtual-machine]`, `[kubernetes]`
- Other: `[tests]`, `[ci]`, `[docs]`, `[maintenance]`
**Examples:**
```bash
git commit --signoff -m "[dashboard] Add config hash annotations to restart pods on config changes"
git commit --signoff -m "[postgres] Update operator to version 1.2.3"
git commit --signoff -m "[docs] Add installation guide"
```
### 3. Rebase on upstream/main (if needed)
If your branch has extra commits, clean it up:
```bash
# Fetch latest
git fetch upstream
# Create clean branch from upstream/main
git checkout -b my-feature upstream/main
# Cherry-pick only your commit
git cherry-pick <your-commit-hash>
# Force push to your branch
git push -f origin my-feature:my-branch-name
```
### 4. Push Your Branch
```bash
git push origin <branch-name>
```
### 5. Create Pull Request
Write the PR body to a temporary file:
```bash
cat > /tmp/pr_body.md << 'EOF'
## What this PR does
Brief description of the changes.
Changes:
- Change 1
- Change 2
### Release note
```release-note
[component] Description for changelog
```
EOF
```
Create the PR:
```bash
gh pr create --title "[component] Brief description" --body-file /tmp/pr_body.md
```
Clean up:
```bash
rm /tmp/pr_body.md
```
## Addressing AI Bot Reviewer Comments
When the user asks to fix comments from AI bot reviewers (like Qodo, Copilot, etc.):
### 1. Get PR Comments
View all comments on the pull request:
```bash
gh pr view <PR-number> --comments
```
Or for the current branch:
```bash
gh pr view --comments
```
### 2. Review Each Comment Carefully
**Important**: Do NOT blindly apply all suggestions. Each comment should be evaluated:
- **Consider context** - Does the suggestion make sense for this specific case?
- **Check project conventions** - Does it align with Cozystack patterns?
- **Evaluate impact** - Will this improve code quality or introduce issues?
- **Question validity** - AI bots can be wrong or miss context
**When to apply:**
- ✅ Legitimate bugs or security issues
- ✅ Clear improvements to code quality
- ✅ Better error handling or edge cases
- ✅ Conformance to project conventions
**When to skip:**
- ❌ Stylistic preferences that don't match project style
- ❌ Over-engineering simple code
- ❌ Changes that break existing patterns
- ❌ Suggestions that show misunderstanding of the code
### 3. Apply Valid Fixes
Make changes addressing the valid comments. Use your judgment.
### 4. Leave Changes Uncommitted
**Critical**: Do NOT commit or push the changes automatically.
Leave the changes in the working directory so the user can:
- Review the fixes
- Decide whether to commit them
- Make additional adjustments if needed
```bash
# After making changes, show status but DON'T commit
git status
git diff
```
The user will commit and push when ready.
## Code Review Comments
When asked to fix code review comments, **always work only with unresolved (open) comments**. Resolved comments should be ignored as they have already been addressed.
### Getting Unresolved Review Comments
Use GitHub GraphQL API to fetch only unresolved review comments from a pull request:
```bash
gh api graphql -F owner=cozystack -F repo=cozystack -F pr=<PR_NUMBER> -f query='
query($owner: String!, $repo: String!, $pr: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pr) {
reviewThreads(first: 100) {
nodes {
isResolved
comments(first: 100) {
nodes {
id
path
line
author { login }
bodyText
url
createdAt
}
}
}
}
}
}
}' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | .comments.nodes[]'
```
### Filtering for Unresolved Comments
The key filter is `select(.isResolved == false)` which ensures only unresolved review threads are processed. Each thread can contain multiple comments, but if the thread is resolved, all its comments should be ignored.
### Working with Review Comments
1. **Fetch unresolved comments** using the GraphQL query above
2. **Parse the results** to identify:
- File path (`path`)
- Line number (`line` or `originalLine`)
- Comment text (`bodyText`)
- Author (`author.login`)
3. **Address each unresolved comment** by:
- Locating the relevant code section
- Making the requested changes
- Ensuring the fix addresses the concern raised
4. **Do NOT process resolved comments** - they have already been handled
### Example: Compact List of Unresolved Comments
For a quick overview of unresolved comments:
```bash
gh api graphql -F owner=cozystack -F repo=cozystack -F pr=<PR_NUMBER> -f query='
query($owner: String!, $repo: String!, $pr: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pr) {
reviewThreads(first: 100) {
nodes {
isResolved
comments(first: 100) {
nodes {
path
line
author { login }
bodyText
}
}
}
}
}
}
}' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | .comments.nodes[] | "\(.path):\(.line // "N/A") - \(.author.login): \(.bodyText[:150])"'
```
### Important Notes
- **REST API limitation**: The REST endpoint `/pulls/{pr}/reviews` returns review summaries, not individual review comments. Use GraphQL API for accessing `reviewThreads` with `isResolved` status.
- **Thread-based resolution**: Comments are organized in threads. If a thread is resolved (`isResolved: true`), ignore all comments in that thread.
- **Always filter**: Never process comments from resolved threads, even if they appear in the results.
### Example Workflow
```bash
# Get PR comments
gh pr view 1234 --comments
# Review comments and identify valid ones
# Make necessary changes to address valid comments
# ... edit files ...
# Show what was changed (but don't commit)
git status
git diff
# Tell the user what was fixed and what was skipped
```
## Git Permissions
Request these permissions when needed:
- `git_write` - For commit, rebase, cherry-pick, branch operations
- `network` - For push, fetch, pull operations
## Common Issues
**PR has extra commits?**
→ Rebase on `upstream/main` and cherry-pick only your commits
**Wrong commit message?**
`git commit --amend --signoff -m "[correct] message"` then `git push -f`
**Need to update PR?**
`gh pr edit <number> --body "new description"`

115
docs/agents/overview.md Normal file
View File

@@ -0,0 +1,115 @@
# Cozystack Project Overview
This document provides detailed information about Cozystack project structure and conventions for AI agents.
## About Cozystack
Cozystack is an open-source Kubernetes-based platform and framework for building cloud infrastructure. It provides:
- **Managed Services**: Databases, VMs, Kubernetes clusters, object storage, and more
- **Multi-tenancy**: Full isolation and self-service for tenants
- **GitOps-driven**: FluxCD-based continuous delivery
- **Modular Architecture**: Extensible with custom packages and services
- **Developer Experience**: Simplified local development with cozyhr tool
The platform exposes infrastructure services via the Kubernetes API with ready-made configs, built-in monitoring, and alerts.
## Code Layout
```
.
├── packages/ # Main directory for cozystack packages
│ ├── core/ # Core platform logic charts (installer, platform)
│ ├── system/ # System charts (CSI, CNI, operators, etc.)
│ ├── apps/ # User-facing charts shown in dashboard catalog
│ └── extra/ # Tenant-specific modules, singleton charts which are used as dependencies
├── dashboards/ # Grafana dashboards for monitoring
├── hack/ # Helper scripts for local development
│ └── e2e-apps/ # End-to-end application tests
├── scripts/ # Scripts used by cozystack container
│ └── migrations/ # Version migration scripts
├── docs/ # Documentation
│ ├── agents/ # AI agent instructions
│ └── changelogs/ # Release changelogs
├── cmd/ # Go command entry points
│ ├── cozystack-api/
│ ├── cozystack-controller/
│ └── cozystack-assets-server/
├── internal/ # Internal Go packages
│ ├── controller/ # Controller implementations
│ └── lineagecontrollerwebhook/
├── pkg/ # Public Go packages
│ ├── apis/
│ ├── apiserver/
│ └── registry/
└── api/ # Kubernetes API definitions (CRDs)
└── v1alpha1/
```
## Package Structure
Every package is a Helm chart following the umbrella chart pattern:
```
packages/<category>/<package-name>/
├── Chart.yaml # Chart definition and parameter docs
├── Makefile # Development workflow targets
├── charts/ # Vendored upstream charts
├── images/ # Dockerfiles and image build context
├── patches/ # Optional upstream chart patches
├── templates/ # Additional manifests
├── templates/dashboard-resourcemap.yaml # Dashboard resource mapping
├── values.yaml # Override values for upstream
└── values.schema.json # JSON schema for validation and UI
```
## Conventions
### Helm Charts
- Follow **umbrella chart** pattern for system components
- Include upstream charts in `charts/` directory (vendored, not referenced)
- Override configuration in root `values.yaml`
- Use `values.schema.json` for input validation and dashboard UI rendering
### Go Code
- Follow standard **Go conventions** and idioms
- Use **controller-runtime** patterns for Kubernetes controllers
- Prefer **kubebuilder** for API definitions and controllers
- Add proper error handling and structured logging
### Git Commits
- Use format: `[component] Description`
- Always use `--signoff` flag
- Reference PR numbers when available
- Keep commits atomic and focused
- Follow conventional commit format for changelogs
### Documentation
Documentation is organized as follows:
- `docs/` - General documentation
- `docs/agents/` - Instructions for AI agents
- `docs/changelogs/` - Release changelogs
- Main website: https://github.com/cozystack/website
## Things Agents Should Not Do
### Never Edit These
- Do not modify files in `/vendor/` (Go dependencies)
- Do not edit generated files: `zz_generated.*.go`
- Do not change `go.mod`/`go.sum` manually (use `go get`)
- Do not edit upstream charts in `packages/*/charts/` directly (use patches)
- Do not modify image digests in `values.yaml` (generated by build)
### Version Control
- Do not commit built artifacts from `_out`
- Do not commit test artifacts or temporary files
### Git Operations
- Do not force push to main/master
- Do not update git config
- Do not perform destructive operations without explicit request
### Core Components
- Do not modify `packages/core/platform/` without understanding migration impact

29
docs/agents/releasing.md Normal file
View File

@@ -0,0 +1,29 @@
# Release Process
This document provides instructions for AI agents on how to handle release-related tasks.
## When to Use
Follow these instructions when the user asks to:
- Create a new release
- Prepare a release
- Tag a release
- Perform release-related tasks
## Instructions
For detailed release process instructions, follow the steps documented in:
**[docs/release.md](../release.md)**
## Quick Reference
The release process typically involves:
1. Preparing the release branch
2. Generating changelog
3. Updating version numbers
4. Creating git tags
5. Building and publishing artifacts
All detailed steps are documented in `docs/release.md`.

View File

@@ -1,3 +0,0 @@
# Changes after v0.37.0
* [lineage] Break webhook out into a separate daemonset. Reduce unnecessary webhook calls by marking handled resources and excluding them from consideration by the webhook's object selector (@lllamnyp in #1515).

View File

@@ -5,10 +5,13 @@ https://github.com/cozystack/cozystack/releases/tag/v0.36.2
## Features and Improvements
## Security
* [vm-disk] New SVG icon for VM disk application. (@kvaps and @kvapsova in https://github.com/cozystack/cozystack/pull/1435)
## Fixes
* [kubernetes] Pin CoreDNS image tag to v1.12.4 for consistent, reproducible deployments. (@kvaps in https://github.com/cozystack/cozystack/pull/1469)
* [dashboard] Fix FerretDB spec typo that prevented deploy/display in the web UI. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1440)
## Dependencies
## Development, Testing, and CI/CD

View File

@@ -0,0 +1,31 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.37.1
-->
## Features and Improvements
* **[api] Efficient listing of TenantNamespaces**: Optimized TenantNamespace listing by replacing per-namespace SubjectAccessReview calls with group-based rolebinding checks, significantly reducing API latency and improving performance ([**@lllamnyp**](https://github.com/lllamnyp) in #1507).
## Fixes
* **[api] Fix RBAC for listing of TenantNamespaces and handle system:masters**: Fixed regression in TenantNamespace listing RBAC and added proper handling for system:masters group to ensure correct authorization ([**@kvaps**](https://github.com/kvaps) in #1511).
* **[dashboard] Fix logout**: Fixed dashboard logout functionality to properly clear session and redirect users ([**@kvaps**](https://github.com/kvaps) in #1510).
* **[installer] Add additional check to wait for lineage-webhook**: Added additional readiness check to ensure lineage-webhook is fully ready before proceeding with installation, improving upgrade reliability ([**@kvaps**](https://github.com/kvaps) in #1506).
## Development, Testing, and CI/CD
* **[tests] Make Kubernetes tests POSIX-compatible**: Replaced bash-specific constructs with POSIX-compliant code, ensuring tests work reliably with /bin/sh and improving compatibility across different shell environments ([**@IvanHunters**](https://github.com/IvanHunters) in #1509).
## Documentation
* **[website] Update troubleshooting documentation**: Updated Kubernetes installation troubleshooting guide with additional information and fixes ([**@lb0o**](https://github.com/lb0o) in cozystack/website@82beddd).
* **[website] Add LLDPD disabling documentation**: Added minimal patch documentation for disabling lldpd based on official LLDPD usage guide ([**@lb0o**](https://github.com/lb0o) in cozystack/website@7ec5d7b).
* **[website] Fix typo in utility command**: Fixed typo in utility command documentation ([**@lb0o**](https://github.com/lb0o) in cozystack/website@6c76cb5).
* **[website] Update backup and recovery docs**: Updated backup and recovery documentation with latest information ([**@kvaps**](https://github.com/kvaps) in cozystack/website@2781aa5).
* **[website] Add Troubleshooting checklist**: Added troubleshooting checklist to help users diagnose and resolve common issues ([**@kvaps**](https://github.com/kvaps) in cozystack/website@59fc304).
---
**Full Changelog**: [v0.37.0...v0.37.1](https://github.com/cozystack/cozystack/compare/v0.37.0...v0.37.1)

View File

@@ -0,0 +1,21 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.37.2
-->
## Features and Improvements
* **[lineage] Separate webhook from cozy controller**: Separated the lineage-controller-webhook from cozystack-controller into a separate daemonset component deployed on all control-plane nodes, reducing API server latency and improving performance by decreasing outgoing API calls. Introduced internal label to track resources already handled by the webhook ([**@lllamnyp**](https://github.com/lllamnyp) in #1515).
## Fixes
* **[api] Fix listing tenantnamespaces for non-oidc users**: Fixed TenantNamespace listing functionality for users not using OIDC authentication, ensuring proper namespace visibility for all authentication methods ([**@kvaps**](https://github.com/kvaps) in #1517, #1519).
## Migration and Upgrades
* **[platform] Better migration for 0.36.2->0.37.2+**: Improved migration script for users upgrading directly from 0.36.2 to 0.37.2+, ensuring the new lineage webhook daemonset is properly deployed and fixing a bug where webhook readiness was not appropriately verified during migration ([**@lllamnyp**](https://github.com/lllamnyp) in #1521, #1522).
---
**Full Changelog**: [v0.37.1...v0.37.2](https://github.com/cozystack/cozystack/compare/v0.37.1...v0.37.2)

View File

@@ -0,0 +1,45 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.37.3
-->
## Features and Improvements
* **[apps] Make VM service user facing**: Virtual machine services are now marked as user-facing, improving service discovery and visibility in the dashboard ([**@lllamnyp**](https://github.com/lllamnyp) in #1523).
* **[seaweedfs] Allow users to discover their buckets**: Users can now discover and list their S3 buckets in SeaweedFS, improving usability and bucket management ([**@kvaps**](https://github.com/kvaps) in #1528).
* **[seaweedfs] Update SeaweedFS v3.99 and deploy S3 as stacked service**: Updated SeaweedFS to version 3.99 and deployed S3 gateway as a stacked service for better integration and performance ([**@kvaps**](https://github.com/kvaps) in #1562).
* **[dashboard] Show service LB IP**: Fixed JSON path issue to correctly display Service LoadBalancer IPs in the dashboard table view, improving visibility of service endpoints ([**@lllamnyp**](https://github.com/lllamnyp) in #1524).
* **[dashboard] Update openapi-ui v1.0.3 + fixes**: Updated OpenAPI UI to version 1.0.3 with various fixes and improvements ([**@kvaps**](https://github.com/kvaps) in #1564).
* **[kubernetes] Use controlPlane.replicas field**: Fixed managed Kubernetes app to properly use the `controlPlane.replicas` field instead of hardcoding the value, allowing users to configure control plane replica count ([**@lllamnyp**](https://github.com/lllamnyp) in #1556).
* **[monitoring] add settings alert for slack**: Added Slack integration configuration for Alerta alerts, enabling notifications to Slack channels ([**@scooby87**](https://github.com/scooby87) in #1545).
## Fixes
* **[lineage] Check for nil chart in HelmRelease**: Added nil check to prevent crashes when lineage webhook encounters HelmReleases using `chartRef` instead of `chart`, improving stability ([**@lllamnyp**](https://github.com/lllamnyp) in #1525).
* **[kamaji] Respect 3rd party labels**: Applied patch to Kamaji controller to respect third-party labels, preventing reconciliation loops between lineage webhook and Kamaji controller ([**@lllamnyp**](https://github.com/lllamnyp) in #1531, #1534).
* **[redis-operator] Build patched operator in-tree**: Moved Redis operator build into Cozystack organization and patched it to prevent overwriting third-party labels on owned resources ([**@lllamnyp**](https://github.com/lllamnyp) in #1547).
* **[mariadb-operator] Add post-delete job to remove PVCs**: Added post-delete job to automatically remove PersistentVolumeClaims when MariaDB instances are deleted, preventing orphaned storage resources ([**@IvanHunters**](https://github.com/IvanHunters) in #1553).
* **[velero] Set defaultItemOperationTimeout=24h**: Set default item operation timeout to 24 hours for Velero backups, preventing timeouts on large backup operations ([**@kvaps**](https://github.com/kvaps) in #1542).
## Dependencies
* **Update LINSTOR v1.32.3**: Updated LINSTOR to version 1.32.3 with latest features and bug fixes ([**@kvaps**](https://github.com/kvaps) in #1565).
## System Configuration
* **[system] kube-ovn: turn off enableLb**: Disabled load balancer functionality in Kube-OVN configuration ([**@nbykov0**](https://github.com/nbykov0) in #1548).
## Documentation
* **[website] Update LINSTOR documentation**: Updated LINSTOR guide and set failmode=continue for ZFS configurations ([**@kvaps**](https://github.com/kvaps) in cozystack/website@033804e).
* **[website] Update managed apps reference**: Updated managed applications reference documentation ([**@kvaps**](https://github.com/kvaps) in cozystack/website@b886a74).
* **[website] Update external apps documentation**: Updated documentation for external applications ([**@kvaps**](https://github.com/kvaps) in cozystack/website@565dad9).
* **[website] Add naming conventions**: Added naming conventions documentation ([**@kvaps**](https://github.com/kvaps) in cozystack/website@b227abb).
* **[website] Update golden image documentation**: Updated documentation for creating golden images for virtual machines ([**@kvaps**](https://github.com/kvaps) in cozystack/website@34c2f3a, cozystack/website@ef65593).
* **[website] Fix documentation formatting**: Fixed alerts, infoboxes, tabs styles and main page formatting ([**@kvaps**](https://github.com/kvaps) in cozystack/website@e992e97, cozystack/website@b2c4dee).
* **[website] Fix typo in blog article**: Fixed typo in blog article ([**@kvaps**](https://github.com/kvaps) in cozystack/website@0a4bbf3).
---
**Full Changelog**: [v0.37.2...v0.37.3](https://github.com/cozystack/cozystack/compare/v0.37.2...v0.37.3)

View File

@@ -0,0 +1,29 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.37.4
-->
## Features and Improvements
* **[tenant] Allow listing workloads**: Enabled listing of workloads for tenants, improving visibility and management of tenant resources ([**@kvaps**](https://github.com/kvaps) in #1576, #1577).
## Fixes
* **[seaweedfs] Fix migration to v3.99**: Fixed migration issues when upgrading SeaweedFS to version 3.99, ensuring smooth upgrades ([**@kvaps**](https://github.com/kvaps) in #1572, #1575).
* **[nats] Merge container spec, not podTemplate**: Fixed NATS configuration to properly merge container specifications instead of podTemplate, ensuring correct container configuration ([**@lllamnyp**](https://github.com/lllamnyp) in #1571, #1574).
## Development, Testing, and CI/CD
* **[e2e] Increase Kubernetes connection timeouts**: Increased connection and request timeouts in E2E tests when communicating with Kubernetes API, improving test stability under high load and slow cluster response conditions ([**@IvanHunters**](https://github.com/IvanHunters) in #1570, #1573).
## Documentation
* **[website] Optimize website for mobile devices**: Improved website layout and responsiveness for mobile devices ([**@kvaps**](https://github.com/kvaps) in cozystack/website@3ab2338).
* **[website] Add OpenAPI UI**: Added OpenAPI UI documentation and integration ([**@kvaps**](https://github.com/kvaps) in cozystack/website@b1c1668).
* **[website] Update Cozystack video in hero banner**: Updated hero banner with new Cozystack video ([**@kvaps**](https://github.com/kvaps) in cozystack/website@e351137).
* **[website] Add screenshots carousel**: Added screenshots carousel to showcase Cozystack features ([**@kvaps**](https://github.com/kvaps) in cozystack/website@8422bd0).
---
**Full Changelog**: [v0.37.3...v0.37.4](https://github.com/cozystack/cozystack/compare/v0.37.3...v0.37.4)

View File

@@ -0,0 +1,28 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.37.5
-->
## Features and Improvements
* **[dashboard-controller] Move badges generation logic to internal dashboard component**: Moved badges generation logic to internal dashboard component for better code organization and maintainability ([**@kvaps**](https://github.com/kvaps) in #1567).
## Security
* **[redis] Bump Redis image version for security fixes**: Updated Redis image version to include latest security fixes, improving cluster security ([**@IvanHunters**](https://github.com/IvanHunters) in #1580).
* **[flux] Close Flux Operator ports to external access**: Removed hostPort and hostNetwork from Flux Operator Deployment, ensuring ports 8080 and 8081 are only accessible within the cluster, preventing external exposure and improving security ([**@IvanHunters**](https://github.com/IvanHunters) in #1581).
* **[ingress] Enforce HTTPS-only for API**: Added force-ssl-redirect annotation to default API Ingress, ensuring all HTTP traffic is redirected to HTTPS, preventing unencrypted external access and improving security ([**@IvanHunters**](https://github.com/IvanHunters) in #1582, #1585).
## Fixes
* **[nats] Fixes for NATS App Helm chart, fix template issues with config.merge**: Fixed template issues in NATS Helm chart related to config.merge value, ensuring correct configuration ([**@insignia96**](https://github.com/insignia96) in #1583, #1591).
* **[kubevirt] Fix: kubevirt metrics rule**: Fixed KubeVirt metrics rule configuration ([**@kvaps**](https://github.com/kvaps) in #1584, #1588).
## System Configuration
* **[core] rm talos lldp extension**: Removed Talos LLDP extension from core configuration ([**@nbykov0**](https://github.com/nbykov0) in #1586).
---
**Full Changelog**: [v0.37.4...v0.37.5](https://github.com/cozystack/cozystack/compare/v0.37.4...v0.37.5)

View File

@@ -0,0 +1,30 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.37.6
-->
## Features and Improvements
* **[api] Use shared informer cache**: Optimized API server by using shared informer cache, reducing API server load and improving performance ([**@lllamnyp**](https://github.com/lllamnyp) in #1539).
* **[dashboard] sync with upstream & enhancements**: Synchronized dashboard with upstream and added various enhancements ([**@kvaps**](https://github.com/kvaps) in #1603).
* **[cozystack-api][dashboard] Fix filtering for application services/ingresses/secrets**: Fixed filtering functionality for application services, ingresses, and secrets in both API and dashboard ([**@kvaps**](https://github.com/kvaps) in #1612).
## Fixes
* **[controller] Remove crdmem, handle DaemonSet**: Removed crdmem and improved DaemonSet handling in controller ([**@lllamnyp**](https://github.com/lllamnyp) in #1555).
* **[dashboard] Revert reconciler removal**: Reverted reconciler removal to restore proper dashboard functionality ([**@lllamnyp**](https://github.com/lllamnyp) in #1559).
* **[dashboard-controller] Fix static resources reconciliation and showing secrets**: Fixed static resources reconciliation and improved secret display in dashboard controller ([**@kvaps**](https://github.com/kvaps) in #1605).
* **[api,lineage] Ensure node-local traffic**: Ensured node-local traffic handling for API and lineage components ([**@lllamnyp**](https://github.com/lllamnyp) in #1606).
* **[virtual-machine] Revert per-vm network policies**: Reverted per-VM network policies to previous behavior ([**@lllamnyp**](https://github.com/lllamnyp) in #1611).
* **[cozy-lib] Fix: handling resources=nil**: Fixed handling of nil resources in cozy-lib templates ([**@kvaps**](https://github.com/kvaps) in #1607).
* **[nats] Use dig function to check for existing secret and prevent nil indexing**: Fixed NATS app chart to use dig function for checking existing secrets and prevent nil indexing errors ([**@kvaps**](https://github.com/kvaps) in #1609, #1610).
## Development, Testing, and CI/CD
* **[cozystack-controller] improve API tests**: Improved API tests for cozystack-controller ([**@lllamnyp**](https://github.com/lllamnyp) in #1599).
* **[kubernetes] Helm hooks for cleanup**: Added Helm hooks for cleanup operations in Kubernetes app ([**@lllamnyp**](https://github.com/lllamnyp) in #1616).
---
**Full Changelog**: [v0.37.5...v0.37.6](https://github.com/cozystack/cozystack/compare/v0.37.5...v0.37.6)

View File

@@ -0,0 +1,18 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.37.7
-->
## Fixes
* **[kubernetes] Cleanup loadbalancer services**: Added cleanup functionality for load balancer services in Kubernetes app ([**@lllamnyp**](https://github.com/lllamnyp) in #1622).
* **[rbac] Fix permissions for high-privilege users**: Fixed RBAC permissions for high-privilege users, ensuring proper access control ([**@lllamnyp**](https://github.com/lllamnyp) in #1624).
## System Configuration
* **[system] kubeovn: increase limits**: Increased resource limits for Kube-OVN components to improve stability and performance ([**@nbykov0**](https://github.com/nbykov0) in #1629).
---
**Full Changelog**: [v0.37.6...v0.37.7](https://github.com/cozystack/cozystack/compare/v0.37.6...v0.37.7)

View File

@@ -0,0 +1,19 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.37.8
-->
## Fixes
* **[cozy-lib] Fix malformed ResourceQuota rendering for LoadBalancer services**: Fixed malformed ResourceQuota rendering for LoadBalancer services in cozy-lib templates ([**@IvanHunters**](https://github.com/IvanHunters) in #1642).
* **[extra] ingress: rm spaces from external ip list**: Removed spaces from external IP list in ingress configuration, fixing formatting issues ([**@nbykov0**](https://github.com/nbykov0) in #1652).
* **scripts: fix 20 migration**: Fixed migration script #20 to ensure proper execution during upgrades ([**@nbykov0**](https://github.com/nbykov0) in #1653).
## System Configuration
* **Increase strimzi memory limit**: Increased memory limit for Strimzi Kafka operator to improve stability and performance ([**@nbykov0**](https://github.com/nbykov0) in #1651).
---
**Full Changelog**: [v0.37.7...v0.37.8](https://github.com/cozystack/cozystack/compare/v0.37.7...v0.37.8)

View File

@@ -0,0 +1,19 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.37.9
-->
## Improvements
* **[seaweedfs] Extended CA certificate duration to reduce disruptive CA rotations**: Extended CA certificate duration to reduce disruptive CA rotations. ([**@IvanHunters**](https://github.com/IvanHunters) in #1657, #1666).
* **[dashboard] Add config hash annotations to restart pods on config changes**: Added config hash annotations to restart pods when configuration changes, ensuring pods are automatically restarted when their configuration is updated ([**@kvaps**](https://github.com/kvaps) in #1662, #1665).
## Fixes
* **[tenant][kubernetes] Introduce better cleanup logic**: Improved cleanup logic for tenant Kubernetes resources, ensuring proper resource cleanup when tenants are deleted or updated ([**@kvaps**](https://github.com/kvaps) in #1661).
* **[dashboard] Fix loading arrays in forms when editing existing objects**: Fixed issue where arrays in forms were not loading correctly when editing existing objects in the dashboard ([**@kvaps**](https://github.com/kvaps)).
---
**Full Changelog**: [v0.37.8...v0.37.9](https://github.com/cozystack/cozystack/compare/v0.37.8...v0.37.9)

235
docs/changelogs/v0.38.0.md Normal file
View File

@@ -0,0 +1,235 @@
# Cozystack v0.38 — "VPC & Enhanced Networking"
This release introduces **Virtual Private Cloud (VPC)** support, enabling advanced networking capabilities for tenant applications. We've also added VNC console support in the dashboard, made Kubernetes worker versions configurable, and delivered numerous improvements and fixes across the platform.
### Virtual Private Cloud (VPC) Networking
Cozystack v0.38.0 introduces Virtual Private Cloud (VPC) support, enabling platform administrators to create isolated network segments for tenant applications. VPCs provide network isolation and allow fine-grained control over network topology, subnets, and routing. Each VPC can contain multiple subnets, and administrators can configure subnet details including IP ranges, gateway settings, and DNS configuration.
The VPC feature integrates seamlessly with the Cozystack dashboard, allowing users to view and manage VPCs and their subnets through an intuitive interface. Subnet details are exposed in the dashboard as tables, making it easy to understand network configuration at a glance. VPC configuration is stored in ConfigMaps with predictable naming, ensuring reliable access to subnet information.
This feature is particularly valuable for multi-tenant environments where network isolation is critical, and for applications that require specific network configurations or routing rules.
### VNC Console for Virtual Machines
The Cozystack dashboard now includes a built-in VNC console for virtual machines, enabling users to access VM console directly from the web interface without requiring external tools. This feature provides immediate access to virtual machine consoles for troubleshooting, configuration, and maintenance tasks. The VNC console integration streamlines VM management workflows and improves the user experience by keeping all VM operations within the Cozystack dashboard.
## Highlights
* **Virtual Private Cloud (VPC)**: New VPC system module enables advanced networking with Multus CNI, subnet management, and network isolation for tenant applications ([**@nbykov0**](https://github.com/nbykov0) in #1543; [**@lllamnyp**](https://github.com/lllamnyp) in #1587, #1590, #1600, #1621, #1638).
* **VNC Console in Dashboard**: Users can now access virtual machine consoles directly from the dashboard, improving VM management experience ([**@kvaps**](https://github.com/kvaps) in #1627).
* **Configurable Kubernetes Worker Versions**: Platform administrators can now configure Kubernetes worker node versions independently, providing more flexibility in cluster management ([**@lllamnyp**](https://github.com/lllamnyp) in #1619).
* **Security Enhancements**: Multiple security improvements including HTTPS-only enforcement for API, closed Flux Operator ports, and Redis security updates ([**@IvanHunters**](https://github.com/IvanHunters) in #1580, #1581, #1582).
* **Cozy-lib Improvements**: Enhanced flatten function with better ResourceQuota handling and nil resource support ([**@lllamnyp**](https://github.com/lllamnyp) in #1647; [**@IvanHunters**](https://github.com/IvanHunters) in #1642; [**@kvaps**](https://github.com/kvaps) in #1607).
---
## New features
### VPC (Virtual Private Cloud)
* **[system] Add VPC**: Introduced Virtual Private Cloud system module with Multus CNI integration, enabling advanced networking capabilities for tenant applications ([**@nbykov0**](https://github.com/nbykov0) in #1543).
* **[vpc] Install Multus by default**: Multus CNI is now installed by default when VPC is enabled, providing multi-network interface support ([**@lllamnyp**](https://github.com/lllamnyp) in #1587).
* **[vpc] Give predictable name to subnet configmap**: Subnet configuration maps now use predictable naming for better management and debugging ([**@lllamnyp**](https://github.com/lllamnyp) in #1590).
* **[vpc] Entry per subnet in the subnets configmap**: Each subnet now has its own entry in the subnets configmap, improving subnet organization and management ([**@lllamnyp**](https://github.com/lllamnyp) in #1600).
* **[vpc,dashboard] Print subnet details as table**: Subnet details are now displayed as a table in the dashboard, improving visibility and management ([**@lllamnyp**](https://github.com/lllamnyp) in #1621).
* **[apps] Add VPC app**: Added VPC application for tenant use, enabling users to create and manage VPCs ([**@nbykov0**](https://github.com/nbykov0) in #1543).
### Dashboard
* **[dashboard] Introduce VNC console**: Added VNC console support in the dashboard, allowing users to access virtual machine consoles directly from the web interface ([**@kvaps**](https://github.com/kvaps) in #1627).
* **[dashboard] sync with upstream & enhancements**: Synchronized dashboard with upstream project and added various enhancements ([**@kvaps**](https://github.com/kvaps) in #1603).
* **[dashboard] Migrate patches to upstream project**: Migrated dashboard patches to upstream project for better maintainability ([**@kvaps**](https://github.com/kvaps) in #1569).
### Kubernetes
* **[kubernetes] Make worker version configurable**: Platform administrators can now configure Kubernetes worker node versions independently from control plane versions, providing more flexibility ([**@lllamnyp**](https://github.com/lllamnyp) in #1619).
* **[kubernetes] Use controlPlane.replicas field**: Fixed managed Kubernetes app to properly use the `controlPlane.replicas` field instead of hardcoding the value ([**@lllamnyp**](https://github.com/lllamnyp) in #1556).
* **[kubernetes] Helm hooks for cleanup**: Added Helm hooks for cleanup operations in Kubernetes app ([**@lllamnyp**](https://github.com/lllamnyp) in #1606).
### API & Platform
* **[api] Efficient listing of TenantNamespaces**: Optimized TenantNamespace listing by replacing per-namespace SubjectAccessReview calls with group-based rolebinding checks, significantly reducing API latency ([**@lllamnyp**](https://github.com/lllamnyp) in #1507).
* **[api] Use shared informer cache**: Optimized API server by using shared informer cache, reducing API server load and improving performance ([**@lllamnyp**](https://github.com/lllamnyp) in #1539).
* **[api] Fix representation of dynamic list kinds**: Fixed API representation of dynamic list kinds for better compatibility ([**@lllamnyp**](https://github.com/lllamnyp) in #1630).
* **[api] Delete previous instance when changing type**: API now properly deletes previous instance when changing application type ([**@lllamnyp**](https://github.com/lllamnyp) in #1579).
### Applications
* **[tenant] Allow listing workloads**: Enabled listing of workloads for tenants, improving visibility and management of tenant resources ([**@kvaps**](https://github.com/kvaps) in #1576).
* **[apps] Make VM service user facing**: Virtual machine services are now marked as user-facing, improving service discovery and visibility in the dashboard ([**@lllamnyp**](https://github.com/lllamnyp) in #1523).
* **[foundationdb] Upgrade FDB app for latest Cozy**: Upgraded FoundationDB application for compatibility with latest Cozystack version ([**@lllamnyp**](https://github.com/lllamnyp) in #1505).
### Storage & Backups
* **[seaweedfs] Update SeaweedFS v3.99 and deploy S3 as stacked service**: Updated SeaweedFS to version 3.99 and deployed S3 gateway as a stacked service for better integration and performance ([**@kvaps**](https://github.com/kvaps) in #1562).
* **[seaweedfs] Allow users to discover their buckets**: Users can now discover and list their S3 buckets in SeaweedFS, improving usability and bucket management ([**@kvaps**](https://github.com/kvaps) in #1528).
* **[velero] Set defaultItemOperationTimeout=24h**: Set default item operation timeout to 24 hours for Velero backups, preventing timeouts on large backup operations ([**@kvaps**](https://github.com/kvaps) in #1542).
### Monitoring & Operations
* **[monitoring] add settings alert for slack**: Added Slack integration configuration for Alerta alerts, enabling notifications to Slack channels ([**@scooby87**](https://github.com/scooby87) in #1545).
---
## Improvements (minor)
* **[lineage] Separate webhook from cozy controller**: Separated the lineage-controller-webhook from cozystack-controller into a separate daemonset component deployed on all control-plane nodes, reducing API server latency ([**@lllamnyp**](https://github.com/lllamnyp) in #1515).
* **[dashboard] Show service LB IP**: Fixed JSON path issue to correctly display Service LoadBalancer IPs in the dashboard table view ([**@lllamnyp**](https://github.com/lllamnyp) in #1524).
* **[dashboard] Update openapi-ui v1.0.3 + fixes**: Updated OpenAPI UI to version 1.0.3 with various fixes and improvements ([**@kvaps**](https://github.com/kvaps) in #1564).
* **[dashboard-controller] Move badges generation logic to internal dashboard component**: Moved badges generation logic to internal dashboard component for better code organization ([**@kvaps**](https://github.com/kvaps) in #1567).
* **[bucket] Expose bucket name in secrets**: Bucket names are now exposed in secrets for better integration with applications ([**@lllamnyp**](https://github.com/lllamnyp) in #1518).
* **[platform] Better migration for 0.36.2->0.37.2+**: Improved migration script for users upgrading directly from 0.36.2 to 0.37.2+ ([**@lllamnyp**](https://github.com/lllamnyp) in #1521).
* **[cozy-lib] Improve flatten function**: Improved flatten function in cozy-lib with better handling of complex resource structures ([**@lllamnyp**](https://github.com/lllamnyp) in #1647).
* **[dx] JSDoc compatible syntax for values.yaml**: Added JSDoc compatible syntax for values.yaml documentation ([**@kvaps**](https://github.com/kvaps) in #1536).
* **[system] Tune kubevirt rollout and eviction settings**: Tuned KubeVirt rollout and eviction settings for better stability ([**@nbykov0**](https://github.com/nbykov0) in #1544).
* **[system] multus: update to the latest version**: Updated Multus CNI to the latest version ([**@nbykov0**](https://github.com/nbykov0) in #1628).
* **[system] kubeovn: increase limits**: Increased resource limits for Kube-OVN components to improve stability and performance ([**@nbykov0**](https://github.com/nbykov0) in #1629).
* **[linstor] Update Piraeus Operator to v2.10.1 to enable RWX support**: Updated Piraeus Operator to v2.10.1, enabling ReadWriteMany (RWX) volume support ([**@kvaps**](https://github.com/kvaps) in #1650).
* **[ci,dx] Bump MariaDB operator version**: Bumped MariaDB operator version for latest features and bug fixes ([**@IvanHunters**](https://github.com/IvanHunters) in #1646).
---
## Bug fixes
* **[api] Fix RBAC for listing of TenantNamespaces and handle system:masters**: Fixed regression in TenantNamespace listing RBAC and added proper handling for system:masters group ([**@kvaps**](https://github.com/kvaps) in #1511).
* **[api] Fix listing tenantnamespaces for non-oidc users**: Fixed TenantNamespace listing functionality for users not using OIDC authentication ([**@kvaps**](https://github.com/kvaps) in #1517).
* **[dashboard] Fix logout**: Fixed dashboard logout functionality to properly clear session and redirect users ([**@kvaps**](https://github.com/kvaps) in #1510).
* **[installer] Add additional check to wait for lineage-webhook**: Added additional readiness check to ensure lineage-webhook is fully ready before proceeding with installation ([**@kvaps**](https://github.com/kvaps) in #1506).
* **[lineage] Check for nil chart in HelmRelease**: Added nil check to prevent crashes when lineage webhook encounters HelmReleases using `chartRef` instead of `chart` ([**@lllamnyp**](https://github.com/lllamnyp) in #1525).
* **[kamaji] Respect 3rd party labels**: Applied patch to Kamaji controller to respect third-party labels, preventing reconciliation loops ([**@lllamnyp**](https://github.com/lllamnyp) in #1531).
* **[redis-operator] Build patched operator in-tree**: Moved Redis operator build into Cozystack organization and patched it to prevent overwriting third-party labels ([**@lllamnyp**](https://github.com/lllamnyp) in #1547).
* **[mariadb-operator] Add post-delete job to remove PVCs**: Added post-delete job to automatically remove PersistentVolumeClaims when MariaDB instances are deleted ([**@IvanHunters**](https://github.com/IvanHunters) in #1553).
* **[seaweedfs] Fix migration to v3.99**: Fixed migration issues when upgrading SeaweedFS to version 3.99 ([**@kvaps**](https://github.com/kvaps) in #1572).
* **[nats] Merge container spec, not podTemplate**: Fixed NATS configuration to properly merge container specifications instead of podTemplate ([**@lllamnyp**](https://github.com/lllamnyp) in #1571).
* **[nats] Fixes for NATS App Helm chart, fix template issues with config.merge**: Fixed template issues in NATS Helm chart related to config.merge value ([**@insignia96**](https://github.com/insignia96) in #1583).
* **[nats] Fix NATS app chart to use existing secret credentials when present**: Fixed NATS app chart to use existing secret credentials when present, preventing credential regeneration ([**@insignia96**](https://github.com/insignia96) in #1599).
* **[kubevirt] Fix: kubevirt metrics rule**: Fixed KubeVirt metrics rule configuration ([**@kvaps**](https://github.com/kvaps) in #1584).
* **[controller] Remove crdmem, handle DaemonSet**: Removed crdmem and improved DaemonSet handling in controller ([**@lllamnyp**](https://github.com/lllamnyp) in #1555).
* **[dashboard] Revert reconciler removal**: Reverted reconciler removal to restore proper dashboard functionality ([**@lllamnyp**](https://github.com/lllamnyp) in #1559).
* **[dashboard-controller] Fix static resources reconciliation and showing secrets**: Fixed static resources reconciliation and improved secret display in dashboard controller ([**@kvaps**](https://github.com/kvaps) in #1615).
* **[cozystack-api][dashboard] Fix filtering for application services/ingresses/secrets**: Fixed filtering functionality for application services, ingresses, and secrets in both API and dashboard ([**@kvaps**](https://github.com/kvaps) in #1612).
* **[virtual-machine] Revert per-vm network policies**: Reverted per-VM network policies to previous behavior ([**@kvaps**](https://github.com/kvaps) in #1611).
* **[cozy-lib] Fix: handling resources=nil**: Fixed handling of nil resources in cozy-lib templates ([**@kvaps**](https://github.com/kvaps) in #1607).
* **[cozy-lib] Fix malformed ResourceQuota rendering for LoadBalancer services**: Fixed malformed ResourceQuota rendering for LoadBalancer services in cozy-lib templates ([**@IvanHunters**](https://github.com/IvanHunters) in #1642).
* **[kubernetes] Cleanup loadbalancer services**: Added cleanup functionality for load balancer services in Kubernetes app ([**@lllamnyp**](https://github.com/lllamnyp) in #1631).
* **[rbac] Fix permissions for high-privilege users**: Fixed RBAC permissions for high-privilege users, ensuring proper access control ([**@lllamnyp**](https://github.com/lllamnyp) in #1622).
* **[vpc] Fix access to subnet details configmap**: Fixed access to subnet details configmap in VPC functionality ([**@lllamnyp**](https://github.com/lllamnyp) in #1638).
* **[api,lineage] Ensure node-local traffic**: Ensured node-local traffic handling for API and lineage components ([**@lllamnyp**](https://github.com/lllamnyp) in #1554).
* **[extra] ingress: rm spaces from external ip list**: Removed spaces from external IP list in ingress configuration, fixing formatting issues ([**@nbykov0**](https://github.com/nbykov0) in #1652).
* **scripts: fix 20 migration**: Fixed migration script #20 to ensure proper execution during upgrades ([**@nbykov0**](https://github.com/nbykov0) in #1653).
---
## Security
* **[redis] Bump Redis image version for security fixes**: Updated Redis image version to include latest security fixes, improving cluster security ([**@IvanHunters**](https://github.com/IvanHunters) in #1580).
* **[flux] Close Flux Operator ports to external access**: Removed hostPort and hostNetwork from Flux Operator Deployment, ensuring ports 8080 and 8081 are only accessible within the cluster ([**@IvanHunters**](https://github.com/IvanHunters) in #1581).
* **[ingress] Enforce HTTPS-only for API**: Added force-ssl-redirect annotation to default API Ingress, ensuring all HTTP traffic is redirected to HTTPS ([**@IvanHunters**](https://github.com/IvanHunters) in #1582).
---
## Dependencies & version updates
* **Update LINSTOR v1.32.3**: Updated LINSTOR to version 1.32.3 with latest features and bug fixes ([**@kvaps**](https://github.com/kvaps) in #1565).
* **Update Talos Linux v1.11.3**: Updated Talos Linux to version 1.11.3 ([**@kvaps**](https://github.com/kvaps) in #1527).
* **Update Kube-OVN v1.14.11**: Updated Kube-OVN to version 1.14.11 ([**@kvaps**](https://github.com/kvaps) in #1514).
* **[linstor] Update Piraeus Operator to v2.10.1**: Updated Piraeus Operator to v2.10.1 to enable RWX support ([**@kvaps**](https://github.com/kvaps) in #1650).
* **[system] multus: update to the latest version**: Updated Multus CNI to the latest version ([**@nbykov0**](https://github.com/nbykov0) in #1628).
* **[ci,dx] Bump MariaDB operator version**: Bumped MariaDB operator version ([**@IvanHunters**](https://github.com/IvanHunters) in #1646).
* **Increase strimzi memory limit**: Increased memory limit for Strimzi Kafka operator to improve stability and performance ([**@nbykov0**](https://github.com/nbykov0) in #1651).
---
## System Configuration
* **[system] kube-ovn: turn off enableLb**: Disabled load balancer functionality in Kube-OVN configuration ([**@nbykov0**](https://github.com/nbykov0) in #1548).
* **[core] rm talos lldp extension**: Removed Talos LLDP extension from core configuration ([**@nbykov0**](https://github.com/nbykov0) in #1586).
---
## Development, Testing, and CI/CD
* **[tests] Make Kubernetes tests POSIX-compatible**: Replaced bash-specific constructs with POSIX-compliant code, ensuring tests work reliably with /bin/sh ([**@IvanHunters**](https://github.com/IvanHunters) in #1509).
* **[ferretdb] fix tests**: Fixed FerretDB tests to ensure proper execution ([**@IvanHunters**](https://github.com/IvanHunters) in #1540).
* **[e2e] Increase Kubernetes connection timeouts**: Increased connection and request timeouts in E2E tests when communicating with Kubernetes API ([**@IvanHunters**](https://github.com/IvanHunters) in #1570).
* **[cozystack-controller] improve API tests**: Improved API tests for cozystack-controller ([**@kvaps**](https://github.com/kvaps) in #1617).
* **[ci] Fix build from external forks**: Fixed build process to work correctly from external forks ([**@kvaps**](https://github.com/kvaps) in #1530).
* **[ci,dx] Add unit tests for cozy-lib**: Added unit tests for cozy-lib to improve code quality and reliability ([**@lllamnyp**](https://github.com/lllamnyp) in #1643).
---
## Documentation
* **[website] Add VPC page**: Added VPC documentation page explaining VPC features and usage ([**@nbykov0**](https://github.com/nbykov0) in cozystack/website@9ccac78).
* **[website] Add VPC to auto-update list**: Added VPC to auto-update list in documentation ([**@nbykov0**](https://github.com/nbykov0) in cozystack/website@ca2bce6).
* **[website] Update dashboard part in OIDC configuration doc**: Updated OIDC configuration documentation with dashboard information ([**@nbykov0**](https://github.com/nbykov0) in cozystack/website@6c44b93).
* **[website] Update storage requirements**: Updated storage requirements documentation ([**@nbykov0**](https://github.com/nbykov0) in cozystack/website@cac3af6).
* **[website] Add System Resource Planning Recommendations**: Added system resource planning recommendations documentation ([**@kvaps**](https://github.com/kvaps) in cozystack/website@c877c2a).
* **[website] Optimize website for mobile devices**: Improved website layout and responsiveness for mobile devices ([**@kvaps**](https://github.com/kvaps) in cozystack/website@3ab2338).
* **[website] Add OpenAPI UI**: Added OpenAPI UI documentation and integration ([**@kvaps**](https://github.com/kvaps) in cozystack/website@b1c1668).
* **[website] Update Cozystack video in hero banner**: Updated hero banner with new Cozystack video ([**@kvaps**](https://github.com/kvaps) in cozystack/website@e351137).
* **[website] Add screenshots carousel**: Added screenshots carousel to showcase Cozystack features ([**@kvaps**](https://github.com/kvaps) in cozystack/website@8422bd0).
* **[website] Update LINSTOR documentation**: Updated LINSTOR guide and set failmode=continue for ZFS configurations ([**@kvaps**](https://github.com/kvaps) in cozystack/website@033804e).
* **[website] Update managed apps reference**: Updated managed applications reference documentation ([**@kvaps**](https://github.com/kvaps) in cozystack/website@b886a74, cozystack/website@41c1849, cozystack/website@0ab71fd).
* **[website] Update external apps documentation**: Updated documentation for external applications ([**@kvaps**](https://github.com/kvaps) in cozystack/website@565dad9).
* **[website] Add naming conventions**: Added naming conventions documentation ([**@kvaps**](https://github.com/kvaps) in cozystack/website@b227abb).
* **[website] Update golden image documentation**: Updated documentation for creating golden images for virtual machines ([**@kvaps**](https://github.com/kvaps) in cozystack/website@34c2f3a, cozystack/website@ef65593).
* **[website] Fix documentation formatting**: Fixed alerts, infoboxes, tabs styles and main page formatting ([**@kvaps**](https://github.com/kvaps) in cozystack/website@e992e97, cozystack/website@b2c4dee).
* **[website] Fix typo in blog article**: Fixed typo in blog article ([**@kvaps**](https://github.com/kvaps) in cozystack/website@0a4bbf3).
* **[apps] vpc: more docs**: Added more VPC documentation ([**@nbykov0**](https://github.com/nbykov0) in #1594).
* **[apps] vpc: fix typo in README**: Fixed typo in VPC README ([**@nbykov0**](https://github.com/nbykov0) in #1637).
---
## Additional Repositories
### boot-to-talos
* **[boot-to-talos] Introduce boot/install mode**: Introduced boot/install mode in boot-to-talos tool ([**@kvaps**](https://github.com/kvaps) in cozystack/boot-to-talos#5).
### cozypkg
* **[cozypkg] Handle valuesFiles from cozypkg.cozystack.io/values-files annotation**: Added support for handling valuesFiles from annotation in cozypkg ([**@kvaps**](https://github.com/kvaps) in cozystack/cozypkg#8).
---
## Refactors & chores
* **[dashboard] Migrate patches to upstream project**: Migrated dashboard patches to upstream project for better maintainability ([**@kvaps**](https://github.com/kvaps) in #1569).
* **Update CODEOWNERS**: Updated CODEOWNERS file ([**@nbykov0**](https://github.com/nbykov0) in #1537).
* **Add QOSI to ADOPTERS.md**: Added QOSI to adopters list ([**@tabu-a**](https://github.com/tabu-a) in #1589).
---
## Breaking changes & upgrade notes
No breaking changes in this release.
---
## Contributors
We'd like to thank all contributors who made this release possible:
* [**@IvanHunters**](https://github.com/IvanHunters)
* [**@insignia96**](https://github.com/insignia96)
* [**@kvaps**](https://github.com/kvaps)
* [**@lllamnyp**](https://github.com/lllamnyp)
* [**@nbykov0**](https://github.com/nbykov0)
* [**@scooby87**](https://github.com/scooby87)
* [**@tabu-a**](https://github.com/tabu-a)
### New Contributors
We're excited to welcome our first-time contributors:
* [**@tabu-a**](https://github.com/tabu-a) - First contribution!
---
**Full Changelog**: [v0.37.0...v0.38.0](https://github.com/cozystack/cozystack/compare/v0.37.0...v0.38.0)
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.38.0
-->

View File

@@ -0,0 +1,19 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.38.1
-->
## Improvements
* **[seaweedfs] Extended CA certificate duration to reduce disruptive CA rotations**: Extended CA certificate duration to reduce disruptive CA rotations. ([**@IvanHunters**](https://github.com/IvanHunters) in #1657, #1666).
* **[dashboard] Add config hash annotations to restart pods on config changes**: Added config hash annotations to restart pods when configuration changes, ensuring pods are automatically restarted when their configuration is updated ([**@kvaps**](https://github.com/kvaps) in #1662, #1665).
## Fixes
* **[tenant][kubernetes] Introduce better cleanup logic**: Improved cleanup logic for tenant Kubernetes resources, ensuring proper resource cleanup when tenants are deleted or updated ([**@kvaps**](https://github.com/kvaps) in #1661).
* **[dashboard] Fix loading arrays in forms when editing existing objects**: Fixed issue where arrays in forms were not loading correctly when editing existing objects in the dashboard ([**@kvaps**](https://github.com/kvaps)).
---
**Full Changelog**: [v0.38.0...v0.38.1](https://github.com/cozystack/cozystack/compare/v0.38.0...v0.38.1)

View File

@@ -0,0 +1,13 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.38.2
-->
## Fixes
* **[api] Revert dynamic list kinds representation fix (fixes namespace deletion regression)**: Reverted changes from #1630 that caused a regression affecting namespace deletion and upgrades from previous versions. The regression caused namespace deletion failures with errors like "content is not a list: []unstructured.Unstructured" during namespace finalization. This revert restores compatibility with namespace deletion controller and fixes upgrade issues from previous versions, particularly when running migration 20 ([**@kvaps**](https://github.com/kvaps) in #1677).
---
**Full Changelog**: [v0.38.1...v0.38.2](https://github.com/cozystack/cozystack/compare/v0.38.1...v0.38.2)

View File

@@ -0,0 +1,14 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.38.3
-->
## Improvements
* **[core:installer] Address buildx warnings for installer image builds**: Aligns Dockerfile syntax casing to remove buildx warnings, keeping installer builds clean ([**@nbykov0**](https://github.com/nbykov0) in #1682).
* **[system:coredns] Align CoreDNS app labels with Talos defaults**: Matches CoreDNS labels to Talos conventions so services select pods consistently across platform and tenant clusters ([**@nbykov0**](https://github.com/nbykov0) in #1675).
* **[system:monitoring-agents] Rename CoreDNS metrics service to avoid conflicts**: Renames the metrics service so it no longer clashes with the CoreDNS service used for name resolution in tenant clusters ([**@nbykov0**](https://github.com/nbykov0) in #1676).
---
**Full Changelog**: [v0.38.2...v0.38.3](https://github.com/cozystack/cozystack/compare/v0.38.2...v0.38.3)

View File

@@ -0,0 +1,18 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.38.4
-->
## Fixes
* **[linstor] Update piraeus-operator v2.10.2 to handle fsck checks reliably**: Upgrades LINSTOR CSI to avoid failed mounts when fsck sees mounted volumes, improving volume publish reliability ([**@kvaps**](https://github.com/kvaps) in #1689, #1697).
* **[dashboard] Nest CustomFormsOverride properties under spec.properties**: Fixes schema generation so custom form properties are placed under `spec.properties`, preventing mis-rendered or missing form fields ([**@kvaps**](https://github.com/kvaps) in #1692, #1700).
* **[virtual-machine] Guard PVC resize to only expand storage**: Ensures resize jobs run only when storage size increases, avoiding unintended shrink attempts during VM updates ([**@kvaps**](https://github.com/kvaps) in #1688, #1701).
## Documentation
* **[website] Clarify GPU check command**: Makes the kubectl command for validating GPU binding more explicit, including namespace context ([**@nbykov0**](https://github.com/nbykov0) in cozystack/website#379).
---
**Full Changelog**: [v0.38.3...v0.38.4](https://github.com/cozystack/cozystack/compare/v0.38.3...v0.38.4)

View File

@@ -0,0 +1,95 @@
# Cozystack v0.39 — "Enhanced Networking & Monitoring"
This release introduces topology-aware routing for Cilium services, automatic pod rollouts on configuration changes, improved monitoring capabilities, and numerous bug fixes and improvements across the platform.
## Highlights
* **Topology-Aware Routing**: Enabled topology-aware routing for Cilium services, improving traffic distribution and reducing latency by routing traffic to endpoints in the same zone when possible ([**@nbykov0**](https://github.com/nbykov0) in #1734).
* **Automatic Pod Rollouts**: Cilium and Cilium operator pods now automatically restart when configuration changes, ensuring configuration updates are applied immediately ([**@kvaps**](https://github.com/kvaps) in #1728).
* **Windows VM Scheduling**: Added nodeAffinity configuration for Windows VMs based on scheduling config, enabling dedicated nodes for Windows workloads ([**@kvaps**](https://github.com/kvaps) in #1693).
* **SeaweedFS Updates**: Updated to SeaweedFS v4.02 with improved S3 daemon performance and fixes ([**@kvaps**](https://github.com/kvaps) in #1725).
---
## Major Features and Improvements
### Networking
* **[system/cilium] Enable topology-aware routing for services**: Enabled topology-aware routing for services, improving traffic distribution and reducing latency by routing traffic to endpoints in the same zone when possible. This feature helps optimize network performance in multi-zone deployments ([**@nbykov0**](https://github.com/nbykov0) in #1734).
* **[cilium] Enable automatic pod rollout on configmap updates**: Cilium and Cilium operator pods now automatically restart when the cilium-config ConfigMap is updated, ensuring configuration changes are applied immediately without manual intervention ([**@kvaps**](https://github.com/kvaps) in #1728).
### Virtual Machines
* **[virtual-machine,vm-instance] Add nodeAffinity for Windows VMs based on scheduling config**: Added nodeAffinity configuration to virtual-machine and vm-instance charts to support dedicated nodes for Windows VMs. When `dedicatedNodesForWindowsVMs` is enabled in the `cozystack-scheduling` ConfigMap, Windows VMs are scheduled on nodes with label `scheduling.cozystack.io/vm-windows=true`, while non-Windows VMs prefer nodes without this label ([**@kvaps**](https://github.com/kvaps) in #1693).
### Storage
* **Update SeaweedFS v4.02**: Updated SeaweedFS to version 4.02 with improved performance for S3 daemon and fixes for known issues. This update includes better S3 compatibility and performance improvements ([**@kvaps**](https://github.com/kvaps) in #1725).
### Tools
* **[talm] feat(init)!: require --name flag for cluster name**: Breaking change: The `talm init` command now requires the `--name` flag to specify the cluster name. This ensures consistent cluster naming and prevents accidental initialization without a name ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#86).
* **[talm] feat(template): preserve extra YAML documents in output**: Templates now preserve extra YAML documents in the output, allowing for more flexible template processing ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#87).
* **[talm] feat: add directory expansion for -f flag**: Added directory expansion support for the `-f` flag, allowing users to specify directories instead of individual files ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@ca5713e).
* **[talm] Introduce automatic root detection**: Added automatic root detection logic to simplify talm usage and reduce manual configuration ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@d165162).
* **[talm] Introduce talm kubeconfig --login command**: Added new `talm kubeconfig --login` command for easier kubeconfig management ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@5f7e05b).
* **[talm] Introduce encryption**: Added encryption support to talm for secure configuration management ([**@kvaps**](https://github.com/kvaps) in cozystack/talm#81).
* **[talm] Replace code-generation with wrapper on talosctl**: Refactored talm to use a wrapper on talosctl instead of code generation, simplifying the codebase and improving maintainability ([**@kvaps**](https://github.com/kvaps) in cozystack/talm#80).
* **[talm] Use go embed instead of code generation**: Migrated from code generation to go embed for better build performance and simpler dependency management ([**@kvaps**](https://github.com/kvaps) in cozystack/talm#79).
* **[boot-to-talos] Cozystack: Update Talos Linux v1.11.3**: Updated boot-to-talos to use Talos Linux v1.11.3 ([**@kvaps**](https://github.com/kvaps) in cozystack/boot-to-talos#7).
## Improvements
* **[seaweedfs] Extended CA certificate duration to reduce disruptive CA rotations**: Extended CA certificate duration to reduce disruptive CA rotations, improving long-term certificate management and reducing operational overhead ([**@IvanHunters**](https://github.com/IvanHunters) in #1657).
* **[dashboard] Add config hash annotations to restart pods on config changes**: Added config hash annotations to dashboard deployment templates to ensure pods are automatically restarted when their configuration changes, ensuring configuration updates are applied immediately ([**@kvaps**](https://github.com/kvaps) in #1662).
* **[tenant][kubernetes] Introduce better cleanup logic**: Improved cleanup logic for tenant Kubernetes resources, ensuring proper resource cleanup when tenants are deleted or updated. Added automated pre-delete cleanup job for tenant namespaces to remove tenant-related releases during uninstall ([**@kvaps**](https://github.com/kvaps) in #1661).
* **[system:coredns] update coredns app labels to match Talos coredns labels**: Updated coredns app labels to match Talos coredns labels, ensuring consistency across the platform ([**@nbykov0**](https://github.com/nbykov0) in #1675).
* **[system:monitoring-agents] rename coredns metrics service**: Renamed coredns metrics service to avoid interference with coredns service used for name resolution in tenant k8s clusters ([**@nbykov0**](https://github.com/nbykov0) in #1676).
* **[core:installer] Address buildx warnings**: Fixed Dockerfile syntax warnings from buildx, ensuring clean builds without warnings ([**@nbykov0**](https://github.com/nbykov0) in #1682).
* **[talm] Refactor root detection logic into single file**: Improved code organization by consolidating root detection logic into a single file ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@487b479).
* **[talm] Refactor init logic, better upgrade**: Improved initialization logic and upgrade process for better reliability ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@c512777).
* **[talm] Sugar for kubeconfig command**: Added convenience features to the kubeconfig command for improved usability ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@a4010b3).
* **[talm] wrap upgrade command**: Wrapped upgrade command for better integration and error handling ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@2e1afbf).
* **[talm] docs(readme): add Homebrew installation option**: Added Homebrew installation option to the README for easier installation on macOS ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm@12bd4f2).
* **[talm] cozystack: disable nodeCIDRs allocation**: Disabled nodeCIDRs allocation in talm for better network configuration control ([**@kvaps**](https://github.com/kvaps) in cozystack/talm#82).
* **[talm] Update license to Apache2.0**: Updated license to Apache 2.0 for better compatibility and clarity ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@eda1032).
## Fixes
* **[apps] Refactor apiserver to use typed objects and fix UnstructuredList GVK**: Refactored the apiserver REST handlers to use typed objects (`appsv1alpha1.Application`) instead of `unstructured.Unstructured`, eliminating the need for runtime conversions and simplifying the codebase. Additionally, fixed an issue where `UnstructuredList` objects were using the first registered kind from `typeToGVK` instead of the kind from the object's field when multiple kinds are registered with the same Go type. This fix includes the upstream fix from kubernetes/kubernetes#135537 ([**@kvaps**](https://github.com/kvaps) in #1679).
* **[dashboard] Fix CustomFormsOverride schema to nest properties under spec.properties**: Fixed the logic for generating CustomFormsOverride schema to properly nest properties under `spec.properties` instead of directly under `properties`, ensuring correct form schema generation ([**@kvaps**](https://github.com/kvaps) in #1692).
* **[virtual-machine] Improve check for resizing job**: Improved storage resize logic to only expand persistent volume claims when storage is being increased, preventing unintended storage reduction operations. Added validation to accurately compare current and desired storage sizes before triggering resize operations ([**@kvaps**](https://github.com/kvaps) in #1688).
* **[linstor] Update piraeus-operator v2.10.2**: Updated LINSTOR CSI to fix issues with the new fsck behaviour, resolving mount failures when fsck attempts to run on mounted devices ([**@kvaps**](https://github.com/kvaps) in #1689).
* **[api] Revert dynamic list kinds representation fix (fixes namespace deletion regression)**: Reverted changes from #1630 that caused a regression affecting namespace deletion and upgrades from previous versions. The regression caused namespace deletion failures with errors like "content is not a list: []unstructured.Unstructured" during namespace finalization. This revert restores compatibility with namespace deletion controller and fixes upgrade issues from previous versions ([**@kvaps**](https://github.com/kvaps) in #1677).
* **[talm] fix: normalize template paths for Windows compatibility**: Fixed template path handling to ensure Windows compatibility by normalizing paths ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#88).
## Dependencies
* **Update SeaweedFS v4.02**: Updated SeaweedFS to version 4.02 ([**@kvaps**](https://github.com/kvaps) in #1725).
* **[linstor] Update piraeus-operator v2.10.2**: Updated piraeus-operator to version 2.10.2 ([**@kvaps**](https://github.com/kvaps) in #1689).
* **[talm] Cozystack: Update Talos Linux v1.11.3**: Updated talm to use Talos Linux v1.11.3 ([**@kvaps**](https://github.com/kvaps) in cozystack/talm#83).
## Documentation
* **[website] Add article: Talm v0.17: Built-in Age Encryption for Secrets Management**: Added comprehensive blog post announcing Talm v0.17 and its built-in age-based encryption for secrets. Covers initial setup and key generation, encryption/decryption workflows, idempotent encryption behavior, automatic .gitignore handling, file permission safeguards, security best practices, and guidance for GitOps and CI/CD integration ([**@kvaps**](https://github.com/kvaps) in [cozystack/website#384](https://github.com/cozystack/website/pull/384)).
* **[website] docs(talm): update talm init syntax for mandatory --preset and --name flags**: Updated documentation to reflect breaking changes in talm, adding mandatory `--preset` and `--name` flags to the talm init command ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#386).
---
## Contributors
We'd like to thank all contributors who made this release possible:
* [**@IvanHunters**](https://github.com/IvanHunters)
* [**@kvaps**](https://github.com/kvaps)
* [**@lexfrei**](https://github.com/lexfrei)
* [**@nbykov0**](https://github.com/nbykov0)
---
**Full Changelog**: [v0.38.0...v0.39.0](https://github.com/cozystack/cozystack/compare/v0.38.0...v0.39.0)
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.39.0
-->

View File

@@ -0,0 +1,12 @@
<!--
https://github.com/cozystack/cozystack/releases/tag/v0.39.1
-->
## Features and Improvements
* **[monitoring] Add SLACK_SEVERITY_FILTER field and VMAgent for tenant monitoring**: Introduced the SLACK_SEVERITY_FILTER environment variable in the Alerta deployment to enable filtering of alert severities for Slack notifications based on the disabledSeverity configuration. Additionally, added a VMAgent resource template for scraping metrics within tenant namespaces, improving monitoring granularity and control. This enhancement allows administrators to configure which alert severities are sent to Slack and enables tenant-specific metrics collection for better observability ([**@IvanHunters**](https://github.com/IvanHunters) in #1712).
---
**Full Changelog**: [v0.39.0...v0.39.1](https://github.com/cozystack/cozystack/compare/v0.39.0...v0.39.1)

148
go.mod
View File

@@ -2,33 +2,37 @@
module github.com/cozystack/cozystack
go 1.23.0
go 1.25.0
require (
github.com/fluxcd/helm-controller/api v1.1.0
github.com/fluxcd/helm-controller/api v1.4.3
github.com/go-logr/logr v1.4.3
github.com/go-logr/zapr v1.3.0
github.com/google/gofuzz v1.2.0
github.com/onsi/ginkgo/v2 v2.19.0
github.com/onsi/gomega v1.33.1
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
github.com/onsi/ginkgo/v2 v2.23.3
github.com/onsi/gomega v1.37.0
github.com/prometheus/client_golang v1.22.0
github.com/robfig/cron/v3 v3.0.1
github.com/spf13/cobra v1.9.1
go.uber.org/zap v1.27.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.31.2
k8s.io/apiextensions-apiserver v0.31.2
k8s.io/apimachinery v0.31.2
k8s.io/apiserver v0.31.2
k8s.io/client-go v0.31.2
k8s.io/component-base v0.31.2
k8s.io/api v0.34.1
k8s.io/apiextensions-apiserver v0.34.1
k8s.io/apimachinery v0.34.1
k8s.io/apiserver v0.34.1
k8s.io/client-go v0.34.1
k8s.io/component-base v0.34.1
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20240827152857-f7e401e7b4c2
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
sigs.k8s.io/controller-runtime v0.19.0
sigs.k8s.io/structured-merge-diff/v4 v4.4.1
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b
k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d
sigs.k8s.io/controller-runtime v0.22.2
sigs.k8s.io/structured-merge-diff/v4 v4.7.0
)
require (
cel.dev/expr v0.24.0 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
@@ -36,86 +40,90 @@ require (
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fluxcd/pkg/apis/kustomize v1.6.1 // indirect
github.com/fluxcd/pkg/apis/meta v1.6.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/fluxcd/pkg/apis/kustomize v1.13.0 // indirect
github.com/fluxcd/pkg/apis/meta v1.22.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/cel-go v0.21.0 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/cel-go v0.26.0 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/moby/spdystream v0.4.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/moby/spdystream v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/pflag v1.0.7 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.etcd.io/etcd/api/v3 v3.5.16 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.16 // indirect
go.etcd.io/etcd/client/v3 v3.5.16 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.etcd.io/etcd/api/v3 v3.6.4 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.6.4 // indirect
go.etcd.io/etcd/client/v3 v3.6.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.42.0 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/term v0.27.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.7.0 // indirect
golang.org/x/tools v0.26.0 // indirect
golang.org/x/net v0.45.0 // indirect
golang.org/x/oauth2 v0.29.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/term v0.35.0 // indirect
golang.org/x/text v0.29.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.37.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/grpc v1.65.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/grpc v1.72.1 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/kms v0.31.2 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
k8s.io/kms v0.34.1 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)
// See: issues.k8s.io/135537
replace k8s.io/apimachinery => github.com/cozystack/apimachinery v0.0.0-20251219010959-1f91eabae46c

341
go.sum
View File

@@ -1,11 +1,11 @@
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
@@ -18,45 +18,44 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cozystack/apimachinery v0.0.0-20251219010959-1f91eabae46c h1:C2wIfH/OzhU9XOK/e6Ik9cg7nZ1z6fN4lf6a3yFdik8=
github.com/cozystack/apimachinery v0.0.0-20251219010959-1f91eabae46c/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fluxcd/helm-controller/api v1.1.0 h1:NS5Wm3U6Kv4w7Cw2sDOV++vf2ecGfFV00x1+2Y3QcOY=
github.com/fluxcd/helm-controller/api v1.1.0/go.mod h1:BgHMgMY6CWynzl4KIbHpd6Wpn3FN9BqgkwmvoKCp6iE=
github.com/fluxcd/pkg/apis/kustomize v1.6.1 h1:22FJc69Mq4i8aCxnKPlddHhSMyI4UPkQkqiAdWFcqe0=
github.com/fluxcd/pkg/apis/kustomize v1.6.1/go.mod h1:5dvQ4IZwz0hMGmuj8tTWGtarsuxW0rWsxJOwC6i+0V8=
github.com/fluxcd/pkg/apis/meta v1.6.1 h1:maLhcRJ3P/70ArLCY/LF/YovkxXbX+6sTWZwZQBeNq0=
github.com/fluxcd/pkg/apis/meta v1.6.1/go.mod h1:YndB/gxgGZmKfqpAfFxyCDNFJFP0ikpeJzs66jwq280=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/fluxcd/helm-controller/api v1.4.3 h1:CdZwjL1liXmYCWyk2jscmFEB59tICIlnWB9PfDDW5q4=
github.com/fluxcd/helm-controller/api v1.4.3/go.mod h1:0XrBhKEaqvxyDj/FziG1Q8Fmx2UATdaqLgYqmZh6wW4=
github.com/fluxcd/pkg/apis/kustomize v1.13.0 h1:GGf0UBVRIku+gebY944icVeEIhyg1P/KE3IrhOyJJnE=
github.com/fluxcd/pkg/apis/kustomize v1.13.0/go.mod h1:TLKVqbtnzkhDuhWnAsN35977HvRfIjs+lgMuNro/LEc=
github.com/fluxcd/pkg/apis/meta v1.22.0 h1:EHWQH5ZWml7i8eZ/AMjm1jxid3j/PQ31p+hIwCt6crM=
github.com/fluxcd/pkg/apis/meta v1.22.0/go.mod h1:Kc1+bWe5p0doROzuV9XiTfV/oL3ddsemYXt8ZYWdVVg=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
@@ -64,162 +63,171 @@ github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZ
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/cel-go v0.21.0 h1:cl6uW/gxN+Hy50tNYvI691+sXxioCnstFzLp2WO4GCI=
github.com/google/cel-go v0.21.0/go.mod h1:rHUlWCcBKgyEk+eV03RPdZUekPp6YcJwV0FxuUksYxc=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI=
github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8=
github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0=
github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM=
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk=
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
go.etcd.io/etcd/api/v3 v3.5.16 h1:WvmyJVbjWqK4R1E+B12RRHz3bRGy9XVfh++MgbN+6n0=
go.etcd.io/etcd/api/v3 v3.5.16/go.mod h1:1P4SlIP/VwkDmGo3OlOD7faPeP8KDIFhqvciH5EfN28=
go.etcd.io/etcd/client/pkg/v3 v3.5.16 h1:ZgY48uH6UvB+/7R9Yf4x574uCO3jIx0TRDyetSfId3Q=
go.etcd.io/etcd/client/pkg/v3 v3.5.16/go.mod h1:V8acl8pcEK0Y2g19YlOV9m9ssUe6MgiDSobSoaBAM0E=
go.etcd.io/etcd/client/v2 v2.305.13 h1:RWfV1SX5jTU0lbCvpVQe3iPQeAHETWdOTb6pxhd77C8=
go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg=
go.etcd.io/etcd/client/v3 v3.5.16 h1:sSmVYOAHeC9doqi0gv7v86oY/BTld0SEFGaxsU9eRhE=
go.etcd.io/etcd/client/v3 v3.5.16/go.mod h1:X+rExSGkyqxvu276cr2OwPLBaeqFu1cIl4vmRjAD/50=
go.etcd.io/etcd/pkg/v3 v3.5.13 h1:st9bDWNsKkBNpP4PR1MvM/9NqUPfvYZx/YXegsYEH8M=
go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0=
go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA=
go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw=
go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok=
go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ=
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I=
go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM=
go.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo=
go.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk=
go.etcd.io/etcd/client/pkg/v3 v3.6.4 h1:9HBYrjppeOfFjBjaMTRxT3R7xT0GLK8EJMVC4xg6ok0=
go.etcd.io/etcd/client/pkg/v3 v3.6.4/go.mod h1:sbdzr2cl3HzVmxNw//PH7aLGVtY4QySjQFuaCgcRFAI=
go.etcd.io/etcd/client/v3 v3.6.4 h1:YOMrCfMhRzY8NgtzUsHl8hC2EBSnuqbR3dh84Uryl7A=
go.etcd.io/etcd/client/v3 v3.6.4/go.mod h1:jaNNHCyg2FdALyKWnd7hxZXZxZANb0+KGY+YQaEMISo=
go.etcd.io/etcd/pkg/v3 v3.6.4 h1:fy8bmXIec1Q35/jRZ0KOes8vuFxbvdN0aAFqmEfJZWA=
go.etcd.io/etcd/pkg/v3 v3.6.4/go.mod h1:kKcYWP8gHuBRcteyv6MXWSN0+bVMnfgqiHueIZnKMtE=
go.etcd.io/etcd/server/v3 v3.6.4 h1:LsCA7CzjVt+8WGrdsnh6RhC0XqCsLkBly3ve5rTxMAU=
go.etcd.io/etcd/server/v3 v3.6.4/go.mod h1:aYCL/h43yiONOv0QIR82kH/2xZ7m+IWYjzRmyQfnCAg=
go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ=
go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -228,50 +236,48 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY=
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -281,39 +287,42 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0=
k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk=
k8s.io/apiextensions-apiserver v0.31.2 h1:W8EwUb8+WXBLu56ser5IudT2cOho0gAKeTOnywBLxd0=
k8s.io/apiextensions-apiserver v0.31.2/go.mod h1:i+Geh+nGCJEGiCGR3MlBDkS7koHIIKWVfWeRFiOsUcM=
k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw=
k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/apiserver v0.31.2 h1:VUzOEUGRCDi6kX1OyQ801m4A7AUPglpsmGvdsekmcI4=
k8s.io/apiserver v0.31.2/go.mod h1:o3nKZR7lPlJqkU5I3Ove+Zx3JuoFjQobGX1Gctw6XuE=
k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc=
k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs=
k8s.io/component-base v0.31.2 h1:Z1J1LIaC0AV+nzcPRFqfK09af6bZ4D1nAOpWsy9owlA=
k8s.io/component-base v0.31.2/go.mod h1:9PeyyFN/drHjtJZMCTkSpQJS3U9OXORnHQqMLDz0sUQ=
k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM=
k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk=
k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI=
k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc=
k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA=
k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0=
k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY=
k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8=
k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A=
k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kms v0.31.2 h1:pyx7l2qVOkClzFMIWMVF/FxsSkgd+OIGH7DecpbscJI=
k8s.io/kms v0.31.2/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94=
k8s.io/kube-openapi v0.0.0-20240827152857-f7e401e7b4c2 h1:GKE9U8BH16uynoxQii0auTjmmmuZ3O0LFMN6S0lPPhI=
k8s.io/kube-openapi v0.0.0-20240827152857-f7e401e7b4c2/go.mod h1:coRQXBK9NxO98XUv3ZD6AK3xzHCxV6+b7lrquKwaKzA=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q=
sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
k8s.io/kms v0.34.1 h1:iCFOvewDPzWM9fMTfyIPO+4MeuZ0tcZbugxLNSHFG4w=
k8s.io/kms v0.34.1/go.mod h1:s1CFkLG7w9eaTYvctOxosx88fl4spqmixnNpys0JAtM=
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA=
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPGPs+Ki1gHw4w1R0=
k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/controller-runtime v0.22.2 h1:cK2l8BGWsSWkXz09tcS4rJh95iOLney5eawcK5A33r4=
sigs.k8s.io/controller-runtime v0.22.2/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=

145
hack/check-optional-repos.sh Executable file
View File

@@ -0,0 +1,145 @@
#!/bin/bash
###############################################################################
# check-optional-repos.sh - Check optional repositories for tags and commits #
# during a release period #
###############################################################################
set -eu
# Function to ensure repository is cloned and up-to-date
update_repo() {
local repo_name=$1
local repo_url="https://github.com/cozystack/${repo_name}.git"
mkdir -p _repos
cd _repos
if [ -d "$repo_name" ]; then
cd "$repo_name"
git fetch --all --tags --force
git checkout main 2>/dev/null || git checkout master
git pull
else
git clone "$repo_url"
cd "$repo_name"
fi
cd ../..
}
# Check if required parameters are provided
if [ $# -lt 2 ]; then
echo "Usage: $0 <RELEASE_START> <RELEASE_END>"
echo "Example: $0 '2025-10-10 12:27:31 +0400' '2025-10-13 16:04:33 +0200'"
exit 1
fi
RELEASE_START="$1"
RELEASE_END="$2"
# Get the script directory to return to it later
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
COZYSTACK_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
cd "$COZYSTACK_ROOT"
echo "Checking optional repositories for tags and commits between:"
echo " Start: $RELEASE_START"
echo " End: $RELEASE_END"
echo ""
# Loop through ALL optional repositories
for repo_name in talm boot-to-talos cozyhr cozy-proxy; do
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Checking repository: $repo_name"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# Update/clone repository
update_repo "$repo_name"
cd "_repos/$repo_name"
REPO_NAME=$(basename "$(pwd)")
git fetch --all --tags --force
# Check for tags matching release version pattern or created during release period
TAGS=$(git for-each-ref --format='%(refname:short) %(creatordate)' refs/tags 2>/dev/null | \
awk -v start="$RELEASE_START" -v end="$RELEASE_END" '$2 >= start && $2 <= end {print $1}' || true)
if [ -n "$TAGS" ]; then
echo "Found tags in $repo_name: $TAGS"
PREV_TAG=$(echo "$TAGS" | head -1)
NEW_TAG=$(echo "$TAGS" | tail -1)
echo ""
echo "Commits between $PREV_TAG and $NEW_TAG:"
# Include merge commits to capture backports
git log "$PREV_TAG..$NEW_TAG" --format="%H|%s|%an" 2>/dev/null | while IFS='|' read -r commit_hash subject author_name; do
if [ -z "$commit_hash" ]; then
continue
fi
# Get PR number from commit message
COMMIT_MSG=$(git log -1 --format=%B "$commit_hash" 2>/dev/null || echo "")
PR_NUMBER=$(echo "$COMMIT_MSG" | grep -oE '#[0-9]+' | head -1 | tr -d '#' || echo "")
# Get author: prioritize PR author, fallback to commit author
GITHUB_USERNAME=""
if [ -n "$PR_NUMBER" ]; then
GITHUB_USERNAME=$(gh pr view "$PR_NUMBER" --repo "cozystack/$REPO_NAME" --json author --jq '.author.login // empty' 2>/dev/null || echo "")
fi
if [ -z "$GITHUB_USERNAME" ]; then
GITHUB_USERNAME=$(gh api "repos/cozystack/$REPO_NAME/commits/$commit_hash" --jq '.author.login // empty' 2>/dev/null || echo "")
fi
if [ -n "$PR_NUMBER" ]; then
echo " $commit_hash|$subject|$author_name|$GITHUB_USERNAME|cozystack/$REPO_NAME#$PR_NUMBER"
else
echo " $commit_hash|$subject|$author_name|$GITHUB_USERNAME|cozystack/$REPO_NAME@${commit_hash:0:7}"
fi
done
else
echo "No tags found in $repo_name during release period"
# Check for commits by dates if no exact version tags
# Include merge commits to capture backports
COMMITS=$(git log --since="$RELEASE_START" --until="$RELEASE_END" --format="%H|%s|%an" 2>/dev/null || true)
if [ -n "$COMMITS" ]; then
echo ""
echo "Commits found by date range:"
echo "$COMMITS" | while IFS='|' read -r commit_hash subject author_name; do
if [ -z "$commit_hash" ]; then
continue
fi
# Get PR number from commit message
COMMIT_MSG=$(git log -1 --format=%B "$commit_hash" 2>/dev/null || echo "")
PR_NUMBER=$(echo "$COMMIT_MSG" | grep -oE '#[0-9]+' | head -1 | tr -d '#' || echo "")
# Get author: prioritize PR author, fallback to commit author
GITHUB_USERNAME=""
if [ -n "$PR_NUMBER" ]; then
GITHUB_USERNAME=$(gh pr view "$PR_NUMBER" --repo "cozystack/$REPO_NAME" --json author --jq '.author.login // empty' 2>/dev/null || echo "")
fi
if [ -z "$GITHUB_USERNAME" ]; then
GITHUB_USERNAME=$(gh api "repos/cozystack/$REPO_NAME/commits/$commit_hash" --jq '.author.login // empty' 2>/dev/null || echo "")
fi
if [ -n "$PR_NUMBER" ]; then
echo " $commit_hash|$subject|$author_name|$GITHUB_USERNAME|cozystack/$REPO_NAME#$PR_NUMBER"
else
echo " $commit_hash|$subject|$author_name|$GITHUB_USERNAME|cozystack/$REPO_NAME@${commit_hash:0:7}"
fi
done
else
echo "No commits found in $repo_name during release period"
fi
fi
echo ""
cd "$COZYSTACK_ROOT"
done
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Finished checking all optional repositories"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bats
@test "Create DB MongoDB" {
name='test'
kubectl apply -f - <<EOF
apiVersion: apps.cozystack.io/v1alpha1
kind: MongoDB
metadata:
name: $name
namespace: tenant-test
spec:
external: false
size: 10Gi
replicas: 1
storageClass: ""
resourcesPreset: "nano"
backup:
enabled: false
EOF
sleep 5
# Wait for HelmRelease
kubectl -n tenant-test wait hr mongodb-$name --timeout=60s --for=condition=ready
# Wait for MongoDB service (port 27017)
timeout 120 sh -ec "until kubectl -n tenant-test get svc mongodb-$name-rs0 -o jsonpath='{.spec.ports[0].port}' | grep -q '27017'; do sleep 10; done"
# Wait for endpoints
timeout 180 sh -ec "until kubectl -n tenant-test get endpoints mongodb-$name-rs0 -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
# Wait for StatefulSet replicas
kubectl -n tenant-test wait statefulset.apps/mongodb-$name-rs0 --timeout=300s --for=jsonpath='{.status.replicas}'=1
# Cleanup
kubectl -n tenant-test delete mongodbs.apps.cozystack.io $name
}

View File

@@ -72,7 +72,7 @@ EOF
kubectl wait --for=condition=TenantControlPlaneCreated kamajicontrolplane -n tenant-test kubernetes-${test_name} --timeout=4m
# Wait for Kubernetes resources to be ready (timeout after 2 minutes)
kubectl wait tcp -n tenant-test kubernetes-${test_name} --timeout=2m --for=jsonpath='{.status.kubernetesResources.version.status}'=Ready
kubectl wait tcp -n tenant-test kubernetes-${test_name} --timeout=5m --for=jsonpath='{.status.kubernetesResources.version.status}'=Ready
# Wait for all required deployments to be available (timeout after 4 minutes)
kubectl wait deploy --timeout=4m --for=condition=available -n tenant-test kubernetes-${test_name} kubernetes-${test_name}-cluster-autoscaler kubernetes-${test_name}-kccm kubernetes-${test_name}-kcsi-controller
@@ -80,58 +80,41 @@ EOF
# Wait for the machine deployment to scale to 2 replicas (timeout after 1 minute)
kubectl wait machinedeployment kubernetes-${test_name}-md0 -n tenant-test --timeout=1m --for=jsonpath='{.status.replicas}'=2
# Get the admin kubeconfig and save it to a file
kubectl get secret kubernetes-${test_name}-admin-kubeconfig -ojsonpath='{.data.super-admin\.conf}' -n tenant-test | base64 -d > tenantkubeconfig
kubectl get secret kubernetes-${test_name}-admin-kubeconfig -ojsonpath='{.data.super-admin\.conf}' -n tenant-test | base64 -d > tenantkubeconfig-${test_name}
# Update the kubeconfig to use localhost for the API server
yq -i ".clusters[0].cluster.server = \"https://localhost:${port}\"" tenantkubeconfig
yq -i ".clusters[0].cluster.server = \"https://localhost:${port}\"" tenantkubeconfig-${test_name}
# Set up port forwarding to the Kubernetes API server for a 200 second timeout
bash -c 'timeout 300s kubectl port-forward service/kubernetes-'"${test_name}"' -n tenant-test '"${port}"':6443 > /dev/null 2>&1 &'
bash -c 'timeout 500s kubectl port-forward service/kubernetes-'"${test_name}"' -n tenant-test '"${port}"':6443 > /dev/null 2>&1 &'
# Verify the Kubernetes version matches what we expect (retry for up to 20 seconds)
timeout 20 sh -ec 'until kubectl --kubeconfig tenantkubeconfig version 2>/dev/null | grep -Fq "Server Version: ${k8s_version}"; do sleep 5; done'
timeout 20 sh -ec 'until kubectl --kubeconfig tenantkubeconfig-'"${test_name}"' version 2>/dev/null | grep -Fq "Server Version: ${k8s_version}"; do sleep 5; done'
# Wait for the nodes to be ready (timeout after 2 minutes)
timeout 3m bash -c '
until [ "$(kubectl --kubeconfig tenantkubeconfig get nodes -o jsonpath="{.items[*].metadata.name}" | wc -w)" -eq 2 ]; do
until [ "$(kubectl --kubeconfig tenantkubeconfig-'"${test_name}"' get nodes -o jsonpath="{.items[*].metadata.name}" | wc -w)" -eq 2 ]; do
sleep 2
done
'
# Verify the nodes are ready
kubectl --kubeconfig tenantkubeconfig wait node --all --timeout=2m --for=condition=Ready
kubectl --kubeconfig tenantkubeconfig get nodes -o wide
kubectl --kubeconfig tenantkubeconfig-${test_name} wait node --all --timeout=2m --for=condition=Ready
kubectl --kubeconfig tenantkubeconfig-${test_name} get nodes -o wide
# Verify the kubelet version matches what we expect
versions=$(kubectl --kubeconfig tenantkubeconfig get nodes -o jsonpath='{.items[*].status.nodeInfo.kubeletVersion}')
versions=$(kubectl --kubeconfig "tenantkubeconfig-${test_name}" \
get nodes -o jsonpath='{.items[*].status.nodeInfo.kubeletVersion}')
node_ok=true
case "$k8s_version" in
v1.32*)
echo "⚠️ TODO: Temporary stub — allowing nodes with v1.33 while k8s_version is v1.32"
;;
esac
for v in $versions; do
case "$k8s_version" in
v1.32|v1.32.*)
case "$v" in
v1.32 | v1.32.* | v1.32-* | v1.33 | v1.33.* | v1.33-*)
;;
*)
node_ok=false
break
;;
esac
case "$v" in
"${k8s_version}" | "${k8s_version}".* | "${k8s_version}"-*)
# acceptable
;;
*)
case "$v" in
"${k8s_version}" | "${k8s_version}".* | "${k8s_version}"-*)
;;
*)
node_ok=false
break
;;
esac
node_ok=false
break
;;
esac
done
@@ -141,6 +124,100 @@ EOF
exit 1
fi
kubectl --kubeconfig tenantkubeconfig-${test_name} apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: tenant-test
EOF
# Backend 1
kubectl apply --kubeconfig tenantkubeconfig-${test_name} -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: "${test_name}-backend"
namespace: tenant-test
spec:
replicas: 1
selector:
matchLabels:
app: backend
backend: "${test_name}-backend"
template:
metadata:
labels:
app: backend
backend: "${test_name}-backend"
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 2
periodSeconds: 2
EOF
# LoadBalancer Service
kubectl apply --kubeconfig tenantkubeconfig-${test_name} -f- <<EOF
apiVersion: v1
kind: Service
metadata:
name: "${test_name}-backend"
namespace: tenant-test
spec:
type: LoadBalancer
selector:
app: backend
backend: "${test_name}-backend"
ports:
- port: 80
targetPort: 80
EOF
# Wait for pods readiness
kubectl wait deployment --kubeconfig tenantkubeconfig-${test_name} ${test_name}-backend -n tenant-test --for=condition=Available --timeout=90s
# Wait for LoadBalancer to be provisioned (IP or hostname)
timeout 90 sh -ec "
until kubectl get svc ${test_name}-backend --kubeconfig tenantkubeconfig-${test_name} -n tenant-test \
-o jsonpath='{.status.loadBalancer.ingress[0]}' | grep -q .; do
sleep 5
done
"
LB_ADDR=$(
kubectl get svc --kubeconfig tenantkubeconfig-${test_name} "${test_name}-backend" \
-n tenant-test \
-o jsonpath='{.status.loadBalancer.ingress[0].ip}{.status.loadBalancer.ingress[0].hostname}'
)
if [ -z "$LB_ADDR" ]; then
echo "LoadBalancer address is empty" >&2
exit 1
fi
for i in $(seq 1 20); do
echo "Attempt $i"
curl --silent --fail "http://${LB_ADDR}" && break
sleep 3
done
if [ "$i" -eq 20 ]; then
echo "LoadBalancer not reachable" >&2
exit 1
fi
# Cleanup
kubectl delete deployment --kubeconfig tenantkubeconfig-${test_name} "${test_name}-backend" -n tenant-test
kubectl delete service --kubeconfig tenantkubeconfig-${test_name} "${test_name}-backend" -n tenant-test
# Wait for all machine deployment replicas to be ready (timeout after 10 minutes)
kubectl wait machinedeployment kubernetes-${test_name}-md0 -n tenant-test --timeout=10m --for=jsonpath='{.status.v1beta2.readyReplicas}'=2

View File

@@ -19,3 +19,35 @@
curl -sS --fail 'http://localhost:21234/openapi/v2?timeout=32s' -H 'Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf' > /dev/null
)
}
@test "Test kinds" {
val=$(kubectl get --raw /apis/apps.cozystack.io/v1alpha1/tenants | jq -r '.kind')
if [ "$val" != "TenantList" ]; then
echo "Expected kind to be TenantList, got $val"
exit 1
fi
val=$(kubectl get --raw /apis/apps.cozystack.io/v1alpha1/tenants | jq -r '.items[0].kind')
if [ "$val" != "Tenant" ]; then
echo "Expected kind to be Tenant, got $val"
exit 1
fi
val=$(kubectl get --raw /apis/apps.cozystack.io/v1alpha1/ingresses | jq -r '.kind')
if [ "$val" != "IngressList" ]; then
echo "Expected kind to be IngressList, got $val"
exit 1
fi
val=$(kubectl get --raw /apis/apps.cozystack.io/v1alpha1/ingresses | jq -r '.items[0].kind')
if [ "$val" != "Ingress" ]; then
echo "Expected kind to be Ingress, got $val"
exit 1
fi
}
@test "Create and delete namespace" {
kubectl create ns cozy-test-create-and-delete-namespace --dry-run=client -o yaml | kubectl apply -f -
if ! kubectl delete ns cozy-test-create-and-delete-namespace; then
echo "Failed to delete namespace"
kubectl describe ns cozy-test-create-and-delete-namespace
exit 1
fi
}

59
hack/helm-unit-tests.sh Executable file
View File

@@ -0,0 +1,59 @@
#!/bin/sh
set -eu
# Script to run unit tests for all Helm charts.
# It iterates through directories in packages/apps, packages/extra,
# packages/system, and packages/library and runs the 'test' Makefile
# target if it exists.
FAILED_DIRS_FILE="$(mktemp)"
trap 'rm -f "$FAILED_DIRS_FILE"' EXIT
tests_found=0
check_and_run_test() {
dir="$1"
makefile="$dir/Makefile"
if [ ! -f "$makefile" ]; then
return 0
fi
if make -C "$dir" -n test >/dev/null 2>&1; then
echo "Running tests in $dir"
tests_found=$((tests_found + 1))
if ! make -C "$dir" test; then
printf '%s\n' "$dir" >> "$FAILED_DIRS_FILE"
return 1
fi
fi
return 0
}
for package_dir in packages/apps packages/extra packages/system packages/library; do
if [ ! -d "$package_dir" ]; then
echo "Warning: Directory $package_dir does not exist, skipping..." >&2
continue
fi
for dir in "$package_dir"/*; do
[ -d "$dir" ] || continue
check_and_run_test "$dir" || true
done
done
if [ "$tests_found" -eq 0 ]; then
echo "No directories with 'test' Makefile targets found."
exit 0
fi
if [ -s "$FAILED_DIRS_FILE" ]; then
echo "ERROR: Tests failed in the following directories:" >&2
while IFS= read -r dir; do
echo " - $dir" >&2
done < "$FAILED_DIRS_FILE"
exit 1
fi
echo "All Helm unit tests passed."

View File

@@ -8,7 +8,6 @@ need yq; need jq; need base64
CHART_YAML="${CHART_YAML:-Chart.yaml}"
VALUES_YAML="${VALUES_YAML:-values.yaml}"
SCHEMA_JSON="${SCHEMA_JSON:-values.schema.json}"
CRD_DIR="../../system/cozystack-resource-definitions/cozyrds"
[[ -f "$CHART_YAML" ]] || { echo "No $CHART_YAML found"; exit 1; }
[[ -f "$SCHEMA_JSON" ]] || { echo "No $SCHEMA_JSON found"; exit 1; }
@@ -22,6 +21,8 @@ if [[ -z "$NAME" ]]; then
echo "Chart.yaml: .name is empty"; exit 1
fi
CRD_DIR="../../system/${NAME}-rd/cozyrds"
# Resolve icon path
# Accepts:
# /logos/foo.svg -> ./logos/foo.svg

40
hack/upload-releasenotes.sh Executable file
View File

@@ -0,0 +1,40 @@
#!/bin/sh
if [ $# -ne 1 ]; then
echo "Usage: $0 <version>"
echo "Example: 0.37.*"
exit 1
fi
VERSION_PATTERN="$1"
# Collect matching files first
FILES=$(find docs/changelogs -name "v${VERSION_PATTERN}.md" 2>/dev/null || true)
if [ -z "$FILES" ]; then
echo "No changelog files found matching pattern: v${VERSION_PATTERN}.md"
exit 1
fi
# Process each file
echo "$FILES" | while IFS= read -r file; do
if [ -z "$file" ]; then
continue
fi
# Extract version from filename safely (basename without extension)
version=$(basename "$file" .md)
if [ -z "$version" ]; then
echo "Warning: Could not extract version from file: $file"
continue
fi
echo "Uploading release notes for version: $version"
# Check exit status of gh release edit
if ! gh release edit "$version" --notes-file "docs/changelogs/${version}.md"; then
echo "Error: Failed to upload release notes for version: $version"
exit 1
fi
done

View File

@@ -37,6 +37,8 @@ type CozystackResourceDefinitionReconciler struct {
}
func (r *CozystackResourceDefinitionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// Only handle debounced restart logic
// HelmRelease reconciliation is handled by CozystackResourceDefinitionHelmReconciler
return r.debouncedRestart(ctx)
}

View File

@@ -0,0 +1,201 @@
package controller
import (
"context"
"fmt"
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
helmv2 "github.com/fluxcd/helm-controller/api/v2"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)
// +kubebuilder:rbac:groups=cozystack.io,resources=cozystackresourcedefinitions,verbs=get;list;watch
// +kubebuilder:rbac:groups=helm.toolkit.fluxcd.io,resources=helmreleases,verbs=get;list;watch;update;patch
// CozystackResourceDefinitionHelmReconciler reconciles CozystackResourceDefinitions
// and updates related HelmReleases when a CozyRD changes.
// This controller does NOT watch HelmReleases to avoid mutual reconciliation storms
// with Flux's helm-controller.
type CozystackResourceDefinitionHelmReconciler struct {
client.Client
Scheme *runtime.Scheme
}
func (r *CozystackResourceDefinitionHelmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx)
// Get the CozystackResourceDefinition that triggered this reconciliation
crd := &cozyv1alpha1.CozystackResourceDefinition{}
if err := r.Get(ctx, req.NamespacedName, crd); err != nil {
logger.Error(err, "failed to get CozystackResourceDefinition", "name", req.Name)
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// Update HelmReleases related to this specific CozyRD
if err := r.updateHelmReleasesForCRD(ctx, crd); err != nil {
logger.Error(err, "failed to update HelmReleases for CRD", "crd", crd.Name)
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}
func (r *CozystackResourceDefinitionHelmReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
Named("cozystackresourcedefinition-helm-reconciler").
For(&cozyv1alpha1.CozystackResourceDefinition{}).
Complete(r)
}
// updateHelmReleasesForCRD updates all HelmReleases that match the application labels from CozystackResourceDefinition
func (r *CozystackResourceDefinitionHelmReconciler) updateHelmReleasesForCRD(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) error {
logger := log.FromContext(ctx)
// Use application labels to find HelmReleases
// Labels: apps.cozystack.io/application.kind and apps.cozystack.io/application.group
applicationKind := crd.Spec.Application.Kind
// Validate that applicationKind is non-empty
if applicationKind == "" {
logger.V(4).Info("Skipping HelmRelease update: Application.Kind is empty", "crd", crd.Name)
return nil
}
applicationGroup := "apps.cozystack.io" // All applications use this group
// Build label selector for HelmReleases
// Only reconcile HelmReleases with cozystack.io/ui=true label
labelSelector := client.MatchingLabels{
"apps.cozystack.io/application.kind": applicationKind,
"apps.cozystack.io/application.group": applicationGroup,
"cozystack.io/ui": "true",
}
// List all HelmReleases with matching labels
hrList := &helmv2.HelmReleaseList{}
if err := r.List(ctx, hrList, labelSelector); err != nil {
logger.Error(err, "failed to list HelmReleases", "kind", applicationKind, "group", applicationGroup)
return err
}
logger.V(4).Info("Found HelmReleases to update", "crd", crd.Name, "kind", applicationKind, "count", len(hrList.Items))
// Update each HelmRelease
for i := range hrList.Items {
hr := &hrList.Items[i]
if err := r.updateHelmReleaseChart(ctx, hr, crd); err != nil {
logger.Error(err, "failed to update HelmRelease", "name", hr.Name, "namespace", hr.Namespace)
continue
}
}
return nil
}
// expectedValuesFrom returns the expected valuesFrom configuration for HelmReleases
func expectedValuesFrom() []helmv2.ValuesReference {
return []helmv2.ValuesReference{
{
Kind: "Secret",
Name: "cozystack-values",
},
}
}
// valuesFromEqual compares two ValuesReference slices
func valuesFromEqual(a, b []helmv2.ValuesReference) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i].Kind != b[i].Kind ||
a[i].Name != b[i].Name ||
a[i].ValuesKey != b[i].ValuesKey ||
a[i].TargetPath != b[i].TargetPath ||
a[i].Optional != b[i].Optional {
return false
}
}
return true
}
// updateHelmReleaseChart updates the chart and valuesFrom in HelmRelease based on CozystackResourceDefinition
func (r *CozystackResourceDefinitionHelmReconciler) updateHelmReleaseChart(ctx context.Context, hr *helmv2.HelmRelease, crd *cozyv1alpha1.CozystackResourceDefinition) error {
logger := log.FromContext(ctx)
hrCopy := hr.DeepCopy()
updated := false
// Validate Chart configuration exists
if crd.Spec.Release.Chart.Name == "" {
logger.V(4).Info("Skipping HelmRelease chart update: Chart.Name is empty", "crd", crd.Name)
return nil
}
// Validate SourceRef fields
if crd.Spec.Release.Chart.SourceRef.Kind == "" ||
crd.Spec.Release.Chart.SourceRef.Name == "" ||
crd.Spec.Release.Chart.SourceRef.Namespace == "" {
logger.Error(fmt.Errorf("invalid SourceRef in CRD"), "Skipping HelmRelease chart update: SourceRef fields are incomplete",
"crd", crd.Name,
"kind", crd.Spec.Release.Chart.SourceRef.Kind,
"name", crd.Spec.Release.Chart.SourceRef.Name,
"namespace", crd.Spec.Release.Chart.SourceRef.Namespace)
return nil
}
// Get version and reconcileStrategy from CRD or use defaults
version := ">= 0.0.0-0"
reconcileStrategy := "Revision"
// TODO: Add Version and ReconcileStrategy fields to CozystackResourceDefinitionChart if needed
// Build expected SourceRef
expectedSourceRef := helmv2.CrossNamespaceObjectReference{
Kind: crd.Spec.Release.Chart.SourceRef.Kind,
Name: crd.Spec.Release.Chart.SourceRef.Name,
Namespace: crd.Spec.Release.Chart.SourceRef.Namespace,
}
if hrCopy.Spec.Chart == nil {
// Need to create Chart spec
hrCopy.Spec.Chart = &helmv2.HelmChartTemplate{
Spec: helmv2.HelmChartTemplateSpec{
Chart: crd.Spec.Release.Chart.Name,
Version: version,
ReconcileStrategy: reconcileStrategy,
SourceRef: expectedSourceRef,
},
}
updated = true
} else {
// Update existing Chart spec
if hrCopy.Spec.Chart.Spec.Chart != crd.Spec.Release.Chart.Name ||
hrCopy.Spec.Chart.Spec.SourceRef != expectedSourceRef {
hrCopy.Spec.Chart.Spec.Chart = crd.Spec.Release.Chart.Name
hrCopy.Spec.Chart.Spec.SourceRef = expectedSourceRef
updated = true
}
}
// Check and update valuesFrom configuration
expected := expectedValuesFrom()
if !valuesFromEqual(hrCopy.Spec.ValuesFrom, expected) {
logger.V(4).Info("Updating HelmRelease valuesFrom", "name", hr.Name, "namespace", hr.Namespace)
hrCopy.Spec.ValuesFrom = expected
updated = true
}
if updated {
logger.V(4).Info("Updating HelmRelease chart", "name", hr.Name, "namespace", hr.Namespace)
if err := r.Update(ctx, hrCopy); err != nil {
return fmt.Errorf("failed to update HelmRelease: %w", err)
}
}
return nil
}

View File

@@ -34,9 +34,6 @@ func (m *Manager) ensureCustomColumnsOverride(ctx context.Context, crd *cozyv1al
obj.SetName(name)
href := fmt.Sprintf("/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/%s/{reqsJsonPath[0]['.metadata.name']['-']}", detailsSegment)
if g == "apps.cozystack.io" && kind == "Tenant" && plural == "tenants" {
href = "/openapi-ui/{2}/{reqsJsonPath[0]['.status.namespace']['-']}/api-table/core.cozystack.io/v1alpha1/tenantmodules"
}
desired := map[string]any{
"spec": map[string]any{

View File

@@ -105,8 +105,26 @@ func buildMultilineStringSchema(openAPISchema string) (map[string]any, error) {
"properties": map[string]any{},
}
// Check if there's a spec property
specProp, ok := props["spec"].(map[string]any)
if !ok {
return map[string]any{}, nil
}
specProps, ok := specProp["properties"].(map[string]any)
if !ok {
return map[string]any{}, nil
}
// Create spec.properties structure in schema
schemaProps := schema["properties"].(map[string]any)
specSchema := map[string]any{
"properties": map[string]any{},
}
schemaProps["spec"] = specSchema
// Process spec properties recursively
processSpecProperties(props, schema["properties"].(map[string]any))
processSpecProperties(specProps, specSchema["properties"].(map[string]any))
return schema, nil
}

View File

@@ -9,41 +9,46 @@ func TestBuildMultilineStringSchema(t *testing.T) {
// Test OpenAPI schema with various field types
openAPISchema := `{
"properties": {
"simpleString": {
"type": "string",
"description": "A simple string field"
},
"stringWithEnum": {
"type": "string",
"enum": ["option1", "option2"],
"description": "String with enum should be skipped"
},
"numberField": {
"type": "number",
"description": "Number field should be skipped"
},
"nestedObject": {
"spec": {
"type": "object",
"properties": {
"nestedString": {
"simpleString": {
"type": "string",
"description": "Nested string should get multilineString"
"description": "A simple string field"
},
"nestedStringWithEnum": {
"stringWithEnum": {
"type": "string",
"enum": ["a", "b"],
"description": "Nested string with enum should be skipped"
}
}
},
"arrayOfObjects": {
"type": "array",
"items": {
"type": "object",
"properties": {
"itemString": {
"type": "string",
"description": "String in array item"
"enum": ["option1", "option2"],
"description": "String with enum should be skipped"
},
"numberField": {
"type": "number",
"description": "Number field should be skipped"
},
"nestedObject": {
"type": "object",
"properties": {
"nestedString": {
"type": "string",
"description": "Nested string should get multilineString"
},
"nestedStringWithEnum": {
"type": "string",
"enum": ["a", "b"],
"description": "Nested string with enum should be skipped"
}
}
},
"arrayOfObjects": {
"type": "array",
"items": {
"type": "object",
"properties": {
"itemString": {
"type": "string",
"description": "String in array item"
}
}
}
}
}
@@ -70,33 +75,44 @@ func TestBuildMultilineStringSchema(t *testing.T) {
t.Fatal("schema.properties is not a map")
}
// Check simpleString
simpleString, ok := props["simpleString"].(map[string]any)
// Check spec property exists
spec, ok := props["spec"].(map[string]any)
if !ok {
t.Fatal("simpleString not found in properties")
t.Fatal("spec not found in properties")
}
specProps, ok := spec["properties"].(map[string]any)
if !ok {
t.Fatal("spec.properties is not a map")
}
// Check simpleString
simpleString, ok := specProps["simpleString"].(map[string]any)
if !ok {
t.Fatal("simpleString not found in spec.properties")
}
if simpleString["type"] != "multilineString" {
t.Errorf("simpleString should have type multilineString, got %v", simpleString["type"])
}
// Check stringWithEnum should not be present (or should not have multilineString)
if stringWithEnum, ok := props["stringWithEnum"].(map[string]any); ok {
if stringWithEnum, ok := specProps["stringWithEnum"].(map[string]any); ok {
if stringWithEnum["type"] == "multilineString" {
t.Error("stringWithEnum should not have multilineString type")
}
}
// Check numberField should not be present
if numberField, ok := props["numberField"].(map[string]any); ok {
if numberField, ok := specProps["numberField"].(map[string]any); ok {
if numberField["type"] != nil {
t.Error("numberField should not have any type override")
}
}
// Check nested object
nestedObject, ok := props["nestedObject"].(map[string]any)
nestedObject, ok := specProps["nestedObject"].(map[string]any)
if !ok {
t.Fatal("nestedObject not found in properties")
t.Fatal("nestedObject not found in spec.properties")
}
nestedProps, ok := nestedObject["properties"].(map[string]any)
if !ok {
@@ -113,9 +129,9 @@ func TestBuildMultilineStringSchema(t *testing.T) {
}
// Check array of objects
arrayOfObjects, ok := props["arrayOfObjects"].(map[string]any)
arrayOfObjects, ok := specProps["arrayOfObjects"].(map[string]any)
if !ok {
t.Fatal("arrayOfObjects not found in properties")
t.Fatal("arrayOfObjects not found in spec.properties")
}
items, ok := arrayOfObjects["items"].(map[string]any)
if !ok {

View File

@@ -44,6 +44,9 @@ func (m *Manager) ensureFactory(ctx context.Context, crd *cozyv1alpha1.Cozystack
if flags.Secrets {
tabs = append(tabs, secretsTab(kind))
}
if prefix, ok := vncTabPrefix(kind); ok {
tabs = append(tabs, vncTab(prefix))
}
tabs = append(tabs, yamlTab(plural))
// Use unified factory creation
@@ -150,6 +153,69 @@ func detailsTab(kind, endpoint, schemaJSON string, keysOrder [][]string) map[str
}),
paramsList,
}
if kind == "VirtualPrivateCloud" {
rightColStack = append(rightColStack,
antdFlexVertical("vpc-subnets-block", 4, []any{
antdText("vpc-subnets-label", true, "Subnets", nil),
map[string]any{
"type": "EnrichedTable",
"data": map[string]any{
"id": "vpc-subnets-table",
"baseprefix": "/openapi-ui",
"clusterNamePartOfUrl": "{2}",
"customizationId": "virtualprivatecloud-subnets",
"fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/configmaps",
"fieldSelector": map[string]any{
"metadata.name": "virtualprivatecloud-{6}-subnets",
},
"pathToItems": []any{"items"},
},
},
}),
)
}
if kind == "Info" {
rightColStack = append(rightColStack,
antdFlexVertical("resource-quotas-block", 4, []any{
antdText("resource-quotas-label", true, "Resource Quotas", map[string]any{
"fontSize": float64(20),
"marginBottom": float64(12),
}),
map[string]any{
"type": "EnrichedTable",
"data": map[string]any{
"id": "resource-quotas-table",
"baseprefix": "/openapi-ui",
"clusterNamePartOfUrl": "{2}",
"customizationId": "factory-resource-quotas",
"fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/resourcequotas",
"pathToItems": []any{`items`},
},
},
}),
)
}
if kind == "Tenant" {
rightColStack = append(rightColStack,
antdFlexVertical("resource-quotas-block", 4, []any{
antdText("resource-quotas-label", true, "Resource Quotas", map[string]any{
"fontSize": float64(20),
"marginBottom": float64(12),
}),
map[string]any{
"type": "EnrichedTable",
"data": map[string]any{
"id": "resource-quotas-table",
"baseprefix": "/openapi-ui",
"clusterNamePartOfUrl": "{2}",
"customizationId": "factory-resource-quotas",
"fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/resourcequotas",
"pathToItems": []any{`items`},
},
},
}),
)
}
return map[string]any{
"key": "details",
@@ -331,6 +397,36 @@ func yamlTab(plural string) map[string]any {
}
}
func vncTabPrefix(kind string) (string, bool) {
switch kind {
case "VirtualMachine":
return "virtual-machine", true
case "VMInstance":
return "vm-instance", true
default:
return "", false
}
}
func vncTab(prefix string) map[string]any {
return map[string]any{
"key": "vnc",
"label": "VNC",
"children": []any{
map[string]any{
"type": "VMVNC",
"data": map[string]any{
"id": "vm-vnc",
"cluster": "{2}",
"namespace": "{reqsJsonPath[0]['.metadata.namespace']['-']}",
"substractHeight": float64(400),
"vmName": fmt.Sprintf("%s-{reqsJsonPath[0]['.metadata.name']['-']}", prefix),
},
},
},
}
}
// ---------------- OpenAPI → Right column ----------------
func buildOpenAPIParamsBlocks(schemaJSON string, keysOrder [][]string) []any {

View File

@@ -134,7 +134,7 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
createCustomColumnsOverride("factory-details-v1.services", []any{
createCustomColumnWithSpecificColor("Name", "Service", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-service-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
createStringColumn("ClusterIP", ".spec.clusterIP"),
createStringColumn("LoadbalancerIP", ".spec.loadBalancerIP"),
createStringColumn("LoadbalancerIP", ".status.loadBalancer.ingress[0].ip"),
createTimestampColumn("Created", ".metadata.creationTimestamp"),
}),
@@ -182,6 +182,21 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
createTimestampColumn("Created", ".metadata.creationTimestamp"),
}),
// Virtual private cloud subnets
createCustomColumnsOverride("virtualprivatecloud-subnets", []any{
createFlatMapColumn("Data", ".data"),
createStringColumn("Subnet Parameters", "_flatMapData_Key"),
createStringColumn("Values", "_flatMapData_Value"),
}),
// Factory resource quotas
createCustomColumnsOverride("factory-resource-quotas", []any{
createFlatMapColumn("Data", ".spec.hard"),
createStringColumn("Resource", "_flatMapData_Key"),
createStringColumn("Hard", "_flatMapData_Value"),
createStringColumn("Used", ".status.used['{_flatMapData_Key}']"),
}),
// Factory ingress details rules
createCustomColumnsOverride("factory-kube-ingress-details-rules", []any{
createStringColumn("Host", ".host"),
@@ -1113,7 +1128,7 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory {
"clusterNamePartOfUrl": "{2}",
"customizationId": "factory-node-details-/v1/pods",
"fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/pods",
"labelsSelectorFull": map[string]any{
"labelSelectorFull": map[string]any{
"pathToLabels": ".spec.selector",
"reqIndex": 0,
},

View File

@@ -102,6 +102,22 @@ func antdFlex(id string, gap float64, children []any) map[string]any {
}
}
func antdFlexSpaceBetween(id string, children []any) map[string]any {
if id == "" {
id = generateContainerID("auto", "flex")
}
return map[string]any{
"type": "antdFlex",
"data": map[string]any{
"id": id,
"align": "center",
"justify": "space-between",
},
"children": children,
}
}
func antdFlexVertical(id string, gap float64, children []any) map[string]any {
// Auto-generate ID if not provided
if id == "" {

View File

@@ -237,9 +237,16 @@ func createUnifiedFactory(config UnifiedResourceConfig, tabs []any, urlsToFetch
"lineHeight": "24px",
})
header := antdFlex(generateContainerID("header", "row"), float64(6), []any{
badge,
nameText,
header := antdFlexSpaceBetween(generateContainerID("header", "row"), []any{
antdFlex(generateContainerID("header", "title-text"), float64(6), []any{
badge,
nameText,
}),
antdLink(generateLinkID("header", "edit"),
"Edit",
fmt.Sprintf("/openapi-ui/{2}/{3}/forms/apis/{reqsJsonPath[0]['.apiVersion']['-']}/%s/{reqsJsonPath[0]['.metadata.name']['-']}",
config.Plural),
),
})
// Add marginBottom style to header

View File

@@ -1,140 +0,0 @@
package controller
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"sort"
"time"
helmv2 "github.com/fluxcd/helm-controller/api/v2"
corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
type CozystackConfigReconciler struct {
client.Client
Scheme *runtime.Scheme
}
var configMapNames = []string{"cozystack", "cozystack-branding", "cozystack-scheduling"}
const configMapNamespace = "cozy-system"
const digestAnnotation = "cozystack.io/cozy-config-digest"
const forceReconcileKey = "reconcile.fluxcd.io/forceAt"
const requestedAt = "reconcile.fluxcd.io/requestedAt"
func (r *CozystackConfigReconciler) Reconcile(ctx context.Context, _ ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)
time.Sleep(2 * time.Second)
digest, err := r.computeDigest(ctx)
if err != nil {
log.Error(err, "failed to compute config digest")
return ctrl.Result{}, nil
}
var helmList helmv2.HelmReleaseList
if err := r.List(ctx, &helmList); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to list HelmReleases: %w", err)
}
now := time.Now().Format(time.RFC3339Nano)
updated := 0
for _, hr := range helmList.Items {
isSystemApp := hr.Labels["cozystack.io/system-app"] == "true"
isTenantRoot := hr.Namespace == "tenant-root" && hr.Name == "tenant-root"
if !isSystemApp && !isTenantRoot {
continue
}
patchTarget := hr.DeepCopy()
if hr.Annotations == nil {
hr.Annotations = map[string]string{}
}
if hr.Annotations[digestAnnotation] == digest {
continue
}
patchTarget.Annotations[digestAnnotation] = digest
patchTarget.Annotations[forceReconcileKey] = now
patchTarget.Annotations[requestedAt] = now
patch := client.MergeFrom(hr.DeepCopy())
if err := r.Patch(ctx, patchTarget, patch); err != nil {
log.Error(err, "failed to patch HelmRelease", "name", hr.Name, "namespace", hr.Namespace)
continue
}
updated++
log.Info("patched HelmRelease with new config digest", "name", hr.Name, "namespace", hr.Namespace)
}
log.Info("finished reconciliation", "updatedHelmReleases", updated)
return ctrl.Result{}, nil
}
func (r *CozystackConfigReconciler) computeDigest(ctx context.Context) (string, error) {
hash := sha256.New()
for _, name := range configMapNames {
var cm corev1.ConfigMap
err := r.Get(ctx, client.ObjectKey{Namespace: configMapNamespace, Name: name}, &cm)
if err != nil {
if kerrors.IsNotFound(err) {
continue // ignore missing
}
return "", err
}
// Sort keys for consistent hashing
var keys []string
for k := range cm.Data {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
v := cm.Data[k]
fmt.Fprintf(hash, "%s:%s=%s\n", name, k, v)
}
}
return hex.EncodeToString(hash.Sum(nil)), nil
}
func (r *CozystackConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
WithEventFilter(predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
cm, ok := e.ObjectNew.(*corev1.ConfigMap)
return ok && cm.Namespace == configMapNamespace && contains(configMapNames, cm.Name)
},
CreateFunc: func(e event.CreateEvent) bool {
cm, ok := e.Object.(*corev1.ConfigMap)
return ok && cm.Namespace == configMapNamespace && contains(configMapNames, cm.Name)
},
DeleteFunc: func(e event.DeleteEvent) bool {
cm, ok := e.Object.(*corev1.ConfigMap)
return ok && cm.Namespace == configMapNamespace && contains(configMapNames, cm.Name)
},
}).
For(&corev1.ConfigMap{}).
Complete(r)
}
func contains(slice []string, val string) bool {
for _, s := range slice {
if s == val {
return true
}
}
return false
}

View File

@@ -1,159 +0,0 @@
package controller
import (
"context"
"fmt"
"strings"
"time"
e "errors"
helmv2 "github.com/fluxcd/helm-controller/api/v2"
"gopkg.in/yaml.v2"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)
type TenantHelmReconciler struct {
client.Client
Scheme *runtime.Scheme
}
func (r *TenantHelmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx)
time.Sleep(2 * time.Second)
hr := &helmv2.HelmRelease{}
if err := r.Get(ctx, req.NamespacedName, hr); err != nil {
if errors.IsNotFound(err) {
return ctrl.Result{}, nil
}
logger.Error(err, "unable to fetch HelmRelease")
return ctrl.Result{}, err
}
if !strings.HasPrefix(hr.Name, "tenant-") {
return ctrl.Result{}, nil
}
if len(hr.Status.Conditions) == 0 || hr.Status.Conditions[0].Type != "Ready" {
return ctrl.Result{}, nil
}
if len(hr.Status.History) == 0 {
logger.Info("no history in HelmRelease status", "name", hr.Name)
return ctrl.Result{}, nil
}
if hr.Status.History[0].Status != "deployed" {
return ctrl.Result{}, nil
}
newDigest := hr.Status.History[0].Digest
var hrList helmv2.HelmReleaseList
childNamespace := getChildNamespace(hr.Namespace, hr.Name)
if childNamespace == "tenant-root" && hr.Name == "tenant-root" {
if hr.Spec.Values == nil {
logger.Error(e.New("hr.Spec.Values is nil"), "cant annotate tenant-root ns")
return ctrl.Result{}, nil
}
err := annotateTenantRootNs(*hr.Spec.Values, r.Client)
if err != nil {
logger.Error(err, "cant annotate tenant-root ns")
return ctrl.Result{}, nil
}
logger.Info("namespace 'tenant-root' annotated")
}
if err := r.List(ctx, &hrList, client.InNamespace(childNamespace)); err != nil {
logger.Error(err, "unable to list HelmReleases in namespace", "namespace", hr.Name)
return ctrl.Result{}, err
}
for _, item := range hrList.Items {
if item.Name == hr.Name {
continue
}
oldDigest := item.GetAnnotations()["cozystack.io/tenant-config-digest"]
if oldDigest == newDigest {
continue
}
patchTarget := item.DeepCopy()
if patchTarget.Annotations == nil {
patchTarget.Annotations = map[string]string{}
}
ts := time.Now().Format(time.RFC3339Nano)
patchTarget.Annotations["cozystack.io/tenant-config-digest"] = newDigest
patchTarget.Annotations["reconcile.fluxcd.io/forceAt"] = ts
patchTarget.Annotations["reconcile.fluxcd.io/requestedAt"] = ts
patch := client.MergeFrom(item.DeepCopy())
if err := r.Patch(ctx, patchTarget, patch); err != nil {
logger.Error(err, "failed to patch HelmRelease", "name", patchTarget.Name)
continue
}
logger.Info("patched HelmRelease with new digest", "name", patchTarget.Name, "digest", newDigest, "version", hr.Status.History[0].Version)
}
return ctrl.Result{}, nil
}
func (r *TenantHelmReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&helmv2.HelmRelease{}).
Complete(r)
}
func getChildNamespace(currentNamespace, hrName string) string {
tenantName := strings.TrimPrefix(hrName, "tenant-")
switch {
case currentNamespace == "tenant-root" && hrName == "tenant-root":
// 1) root tenant inside root namespace
return "tenant-root"
case currentNamespace == "tenant-root":
// 2) any other tenant in root namespace
return fmt.Sprintf("tenant-%s", tenantName)
default:
// 3) tenant in a dedicated namespace
return fmt.Sprintf("%s-%s", currentNamespace, tenantName)
}
}
func annotateTenantRootNs(values apiextensionsv1.JSON, c client.Client) error {
var data map[string]interface{}
if err := yaml.Unmarshal(values.Raw, &data); err != nil {
return fmt.Errorf("failed to parse HelmRelease values: %w", err)
}
host, ok := data["host"].(string)
if !ok || host == "" {
return fmt.Errorf("host field not found or not a string")
}
var ns corev1.Namespace
if err := c.Get(context.TODO(), client.ObjectKey{Name: "tenant-root"}, &ns); err != nil {
return fmt.Errorf("failed to get namespace tenant-root: %w", err)
}
if ns.Annotations == nil {
ns.Annotations = map[string]string{}
}
ns.Annotations["namespace.cozystack.io/host"] = host
if err := c.Update(context.TODO(), &ns); err != nil {
return fmt.Errorf("failed to update namespace: %w", err)
}
return nil
}

View File

@@ -467,5 +467,8 @@ func (r *WorkloadMonitorReconciler) getWorkloadMetadata(obj client.Object) map[s
if instanceType, ok := annotations["kubevirt.io/cluster-instancetype-name"]; ok {
labels["workloads.cozystack.io/kubevirt-vmi-instance-type"] = instanceType
}
if instanceProfile, ok := annotations["kubevirt.io/cluster-instanceprofile-name"]; ok {
labels["workloads.cozystack.io/kubevirt-vmi-instance-profile"] = instanceProfile
}
return labels
}

View File

@@ -2,49 +2,72 @@ package lineagecontrollerwebhook
import (
"fmt"
"strings"
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
helmv2 "github.com/fluxcd/helm-controller/api/v2"
)
type chartRef struct {
repo string
chart string
}
type appRef struct {
group string
kind string
}
type runtimeConfig struct {
chartAppMap map[chartRef]*cozyv1alpha1.CozystackResourceDefinition
appCRDMap map[appRef]*cozyv1alpha1.CozystackResourceDefinition
appCRDMap map[appRef]*cozyv1alpha1.CozystackResourceDefinition
}
func (l *LineageControllerWebhook) initConfig() {
l.initOnce.Do(func() {
if l.config.Load() == nil {
l.config.Store(&runtimeConfig{
chartAppMap: make(map[chartRef]*cozyv1alpha1.CozystackResourceDefinition),
appCRDMap: make(map[appRef]*cozyv1alpha1.CozystackResourceDefinition),
appCRDMap: make(map[appRef]*cozyv1alpha1.CozystackResourceDefinition),
})
}
})
}
func (l *LineageControllerWebhook) Map(hr *helmv2.HelmRelease) (string, string, string, error) {
cfg, ok := l.config.Load().(*runtimeConfig)
// getApplicationLabel safely extracts an application label from HelmRelease
func getApplicationLabel(hr *helmv2.HelmRelease, key string) (string, error) {
if hr.Labels == nil {
return "", fmt.Errorf("cannot map helm release %s/%s to dynamic app: labels are nil", hr.Namespace, hr.Name)
}
val, ok := hr.Labels[key]
if !ok {
return "", "", "", fmt.Errorf("failed to load chart-app mapping from config")
return "", fmt.Errorf("cannot map helm release %s/%s to dynamic app: missing %s label", hr.Namespace, hr.Name, key)
}
if hr.Spec.Chart == nil {
return "", "", "", fmt.Errorf("cannot map helm release %s/%s to dynamic app", hr.Namespace, hr.Name)
}
s := hr.Spec.Chart.Spec
val, ok := cfg.chartAppMap[chartRef{s.SourceRef.Name, s.Chart}]
if !ok {
return "", "", "", fmt.Errorf("cannot map helm release %s/%s to dynamic app", hr.Namespace, hr.Name)
}
return "apps.cozystack.io/v1alpha1", val.Spec.Application.Kind, val.Spec.Release.Prefix, nil
return val, nil
}
func (l *LineageControllerWebhook) Map(hr *helmv2.HelmRelease) (string, string, string, error) {
// Extract application metadata from labels
appKind, err := getApplicationLabel(hr, "apps.cozystack.io/application.kind")
if err != nil {
return "", "", "", err
}
appGroup, err := getApplicationLabel(hr, "apps.cozystack.io/application.group")
if err != nil {
return "", "", "", err
}
appName, err := getApplicationLabel(hr, "apps.cozystack.io/application.name")
if err != nil {
return "", "", "", err
}
// Construct API version from group
apiVersion := fmt.Sprintf("%s/v1alpha1", appGroup)
// Extract prefix from HelmRelease name by removing the application name
// HelmRelease name format: <prefix><application-name>
prefix := strings.TrimSuffix(hr.Name, appName)
// Validate the derived prefix
// This ensures correctness when appName appears multiple times in hr.Name
if prefix+appName != hr.Name {
return "", "", "", fmt.Errorf("cannot derive prefix from helm release %s/%s: name does not end with application name %s", hr.Namespace, hr.Name, appName)
}
return apiVersion, appKind, prefix, nil
}

View File

@@ -24,25 +24,15 @@ func (c *LineageControllerWebhook) Reconcile(ctx context.Context, req ctrl.Reque
return ctrl.Result{}, err
}
cfg := &runtimeConfig{
chartAppMap: make(map[chartRef]*cozyv1alpha1.CozystackResourceDefinition),
appCRDMap: make(map[appRef]*cozyv1alpha1.CozystackResourceDefinition),
appCRDMap: make(map[appRef]*cozyv1alpha1.CozystackResourceDefinition),
}
for _, crd := range crds.Items {
chRef := chartRef{
crd.Spec.Release.Chart.SourceRef.Name,
crd.Spec.Release.Chart.Name,
}
appRef := appRef{
"apps.cozystack.io",
crd.Spec.Application.Kind,
}
newRef := crd
if _, exists := cfg.chartAppMap[chRef]; exists {
l.Info("duplicate chart mapping detected; ignoring subsequent entry", "key", chRef)
} else {
cfg.chartAppMap[chRef] = &newRef
}
if _, exists := cfg.appCRDMap[appRef]; exists {
l.Info("duplicate app mapping detected; ignoring subsequent entry", "key", appRef)
} else {

View File

@@ -1,5 +1,4 @@
{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }}
{{- $seaweedfs := index $myNS.metadata.annotations "namespace.cozystack.io/seaweedfs" }}
{{- $seaweedfs := .Values._namespace.seaweedfs }}
apiVersion: objectstorage.k8s.io/v1alpha1
kind: BucketClaim
metadata:

View File

@@ -21,5 +21,8 @@ spec:
force: true
remediation:
retries: -1
valuesFrom:
- kind: Secret
name: cozystack-values
values:
bucketName: {{ .Release.Name }}

View File

@@ -1,5 +1,4 @@
{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }}
{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }}
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }}
{{- if .Values.clickhouseKeeper.enabled }}
apiVersion: "clickhouse-keeper.altinity.com/v1"

View File

@@ -1,5 +1,4 @@
{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }}
{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }}
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }}
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-credentials" .Release.Name) }}
{{- $passwords := dict }}
{{- $users := .Values.users }}

View File

@@ -50,9 +50,8 @@ spec:
postgresUID: 999
postgresGID: 999
enableSuperuserAccess: true
{{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }}
{{- if $configMap }}
{{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }}
{{- if .Values._cluster.scheduling }}
{{- $rawConstraints := get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }}
{{- if $rawConstraints }}
{{- $rawConstraints | fromYaml | toYaml | nindent 2 }}
labelSelector:

View File

@@ -1,5 +1,4 @@
{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" | default (dict "data" (dict)) }}
{{- $clusterDomain := index $cozyConfig.data "cluster-domain" | default "cozy.local" }}
{{- $clusterDomain := index .Values._cluster "cluster-domain" | default "cozy.local" }}
---
apiVersion: apps.foundationdb.org/v1beta2
kind: FoundationDBCluster

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/nginx-cache:0.0.0@sha256:50ac1581e3100bd6c477a71161cb455a341ffaf9e5e2f6086802e4e25271e8af
ghcr.io/cozystack/cozystack/nginx-cache:0.0.0@sha256:cb25e40cb665b8bbeee8cb1ec39da4c9a7452ef3f2f371912bbc0d1b1e2d40a8

View File

@@ -1,3 +1,4 @@
.helmignore
/logos
/Makefile
/hack

View File

@@ -6,9 +6,12 @@ include ../../../scripts/package.mk
generate:
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
yq -o=json -i '.properties.version.enum = (load("files/versions.yaml") | keys)' values.schema.json
../../../hack/update-crd.sh
update:
hack/update-versions.sh
make generate
image: image-ubuntu-container-disk image-kubevirt-cloud-provider image-kubevirt-csi-driver image-cluster-autoscaler
image-ubuntu-container-disk:

View File

@@ -104,7 +104,7 @@ See the reference for components utilized in this service:
| `nodeGroups[name].resources.memory` | Memory (RAM) available. | `quantity` | `""` |
| `nodeGroups[name].gpus` | List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). | `[]object` | `[]` |
| `nodeGroups[name].gpus[i].name` | Name of GPU, such as "nvidia.com/AD102GL_L40S". | `string` | `""` |
| `version` | Kubernetes version (vMAJOR.MINOR). Supported: 1.281.33. | `string` | `v1.33` |
| `version` | Kubernetes major.minor version to deploy | `string` | `v1.33` |
| `host` | External hostname for Kubernetes cluster. Defaults to `<cluster-name>.<tenant-host>` if empty. | `string` | `""` |
@@ -145,31 +145,31 @@ See the reference for components utilized in this service:
### Kubernetes Control Plane Configuration
| Name | Description | Type | Value |
| --------------------------------------------------- | ------------------------------------------------ | ---------- | -------- |
| `controlPlane` | Kubernetes control-plane configuration. | `object` | `{}` |
| `controlPlane.replicas` | Number of control-plane replicas. | `int` | `2` |
| `controlPlane.apiServer` | API Server configuration. | `object` | `{}` |
| `controlPlane.apiServer.resources` | CPU and memory resources for API Server. | `object` | `{}` |
| `controlPlane.apiServer.resources.cpu` | CPU available. | `quantity` | `""` |
| `controlPlane.apiServer.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
| `controlPlane.apiServer.resourcesPreset` | Preset if `resources` omitted. | `string` | `medium` |
| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` |
| `controlPlane.controllerManager.resources` | CPU and memory resources for Controller Manager. | `object` | `{}` |
| `controlPlane.controllerManager.resources.cpu` | CPU available. | `quantity` | `""` |
| `controlPlane.controllerManager.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
| `controlPlane.controllerManager.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` |
| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` |
| `controlPlane.scheduler.resources` | CPU and memory resources for Scheduler. | `object` | `{}` |
| `controlPlane.scheduler.resources.cpu` | CPU available. | `quantity` | `""` |
| `controlPlane.scheduler.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
| `controlPlane.scheduler.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` |
| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` |
| `controlPlane.konnectivity.server` | Konnectivity Server configuration. | `object` | `{}` |
| `controlPlane.konnectivity.server.resources` | CPU and memory resources for Konnectivity. | `object` | `{}` |
| `controlPlane.konnectivity.server.resources.cpu` | CPU available. | `quantity` | `""` |
| `controlPlane.konnectivity.server.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
| `controlPlane.konnectivity.server.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` |
| Name | Description | Type | Value |
| --------------------------------------------------- | ------------------------------------------------ | ---------- | ------- |
| `controlPlane` | Kubernetes control-plane configuration. | `object` | `{}` |
| `controlPlane.replicas` | Number of control-plane replicas. | `int` | `2` |
| `controlPlane.apiServer` | API Server configuration. | `object` | `{}` |
| `controlPlane.apiServer.resources` | CPU and memory resources for API Server. | `object` | `{}` |
| `controlPlane.apiServer.resources.cpu` | CPU available. | `quantity` | `""` |
| `controlPlane.apiServer.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
| `controlPlane.apiServer.resourcesPreset` | Preset if `resources` omitted. | `string` | `large` |
| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` |
| `controlPlane.controllerManager.resources` | CPU and memory resources for Controller Manager. | `object` | `{}` |
| `controlPlane.controllerManager.resources.cpu` | CPU available. | `quantity` | `""` |
| `controlPlane.controllerManager.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
| `controlPlane.controllerManager.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` |
| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` |
| `controlPlane.scheduler.resources` | CPU and memory resources for Scheduler. | `object` | `{}` |
| `controlPlane.scheduler.resources.cpu` | CPU available. | `quantity` | `""` |
| `controlPlane.scheduler.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
| `controlPlane.scheduler.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` |
| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` |
| `controlPlane.konnectivity.server` | Konnectivity Server configuration. | `object` | `{}` |
| `controlPlane.konnectivity.server.resources` | CPU and memory resources for Konnectivity. | `object` | `{}` |
| `controlPlane.konnectivity.server.resources.cpu` | CPU available. | `quantity` | `""` |
| `controlPlane.konnectivity.server.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
| `controlPlane.konnectivity.server.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` |
## Parameter examples and reference

View File

@@ -1,6 +1,6 @@
"v1.28": "v1.28.15"
"v1.29": "v1.29.15"
"v1.30": "v1.30.14"
"v1.31": "v1.31.10"
"v1.32": "v1.32.6"
"v1.33": "v1.33.0"
"v1.32": "v1.32.10"
"v1.31": "v1.31.14"
"v1.30": "v1.30.14"
"v1.29": "v1.29.15"
"v1.28": "v1.28.15"

View File

@@ -0,0 +1,260 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
KUBERNETES_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
VALUES_FILE="${KUBERNETES_DIR}/values.yaml"
VERSIONS_FILE="${KUBERNETES_DIR}/files/versions.yaml"
MAKEFILE="${KUBERNETES_DIR}/Makefile"
KAMAJI_DOCKERFILE="${KUBERNETES_DIR}/../../system/kamaji/images/kamaji/Dockerfile"
# Check if skopeo is installed
if ! command -v skopeo &> /dev/null; then
echo "Error: skopeo is not installed. Please install skopeo and try again." >&2
exit 1
fi
# Check if jq is installed
if ! command -v jq &> /dev/null; then
echo "Error: jq is not installed. Please install jq and try again." >&2
exit 1
fi
# Get kamaji version from Dockerfile
echo "Reading kamaji version from Dockerfile..."
if [ ! -f "$KAMAJI_DOCKERFILE" ]; then
echo "Error: Kamaji Dockerfile not found at $KAMAJI_DOCKERFILE" >&2
exit 1
fi
KAMAJI_VERSION=$(grep "^ARG VERSION=" "$KAMAJI_DOCKERFILE" | cut -d= -f2 | tr -d '"')
if [ -z "$KAMAJI_VERSION" ]; then
echo "Error: Could not extract kamaji version from Dockerfile" >&2
exit 1
fi
echo "Kamaji version: $KAMAJI_VERSION"
# Get Kubernetes version from kamaji repository
echo "Fetching Kubernetes version from kamaji repository..."
KUBERNETES_VERSION_FROM_KAMAJI=$(curl -sSL "https://raw.githubusercontent.com/clastix/kamaji/${KAMAJI_VERSION}/internal/upgrade/kubeadm_version.go" | grep "KubeadmVersion" | sed -E 's/.*KubeadmVersion = "([^"]+)".*/\1/')
if [ -z "$KUBERNETES_VERSION_FROM_KAMAJI" ]; then
echo "Error: Could not fetch Kubernetes version from kamaji repository" >&2
exit 1
fi
echo "Kubernetes version from kamaji: $KUBERNETES_VERSION_FROM_KAMAJI"
# Extract major.minor version (e.g., "1.33" from "v1.33.0")
KUBERNETES_MAJOR_MINOR=$(echo "$KUBERNETES_VERSION_FROM_KAMAJI" | sed -E 's/v([0-9]+)\.([0-9]+)\.[0-9]+/\1.\2/')
KUBERNETES_MAJOR=$(echo "$KUBERNETES_MAJOR_MINOR" | cut -d. -f1)
KUBERNETES_MINOR=$(echo "$KUBERNETES_MAJOR_MINOR" | cut -d. -f2)
echo "Kubernetes major.minor: $KUBERNETES_MAJOR_MINOR"
# Get available image tags
echo "Fetching available image tags from registry..."
AVAILABLE_TAGS=$(skopeo list-tags docker://registry.k8s.io/kube-apiserver | jq -r '.Tags[] | select(test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))' | sort -V)
if [ -z "$AVAILABLE_TAGS" ]; then
echo "Error: Could not fetch available image tags" >&2
exit 1
fi
# Filter out versions higher than KUBERNETES_VERSION_FROM_KAMAJI
echo "Filtering versions above ${KUBERNETES_VERSION_FROM_KAMAJI}..."
FILTERED_TAGS=$(echo "$AVAILABLE_TAGS" | while read tag; do
if [ -n "$tag" ]; then
# Compare tag with KUBERNETES_VERSION_FROM_KAMAJI using version sort
# Include tag if it's less than or equal to KUBERNETES_VERSION_FROM_KAMAJI
if [ "$(printf '%s\n%s\n' "$tag" "$KUBERNETES_VERSION_FROM_KAMAJI" | sort -V | head -1)" = "$tag" ] || [ "$tag" = "$KUBERNETES_VERSION_FROM_KAMAJI" ]; then
echo "$tag"
fi
fi
done)
if [ -z "$FILTERED_TAGS" ]; then
echo "Error: No versions found after filtering" >&2
exit 1
fi
AVAILABLE_TAGS="$FILTERED_TAGS"
echo "Filtered to $(echo "$AVAILABLE_TAGS" | wc -l | tr -d ' ') versions"
# Find the latest patch version for the supported major.minor version
echo "Finding latest patch version for ${KUBERNETES_MAJOR_MINOR}..."
SUPPORTED_PATCH_TAGS=$(echo "$AVAILABLE_TAGS" | grep "^v${KUBERNETES_MAJOR}\\.${KUBERNETES_MINOR}\\.")
if [ -z "$SUPPORTED_PATCH_TAGS" ]; then
echo "Error: Could not find any patch versions for ${KUBERNETES_MAJOR_MINOR}" >&2
exit 1
fi
KUBERNETES_VERSION=$(echo "$SUPPORTED_PATCH_TAGS" | tail -n1)
echo "Using latest patch version: $KUBERNETES_VERSION"
# Build versions map: major.minor -> latest patch version
# First, collect all unique major.minor versions from available tags
echo "Collecting all available major.minor versions..."
ALL_MAJOR_MINOR_VERSIONS=$(echo "$AVAILABLE_TAGS" | sed -E 's/v([0-9]+)\.([0-9]+)\.[0-9]+/v\1.\2/' | sort -V -u)
# Find the position of the supported version in the sorted list
SUPPORTED_MAJOR_MINOR="v${KUBERNETES_MAJOR}.${KUBERNETES_MINOR}"
echo "Looking for supported version: $SUPPORTED_MAJOR_MINOR"
# Get all versions that are <= supported version
# Create a temporary file for filtering
TEMP_VERSIONS=$(mktemp)
echo "$ALL_MAJOR_MINOR_VERSIONS" | while read version; do
# Compare versions using sort -V (version sort)
# If version <= supported, include it
if [ "$(printf '%s\n%s\n' "$version" "$SUPPORTED_MAJOR_MINOR" | sort -V | head -1)" = "$version" ] || [ "$version" = "$SUPPORTED_MAJOR_MINOR" ]; then
echo "$version"
fi
done > "$TEMP_VERSIONS"
# Get the supported version and 5 previous versions (total 6 versions)
# First, find the position of supported version
SUPPORTED_POS=$(grep -n "^${SUPPORTED_MAJOR_MINOR}$" "$TEMP_VERSIONS" | cut -d: -f1)
if [ -z "$SUPPORTED_POS" ]; then
echo "Error: Supported version $SUPPORTED_MAJOR_MINOR not found in available versions" >&2
exit 1
fi
# Calculate start position (5 versions before supported, or from beginning if less than 5 available)
TOTAL_LINES=$(wc -l < "$TEMP_VERSIONS" | tr -d ' ')
START_POS=$((SUPPORTED_POS - 5))
if [ $START_POS -lt 1 ]; then
START_POS=1
fi
# Extract versions from START_POS to SUPPORTED_POS (inclusive)
CANDIDATE_VERSIONS=$(sed -n "${START_POS},${SUPPORTED_POS}p" "$TEMP_VERSIONS")
if [ -z "$CANDIDATE_VERSIONS" ]; then
echo "Error: Could not find supported version $SUPPORTED_MAJOR_MINOR in available versions" >&2
exit 1
fi
declare -A VERSION_MAP
VERSIONS=()
# Process each candidate version
for major_minor_key in $CANDIDATE_VERSIONS; do
# Extract major and minor for matching
major=$(echo "$major_minor_key" | sed -E 's/v([0-9]+)\.([0-9]+)/\1/')
minor=$(echo "$major_minor_key" | sed -E 's/v([0-9]+)\.([0-9]+)/\2/')
# Find all tags that match this major.minor version
matching_tags=$(echo "$AVAILABLE_TAGS" | grep "^v${major}\\.${minor}\\.")
if [ -n "$matching_tags" ]; then
# Get the latest patch version for this major.minor version
latest_tag=$(echo "$matching_tags" | tail -n1)
VERSION_MAP["${major_minor_key}"]="${latest_tag}"
VERSIONS+=("${major_minor_key}")
echo "Found version: ${major_minor_key} -> ${latest_tag}"
fi
done
if [ ${#VERSIONS[@]} -eq 0 ]; then
echo "Error: No matching versions found" >&2
exit 1
fi
# Sort versions in descending order (newest first)
IFS=$'\n' VERSIONS=($(printf '%s\n' "${VERSIONS[@]}" | sort -V -r))
unset IFS
echo "Versions to add: ${VERSIONS[*]}"
# Create/update versions.yaml file
echo "Updating $VERSIONS_FILE..."
{
for ver in "${VERSIONS[@]}"; do
echo "\"${ver}\": \"${VERSION_MAP[$ver]}\""
done
} > "$VERSIONS_FILE"
echo "Successfully updated $VERSIONS_FILE"
# Update values.yaml - enum with major.minor versions only
TEMP_FILE=$(mktemp)
trap "rm -f $TEMP_FILE $TEMP_VERSIONS" EXIT
# Build new version section
NEW_VERSION_SECTION="## @enum {string} Version"
for ver in "${VERSIONS[@]}"; do
NEW_VERSION_SECTION="${NEW_VERSION_SECTION}
## @value $ver"
done
NEW_VERSION_SECTION="${NEW_VERSION_SECTION}
## @param {Version} version - Kubernetes major.minor version to deploy
version: \"${VERSIONS[0]}\""
# Check if version section already exists
if grep -q "^## @enum {string} Version" "$VALUES_FILE"; then
# Version section exists, update it using awk
echo "Updating existing version section in $VALUES_FILE..."
# Use awk to replace the section from "## @enum {string} Version" to "version: " (inclusive)
# Delete the old section and insert the new one
awk -v new_section="$NEW_VERSION_SECTION" '
/^## @enum {string} Version/ {
in_section = 1
print new_section
next
}
in_section && /^version: / {
in_section = 0
next
}
in_section {
next
}
{ print }
' "$VALUES_FILE" > "$TEMP_FILE.tmp"
mv "$TEMP_FILE.tmp" "$VALUES_FILE"
else
# Version section doesn't exist, insert it before Application-specific parameters section
echo "Inserting new version section in $VALUES_FILE..."
# Use awk to insert before "## @section Application-specific parameters"
awk -v new_section="$NEW_VERSION_SECTION" '
/^## @section Application-specific parameters/ {
print new_section
print ""
}
{ print }
' "$VALUES_FILE" > "$TEMP_FILE.tmp"
mv "$TEMP_FILE.tmp" "$VALUES_FILE"
fi
echo "Successfully updated $VALUES_FILE with versions: ${VERSIONS[*]}"
# Update KUBERNETES_VERSION in Makefile
# Extract major.minor from KUBERNETES_VERSION (e.g., "v1.33" from "v1.33.4")
KUBERNETES_MAJOR_MINOR_FOR_MAKEFILE=$(echo "$KUBERNETES_VERSION" | sed -E 's/v([0-9]+)\.([0-9]+)\.[0-9]+/v\1.\2/')
if grep -q "^KUBERNETES_VERSION" "$MAKEFILE"; then
# Update existing KUBERNETES_VERSION line using awk
echo "Updating KUBERNETES_VERSION in $MAKEFILE..."
awk -v new_version="${KUBERNETES_MAJOR_MINOR_FOR_MAKEFILE}" '
/^KUBERNETES_VERSION = / {
print "KUBERNETES_VERSION = " new_version
next
}
{ print }
' "$MAKEFILE" > "$TEMP_FILE.tmp"
mv "$TEMP_FILE.tmp" "$MAKEFILE"
echo "Successfully updated KUBERNETES_VERSION in $MAKEFILE to ${KUBERNETES_MAJOR_MINOR_FOR_MAKEFILE}"
else
echo "Warning: KUBERNETES_VERSION not found in $MAKEFILE" >&2
fi

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/cluster-autoscaler:0.0.0@sha256:2d39989846c3579dd020b9f6c77e6e314cc81aa344eaac0f6d633e723c17196d
ghcr.io/cozystack/cozystack/cluster-autoscaler:0.0.0@sha256:7deeee117e7eec599cb453836ca95eadd131dfc8c875dc457ef29dc1433395e0

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.0.0@sha256:5335c044313b69ee13b30ca4941687e509005e55f4ae25723861edbf2fbd6dd2
ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.0.0@sha256:dee69d15fa8616aa6a1e5a67fc76370e7698a7f58b25e30650eb39c9fb826de8

View File

@@ -1,5 +1,5 @@
diff --git a/pkg/controller/kubevirteps/kubevirteps_controller.go b/pkg/controller/kubevirteps/kubevirteps_controller.go
index 53388eb8e..28644236f 100644
index 53388eb8e..873060251 100644
--- a/pkg/controller/kubevirteps/kubevirteps_controller.go
+++ b/pkg/controller/kubevirteps/kubevirteps_controller.go
@@ -12,7 +12,6 @@ import (
@@ -10,12 +10,17 @@ index 53388eb8e..28644236f 100644
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@@ -669,35 +668,50 @@ func (c *Controller) getDesiredEndpoints(service *v1.Service, tenantSlices []*di
@@ -666,38 +665,62 @@ func (c *Controller) getDesiredEndpoints(service *v1.Service, tenantSlices []*di
// for extracting the nodes it does not matter what type of address we are dealing with
// all nodes with an endpoint for a corresponding slice will be selected.
nodeSet := sets.Set[string]{}
+ hasEndpointsWithoutNodeName := false
for _, slice := range tenantSlices {
for _, endpoint := range slice.Endpoints {
// find all unique nodes that correspond to an endpoint in a tenant slice
+ if endpoint.NodeName == nil {
+ klog.Warningf("Skipping endpoint without NodeName in slice %s/%s", slice.Namespace, slice.Name)
+ hasEndpointsWithoutNodeName = true
+ continue
+ }
nodeSet.Insert(*endpoint.NodeName)
@@ -23,6 +28,13 @@ index 53388eb8e..28644236f 100644
}
- klog.Infof("Desired nodes for service %s in namespace %s: %v", service.Name, service.Namespace, sets.List(nodeSet))
+ // Fallback: if no endpoints with NodeName were found, but there are endpoints without NodeName,
+ // distribute traffic to all VMIs (similar to ExternalTrafficPolicy=Cluster behavior)
+ if nodeSet.Len() == 0 && hasEndpointsWithoutNodeName {
+ klog.Infof("No endpoints with NodeName found for service %s/%s, falling back to all VMIs", service.Namespace, service.Name)
+ return c.getAllVMIEndpoints()
+ }
+
+ klog.Infof("Desired nodes for service %s/%s: %v", service.Namespace, service.Name, sets.List(nodeSet))
for _, node := range sets.List(nodeSet) {
@@ -68,7 +80,7 @@ index 53388eb8e..28644236f 100644
desiredEndpoints = append(desiredEndpoints, &discovery.Endpoint{
Addresses: []string{i.IP},
Conditions: discovery.EndpointConditions{
@@ -705,9 +719,9 @@ func (c *Controller) getDesiredEndpoints(service *v1.Service, tenantSlices []*di
@@ -705,9 +728,9 @@ func (c *Controller) getDesiredEndpoints(service *v1.Service, tenantSlices []*di
Serving: &serving,
Terminating: &terminating,
},
@@ -80,6 +92,71 @@ index 53388eb8e..28644236f 100644
}
}
}
@@ -716,6 +739,64 @@ func (c *Controller) getDesiredEndpoints(service *v1.Service, tenantSlices []*di
return desiredEndpoints
}
+// getAllVMIEndpoints returns endpoints for all VMIs in the infra namespace.
+// This is used as a fallback when tenant endpoints don't have NodeName specified,
+// similar to ExternalTrafficPolicy=Cluster behavior where traffic is distributed to all nodes.
+func (c *Controller) getAllVMIEndpoints() []*discovery.Endpoint {
+ var endpoints []*discovery.Endpoint
+
+ // List all VMIs in the infra namespace
+ vmiList, err := c.infraDynamic.
+ Resource(kubevirtv1.VirtualMachineInstanceGroupVersionKind.GroupVersion().WithResource("virtualmachineinstances")).
+ Namespace(c.infraNamespace).
+ List(context.TODO(), metav1.ListOptions{})
+ if err != nil {
+ klog.Errorf("Failed to list VMIs in namespace %q: %v", c.infraNamespace, err)
+ return endpoints
+ }
+
+ for _, obj := range vmiList.Items {
+ vmi := &kubevirtv1.VirtualMachineInstance{}
+ err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, vmi)
+ if err != nil {
+ klog.Errorf("Failed to convert Unstructured to VirtualMachineInstance: %v", err)
+ continue
+ }
+
+ if vmi.Status.NodeName == "" {
+ klog.Warningf("Skipping VMI %s/%s: NodeName is empty", vmi.Namespace, vmi.Name)
+ continue
+ }
+ nodeNamePtr := &vmi.Status.NodeName
+
+ ready := vmi.Status.Phase == kubevirtv1.Running
+ serving := vmi.Status.Phase == kubevirtv1.Running
+ terminating := vmi.Status.Phase == kubevirtv1.Failed || vmi.Status.Phase == kubevirtv1.Succeeded
+
+ for _, i := range vmi.Status.Interfaces {
+ if i.Name == "default" {
+ if i.IP == "" {
+ klog.Warningf("VMI %s/%s interface %q has no IP, skipping", vmi.Namespace, vmi.Name, i.Name)
+ continue
+ }
+ endpoints = append(endpoints, &discovery.Endpoint{
+ Addresses: []string{i.IP},
+ Conditions: discovery.EndpointConditions{
+ Ready: &ready,
+ Serving: &serving,
+ Terminating: &terminating,
+ },
+ NodeName: nodeNamePtr,
+ })
+ break
+ }
+ }
+ }
+
+ klog.Infof("Fallback: created %d endpoints from all VMIs in namespace %s", len(endpoints), c.infraNamespace)
+ return endpoints
+}
+
func (c *Controller) ensureEndpointSliceLabels(slice *discovery.EndpointSlice, svc *v1.Service) (map[string]string, bool) {
labels := make(map[string]string)
labelsChanged := false
diff --git a/pkg/controller/kubevirteps/kubevirteps_controller_test.go b/pkg/controller/kubevirteps/kubevirteps_controller_test.go
index 1c97035b4..d205d0bed 100644
--- a/pkg/controller/kubevirteps/kubevirteps_controller_test.go

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:c8b08084a86251cdd18e237de89b695bca0e4f7eb1f1f6ddc2b903b4d74ea5ff
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:7ee7702a8b40864a77f2da4a2fda56108719f81a02661c36657c78a551180ec5

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.33@sha256:a09724a7f95283f9130b3da2a89d81c4c6051c6edf0392a81b6fc90f404b76b6
ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.33@sha256:9d4ad080ef729e0f9f1f5919cb85c0c9b6dc772a22d52046b2de9ccba3772715

View File

@@ -10,3 +10,8 @@ data:
enableEPSController: true
selectorless: true
namespace: {{ .Release.Namespace }}
infraLabels:
apps.cozystack.io/application.group: apps.cozystack.io
apps.cozystack.io/application.kind: Kubernetes
apps.cozystack.io/application.name: {{ .Release.Name | trimPrefix "kubernetes-" }}
internal.cozystack.io/tenantresource: "true"

View File

@@ -1,7 +1,6 @@
{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }}
{{- $etcd := index $myNS.metadata.annotations "namespace.cozystack.io/etcd" }}
{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }}
{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }}
{{- $etcd := .Values._namespace.etcd }}
{{- $ingress := .Values._namespace.ingress }}
{{- $host := .Values._namespace.host }}
{{- $kubevirtmachinetemplateNames := list }}
{{- define "kubevirtmachinetemplate" -}}
spec:
@@ -31,9 +30,8 @@ spec:
{{- end }}
cluster.x-k8s.io/deployment-name: {{ $.Release.Name }}-{{ .groupName }}
spec:
{{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }}
{{- if $configMap }}
{{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }}
{{- if .Values._cluster.scheduling }}
{{- $rawConstraints := get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }}
{{- if $rawConstraints }}
{{- $rawConstraints | fromYaml | toYaml | nindent 10 }}
labelSelector:
@@ -182,6 +180,33 @@ metadata:
spec:
template:
spec:
files:
- path: /usr/bin/update-k8s.sh
owner: root:root
permissions: "0755"
content: |
#!/usr/bin/env bash
set -euo pipefail
# Expected to be passed in via preKubeadmCommands
: "${KUBELET_VERSION:?KUBELET_VERSION must be set, e.g. v1.31.0}"
ARCH="$(uname -m)"
case "${ARCH}" in
x86_64) ARCH=amd64 ;;
aarch64) ARCH=arm64 ;;
esac
# Use your internal mirror here for real-world use.
BASE_URL="https://dl.k8s.io/release/${KUBELET_VERSION}/bin/linux/${ARCH}"
echo "Installing kubelet and kubeadm ${KUBELET_VERSION} for ${ARCH}..."
curl -fsSL "${BASE_URL}/kubelet" -o /root/kubelet
curl -fsSL "${BASE_URL}/kubeadm" -o /root/kubeadm
chmod 0755 /root/kubelet
chmod 0755 /root/kubeadm
if /root/kubelet --version ; then mv /root/kubelet /usr/bin/kubelet ; fi
if /root/kubeadm version ; then mv /root/kubeadm /usr/bin/kubeadm ; fi
diskSetup:
filesystems:
- device: /dev/vdb
@@ -205,6 +230,7 @@ spec:
{{- end }}
{{- end }}
preKubeadmCommands:
- KUBELET_VERSION={{ include "kubernetes.versionMap" $}} /usr/bin/update-k8s.sh || true
- sed -i 's|root:x:|root::|' /etc/passwd
- systemctl stop containerd.service
- mkdir -p /ephemeral/kubelet /ephemeral/containerd
@@ -266,6 +292,12 @@ metadata:
{{- end }}
spec:
clusterName: {{ $.Release.Name }}
replicas: 2
strategy:
rollingUpdate:
maxSurge: {{ $group.maxReplicas }}
maxUnavailable: 1
type: RollingUpdate
selector:
matchLabels:
cluster.x-k8s.io/cluster-name: {{ $.Release.Name }}
@@ -300,6 +332,7 @@ metadata:
namespace: {{ $.Release.Namespace }}
spec:
clusterName: {{ $.Release.Name }}
maxUnhealthy: 0
nodeStartupTimeout: 10m
selector:
matchLabels:

View File

@@ -1,76 +0,0 @@
---
apiVersion: batch/v1
kind: Job
metadata:
annotations:
"helm.sh/hook": post-delete
"helm.sh/hook-weight": "10"
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed
name: {{ .Release.Name }}-datavolume-cleanup
spec:
template:
spec:
serviceAccountName: {{ .Release.Name }}-datavolume-cleanup
restartPolicy: Never
tolerations:
- key: CriticalAddonsOnly
operator: Exists
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: "NoSchedule"
containers:
- name: kubectl
image: docker.io/clastix/kubectl:v1.32
command:
- /bin/sh
- -c
- kubectl -n {{ .Release.Namespace }} delete datavolumes
-l "cluster.x-k8s.io/cluster-name={{ .Release.Name }}"
--ignore-not-found=true
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Release.Name }}-datavolume-cleanup
annotations:
helm.sh/hook: post-delete
helm.sh/hook-delete-policy: before-hook-creation,hook-failed,hook-succeeded
helm.sh/hook-weight: "0"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
"helm.sh/hook": post-delete
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed
"helm.sh/hook-weight": "5"
name: {{ .Release.Name }}-datavolume-cleanup
rules:
- apiGroups:
- "cdi.kubevirt.io"
resources:
- datavolumes
verbs:
- get
- list
- delete
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
"helm.sh/hook": post-delete
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed
"helm.sh/hook-weight": "5"
name: {{ .Release.Name }}-datavolume-cleanup
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ .Release.Name }}-datavolume-cleanup
subjects:
- kind: ServiceAccount
name: {{ .Release.Name }}-datavolume-cleanup
namespace: {{ .Release.Namespace }}

View File

@@ -0,0 +1,149 @@
---
apiVersion: batch/v1
kind: Job
metadata:
annotations:
"helm.sh/hook": pre-delete
"helm.sh/hook-weight": "10"
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation
name: {{ .Release.Name }}-pre-cleanup
spec:
template:
metadata:
labels:
policy.cozystack.io/allow-to-apiserver: "true"
spec:
serviceAccountName: {{ .Release.Name }}-cleanup
restartPolicy: Never
tolerations:
- key: CriticalAddonsOnly
operator: Exists
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: "NoSchedule"
containers:
- name: kubectl
image: docker.io/clastix/kubectl:v1.32
command:
- /bin/sh
- -c
- |
set -e
echo "Step 1: Suspending all HelmReleases with label cozystack.io/target-cluster-name={{ .Release.Name }}"
for hr in $(kubectl -n {{ .Release.Namespace }} get helmreleases.helm.toolkit.fluxcd.io -l "cozystack.io/target-cluster-name={{ .Release.Name }}" -o name 2>/dev/null || true); do
if [ -n "$hr" ]; then
echo " Suspending $hr"
kubectl -n {{ .Release.Namespace }} patch "$hr" \
-p '{"spec": {"suspend": true}}' \
--type=merge --field-manager=flux-client-side-apply
fi
done
echo "Step 2: Deleting HelmReleases with label cozystack.io/target-cluster-name={{ .Release.Name }}"
kubectl -n {{ .Release.Namespace }} delete helmreleases.helm.toolkit.fluxcd.io \
-l "cozystack.io/target-cluster-name={{ .Release.Name }}" \
--ignore-not-found=true --wait=true
echo "Step 3: Deleting KamajiControlPlane {{ .Release.Name }}"
kubectl -n {{ .Release.Namespace }} delete kamajicontrolplanes.controlplane.cluster.x-k8s.io {{ .Release.Name }} \
--ignore-not-found=true
echo "Step 4: Deleting TenantControlPlane {{ .Release.Name }}"
kubectl -n {{ .Release.Namespace }} delete tenantcontrolplanes.kamaji.clastix.io {{ .Release.Name }} \
--ignore-not-found=true
echo "Step 5: Cleaning up DataVolumes"
kubectl -n {{ .Release.Namespace }} delete datavolumes \
-l "cluster.x-k8s.io/cluster-name={{ .Release.Name }}" \
--ignore-not-found=true
echo "Step 6: Cleaning up LoadBalancer Services"
kubectl -n {{ .Release.Namespace }} delete services \
-l "cluster.x-k8s.io/cluster-name={{ .Release.Name }}" \
--field-selector spec.type=LoadBalancer \
--ignore-not-found=true
echo "Cleanup completed successfully"
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Release.Name }}-cleanup
annotations:
helm.sh/hook: pre-delete
helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation,hook-failed
helm.sh/hook-weight: "0"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
"helm.sh/hook": pre-delete
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed
"helm.sh/hook-weight": "5"
name: {{ .Release.Name }}-cleanup
rules:
- apiGroups:
- "helm.toolkit.fluxcd.io"
resources:
- helmreleases
verbs:
- get
- list
- watch
- patch
- delete
- apiGroups:
- "controlplane.cluster.x-k8s.io"
resources:
- kamajicontrolplanes
verbs:
- get
- list
- watch
- delete
- apiGroups:
- "kamaji.clastix.io"
resources:
- tenantcontrolplanes
verbs:
- get
- list
- watch
- delete
- apiGroups:
- "cdi.kubevirt.io"
resources:
- datavolumes
verbs:
- get
- list
- watch
- delete
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- delete
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
"helm.sh/hook": pre-delete
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed
"helm.sh/hook-weight": "5"
name: {{ .Release.Name }}-cleanup
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ .Release.Name }}-cleanup
subjects:
- kind: ServiceAccount
name: {{ .Release.Name }}-cleanup
namespace: {{ .Release.Namespace }}

View File

@@ -45,8 +45,6 @@ spec:
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
{{- if .Values.addons.certManager.valuesOverride }}
---
apiVersion: v1

View File

@@ -1,3 +1,13 @@
{{- define "cozystack.defaultCertManagerValues" -}}
{{- if $.Values.addons.gatewayAPI.enabled }}
cert-manager:
config:
apiVersion: controller.config.cert-manager.io/v1alpha1
kind: ControllerConfiguration
enableGatewayAPI: true
{{- end }}
{{- end }}
{{- if .Values.addons.certManager.enabled }}
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
@@ -33,11 +43,8 @@ spec:
force: true
remediation:
retries: -1
{{- with .Values.addons.certManager.valuesOverride }}
values:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- toYaml (deepCopy .Values.addons.certManager.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultCertManagerValues" .))) | nindent 4 }}
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}

View File

@@ -37,6 +37,8 @@ spec:
dependsOn:
- name: {{ .Release.Name }}-vsnap-crd
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}

View File

@@ -1,104 +0,0 @@
---
apiVersion: batch/v1
kind: Job
metadata:
annotations:
"helm.sh/hook": pre-delete
"helm.sh/hook-weight": "10"
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed
name: {{ .Release.Name }}-flux-teardown
spec:
template:
spec:
serviceAccountName: {{ .Release.Name }}-flux-teardown
restartPolicy: Never
tolerations:
- key: CriticalAddonsOnly
operator: Exists
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: "NoSchedule"
containers:
- name: kubectl
image: docker.io/clastix/kubectl:v1.32
command:
- /bin/sh
- -c
- >-
kubectl
--namespace={{ .Release.Namespace }}
patch
helmrelease
{{ .Release.Name }}-cilium
{{ .Release.Name }}-gateway-api-crds
{{ .Release.Name }}-csi
{{ .Release.Name }}-cert-manager
{{ .Release.Name }}-cert-manager-crds
{{ .Release.Name }}-vertical-pod-autoscaler
{{ .Release.Name }}-vertical-pod-autoscaler-crds
{{ .Release.Name }}-ingress-nginx
{{ .Release.Name }}-fluxcd-operator
{{ .Release.Name }}-fluxcd
{{ .Release.Name }}-gpu-operator
{{ .Release.Name }}-velero
{{ .Release.Name }}-coredns
-p '{"spec": {"suspend": true}}'
--type=merge --field-manager=flux-client-side-apply || true
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Release.Name }}-flux-teardown
annotations:
helm.sh/hook: pre-delete
helm.sh/hook-delete-policy: before-hook-creation,hook-failed,hook-succeeded
helm.sh/hook-weight: "0"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
"helm.sh/hook": pre-install,post-install,pre-delete
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed
"helm.sh/hook-weight": "5"
name: {{ .Release.Name }}-flux-teardown
rules:
- apiGroups:
- "helm.toolkit.fluxcd.io"
resources:
- helmreleases
verbs:
- get
- patch
resourceNames:
- {{ .Release.Name }}-cilium
- {{ .Release.Name }}-csi
- {{ .Release.Name }}-cert-manager
- {{ .Release.Name }}-cert-manager-crds
- {{ .Release.Name }}-gateway-api-crds
- {{ .Release.Name }}-vertical-pod-autoscaler
- {{ .Release.Name }}-vertical-pod-autoscaler-crds
- {{ .Release.Name }}-ingress-nginx
- {{ .Release.Name }}-fluxcd-operator
- {{ .Release.Name }}-fluxcd
- {{ .Release.Name }}-gpu-operator
- {{ .Release.Name }}-velero
- {{ .Release.Name }}-coredns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
helm.sh/hook: pre-delete
helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation,hook-failed
helm.sh/hook-weight: "5"
name: {{ .Release.Name }}-flux-teardown
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ .Release.Name }}-flux-teardown
subjects:
- kind: ServiceAccount
name: {{ .Release.Name }}-flux-teardown
namespace: {{ .Release.Namespace }}

View File

@@ -0,0 +1,42 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: {{ .Release.Name }}-metrics-server
labels:
cozystack.io/repository: system
cozystack.io/target-cluster-name: {{ .Release.Name }}
spec:
releaseName: metrics-server
chart:
spec:
chart: cozy-metrics-server
reconcileStrategy: Revision
sourceRef:
kind: HelmRepository
name: cozystack-system
namespace: cozy-system
version: '>= 0.0.0-0'
kubeConfig:
secretRef:
name: {{ .Release.Name }}-admin-kubeconfig
key: super-admin.svc
targetNamespace: cozy-monitoring
storageNamespace: cozy-monitoring
interval: 5m
timeout: 10m
install:
createNamespace: true
remediation:
retries: -1
upgrade:
remediation:
retries: -1
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-prometheus-operator-crds
namespace: {{ .Release.Namespace }}

View File

@@ -1,5 +1,4 @@
{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }}
{{- $targetTenant := index $myNS.metadata.annotations "namespace.cozystack.io/monitoring" }}
{{- $targetTenant := .Values._namespace.monitoring }}
{{- if .Values.addons.monitoringAgents.enabled }}
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
@@ -44,6 +43,10 @@ spec:
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-vertical-pod-autoscaler-crds
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-prometheus-operator-crds
namespace: {{ .Release.Namespace }}
- name: {{ .Release.Name }}-metrics-server
namespace: {{ .Release.Namespace }}
values:
vmagent:
externalLabels:

View File

@@ -0,0 +1,37 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: {{ .Release.Name }}-prometheus-operator-crds
labels:
cozystack.io/repository: system
cozystack.io/target-cluster-name: {{ .Release.Name }}
spec:
releaseName: prometheus-operator-crds
chart:
spec:
chart: cozy-prometheus-operator-crds
reconcileStrategy: Revision
sourceRef:
kind: HelmRepository
name: cozystack-system
namespace: cozy-system
version: '>= 0.0.0-0'
kubeConfig:
secretRef:
name: {{ .Release.Name }}-admin-kubeconfig
key: super-admin.svc
targetNamespace: cozy-victoria-metrics-operator
storageNamespace: cozy-victoria-metrics-operator
interval: 5m
install:
createNamespace: true
remediation:
retries: -1
upgrade:
remediation:
retries: -1
dependsOn:
{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }}
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -37,6 +37,4 @@ spec:
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -1,8 +1,6 @@
{{- define "cozystack.defaultVPAValues" -}}
{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }}
{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }}
{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }}
{{- $targetTenant := index $myNS.metadata.annotations "namespace.cozystack.io/monitoring" }}
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }}
{{- $targetTenant := .Values._namespace.monitoring }}
vpaForVPA: false
vertical-pod-autoscaler:
recommender:

View File

@@ -37,5 +37,3 @@ spec:
- name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- end }}
- name: {{ .Release.Name }}-cilium
namespace: {{ .Release.Namespace }}

View File

@@ -1,5 +1,4 @@
{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }}
{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }}
{{- $ingress := .Values._namespace.ingress }}
{{- if and (eq .Values.addons.ingressNginx.exposeMethod "Proxied") .Values.addons.ingressNginx.hosts }}
---
apiVersion: networking.k8s.io/v1
@@ -15,6 +14,11 @@ metadata:
}
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
labels:
apps.cozystack.io/application.group: apps.cozystack.io
apps.cozystack.io/application.kind: Kubernetes
apps.cozystack.io/application.name: {{ .Release.Name | trimPrefix "kubernetes-" }}
internal.cozystack.io/tenantresource: "true"
spec:
ingressClassName: "{{ $ingress }}"
rules:
@@ -42,6 +46,11 @@ apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-ingress-nginx
labels:
apps.cozystack.io/application.group: apps.cozystack.io
apps.cozystack.io/application.kind: Kubernetes
apps.cozystack.io/application.name: {{ .Release.Name | trimPrefix "kubernetes-" }}
internal.cozystack.io/tenantresource: "true"
spec:
ports:
- appProtocol: http

View File

@@ -150,7 +150,11 @@
"exposeMethod": {
"description": "Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`.",
"type": "string",
"default": "Proxied"
"default": "Proxied",
"enum": [
"Proxied",
"LoadBalancer"
]
},
"hosts": {
"description": "Domains routed to this tenant cluster when `exposeMethod` is `Proxied`.",
@@ -287,7 +291,7 @@
"resourcesPreset": {
"description": "Preset if `resources` omitted.",
"type": "string",
"default": "medium",
"default": "large",
"enum": [
"nano",
"micro",
@@ -492,7 +496,7 @@
}
},
"host": {
"description": "External hostname for Kubernetes cluster. Defaults to `<cluster-name>.<tenant-host>` if empty.",
"description": "External hostname for Kubernetes cluster. Defaults to `\u003ccluster-name\u003e.\u003ctenant-host\u003e` if empty.",
"type": "string",
"default": ""
},
@@ -615,17 +619,17 @@
"default": "replicated"
},
"version": {
"description": "Kubernetes version (vMAJOR.MINOR). Supported: 1.281.33.",
"description": "Kubernetes major.minor version to deploy",
"type": "string",
"default": "v1.33",
"enum": [
"v1.28",
"v1.29",
"v1.30",
"v1.31",
"v1.33",
"v1.32",
"v1.33"
"v1.31",
"v1.30",
"v1.29",
"v1.28"
]
}
}
}
}

View File

@@ -46,9 +46,19 @@ nodeGroups:
resources: {}
gpus: []
## @param {string} version - Kubernetes version (vMAJOR.MINOR). Supported: 1.281.33.
##
## @enum {string} Version
## @value v1.33
## @value v1.32
## @value v1.31
## @value v1.30
## @value v1.29
## @value v1.28
## @param {Version} version - Kubernetes major.minor version to deploy
version: "v1.33"
## @param {string} host - External hostname for Kubernetes cluster. Defaults to `<cluster-name>.<tenant-host>` if empty.
host: ""
@@ -66,9 +76,13 @@ host: ""
## @typedef {struct} GatewayAPIAddon - Gateway API addon.
## @field {bool} enabled - Enable Gateway API.
## @enum {string} IngressNginxExposeMethod - Method to expose the controller
## @value Proxied
## @value LoadBalancer
## @typedef {struct} IngressNginxAddon - Ingress-NGINX controller.
## @field {bool} enabled - Enable the controller (requires nodes labeled `ingress-nginx`).
## @field {string} exposeMethod - Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`.
## @field {IngressNginxExposeMethod} exposeMethod - Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`.
## @field {[]string} hosts - Domains routed to this tenant cluster when `exposeMethod` is `Proxied`.
## @field {object} valuesOverride - Custom Helm values overrides.
@@ -143,7 +157,7 @@ addons:
## @typedef {struct} APIServer - API Server configuration.
## @field {Resources} resources - CPU and memory resources for API Server.
## @field {ResourcesPreset} resourcesPreset="medium" - Preset if `resources` omitted.
## @field {ResourcesPreset} resourcesPreset="large" - Preset if `resources` omitted.
## @typedef {struct} ControllerManager - Controller Manager configuration.
## @field {Resources} resources - CPU and memory resources for Controller Manager.
@@ -172,7 +186,7 @@ controlPlane:
replicas: 2
apiServer:
resources: {}
resourcesPreset: "medium"
resourcesPreset: "large"
controllerManager:
resources: {}
resourcesPreset: "micro"

View File

@@ -0,0 +1,7 @@
apiVersion: v2
name: mongodb
description: Managed MongoDB service
icon: /logos/mongodb.svg
type: application
version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process
appVersion: "8.0"

View File

@@ -0,0 +1,11 @@
include ../../../scripts/package.mk
.PHONY: generate update
generate:
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
../../../hack/update-crd.sh
update:
hack/update-versions.sh
make generate

View File

@@ -0,0 +1,104 @@
# Managed MongoDB Service
MongoDB is a popular document-oriented NoSQL database known for its flexibility and scalability.
The Managed MongoDB Service provides a self-healing replicated cluster managed by the Percona Operator for MongoDB.
## Deployment Details
This managed service is controlled by the Percona Operator for MongoDB, ensuring efficient management and seamless operation.
- Docs: <https://docs.percona.com/percona-operator-for-mongodb/>
- Github: <https://github.com/percona/percona-server-mongodb-operator>
## Deployment Modes
### Replica Set Mode (default)
By default, MongoDB deploys as a replica set with the specified number of replicas.
This mode is suitable for most use cases requiring high availability.
### Sharded Cluster Mode
Enable `sharding: true` for horizontal scaling across multiple shards.
Each shard is a replica set, and mongos routers handle query routing.
## Notes
### External Access
When `external: true` is enabled:
- **Replica Set mode**: Traffic is load-balanced across all replica set members. This works well for read operations, but write operations require connecting to the primary. MongoDB drivers handle primary discovery automatically using the replica set connection string.
- **Sharded mode**: Traffic is routed through mongos routers, which handle both reads and writes correctly.
### Credentials
On first install, the credentials secret will be empty until the Percona operator initializes the cluster.
Run `helm upgrade` after MongoDB is ready to populate the credentials secret with the actual password.
## Parameters
### Common parameters
| Name | Description | Type | Value |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
| `replicas` | Number of MongoDB replicas in replica set. | `int` | `3` |
| `resources` | Explicit CPU and memory configuration for each MongoDB replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
| `resources.cpu` | CPU available to each replica. | `quantity` | `""` |
| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` |
| `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` |
| `storageClass` | StorageClass used to store the data. | `string` | `""` |
| `external` | Enable external access from outside the cluster. | `bool` | `false` |
| `version` | MongoDB major version to deploy. | `string` | `v8` |
### Sharding configuration
| Name | Description | Type | Value |
| ----------------------------------- | ------------------------------------------------------------------ | ---------- | ------- |
| `sharding` | Enable sharded cluster mode. When disabled, deploys a replica set. | `bool` | `false` |
| `shardingConfig` | Configuration for sharded cluster mode. | `object` | `{}` |
| `shardingConfig.configServers` | Number of config server replicas. | `int` | `3` |
| `shardingConfig.configServerSize` | PVC size for config servers. | `quantity` | `3Gi` |
| `shardingConfig.mongos` | Number of mongos router replicas. | `int` | `2` |
| `shardingConfig.shards` | List of shard configurations. | `[]object` | `[...]` |
| `shardingConfig.shards[i].name` | Shard name. | `string` | `""` |
| `shardingConfig.shards[i].replicas` | Number of replicas in this shard. | `int` | `0` |
| `shardingConfig.shards[i].size` | PVC size for this shard. | `quantity` | `""` |
### Users configuration
| Name | Description | Type | Value |
| --------------------------- | --------------------------------------------------- | ------------------- | ----- |
| `users` | Custom MongoDB users configuration map. | `map[string]object` | `{}` |
| `users[name].password` | Password for the user (auto-generated if omitted). | `string` | `""` |
| `users[name].db` | Database to authenticate against. | `string` | `""` |
| `users[name].roles` | List of MongoDB roles with database scope. | `[]object` | `[]` |
| `users[name].roles[i].name` | Role name (e.g., readWrite, dbAdmin, clusterAdmin). | `string` | `""` |
| `users[name].roles[i].db` | Database the role applies to. | `string` | `""` |
### Backup parameters
| Name | Description | Type | Value |
| ------------------------ | ------------------------------------------------------ | -------- | ----------------------------------- |
| `backup` | Backup configuration. | `object` | `{}` |
| `backup.enabled` | Enable regular backups. | `bool` | `false` |
| `backup.schedule` | Cron schedule for automated backups. | `string` | `0 2 * * *` |
| `backup.retentionPolicy` | Retention policy (e.g. "30d"). | `string` | `30d` |
| `backup.destinationPath` | Destination path for backups (e.g. s3://bucket/path/). | `string` | `s3://bucket/path/to/folder/` |
| `backup.endpointURL` | S3 endpoint URL for uploads. | `string` | `http://minio-gateway-service:9000` |
| `backup.s3AccessKey` | Access key for S3 authentication. | `string` | `""` |
| `backup.s3SecretKey` | Secret key for S3 authentication. | `string` | `""` |
### Bootstrap (recovery) parameters
| Name | Description | Type | Value |
| ------------------------ | --------------------------------------------------------- | -------- | ------- |
| `bootstrap` | Bootstrap configuration. | `object` | `{}` |
| `bootstrap.enabled` | Whether to restore from a backup. | `bool` | `false` |
| `bootstrap.recoveryTime` | Timestamp for point-in-time recovery; empty means latest. | `string` | `""` |
| `bootstrap.backupName` | Name of backup to restore from. | `string` | `""` |

View File

@@ -0,0 +1 @@
../../../library/cozy-lib

View File

@@ -0,0 +1,5 @@
# MongoDB version mapping (major version -> Percona image tag)
# Auto-generated by hack/update-versions.sh - do not edit manually
"v8": "8.0.17-6"
"v7": "7.0.28-15"
"v6": "6.0.25-20"

View File

@@ -0,0 +1,125 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MONGODB_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
VALUES_FILE="${MONGODB_DIR}/values.yaml"
VERSIONS_FILE="${MONGODB_DIR}/files/versions.yaml"
# Supported major versions (newest first)
SUPPORTED_MAJOR_VERSIONS="8 7 6"
echo "Supported major versions: $SUPPORTED_MAJOR_VERSIONS"
# Check if skopeo is installed
if ! command -v skopeo &> /dev/null; then
echo "Error: skopeo is not installed. Please install skopeo and try again." >&2
exit 1
fi
# Check if jq is installed
if ! command -v jq &> /dev/null; then
echo "Error: jq is not installed. Please install jq and try again." >&2
exit 1
fi
# Get available image tags from Percona registry
echo "Fetching available image tags from registry..."
AVAILABLE_TAGS=$(skopeo list-tags docker://percona/percona-server-mongodb | jq -r '.Tags[]' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+-[0-9]+$' | sort -V)
if [ -z "$AVAILABLE_TAGS" ]; then
echo "Error: Could not fetch available image tags" >&2
exit 1
fi
# Build versions map: major version -> latest tag
declare -A VERSION_MAP
MAJOR_VERSIONS=()
for major_version in $SUPPORTED_MAJOR_VERSIONS; do
# Find all tags that match this major version
matching_tags=$(echo "$AVAILABLE_TAGS" | grep "^${major_version}\\.")
if [ -n "$matching_tags" ]; then
# Get the latest tag for this major version
latest_tag=$(echo "$matching_tags" | tail -n1)
VERSION_MAP["v${major_version}"]="${latest_tag}"
MAJOR_VERSIONS+=("v${major_version}")
echo "Found version: v${major_version} -> ${latest_tag}"
fi
done
if [ ${#MAJOR_VERSIONS[@]} -eq 0 ]; then
echo "Error: No matching versions found" >&2
exit 1
fi
echo "Major versions to add: ${MAJOR_VERSIONS[*]}"
# Create/update versions.yaml file
echo "Updating $VERSIONS_FILE..."
{
echo "# MongoDB version mapping (major version -> Percona image tag)"
echo "# Auto-generated by hack/update-versions.sh - do not edit manually"
for major_ver in "${MAJOR_VERSIONS[@]}"; do
echo "\"${major_ver}\": \"${VERSION_MAP[$major_ver]}\""
done
} > "$VERSIONS_FILE"
echo "Successfully updated $VERSIONS_FILE"
# Update values.yaml - enum with major versions only
TEMP_FILE=$(mktemp)
trap 'rm -f "$TEMP_FILE" "${TEMP_FILE}.tmp"' EXIT
# Build new version section
NEW_VERSION_SECTION="## @enum {string} Version"
for major_ver in "${MAJOR_VERSIONS[@]}"; do
NEW_VERSION_SECTION="${NEW_VERSION_SECTION}
## @value $major_ver"
done
NEW_VERSION_SECTION="${NEW_VERSION_SECTION}
## @param {Version} version - MongoDB major version to deploy.
version: ${MAJOR_VERSIONS[0]}"
# Check if version section already exists
if grep -q "^## @enum {string} Version" "$VALUES_FILE"; then
# Version section exists, update it using awk
echo "Updating existing version section in $VALUES_FILE..."
# Use awk to replace the section from "## @enum {string} Version" to "version: " (inclusive)
awk -v new_section="$NEW_VERSION_SECTION" '
/^## @enum {string} Version/ {
in_section = 1
print new_section
next
}
in_section && /^version: / {
in_section = 0
next
}
in_section {
next
}
{ print }
' "$VALUES_FILE" > "$TEMP_FILE.tmp"
mv "$TEMP_FILE.tmp" "$VALUES_FILE"
else
# Version section doesn't exist, insert it before Sharding section
echo "Inserting new version section in $VALUES_FILE..."
awk -v new_section="$NEW_VERSION_SECTION" '
/^## @section Sharding configuration/ {
print new_section
print ""
}
{ print }
' "$VALUES_FILE" > "$TEMP_FILE.tmp"
mv "$TEMP_FILE.tmp" "$VALUES_FILE"
fi
echo "Successfully updated $VALUES_FILE with major versions: ${MAJOR_VERSIONS[*]}"

View File

@@ -0,0 +1,13 @@
<svg width="144" height="144" viewBox="0 0 144 144" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="144" height="144" rx="24" fill="url(#paint0_linear_mongodb)"/>
<path d="M72 24C72 24 72 24 72 24C72 24 58 40 58 62C58 84 72 120 72 120C72 120 86 84 86 62C86 40 72 24 72 24Z" fill="#00ED64"/>
<path d="M72 120C72 120 86 84 86 62C86 40 72 24 72 24" stroke="#00684A" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M72 24C72 24 58 40 58 62C58 84 72 120 72 120" stroke="#001E2B" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="69" y="108" width="6" height="16" rx="2" fill="#00684A"/>
<defs>
<linearGradient id="paint0_linear_mongodb" x1="140" y1="130.5" x2="4" y2="9.49999" gradientUnits="userSpaceOnUse">
<stop stop-color="#001E2B"/>
<stop offset="1" stop-color="#023430"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 871 B

Some files were not shown because too many files have changed in this diff Show More