From a5d3757c3620a229614d25fa492567e20cf2f327 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Fri, 2 Jan 2026 20:44:09 +0100 Subject: [PATCH 1/2] refactor: replace Helm lookup with valuesFrom mechanism Replace Helm lookup functions with FluxCD valuesFrom for passing configuration to HelmReleases. This eliminates the need for force reconcile controllers and provides cleaner config propagation. Changes: - Add Secret cozystack-values creation in platform and tenant charts - Modify cozystack-api to add valuesFrom, filter _ prefixed keys - Add valuesFrom validation in cozystack-controller - Add helper templates in cozy-lib for _cluster/_namespace access - Replace ConfigMap/Namespace lookups in 40+ Helm charts - Remove CozystackConfigReconciler and TenantHelmReconciler The Secret cozystack-values contains: - _cluster: data from cozystack, cozystack-branding, cozystack-scheduling ConfigMaps - _namespace: service references (etcd, host, ingress, monitoring, seaweedfs) Co-Authored-By: Claude Signed-off-by: Andrei Kvapil --- cmd/cozystack-controller/main.go | 16 -- ...ystackresourcedefinition_helmreconciler.go | 47 +++++- internal/controller/system_helm_reconciler.go | 140 --------------- internal/controller/tenant_helm_reconciler.go | 159 ------------------ .../apps/bucket/templates/bucketclaim.yaml | 3 +- .../apps/bucket/templates/helmrelease.yaml | 9 + .../apps/clickhouse/templates/chkeeper.yaml | 3 +- .../apps/clickhouse/templates/clickhouse.yaml | 3 +- .../apps/ferretdb/templates/postgres.yaml | 5 +- .../apps/foundationdb/templates/cluster.yaml | 3 +- .../apps/kubernetes/templates/cluster.yaml | 12 +- .../helmreleases/monitoring-agents.yaml | 3 +- .../helmreleases/vertical-pod-autoscaler.yaml | 6 +- .../apps/kubernetes/templates/ingress.yaml | 3 +- packages/apps/nats/templates/nats.yaml | 12 +- packages/apps/postgres/templates/db.yaml | 5 +- packages/apps/tenant/templates/etcd.yaml | 9 + packages/apps/tenant/templates/info.yaml | 9 + packages/apps/tenant/templates/ingress.yaml | 9 + .../apps/tenant/templates/keycloakgroups.yaml | 3 +- .../apps/tenant/templates/monitoring.yaml | 9 + packages/apps/tenant/templates/namespace.yaml | 85 +++++++--- packages/apps/tenant/templates/seaweedfs.yaml | 9 + .../virtual-machine/templates/_helpers.tpl | 5 +- .../apps/vm-instance/templates/_helpers.tpl | 5 +- packages/apps/vpn/templates/secret.yaml | 3 +- packages/core/platform/templates/apps.yaml | 41 +++++ .../core/platform/templates/helmreleases.yaml | 5 + .../core/platform/templates/namespaces.yaml | 22 +++ .../bootbox/templates/matchbox/ingress.yaml | 9 +- .../bootbox/templates/matchbox/machines.yaml | 7 +- .../extra/etcd/templates/etcd-cluster.yaml | 5 +- .../info/templates/dashboard-resourcemap.yaml | 3 +- packages/extra/info/templates/kubeconfig.yaml | 14 +- .../ingress/templates/nginx-ingress.yaml | 14 +- .../templates/alerta/alerta-db.yaml | 5 +- .../monitoring/templates/alerta/alerta.yaml | 9 +- .../monitoring/templates/grafana/db.yaml | 5 +- .../monitoring/templates/grafana/grafana.yaml | 9 +- .../templates/client/cosi-deployment.yaml | 4 +- .../extra/seaweedfs/templates/ingress.yaml | 8 +- .../extra/seaweedfs/templates/seaweedfs.yaml | 14 +- .../cozy-lib/templates/_cozyconfig.tpl | 127 +++++++++++++- packages/system/bucket/templates/ingress.yaml | 8 +- .../templates/cluster-issuers.yaml | 3 +- .../cozystack-api/templates/api-ingress.yaml | 7 +- .../system/dashboard/templates/configmap.yaml | 14 +- .../dashboard/templates/gatekeeper.yaml | 5 +- .../system/dashboard/templates/ingress.yaml | 9 +- .../dashboard/templates/keycloakclient.yaml | 5 +- .../dashboard/templates/nginx-config.yaml | 3 +- .../templates/configure-kk.yaml | 11 +- packages/system/keycloak/templates/db.yaml | 5 +- .../system/keycloak/templates/ingress.yaml | 7 +- packages/system/keycloak/templates/sts.yaml | 5 +- .../templates/cdi-uploadproxy-ingress.yaml | 7 +- .../templates/vm-exportproxy-ingress.yaml | 7 +- .../cozy-lib-tests/tests/quota_values.yaml | 3 + pkg/registry/apps/application/rest.go | 69 +++++++- 59 files changed, 543 insertions(+), 501 deletions(-) delete mode 100644 internal/controller/system_helm_reconciler.go delete mode 100644 internal/controller/tenant_helm_reconciler.go diff --git a/cmd/cozystack-controller/main.go b/cmd/cozystack-controller/main.go index 91889224..0e7199d3 100644 --- a/cmd/cozystack-controller/main.go +++ b/cmd/cozystack-controller/main.go @@ -200,22 +200,6 @@ func main() { os.Exit(1) } - if err = (&controller.TenantHelmReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "TenantHelmReconciler") - os.Exit(1) - } - - if err = (&controller.CozystackConfigReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "CozystackConfigReconciler") - os.Exit(1) - } - cozyAPIKind := "DaemonSet" if reconcileDeployment { cozyAPIKind = "Deployment" diff --git a/internal/controller/cozystackresourcedefinition_helmreconciler.go b/internal/controller/cozystackresourcedefinition_helmreconciler.go index c086b56f..57c8141f 100644 --- a/internal/controller/cozystackresourcedefinition_helmreconciler.go +++ b/internal/controller/cozystackresourcedefinition_helmreconciler.go @@ -97,7 +97,44 @@ func (r *CozystackResourceDefinitionHelmReconciler) updateHelmReleasesForCRD(ctx return nil } -// updateHelmReleaseChart updates the chart in HelmRelease based on CozystackResourceDefinition +// expectedValuesFrom returns the expected valuesFrom configuration for HelmReleases +func expectedValuesFrom() []helmv2.ValuesReference { + return []helmv2.ValuesReference{ + { + Kind: "Secret", + Name: "cozystack-values", + ValuesKey: "_namespace", + TargetPath: "_namespace", + Optional: false, + }, + { + Kind: "Secret", + Name: "cozystack-values", + ValuesKey: "_cluster", + TargetPath: "_cluster", + Optional: false, + }, + } +} + +// valuesFromEqual compares two ValuesReference slices +func valuesFromEqual(a, b []helmv2.ValuesReference) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i].Kind != b[i].Kind || + a[i].Name != b[i].Name || + a[i].ValuesKey != b[i].ValuesKey || + a[i].TargetPath != b[i].TargetPath || + a[i].Optional != b[i].Optional { + return false + } + } + return true +} + +// updateHelmReleaseChart updates the chart and valuesFrom in HelmRelease based on CozystackResourceDefinition func (r *CozystackResourceDefinitionHelmReconciler) updateHelmReleaseChart(ctx context.Context, hr *helmv2.HelmRelease, crd *cozyv1alpha1.CozystackResourceDefinition) error { logger := log.FromContext(ctx) hrCopy := hr.DeepCopy() @@ -154,6 +191,14 @@ func (r *CozystackResourceDefinitionHelmReconciler) updateHelmReleaseChart(ctx c } } + // Check and update valuesFrom configuration + expected := expectedValuesFrom() + if !valuesFromEqual(hrCopy.Spec.ValuesFrom, expected) { + logger.V(4).Info("Updating HelmRelease valuesFrom", "name", hr.Name, "namespace", hr.Namespace) + hrCopy.Spec.ValuesFrom = expected + updated = true + } + if updated { logger.V(4).Info("Updating HelmRelease chart", "name", hr.Name, "namespace", hr.Namespace) if err := r.Update(ctx, hrCopy); err != nil { diff --git a/internal/controller/system_helm_reconciler.go b/internal/controller/system_helm_reconciler.go deleted file mode 100644 index 6e40027c..00000000 --- a/internal/controller/system_helm_reconciler.go +++ /dev/null @@ -1,140 +0,0 @@ -package controller - -import ( - "context" - "crypto/sha256" - "encoding/hex" - "fmt" - "sort" - "time" - - helmv2 "github.com/fluxcd/helm-controller/api/v2" - corev1 "k8s.io/api/core/v1" - kerrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/predicate" -) - -type CozystackConfigReconciler struct { - client.Client - Scheme *runtime.Scheme -} - -var configMapNames = []string{"cozystack", "cozystack-branding", "cozystack-scheduling"} - -const configMapNamespace = "cozy-system" -const digestAnnotation = "cozystack.io/cozy-config-digest" -const forceReconcileKey = "reconcile.fluxcd.io/forceAt" -const requestedAt = "reconcile.fluxcd.io/requestedAt" - -func (r *CozystackConfigReconciler) Reconcile(ctx context.Context, _ ctrl.Request) (ctrl.Result, error) { - log := log.FromContext(ctx) - time.Sleep(2 * time.Second) - - digest, err := r.computeDigest(ctx) - if err != nil { - log.Error(err, "failed to compute config digest") - return ctrl.Result{}, nil - } - - var helmList helmv2.HelmReleaseList - if err := r.List(ctx, &helmList); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to list HelmReleases: %w", err) - } - - now := time.Now().Format(time.RFC3339Nano) - updated := 0 - - for _, hr := range helmList.Items { - isSystemApp := hr.Labels["cozystack.io/system-app"] == "true" - isTenantRoot := hr.Namespace == "tenant-root" && hr.Name == "tenant-root" - if !isSystemApp && !isTenantRoot { - continue - } - patchTarget := hr.DeepCopy() - - if hr.Annotations == nil { - hr.Annotations = map[string]string{} - } - - if hr.Annotations[digestAnnotation] == digest { - continue - } - patchTarget.Annotations[digestAnnotation] = digest - patchTarget.Annotations[forceReconcileKey] = now - patchTarget.Annotations[requestedAt] = now - - patch := client.MergeFrom(hr.DeepCopy()) - if err := r.Patch(ctx, patchTarget, patch); err != nil { - log.Error(err, "failed to patch HelmRelease", "name", hr.Name, "namespace", hr.Namespace) - continue - } - updated++ - log.Info("patched HelmRelease with new config digest", "name", hr.Name, "namespace", hr.Namespace) - } - - log.Info("finished reconciliation", "updatedHelmReleases", updated) - return ctrl.Result{}, nil -} - -func (r *CozystackConfigReconciler) computeDigest(ctx context.Context) (string, error) { - hash := sha256.New() - - for _, name := range configMapNames { - var cm corev1.ConfigMap - err := r.Get(ctx, client.ObjectKey{Namespace: configMapNamespace, Name: name}, &cm) - if err != nil { - if kerrors.IsNotFound(err) { - continue // ignore missing - } - return "", err - } - - // Sort keys for consistent hashing - var keys []string - for k := range cm.Data { - keys = append(keys, k) - } - sort.Strings(keys) - - for _, k := range keys { - v := cm.Data[k] - fmt.Fprintf(hash, "%s:%s=%s\n", name, k, v) - } - } - - return hex.EncodeToString(hash.Sum(nil)), nil -} - -func (r *CozystackConfigReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - WithEventFilter(predicate.Funcs{ - UpdateFunc: func(e event.UpdateEvent) bool { - cm, ok := e.ObjectNew.(*corev1.ConfigMap) - return ok && cm.Namespace == configMapNamespace && contains(configMapNames, cm.Name) - }, - CreateFunc: func(e event.CreateEvent) bool { - cm, ok := e.Object.(*corev1.ConfigMap) - return ok && cm.Namespace == configMapNamespace && contains(configMapNames, cm.Name) - }, - DeleteFunc: func(e event.DeleteEvent) bool { - cm, ok := e.Object.(*corev1.ConfigMap) - return ok && cm.Namespace == configMapNamespace && contains(configMapNames, cm.Name) - }, - }). - For(&corev1.ConfigMap{}). - Complete(r) -} - -func contains(slice []string, val string) bool { - for _, s := range slice { - if s == val { - return true - } - } - return false -} diff --git a/internal/controller/tenant_helm_reconciler.go b/internal/controller/tenant_helm_reconciler.go deleted file mode 100644 index 28b4ad16..00000000 --- a/internal/controller/tenant_helm_reconciler.go +++ /dev/null @@ -1,159 +0,0 @@ -package controller - -import ( - "context" - "fmt" - "strings" - "time" - - e "errors" - - helmv2 "github.com/fluxcd/helm-controller/api/v2" - "gopkg.in/yaml.v2" - corev1 "k8s.io/api/core/v1" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" -) - -type TenantHelmReconciler struct { - client.Client - Scheme *runtime.Scheme -} - -func (r *TenantHelmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := log.FromContext(ctx) - time.Sleep(2 * time.Second) - - hr := &helmv2.HelmRelease{} - if err := r.Get(ctx, req.NamespacedName, hr); err != nil { - if errors.IsNotFound(err) { - return ctrl.Result{}, nil - } - logger.Error(err, "unable to fetch HelmRelease") - return ctrl.Result{}, err - } - - if !strings.HasPrefix(hr.Name, "tenant-") { - return ctrl.Result{}, nil - } - - if len(hr.Status.Conditions) == 0 || hr.Status.Conditions[0].Type != "Ready" { - return ctrl.Result{}, nil - } - - if len(hr.Status.History) == 0 { - logger.Info("no history in HelmRelease status", "name", hr.Name) - return ctrl.Result{}, nil - } - - if hr.Status.History[0].Status != "deployed" { - return ctrl.Result{}, nil - } - - newDigest := hr.Status.History[0].Digest - var hrList helmv2.HelmReleaseList - childNamespace := getChildNamespace(hr.Namespace, hr.Name) - if childNamespace == "tenant-root" && hr.Name == "tenant-root" { - if hr.Spec.Values == nil { - logger.Error(e.New("hr.Spec.Values is nil"), "cant annotate tenant-root ns") - return ctrl.Result{}, nil - } - err := annotateTenantRootNs(*hr.Spec.Values, r.Client) - if err != nil { - logger.Error(err, "cant annotate tenant-root ns") - return ctrl.Result{}, nil - } - logger.Info("namespace 'tenant-root' annotated") - } - - if err := r.List(ctx, &hrList, client.InNamespace(childNamespace)); err != nil { - logger.Error(err, "unable to list HelmReleases in namespace", "namespace", hr.Name) - return ctrl.Result{}, err - } - - for _, item := range hrList.Items { - if item.Name == hr.Name { - continue - } - oldDigest := item.GetAnnotations()["cozystack.io/tenant-config-digest"] - if oldDigest == newDigest { - continue - } - patchTarget := item.DeepCopy() - - if patchTarget.Annotations == nil { - patchTarget.Annotations = map[string]string{} - } - ts := time.Now().Format(time.RFC3339Nano) - - patchTarget.Annotations["cozystack.io/tenant-config-digest"] = newDigest - patchTarget.Annotations["reconcile.fluxcd.io/forceAt"] = ts - patchTarget.Annotations["reconcile.fluxcd.io/requestedAt"] = ts - - patch := client.MergeFrom(item.DeepCopy()) - if err := r.Patch(ctx, patchTarget, patch); err != nil { - logger.Error(err, "failed to patch HelmRelease", "name", patchTarget.Name) - continue - } - - logger.Info("patched HelmRelease with new digest", "name", patchTarget.Name, "digest", newDigest, "version", hr.Status.History[0].Version) - } - - return ctrl.Result{}, nil -} - -func (r *TenantHelmReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&helmv2.HelmRelease{}). - Complete(r) -} - -func getChildNamespace(currentNamespace, hrName string) string { - tenantName := strings.TrimPrefix(hrName, "tenant-") - - switch { - case currentNamespace == "tenant-root" && hrName == "tenant-root": - // 1) root tenant inside root namespace - return "tenant-root" - - case currentNamespace == "tenant-root": - // 2) any other tenant in root namespace - return fmt.Sprintf("tenant-%s", tenantName) - - default: - // 3) tenant in a dedicated namespace - return fmt.Sprintf("%s-%s", currentNamespace, tenantName) - } -} - -func annotateTenantRootNs(values apiextensionsv1.JSON, c client.Client) error { - var data map[string]interface{} - if err := yaml.Unmarshal(values.Raw, &data); err != nil { - return fmt.Errorf("failed to parse HelmRelease values: %w", err) - } - - host, ok := data["host"].(string) - if !ok || host == "" { - return fmt.Errorf("host field not found or not a string") - } - - var ns corev1.Namespace - if err := c.Get(context.TODO(), client.ObjectKey{Name: "tenant-root"}, &ns); err != nil { - return fmt.Errorf("failed to get namespace tenant-root: %w", err) - } - - if ns.Annotations == nil { - ns.Annotations = map[string]string{} - } - ns.Annotations["namespace.cozystack.io/host"] = host - - if err := c.Update(context.TODO(), &ns); err != nil { - return fmt.Errorf("failed to update namespace: %w", err) - } - - return nil -} diff --git a/packages/apps/bucket/templates/bucketclaim.yaml b/packages/apps/bucket/templates/bucketclaim.yaml index cebf95b4..5cfdc1c1 100644 --- a/packages/apps/bucket/templates/bucketclaim.yaml +++ b/packages/apps/bucket/templates/bucketclaim.yaml @@ -1,5 +1,4 @@ -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $seaweedfs := index $myNS.metadata.annotations "namespace.cozystack.io/seaweedfs" }} +{{- $seaweedfs := .Values._namespace.seaweedfs }} apiVersion: objectstorage.k8s.io/v1alpha1 kind: BucketClaim metadata: diff --git a/packages/apps/bucket/templates/helmrelease.yaml b/packages/apps/bucket/templates/helmrelease.yaml index 45959572..8a57760e 100644 --- a/packages/apps/bucket/templates/helmrelease.yaml +++ b/packages/apps/bucket/templates/helmrelease.yaml @@ -21,5 +21,14 @@ spec: force: true remediation: retries: -1 + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster + - kind: Secret + name: cozystack-values + valuesKey: _namespace + targetPath: _namespace values: bucketName: {{ .Release.Name }} diff --git a/packages/apps/clickhouse/templates/chkeeper.yaml b/packages/apps/clickhouse/templates/chkeeper.yaml index 54824a44..42d88af4 100644 --- a/packages/apps/clickhouse/templates/chkeeper.yaml +++ b/packages/apps/clickhouse/templates/chkeeper.yaml @@ -1,5 +1,4 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }} +{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} {{- if .Values.clickhouseKeeper.enabled }} apiVersion: "clickhouse-keeper.altinity.com/v1" diff --git a/packages/apps/clickhouse/templates/clickhouse.yaml b/packages/apps/clickhouse/templates/clickhouse.yaml index 47e5b56a..b645260b 100644 --- a/packages/apps/clickhouse/templates/clickhouse.yaml +++ b/packages/apps/clickhouse/templates/clickhouse.yaml @@ -1,5 +1,4 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }} +{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} {{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-credentials" .Release.Name) }} {{- $passwords := dict }} {{- $users := .Values.users }} diff --git a/packages/apps/ferretdb/templates/postgres.yaml b/packages/apps/ferretdb/templates/postgres.yaml index 4d1d8e29..f1b1ce2c 100644 --- a/packages/apps/ferretdb/templates/postgres.yaml +++ b/packages/apps/ferretdb/templates/postgres.yaml @@ -50,9 +50,8 @@ spec: postgresUID: 999 postgresGID: 999 enableSuperuserAccess: true - {{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} - {{- if $configMap }} - {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} + {{- if .Values._cluster.scheduling }} + {{- $rawConstraints := get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }} {{- if $rawConstraints }} {{- $rawConstraints | fromYaml | toYaml | nindent 2 }} labelSelector: diff --git a/packages/apps/foundationdb/templates/cluster.yaml b/packages/apps/foundationdb/templates/cluster.yaml index 06992cb5..be804233 100644 --- a/packages/apps/foundationdb/templates/cluster.yaml +++ b/packages/apps/foundationdb/templates/cluster.yaml @@ -1,5 +1,4 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" | default (dict "data" (dict)) }} -{{- $clusterDomain := index $cozyConfig.data "cluster-domain" | default "cozy.local" }} +{{- $clusterDomain := index .Values._cluster "cluster-domain" | default "cozy.local" }} --- apiVersion: apps.foundationdb.org/v1beta2 kind: FoundationDBCluster diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml index 7edd07f5..6acfb107 100644 --- a/packages/apps/kubernetes/templates/cluster.yaml +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -1,7 +1,6 @@ -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $etcd := index $myNS.metadata.annotations "namespace.cozystack.io/etcd" }} -{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- $etcd := .Values._namespace.etcd }} +{{- $ingress := .Values._namespace.ingress }} +{{- $host := .Values._namespace.host }} {{- $kubevirtmachinetemplateNames := list }} {{- define "kubevirtmachinetemplate" -}} spec: @@ -31,9 +30,8 @@ spec: {{- end }} cluster.x-k8s.io/deployment-name: {{ $.Release.Name }}-{{ .groupName }} spec: - {{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} - {{- if $configMap }} - {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} + {{- if .Values._cluster.scheduling }} + {{- $rawConstraints := get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }} {{- if $rawConstraints }} {{- $rawConstraints | fromYaml | toYaml | nindent 10 }} labelSelector: diff --git a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml index cf93f233..73c3a368 100644 --- a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml @@ -1,5 +1,4 @@ -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $targetTenant := index $myNS.metadata.annotations "namespace.cozystack.io/monitoring" }} +{{- $targetTenant := .Values._namespace.monitoring }} {{- if .Values.addons.monitoringAgents.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml index 8b615c9c..8a62288d 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml @@ -1,8 +1,6 @@ {{- define "cozystack.defaultVPAValues" -}} -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }} -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $targetTenant := index $myNS.metadata.annotations "namespace.cozystack.io/monitoring" }} +{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} +{{- $targetTenant := .Values._namespace.monitoring }} vpaForVPA: false vertical-pod-autoscaler: recommender: diff --git a/packages/apps/kubernetes/templates/ingress.yaml b/packages/apps/kubernetes/templates/ingress.yaml index 8dd244cb..7993dba8 100644 --- a/packages/apps/kubernetes/templates/ingress.yaml +++ b/packages/apps/kubernetes/templates/ingress.yaml @@ -1,5 +1,4 @@ -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} +{{- $ingress := .Values._namespace.ingress }} {{- if and (eq .Values.addons.ingressNginx.exposeMethod "Proxied") .Values.addons.ingressNginx.hosts }} --- apiVersion: networking.k8s.io/v1 diff --git a/packages/apps/nats/templates/nats.yaml b/packages/apps/nats/templates/nats.yaml index b05c87b5..b41c1574 100644 --- a/packages/apps/nats/templates/nats.yaml +++ b/packages/apps/nats/templates/nats.yaml @@ -1,5 +1,4 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }} +{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} {{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-credentials" .Release.Name) }} {{- $passwords := dict }} @@ -53,6 +52,15 @@ spec: force: true remediation: retries: -1 + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster + - kind: Secret + name: cozystack-values + valuesKey: _namespace + targetPath: _namespace values: nats: container: diff --git a/packages/apps/postgres/templates/db.yaml b/packages/apps/postgres/templates/db.yaml index 92fb34c6..7557c436 100644 --- a/packages/apps/postgres/templates/db.yaml +++ b/packages/apps/postgres/templates/db.yaml @@ -46,9 +46,8 @@ spec: imageName: ghcr.io/cloudnative-pg/postgresql:{{ include "postgres.versionMap" $ | trimPrefix "v" }} enableSuperuserAccess: true - {{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} - {{- if $configMap }} - {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} + {{- if .Values._cluster.scheduling }} + {{- $rawConstraints := get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }} {{- if $rawConstraints }} {{- $rawConstraints | fromYaml | toYaml | nindent 2 }} labelSelector: diff --git a/packages/apps/tenant/templates/etcd.yaml b/packages/apps/tenant/templates/etcd.yaml index 8cd720cc..4da22fb7 100644 --- a/packages/apps/tenant/templates/etcd.yaml +++ b/packages/apps/tenant/templates/etcd.yaml @@ -31,4 +31,13 @@ spec: force: true remediation: retries: -1 + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster + - kind: Secret + name: cozystack-values + valuesKey: _namespace + targetPath: _namespace {{- end }} diff --git a/packages/apps/tenant/templates/info.yaml b/packages/apps/tenant/templates/info.yaml index 4a66e422..e1281ebb 100644 --- a/packages/apps/tenant/templates/info.yaml +++ b/packages/apps/tenant/templates/info.yaml @@ -30,3 +30,12 @@ spec: force: true remediation: retries: -1 + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster + - kind: Secret + name: cozystack-values + valuesKey: _namespace + targetPath: _namespace diff --git a/packages/apps/tenant/templates/ingress.yaml b/packages/apps/tenant/templates/ingress.yaml index beb07342..c9c791f1 100644 --- a/packages/apps/tenant/templates/ingress.yaml +++ b/packages/apps/tenant/templates/ingress.yaml @@ -31,4 +31,13 @@ spec: force: true remediation: retries: -1 + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster + - kind: Secret + name: cozystack-values + valuesKey: _namespace + targetPath: _namespace {{- end }} diff --git a/packages/apps/tenant/templates/keycloakgroups.yaml b/packages/apps/tenant/templates/keycloakgroups.yaml index 59288ca4..9e25e60d 100644 --- a/packages/apps/tenant/templates/keycloakgroups.yaml +++ b/packages/apps/tenant/templates/keycloakgroups.yaml @@ -1,5 +1,4 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $oidcEnabled := index $cozyConfig.data "oidc-enabled" }} +{{- $oidcEnabled := index .Values._cluster "oidc-enabled" }} {{- if eq $oidcEnabled "true" }} {{- if .Capabilities.APIVersions.Has "v1.edp.epam.com/v1" }} apiVersion: v1.edp.epam.com/v1 diff --git a/packages/apps/tenant/templates/monitoring.yaml b/packages/apps/tenant/templates/monitoring.yaml index 4986fc21..3b0536de 100644 --- a/packages/apps/tenant/templates/monitoring.yaml +++ b/packages/apps/tenant/templates/monitoring.yaml @@ -31,4 +31,13 @@ spec: force: true remediation: retries: -1 + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster + - kind: Secret + name: cozystack-values + valuesKey: _namespace + targetPath: _namespace {{- end }} diff --git a/packages/apps/tenant/templates/namespace.yaml b/packages/apps/tenant/templates/namespace.yaml index d97ebf42..6c94a87f 100644 --- a/packages/apps/tenant/templates/namespace.yaml +++ b/packages/apps/tenant/templates/namespace.yaml @@ -1,46 +1,63 @@ -{{- define "cozystack.namespace-anotations" }} -{{- $context := index . 0 }} -{{- $existingNS := index . 1 }} -{{- range $x := list "etcd" "monitoring" "ingress" "seaweedfs" }} -{{- if (index $context.Values $x) }} -namespace.cozystack.io/{{ $x }}: "{{ include "tenant.name" $context }}" -{{- else }} -namespace.cozystack.io/{{ $x }}: "{{ index $existingNS.metadata.annotations (printf "namespace.cozystack.io/%s" $x) | required (printf "namespace %s has no namespace.cozystack.io/%s annotation" $context.Release.Namespace $x) }}" -{{- end }} -{{- end }} -{{- end }} - +{{/* Lookup for namespace uid (needed for ownerReferences) */}} {{- $existingNS := lookup "v1" "Namespace" "" .Release.Namespace }} {{- if not $existingNS }} {{- fail (printf "error lookup existing namespace: %s" .Release.Namespace) }} {{- end }} {{- if ne (include "tenant.name" .) "tenant-root" }} +{{/* Compute namespace values once for use in both Secret and labels */}} +{{- $tenantName := include "tenant.name" . }} +{{- $parentNamespace := .Values._namespace | default dict }} +{{- $parentHost := $parentNamespace.host | default "" }} + +{{/* Compute host */}} +{{- $computedHost := "" }} +{{- if .Values.host }} +{{- $computedHost = .Values.host }} +{{- else if $parentHost }} +{{- $computedHost = printf "%s.%s" (splitList "-" $tenantName | last) $parentHost }} +{{- end }} + +{{/* Compute service references */}} +{{- $etcd := $parentNamespace.etcd | default "" }} +{{- if .Values.etcd }} +{{- $etcd = $tenantName }} +{{- end }} + +{{- $ingress := $parentNamespace.ingress | default "" }} +{{- if .Values.ingress }} +{{- $ingress = $tenantName }} +{{- end }} + +{{- $monitoring := $parentNamespace.monitoring | default "" }} +{{- if .Values.monitoring }} +{{- $monitoring = $tenantName }} +{{- end }} + +{{- $seaweedfs := $parentNamespace.seaweedfs | default "" }} +{{- if .Values.seaweedfs }} +{{- $seaweedfs = $tenantName }} +{{- end }} --- apiVersion: v1 kind: Namespace metadata: - name: {{ include "tenant.name" . }} + name: {{ $tenantName }} {{- if hasPrefix "tenant-" .Release.Namespace }} - annotations: - {{- if .Values.host }} - namespace.cozystack.io/host: "{{ .Values.host }}" - {{- else }} - {{ $parentHost := index $existingNS.metadata.annotations "namespace.cozystack.io/host" | required (printf "namespace %s has no namespace.cozystack.io/host annotation" .Release.Namespace) }} - namespace.cozystack.io/host: "{{ splitList "-" (include "tenant.name" .) | last }}.{{ $parentHost }}" - {{- end }} - {{- include "cozystack.namespace-anotations" (list . $existingNS) | nindent 4 }} labels: - tenant.cozystack.io/{{ include "tenant.name" $ }}: "" - {{- if hasPrefix "tenant-" .Release.Namespace }} + tenant.cozystack.io/{{ $tenantName }}: "" {{- $parts := splitList "-" .Release.Namespace }} {{- range $i, $v := $parts }} {{- if ne $i 0 }} tenant.cozystack.io/{{ join "-" (slice $parts 0 (add $i 1)) }}: "" {{- end }} {{- end }} - {{- end }} - {{- include "cozystack.namespace-anotations" (list $ $existingNS) | nindent 4 }} + {{/* Labels for network policies */}} + namespace.cozystack.io/etcd: {{ $etcd | quote }} + namespace.cozystack.io/ingress: {{ $ingress | quote }} + namespace.cozystack.io/monitoring: {{ $monitoring | quote }} + namespace.cozystack.io/seaweedfs: {{ $seaweedfs | quote }} + namespace.cozystack.io/host: {{ $computedHost | quote }} alpha.kubevirt.io/auto-memory-limits-ratio: "1.0" ownerReferences: - apiVersion: v1 @@ -50,4 +67,22 @@ metadata: name: {{ .Release.Namespace }} uid: {{ $existingNS.metadata.uid }} {{- end }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: cozystack-values + namespace: {{ $tenantName }} + labels: + reconcile.fluxcd.io/watch: Enabled +type: Opaque +stringData: + _cluster: | + {{- .Values._cluster | toYaml | nindent 4 }} + _namespace: | + etcd: {{ $etcd | quote }} + ingress: {{ $ingress | quote }} + monitoring: {{ $monitoring | quote }} + seaweedfs: {{ $seaweedfs | quote }} + host: {{ $computedHost | quote }} {{- end }} diff --git a/packages/apps/tenant/templates/seaweedfs.yaml b/packages/apps/tenant/templates/seaweedfs.yaml index 9a714b79..be768571 100644 --- a/packages/apps/tenant/templates/seaweedfs.yaml +++ b/packages/apps/tenant/templates/seaweedfs.yaml @@ -31,4 +31,13 @@ spec: force: true remediation: retries: -1 + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster + - kind: Secret + name: cozystack-values + valuesKey: _namespace + targetPath: _namespace {{- end }} diff --git a/packages/apps/virtual-machine/templates/_helpers.tpl b/packages/apps/virtual-machine/templates/_helpers.tpl index 7b6929ac..e65cad9d 100644 --- a/packages/apps/virtual-machine/templates/_helpers.tpl +++ b/packages/apps/virtual-machine/templates/_helpers.tpl @@ -74,9 +74,8 @@ Generate a stable UUID for cloud-init re-initialization upon upgrade. Node Affinity for Windows VMs */}} {{- define "virtual-machine.nodeAffinity" -}} -{{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" -}} -{{- if $configMap -}} -{{- $dedicatedNodesForWindowsVMs := get $configMap.data "dedicatedNodesForWindowsVMs" -}} +{{- if .Values._cluster.scheduling -}} +{{- $dedicatedNodesForWindowsVMs := get .Values._cluster.scheduling "dedicatedNodesForWindowsVMs" -}} {{- if eq $dedicatedNodesForWindowsVMs "true" -}} {{- $isWindows := hasPrefix "windows" (toString .Values.instanceProfile) -}} affinity: diff --git a/packages/apps/vm-instance/templates/_helpers.tpl b/packages/apps/vm-instance/templates/_helpers.tpl index 7b6929ac..e65cad9d 100644 --- a/packages/apps/vm-instance/templates/_helpers.tpl +++ b/packages/apps/vm-instance/templates/_helpers.tpl @@ -74,9 +74,8 @@ Generate a stable UUID for cloud-init re-initialization upon upgrade. Node Affinity for Windows VMs */}} {{- define "virtual-machine.nodeAffinity" -}} -{{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" -}} -{{- if $configMap -}} -{{- $dedicatedNodesForWindowsVMs := get $configMap.data "dedicatedNodesForWindowsVMs" -}} +{{- if .Values._cluster.scheduling -}} +{{- $dedicatedNodesForWindowsVMs := get .Values._cluster.scheduling "dedicatedNodesForWindowsVMs" -}} {{- if eq $dedicatedNodesForWindowsVMs "true" -}} {{- $isWindows := hasPrefix "windows" (toString .Values.instanceProfile) -}} affinity: diff --git a/packages/apps/vpn/templates/secret.yaml b/packages/apps/vpn/templates/secret.yaml index 79960096..3ef4ac4b 100644 --- a/packages/apps/vpn/templates/secret.yaml +++ b/packages/apps/vpn/templates/secret.yaml @@ -1,5 +1,4 @@ -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- $host := .Values._namespace.host }} {{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-vpn" .Release.Name) }} {{- $accessKeys := list }} {{- $passwords := dict }} diff --git a/packages/core/platform/templates/apps.yaml b/packages/core/platform/templates/apps.yaml index 514dcffb..2477fc17 100644 --- a/packages/core/platform/templates/apps.yaml +++ b/packages/core/platform/templates/apps.yaml @@ -1,4 +1,6 @@ {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} +{{- $cozystackBranding := lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} +{{- $cozystackScheduling := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} {{- $bundleName := index $cozyConfig.data "bundle-name" }} {{- $bundle := tpl (.Files.Get (printf "bundles/%s.yaml" $bundleName)) . | fromYaml }} {{- $host := "example.org" }} @@ -22,6 +24,8 @@ kind: Namespace metadata: annotations: helm.sh/resource-policy: keep + labels: + tenant.cozystack.io/tenant-root: "" namespace.cozystack.io/etcd: tenant-root namespace.cozystack.io/monitoring: tenant-root namespace.cozystack.io/ingress: tenant-root @@ -29,6 +33,32 @@ metadata: namespace.cozystack.io/host: "{{ $host }}" name: tenant-root --- +apiVersion: v1 +kind: Secret +metadata: + name: cozystack-values + namespace: tenant-root + labels: + reconcile.fluxcd.io/watch: Enabled +type: Opaque +stringData: + _cluster: | + {{- $cozyConfig.data | toYaml | nindent 4 }} + {{- with $cozystackBranding.data }} + branding: + {{- . | toYaml | nindent 6 }} + {{- end }} + {{- with $cozystackScheduling.data }} + scheduling: + {{- . | toYaml | nindent 6 }} + {{- end }} + _namespace: | + etcd: tenant-root + monitoring: tenant-root + ingress: tenant-root + seaweedfs: tenant-root + host: {{ $host | quote }} +--- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -56,6 +86,17 @@ spec: kind: HelmRepository name: cozystack-apps namespace: cozy-public + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _namespace + targetPath: _namespace + optional: false + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster + optional: false values: host: "{{ $host }}" dependsOn: diff --git a/packages/core/platform/templates/helmreleases.yaml b/packages/core/platform/templates/helmreleases.yaml index 6ed61ed8..83ab18ea 100644 --- a/packages/core/platform/templates/helmreleases.yaml +++ b/packages/core/platform/templates/helmreleases.yaml @@ -83,6 +83,11 @@ spec: values: {{- toYaml . | nindent 4}} {{- end }} + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster {{- with $x.dependsOn }} dependsOn: diff --git a/packages/core/platform/templates/namespaces.yaml b/packages/core/platform/templates/namespaces.yaml index 11d00553..a4ed5135 100644 --- a/packages/core/platform/templates/namespaces.yaml +++ b/packages/core/platform/templates/namespaces.yaml @@ -1,4 +1,6 @@ {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} +{{- $cozystackBranding := lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} +{{- $cozystackScheduling := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} {{- $bundleName := index $cozyConfig.data "bundle-name" }} {{- $bundle := tpl (.Files.Get (printf "bundles/%s.yaml" $bundleName)) . | fromYaml }} {{- $disabledComponents := splitList "," ((index $cozyConfig.data "bundle-disable") | default "") }} @@ -37,4 +39,24 @@ metadata: pod-security.kubernetes.io/enforce: privileged {{- end }} name: {{ $namespace }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: cozystack-values + namespace: {{ $namespace }} + labels: + reconcile.fluxcd.io/watch: Enabled +type: Opaque +stringData: + _cluster: | + {{- $cozyConfig.data | toYaml | nindent 4 }} + {{- with $cozystackBranding.data }} + branding: + {{- . | toYaml | nindent 6 }} + {{- end }} + {{- with $cozystackScheduling.data }} + scheduling: + {{- . | toYaml | nindent 6 }} + {{- end }} {{- end }} diff --git a/packages/extra/bootbox/templates/matchbox/ingress.yaml b/packages/extra/bootbox/templates/matchbox/ingress.yaml index 31de7716..fa62165b 100644 --- a/packages/extra/bootbox/templates/matchbox/ingress.yaml +++ b/packages/extra/bootbox/templates/matchbox/ingress.yaml @@ -1,9 +1,6 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} - -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} +{{- $ingress := .Values._namespace.ingress }} +{{- $host := .Values._namespace.host }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: diff --git a/packages/extra/bootbox/templates/matchbox/machines.yaml b/packages/extra/bootbox/templates/matchbox/machines.yaml index e2733b89..a52c4b40 100644 --- a/packages/extra/bootbox/templates/matchbox/machines.yaml +++ b/packages/extra/bootbox/templates/matchbox/machines.yaml @@ -1,9 +1,4 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} - -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- $host := .Values._namespace.host }} {{ range $m := .Values.machines }} --- diff --git a/packages/extra/etcd/templates/etcd-cluster.yaml b/packages/extra/etcd/templates/etcd-cluster.yaml index 017a3178..a26ae173 100644 --- a/packages/extra/etcd/templates/etcd-cluster.yaml +++ b/packages/extra/etcd/templates/etcd-cluster.yaml @@ -49,10 +49,9 @@ spec: {{- with .Values.resources }} resources: {{- include "cozy-lib.resources.sanitize" (list . $) | nindent 10 }} {{- end }} - {{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} {{- $rawConstraints := "" }} - {{- if $configMap }} - {{- $rawConstraints = get $configMap.data "globalAppTopologySpreadConstraints" }} + {{- if .Values._cluster.scheduling }} + {{- $rawConstraints = get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }} {{- end }} {{- if $rawConstraints }} {{- $rawConstraints | fromYaml | toYaml | nindent 6 }} diff --git a/packages/extra/info/templates/dashboard-resourcemap.yaml b/packages/extra/info/templates/dashboard-resourcemap.yaml index 39da1b37..aa8b7641 100644 --- a/packages/extra/info/templates/dashboard-resourcemap.yaml +++ b/packages/extra/info/templates/dashboard-resourcemap.yaml @@ -1,5 +1,4 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $oidcEnabled := index $cozyConfig.data "oidc-enabled" }} +{{- $oidcEnabled := index .Values._cluster "oidc-enabled" }} apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: diff --git a/packages/extra/info/templates/kubeconfig.yaml b/packages/extra/info/templates/kubeconfig.yaml index d960a587..8a5c150d 100644 --- a/packages/extra/info/templates/kubeconfig.yaml +++ b/packages/extra/info/templates/kubeconfig.yaml @@ -1,23 +1,15 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $host := index $cozyConfig.data "root-host" }} +{{- $host := .Values._namespace.host | default (index .Values._cluster "root-host") }} {{- $k8sClientSecret := lookup "v1" "Secret" "cozy-keycloak" "k8s-client" }} {{- if $k8sClientSecret }} -{{- $apiServerEndpoint := index $cozyConfig.data "api-server-endpoint" }} -{{- $managementKubeconfigEndpoint := default "" (get $cozyConfig.data "management-kubeconfig-endpoint") }} +{{- $apiServerEndpoint := index .Values._cluster "api-server-endpoint" }} +{{- $managementKubeconfigEndpoint := default "" (index .Values._cluster "management-kubeconfig-endpoint") }} {{- if and $managementKubeconfigEndpoint (ne $managementKubeconfigEndpoint "") }} {{- $apiServerEndpoint = $managementKubeconfigEndpoint }} {{- end }} {{- $k8sClient := index $k8sClientSecret.data "client-secret-key" | b64dec }} {{- $rootSaConfigMap := lookup "v1" "ConfigMap" "kube-system" "kube-root-ca.crt" }} {{- $k8sCa := index $rootSaConfigMap.data "ca.crt" | b64enc }} - -{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} -{{- $tenantRoot := lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} -{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} -{{- $host = $tenantRoot.spec.values.host }} -{{- end }} -{{- end }} --- apiVersion: v1 kind: Secret diff --git a/packages/extra/ingress/templates/nginx-ingress.yaml b/packages/extra/ingress/templates/nginx-ingress.yaml index e28918e4..13ad9a6b 100644 --- a/packages/extra/ingress/templates/nginx-ingress.yaml +++ b/packages/extra/ingress/templates/nginx-ingress.yaml @@ -1,6 +1,5 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} -{{- $exposeExternalIPs := (index $cozyConfig.data "expose-external-ips") | default "" | nospace }} +{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} +{{- $exposeExternalIPs := (index .Values._cluster "expose-external-ips") | default "" | nospace }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -24,6 +23,15 @@ spec: force: true remediation: retries: -1 + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster + - kind: Secret + name: cozystack-values + valuesKey: _namespace + targetPath: _namespace values: ingress-nginx: fullnameOverride: {{ trimPrefix "tenant-" .Release.Namespace }}-ingress diff --git a/packages/extra/monitoring/templates/alerta/alerta-db.yaml b/packages/extra/monitoring/templates/alerta/alerta-db.yaml index a2cca187..845cd8ba 100644 --- a/packages/extra/monitoring/templates/alerta/alerta-db.yaml +++ b/packages/extra/monitoring/templates/alerta/alerta-db.yaml @@ -5,9 +5,8 @@ metadata: name: alerta-db spec: instances: 2 - {{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} - {{- if $configMap }} - {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} + {{- if .Values._cluster.scheduling }} + {{- $rawConstraints := get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }} {{- if $rawConstraints }} {{- $rawConstraints | fromYaml | toYaml | nindent 2 }} labelSelector: diff --git a/packages/extra/monitoring/templates/alerta/alerta.yaml b/packages/extra/monitoring/templates/alerta/alerta.yaml index 72500948..76b7a02b 100644 --- a/packages/extra/monitoring/templates/alerta/alerta.yaml +++ b/packages/extra/monitoring/templates/alerta/alerta.yaml @@ -1,9 +1,6 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} - -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} +{{- $ingress := .Values._namespace.ingress }} +{{- $host := .Values._namespace.host }} {{- $apiKey := randAlphaNum 32 }} {{- $existingSecret := lookup "v1" "Secret" .Release.Namespace "alerta" }} diff --git a/packages/extra/monitoring/templates/grafana/db.yaml b/packages/extra/monitoring/templates/grafana/db.yaml index f1781cff..662f5cf4 100644 --- a/packages/extra/monitoring/templates/grafana/db.yaml +++ b/packages/extra/monitoring/templates/grafana/db.yaml @@ -6,9 +6,8 @@ spec: instances: 2 storage: size: {{ .Values.grafana.db.size }} - {{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} - {{- if $configMap }} - {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} + {{- if .Values._cluster.scheduling }} + {{- $rawConstraints := get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }} {{- if $rawConstraints }} {{- $rawConstraints | fromYaml | toYaml | nindent 2 }} labelSelector: diff --git a/packages/extra/monitoring/templates/grafana/grafana.yaml b/packages/extra/monitoring/templates/grafana/grafana.yaml index 2397fd10..1eadda9e 100644 --- a/packages/extra/monitoring/templates/grafana/grafana.yaml +++ b/packages/extra/monitoring/templates/grafana/grafana.yaml @@ -1,9 +1,6 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} - -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} +{{- $ingress := .Values._namespace.ingress }} +{{- $host := .Values._namespace.host }} --- apiVersion: grafana.integreatly.org/v1beta1 kind: Grafana diff --git a/packages/extra/seaweedfs/templates/client/cosi-deployment.yaml b/packages/extra/seaweedfs/templates/client/cosi-deployment.yaml index 5307a67f..f73a61bf 100644 --- a/packages/extra/seaweedfs/templates/client/cosi-deployment.yaml +++ b/packages/extra/seaweedfs/templates/client/cosi-deployment.yaml @@ -1,7 +1,5 @@ {{- if eq .Values.topology "Client" }} -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- $host := .Values._namespace.host }} --- apiVersion: apps/v1 kind: Deployment diff --git a/packages/extra/seaweedfs/templates/ingress.yaml b/packages/extra/seaweedfs/templates/ingress.yaml index 05bf201d..cf4e837e 100644 --- a/packages/extra/seaweedfs/templates/ingress.yaml +++ b/packages/extra/seaweedfs/templates/ingress.yaml @@ -1,9 +1,5 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} - -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- $ingress := .Values._namespace.ingress }} +{{- $host := .Values._namespace.host }} {{- if and (not (eq .Values.topology "Client")) (.Values.filer.grpcHost) }} --- apiVersion: networking.k8s.io/v1 diff --git a/packages/extra/seaweedfs/templates/seaweedfs.yaml b/packages/extra/seaweedfs/templates/seaweedfs.yaml index 02bac375..4ef17dec 100644 --- a/packages/extra/seaweedfs/templates/seaweedfs.yaml +++ b/packages/extra/seaweedfs/templates/seaweedfs.yaml @@ -34,9 +34,8 @@ {{- end }} {{- if not (eq .Values.topology "Client") }} -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- $ingress := .Values._namespace.ingress }} +{{- $host := .Values._namespace.host }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -60,6 +59,15 @@ spec: force: true remediation: retries: -1 + valuesFrom: + - kind: Secret + name: cozystack-values + valuesKey: _cluster + targetPath: _cluster + - kind: Secret + name: cozystack-values + valuesKey: _namespace + targetPath: _namespace values: global: serviceAccountName: "{{ .Release.Namespace }}-seaweedfs" diff --git a/packages/library/cozy-lib/templates/_cozyconfig.tpl b/packages/library/cozy-lib/templates/_cozyconfig.tpl index 559f7415..648b2617 100644 --- a/packages/library/cozy-lib/templates/_cozyconfig.tpl +++ b/packages/library/cozy-lib/templates/_cozyconfig.tpl @@ -1,7 +1,130 @@ +{{/* +Cluster-wide configuration helpers. +These helpers read from .Values._cluster which is populated via valuesFrom from Secret cozystack-values. +*/}} + +{{/* +Get the root host for the cluster. +Usage: {{ include "cozy-lib.root-host" . }} +*/}} +{{- define "cozy-lib.root-host" -}} +{{- (index .Values._cluster "root-host") | default "" }} +{{- end }} + +{{/* +Get the bundle name for the cluster. +Usage: {{ include "cozy-lib.bundle-name" . }} +*/}} +{{- define "cozy-lib.bundle-name" -}} +{{- (index .Values._cluster "bundle-name") | default "" }} +{{- end }} + +{{/* +Get the images registry. +Usage: {{ include "cozy-lib.images-registry" . }} +*/}} +{{- define "cozy-lib.images-registry" -}} +{{- (index .Values._cluster "images-registry") | default "" }} +{{- end }} + +{{/* +Get the ipv4 cluster CIDR. +Usage: {{ include "cozy-lib.ipv4-cluster-cidr" . }} +*/}} +{{- define "cozy-lib.ipv4-cluster-cidr" -}} +{{- (index .Values._cluster "ipv4-cluster-cidr") | default "" }} +{{- end }} + +{{/* +Get the ipv4 service CIDR. +Usage: {{ include "cozy-lib.ipv4-service-cidr" . }} +*/}} +{{- define "cozy-lib.ipv4-service-cidr" -}} +{{- (index .Values._cluster "ipv4-service-cidr") | default "" }} +{{- end }} + +{{/* +Get the ipv4 join CIDR. +Usage: {{ include "cozy-lib.ipv4-join-cidr" . }} +*/}} +{{- define "cozy-lib.ipv4-join-cidr" -}} +{{- (index .Values._cluster "ipv4-join-cidr") | default "" }} +{{- end }} + +{{/* +Get scheduling configuration. +Usage: {{ include "cozy-lib.scheduling" . }} +Returns: YAML string of scheduling configuration +*/}} +{{- define "cozy-lib.scheduling" -}} +{{- if .Values._cluster.scheduling }} +{{- .Values._cluster.scheduling | toYaml }} +{{- end }} +{{- end }} + +{{/* +Get branding configuration. +Usage: {{ include "cozy-lib.branding" . }} +Returns: YAML string of branding configuration +*/}} +{{- define "cozy-lib.branding" -}} +{{- if .Values._cluster.branding }} +{{- .Values._cluster.branding | toYaml }} +{{- end }} +{{- end }} + +{{/* +Namespace-specific configuration helpers. +These helpers read from .Values._namespace which is populated via valuesFrom from Secret cozystack-values. +*/}} + +{{/* +Get the host for this namespace. +Usage: {{ include "cozy-lib.ns-host" . }} +*/}} +{{- define "cozy-lib.ns-host" -}} +{{- .Values._namespace.host | default "" }} +{{- end }} + +{{/* +Get the etcd namespace reference. +Usage: {{ include "cozy-lib.ns-etcd" . }} +*/}} +{{- define "cozy-lib.ns-etcd" -}} +{{- .Values._namespace.etcd | default "" }} +{{- end }} + +{{/* +Get the ingress namespace reference. +Usage: {{ include "cozy-lib.ns-ingress" . }} +*/}} +{{- define "cozy-lib.ns-ingress" -}} +{{- .Values._namespace.ingress | default "" }} +{{- end }} + +{{/* +Get the monitoring namespace reference. +Usage: {{ include "cozy-lib.ns-monitoring" . }} +*/}} +{{- define "cozy-lib.ns-monitoring" -}} +{{- .Values._namespace.monitoring | default "" }} +{{- end }} + +{{/* +Get the seaweedfs namespace reference. +Usage: {{ include "cozy-lib.ns-seaweedfs" . }} +*/}} +{{- define "cozy-lib.ns-seaweedfs" -}} +{{- .Values._namespace.seaweedfs | default "" }} +{{- end }} + +{{/* +Legacy helper - kept for backward compatibility during migration. +Loads config into context. Deprecated: use direct .Values._cluster access instead. +*/}} {{- define "cozy-lib.loadCozyConfig" }} {{- include "cozy-lib.checkInput" . }} {{- if not (hasKey (index . 1) "cozyConfig") }} -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $_ := set (index . 1) "cozyConfig" $cozyConfig }} +{{- $_ := set (index . 1) "cozyConfig" (dict "data" ((index . 1).Values._cluster | default dict)) }} {{- end }} {{- end }} diff --git a/packages/system/bucket/templates/ingress.yaml b/packages/system/bucket/templates/ingress.yaml index d8d659c7..f7b4eed4 100644 --- a/packages/system/bucket/templates/ingress.yaml +++ b/packages/system/bucket/templates/ingress.yaml @@ -1,8 +1,6 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} -{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} -{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} +{{- $host := .Values._namespace.host }} +{{- $ingress := .Values._namespace.ingress }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} apiVersion: networking.k8s.io/v1 kind: Ingress diff --git a/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml b/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml index 6a70eef0..e93f3f67 100644 --- a/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml +++ b/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml @@ -1,5 +1,4 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} apiVersion: cert-manager.io/v1 kind: ClusterIssuer diff --git a/packages/system/cozystack-api/templates/api-ingress.yaml b/packages/system/cozystack-api/templates/api-ingress.yaml index 54fdf54b..9226d887 100644 --- a/packages/system/cozystack-api/templates/api-ingress.yaml +++ b/packages/system/cozystack-api/templates/api-ingress.yaml @@ -1,7 +1,6 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- $exposeServices := splitList "," ((index $cozyConfig.data "expose-services") | default "") }} -{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} +{{- $host := index .Values._cluster "root-host" }} +{{- $exposeServices := splitList "," ((index .Values._cluster "expose-services") | default "") }} +{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} {{- if and (has "api" $exposeServices) }} apiVersion: networking.k8s.io/v1 diff --git a/packages/system/dashboard/templates/configmap.yaml b/packages/system/dashboard/templates/configmap.yaml index bbf71610..f148109f 100644 --- a/packages/system/dashboard/templates/configmap.yaml +++ b/packages/system/dashboard/templates/configmap.yaml @@ -1,4 +1,4 @@ -{{- $brandingConfig:= lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} +{{- $brandingConfig := .Values._cluster.branding | default dict }} {{- $tenantText := "v0.38.2" }} {{- $footerText := "Cozystack" }} @@ -16,9 +16,9 @@ metadata: app.kubernetes.io/instance: incloud-web app.kubernetes.io/name: web data: - CUSTOM_TENANT_TEXT: {{ $brandingConfig | dig "data" "tenantText" $tenantText | quote }} - FOOTER_TEXT: {{ $brandingConfig | dig "data" "footerText" $footerText | quote }} - TITLE_TEXT: {{ $brandingConfig | dig "data" "titleText" $titleText | quote }} - LOGO_TEXT: {{ $brandingConfig | dig "data" "logoText" $logoText | quote }} - CUSTOM_LOGO_SVG: {{ $brandingConfig | dig "data" "logoSvg" $logoSvg | quote }} - ICON_SVG: {{ $brandingConfig | dig "data" "iconSvg" $iconSvg | quote }} + CUSTOM_TENANT_TEXT: {{ $brandingConfig.tenantText | default $tenantText | quote }} + FOOTER_TEXT: {{ $brandingConfig.footerText | default $footerText | quote }} + TITLE_TEXT: {{ $brandingConfig.titleText | default $titleText | quote }} + LOGO_TEXT: {{ $brandingConfig.logoText | default $logoText | quote }} + CUSTOM_LOGO_SVG: {{ $brandingConfig.logoSvg | default $logoSvg | quote }} + ICON_SVG: {{ $brandingConfig.iconSvg | default $iconSvg | quote }} diff --git a/packages/system/dashboard/templates/gatekeeper.yaml b/packages/system/dashboard/templates/gatekeeper.yaml index b4503f4f..40f2565f 100644 --- a/packages/system/dashboard/templates/gatekeeper.yaml +++ b/packages/system/dashboard/templates/gatekeeper.yaml @@ -1,6 +1,5 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- $oidcEnabled := index $cozyConfig.data "oidc-enabled" }} +{{- $host := index .Values._cluster "root-host" }} +{{- $oidcEnabled := index .Values._cluster "oidc-enabled" }} apiVersion: apps/v1 kind: Deployment diff --git a/packages/system/dashboard/templates/ingress.yaml b/packages/system/dashboard/templates/ingress.yaml index 5a634e2c..aacc1bc1 100644 --- a/packages/system/dashboard/templates/ingress.yaml +++ b/packages/system/dashboard/templates/ingress.yaml @@ -1,8 +1,7 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- $exposeServices := splitList "," ((index $cozyConfig.data "expose-services") | default "") }} -{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} +{{- $host := index .Values._cluster "root-host" }} +{{- $exposeServices := splitList "," ((index .Values._cluster "expose-services") | default "") }} +{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} {{- if and (has "dashboard" $exposeServices) }} apiVersion: networking.k8s.io/v1 diff --git a/packages/system/dashboard/templates/keycloakclient.yaml b/packages/system/dashboard/templates/keycloakclient.yaml index 55ebc5d5..80f7332e 100644 --- a/packages/system/dashboard/templates/keycloakclient.yaml +++ b/packages/system/dashboard/templates/keycloakclient.yaml @@ -1,6 +1,5 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- $extraRedirectUris := splitList "," ((index $cozyConfig.data "extra-keycloak-redirect-uri-for-dashboard") | default "") }} +{{- $host := index .Values._cluster "root-host" }} +{{- $extraRedirectUris := splitList "," ((index .Values._cluster "extra-keycloak-redirect-uri-for-dashboard") | default "") }} {{- $existingK8sSecret := lookup "v1" "Secret" .Release.Namespace "k8s-client" }} {{- $existingDashboardSecret := lookup "v1" "Secret" .Release.Namespace "dashboard-client" }} diff --git a/packages/system/dashboard/templates/nginx-config.yaml b/packages/system/dashboard/templates/nginx-config.yaml index c2d6f624..696e9ce9 100644 --- a/packages/system/dashboard/templates/nginx-config.yaml +++ b/packages/system/dashboard/templates/nginx-config.yaml @@ -1,5 +1,4 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $host := index $cozyConfig.data "root-host" }} +{{- $host := index .Values._cluster "root-host" }} apiVersion: v1 data: diff --git a/packages/system/keycloak-configure/templates/configure-kk.yaml b/packages/system/keycloak-configure/templates/configure-kk.yaml index 3fc92c86..7e77ac4c 100644 --- a/packages/system/keycloak-configure/templates/configure-kk.yaml +++ b/packages/system/keycloak-configure/templates/configure-kk.yaml @@ -1,13 +1,12 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- $extraRedirectUris := splitList "," ((index $cozyConfig.data "extra-keycloak-redirect-uri-for-dashboard") | default "") }} +{{- $host := index .Values._cluster "root-host" }} +{{- $extraRedirectUris := splitList "," ((index .Values._cluster "extra-keycloak-redirect-uri-for-dashboard") | default "") }} {{- $rootSaConfigMap := lookup "v1" "ConfigMap" "kube-system" "kube-root-ca.crt" }} {{- $k8sCa := index $rootSaConfigMap.data "ca.crt" | b64enc }} {{- $existingK8sSecret := lookup "v1" "Secret" .Release.Namespace "k8s-client" }} {{- $existingKubeappsSecret := lookup "v1" "Secret" .Release.Namespace "kubeapps-client" }} {{- $existingAuthConfig := lookup "v1" "Secret" "cozy-dashboard" "kubeapps-auth-config" }} -{{- $cozystackBranding:= lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} +{{- $brandingConfig := .Values._cluster.branding | default dict }} {{ $k8sClient := "" }} {{- if $existingK8sSecret }} @@ -17,8 +16,8 @@ {{- end }} {{ $branding := "" }} -{{- if $cozystackBranding }} - {{- $branding = index $cozystackBranding.data "branding" }} +{{- if $brandingConfig }} + {{- $branding = $brandingConfig.branding }} {{- end }} --- diff --git a/packages/system/keycloak/templates/db.yaml b/packages/system/keycloak/templates/db.yaml index 70666d7b..1cd98ffc 100644 --- a/packages/system/keycloak/templates/db.yaml +++ b/packages/system/keycloak/templates/db.yaml @@ -6,9 +6,8 @@ spec: instances: 2 storage: size: 20Gi - {{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} - {{- if $configMap }} - {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} + {{- if .Values._cluster.scheduling }} + {{- $rawConstraints := get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }} {{- if $rawConstraints }} {{- $rawConstraints | fromYaml | toYaml | nindent 2 }} labelSelector: diff --git a/packages/system/keycloak/templates/ingress.yaml b/packages/system/keycloak/templates/ingress.yaml index 30120619..0e0f56cb 100644 --- a/packages/system/keycloak/templates/ingress.yaml +++ b/packages/system/keycloak/templates/ingress.yaml @@ -1,7 +1,6 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- $issuerType := (index $cozyConfig.data "clusterissuer") | default "http01" }} -{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} +{{- $host := index .Values._cluster "root-host" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} +{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} apiVersion: networking.k8s.io/v1 kind: Ingress diff --git a/packages/system/keycloak/templates/sts.yaml b/packages/system/keycloak/templates/sts.yaml index 4705f77c..96d30601 100644 --- a/packages/system/keycloak/templates/sts.yaml +++ b/packages/system/keycloak/templates/sts.yaml @@ -1,6 +1,5 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }} +{{- $host := index .Values._cluster "root-host" }} +{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} {{- $existingPassword := lookup "v1" "Secret" "cozy-keycloak" (printf "%s-credentials" .Release.Name) }} {{- $password := randAlphaNum 16 -}} diff --git a/packages/system/kubevirt-cdi/templates/cdi-uploadproxy-ingress.yaml b/packages/system/kubevirt-cdi/templates/cdi-uploadproxy-ingress.yaml index 58eef4fa..ee89953f 100644 --- a/packages/system/kubevirt-cdi/templates/cdi-uploadproxy-ingress.yaml +++ b/packages/system/kubevirt-cdi/templates/cdi-uploadproxy-ingress.yaml @@ -1,7 +1,6 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- $exposeServices := splitList "," ((index $cozyConfig.data "expose-services") | default "") }} -{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} +{{- $host := index .Values._cluster "root-host" }} +{{- $exposeServices := splitList "," ((index .Values._cluster "expose-services") | default "") }} +{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} {{- if and (has "cdi-uploadproxy" $exposeServices) }} diff --git a/packages/system/kubevirt/templates/vm-exportproxy-ingress.yaml b/packages/system/kubevirt/templates/vm-exportproxy-ingress.yaml index b77743d0..a089f5ef 100644 --- a/packages/system/kubevirt/templates/vm-exportproxy-ingress.yaml +++ b/packages/system/kubevirt/templates/vm-exportproxy-ingress.yaml @@ -1,7 +1,6 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- $exposeServices := splitList "," ((index $cozyConfig.data "expose-services") | default "") }} -{{- $exposeIngress := index $cozyConfig.data "expose-ingress" | default "tenant-root" }} +{{- $host := index .Values._cluster "root-host" }} +{{- $exposeServices := splitList "," ((index .Values._cluster "expose-services") | default "") }} +{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} {{- if and (has "vm-exportproxy" $exposeServices) }} apiVersion: networking.k8s.io/v1 diff --git a/packages/tests/cozy-lib-tests/tests/quota_values.yaml b/packages/tests/cozy-lib-tests/tests/quota_values.yaml index bcf6a21e..87e5cf17 100644 --- a/packages/tests/cozy-lib-tests/tests/quota_values.yaml +++ b/packages/tests/cozy-lib-tests/tests/quota_values.yaml @@ -3,3 +3,6 @@ quota: cpu: "20" storage: "5Gi" foobar: "3" + +_cluster: {} +_namespace: {} diff --git a/pkg/registry/apps/application/rest.go b/pkg/registry/apps/application/rest.go index ee189e26..dd211cf3 100644 --- a/pkg/registry/apps/application/rest.go +++ b/pkg/registry/apps/application/rest.go @@ -148,6 +148,11 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation return nil, fmt.Errorf("expected *appsv1alpha1.Application object, got %T", obj) } + // Validate that values don't contain reserved keys (starting with "_") + if err := validateNoInternalKeys(app.Spec); err != nil { + return nil, apierrors.NewBadRequest(err.Error()) + } + // Convert Application to HelmRelease helmRelease, err := r.ConvertApplicationToHelmRelease(app) if err != nil { @@ -442,6 +447,11 @@ func (r *REST) Update(ctx context.Context, name string, objInfo rest.UpdatedObje return nil, false, fmt.Errorf("expected *appsv1alpha1.Application object, got %T", newObj) } + // Validate that values don't contain reserved keys (starting with "_") + if err := validateNoInternalKeys(app.Spec); err != nil { + return nil, false, apierrors.NewBadRequest(err.Error()) + } + // Convert Application to HelmRelease helmRelease, err := r.ConvertApplicationToHelmRelease(app) if err != nil { @@ -851,8 +861,49 @@ func (r *REST) ConvertApplicationToHelmRelease(app *appsv1alpha1.Application) (* return r.convertApplicationToHelmRelease(app) } +// filterInternalKeys removes keys starting with "_" from the JSON values +func filterInternalKeys(values *apiextv1.JSON) *apiextv1.JSON { + if values == nil || len(values.Raw) == 0 { + return values + } + var data map[string]interface{} + if err := json.Unmarshal(values.Raw, &data); err != nil { + return values + } + for key := range data { + if strings.HasPrefix(key, "_") { + delete(data, key) + } + } + filtered, err := json.Marshal(data) + if err != nil { + return values + } + return &apiextv1.JSON{Raw: filtered} +} + +// validateNoInternalKeys checks that values don't contain keys starting with "_" +func validateNoInternalKeys(values *apiextv1.JSON) error { + if values == nil || len(values.Raw) == 0 { + return nil + } + var data map[string]interface{} + if err := json.Unmarshal(values.Raw, &data); err != nil { + return err + } + for key := range data { + if strings.HasPrefix(key, "_") { + return fmt.Errorf("values key %q is reserved (keys starting with '_' are not allowed)", key) + } + } + return nil +} + // convertHelmReleaseToApplication implements the actual conversion logic func (r *REST) convertHelmReleaseToApplication(hr *helmv2.HelmRelease) (appsv1alpha1.Application, error) { + // Filter out internal keys (starting with "_") from spec + filteredSpec := filterInternalKeys(hr.Spec.Values) + app := appsv1alpha1.Application{ TypeMeta: metav1.TypeMeta{ APIVersion: "apps.cozystack.io/v1alpha1", @@ -868,7 +919,7 @@ func (r *REST) convertHelmReleaseToApplication(hr *helmv2.HelmRelease) (appsv1al Labels: filterPrefixedMap(hr.Labels, LabelPrefix), Annotations: filterPrefixedMap(hr.Annotations, AnnotationPrefix), }, - Spec: hr.Spec.Values, + Spec: filteredSpec, Status: appsv1alpha1.ApplicationStatus{ Version: hr.Status.LastAttemptedRevision, }, @@ -935,6 +986,22 @@ func (r *REST) convertApplicationToHelmRelease(app *appsv1alpha1.Application) (* Retries: -1, }, }, + ValuesFrom: []helmv2.ValuesReference{ + { + Kind: "Secret", + Name: "cozystack-values", + ValuesKey: "_namespace", + TargetPath: "_namespace", + Optional: false, + }, + { + Kind: "Secret", + Name: "cozystack-values", + ValuesKey: "_cluster", + TargetPath: "_cluster", + Optional: false, + }, + }, Values: app.Spec, }, } From a8d32a4bc3cf17751ce7007b634f47bcbdc77686 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Sun, 4 Jan 2026 10:00:12 +0100 Subject: [PATCH 2/2] fix: add default values for _cluster config in cozystack-values Secret Ensure all required keys exist in the _cluster config by merging ConfigMap data with default values. This prevents errors when accessing keys that may not be present in the cozystack ConfigMap. Co-Authored-By: Claude Signed-off-by: Andrei Kvapil --- packages/core/platform/templates/apps.yaml | 15 ++++++++++++++- packages/core/platform/templates/namespaces.yaml | 15 ++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/core/platform/templates/apps.yaml b/packages/core/platform/templates/apps.yaml index 2477fc17..46c9a370 100644 --- a/packages/core/platform/templates/apps.yaml +++ b/packages/core/platform/templates/apps.yaml @@ -3,6 +3,19 @@ {{- $cozystackScheduling := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} {{- $bundleName := index $cozyConfig.data "bundle-name" }} {{- $bundle := tpl (.Files.Get (printf "bundles/%s.yaml" $bundleName)) . | fromYaml }} +{{/* Default values for _cluster config to ensure all required keys exist */}} +{{- $clusterDefaults := dict + "root-host" "" + "bundle-name" "" + "clusterissuer" "http01" + "oidc-enabled" "false" + "expose-services" "" + "expose-ingress" "tenant-root" + "expose-external-ips" "" + "cluster-domain" "cozy.local" + "api-server-endpoint" "" +}} +{{- $clusterConfig := mergeOverwrite $clusterDefaults ($cozyConfig.data | default dict) }} {{- $host := "example.org" }} {{- $host := "example.org" }} {{- if $cozyConfig.data }} @@ -43,7 +56,7 @@ metadata: type: Opaque stringData: _cluster: | - {{- $cozyConfig.data | toYaml | nindent 4 }} + {{- $clusterConfig | toYaml | nindent 4 }} {{- with $cozystackBranding.data }} branding: {{- . | toYaml | nindent 6 }} diff --git a/packages/core/platform/templates/namespaces.yaml b/packages/core/platform/templates/namespaces.yaml index a4ed5135..58eca481 100644 --- a/packages/core/platform/templates/namespaces.yaml +++ b/packages/core/platform/templates/namespaces.yaml @@ -2,6 +2,19 @@ {{- $cozystackBranding := lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} {{- $cozystackScheduling := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} {{- $bundleName := index $cozyConfig.data "bundle-name" }} +{{/* Default values for _cluster config to ensure all required keys exist */}} +{{- $clusterDefaults := dict + "root-host" "" + "bundle-name" "" + "clusterissuer" "http01" + "oidc-enabled" "false" + "expose-services" "" + "expose-ingress" "tenant-root" + "expose-external-ips" "" + "cluster-domain" "cozy.local" + "api-server-endpoint" "" +}} +{{- $clusterConfig := mergeOverwrite $clusterDefaults ($cozyConfig.data | default dict) }} {{- $bundle := tpl (.Files.Get (printf "bundles/%s.yaml" $bundleName)) . | fromYaml }} {{- $disabledComponents := splitList "," ((index $cozyConfig.data "bundle-disable") | default "") }} {{- $enabledComponents := splitList "," ((index $cozyConfig.data "bundle-enable") | default "") }} @@ -50,7 +63,7 @@ metadata: type: Opaque stringData: _cluster: | - {{- $cozyConfig.data | toYaml | nindent 4 }} + {{- $clusterConfig | toYaml | nindent 4 }} {{- with $cozystackBranding.data }} branding: {{- . | toYaml | nindent 6 }}