mirror of
https://github.com/cozystack/cozystack.git
synced 2026-03-15 03:18:56 +00:00
Compare commits
85 Commits
feat/cozyc
...
v1.0.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28c9ad9253 | ||
|
|
8c49cf373d | ||
|
|
c0ea9daca5 | ||
|
|
f0134cf6ae | ||
|
|
5e897ef207 | ||
|
|
c10fdc36b8 | ||
|
|
92bf13a9fc | ||
|
|
c055fcbb48 | ||
|
|
81f2546f44 | ||
|
|
3251991014 | ||
|
|
1f0df5fbcd | ||
|
|
d412bd54f2 | ||
|
|
ca0282d3c7 | ||
|
|
4389b60571 | ||
|
|
1eaf32812d | ||
|
|
2658bfabda | ||
|
|
448b4d9c80 | ||
|
|
80a62bd3ee | ||
|
|
ca330b2aca | ||
|
|
352be923ae | ||
|
|
5356a5260a | ||
|
|
64b4be5c78 | ||
|
|
c79545ba04 | ||
|
|
eda0e8ee50 | ||
|
|
f68fc0c921 | ||
|
|
48ce08f584 | ||
|
|
2675ff326a | ||
|
|
51a5073175 | ||
|
|
05d1c02eff | ||
|
|
f06817d4e8 | ||
|
|
0fefaa246f | ||
|
|
7cea11e57b | ||
|
|
31ae2bb826 | ||
|
|
c976378f2f | ||
|
|
edc32eec51 | ||
|
|
e51f05d850 | ||
|
|
dac1a375e2 | ||
|
|
2a956eb0f9 | ||
|
|
6fbe026927 | ||
|
|
4c3a6987c5 | ||
|
|
30c5696541 | ||
|
|
42780f26d2 | ||
|
|
e9e2121153 | ||
|
|
3033e718dd | ||
|
|
aa8a7eae47 | ||
|
|
5a14dc6f54 | ||
|
|
2b59d4fc97 | ||
|
|
ab26d71cc7 | ||
|
|
66a61bd63e | ||
|
|
f887e34206 | ||
|
|
7a107296e5 | ||
|
|
e16d987403 | ||
|
|
c63fcf50b3 | ||
|
|
4417cc35a0 | ||
|
|
78cc4c0955 | ||
|
|
65c6936e95 | ||
|
|
cd3643b8cc | ||
|
|
2024ec3a8b | ||
|
|
f282f19c1b | ||
|
|
7427bbdaa3 | ||
|
|
da89203a32 | ||
|
|
e0dfc8a321 | ||
|
|
9cbd948b08 | ||
|
|
e5f7bc5c53 | ||
|
|
e89ba43c39 | ||
|
|
a20951def3 | ||
|
|
4c73ac54a0 | ||
|
|
cfb5914cdd | ||
|
|
948346ef6d | ||
|
|
da597225d1 | ||
|
|
7871d425dd | ||
|
|
a9adda5e88 | ||
|
|
880b99f3f7 | ||
|
|
c7290f3521 | ||
|
|
2b1b5e8fa9 | ||
|
|
4f2578a32b | ||
|
|
d8f5083c6d | ||
|
|
211e01bd87 | ||
|
|
d8bb3527de | ||
|
|
1fd1da45b9 | ||
|
|
2c82b22c5e | ||
|
|
b61dc7c988 | ||
|
|
473ac87d70 | ||
|
|
9fa311e5ac | ||
|
|
7994976052 |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -1 +1 @@
|
||||
* @kvaps @lllamnyp @lexfrei @androndo @IvanHunters
|
||||
* @kvaps @lllamnyp @lexfrei @androndo @IvanHunters @sircthulhu
|
||||
|
||||
15
docs/changelogs/v0.40.5.md
Normal file
15
docs/changelogs/v0.40.5.md
Normal file
@@ -0,0 +1,15 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.40.5
|
||||
-->
|
||||
|
||||
## Improvements
|
||||
|
||||
* **[dashboard] Improve dashboard session params**: Improved session parameter handling in the dashboard for better user experience and more reliable session management ([**@lllamnyp**](https://github.com/lllamnyp) in #1913, #1919).
|
||||
|
||||
## Dependencies
|
||||
|
||||
* **Update cozyhr to v1.6.1**: Updated cozyhr to v1.6.1, which fixes a critical bug causing helm-controller v0.37.0+ to unexpectedly uninstall HelmReleases after cozyhr apply by correcting history snapshot fields for helm-controller compatibility ([**@kvaps**](https://github.com/kvaps) in cozystack/cozyhr#10).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.40.4...v0.40.5](https://github.com/cozystack/cozystack/compare/v0.40.4...v0.40.5)
|
||||
11
docs/changelogs/v0.40.6.md
Normal file
11
docs/changelogs/v0.40.6.md
Normal file
@@ -0,0 +1,11 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.40.6
|
||||
-->
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[kubernetes] Fix manifests for kubernetes deployment**: Fixed incorrect manifests that prevented proper Kubernetes deployment, restoring correct application behavior ([**@IvanHunters**](https://github.com/IvanHunters) in #1943, #1944).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.40.5...v0.40.6](https://github.com/cozystack/cozystack/compare/v0.40.5...v0.40.6)
|
||||
11
docs/changelogs/v0.40.7.md
Normal file
11
docs/changelogs/v0.40.7.md
Normal file
@@ -0,0 +1,11 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.40.7
|
||||
-->
|
||||
|
||||
## Security
|
||||
|
||||
* **[dashboard] Verify JWT token**: Added JWT token verification to the dashboard, ensuring that authentication tokens are properly validated before granting access. This prevents unauthorized access through forged or expired tokens ([**@lllamnyp**](https://github.com/lllamnyp) in #1980, #1984).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.40.6...v0.40.7](https://github.com/cozystack/cozystack/compare/v0.40.6...v0.40.7)
|
||||
11
docs/changelogs/v0.41.4.md
Normal file
11
docs/changelogs/v0.41.4.md
Normal file
@@ -0,0 +1,11 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.4
|
||||
-->
|
||||
|
||||
## Dependencies
|
||||
|
||||
* **Update cozyhr to v1.6.1**: Updated cozyhr to v1.6.1, which fixes a critical bug causing helm-controller v0.37.0+ to unexpectedly uninstall HelmReleases after cozyhr apply by correcting history snapshot fields for helm-controller compatibility ([**@kvaps**](https://github.com/kvaps) in cozystack/cozyhr#10).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.3...v0.41.4](https://github.com/cozystack/cozystack/compare/v0.41.3...v0.41.4)
|
||||
21
docs/changelogs/v0.41.5.md
Normal file
21
docs/changelogs/v0.41.5.md
Normal file
@@ -0,0 +1,21 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.5
|
||||
-->
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
* **[dashboard] Add "Edit" button to all resources**: Added an "Edit" button across all resource views in the dashboard, allowing users to modify resource configurations directly from the UI ([**@sircthulhu**](https://github.com/sircthulhu) in #1928, #1931).
|
||||
|
||||
* **[dashboard] Add resource quota usage to tenant details page**: Added resource quota usage display to the tenant details page, giving administrators visibility into how much of allocated resources each tenant is consuming ([**@sircthulhu**](https://github.com/sircthulhu) in #1929, #1932).
|
||||
|
||||
* **[branding] Separate values for keycloak**: Separated Keycloak branding values into dedicated configuration, allowing more granular customization of Keycloak appearance without affecting other branding settings ([**@nbykov0**](https://github.com/nbykov0) in #1946).
|
||||
|
||||
* **Add instance profile label to workload monitor**: Added instance profile metadata labels to the workload monitor, enabling better resource tracking and monitoring by instance profile type ([**@matthieu-robin**](https://github.com/matthieu-robin) in #1954, #1957).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[kubernetes] Fix manifests for kubernetes deployment**: Fixed incorrect manifests that prevented proper Kubernetes deployment, restoring correct application behavior ([**@IvanHunters**](https://github.com/IvanHunters) in #1943, #1945).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.4...v0.41.5](https://github.com/cozystack/cozystack/compare/v0.41.4...v0.41.5)
|
||||
17
docs/changelogs/v0.41.6.md
Normal file
17
docs/changelogs/v0.41.6.md
Normal file
@@ -0,0 +1,17 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.6
|
||||
-->
|
||||
|
||||
## Improvements
|
||||
|
||||
* **[vm] Allow changing field external after creation**: Users can now modify the external network field on virtual machines after initial creation, providing more flexibility in VM networking configuration without requiring recreation ([**@sircthulhu**](https://github.com/sircthulhu) in #1956, #1962).
|
||||
|
||||
* **[branding] Separate values for keycloak**: Separated Keycloak branding values into dedicated configuration for more granular customization of Keycloak appearance ([**@nbykov0**](https://github.com/nbykov0) in #1947, #1963).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[kubernetes] Fix coredns serviceaccount to match kubernetes bootstrap RBAC**: Configured the CoreDNS chart to create a `kube-dns` ServiceAccount matching the Kubernetes bootstrap ClusterRoleBinding, fixing RBAC errors (`Failed to watch`) when CoreDNS pods restart ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1958, #1978).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.5...v0.41.6](https://github.com/cozystack/cozystack/compare/v0.41.5...v0.41.6)
|
||||
15
docs/changelogs/v0.41.7.md
Normal file
15
docs/changelogs/v0.41.7.md
Normal file
@@ -0,0 +1,15 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.7
|
||||
-->
|
||||
|
||||
## Security
|
||||
|
||||
* **[dashboard] Verify JWT token**: Added JWT token verification to the dashboard, ensuring that authentication tokens are properly validated before granting access. This prevents unauthorized access through forged or expired tokens ([**@lllamnyp**](https://github.com/lllamnyp) in #1980, #1983).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[postgres-operator] Correct PromQL syntax in CNPGClusterOffline alert**: Fixed incorrect PromQL syntax in the `CNPGClusterOffline` alert rule for CloudNativePG, ensuring the alert fires correctly when all instances of a PostgreSQL cluster are offline ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1981, #1989).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.6...v0.41.7](https://github.com/cozystack/cozystack/compare/v0.41.6...v0.41.7)
|
||||
17
docs/changelogs/v0.41.8.md
Normal file
17
docs/changelogs/v0.41.8.md
Normal file
@@ -0,0 +1,17 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.8
|
||||
-->
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
* **[kubernetes] Auto-enable Gateway API support in cert-manager**: cert-manager now automatically enables `enableGatewayAPI` when the Gateway API addon is active in the Kubernetes application. Users no longer need to manually configure this setting, and the option can still be overridden via `valuesOverride` ([**@kvaps**](https://github.com/kvaps) in #1997, #2012).
|
||||
|
||||
* **[vm] Allow switching between instancetype and custom resources**: Users can now switch virtual machines between instancetype-based and custom resource configurations after creation. The upgrade hook atomically patches VM resources, providing more flexibility in adjusting VM sizing without recreation ([**@sircthulhu**](https://github.com/sircthulhu) in #2008, #2013).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[dashboard] Add startupProbe to prevent container restarts on slow hardware**: Added `startupProbe` to both `bff` and `web` containers in the dashboard deployment. On slow hardware, kubelet was killing containers because the `livenessProbe` only allowed ~33 seconds for startup. The `startupProbe` gives containers up to 60 seconds to start before `livenessProbe` kicks in ([**@kvaps**](https://github.com/kvaps) in #1996, #2014).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.7...v0.41.8](https://github.com/cozystack/cozystack/compare/v0.41.7...v0.41.8)
|
||||
15
docs/changelogs/v0.41.9.md
Normal file
15
docs/changelogs/v0.41.9.md
Normal file
@@ -0,0 +1,15 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.9
|
||||
-->
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[cozystack-basics] Deny resourcequotas deletion for tenant admin**: Prevented tenant administrators from deleting resource quotas, ensuring that resource limits set by platform administrators cannot be bypassed by tenant-level users ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2076).
|
||||
|
||||
## Dependencies
|
||||
|
||||
* **Update Kube-OVN to v1.15.3**: Updated Kube-OVN CNI to v1.15.3 with latest bug fixes and improvements ([**@kvaps**](https://github.com/kvaps)).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.8...v0.41.9](https://github.com/cozystack/cozystack/compare/v0.41.8...v0.41.9)
|
||||
65
docs/changelogs/v1.0.0-rc.1.md
Normal file
65
docs/changelogs/v1.0.0-rc.1.md
Normal file
@@ -0,0 +1,65 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.0.0-rc.1
|
||||
-->
|
||||
|
||||
> **⚠️ Release Candidate Warning**: This is a release candidate intended for final validation before the stable v1.0.0 release. Breaking changes are not expected at this stage, but please test thoroughly before deploying to production.
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
* **[harbor] Add managed Harbor container registry**: Added Harbor v2.14.2 as a managed tenant-level container registry service. The application uses CloudNativePG for PostgreSQL, the Redis operator for caching, and S3 via COSI BucketClaim (from SeaweedFS) for registry image storage. Auto-generated admin credentials are persisted across upgrades, TLS is handled by cert-manager, and Trivy vulnerability scanner is included. Users can now deploy a fully managed, production-ready OCI container registry within their tenant ([**@lexfrei**](https://github.com/lexfrei) in #2058).
|
||||
|
||||
* **[kubernetes] Update supported Kubernetes versions to v1.30–v1.35**: Updated the tenant Kubernetes version matrix to v1.30, v1.31, v1.32, v1.33, v1.34, and v1.35 (now the default). EOL versions v1.28 and v1.29 are removed. Kamaji is updated to edge-26.2.4 with full Kubernetes 1.35 support, and the CAPI Kamaji provider is updated to v0.16.0. A compatibility patch ensures kubelets older than v1.35 are not broken by Kamaji injecting 1.35-specific kubelet fields ([**@lexfrei**](https://github.com/lexfrei) in #2073).
|
||||
|
||||
* **[platform] Make cluster issuer name and ACME solver configurable**: Added `publishing.certificates.solver` (`http01` or `dns01`) and `publishing.certificates.issuerName` (default: `letsencrypt-prod`) parameters to the platform chart. This allows operators to point all ingress TLS annotations at any ClusterIssuer — custom ACME, self-signed, or internal CA — without modifying individual package templates. See the Breaking Changes section for the rename from the previous `issuerType` field ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2077).
|
||||
|
||||
* **[dashboard] VMInstance dropdowns for disks and instanceType**: The VM instance creation form now renders API-backed dropdowns for the `instanceType` field (populated from `VirtualMachineClusterInstancetype` cluster resources) and for disk `name` fields (populated from `VMDisk` resources in the same namespace). Default values are read from the ApplicationDefinition's OpenAPI schema. This eliminates manual lookups and reduces misconfiguration when attaching disks or selecting VM instance types ([**@sircthulhu**](https://github.com/sircthulhu) in #2071).
|
||||
|
||||
* **[installer] Remove CRDs from Helm chart, delegate lifecycle to operator**: The `cozy-installer` Helm chart no longer ships CRDs in its `crds/` directory. CRD lifecycle is now fully managed by the Cozystack operator via the `--install-crds` flag, which applies embedded CRD manifests on every startup using server-side apply. The platform PackageSource is also created by the operator instead of a Helm template. This ensures CRDs and the PackageSource are always up to date after each operator restart, eliminating stale CRDs from Helm's install-only behavior ([**@lexfrei**](https://github.com/lexfrei) in #2074).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[kubevirt] Update KubeVirt to v1.6.4 and CDI to v1.64.0, fix VM pod initialization**: Updated KubeVirt operator to v1.6.4 and CDI operator to v1.64.0, including live migration of existing VMs during the upgrade. Additionally, disabled serial console logging globally via the KubeVirt CR to prevent a known v1.6.x issue ([upstream #15989](https://github.com/kubevirt/kubevirt/issues/15989)) where the `guest-console-log` init container blocked virt-launcher pods from starting, causing all VMs to get stuck in `PodInitializing` state ([**@nbykov0**](https://github.com/nbykov0) in #1833; [**@kvaps**](https://github.com/kvaps) in 7dfb819).
|
||||
|
||||
* **[linstor] Fix DRBD+LUKS+STORAGE resource creation failure**: All newly created encrypted volumes were failing because the DRBD `.res` file was never written due to a missing `setExists(true)` call in the `LuksLayer`. Applied the upstream `skip-adjust-when-device-inaccessible` patch ([LINBIT/linstor-server#477](https://github.com/LINBIT/linstor-server/pull/477)) which fixes the root cause and also prevents unnecessary lsblk calls when devices are not yet physically present ([**@kvaps**](https://github.com/kvaps) in #2072).
|
||||
|
||||
* **[system] Fix monitoring-agents FQDN resolution for tenant workload clusters**: Monitoring agents (`vmagent`, `fluent-bit`) in tenant workload clusters were failing to deliver metrics and logs because service addresses used short DNS names without the cluster domain suffix. Fixed by appending the configured cluster domain from `_cluster.cluster-domain` (with fallback to `cluster.local`) to all vmagent remoteWrite URLs and fluent-bit output hosts ([**@IvanHunters**](https://github.com/IvanHunters) in #2075).
|
||||
|
||||
* **[cozystack-basics] Preserve existing HelmRelease values during reconciliations**: Fixed a data-loss bug where changes made to the `tenant-root` HelmRelease were silently dropped on the next forced or upgrade reconciliation of the `cozystack-basics` HelmRelease. The reconciler now merges new configuration with existing values instead of overwriting them ([**@sircthulhu**](https://github.com/sircthulhu) in #2068).
|
||||
|
||||
* **[cozystack-basics] Deny resourcequotas deletion for tenant admin**: Fixed the `cozy:tenant:admin:base` ClusterRole to explicitly deny deletion of `ResourceQuota` objects for tenant admins and superadmins, preventing accidental removal of tenant resource limits ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2076).
|
||||
|
||||
## Breaking Changes & Upgrade Notes
|
||||
|
||||
* **[platform] Certificate issuer configuration parameters renamed**: The `publishing.certificates.issuerType` field is renamed to `publishing.certificates.solver`, and the value `cloudflare` is renamed to `dns01` to align with standard ACME terminology. A new `publishing.certificates.issuerName` field (default: `letsencrypt-prod`) is introduced to allow pointing all ingresses at a custom ClusterIssuer. Migration 32 is included and automatically converts existing configurations during upgrade — no manual action is required ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2077).
|
||||
|
||||
## Documentation
|
||||
|
||||
* **[website] Migrate ConfigMap references to Platform Package in v1 documentation**: Updated the entire v1 documentation tree to replace legacy ConfigMap-based configuration references with the new Platform Package API, ensuring guides are consistent with the v1 configuration model ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#426).
|
||||
|
||||
* **[website] Add generic Kubernetes deployment guide for v1**: Added a new installation guide covering Cozystack deployment on any generic Kubernetes cluster, expanding the set of supported deployment targets beyond provider-specific guides ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#408).
|
||||
|
||||
* **[website] Refactor resource planning documentation**: Improved the resource planning guide with a clearer structure and more comprehensive coverage of planning considerations for Cozystack deployments ([**@IvanStukov**](https://github.com/IvanStukov) in cozystack/website#423).
|
||||
|
||||
* **[website] Add ServiceAccount API access documentation and update FAQ**: Added a new article documenting ServiceAccount API access token configuration and updated the FAQ to include related troubleshooting guidance ([**@IvanStukov**](https://github.com/IvanStukov) in cozystack/website#421).
|
||||
|
||||
* **[website] Update networking-mesh allowed-location-ips example**: Replaced provider-specific CLI usage with standard `kubectl` commands in the multi-location networking guide's `allowed-location-ips` example, making the documentation more universally applicable ([**@kvaps**](https://github.com/kvaps) in cozystack/website#425).
|
||||
|
||||
## Contributors
|
||||
|
||||
We'd like to thank all contributors who made this release possible:
|
||||
|
||||
* [**@IvanHunters**](https://github.com/IvanHunters)
|
||||
* [**@IvanStukov**](https://github.com/IvanStukov)
|
||||
* [**@kvaps**](https://github.com/kvaps)
|
||||
* [**@lexfrei**](https://github.com/lexfrei)
|
||||
* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil)
|
||||
* [**@nbykov0**](https://github.com/nbykov0)
|
||||
* [**@sircthulhu**](https://github.com/sircthulhu)
|
||||
|
||||
### New Contributors
|
||||
|
||||
We're excited to welcome our first-time contributors:
|
||||
|
||||
* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) - First contribution!
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.0-beta.6...v1.0.0-rc.1
|
||||
57
docs/changelogs/v1.0.0-rc.2.md
Normal file
57
docs/changelogs/v1.0.0-rc.2.md
Normal file
@@ -0,0 +1,57 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.0.0-rc.2
|
||||
-->
|
||||
|
||||
> **⚠️ Release Candidate Warning**: This is a release candidate intended for final validation before the stable v1.0.0 release. Breaking changes are not expected at this stage, but please test thoroughly before deploying to production.
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
* **[keycloak] Allow custom Ingress hostname via values**: Added an `ingress.host` field to the cozy-keycloak chart values, allowing operators to override the default `keycloak.<root-host>` Ingress hostname. The custom hostname is applied to both the Ingress resource and the `KC_HOSTNAME` environment variable in the StatefulSet. When left empty, the original behavior is preserved (fully backward compatible) ([**@sircthulhu**](https://github.com/sircthulhu) in #2101).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[platform] Fix upgrade issues in migrations, etcd timeout, and migration script**: Fixed multiple upgrade failures discovered during v0.41.1 → v1.0 upgrade testing. Migration 26 now uses the `cozystack.io/ui=true` label (always present on v0.41.1) instead of the new label that depends on migration 22 having run, and adds robust Helm secret deletion with fallback and verification. Migrations 28 and 29 wrap `grep` calls to prevent `pipefail` exits and fix the reconcile annotation to use RFC3339 format. Migration 27 now skips missing CRDs and adds a name-pattern fallback for Helm secret deletion. The etcd HelmRelease timeout is increased from 10m to 30m to accommodate TLS cert rotation hooks. The `migrate-to-version-1.0.sh` script gains the missing `bundle-disable`, `bundle-enable`, `expose-ingress`, and `expose-services` field mappings ([**@kvaps**](https://github.com/kvaps) in #2096).
|
||||
|
||||
* **[platform] Fix orphaned -rd HelmReleases after application renames**: After the `ferretdb→mongodb`, `mysql→mariadb`, and `virtual-machine→vm-disk+vm-instance` renames, the system-level `-rd` HelmReleases in `cozy-system` (`ferretdb-rd`, `mysql-rd`, `virtual-machine-rd`) were left orphaned, referencing ExternalArtifacts that no longer exist and causing persistent reconciliation failures. Migrations 28 and 29 are updated to remove these resources, and migration 33 is added as a safety net for clusters that already passed those migrations ([**@kvaps**](https://github.com/kvaps) in #2102).
|
||||
|
||||
* **[monitoring-agents] Fix FQDN resolution regression in tenant workload clusters**: The fix introduced in #2075 used `_cluster.cluster-domain` references in `values.yaml`, but `_cluster` values are not accessible from Helm subchart contexts — meaning fluent-bit received empty hostnames and failed to forward logs. This PR replaces the `_cluster` references with a new `global.clusterDomain` variable (empty by default for management clusters, set to the cluster domain for tenant clusters), which is correctly shared with all subcharts ([**@kvaps**](https://github.com/kvaps) in #2086).
|
||||
|
||||
* **[dashboard] Fix legacy templating and cluster identifier in sidebar links**: Standardized the cluster identifier used across dashboard menu links, administration links, and API request paths, resolving incorrect or broken link targets for the Backups and External IPs sidebar sections ([**@androndo**](https://github.com/androndo) in #2093).
|
||||
|
||||
* **[dashboard] Fix backupjobs creation form and sidebar backup category identifier**: Fixed the backup job creation form configuration, adding the required Name, Namespace, Plan Name, Application, and Backup Class fields. Fixed the sidebar backup category identifier that was causing incorrect navigation ([**@androndo**](https://github.com/androndo) in #2103).
|
||||
|
||||
## Documentation
|
||||
|
||||
* **[website] Add Helm chart development principles guide**: Added a new developer guide section documenting Cozystack's four core Helm chart principles: easy upstream updates, local-first artifacts, local dev/test workflow, and no external dependencies ([**@kvaps**](https://github.com/kvaps) in cozystack/website#418).
|
||||
|
||||
* **[website] Add network architecture overview**: Added comprehensive network architecture documentation covering the multi-layered networking stack — MetalLB (L2/BGP), Cilium eBPF (kube-proxy replacement), Kube-OVN (centralized IPAM), and tenant isolation with identity-based eBPF policies — with Mermaid diagrams for all major traffic flows ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#422).
|
||||
|
||||
* **[website] Update documentation to use jsonpatch for service exposure**: Improved `kubectl patch` commands throughout installation and configuration guides to use JSON Patch `add` operations for extending arrays instead of replacing them wholesale, making the documented commands safer and more precise ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#427).
|
||||
|
||||
* **[website] Update certificates section in Platform Package documentation**: Updated the certificate configuration documentation to reflect the new `solver` and `issuerName` fields introduced in v1.0.0-rc.1, replacing the legacy `issuerType` references ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#429).
|
||||
|
||||
* **[website] Add tenant Kubernetes cluster log querying guide**: Added documentation for querying logs from tenant Kubernetes clusters in Grafana using VictoriaLogs labels (`tenant`, `kubernetes_namespace_name`, `kubernetes_pod_name`), including the `monitoringAgents` addon prerequisite and step-by-step filtering examples ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#430).
|
||||
|
||||
* **[website] Replace non-idempotent commands with idempotent alternatives**: Updated `helm install` to `helm upgrade --install`, `kubectl create -f` to `kubectl apply -f`, and `kubectl create ns` to the dry-run+apply pattern across all installation and deployment guides so commands can be safely re-run ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#431).
|
||||
|
||||
* **[website] Fix broken documentation links with `.md` suffix**: Fixed incorrect internal links with `.md` suffix across virtualization guides for both v0 and v1 documentation, standardizing link text to "Developer Guide" ([**@cheese**](https://github.com/cheese) in cozystack/website#432).
|
||||
|
||||
## Contributors
|
||||
|
||||
We'd like to thank all contributors who made this release possible:
|
||||
|
||||
* [**@androndo**](https://github.com/androndo)
|
||||
* [**@cheese**](https://github.com/cheese)
|
||||
* [**@IvanHunters**](https://github.com/IvanHunters)
|
||||
* [**@kvaps**](https://github.com/kvaps)
|
||||
* [**@lexfrei**](https://github.com/lexfrei)
|
||||
* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil)
|
||||
* [**@sircthulhu**](https://github.com/sircthulhu)
|
||||
|
||||
### New Contributors
|
||||
|
||||
We're excited to welcome our first-time contributors:
|
||||
|
||||
* [**@cheese**](https://github.com/cheese) - First contribution!
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.0-rc.1...v1.0.0-rc.2
|
||||
@@ -32,6 +32,54 @@ if ! kubectl get namespace "$NAMESPACE" &> /dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 0: Annotate critical resources to prevent Helm from deleting them
|
||||
echo "Step 0: Protect critical resources from Helm deletion"
|
||||
echo ""
|
||||
echo "The following resources will be annotated with helm.sh/resource-policy=keep"
|
||||
echo "to prevent Helm from deleting them when the installer release is removed:"
|
||||
echo " - Namespace: $NAMESPACE"
|
||||
echo " - ConfigMap: $NAMESPACE/cozystack-version"
|
||||
echo ""
|
||||
read -p "Do you want to annotate these resources? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Annotating namespace $NAMESPACE..."
|
||||
kubectl annotate namespace "$NAMESPACE" helm.sh/resource-policy=keep --overwrite
|
||||
echo "Annotating ConfigMap cozystack-version..."
|
||||
kubectl annotate configmap -n "$NAMESPACE" cozystack-version helm.sh/resource-policy=keep --overwrite 2>/dev/null || echo " ConfigMap cozystack-version not found, skipping."
|
||||
echo ""
|
||||
echo "Resources annotated successfully."
|
||||
else
|
||||
echo "WARNING: Skipping annotation. If you remove the Helm installer release,"
|
||||
echo "the namespace and its contents may be deleted!"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Step 1: Check for cozy-proxy HelmRelease with conflicting releaseName
|
||||
# In v0.41.x, cozy-proxy was incorrectly configured with releaseName "cozystack",
|
||||
# which conflicts with the installer helm release name. If not suspended, cozy-proxy
|
||||
# HelmRelease will overwrite the installer release and delete cozystack-operator.
|
||||
COZY_PROXY_RELEASE_NAME=$(kubectl get hr -n "$NAMESPACE" cozy-proxy -o jsonpath='{.spec.releaseName}' 2>/dev/null || true)
|
||||
if [ "$COZY_PROXY_RELEASE_NAME" = "cozystack" ]; then
|
||||
echo "WARNING: HelmRelease cozy-proxy has releaseName 'cozystack', which conflicts"
|
||||
echo "with the installer release. It must be suspended before proceeding, otherwise"
|
||||
echo "it will overwrite the installer and delete cozystack-operator."
|
||||
echo ""
|
||||
read -p "Suspend HelmRelease cozy-proxy? (y/N) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
kubectl -n "$NAMESPACE" patch hr cozy-proxy --type=merge --field-manager=flux-client-side-apply -p '{"spec":{"suspend":true}}'
|
||||
echo "HelmRelease cozy-proxy suspended."
|
||||
else
|
||||
echo "ERROR: Cannot proceed with conflicting cozy-proxy HelmRelease active."
|
||||
echo "Please suspend it manually:"
|
||||
echo " kubectl -n $NAMESPACE patch hr cozy-proxy --type=merge -p '{\"spec\":{\"suspend\":true}}'"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Read ConfigMap cozystack
|
||||
echo "Reading ConfigMap cozystack..."
|
||||
COZYSTACK_CM=$(kubectl get configmap -n "$NAMESPACE" cozystack -o json 2>/dev/null || echo "{}")
|
||||
@@ -52,6 +100,10 @@ OIDC_ENABLED=$(echo "$COZYSTACK_CM" | jq -r '.data["oidc-enabled"] // "false"')
|
||||
KEYCLOAK_REDIRECTS=$(echo "$COZYSTACK_CM" | jq -r '.data["extra-keycloak-redirect-uri-for-dashboard"] // ""' )
|
||||
TELEMETRY_ENABLED=$(echo "$COZYSTACK_CM" | jq -r '.data["telemetry-enabled"] // "true"')
|
||||
BUNDLE_NAME=$(echo "$COZYSTACK_CM" | jq -r '.data["bundle-name"] // "paas-full"')
|
||||
BUNDLE_DISABLE=$(echo "$COZYSTACK_CM" | jq -r '.data["bundle-disable"] // ""')
|
||||
BUNDLE_ENABLE=$(echo "$COZYSTACK_CM" | jq -r '.data["bundle-enable"] // ""')
|
||||
EXPOSE_INGRESS=$(echo "$COZYSTACK_CM" | jq -r '.data["expose-ingress"] // "tenant-root"')
|
||||
EXPOSE_SERVICES=$(echo "$COZYSTACK_CM" | jq -r '.data["expose-services"] // ""')
|
||||
|
||||
# Certificate issuer configuration (old undocumented field: clusterissuer)
|
||||
OLD_CLUSTER_ISSUER=$(echo "$COZYSTACK_CM" | jq -r '.data["clusterissuer"] // ""')
|
||||
@@ -99,28 +151,31 @@ else
|
||||
EXTERNAL_IPS=$(echo "$EXTERNAL_IPS" | sed 's/,/\n/g' | awk 'BEGIN{print}{print " - "$0}')
|
||||
fi
|
||||
|
||||
# Determine bundle type
|
||||
case "$BUNDLE_NAME" in
|
||||
paas-full|distro-full)
|
||||
SYSTEM_ENABLED="true"
|
||||
SYSTEM_TYPE="full"
|
||||
;;
|
||||
paas-hosted|distro-hosted)
|
||||
SYSTEM_ENABLED="false"
|
||||
SYSTEM_TYPE="hosted"
|
||||
;;
|
||||
*)
|
||||
SYSTEM_ENABLED="false"
|
||||
SYSTEM_TYPE="hosted"
|
||||
;;
|
||||
esac
|
||||
# Convert comma-separated lists to YAML arrays
|
||||
if [ -z "$BUNDLE_DISABLE" ]; then
|
||||
DISABLED_PACKAGES="[]"
|
||||
else
|
||||
DISABLED_PACKAGES=$(echo "$BUNDLE_DISABLE" | sed 's/,/\n/g' | awk 'BEGIN{print}{print " - cozystack."$0}')
|
||||
fi
|
||||
|
||||
if [ -z "$BUNDLE_ENABLE" ]; then
|
||||
ENABLED_PACKAGES="[]"
|
||||
else
|
||||
ENABLED_PACKAGES=$(echo "$BUNDLE_ENABLE" | sed 's/,/\n/g' | awk 'BEGIN{print}{print " - cozystack."$0}')
|
||||
fi
|
||||
|
||||
if [ -z "$EXPOSE_SERVICES" ]; then
|
||||
EXPOSED_SERVICES_YAML="[]"
|
||||
else
|
||||
EXPOSED_SERVICES_YAML=$(echo "$EXPOSE_SERVICES" | sed 's/,/\n/g' | awk 'BEGIN{print}{print " - "$0}')
|
||||
fi
|
||||
|
||||
# Update bundle naming
|
||||
BUNDLE_NAME=$(echo "$BUNDLE_NAME" | sed 's/paas/isp/')
|
||||
|
||||
# Extract branding if available
|
||||
BRANDING=$(echo "$BRANDING_CM" | jq -r '.data // {} | to_entries[] | "\(.key): \"\(.value)\""')
|
||||
if [ -z "$BRANDING" ]; then
|
||||
if [ -z "$BRANDING" ]; then
|
||||
BRANDING="{}"
|
||||
else
|
||||
BRANDING=$(echo "$BRANDING" | awk 'BEGIN{print}{print " " $0}')
|
||||
@@ -141,8 +196,6 @@ echo " Root Host: $ROOT_HOST"
|
||||
echo " API Server Endpoint: $API_SERVER_ENDPOINT"
|
||||
echo " OIDC Enabled: $OIDC_ENABLED"
|
||||
echo " Bundle Name: $BUNDLE_NAME"
|
||||
echo " System Enabled: $SYSTEM_ENABLED"
|
||||
echo " System Type: $SYSTEM_TYPE"
|
||||
echo " Certificate Solver: ${SOLVER:-http01 (default)}"
|
||||
echo " Issuer Name: ${ISSUER_NAME:-letsencrypt-prod (default)}"
|
||||
echo ""
|
||||
@@ -160,15 +213,8 @@ spec:
|
||||
platform:
|
||||
values:
|
||||
bundles:
|
||||
system:
|
||||
enabled: $SYSTEM_ENABLED
|
||||
type: "$SYSTEM_TYPE"
|
||||
iaas:
|
||||
enabled: true
|
||||
paas:
|
||||
enabled: true
|
||||
naas:
|
||||
enabled: true
|
||||
disabledPackages: $DISABLED_PACKAGES
|
||||
enabledPackages: $ENABLED_PACKAGES
|
||||
networking:
|
||||
clusterDomain: "$CLUSTER_DOMAIN"
|
||||
podCIDR: "$POD_CIDR"
|
||||
@@ -177,6 +223,8 @@ spec:
|
||||
joinCIDR: "$JOIN_CIDR"
|
||||
publishing:
|
||||
host: "$ROOT_HOST"
|
||||
ingressName: "$EXPOSE_INGRESS"
|
||||
exposedServices: $EXPOSED_SERVICES_YAML
|
||||
apiServerEndpoint: "$API_SERVER_ENDPOINT"
|
||||
externalIPs: $EXTERNAL_IPS
|
||||
${CERTIFICATES_SECTION}
|
||||
|
||||
@@ -156,7 +156,7 @@ menuItems = append(menuItems, map[string]any{
|
||||
map[string]any{
|
||||
"key": "{plural}",
|
||||
"label": "{ResourceLabel}",
|
||||
"link": "/openapi-ui/{clusterName}/{namespace}/api-table/{group}/{version}/{plural}",
|
||||
"link": "/openapi-ui/{cluster}/{namespace}/api-table/{group}/{version}/{plural}",
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -174,7 +174,7 @@ menuItems = append(menuItems, map[string]any{
|
||||
|
||||
**Important Notes**:
|
||||
- The sidebar tag (`{lowercase-kind}-sidebar`) must match what the Factory uses
|
||||
- The link format: `/openapi-ui/{clusterName}/{namespace}/api-table/{group}/{version}/{plural}`
|
||||
- The link format: `/openapi-ui/{cluster}/{namespace}/api-table/{group}/{version}/{plural}`
|
||||
- All sidebars share the same `keysAndTags` and `menuItems`, so changes affect all sidebar instances
|
||||
|
||||
### Step 4: Verify Integration
|
||||
|
||||
@@ -195,6 +195,7 @@ func applyListInputOverrides(schema map[string]any, kind string, openAPIProps ma
|
||||
"valueUri": "/api/clusters/{cluster}/k8s/apis/instancetype.kubevirt.io/v1beta1/virtualmachineclusterinstancetypes",
|
||||
"keysToValue": []any{"metadata", "name"},
|
||||
"keysToLabel": []any{"metadata", "name"},
|
||||
"allowEmpty": true,
|
||||
},
|
||||
}
|
||||
if prop, _ := openAPIProps["instanceType"].(map[string]any); prop != nil {
|
||||
|
||||
@@ -202,6 +202,10 @@ func TestApplyListInputOverrides_VMInstance(t *testing.T) {
|
||||
t.Errorf("expected valueUri %s, got %v", expectedURI, customProps["valueUri"])
|
||||
}
|
||||
|
||||
if customProps["allowEmpty"] != true {
|
||||
t.Errorf("expected allowEmpty true, got %v", customProps["allowEmpty"])
|
||||
}
|
||||
|
||||
// Check disks[].name is a listInput
|
||||
disks, ok := specProps["disks"].(map[string]any)
|
||||
if !ok {
|
||||
|
||||
@@ -582,15 +582,14 @@ type factoryFlags struct {
|
||||
Secrets bool
|
||||
}
|
||||
|
||||
// factoryFeatureFlags tries several conventional locations so you can evolve the API
|
||||
// without breaking the controller. Defaults are false (hidden).
|
||||
// factoryFeatureFlags determines which tabs to show based on whether the
|
||||
// ApplicationDefinition has non-empty Include resource selectors.
|
||||
// Workloads tab is always shown.
|
||||
func factoryFeatureFlags(crd *cozyv1alpha1.ApplicationDefinition) factoryFlags {
|
||||
var f factoryFlags
|
||||
|
||||
f.Workloads = true
|
||||
f.Ingresses = true
|
||||
f.Services = true
|
||||
f.Secrets = true
|
||||
|
||||
return f
|
||||
return factoryFlags{
|
||||
Workloads: true,
|
||||
Ingresses: len(crd.Spec.Ingresses.Include) > 0,
|
||||
Services: len(crd.Spec.Services.Include) > 0,
|
||||
Secrets: len(crd.Spec.Secrets.Include) > 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,10 +299,6 @@ func (m *Manager) buildExpectedResourceSet(crds []cozyv1alpha1.ApplicationDefini
|
||||
|
||||
// Add other stock sidebars that are created for each CRD
|
||||
stockSidebars := []string{
|
||||
"stock-instance-api-form",
|
||||
"stock-instance-api-table",
|
||||
"stock-instance-builtin-form",
|
||||
"stock-instance-builtin-table",
|
||||
"stock-project-factory-marketplace",
|
||||
"stock-project-factory-workloadmonitor-details",
|
||||
"stock-project-api-form",
|
||||
@@ -311,6 +307,10 @@ func (m *Manager) buildExpectedResourceSet(crds []cozyv1alpha1.ApplicationDefini
|
||||
"stock-project-builtin-table",
|
||||
"stock-project-crd-form",
|
||||
"stock-project-crd-table",
|
||||
"stock-instance-api-form",
|
||||
"stock-instance-api-table",
|
||||
"stock-instance-builtin-form",
|
||||
"stock-instance-builtin-table",
|
||||
}
|
||||
for _, sidebarID := range stockSidebars {
|
||||
expected["Sidebar"][sidebarID] = true
|
||||
|
||||
@@ -68,31 +68,46 @@ func (m *Manager) ensureMarketplacePanel(ctx context.Context, crd *cozyv1alpha1.
|
||||
tags[i] = t
|
||||
}
|
||||
|
||||
specMap := map[string]any{
|
||||
"description": d.Description,
|
||||
"name": displayName,
|
||||
"type": "nonCrd",
|
||||
"apiGroup": "apps.cozystack.io",
|
||||
"apiVersion": "v1alpha1",
|
||||
"plural": app.Plural, // e.g., "buckets"
|
||||
"disabled": false,
|
||||
"hidden": false,
|
||||
"tags": tags,
|
||||
"icon": d.Icon,
|
||||
}
|
||||
|
||||
specBytes, err := json.Marshal(specMap)
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, m.Client, mp, func() error {
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, m.Client, mp, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, mp, m.Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
// Add dashboard labels to dynamic resources
|
||||
m.addDashboardLabels(mp, crd, ResourceTypeDynamic)
|
||||
|
||||
// Preserve user-set disabled/hidden values from existing resource
|
||||
disabled := false
|
||||
hidden := false
|
||||
if mp.Spec.Raw != nil {
|
||||
var existing map[string]any
|
||||
if err := json.Unmarshal(mp.Spec.Raw, &existing); err == nil {
|
||||
if v, ok := existing["disabled"].(bool); ok {
|
||||
disabled = v
|
||||
}
|
||||
if v, ok := existing["hidden"].(bool); ok {
|
||||
hidden = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
specMap := map[string]any{
|
||||
"description": d.Description,
|
||||
"name": displayName,
|
||||
"type": "nonCrd",
|
||||
"apiGroup": "apps.cozystack.io",
|
||||
"apiVersion": "v1alpha1",
|
||||
"plural": app.Plural, // e.g., "buckets"
|
||||
"disabled": disabled,
|
||||
"hidden": hidden,
|
||||
"tags": tags,
|
||||
"icon": d.Icon,
|
||||
}
|
||||
|
||||
specBytes, err := json.Marshal(specMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Only update spec if it's different to avoid unnecessary updates
|
||||
newSpec := dashv1alpha1.ArbitrarySpec{
|
||||
JSON: apiextv1.JSON{Raw: specBytes},
|
||||
|
||||
@@ -17,8 +17,7 @@ import (
|
||||
|
||||
// ensureSidebar creates/updates multiple Sidebar resources that share the same menu:
|
||||
// - The "details" sidebar tied to the current kind (stock-project-factory-<kind>-details)
|
||||
// - The stock-instance sidebars: api-form, api-table, builtin-form, builtin-table
|
||||
// - The stock-project sidebars: api-form, api-table, builtin-form, builtin-table, crd-form, crd-table
|
||||
// - The stock-project sidebars: api-form, api-table, builtin-form, builtin-table, crd-form, crd-table
|
||||
//
|
||||
// Menu rules:
|
||||
// - The first section is "Marketplace" with two hardcoded entries:
|
||||
@@ -39,6 +38,23 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati
|
||||
}
|
||||
all = crdList.Items
|
||||
|
||||
// 1b) Fetch all MarketplacePanels to determine which resources are hidden
|
||||
hiddenResources := map[string]bool{}
|
||||
var mpList dashv1alpha1.MarketplacePanelList
|
||||
if err := m.List(ctx, &mpList, &client.ListOptions{}); err == nil {
|
||||
for i := range mpList.Items {
|
||||
mp := &mpList.Items[i]
|
||||
if mp.Spec.Raw != nil {
|
||||
var spec map[string]any
|
||||
if err := json.Unmarshal(mp.Spec.Raw, &spec); err == nil {
|
||||
if hidden, ok := spec["hidden"].(bool); ok && hidden {
|
||||
hiddenResources[mp.Name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Build category -> []item map (only for CRDs with spec.dashboard != nil)
|
||||
type item struct {
|
||||
Key string
|
||||
@@ -64,6 +80,11 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati
|
||||
plural := pickPlural(kind, def)
|
||||
lowerKind := strings.ToLower(kind)
|
||||
|
||||
// Skip resources hidden via MarketplacePanel
|
||||
if hiddenResources[def.Name] {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if this resource is a module
|
||||
if def.Spec.Dashboard.Module {
|
||||
// Special case: info should have its own keysAndTags, not be in modules
|
||||
@@ -176,23 +197,23 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati
|
||||
|
||||
// Add hardcoded Backups section
|
||||
menuItems = append(menuItems, map[string]any{
|
||||
"key": "backups",
|
||||
"key": "backups-category",
|
||||
"label": "Backups",
|
||||
"children": []any{
|
||||
map[string]any{
|
||||
"key": "plans",
|
||||
"label": "Plans",
|
||||
"link": "/openapi-ui/{clusterName}/{namespace}/api-table/backups.cozystack.io/v1alpha1/plans",
|
||||
"link": "/openapi-ui/{cluster}/{namespace}/api-table/backups.cozystack.io/v1alpha1/plans",
|
||||
},
|
||||
map[string]any{
|
||||
"key": "backupjobs",
|
||||
"label": "BackupJobs",
|
||||
"link": "/openapi-ui/{clusterName}/{namespace}/api-table/backups.cozystack.io/v1alpha1/backupjobs",
|
||||
"link": "/openapi-ui/{cluster}/{namespace}/api-table/backups.cozystack.io/v1alpha1/backupjobs",
|
||||
},
|
||||
map[string]any{
|
||||
"key": "backups",
|
||||
"label": "Backups",
|
||||
"link": "/openapi-ui/{clusterName}/{namespace}/api-table/backups.cozystack.io/v1alpha1/backups",
|
||||
"link": "/openapi-ui/{cluster}/{namespace}/api-table/backups.cozystack.io/v1alpha1/backups",
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -215,7 +236,7 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati
|
||||
map[string]any{
|
||||
"key": "loadbalancer-services",
|
||||
"label": "External IPs",
|
||||
"link": "/openapi-ui/{clusterName}/{namespace}/factory/external-ips",
|
||||
"link": "/openapi-ui/{cluster}/{namespace}/factory/external-ips",
|
||||
},
|
||||
map[string]any{
|
||||
"key": "tenants",
|
||||
@@ -228,13 +249,7 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati
|
||||
// 6) Prepare the list of Sidebar IDs to upsert with the SAME content
|
||||
// Create sidebars for ALL CRDs with dashboard config
|
||||
targetIDs := []string{
|
||||
// stock-instance sidebars
|
||||
"stock-instance-api-form",
|
||||
"stock-instance-api-table",
|
||||
"stock-instance-builtin-form",
|
||||
"stock-instance-builtin-table",
|
||||
|
||||
// stock-project sidebars
|
||||
// stock-project sidebars (namespace-level, full menu)
|
||||
"stock-project-factory-marketplace",
|
||||
"stock-project-factory-workloadmonitor-details",
|
||||
"stock-project-factory-kube-service-details",
|
||||
@@ -250,6 +265,11 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati
|
||||
"stock-project-builtin-table",
|
||||
"stock-project-crd-form",
|
||||
"stock-project-crd-table",
|
||||
// stock-instance sidebars (namespace-level pages after namespace is selected)
|
||||
"stock-instance-api-form",
|
||||
"stock-instance-api-table",
|
||||
"stock-instance-builtin-form",
|
||||
"stock-instance-builtin-table",
|
||||
}
|
||||
|
||||
// Add details sidebars for all CRDs with dashboard config
|
||||
|
||||
@@ -505,7 +505,7 @@ func CreateAllCustomFormsOverrides() []*dashboardv1alpha1.CustomFormsOverride {
|
||||
createFormItem("spec.applicationRef.name", "Application Name", "text"),
|
||||
createFormItemWithAPI("spec.backupClassName", "Backup Class", "select", map[string]any{
|
||||
"api": map[string]any{
|
||||
"fetchUrl": "/api/clusters/{clusterName}/k8s/apis/backups.cozystack.io/v1alpha1/backupclasses",
|
||||
"fetchUrl": "/api/clusters/{cluster}/k8s/apis/backups.cozystack.io/v1alpha1/backupclasses",
|
||||
"pathToItems": []any{"items"},
|
||||
"pathToValue": []any{"metadata", "name"},
|
||||
"pathToLabel": []any{"metadata", "name"},
|
||||
@@ -516,6 +516,27 @@ func CreateAllCustomFormsOverrides() []*dashboardv1alpha1.CustomFormsOverride {
|
||||
createFormItem("spec.schedule.cron", "Schedule Cron", "text"),
|
||||
},
|
||||
}),
|
||||
|
||||
// BackupJobs form override - backups.cozystack.io/v1alpha1
|
||||
createCustomFormsOverride("default-/backups.cozystack.io/v1alpha1/backupjobs", map[string]any{
|
||||
"formItems": []any{
|
||||
createFormItem("metadata.name", "Name", "text"),
|
||||
createFormItem("metadata.namespace", "Namespace", "text"),
|
||||
createFormItem("spec.planRef.name", "Plan Name (optional)", "text"),
|
||||
createFormItem("spec.applicationRef.apiGroup", "Application API Group", "text"),
|
||||
createFormItem("spec.applicationRef.kind", "Application Kind", "text"),
|
||||
createFormItem("spec.applicationRef.name", "Application Name", "text"),
|
||||
createFormItemWithAPI("spec.backupClassName", "Backup Class", "select", map[string]any{
|
||||
"api": map[string]any{
|
||||
"fetchUrl": "/api/clusters/{cluster}/k8s/apis/backups.cozystack.io/v1alpha1/backupclasses",
|
||||
"pathToItems": []any{"items"},
|
||||
"pathToValue": []any{"metadata", "name"},
|
||||
"pathToLabel": []any{"metadata", "name"},
|
||||
"clusterNameVar": "clusterName",
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1915,12 +1936,12 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory {
|
||||
map[string]any{
|
||||
"type": "EnrichedTable",
|
||||
"data": map[string]any{
|
||||
"id": "external-ips-table",
|
||||
"fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/services",
|
||||
"clusterNamePartOfUrl": "{2}",
|
||||
"baseprefix": "/openapi-ui",
|
||||
"customizationId": "factory-details-v1.services",
|
||||
"pathToItems": []any{"items"},
|
||||
"id": "external-ips-table",
|
||||
"fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/services",
|
||||
"cluster": "{2}",
|
||||
"baseprefix": "/openapi-ui",
|
||||
"customizationId": "factory-details-v1.services",
|
||||
"pathToItems": ".items",
|
||||
"fieldSelector": map[string]any{
|
||||
"spec.type": "LoadBalancer",
|
||||
},
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/cluster-autoscaler:0.0.0@sha256:7deeee117e7eec599cb453836ca95eadd131dfc8c875dc457ef29dc1433395e0
|
||||
ghcr.io/cozystack/cozystack/cluster-autoscaler:0.0.0@sha256:3753b735b0315bee90de54cb25cfebc63bd2cc90ad11ca4fdc0e70439abd5096
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:604561e23df1b8eb25c24cf73fd93c7aaa6d1e7c56affbbda5c6f0f83424e4b1
|
||||
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:1c8c842277f45f189a5c645fcf7b2023c8ed7189f44029ce8b988019000da14c
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.33@sha256:19ee4c76f0b3b7b40b97995ca78988ad8c82f6e9c75288d8b7b4b88a64f75d50
|
||||
ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.35@sha256:39f626c802dd84f95720ffb54fcd80dfb8a58ac280498870d0a1aa30d4252f94
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{{- $targetTenant := .Values._namespace.monitoring }}
|
||||
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }}
|
||||
{{- if .Values.addons.monitoringAgents.enabled }}
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
@@ -49,7 +50,7 @@ spec:
|
||||
cluster: {{ .Release.Name }}
|
||||
tenant: {{ .Release.Namespace }}
|
||||
remoteWrite:
|
||||
url: http://vminsert-shortterm.{{ $targetTenant }}.svc:8480/insert/0/prometheus
|
||||
url: http://vminsert-shortterm.{{ $targetTenant }}.svc.{{ $clusterDomain }}:8480/insert/0/prometheus
|
||||
fluent-bit:
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
@@ -72,7 +73,7 @@ spec:
|
||||
[OUTPUT]
|
||||
Name http
|
||||
Match kube.*
|
||||
Host vlogs-generic.{{ $targetTenant }}.svc
|
||||
Host vlogs-generic.{{ $targetTenant }}.svc.{{ $clusterDomain }}
|
||||
port 9428
|
||||
compress gzip
|
||||
uri /insert/jsonline?_stream_fields=stream,kubernetes_pod_name,kubernetes_container_name,kubernetes_namespace_name&_msg_field=log&_time_field=date
|
||||
|
||||
@@ -18,7 +18,7 @@ spec:
|
||||
name: cozystack-etcd-application-default-etcd
|
||||
namespace: cozy-system
|
||||
interval: 5m
|
||||
timeout: 10m
|
||||
timeout: 30m
|
||||
install:
|
||||
remediation:
|
||||
retries: -1
|
||||
|
||||
@@ -34,6 +34,12 @@ spec:
|
||||
metadata:
|
||||
annotations:
|
||||
kubevirt.io/allow-pod-bridge-network-live-migration: "true"
|
||||
{{- $ovnIPName := printf "%s.%s" (include "virtual-machine.fullname" .) .Release.Namespace }}
|
||||
{{- $ovnIP := lookup "kubeovn.io/v1" "IP" "" $ovnIPName }}
|
||||
{{- if $ovnIP }}
|
||||
ovn.kubernetes.io/mac_address: {{ $ovnIP.spec.macAddress | quote }}
|
||||
ovn.kubernetes.io/ip_address: {{ $ovnIP.spec.ipAddress | quote }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "virtual-machine.labels" . | nindent 8 }}
|
||||
spec:
|
||||
|
||||
@@ -10,6 +10,8 @@ metadata:
|
||||
labels:
|
||||
cozystack.io/system: "true"
|
||||
pod-security.kubernetes.io/enforce: privileged
|
||||
annotations:
|
||||
helm.sh/resource-policy: keep
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
cozystackOperator:
|
||||
# Deployment variant: talos, generic, hosted
|
||||
variant: talos
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-operator:v1.0.0-beta.6@sha256:c7490da9c1ccb51bff4dd5657ca6a33a29ac71ad9861dfa8c72fdfc8b5765b93
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-operator:v1.0.5@sha256:eed2b2aa2d1cb1819bfd5bafd00ccf0a9562fe7b787eb6e391d8941cf41fee00
|
||||
platformSourceUrl: 'oci://ghcr.io/cozystack/cozystack/cozystack-packages'
|
||||
platformSourceRef: 'digest=sha256:b29b87d1a2b80452ffd4db7516a102c30c55121552dcdb237055d4124d12c55d'
|
||||
platformSourceRef: 'digest=sha256:f1df5097ea9ea59cf4aec3d54095dc587b0cd7f6355829e21f44576976416bcc'
|
||||
# Generic variant configuration (only used when cozystackOperator.variant=generic)
|
||||
cozystack:
|
||||
# Kubernetes API server host (IP only, no protocol/port)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Migration 26 --> 27
|
||||
# Migrate monitoring resources from extra/monitoring to system/monitoring
|
||||
# This migration re-labels resources so they become owned by monitoring-system HelmRelease
|
||||
# and deletes old helm release secrets so that helm does not diff old vs new chart manifests.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -35,10 +36,39 @@ relabel_resources() {
|
||||
done
|
||||
}
|
||||
|
||||
# Delete all helm release secrets for a given release name in a namespace.
|
||||
# Uses both label selector and name-pattern matching to ensure complete cleanup.
|
||||
delete_helm_secrets() {
|
||||
local ns="$1"
|
||||
local release="$2"
|
||||
|
||||
# Primary: delete by label selector
|
||||
kubectl delete secrets -n "$ns" -l "name=${release},owner=helm" --ignore-not-found
|
||||
|
||||
# Fallback: find and delete by name pattern (in case labels were modified)
|
||||
local remaining
|
||||
remaining=$(kubectl get secrets -n "$ns" -o name | { grep "^secret/sh\.helm\.release\.v1\.${release}\." || true; })
|
||||
if [ -n "$remaining" ]; then
|
||||
echo " Found secrets not matched by label selector, deleting by name..."
|
||||
echo "$remaining" | while IFS= read -r secret; do
|
||||
echo " Deleting $secret"
|
||||
kubectl delete -n "$ns" "$secret" --ignore-not-found
|
||||
done
|
||||
fi
|
||||
|
||||
# Verify all secrets are gone
|
||||
remaining=$(kubectl get secrets -n "$ns" -o name | { grep "^secret/sh\.helm\.release\.v1\.${release}\." || true; })
|
||||
if [ -n "$remaining" ]; then
|
||||
echo " ERROR: Failed to delete helm release secrets:"
|
||||
echo "$remaining"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Find all tenant namespaces with monitoring HelmRelease
|
||||
echo "Finding tenant namespaces with monitoring HelmRelease..."
|
||||
NAMESPACES=$(kubectl get hr --all-namespaces -l apps.cozystack.io/application.kind=Monitoring \
|
||||
-o jsonpath='{range .items[*]}{.metadata.namespace}{"\n"}{end}' 2>/dev/null | sort -u || true)
|
||||
NAMESPACES=$(kubectl get hr --all-namespaces -l cozystack.io/ui=true --field-selector=metadata.name=monitoring \
|
||||
-o jsonpath='{range .items[*]}{.metadata.namespace}{"\n"}{end}' | sort -u)
|
||||
|
||||
if [ -z "$NAMESPACES" ]; then
|
||||
echo "No monitoring HelmReleases found in tenant namespaces, skipping migration"
|
||||
@@ -66,7 +96,7 @@ for ns in $NAMESPACES; do
|
||||
# Step 1: Suspend the HelmRelease
|
||||
echo ""
|
||||
echo "Step 1: Suspending HelmRelease monitoring..."
|
||||
kubectl patch hr -n "$ns" monitoring --type=merge -p '{"spec":{"suspend":true}}' 2>/dev/null || true
|
||||
kubectl patch hr -n "$ns" monitoring --type=merge -p '{"spec":{"suspend":true}}'
|
||||
|
||||
# Wait a moment for reconciliation to stop
|
||||
sleep 2
|
||||
@@ -74,7 +104,7 @@ for ns in $NAMESPACES; do
|
||||
# Step 2: Delete helm secrets for the monitoring release
|
||||
echo ""
|
||||
echo "Step 2: Deleting helm secrets for monitoring release..."
|
||||
kubectl delete secrets -n "$ns" -l name=monitoring,owner=helm --ignore-not-found
|
||||
delete_helm_secrets "$ns" "monitoring"
|
||||
|
||||
# Step 3: Relabel resources to be owned by monitoring-system
|
||||
echo ""
|
||||
@@ -121,7 +151,9 @@ for ns in $NAMESPACES; do
|
||||
echo "Processing Cozystack resources..."
|
||||
relabel_resources "$ns" "workloadmonitors.cozystack.io"
|
||||
|
||||
# Step 4: Delete the suspended HelmRelease (Flux won't delete resources when HR is suspended)
|
||||
# Step 4: Delete the suspended HelmRelease
|
||||
# Helm secrets are already gone, so flux finalizer will find no release to uninstall
|
||||
# and will simply remove the finalizer without deleting any resources.
|
||||
echo ""
|
||||
echo "Step 4: Deleting suspended HelmRelease monitoring..."
|
||||
kubectl delete hr -n "$ns" monitoring --ignore-not-found
|
||||
|
||||
@@ -5,10 +5,24 @@ set -euo pipefail
|
||||
|
||||
# Migrate Piraeus CRDs to piraeus-operator-crds Helm release
|
||||
for crd in linstorclusters.piraeus.io linstornodeconnections.piraeus.io linstorsatelliteconfigurations.piraeus.io linstorsatellites.piraeus.io; do
|
||||
kubectl annotate crd "$crd" meta.helm.sh/release-namespace=cozy-linstor meta.helm.sh/release-name=piraeus-operator-crds --overwrite
|
||||
kubectl label crd "$crd" app.kubernetes.io/managed-by=Helm helm.toolkit.fluxcd.io/namespace=cozy-linstor helm.toolkit.fluxcd.io/name=piraeus-operator-crds --overwrite
|
||||
if kubectl get crd "$crd" >/dev/null 2>&1; then
|
||||
echo " Relabeling CRD $crd"
|
||||
kubectl annotate crd "$crd" meta.helm.sh/release-namespace=cozy-linstor meta.helm.sh/release-name=piraeus-operator-crds --overwrite
|
||||
kubectl label crd "$crd" app.kubernetes.io/managed-by=Helm helm.toolkit.fluxcd.io/namespace=cozy-linstor helm.toolkit.fluxcd.io/name=piraeus-operator-crds --overwrite
|
||||
else
|
||||
echo " CRD $crd not found, skipping"
|
||||
fi
|
||||
done
|
||||
|
||||
# Delete old piraeus-operator helm secrets (by label and by name pattern)
|
||||
kubectl delete secret -n cozy-linstor -l name=piraeus-operator,owner=helm --ignore-not-found
|
||||
remaining=$(kubectl get secrets -n cozy-linstor -o name 2>/dev/null | { grep "^secret/sh\.helm\.release\.v1\.piraeus-operator\." || true; })
|
||||
if [ -n "$remaining" ]; then
|
||||
echo " Deleting remaining piraeus-operator helm secrets by name..."
|
||||
echo "$remaining" | while IFS= read -r secret; do
|
||||
kubectl delete -n cozy-linstor "$secret" --ignore-not-found
|
||||
done
|
||||
fi
|
||||
|
||||
# Stamp version
|
||||
kubectl create configmap -n cozy-system cozystack-version \
|
||||
|
||||
@@ -348,7 +348,7 @@ PVCEOF
|
||||
# --- 3g: Clone Secrets ---
|
||||
echo " --- Clone Secrets ---"
|
||||
for secret in $(kubectl -n "$NAMESPACE" get secret -o name 2>/dev/null \
|
||||
| grep "secret/${OLD_NAME}" | grep -v "sh.helm.release"); do
|
||||
| { grep "secret/${OLD_NAME}" || true; } | { grep -v "sh.helm.release" || true; }); do
|
||||
old_secret_name="${secret#secret/}"
|
||||
new_secret_name="${NEW_NAME}${old_secret_name#${OLD_NAME}}"
|
||||
clone_resource "$NAMESPACE" "secret" "$old_secret_name" "$new_secret_name" "$OLD_NAME" "$NEW_NAME"
|
||||
@@ -357,7 +357,7 @@ PVCEOF
|
||||
# --- 3h: Clone ConfigMaps ---
|
||||
echo " --- Clone ConfigMaps ---"
|
||||
for cm in $(kubectl -n "$NAMESPACE" get configmap -o name 2>/dev/null \
|
||||
| grep "configmap/${OLD_NAME}"); do
|
||||
| { grep "configmap/${OLD_NAME}" || true; }); do
|
||||
old_cm_name="${cm#configmap/}"
|
||||
new_cm_name="${NEW_NAME}${old_cm_name#${OLD_NAME}}"
|
||||
clone_resource "$NAMESPACE" "configmap" "$old_cm_name" "$new_cm_name" "$OLD_NAME" "$NEW_NAME"
|
||||
@@ -468,13 +468,13 @@ PVCEOF
|
||||
fi
|
||||
|
||||
for secret in $(kubectl -n "$NAMESPACE" get secret -o name 2>/dev/null \
|
||||
| grep "secret/${OLD_NAME}" | grep -v "sh.helm.release"); do
|
||||
| { grep "secret/${OLD_NAME}" || true; } | { grep -v "sh.helm.release" || true; }); do
|
||||
old_secret_name="${secret#secret/}"
|
||||
delete_resource "$NAMESPACE" "secret" "$old_secret_name"
|
||||
done
|
||||
|
||||
for cm in $(kubectl -n "$NAMESPACE" get configmap -o name 2>/dev/null \
|
||||
| grep "configmap/${OLD_NAME}"); do
|
||||
| { grep "configmap/${OLD_NAME}" || true; }); do
|
||||
old_cm_name="${cm#configmap/}"
|
||||
delete_resource "$NAMESPACE" "configmap" "$old_cm_name"
|
||||
done
|
||||
@@ -611,6 +611,19 @@ done
|
||||
echo ""
|
||||
echo "=== Migration complete (${#INSTANCES[@]} instance(s)) ==="
|
||||
|
||||
# ============================================================
|
||||
# STEP 8: Clean up orphaned mysql-rd system HelmRelease
|
||||
# ============================================================
|
||||
echo ""
|
||||
echo "--- Step 8: Clean up orphaned mysql-rd HelmRelease ---"
|
||||
if kubectl -n cozy-system get hr mysql-rd --no-headers 2>/dev/null | grep -q .; then
|
||||
echo " [DELETE] hr/mysql-rd"
|
||||
kubectl -n cozy-system delete hr mysql-rd --wait=false
|
||||
else
|
||||
echo " [SKIP] hr/mysql-rd already gone"
|
||||
fi
|
||||
kubectl -n cozy-system delete secret -l "owner=helm,name=mysql-rd" --ignore-not-found
|
||||
|
||||
# Stamp version
|
||||
kubectl create configmap -n cozy-system cozystack-version \
|
||||
--from-literal=version=29 --dry-run=client -o yaml | kubectl apply -f-
|
||||
|
||||
@@ -9,8 +9,6 @@ set -euo pipefail
|
||||
OLD_PREFIX="virtual-machine"
|
||||
NEW_DISK_PREFIX="vm-disk"
|
||||
NEW_INSTANCE_PREFIX="vm-instance"
|
||||
PROTECTION_WEBHOOK_NAME="protection-webhook"
|
||||
PROTECTION_WEBHOOK_NS="protection-webhook"
|
||||
CDI_APISERVER_NS="cozy-kubevirt-cdi"
|
||||
CDI_APISERVER_DEPLOY="cdi-apiserver"
|
||||
CDI_VALIDATING_WEBHOOKS="cdi-api-datavolume-validate cdi-api-dataimportcron-validate cdi-api-populator-validate cdi-api-validate"
|
||||
@@ -88,7 +86,6 @@ echo " Total: ${#INSTANCES[@]} instance(s)"
|
||||
# STEP 2: Migrate each instance
|
||||
# ============================================================
|
||||
ALL_PV_NAMES=()
|
||||
ALL_PROTECTED_RESOURCES=()
|
||||
|
||||
for entry in "${INSTANCES[@]}"; do
|
||||
NAMESPACE="${entry%%/*}"
|
||||
@@ -315,7 +312,7 @@ PVCEOF
|
||||
# --- 2i: Clone Secrets ---
|
||||
echo " --- Clone Secrets ---"
|
||||
kubectl -n "$NAMESPACE" get secret -o name 2>/dev/null \
|
||||
| grep "secret/${OLD_NAME}" | grep -v "sh.helm.release" | grep -v "values" \
|
||||
| { grep "secret/${OLD_NAME}" || true; } | { grep -v "sh.helm.release" || true; } | { grep -v "values" || true; } \
|
||||
| while IFS= read -r secret; do
|
||||
old_secret_name="${secret#secret/}"
|
||||
suffix="${old_secret_name#${OLD_NAME}}"
|
||||
@@ -542,7 +539,7 @@ SVCEOF
|
||||
# --- 2q: Delete old resources ---
|
||||
echo " --- Delete old resources ---"
|
||||
kubectl -n "$NAMESPACE" get secret -o name 2>/dev/null \
|
||||
| grep "secret/${OLD_NAME}" | grep -v "sh.helm.release" | grep -v "values" \
|
||||
| { grep "secret/${OLD_NAME}" || true; } | { grep -v "sh.helm.release" || true; } | { grep -v "values" || true; } \
|
||||
| while IFS= read -r secret; do
|
||||
old_secret_name="${secret#secret/}"
|
||||
delete_resource "$NAMESPACE" "secret" "$old_secret_name"
|
||||
@@ -564,71 +561,17 @@ SVCEOF
|
||||
delete_resource "$NAMESPACE" "secret" "$VALUES_SECRET"
|
||||
fi
|
||||
|
||||
# Collect protected resources for batch deletion
|
||||
# Delete old service (if exists)
|
||||
if resource_exists "$NAMESPACE" "svc" "$OLD_NAME"; then
|
||||
ALL_PROTECTED_RESOURCES+=("${NAMESPACE}:svc/${OLD_NAME}")
|
||||
delete_resource "$NAMESPACE" "svc" "$OLD_NAME"
|
||||
fi
|
||||
done
|
||||
|
||||
# ============================================================
|
||||
# STEP 3: Delete protected resources (Services)
|
||||
# STEP 3: Restore PV reclaim policies
|
||||
# ============================================================
|
||||
echo ""
|
||||
echo "--- Step 3: Delete protected resources ---"
|
||||
|
||||
if [ ${#ALL_PROTECTED_RESOURCES[@]} -gt 0 ]; then
|
||||
WEBHOOK_EXISTS=false
|
||||
if kubectl -n "$PROTECTION_WEBHOOK_NS" get deploy "$PROTECTION_WEBHOOK_NAME" --no-headers 2>/dev/null | grep -q .; then
|
||||
WEBHOOK_EXISTS=true
|
||||
fi
|
||||
|
||||
if [ "$WEBHOOK_EXISTS" = "true" ]; then
|
||||
echo " --- Temporarily disabling protection-webhook ---"
|
||||
|
||||
WEBHOOK_REPLICAS=$(kubectl -n "$PROTECTION_WEBHOOK_NS" get deploy "$PROTECTION_WEBHOOK_NAME" \
|
||||
-o jsonpath='{.spec.replicas}' 2>/dev/null || echo "1")
|
||||
|
||||
echo " [SCALE] ${PROTECTION_WEBHOOK_NAME} -> 0 (was ${WEBHOOK_REPLICAS})"
|
||||
kubectl -n "$PROTECTION_WEBHOOK_NS" scale deploy "$PROTECTION_WEBHOOK_NAME" --replicas=0
|
||||
|
||||
echo " [PATCH] Set failurePolicy=Ignore on ValidatingWebhookConfiguration/${PROTECTION_WEBHOOK_NAME}"
|
||||
kubectl get validatingwebhookconfiguration "$PROTECTION_WEBHOOK_NAME" -o json | \
|
||||
jq '.webhooks[].failurePolicy = "Ignore"' | \
|
||||
kubectl apply -f - 2>/dev/null || true
|
||||
|
||||
echo " Waiting for webhook pods to terminate..."
|
||||
kubectl -n "$PROTECTION_WEBHOOK_NS" wait --for=delete pod \
|
||||
-l app.kubernetes.io/name=protection-webhook --timeout=60s 2>/dev/null || true
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
for entry in "${ALL_PROTECTED_RESOURCES[@]}"; do
|
||||
ns="${entry%%:*}"
|
||||
res="${entry#*:}"
|
||||
echo " [DELETE] ${ns}/${res}"
|
||||
kubectl -n "$ns" delete "$res" --wait=false 2>/dev/null || true
|
||||
done
|
||||
|
||||
if [ "$WEBHOOK_EXISTS" = "true" ]; then
|
||||
echo " [PATCH] Set failurePolicy=Fail on ValidatingWebhookConfiguration/${PROTECTION_WEBHOOK_NAME}"
|
||||
kubectl get validatingwebhookconfiguration "$PROTECTION_WEBHOOK_NAME" -o json | \
|
||||
jq '.webhooks[].failurePolicy = "Fail"' | \
|
||||
kubectl apply -f - 2>/dev/null || true
|
||||
|
||||
echo " [SCALE] ${PROTECTION_WEBHOOK_NAME} -> ${WEBHOOK_REPLICAS}"
|
||||
kubectl -n "$PROTECTION_WEBHOOK_NS" scale deploy "$PROTECTION_WEBHOOK_NAME" \
|
||||
--replicas="$WEBHOOK_REPLICAS"
|
||||
echo " --- protection-webhook restored ---"
|
||||
fi
|
||||
else
|
||||
echo " [SKIP] No protected resources to delete"
|
||||
fi
|
||||
|
||||
# ============================================================
|
||||
# STEP 4: Restore PV reclaim policies
|
||||
# ============================================================
|
||||
echo ""
|
||||
echo "--- Step 4: Restore PV reclaim policies ---"
|
||||
echo "--- Step 3: Restore PV reclaim policies ---"
|
||||
for pv_name in "${ALL_PV_NAMES[@]}"; do
|
||||
if [ -n "$pv_name" ]; then
|
||||
current_policy=$(kubectl get pv "$pv_name" \
|
||||
@@ -643,7 +586,7 @@ for pv_name in "${ALL_PV_NAMES[@]}"; do
|
||||
done
|
||||
|
||||
# ============================================================
|
||||
# STEP 5: Temporarily disable CDI datavolume webhooks
|
||||
# STEP 4: Temporarily disable CDI datavolume webhooks
|
||||
# ============================================================
|
||||
# CDI's datavolume-validate webhook rejects DataVolume creation when a PVC
|
||||
# with the same name already exists. We must disable it so that vm-disk
|
||||
@@ -652,7 +595,7 @@ done
|
||||
# cdi-apiserver (which serves the webhooks), then delete webhook configs.
|
||||
# Both are restored after vm-disk HRs reconcile.
|
||||
echo ""
|
||||
echo "--- Step 5: Temporarily disable CDI webhooks ---"
|
||||
echo "--- Step 4: Temporarily disable CDI webhooks ---"
|
||||
|
||||
CDI_OPERATOR_REPLICAS=$(kubectl -n "$CDI_APISERVER_NS" get deploy cdi-operator \
|
||||
-o jsonpath='{.spec.replicas}' 2>/dev/null || echo "1")
|
||||
@@ -685,10 +628,10 @@ done
|
||||
sleep 2
|
||||
|
||||
# ============================================================
|
||||
# STEP 6: Unsuspend vm-disk HelmReleases first
|
||||
# STEP 5: Unsuspend vm-disk HelmReleases first
|
||||
# ============================================================
|
||||
echo ""
|
||||
echo "--- Step 6: Unsuspend vm-disk HelmReleases ---"
|
||||
echo "--- Step 5: Unsuspend vm-disk HelmReleases ---"
|
||||
for entry in "${INSTANCES[@]}"; do
|
||||
ns="${entry%%/*}"
|
||||
instance="${entry#*/}"
|
||||
@@ -705,7 +648,7 @@ for entry in "${INSTANCES[@]}"; do
|
||||
# Force immediate reconciliation
|
||||
echo " [TRIGGER] Reconcile ${ns}/hr/${disk_name}"
|
||||
kubectl -n "$ns" annotate hr "$disk_name" --overwrite \
|
||||
"reconcile.fluxcd.io/requestedAt=$(date +%s)" 2>/dev/null || true
|
||||
"reconcile.fluxcd.io/requestedAt=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -729,12 +672,12 @@ for entry in "${INSTANCES[@]}"; do
|
||||
done
|
||||
|
||||
# ============================================================
|
||||
# STEP 7: Restore CDI webhooks
|
||||
# STEP 6: Restore CDI webhooks
|
||||
# ============================================================
|
||||
# Scale cdi-operator and cdi-apiserver back up.
|
||||
# cdi-apiserver will recreate webhook configurations automatically on start.
|
||||
echo ""
|
||||
echo "--- Step 7: Restore CDI webhooks ---"
|
||||
echo "--- Step 6: Restore CDI webhooks ---"
|
||||
|
||||
echo " [SCALE] cdi-operator -> ${CDI_OPERATOR_REPLICAS}"
|
||||
kubectl -n "$CDI_APISERVER_NS" scale deploy cdi-operator \
|
||||
@@ -749,10 +692,10 @@ kubectl -n "$CDI_APISERVER_NS" rollout status deploy "$CDI_APISERVER_DEPLOY" --t
|
||||
echo " --- CDI webhooks restored ---"
|
||||
|
||||
# ============================================================
|
||||
# STEP 8: Unsuspend vm-instance HelmReleases
|
||||
# STEP 7: Unsuspend vm-instance HelmReleases
|
||||
# ============================================================
|
||||
echo ""
|
||||
echo "--- Step 8: Unsuspend vm-instance HelmReleases ---"
|
||||
echo "--- Step 7: Unsuspend vm-instance HelmReleases ---"
|
||||
for entry in "${INSTANCES[@]}"; do
|
||||
ns="${entry%%/*}"
|
||||
instance="${entry#*/}"
|
||||
@@ -772,6 +715,19 @@ done
|
||||
echo ""
|
||||
echo "=== Migration complete (${#INSTANCES[@]} instance(s)) ==="
|
||||
|
||||
# ============================================================
|
||||
# STEP 8: Clean up orphaned virtual-machine-rd system HelmRelease
|
||||
# ============================================================
|
||||
echo ""
|
||||
echo "--- Step 8: Clean up orphaned virtual-machine-rd HelmRelease ---"
|
||||
if kubectl -n cozy-system get hr virtual-machine-rd --no-headers 2>/dev/null | grep -q .; then
|
||||
echo " [DELETE] hr/virtual-machine-rd"
|
||||
kubectl -n cozy-system delete hr virtual-machine-rd --wait=false
|
||||
else
|
||||
echo " [SKIP] hr/virtual-machine-rd already gone"
|
||||
fi
|
||||
kubectl -n cozy-system delete secret -l "owner=helm,name=virtual-machine-rd" --ignore-not-found
|
||||
|
||||
# Stamp version
|
||||
kubectl create configmap -n cozy-system cozystack-version \
|
||||
--from-literal=version=30 --dry-run=client -o yaml | kubectl apply -f-
|
||||
|
||||
30
packages/core/platform/images/migrations/migrations/33
Executable file
30
packages/core/platform/images/migrations/migrations/33
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
# Migration 33 --> 34
|
||||
# Clean up orphaned system -rd HelmReleases left after application renames.
|
||||
#
|
||||
# These HelmReleases reference ExternalArtifacts that no longer exist:
|
||||
# ferretdb-rd -> replaced by mongodb-rd
|
||||
# mysql-rd -> replaced by mariadb-rd (migration 28 handled user HRs only)
|
||||
# virtual-machine-rd -> replaced by vm-disk-rd + vm-instance-rd (migration 29 handled user HRs only)
|
||||
#
|
||||
# Idempotent: safe to re-run.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "=== Cleaning up orphaned -rd HelmReleases ==="
|
||||
|
||||
for hr_name in ferretdb-rd mysql-rd virtual-machine-rd; do
|
||||
if kubectl -n cozy-system get hr "$hr_name" --no-headers 2>/dev/null | grep -q .; then
|
||||
echo " [DELETE] hr/${hr_name}"
|
||||
kubectl -n cozy-system delete hr "$hr_name" --wait=false
|
||||
else
|
||||
echo " [SKIP] hr/${hr_name} already gone"
|
||||
fi
|
||||
kubectl -n cozy-system delete secret -l "owner=helm,name=${hr_name}" --ignore-not-found
|
||||
done
|
||||
|
||||
echo "=== Cleanup complete ==="
|
||||
|
||||
# Stamp version
|
||||
kubectl create configmap -n cozy-system cozystack-version \
|
||||
--from-literal=version=34 --dry-run=client -o yaml | kubectl apply -f-
|
||||
@@ -24,7 +24,7 @@ if [ "$CURRENT_VERSION" -ge "$TARGET_VERSION" ]; then
|
||||
fi
|
||||
|
||||
# Run migrations sequentially from current version to target version
|
||||
for i in $(seq $((CURRENT_VERSION + 1)) $TARGET_VERSION); do
|
||||
for i in $(seq $CURRENT_VERSION $((TARGET_VERSION - 1))); do
|
||||
if [ -f "/migrations/$i" ]; then
|
||||
echo "Running migration $i"
|
||||
chmod +x /migrations/$i
|
||||
|
||||
@@ -6,6 +6,8 @@ kind: ConfigMap
|
||||
metadata:
|
||||
name: cozystack-version
|
||||
namespace: {{ .Release.Namespace }}
|
||||
annotations:
|
||||
helm.sh/resource-policy: keep
|
||||
data:
|
||||
version: {{ .Values.migrations.targetVersion | quote }}
|
||||
{{- end }}
|
||||
|
||||
@@ -5,8 +5,8 @@ sourceRef:
|
||||
path: /
|
||||
migrations:
|
||||
enabled: false
|
||||
image: ghcr.io/cozystack/cozystack/platform-migrations:v1.0.0-beta.6@sha256:37c78dafcedbdad94acd9912550db0b4875897150666b8a06edfa894de99064e
|
||||
targetVersion: 33
|
||||
image: ghcr.io/cozystack/cozystack/platform-migrations:v1.0.5@sha256:d43c6f26c65edd448f586a29969ff76718338f1f1f78b24d3ad54c6c8977c748
|
||||
targetVersion: 34
|
||||
# Bundle deployment configuration
|
||||
bundles:
|
||||
system:
|
||||
@@ -46,7 +46,7 @@ publishing:
|
||||
apiServerEndpoint: "" # example: "https://api.example.org"
|
||||
externalIPs: []
|
||||
certificates:
|
||||
solver: http01 # "http01" or "dns01"
|
||||
solver: http01 # "http01" or "dns01"
|
||||
issuerName: letsencrypt-prod
|
||||
# Authentication configuration
|
||||
authentication:
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
e2e:
|
||||
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v1.0.0-beta.6@sha256:09af5901abcbed2b612d2d93c163e8ad3948bc55a1d8beae714b4fb2b8f7d91d
|
||||
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v1.0.5@sha256:0eae9f519669667d60b160ebb93c127843c470ad9ca3447fceaa54604503a7ba
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/matchbox:v1.0.0-beta.6@sha256:212f624957447f5a932fd5d4564eb8c97694d336b7dc877a2833c1513c0d074d
|
||||
ghcr.io/cozystack/cozystack/matchbox:v1.0.5@sha256:81bd1cd76fd01a61b0bab082aa61325054f6ef80eb56b683ddd38ae072dd0351
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.0-beta.6@sha256:235b194a531b70e266a10ef78d2955d19f5b659513f23d8b3cfbbc0dff7fc1c0
|
||||
ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.5@sha256:2a3595cd88b30af55b2000d3ca204899beecef0012b0e0402754c3914aad1f7f
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
backupController:
|
||||
image: "ghcr.io/cozystack/cozystack/backup-controller:v1.0.0-beta.6@sha256:365214a74ffc34a9314a62a7d4b491590051fc5486f6bae9913c0c1289983d43"
|
||||
image: "ghcr.io/cozystack/cozystack/backup-controller:v1.0.5@sha256:6c61c68fb4110ddcc4e1f5ab5835c4bdcb0c74b5c672e34d73beafd52ec6056d"
|
||||
replicas: 2
|
||||
debug: false
|
||||
metrics:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
backupStrategyController:
|
||||
image: "ghcr.io/cozystack/cozystack/backupstrategy-controller:v1.0.0-beta.6@sha256:aa04ee61dce11950162606fc8db2d5cbc6f5b32ba700f790b3f1eee10d65efb1"
|
||||
image: "ghcr.io/cozystack/cozystack/backupstrategy-controller:v1.0.5@sha256:96eed9980a63cc1093249dcfd5408be8f278cf6c11896d92885aa8a093395a9b"
|
||||
replicas: 2
|
||||
debug: false
|
||||
metrics:
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:291427de7db54a1d19dc9c2c807bdcc664a14caa9538786f31317e8c01a4a008
|
||||
ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:6ace7a9da7dea7eb0a8895d8ce72d3e3ac806488058aac6f386756fc0f143d78
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
cozystackAPI:
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-api:v1.0.0-beta.6@sha256:d89cf68fb622d0dbef7db98db09d352efc93c2cce448d11f2d73dcd363e911b7
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-api:v1.0.5@sha256:7a39918402ae50c51d22d4005e5cf9974a1b8ca0f85441944f685c420b45088f
|
||||
replicas: 2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cozystackController:
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-controller:v1.0.0-beta.6@sha256:d55a3c288934b1f69a00321bc8a94776915556b5f882fe6ac615e9de2701c61f
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-controller:v1.0.5@sha256:5b6dcf2d968343111e6681b2e76ff8725c7cde7826c24a771ae1666e5382b462
|
||||
debug: false
|
||||
disableTelemetry: false
|
||||
|
||||
@@ -6,7 +6,7 @@ FROM node:${NODE_VERSION}-alpine AS openapi-k8s-toolkit-builder
|
||||
RUN apk add git
|
||||
WORKDIR /src
|
||||
# release/1.4.0
|
||||
ARG COMMIT=c67029cc7b7495c65ee0406033576e773a73bb01
|
||||
ARG COMMIT=d6b9e4ad0d1eb9d3730f7f0c664792c8dda3214d
|
||||
RUN wget -O- https://github.com/PRO-Robotech/openapi-k8s-toolkit/archive/${COMMIT}.tar.gz | tar -xzvf- --strip-components=1
|
||||
|
||||
COPY openapi-k8s-toolkit/patches /patches
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
diff --git a/src/localTypes/formExtensions.ts b/src/localTypes/formExtensions.ts
|
||||
--- a/src/localTypes/formExtensions.ts
|
||||
+++ b/src/localTypes/formExtensions.ts
|
||||
@@ -59,2 +59,4 @@
|
||||
relatedValuePath?: string
|
||||
+ allowEmpty?: boolean
|
||||
+ persistType?: 'str' | 'number' | 'arr' | 'obj'
|
||||
}
|
||||
diff --git a/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx b/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx
|
||||
--- a/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx
|
||||
+++ b/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx
|
||||
@@ -149,3 +149,10 @@
|
||||
}, [relatedPath, form, arrName, fixedName, relatedFieldValue, onValuesChangeCallBack, isTouchedPeristed])
|
||||
|
||||
+ // When allowEmpty is set, auto-persist the field so the BFF preserves empty values
|
||||
+ useEffect(() => {
|
||||
+ if (customProps.allowEmpty) {
|
||||
+ persistedControls.onPersistMark(persistName || name, customProps.persistType ?? 'str')
|
||||
+ }
|
||||
+ }, [customProps.allowEmpty, customProps.persistType, persistedControls, persistName, name])
|
||||
+
|
||||
const uri = prepareTemplate({
|
||||
@@ -267,5 +274,14 @@
|
||||
validateTrigger="onBlur"
|
||||
hasFeedback={designNewLayout ? { icons: feedbackIcons } : true}
|
||||
style={{ flex: 1 }}
|
||||
+ normalize={(value: unknown) => {
|
||||
+ if (customProps.allowEmpty && (value === undefined || value === null)) {
|
||||
+ if (customProps.persistType === 'number') return 0
|
||||
+ if (customProps.persistType === 'arr') return []
|
||||
+ if (customProps.persistType === 'obj') return {}
|
||||
+ return ''
|
||||
+ }
|
||||
+ return value
|
||||
+ }}
|
||||
>
|
||||
<Select
|
||||
@@ -1,49 +0,0 @@
|
||||
diff --git a/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx b/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx
|
||||
index d5e5230..9038dbb 100644
|
||||
--- a/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx
|
||||
+++ b/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx
|
||||
@@ -259,14 +259,15 @@ export const FormListInput: FC<TFormListInputProps> = ({
|
||||
<PersistedCheckbox formName={persistName || name} persistedControls={persistedControls} type="arr" />
|
||||
</Flex>
|
||||
</Flex>
|
||||
- <ResetedFormItem
|
||||
- key={arrKey !== undefined ? arrKey : Array.isArray(name) ? name.slice(-1)[0] : name}
|
||||
- name={arrName || fixedName}
|
||||
- rules={[getRequiredRule(forceNonRequired === false && !!required?.includes(getStringByName(name)), name)]}
|
||||
- validateTrigger="onBlur"
|
||||
- hasFeedback={designNewLayout ? { icons: feedbackIcons } : true}
|
||||
- >
|
||||
- <Flex gap={8} align="center">
|
||||
+ <Flex gap={8} align="center">
|
||||
+ <ResetedFormItem
|
||||
+ key={arrKey !== undefined ? arrKey : Array.isArray(name) ? name.slice(-1)[0] : name}
|
||||
+ name={arrName || fixedName}
|
||||
+ rules={[getRequiredRule(forceNonRequired === false && !!required?.includes(getStringByName(name)), name)]}
|
||||
+ validateTrigger="onBlur"
|
||||
+ hasFeedback={designNewLayout ? { icons: feedbackIcons } : true}
|
||||
+ style={{ flex: 1 }}
|
||||
+ >
|
||||
<Select
|
||||
mode={customProps.mode}
|
||||
placeholder="Select"
|
||||
@@ -277,13 +278,13 @@ export const FormListInput: FC<TFormListInputProps> = ({
|
||||
showSearch
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
- {relatedValueTooltip && (
|
||||
- <Tooltip title={relatedValueTooltip}>
|
||||
- <QuestionCircleOutlined />
|
||||
- </Tooltip>
|
||||
- )}
|
||||
- </Flex>
|
||||
- </ResetedFormItem>
|
||||
+ </ResetedFormItem>
|
||||
+ {relatedValueTooltip && (
|
||||
+ <Tooltip title={relatedValueTooltip}>
|
||||
+ <QuestionCircleOutlined />
|
||||
+ </Tooltip>
|
||||
+ )}
|
||||
+ </Flex>
|
||||
</HiddenContainer>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
diff --git a/src/components/organisms/DynamicComponents/molecules/SecretBase64Plain/SecretBase64Plain.tsx b/src/components/organisms/DynamicComponents/molecules/SecretBase64Plain/SecretBase64Plain.tsx
|
||||
--- a/src/components/organisms/DynamicComponents/molecules/SecretBase64Plain/SecretBase64Plain.tsx
|
||||
+++ b/src/components/organisms/DynamicComponents/molecules/SecretBase64Plain/SecretBase64Plain.tsx
|
||||
@@ -145,6 +145,12 @@
|
||||
<Styled.DisabledInput
|
||||
$hidden={effectiveHidden}
|
||||
onClick={e => handleInputClick(e, effectiveHidden, value)}
|
||||
+ onCopy={e => {
|
||||
+ if (!effectiveHidden) {
|
||||
+ e.preventDefault()
|
||||
+ e.clipboardData?.setData('text/plain', value)
|
||||
+ }
|
||||
+ }}
|
||||
value={shownValue}
|
||||
readOnly
|
||||
/>
|
||||
@@ -161,6 +167,12 @@
|
||||
<Styled.DisabledInput
|
||||
$hidden={effectiveHidden}
|
||||
onClick={e => handleInputClick(e, effectiveHidden, value)}
|
||||
+ onCopy={e => {
|
||||
+ if (!effectiveHidden) {
|
||||
+ e.preventDefault()
|
||||
+ e.clipboardData?.setData('text/plain', value)
|
||||
+ }
|
||||
+ }}
|
||||
value={shownValue}
|
||||
readOnly
|
||||
/>
|
||||
@@ -1,6 +1,6 @@
|
||||
{{- $brandingConfig := .Values._cluster.branding | default dict }}
|
||||
|
||||
{{- $tenantText := "v1.0.0-beta.6" }}
|
||||
{{- $tenantText := "v1.0.5" }}
|
||||
{{- $footerText := "Cozystack" }}
|
||||
{{- $titleText := "Cozystack Dashboard" }}
|
||||
{{- $logoText := "" }}
|
||||
|
||||
20
packages/system/dashboard/templates/flowschema.yaml
Normal file
20
packages/system/dashboard/templates/flowschema.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
apiVersion: flowcontrol.apiserver.k8s.io/v1
|
||||
kind: FlowSchema
|
||||
metadata:
|
||||
name: cozy-dashboard-exempt
|
||||
spec:
|
||||
matchingPrecedence: 2
|
||||
priorityLevelConfiguration:
|
||||
name: exempt
|
||||
rules:
|
||||
- subjects:
|
||||
- kind: ServiceAccount
|
||||
serviceAccount:
|
||||
name: incloud-web-web
|
||||
namespace: {{ .Release.Namespace }}
|
||||
resourceRules:
|
||||
- verbs: ["*"]
|
||||
apiGroups: ["*"]
|
||||
resources: ["*"]
|
||||
namespaces: ["*"]
|
||||
clusterScope: true
|
||||
@@ -136,7 +136,7 @@ spec:
|
||||
- name: CUSTOMIZATION_NAVIGATION_RESOURCE_PLURAL
|
||||
value: navigations
|
||||
- name: CUSTOMIZATION_SIDEBAR_FALLBACK_ID
|
||||
value: stock-project-api-table
|
||||
value: ""
|
||||
- name: CUSTOMIZATION_BREADCRUMBS_FALLBACK_ID
|
||||
value: stock-project-api-table
|
||||
- name: INSTANCES_API_GROUP
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
openapiUI:
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui:v1.0.0-beta.6@sha256:c333637673a9e878f6c4ed0fc96db55967bbcf94b2434d075b0f0c6fcfcf9eff
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui:v1.0.5@sha256:b95c6941991b2f5b5cb61e4b322431f89b3f064468ab3353cf68448143ced4a2
|
||||
openapiUIK8sBff:
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v1.0.0-beta.6@sha256:1b3ea6d4c7dbbe6a8def3b2807fffdfab2ac4afc39d7a846e57dd491fa168f92
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v1.0.5@sha256:a17f73592c4b37ac8dbb9697e2866bdea301ff4364e235bb58c665b5f41143c4
|
||||
tokenProxy:
|
||||
image: ghcr.io/cozystack/cozystack/token-proxy:v1.0.0-beta.6@sha256:2e280991e07853ea48f97b0a42946afffa10d03d6a83d41099ed83e6ffc94fdc
|
||||
image: ghcr.io/cozystack/cozystack/token-proxy:v1.0.5@sha256:2e280991e07853ea48f97b0a42946afffa10d03d6a83d41099ed83e6ffc94fdc
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
| kubeRbacProxy.args[2] | string | `"--logtostderr=true"` | |
|
||||
| kubeRbacProxy.args[3] | string | `"--v=0"` | |
|
||||
| kubeRbacProxy.image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
|
||||
| kubeRbacProxy.image.repository | string | `"gcr.io/kubebuilder/kube-rbac-proxy"` | Image repository |
|
||||
| kubeRbacProxy.image.tag | string | `"v0.16.0"` | Version of image |
|
||||
| kubeRbacProxy.image.repository | string | `"quay.io/brancz/kube-rbac-proxy"` | Image repository |
|
||||
| kubeRbacProxy.image.tag | string | `"v0.18.1"` | Version of image |
|
||||
| kubeRbacProxy.livenessProbe | object | `{}` | https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ |
|
||||
| kubeRbacProxy.readinessProbe | object | `{}` | https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ |
|
||||
| kubeRbacProxy.resources | object | `{"limits":{"cpu":"250m","memory":"128Mi"},"requests":{"cpu":"100m","memory":"64Mi"}}` | ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ |
|
||||
|
||||
@@ -98,13 +98,13 @@ kubeRbacProxy:
|
||||
image:
|
||||
|
||||
# -- Image repository
|
||||
repository: gcr.io/kubebuilder/kube-rbac-proxy
|
||||
repository: quay.io/brancz/kube-rbac-proxy
|
||||
|
||||
# -- Image pull policy
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# -- Version of image
|
||||
tag: v0.16.0
|
||||
tag: v0.18.1
|
||||
|
||||
args:
|
||||
- --secure-listen-address=0.0.0.0:8443
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/grafana-dashboards:v1.0.0-beta.6@sha256:7a3c9af59f8d74d5a23750bbc845c7de64610dbd4d4f84011e10be037b3ce2a0
|
||||
ghcr.io/cozystack/cozystack/grafana-dashboards:v1.0.5@sha256:7a3c9af59f8d74d5a23750bbc845c7de64610dbd4d4f84011e10be037b3ce2a0
|
||||
|
||||
@@ -3,7 +3,7 @@ kamaji:
|
||||
deploy: false
|
||||
image:
|
||||
pullPolicy: IfNotPresent
|
||||
tag: v1.0.0-beta.6@sha256:05f8e166dc94aadb74cd6448f6f96fbd2167057a559097516a41b8f53e434918
|
||||
tag: v1.0.5@sha256:914d04f7442f0faecf18f8282c192dee9fe244a711494a8c892e2f9e2ad415f7
|
||||
repository: ghcr.io/cozystack/cozystack/kamaji
|
||||
resources:
|
||||
limits:
|
||||
@@ -13,4 +13,4 @@ kamaji:
|
||||
cpu: 100m
|
||||
memory: 100Mi
|
||||
extraArgs:
|
||||
- --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v1.0.0-beta.6@sha256:05f8e166dc94aadb74cd6448f6f96fbd2167057a559097516a41b8f53e434918
|
||||
- --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v1.0.5@sha256:914d04f7442f0faecf18f8282c192dee9fe244a711494a8c892e2f9e2ad415f7
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{{- $host := index .Values._cluster "root-host" }}
|
||||
{{- $ingressHost := .Values.ingress.host | default (printf "keycloak.%s" $host) }}
|
||||
{{- $solver := (index .Values._cluster "solver") | default "http01" }}
|
||||
{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }}
|
||||
{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }}
|
||||
@@ -19,10 +20,10 @@ spec:
|
||||
ingressClassName: {{ $exposeIngress }}
|
||||
tls:
|
||||
- hosts:
|
||||
- keycloak.{{ $host }}
|
||||
- {{ $ingressHost }}
|
||||
secretName: web-tls
|
||||
rules:
|
||||
- host: keycloak.{{ $host }}
|
||||
- host: {{ $ingressHost }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{{- $host := index .Values._cluster "root-host" }}
|
||||
{{- $ingressHost := .Values.ingress.host | default (printf "keycloak.%s" $host) }}
|
||||
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }}
|
||||
|
||||
{{- $existingPassword := lookup "v1" "Secret" "cozy-keycloak" (printf "%s-credentials" .Release.Name) }}
|
||||
@@ -75,14 +76,18 @@ spec:
|
||||
{{- end }}
|
||||
- name: KC_METRICS_ENABLED
|
||||
value: "true"
|
||||
- name: KC_HEALTH_ENABLED
|
||||
value: "true"
|
||||
- name: KC_LOG_LEVEL
|
||||
value: "info"
|
||||
- name: KC_CACHE
|
||||
value: "ispn"
|
||||
- name: KC_CACHE_STACK
|
||||
value: "kubernetes"
|
||||
- name: KC_PROXY
|
||||
value: "edge"
|
||||
- name: KC_PROXY_HEADERS
|
||||
value: "xforwarded"
|
||||
- name: KC_HTTP_ENABLED
|
||||
value: "true"
|
||||
- name: KEYCLOAK_ADMIN
|
||||
value: admin
|
||||
- name: KEYCLOAK_ADMIN_PASSWORD
|
||||
@@ -120,23 +125,34 @@ spec:
|
||||
- name: KC_FEATURES
|
||||
value: "docker"
|
||||
- name: KC_HOSTNAME
|
||||
value: https://keycloak.{{ $host }}
|
||||
value: https://{{ $ingressHost }}
|
||||
- name: JAVA_OPTS_APPEND
|
||||
value: "-Djgroups.dns.query=keycloak-headless.cozy-keycloak.svc.{{ $clusterDomain }}"
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
- name: management
|
||||
containerPort: 9000
|
||||
protocol: TCP
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /health/ready
|
||||
port: management
|
||||
failureThreshold: 30
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 120
|
||||
path: /health/live
|
||||
port: management
|
||||
periodSeconds: 15
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 5
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /realms/master
|
||||
port: http
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 1
|
||||
path: /health/ready
|
||||
port: management
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
terminationGracePeriodSeconds: 60
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
image: quay.io/keycloak/keycloak:26.0.4
|
||||
|
||||
ingress:
|
||||
# Custom hostname for the Keycloak Ingress.
|
||||
# If set, this value will be used as the Ingress hostname (e.g., "auth.example.com").
|
||||
# If left empty, defaults to "keycloak.<root-host>" based on the cluster root-host setting.
|
||||
host: ""
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/affinity: "cookie"
|
||||
nginx.ingress.kubernetes.io/session-cookie-expires: "86400"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
portSecurity: true
|
||||
routes: ""
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v1.0.0-beta.6@sha256:8e964605efe54e73a94c84abec7dbb5a011c02ccece282bef8ae7b70fce3d217
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v1.0.5@sha256:fbbd24c757a9210e44b4fcb7b1b9f0135683090bd508836c569b9fc669fe356a
|
||||
ovnCentralName: ovn-central
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
portSecurity: true
|
||||
routes: ""
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v1.0.0-beta.6@sha256:e18f9fd679e38f65362a8d0042f25468272f6d081136ad47027168d8e7e07a4a
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v1.0.5@sha256:e18f9fd679e38f65362a8d0042f25468272f6d081136ad47027168d8e7e07a4a
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
storageClass: replicated
|
||||
csiDriver:
|
||||
image: ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:604561e23df1b8eb25c24cf73fd93c7aaa6d1e7c56affbbda5c6f0f83424e4b1
|
||||
image: ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:1c8c842277f45f189a5c645fcf7b2023c8ed7189f44029ce8b988019000da14c
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
lineageControllerWebhook:
|
||||
image: ghcr.io/cozystack/cozystack/lineage-controller-webhook:v1.0.0-beta.6@sha256:cf577e56ebc2b94205741d9c5b08f2983cec0811f0c2890edca8fdca22624de1
|
||||
image: ghcr.io/cozystack/cozystack/lineage-controller-webhook:v1.0.5@sha256:4cff89b0c2b23dd3f7ee5d751744057c29c95c299b6c6a0429e76fae882bf961
|
||||
debug: false
|
||||
localK8sAPIEndpoint:
|
||||
enabled: true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
piraeusServer:
|
||||
image:
|
||||
repository: ghcr.io/cozystack/cozystack/piraeus-server
|
||||
tag: 1.32.3@sha256:66eadfc98cd809d2b3c4e6fd631bcd0c4b4cd72a7fb819ac4a0cab7904280546
|
||||
tag: 1.32.3@sha256:aa97f39d90c0726b587f0a376504f13d1f308adeb42db7d98cec9ac7de237361
|
||||
# Talos-specific workarounds (disable for generic Linux like Ubuntu/Debian)
|
||||
talos:
|
||||
enabled: true
|
||||
@@ -13,4 +13,4 @@ linstor:
|
||||
linstorCSI:
|
||||
image:
|
||||
repository: ghcr.io/cozystack/cozystack/linstor-csi
|
||||
tag: v1.10.5@sha256:6e6cf48cb994f3918df946e02ec454ac64916678b3e60d78c136b431f1a26155
|
||||
tag: v1.10.5@sha256:7349a57e22224a641304594cb558e4f5f65bf01ffd28d9afc79d422607aac9b2
|
||||
|
||||
@@ -280,8 +280,8 @@ vmagent:
|
||||
cluster: cozystack
|
||||
remoteWrite:
|
||||
urls:
|
||||
- http://vminsert-shortterm.{{ .Values.global.target }}.svc.{{ (index .Values._cluster "cluster-domain") | default "cluster.local" }}:8480/insert/0/prometheus
|
||||
- http://vminsert-longterm.{{ .Values.global.target }}.svc.{{ (index .Values._cluster "cluster-domain") | default "cluster.local" }}:8480/insert/0/prometheus
|
||||
- http://vminsert-shortterm.{{ .Values.global.target }}.svc:8480/insert/0/prometheus
|
||||
- http://vminsert-longterm.{{ .Values.global.target }}.svc:8480/insert/0/prometheus
|
||||
extraArgs: {}
|
||||
|
||||
fluent-bit:
|
||||
@@ -344,7 +344,7 @@ fluent-bit:
|
||||
[OUTPUT]
|
||||
Name http
|
||||
Match kube.*
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc.{{ (index .Values._cluster "cluster-domain") | default "cluster.local" }}
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc
|
||||
port 9428
|
||||
compress gzip
|
||||
uri /insert/jsonline?_stream_fields=log_source,stream,kubernetes_pod_name,kubernetes_container_name,kubernetes_namespace_name&_msg_field=log&_time_field=date
|
||||
@@ -355,7 +355,7 @@ fluent-bit:
|
||||
[OUTPUT]
|
||||
Name http
|
||||
Match events.*
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc.{{ (index .Values._cluster "cluster-domain") | default "cluster.local" }}
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc
|
||||
port 9428
|
||||
compress gzip
|
||||
uri /insert/jsonline?_stream_fields=log_source,reason,meatdata_namespace,metadata_name&_msg_field=message&_time_field=date
|
||||
@@ -366,7 +366,7 @@ fluent-bit:
|
||||
[OUTPUT]
|
||||
Name http
|
||||
Match audit.*
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc.{{ (index .Values._cluster "cluster-domain") | default "cluster.local" }}
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc
|
||||
port 9428
|
||||
compress gzip
|
||||
uri /insert/jsonline?_stream_fields=log_source,stage,user_username,verb,requestUri&_msg_field=requestURI&_time_field=date
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
objectstorage:
|
||||
controller:
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v1.0.0-beta.6@sha256:b4c972769afda76c48b58e7acf0ac66a0abf16a622f245c60338f432872f640a"
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v1.0.5@sha256:e40e94f3014cfd04cce4230597315a1acfcca2daa8051b987614d0c05da6d928"
|
||||
|
||||
@@ -177,7 +177,7 @@ seaweedfs:
|
||||
bucketClassName: "seaweedfs"
|
||||
region: ""
|
||||
sidecar:
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.0-beta.6@sha256:235b194a531b70e266a10ef78d2955d19f5b659513f23d8b3cfbbc0dff7fc1c0"
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.5@sha256:2a3595cd88b30af55b2000d3ca204899beecef0012b0e0402754c3914aad1f7f"
|
||||
certificates:
|
||||
commonName: "SeaweedFS CA"
|
||||
ipAddresses: []
|
||||
|
||||
@@ -224,8 +224,8 @@ func buildPostProcessV3(kindSchemas map[string]string) func(*spec3.OpenAPI) (*sp
|
||||
base, ok1 := doc.Components.Schemas[baseRef]
|
||||
list, ok2 := doc.Components.Schemas[baseListRef]
|
||||
stat, ok3 := doc.Components.Schemas[baseStatusRef]
|
||||
if !(ok1 && ok2 && ok3) && len(kindSchemas) > 0 {
|
||||
return doc, fmt.Errorf("base Application* schemas not found")
|
||||
if !(ok1 && ok2 && ok3) {
|
||||
return doc, nil // not the apps GV — nothing to patch
|
||||
}
|
||||
|
||||
// Clone base schemas for each kind
|
||||
@@ -339,8 +339,8 @@ func buildPostProcessV2(kindSchemas map[string]string) func(*spec.Swagger) (*spe
|
||||
base, ok1 := defs[baseRef]
|
||||
list, ok2 := defs[baseListRef]
|
||||
stat, ok3 := defs[baseStatusRef]
|
||||
if !(ok1 && ok2 && ok3) && len(kindSchemas) > 0 {
|
||||
return sw, fmt.Errorf("base Application* schemas not found")
|
||||
if !(ok1 && ok2 && ok3) {
|
||||
return sw, nil // not the apps GV — nothing to patch
|
||||
}
|
||||
|
||||
for kind, raw := range kindSchemas {
|
||||
|
||||
Reference in New Issue
Block a user