From bfbad79d1a6134ed29713bc0ce1a0a23333b6a40 Mon Sep 17 00:00:00 2001 From: RokibulHasan7 Date: Mon, 22 Dec 2025 16:03:00 +0600 Subject: [PATCH] Add central monitoring system Signed-off-by: RokibulHasan7 --- apis/installer/v1alpha1/ace_ace_types.go | 59 +++++ apis/installer/v1alpha1/ace_options_types.go | 9 +- .../v1alpha1/zz_generated.deepcopy.go | 211 ++++++++++++++++++ charts/ace-installer/README.md | 2 + .../templates/presets/bootstrap-presets.yaml | 3 + charts/ace-installer/values.yaml | 3 + charts/ace/Chart.yaml | 4 + charts/ace/README.md | 2 + charts/ace/templates/gateway/route-main.yaml | 18 ++ .../ace/templates/platform/setup-config.yaml | 1 + charts/ace/values.openapiv3_schema.yaml | 158 +++++++++++++ charts/ace/values.yaml | 6 + charts/opscenter-features/README.md | 9 +- .../telemetry-stack/appscode-otel-stack.yaml | 50 +++++ .../telemetry-stack/prom-label-proxy.yaml | 49 ++++ .../telemetry-stack/tenant-operator.yaml | 48 ++++ .../telemetry-stack/thanos-operator.yaml | 47 ++++ charts/opscenter-features/values.yaml | 12 +- features.md | 6 + .../ace-options/values.openapiv3_schema.yaml | 86 +++++++ 20 files changed, 774 insertions(+), 9 deletions(-) create mode 100644 charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/appscode-otel-stack.yaml create mode 100644 charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/prom-label-proxy.yaml create mode 100644 charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/tenant-operator.yaml create mode 100644 charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/thanos-operator.yaml diff --git a/apis/installer/v1alpha1/ace_ace_types.go b/apis/installer/v1alpha1/ace_ace_types.go index 7f9999fa2..f1ca2cca6 100644 --- a/apis/installer/v1alpha1/ace_ace_types.go +++ b/apis/installer/v1alpha1/ace_ace_types.go @@ -55,6 +55,7 @@ type AceSpec struct { PlatformUi AcePlatformUi `json:"platform-ui"` ClusterUi AceClusterUi `json:"cluster-ui"` Grafana AceGrafana `json:"grafana"` + Perses AcePerses `json:"perses"` KubedbUi AceKubedbUi `json:"kubedb-ui"` PlatformApi AcePlatformApi `json:"platform-api"` IngressNginx AceIngressNginx `json:"ingress-nginx"` @@ -123,6 +124,11 @@ type AceGrafana struct { *GrafanaSpec `json:",inline,omitempty"` } +type AcePerses struct { + Enabled bool `json:"enabled"` + *PersesSpec `json:",inline,omitempty"` +} + type AceKubedbUi struct { Enabled bool `json:"enabled"` *KubedbUiSpec `json:",inline,omitempty"` @@ -245,6 +251,54 @@ type KubeStashSpec struct { StorageSecret wizardsapi.OptionalResource `json:"storageSecret"` } +type PersesSpec struct { + Config PersesConfig `json:"config"` + Env []core.EnvVar `json:"env"` + PodAnnotations map[string]string `json:"podAnnotations"` +} + +type PersesConfig struct { + APIPrefix string `json:"api_prefix,omitempty"` + Security SecurityConfig `json:"security,omitempty"` + Database DatabaseConfig `json:"database,omitempty"` +} + +type SecurityConfig struct { + EnableAuth bool `json:"enable_auth,omitempty"` + EncryptionKey string `json:"encryption_key,omitempty"` + Authentication AuthenticationConfig `json:"authentication,omitempty"` + Authorization AuthorizationConfig `json:"authorization,omitempty"` +} + +type AuthenticationConfig struct { + Providers AuthProviders `json:"providers,omitempty"` +} + +type AuthProviders struct { + EnableNative bool `json:"enable_native,omitempty"` +} + +type AuthorizationConfig struct { + GuestPermissions []Permission `json:"guest_permissions,omitempty"` +} + +type Permission struct { + Actions []string `json:"actions,omitempty"` + Scopes []string `json:"scopes,omitempty"` +} + +type DatabaseConfig struct { + SQL SQLConfig `json:"sql,omitempty"` +} + +type SQLConfig struct { + User string `json:"user,omitempty"` + Password string `json:"password,omitempty"` + Address string `json:"addr,omitempty"` + DBName string `json:"db_name,omitempty"` + AllowNativePasswords bool `json:"allow_native_passwords,omitempty"` +} + type InfraDns struct { catgwapi.GatewayDns `json:",inline,omitempty"` // +optional @@ -310,6 +364,7 @@ type Settings struct { Platform PlatformSettings `json:"platform"` Security SecuritySettings `json:"security"` Grafana GrafanaSettings `json:"grafana"` + Perses PersesSettings `json:"perses"` InboxServer InboxServerSettings `json:"inboxServer"` Contract ContractStorage `json:"contract"` Firebase FirebaseSettings `json:"firebase"` @@ -420,6 +475,10 @@ type GrafanaSettings struct { SecretKey string `json:"secretKey"` } +type PersesSettings struct { + EncryptionKey string `json:"encryptionKey"` +} + type InboxServerSettings struct { JmapURL string `json:"jmapURL"` WebAdminURL string `json:"webAdminURL"` diff --git a/apis/installer/v1alpha1/ace_options_types.go b/apis/installer/v1alpha1/ace_options_types.go index ea7ec7130..1dd68c268 100644 --- a/apis/installer/v1alpha1/ace_options_types.go +++ b/apis/installer/v1alpha1/ace_options_types.go @@ -64,6 +64,7 @@ type AceOptionsSpec struct { PlatformUi AceOptionsComponentSpec `json:"platform-ui"` ClusterUi AceOptionsComponentSpec `json:"cluster-ui"` Grafana AceOptionsComponentSpec `json:"grafana"` + Perses AceOptionsComponentSpec `json:"perses"` KubedbUi AceOptionsComponentSpec `json:"kubedb-ui"` PlatformApi AceOptionsComponentSpec `json:"platform-api"` Ingress AceOptionsIngressNginx `json:"ingress"` @@ -514,9 +515,11 @@ type GeneratedValues struct { // +optional JKSPassword string `json:"jksPassword"` // +optional - GrafanaSecretKey string `json:"grafanaSecretKey"` - InboxServer InboxServerValues `json:"inboxServer"` - OpenFGAServer OpenFGAServerValues `json:"openfga"` + GrafanaSecretKey string `json:"grafanaSecretKey"` + // +optional + PersesEncryptionKey string `json:"persesEncryptionKey"` + InboxServer InboxServerValues `json:"inboxServer"` + OpenFGAServer OpenFGAServerValues `json:"openfga"` // InstallerSecret used by hosted mode (prod and ninja) // to generate and validate marketplace self-hosted installer options // +optional diff --git a/apis/installer/v1alpha1/zz_generated.deepcopy.go b/apis/installer/v1alpha1/zz_generated.deepcopy.go index 0d829ae2e..74f536be2 100644 --- a/apis/installer/v1alpha1/zz_generated.deepcopy.go +++ b/apis/installer/v1alpha1/zz_generated.deepcopy.go @@ -1468,6 +1468,7 @@ func (in *AceOptionsSpec) DeepCopyInto(out *AceOptionsSpec) { in.PlatformUi.DeepCopyInto(&out.PlatformUi) in.ClusterUi.DeepCopyInto(&out.ClusterUi) in.Grafana.DeepCopyInto(&out.Grafana) + in.Perses.DeepCopyInto(&out.Perses) in.KubedbUi.DeepCopyInto(&out.KubedbUi) in.PlatformApi.DeepCopyInto(&out.PlatformApi) in.Ingress.DeepCopyInto(&out.Ingress) @@ -1545,6 +1546,26 @@ func (in *AceOutboxSyncerSettingsSecretName) DeepCopy() *AceOutboxSyncerSettings return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AcePerses) DeepCopyInto(out *AcePerses) { + *out = *in + if in.PersesSpec != nil { + in, out := &in.PersesSpec, &out.PersesSpec + *out = new(PersesSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AcePerses. +func (in *AcePerses) DeepCopy() *AcePerses { + if in == nil { + return nil + } + out := new(AcePerses) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AcePgOutbox) DeepCopyInto(out *AcePgOutbox) { *out = *in @@ -1793,6 +1814,7 @@ func (in *AceSpec) DeepCopyInto(out *AceSpec) { in.PlatformUi.DeepCopyInto(&out.PlatformUi) in.ClusterUi.DeepCopyInto(&out.ClusterUi) in.Grafana.DeepCopyInto(&out.Grafana) + in.Perses.DeepCopyInto(&out.Perses) in.KubedbUi.DeepCopyInto(&out.KubedbUi) in.PlatformApi.DeepCopyInto(&out.PlatformApi) in.IngressNginx.DeepCopyInto(&out.IngressNginx) @@ -2284,6 +2306,59 @@ func (in *AppIngressDns) DeepCopy() *AppIngressDns { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthProviders) DeepCopyInto(out *AuthProviders) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthProviders. +func (in *AuthProviders) DeepCopy() *AuthProviders { + if in == nil { + return nil + } + out := new(AuthProviders) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticationConfig) DeepCopyInto(out *AuthenticationConfig) { + *out = *in + out.Providers = in.Providers +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationConfig. +func (in *AuthenticationConfig) DeepCopy() *AuthenticationConfig { + if in == nil { + return nil + } + out := new(AuthenticationConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationConfig) DeepCopyInto(out *AuthorizationConfig) { + *out = *in + if in.GuestPermissions != nil { + in, out := &in.GuestPermissions, &out.GuestPermissions + *out = make([]Permission, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationConfig. +func (in *AuthorizationConfig) DeepCopy() *AuthorizationConfig { + if in == nil { + return nil + } + out := new(AuthorizationConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AutoscalingSpec) DeepCopyInto(out *AutoscalingSpec) { *out = *in @@ -3452,6 +3527,22 @@ func (in *DNSProxyAuth) DeepCopy() *DNSProxyAuth { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseConfig) DeepCopyInto(out *DatabaseConfig) { + *out = *in + out.SQL = in.SQL +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseConfig. +func (in *DatabaseConfig) DeepCopy() *DatabaseConfig { + if in == nil { + return nil + } + out := new(DatabaseConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DeployUi) DeepCopyInto(out *DeployUi) { *out = *in @@ -8965,6 +9056,93 @@ func (in *OutboxSyncerSpec) DeepCopy() *OutboxSyncerSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Permission) DeepCopyInto(out *Permission) { + *out = *in + if in.Actions != nil { + in, out := &in.Actions, &out.Actions + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Scopes != nil { + in, out := &in.Scopes, &out.Scopes + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Permission. +func (in *Permission) DeepCopy() *Permission { + if in == nil { + return nil + } + out := new(Permission) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PersesConfig) DeepCopyInto(out *PersesConfig) { + *out = *in + in.Security.DeepCopyInto(&out.Security) + out.Database = in.Database +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersesConfig. +func (in *PersesConfig) DeepCopy() *PersesConfig { + if in == nil { + return nil + } + out := new(PersesConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PersesSettings) DeepCopyInto(out *PersesSettings) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersesSettings. +func (in *PersesSettings) DeepCopy() *PersesSettings { + if in == nil { + return nil + } + out := new(PersesSettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PersesSpec) DeepCopyInto(out *PersesSpec) { + *out = *in + in.Config.DeepCopyInto(&out.Config) + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.PodAnnotations != nil { + in, out := &in.PodAnnotations, &out.PodAnnotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersesSpec. +func (in *PersesSpec) DeepCopy() *PersesSpec { + if in == nil { + return nil + } + out := new(PersesSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PersistenceSpec) DeepCopyInto(out *PersistenceSpec) { *out = *in @@ -10667,6 +10845,21 @@ func (in *SMTPConfig) DeepCopy() *SMTPConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SQLConfig) DeepCopyInto(out *SQLConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SQLConfig. +func (in *SQLConfig) DeepCopy() *SQLConfig { + if in == nil { + return nil + } + out := new(SQLConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecretKeySelector) DeepCopyInto(out *SecretKeySelector) { *out = *in @@ -10683,6 +10876,23 @@ func (in *SecretKeySelector) DeepCopy() *SecretKeySelector { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityConfig) DeepCopyInto(out *SecurityConfig) { + *out = *in + out.Authentication = in.Authentication + in.Authorization.DeepCopyInto(&out.Authorization) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityConfig. +func (in *SecurityConfig) DeepCopy() *SecurityConfig { + if in == nil { + return nil + } + out := new(SecurityConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecuritySettings) DeepCopyInto(out *SecuritySettings) { *out = *in @@ -11303,6 +11513,7 @@ func (in *Settings) DeepCopyInto(out *Settings) { in.Platform.DeepCopyInto(&out.Platform) out.Security = in.Security out.Grafana = in.Grafana + out.Perses = in.Perses out.InboxServer = in.InboxServer out.Contract = in.Contract out.Firebase = in.Firebase diff --git a/charts/ace-installer/README.md b/charts/ace-installer/README.md index c09808bcd..7a308b353 100644 --- a/charts/ace-installer/README.md +++ b/charts/ace-installer/README.md @@ -102,6 +102,8 @@ The following table lists the configurable parameters of the `ace-installer` cha | helm.releases.panopticon.enabled | | true | | helm.releases.panopticon.version | | "v2026.1.15" | | helm.releases.panopticon.values | | {"monitoring":{"agent":"prometheus.io/operator","enabled":true,"serviceMonitor":{"labels":{"release":"kube-prometheus-stack"}}}} | +| helm.releases.prom-label-proxy.enabled | | false | +| helm.releases.prom-label-proxy.version | | "v2026.4.30" | | helm.releases.reloader.enabled | | true | | helm.releases.reloader.version | | "2.2.9" | | helm.releases.service-gateway-presets.enabled | | false | diff --git a/charts/ace-installer/templates/presets/bootstrap-presets.yaml b/charts/ace-installer/templates/presets/bootstrap-presets.yaml index e8f6de29a..c93113393 100644 --- a/charts/ace-installer/templates/presets/bootstrap-presets.yaml +++ b/charts/ace-installer/templates/presets/bootstrap-presets.yaml @@ -33,6 +33,8 @@ opscenter-features: values: %s license-proxyserver: values: %s + prom-label-proxy: + values: %s service-gateway-presets: values: %s stash-presets: @@ -49,6 +51,7 @@ opscenter-features: ((dig "opscenter-features" "values" "helm" "releases" "kubedb" "values" (dict) $.Values.helm.releases) | toJson) ((dig "opscenter-features" "values" "helm" "releases" "kubestash" "values" (dict) $.Values.helm.releases) | toJson) ((dig "opscenter-features" "values" "helm" "releases" "license-proxyserver" "values" (dict) $.Values.helm.releases) | toJson) + ((dig "opscenter-features" "values" "helm" "releases" "prom-label-proxy" "values" (dict) $.Values.helm.releases) | toJson) ((dig "opscenter-features" "values" "helm" "releases" "service-gateway-presets" "values" (dict) $.Values.helm.releases) | toJson) ((dig "opscenter-features" "values" "helm" "releases" "stash-presets" "values" (dict) $.Values.helm.releases) | toJson) | fromYaml }} diff --git a/charts/ace-installer/values.yaml b/charts/ace-installer/values.yaml index b488ef476..cefa305af 100644 --- a/charts/ace-installer/values.yaml +++ b/charts/ace-installer/values.yaml @@ -123,6 +123,9 @@ helm: serviceMonitor: labels: release: kube-prometheus-stack + prom-label-proxy: + enabled: false + version: "v2026.4.30" reloader: enabled: true version: "2.2.9" diff --git a/charts/ace/Chart.yaml b/charts/ace/Chart.yaml index c39627c9a..36b4e2e46 100644 --- a/charts/ace/Chart.yaml +++ b/charts/ace/Chart.yaml @@ -64,3 +64,7 @@ dependencies: repository: file://../platform-opscenter condition: platform-opscenter.enabled version: v2026.5.22 +- name: perses + repository: oci://ghcr.io/appscode-charts + condition: perses.enabled + version: v2026.4.30 \ No newline at end of file diff --git a/charts/ace/README.md b/charts/ace/README.md index 8fdd7fc54..b49edd91b 100644 --- a/charts/ace/README.md +++ b/charts/ace/README.md @@ -50,6 +50,7 @@ The following table lists the configurable parameters of the `ace` chart and the | platform-ui.enabled | | false | | cluster-ui.enabled | | false | | grafana.enabled | | false | +| perses.enabled | | false | | kubedb-ui.enabled | | false | | platform-api.enabled | | false | | gateway.annotations | | {} | @@ -188,6 +189,7 @@ The following table lists the configurable parameters of the `ace` chart and the | settings.platform.logoutURL | redirect url after logout | "" | | settings.grafana.appMode | possible values : production, development | production | | settings.grafana.secretKey | | 4nHrUDNw00AjlhAq8hCGYPxBt6I1UCbmdC5ReY19IPWdy8qFDzTZzXkdCr5d6qwP | +| settings.perses.encryptionKey | | "" | | settings.inboxServer.jmapURL | | "" | | settings.inboxServer.webAdminURL | | "" | | settings.inboxServer.emailDomain | | "" | diff --git a/charts/ace/templates/gateway/route-main.yaml b/charts/ace/templates/gateway/route-main.yaml index 58c3c0d9c..4fe5fb8b0 100644 --- a/charts/ace/templates/gateway/route-main.yaml +++ b/charts/ace/templates/gateway/route-main.yaml @@ -85,6 +85,7 @@ spec: namespace: {{ .Release.Namespace }} port: 80 weight: 1 + {{- if (index .Values "grafana" "enabled") }} - matches: - path: type: PathPrefix @@ -99,6 +100,23 @@ spec: timeouts: backendRequest: 2m request: 2m + {{- end }} + {{- if (index .Values "perses" "enabled") }} + - matches: + - path: + type: PathPrefix + value: /observe + backendRefs: + - group: "" + kind: Service + name: {{ include "ace.fullname" . }}-perses + namespace: {{ .Release.Namespace }} + port: 8080 + weight: 1 + timeouts: + backendRequest: 2m + request: 2m + {{- end }} - matches: - path: type: PathPrefix diff --git a/charts/ace/templates/platform/setup-config.yaml b/charts/ace/templates/platform/setup-config.yaml index ba49053d7..3a4b87ad4 100644 --- a/charts/ace/templates/platform/setup-config.yaml +++ b/charts/ace/templates/platform/setup-config.yaml @@ -18,6 +18,7 @@ stringData: reloadPlatformAccounts: true {{- end }} importerServiceAccount: {{ include "appscode.serviceAccountName" . }}-importer + syncPersesAccounts: true {{- with .Values.setupJob.config }} {{- . | toYaml | nindent 4 }} {{- end }} diff --git a/charts/ace/values.openapiv3_schema.yaml b/charts/ace/values.openapiv3_schema.yaml index 9abb223f2..e3cf2435d 100644 --- a/charts/ace/values.openapiv3_schema.yaml +++ b/charts/ace/values.openapiv3_schema.yaml @@ -18680,6 +18680,155 @@ properties: - volumeMounts - volumes type: object + perses: + properties: + config: + properties: + api_prefix: + type: string + database: + properties: + sql: + properties: + addr: + type: string + allow_native_passwords: + type: boolean + db_name: + type: string + password: + type: string + user: + type: string + type: object + type: object + security: + properties: + authentication: + properties: + providers: + properties: + enable_native: + type: boolean + type: object + type: object + authorization: + properties: + guest_permissions: + items: + properties: + actions: + items: + type: string + type: array + scopes: + items: + type: string + type: array + type: object + type: array + type: object + enable_auth: + type: boolean + encryption_key: + type: string + type: object + type: object + enabled: + type: boolean + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + podAnnotations: + additionalProperties: + type: string + type: object + required: + - config + - enabled + - env + - podAnnotations + type: object pgoutbox: properties: affinity: @@ -24481,6 +24630,13 @@ properties: - apiURL - preSharedKey type: object + perses: + properties: + encryptionKey: + type: string + required: + - encryptionKey + type: object platform: properties: appName: @@ -24617,6 +24773,7 @@ properties: - inboxServer - nats - openfga + - perses - platform - security - smtp @@ -27403,6 +27560,7 @@ required: - nats-dns - openfga - outbox-syncer +- perses - pgoutbox - platform-api - platform-ui diff --git a/charts/ace/values.yaml b/charts/ace/values.yaml index a1399098a..1fd3ac45f 100644 --- a/charts/ace/values.yaml +++ b/charts/ace/values.yaml @@ -11,6 +11,9 @@ cluster-ui: grafana: enabled: false +perses: + enabled: false + kubedb-ui: enabled: false @@ -419,6 +422,9 @@ settings: appMode: production secretKey: 4nHrUDNw00AjlhAq8hCGYPxBt6I1UCbmdC5ReY19IPWdy8qFDzTZzXkdCr5d6qwP + perses: + encryptionKey: "" + inboxServer: jmapURL: "" webAdminURL: "" diff --git a/charts/opscenter-features/README.md b/charts/opscenter-features/README.md index 35f6f3b4c..0941e8b8c 100644 --- a/charts/opscenter-features/README.md +++ b/charts/opscenter-features/README.md @@ -71,7 +71,7 @@ The following table lists the configurable parameters of the `opscenter-features | helm.createNamespace | | true | | helm.repositories.appscode-charts-oci.url | | oci://ghcr.io/appscode-charts | | helm.releases.aceshifter.version | | "v2026.5.22" | -| helm.releases.appscode-otel-stack.version | | "v2025.2.28" | +| helm.releases.appscode-otel-stack.version | | "v2026.5.22" | | helm.releases.aws-credential-manager.version | | "v2026.1.20" | | helm.releases.azure-credential-manager.version | | "v2026.4.16" | | helm.releases.gcp-credential-manager.version | | "v2026.3.11" | @@ -96,7 +96,7 @@ The following table lists the configurable parameters of the `opscenter-features | helm.releases.gatekeeper-grafana-dashboards.version | | "v2023.10.1" | | helm.releases.gatekeeper-library.version | | "v2023.10.1" | | helm.releases.gateway-api.version | | "v2025.3.14" | -| helm.releases.grafana-operator.version | | "v2026.3.30" | +| helm.releases.grafana-operator.version | | "v2026.5.22" | | helm.releases.keda.version | | "2.19.0" | | helm.releases.keda-add-ons-http.version | | "0.12.0" | | helm.releases.kube-grafana-dashboards.version | | "v2023.10.1" | @@ -116,7 +116,7 @@ The following table lists the configurable parameters of the `opscenter-features | helm.releases.license-proxyserver.version | | "v2026.2.16" | | helm.releases.longhorn.version | | "1.7.2" | | helm.releases.metrics-server.version | | "3.11.0" | -| helm.releases.monitoring-operator.version | | "v2026.3.30" | +| helm.releases.monitoring-operator.version | | "v2026.5.22" | | helm.releases.monitoring-operator.values.alertmanager.email.enabled | | false | | helm.releases.monitoring-operator.values.alertmanager.email.to | | "" | | helm.releases.monitoring-operator.values.alertmanager.email.from | | "" | @@ -135,6 +135,7 @@ The following table lists the configurable parameters of the `opscenter-features | helm.releases.panopticon.version | | "v2026.1.15" | | helm.releases.prepare-cluster.version | | "v2023.12.21" | | helm.releases.prometheus-adapter.version | | "4.9.0" | +| helm.releases.prom-label-proxy.version | | "v2026.5.22" | | helm.releases.reloader.version | | "2.2.9" | | helm.releases.scanner.version | | "v2026.1.15" | | helm.releases.service-backend.version | | "v2026.5.22" | @@ -147,6 +148,8 @@ The following table lists the configurable parameters of the `opscenter-features | helm.releases.stash-opscenter.version | | "v2025.7.31" | | helm.releases.stash-presets.version | | "v2026.5.22" | | helm.releases.supervisor.version | | "v2026.1.15" | +| helm.releases.tenant-operator.version | | "v2026.5.22" | +| helm.releases.thanos-operator.version | | "v2026.5.22" | | helm.releases.topolvm.version | | "15.0.0" | | helm.releases.voyager.version | | "v2026.3.23" | | helm.releases.voyager-gateway.version | | "v2026.1.15" | diff --git a/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/appscode-otel-stack.yaml b/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/appscode-otel-stack.yaml new file mode 100644 index 000000000..c3eb68b75 --- /dev/null +++ b/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/appscode-otel-stack.yaml @@ -0,0 +1,50 @@ +{{ $defaults := dict "registryFQDN" (include "registry.ghcr" $) }} + +{{ $vals := dig "appscode-otel-stack" "values" (dict) .Values.helm.releases }} +{{ $vals = mergeOverwrite $defaults $vals }} + +{{- if eq (include "distro.openshift" $) "true" }} +{{ $vals = mergeOverwrite $vals (dict "distro" .Values.distro) }} +{{- end }} + +apiVersion: ui.k8s.appscode.com/v1alpha1 +kind: Feature +metadata: + name: appscode-otel-stack + labels: + app.kubernetes.io/part-of: opscenter-observability +spec: + title: AppsCode OTEL Stack + description: | + Deploy and manage OpenTelemetry collectors and pipelines for traces, metrics, and logs in Kubernetes. + icons: + - src: https://cdn.appscode.com/k8s/icons/menu/cluster.svg + type: image/svg+xml + featureSet: opscenter-observability + featureBlock: appscode-otel-stack + recommended: true + requirements: + features: + - monitoring-operator + readinessChecks: + workloads: + - group: apps + version: v1 + kind: Deployment + selector: + app.kubernetes.io/component: opentelemetry-collector + app.kubernetes.io/instance: monitoring.appscode-otel-stack-gateway + app.kubernetes.io/managed-by: opentelemetry-operator + app.kubernetes.io/name: appscode-otel-stack-gateway-collector + chart: + name: appscode-otel-stack + namespace: monitoring + createNamespace: {{ $.Values.helm.createNamespace }} + version: {{ dig "appscode-otel-stack" "version" "" $.Values.helm.releases }} + sourceRef: + kind: HelmRepository + name: appscode-charts-oci + namespace: {{ .Release.Namespace }} +{{- with $vals }} + {{- dict "values" . | toYaml | nindent 2 }} +{{- end }} diff --git a/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/prom-label-proxy.yaml b/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/prom-label-proxy.yaml new file mode 100644 index 000000000..72dcd7dec --- /dev/null +++ b/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/prom-label-proxy.yaml @@ -0,0 +1,49 @@ +{{ $defaults := dict "registryFQDN" (include "registry.ghcr" $) }} + +{{ $vals := dig "prom-label-proxy" "values" (dict) .Values.helm.releases }} +{{ $vals = mergeOverwrite $defaults $vals }} + +{{- if eq (include "distro.openshift" $) "true" }} +{{ $vals = mergeOverwrite $vals (dict "distro" .Values.distro) }} +{{- end }} + +apiVersion: ui.k8s.appscode.com/v1alpha1 +kind: Feature +metadata: + name: prom-label-proxy + labels: + app.kubernetes.io/part-of: opscenter-observability +spec: + title: Prometheus Label Proxy + description: | + Enforce label-based tenant isolation for Prometheus queries, restricting data access per namespace or team. + icons: + - src: https://cdn.appscode.com/k8s/icons/menu/cluster.svg + type: image/svg+xml + featureSet: opscenter-observability + featureBlock: tenant-operator + recommended: true + requirements: + features: + - thanos-operator + - gateway-api + - catalog-manager + readinessChecks: + workloads: + - group: apps + version: v1 + kind: Deployment + selector: + app.kubernetes.io/name: prom-label-proxy + chart: + name: prom-label-proxy + namespace: monitoring + createNamespace: {{ $.Values.helm.createNamespace }} + version: {{ dig "appscode-otel-stack" "version" "" $.Values.helm.releases }} + sourceRef: + kind: HelmRepository + name: appscode-charts-oci + namespace: {{ .Release.Namespace }} +{{- with $vals }} + {{- dict "values" . | toYaml | nindent 2 }} +{{- end }} diff --git a/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/tenant-operator.yaml b/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/tenant-operator.yaml new file mode 100644 index 000000000..a1b1010e8 --- /dev/null +++ b/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/tenant-operator.yaml @@ -0,0 +1,48 @@ +{{ $defaults := dict "registryFQDN" (include "registry.ghcr" $) }} + +{{ $vals := dig "tenant-operator" "values" (dict) .Values.helm.releases }} +{{ $vals = mergeOverwrite $defaults $vals }} + +{{- if eq (include "distro.openshift" $) "true" }} +{{ $vals = mergeOverwrite $vals (dict "distro" .Values.distro) }} +{{- end }} + +apiVersion: ui.k8s.appscode.com/v1alpha1 +kind: Feature +metadata: + name: tenant-operator + labels: + app.kubernetes.io/part-of: opscenter-observability +spec: + title: Tenant Operator + description: | + Manage multi-tenant observability by isolating monitoring resources and access per tenant in Kubernetes. + icons: + - src: https://cdn.appscode.com/k8s/icons/menu/cluster.svg + type: image/svg+xml + featureSet: opscenter-observability + featureBlock: tenant-operator + recommended: true + requirements: + features: + - prom-label-proxy + - thanos-operator + readinessChecks: + workloads: + - group: apps + version: v1 + kind: Deployment + selector: + app.kubernetes.io/name: tenant-operator + chart: + name: tenant-operator + namespace: monitoring + createNamespace: {{ $.Values.helm.createNamespace }} + version: {{ dig "tenant-operator" "version" "" $.Values.helm.releases }} + sourceRef: + kind: HelmRepository + name: appscode-charts-oci + namespace: {{ .Release.Namespace }} +{{- with $vals }} + {{- dict "values" . | toYaml | nindent 2 }} +{{- end }} diff --git a/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/thanos-operator.yaml b/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/thanos-operator.yaml new file mode 100644 index 000000000..d3dd3c82e --- /dev/null +++ b/charts/opscenter-features/templates/featuresets/opscenter-observability/telemetry-stack/thanos-operator.yaml @@ -0,0 +1,47 @@ +{{ $defaults := dict "registryFQDN" (include "registry.ghcr" $) }} + +{{ $vals := dig "thanos-operator" "values" (dict) .Values.helm.releases }} +{{ $vals = mergeOverwrite $defaults $vals }} + +{{- if eq (include "distro.openshift" $) "true" }} +{{ $vals = mergeOverwrite $vals (dict "distro" .Values.distro) }} +{{- end }} + +apiVersion: ui.k8s.appscode.com/v1alpha1 +kind: Feature +metadata: + name: thanos-operator + labels: + app.kubernetes.io/part-of: opscenter-observability +spec: + title: Thanos Operator + description: | + Manage Thanos components for highly available, long-term Prometheus metrics storage and global querying. + icons: + - src: https://cdn.appscode.com/k8s/icons/menu/cluster.svg + type: image/svg+xml + featureSet: opscenter-observability + featureBlock: tenant-operator + recommended: true + readinessChecks: + workloads: + - group: apps + version: v1 + kind: Deployment + selector: + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: thanos-operator + app.kubernetes.io/part-of: thanos-operator + control-plane: controller-manager + chart: + name: thanos-operator + namespace: monitoring + createNamespace: {{ $.Values.helm.createNamespace }} + version: {{ dig "appscode-otel-stack" "version" "" $.Values.helm.releases }} + sourceRef: + kind: HelmRepository + name: appscode-charts-oci + namespace: {{ .Release.Namespace }} +{{- with $vals }} + {{- dict "values" . | toYaml | nindent 2 }} +{{- end }} diff --git a/charts/opscenter-features/values.yaml b/charts/opscenter-features/values.yaml index 8d35f59ee..80b92ba26 100644 --- a/charts/opscenter-features/values.yaml +++ b/charts/opscenter-features/values.yaml @@ -57,7 +57,7 @@ helm: aceshifter: version: "v2026.5.22" appscode-otel-stack: - version: "v2025.2.28" + version: "v2026.5.22" aws-credential-manager: version: "v2026.1.20" azure-credential-manager: @@ -107,7 +107,7 @@ helm: gateway-api: version: "v2025.3.14" grafana-operator: - version: "v2026.3.30" + version: "v2026.5.22" keda: version: "2.19.0" keda-add-ons-http: @@ -147,7 +147,7 @@ helm: metrics-server: version: "3.11.0" monitoring-operator: - version: "v2026.3.30" + version: "v2026.5.22" values: alertmanager: email: @@ -177,6 +177,8 @@ helm: version: "v2023.12.21" prometheus-adapter: version: "4.9.0" + prom-label-proxy: + version: "v2026.5.22" reloader: version: "2.2.9" scanner: @@ -201,6 +203,10 @@ helm: version: "v2026.5.22" supervisor: version: "v2026.1.15" + tenant-operator: + version: "v2026.5.22" + thanos-operator: + version: "v2026.5.22" topolvm: version: "15.0.0" voyager: diff --git a/features.md b/features.md index bb3ad7660..29a803e7c 100644 --- a/features.md +++ b/features.md @@ -41,6 +41,12 @@ graph TD; kube-prometheus-stack-->monitoring-operator; panopticon-->license-proxyserver; prometheus-adapter-->kube-prometheus-stack; + appscode-otel-stack-->monitoring-operator; + prom-label-proxy-->thanos-operator; + prom-label-proxy-->gateway-api; + prom-label-proxy-->catalog-manager; + tenant-operator-->prom-label-proxy; + tenant-operator-->thanos-operator; gatekeeper-constraints-->gatekeeper; gatekeeper-constraints-->gatekeeper-templates; gatekeeper-grafana-dashboards-->gatekeeper; diff --git a/schema/ace-options/values.openapiv3_schema.yaml b/schema/ace-options/values.openapiv3_schema.yaml index e2049bc28..710e6f90f 100644 --- a/schema/ace-options/values.openapiv3_schema.yaml +++ b/schema/ace-options/values.openapiv3_schema.yaml @@ -231,6 +231,8 @@ properties: required: - preSharedKeys type: object + persesEncryptionKey: + type: string postgresPassword: type: string promotedToProduction: @@ -1746,6 +1748,89 @@ properties: DynamicResourceAllocation feature gate. + This field is immutable. It can only be set for containers.' + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: 'Name must match the name of one entry in pod.spec.resourceClaims + of + + the Pod where this field is used. It makes that resource available + + inside a container.' + type: string + request: + description: 'Request is the name chosen for a request in the referenced + claim. + + If empty, everything from the claim is made available, otherwise + + only the result of this request.' + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources + allowed. + + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources + required. + + If Requests is omitted for a container, it defaults to Limits if that + is explicitly specified, + + otherwise to an implementation-defined value. Requests cannot exceed + Limits. + + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - enabled + type: object + perses: + properties: + enabled: + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: 'Claims lists the names of resources, defined in spec.resourceClaims, + + that are used by this container. + + + This field depends on the + + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers.' items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -2616,6 +2701,7 @@ required: - nats - openfga - outbox-syncer + - perses - pgoutbox - platform-api - platform-ui