Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This document maps the current Helm chart values to the resources created by the
| --- | --- |
| `Deployment` | Runs the controller manager and gateway sidecar |
| `Service` | Exposes metrics and webhook endpoints |
| `ServiceMonitor` | Optional Prometheus scrape target for the metrics Service |
| `MutatingWebhookConfiguration` | Registers pod mutation webhook |
| `ValidatingWebhookConfiguration` | Registers validation webhook |
| `Secret` | Stores gateway credentials and TLS material when `createSecrets=true` |
Expand Down Expand Up @@ -103,10 +104,16 @@ Note: `kubexCredentials.userSecretName` is currently not consumed by this chart.
| `webhook.certManager.enabled` | `false` | Use cert-manager instead of self-signed TLS |
| `selfSignedCert.validity` | `3650` | Self-signed certificate validity in days |
| `controllerManager.globalConfigReconcileInterval` | `1m` | Base reconcile cadence for global config controller |
| `controllerManager.metricsBindAddress` | `:8080` | Metrics bind address used by the controller manager |
| `kubex.requestTimeout` | `30s` | Kubex API request timeout |
| `podSecurityContext` | chart default | Pod-level security context for the controller Deployment; defaults to `65534` for `runAsUser`, `runAsGroup`, and `fsGroup`, plus `runAsNonRoot=true` and `seccompProfile.type=RuntimeDefault` |
| `openshift.enabled` | `false` | Enable OpenShift-oriented pod security context defaults and cleanup job settings without changing the default Kubernetes installation path |
| `openshift.fsGroup` | `null` | Optional `fsGroup` applied when `openshift.enabled=true` unless already set in `podSecurityContext` |
| `metrics.serviceMonitor.enabled` | `false` | Create a Prometheus Operator `ServiceMonitor` for the metrics Service |
| `metrics.port` | `8080` | Service port for the metrics Service |
| `metrics.serviceMonitor.namespaceSelector` | `[]` | Namespace names to watch from the ServiceMonitor; empty means all namespaces |
| `metrics.serviceMonitor.scheme` | `http` | Scrape scheme for the controller metrics endpoint; HTTP pairs with `--metrics-secure=false` in the manager args |
| `metrics.serviceMonitor.scrapeTimeout` | `""` | Optional scrape timeout; must be less than or equal to `metrics.serviceMonitor.interval` when set |
| `gateway.securityContext` | chart default | Gateway sidecar container security context |
| `cleanup.podSecurityContext` | `{}` | Optional pod security context for the pre-delete cleanup job |
| `cleanup.securityContext` | chart default | Container security context for the pre-delete cleanup job |
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONTENT OF THIS REVIEW IS AI GENERATED

[Severity: Minor] [Confidence: Medium]

Location: charts/kubex-automation-engine/docs/Configuration-Reference.md:119

Issue: The documentation table documents several new metrics.serviceMonitor.* fields but is missing metrics.serviceMonitor.interval, metrics.serviceMonitor.additionalLabels, metrics.serviceMonitor.path, and metrics.serviceMonitor.enabled is only listed once without the co-related guard condition (metrics.enabled must also be true).

Why it matters: Incomplete documentation is a usability issue — operators scanning the reference table cannot discover all available knobs, particularly for the interval and path values that affect scrape behaviour.

Suggested fix: Add rows for metrics.serviceMonitor.interval ("") and metrics.serviceMonitor.additionalLabels ({}), metrics.serviceMonitor.path (/metrics), and update the metrics.serviceMonitor.enabled row description to note that metrics.enabled must also be true.

Expand Down
10 changes: 10 additions & 0 deletions charts/kubex-automation-engine/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,22 @@ Controller manager container args
- --health-probe-bind-address={{ .Values.controllerManager.healthProbeBindAddress }}
{{- if .Values.metrics.enabled }}
- --metrics-bind-address={{ .Values.controllerManager.metricsBindAddress }}
{{- include "kubex-automation-engine.metricsSecureArg" . }}
{{- end }}
{{- range .Values.controllerManager.extraArgs }}
- {{ . }}
{{- end }}
{{- end }}

{{/*
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONTENT OF THIS REVIEW IS AI GENERATED

[Severity: Major] [Confidence: High]

Location: charts/kubex-automation-engine/templates/_helpers.tpl:129

Issue: --metrics-secure=false is injected solely based on metrics.serviceMonitor.scheme, but serviceMonitor can be disabled (metrics.serviceMonitor.enabled=false) while scheme still defaults to "http". In that case the flag is still emitted even though no ServiceMonitor exists and a user may actually want a secured endpoint while using pod-annotation-based scraping.

Why it matters: The security posture of the metrics endpoint is silently degraded to unauthenticated HTTP any time metrics.enabled=true and metrics.serviceMonitor.scheme is "http" (the default), regardless of whether the ServiceMonitor feature is used. This could expose controller metrics without the operator realising.

Suggested fix: Introduce a dedicated, explicit metrics.secure (or metrics.serviceMonitor.secure) boolean that defaults to false, and drive --metrics-secure=false from that value instead of inferring it from scheme. Alternatively, scope the condition to also require metrics.serviceMonitor.enabled=true:

-{{- if and .Values.metrics.enabled (eq .Values.metrics.serviceMonitor.scheme "http") }}
+{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled (eq .Values.metrics.serviceMonitor.scheme "http") }}

Controller metrics security flag.
*/}}
{{- define "kubex-automation-engine.metricsSecureArg" -}}
{{- if and .Values.metrics.enabled (eq .Values.metrics.serviceMonitor.scheme "http") }}
- --metrics-secure=false
{{- end }}
{{- end }}

{{/*
Generate or retrieve self-signed certificates for webhook
Returns a dict with ca, cert, and key
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ metadata:
{{- include "kubex-automation-engine.labels" . | nindent 4 }}
{{- with .Values.metrics.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- tpl (toYaml .) $ | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.metrics.type }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled -}}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "kubex-automation-engine.fullname" . }}-metrics
namespace: {{ include "kubex-automation-engine.namespace" . }}
labels:
{{- include "kubex-automation-engine.labels" . | nindent 4 }}
{{- with .Values.metrics.serviceMonitor.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.metrics.serviceMonitor.namespaceSelector }}
namespaceSelector:
matchNames:
{{- toYaml . | nindent 6 }}
{{- else }}
namespaceSelector:
any: true
{{- end }}
selector:
matchLabels:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONTENT OF THIS REVIEW IS AI GENERATED

[Severity: Minor] [Confidence: High]

Location: charts/kubex-automation-engine/templates/metrics-servicemonitor.yaml:22

Issue: The selector.matchLabels reuses kubex-automation-engine.selectorLabels, which typically includes the app.kubernetes.io/version label. If the chart version changes between the Service and the ServiceMonitor being applied (e.g. a rolling upgrade), the version label mismatch can cause Prometheus to temporarily lose scrape targets.

Why it matters: Pod selector labels (used for workload matching) are appropriate for Deployments, but ServiceMonitor selectors should typically only match stable, non-version labels. Version churn during upgrades silently breaks scraping until the reconciler catches up.

Suggested fix: Consider using a subset of labels that excludes app.kubernetes.io/version, or define a dedicated kubex-automation-engine.metricsServiceSelectorLabels helper that only emits the stable app.kubernetes.io/name and app.kubernetes.io/instance labels.

{{- include "kubex-automation-engine.selectorLabels" . | nindent 6 }}
endpoints:
- port: metrics
path: {{ .Values.metrics.serviceMonitor.path }}
scheme: {{ .Values.metrics.serviceMonitor.scheme }}
# tlsConfig:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONTENT OF THIS REVIEW IS AI GENERATED

[Severity: Minor] [Confidence: High]

Location: charts/kubex-automation-engine/templates/metrics-servicemonitor.yaml:28

Issue: Commented-out TLS config blocks (# tlsConfig: ...) are left in the shipped template. Commented-out code in a production Helm template adds noise, signals an incomplete design, and can be misleading to operators who may not realize those fields are inoperative.

Why it matters: If TLS scraping is a future-planned feature, this is better tracked as a GitHub issue or a NOTES.txt notice. If it is not needed when scheme: https is chosen, users will look for TLS config options that do not exist and have no way to configure them.

Suggested fix: Remove the commented-out block entirely. If HTTPS scraping is intended to be supported, add a metrics.serviceMonitor.tlsConfig value key and render it conditionally, or note the limitation in NOTES.txt.

# caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# insecureSkipVerify: true
# bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
{{- with .Values.metrics.serviceMonitor.interval }}
interval: {{ . }}
{{- end }}
{{- with .Values.metrics.serviceMonitor.scrapeTimeout }}
scrapeTimeout: {{ . }}
{{- end }}
{{- end }}
47 changes: 47 additions & 0 deletions charts/kubex-automation-engine/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,53 @@
}
}
},
"metrics": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"type": {
"type": "string"
},
"port": {
"type": "integer"
},
"annotations": {
"type": "object"
},
"serviceMonitor": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"additionalLabels": {
"type": "object"
},
"namespaceSelector": {
"type": "array",
"items": {
"type": "string"
}
},
"scheme": {
"type": "string",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONTENT OF THIS REVIEW IS AI GENERATED

[Severity: Minor] [Confidence: High]

Location: charts/kubex-automation-engine/values.schema.json:138

Issue: The JSON schema metrics object does not set "additionalProperties": false and does not list required for any of its properties, which means Helm schema validation will silently accept typos like serviceMoniotr or enabeld without error.

Why it matters: Schema validation is the last line of defence against silent misconfiguration. Without additionalProperties: false, unknown keys pass through unchallenged and features like serviceMonitor simply never activate, with no user-visible error.

Suggested fix: Add "additionalProperties": false to both the outer metrics object and the nested serviceMonitor object, consistent with how other Helm chart schemas are typically structured.

"enum": ["http", "https"]
},
"path": {
"type": "string"
},
"interval": {
"type": "string"
},
"scrapeTimeout": {
"type": "string"
}
}
}
}
},
"openshift": {
"type": "object",
"properties": {
Expand Down
27 changes: 24 additions & 3 deletions charts/kubex-automation-engine/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ controllerManager:
healthProbeBindAddress: ":8081"

# -- Metrics bind address
metricsBindAddress: ":8443"
metricsBindAddress: ":8080"

# -- Additional arguments for the controller manager
extraArgs:
Expand Down Expand Up @@ -180,9 +180,30 @@ metrics:
# -- Service type for metrics
type: ClusterIP
# -- Service port for metrics
port: 8443
port: 8080
# -- Service annotations
annotations: {}
annotations:
# Controller metrics are served over plain HTTP without authentication in this chart; the manager args set --metrics-secure=false when this scheme is used.
prometheus.io/scrape: "true"
prometheus.io/port: '{{ .Values.metrics.port }}'
prometheus.io/path: '{{ .Values.metrics.serviceMonitor.path }}'
prometheus.io/scheme: '{{ .Values.metrics.serviceMonitor.scheme }}'
# -- Optional ServiceMonitor configuration for Prometheus Operator
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONTENT OF THIS REVIEW IS AI GENERATED

[Severity: Major] [Confidence: High]

Location: charts/kubex-automation-engine/values.yaml:191

Issue: The default annotations block embeds Go template expressions (e.g. '{{ .Values.metrics.port }}') directly in values.yaml. These are not rendered by helm template when read from values.yaml at the values-layer; they are only rendered because metrics-service.yaml now calls tpl on the annotation block. However, values.schema.json declares annotations as "type": "object" with no special treatment — a user who overrides annotations with plain values (no template expressions) will still have them passed through tpl, which is safe, but any user who passes a value containing {{ in a legitimate non-template string (e.g. a Go format string) will get a Helm render error.

Why it matters: Using tpl on user-supplied annotation values is a well-known footgun: it silently breaks if annotation values happen to contain {{ characters, and it creates an implicit contract (users must escape {{ as {{"{{"}}) that is not documented.

Suggested fix: If templated annotations are really required, document this contract clearly in the values comments, and consider using a named helper with a specific prefix convention instead of templating the entire annotations block. Alternatively, move the templated annotations out of the default values.yaml and into a helper or hardcode the known values so plain toYaml can be used again.

serviceMonitor:
# -- Create a ServiceMonitor for the metrics Service
enabled: false
# -- Additional labels applied to the ServiceMonitor
additionalLabels: {}
# -- Namespace names to discover for the ServiceMonitor. Leave empty to watch all namespaces.
namespaceSelector: []
# -- Scrape scheme used by Prometheus
scheme: http
# -- Metrics endpoint path
path: /metrics
# -- Optional scrape interval
interval: ""
# -- Optional scrape timeout. Must be <= interval when interval is set.
scrapeTimeout: ""

# Webhook configuration
webhook:
Expand Down