diff --git a/charts/lerian-common/README.md b/charts/lerian-common/README.md index 29cfe0d2d..a0e3cc2fe 100644 --- a/charts/lerian-common/README.md +++ b/charts/lerian-common/README.md @@ -13,6 +13,14 @@ via `include` by the product charts that declare it as a dependency. each helper stays **inert until `global.*` is set** (backward-compatible); `serviceDiscovery.env` additionally activates from a legacy `configmap.SD_ADDRESS`, and a component `configmap.SD_*` value takes precedence over the `global.*` default. + The external endpoint (`SD_EXTERNAL_ADDRESS`/`SD_EXTERNAL_PORT`) is derived from + the Ingress host when present, **and** is preserved when supplied explicitly via + legacy `configmap.SD_EXTERNAL_*` even with no Ingress (on-prem) — honoring the + `configmap.SD_*` → `global.*` → default precedence in that case too. Advanced + tuning knobs with no grouped param (`SD_DIAL_TIMEOUT`, `SD_TLS_HANDSHAKE_TIMEOUT`, + `SD_RESPONSE_HEADER_TIMEOUT`, `SD_SEED_TIMEOUT`, `SD_WATCH_WAIT_TIME`, + `SD_ALLOW_STALE`) pass through from `configmap.SD_*` when set (emitted only when + present, so the block stays clean by default). - **Env contracts (flat-passthrough):** `lerian-common.serviceDiscovery.envFlat`, `lerian-common.otel.envFlat`, `lerian-common.multiTenant.envFlat` — reproduce a chart's EXISTING native env block **byte-for-byte** (same keys, defaults, quoting diff --git a/charts/lerian-common/docs/UPGRADE-1.0.md b/charts/lerian-common/docs/UPGRADE-1.0.md index c9d406afb..e0442503f 100644 --- a/charts/lerian-common/docs/UPGRADE-1.0.md +++ b/charts/lerian-common/docs/UPGRADE-1.0.md @@ -63,7 +63,7 @@ The `lerian-common.serviceDiscovery.env` helper emits environment variables for | `SD_WORKLOAD` | `""` | Workload isolation key (provider and consumer must match) | | `SD_PREFER_VIEW` | `external` | Preferred view for service resolution (`internal` or `external`) | | `SD_INTERNAL_SCHEME` | `http` | Scheme for internal service URLs | -| `SD_EXTERNAL_PORT` | `443` | Port for external service URLs (emitted only when component has ingress) | +| `SD_EXTERNAL_PORT` | `443` | Port for external service URLs (emitted when component has ingress OR sets legacy `configmap.SD_EXTERNAL_*`) | **Configuration block (umbrella `values.yaml`):** diff --git a/charts/lerian-common/templates/_datastore.tpl b/charts/lerian-common/templates/_datastore.tpl index 80cf3b2d2..46409f383 100644 --- a/charts/lerian-common/templates/_datastore.tpl +++ b/charts/lerian-common/templates/_datastore.tpl @@ -22,6 +22,9 @@ block (dedicated) and `.Values.global.datastores` = the shared mask. lerian-common.datastore.value — resolve ONE datastore field via the mask. Inputs (dict): context (req) product root ($) + dedicated (opt) the component's dedicated datastores map (`.datastores`) + for a monolithic parent chart; when omitted, `.context.Values. + datastores` is used (subchart mode) configmap (req) the component's `.configmap` map (native key — top precedence) type (req) mask block: postgres | mongo | redis | redisMt | broker | field (req) canonical field. Shared across a product's modules: @@ -33,7 +36,11 @@ Inputs (dict): */}} {{- define "lerian-common.datastore.value" -}} {{- $cm := .configmap | default dict -}} -{{- $dedicated := index (.context.Values.datastores | default dict) .type | default dict -}} +{{- /* Dedicated source: an explicit `dedicated` map (passed by a MONOLITHIC parent + chart whose per-component masks live at `.datastores`, e.g. midaz's + `ledger.datastores` / `crm.datastores`) takes precedence; otherwise fall back to + `.context.Values.datastores`, which in a SUBCHART is that product's own block. */ -}} +{{- $dedicated := index (.dedicated | default (.context.Values.datastores | default dict)) .type | default dict -}} {{- $shared := index ((.context.Values.global | default dict).datastores | default dict) .type | default dict -}} {{/* Ordered presence checks (not chained sprig `default`) so an explicit `false` at any tier — native key, dedicated, shared, or default — wins instead of diff --git a/charts/lerian-common/templates/_multi_tenant.tpl b/charts/lerian-common/templates/_multi_tenant.tpl index 2558e4bca..e89f5d029 100644 --- a/charts/lerian-common/templates/_multi_tenant.tpl +++ b/charts/lerian-common/templates/_multi_tenant.tpl @@ -55,29 +55,34 @@ Inputs (dict): {{- $g := dict -}} {{- with .context }}{{- $g = ((.Values.global | default dict).multiTenant | default dict) -}}{{- end -}} {{- if .enabled -}} -{{- /* URL: universal. Component overrides global; then required or default "". */ -}} -{{- $url := index $c "MULTI_TENANT_URL" | default $g.url -}} +{{- /* URL: universal. Component overrides global; then required or default "". + Resolve by PRESENCE (hasKey) so an explicit configmap value survives even as a + YAML false / 0 / "" — sprig `default` would drop those to the global value. */ -}} +{{- $url := ($g.url | default "") -}}{{- if hasKey $c "MULTI_TENANT_URL" -}}{{- $url = index $c "MULTI_TENANT_URL" -}}{{- end -}} {{- if .requiredUrl }} MULTI_TENANT_URL: {{ required "lerian-common: MULTI_TENANT_URL is required when MULTI_TENANT_ENABLED=true (set component configmap.MULTI_TENANT_URL or global.multiTenant.url)" $url | quote }} {{- else }} -MULTI_TENANT_URL: {{ $url | default "" | quote }} +MULTI_TENANT_URL: {{ $url | quote }} {{- end }} {{- if .serviceName }} -MULTI_TENANT_SERVICE_NAME: {{ index $c "MULTI_TENANT_SERVICE_NAME" | default .serviceName | quote }} +{{- $svcName := .serviceName -}}{{- if hasKey $c "MULTI_TENANT_SERVICE_NAME" -}}{{- $svcName = index $c "MULTI_TENANT_SERVICE_NAME" -}}{{- end }} +MULTI_TENANT_SERVICE_NAME: {{ $svcName | quote }} {{- end }} {{- if not (and (hasKey . "circuitBreaker") (eq .circuitBreaker false)) }} MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD: {{ index $c "MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD" | default "5" | quote }} MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC: {{ index $c "MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC" | default "30" | quote }} {{- end }} {{- if .emitRedis }} -{{- $redisHost := index $c "MULTI_TENANT_REDIS_HOST" | default $g.redisHost -}} +{{- $redisHost := ($g.redisHost | default "") -}}{{- if hasKey $c "MULTI_TENANT_REDIS_HOST" -}}{{- $redisHost = index $c "MULTI_TENANT_REDIS_HOST" -}}{{- end -}} {{- if .requiredRedisHost }} MULTI_TENANT_REDIS_HOST: {{ required "lerian-common: MULTI_TENANT_REDIS_HOST is required when MULTI_TENANT_ENABLED=true (set component configmap.MULTI_TENANT_REDIS_HOST or global.multiTenant.redisHost)" $redisHost | quote }} {{- else }} -MULTI_TENANT_REDIS_HOST: {{ $redisHost | default "" | quote }} +MULTI_TENANT_REDIS_HOST: {{ $redisHost | quote }} {{- end }} -MULTI_TENANT_REDIS_PORT: {{ index $c "MULTI_TENANT_REDIS_PORT" | default $g.redisPort | default "6379" | quote }} -MULTI_TENANT_REDIS_TLS: {{ index $c "MULTI_TENANT_REDIS_TLS" | default $g.redisTls | default (.redisTlsDefault | default "false") | quote }} +{{- $redisPort := ($g.redisPort | default "6379") -}}{{- if hasKey $c "MULTI_TENANT_REDIS_PORT" -}}{{- $redisPort = index $c "MULTI_TENANT_REDIS_PORT" -}}{{- end }} +MULTI_TENANT_REDIS_PORT: {{ $redisPort | quote }} +{{- $redisTls := ($g.redisTls | default (.redisTlsDefault | default "false")) -}}{{- if hasKey $c "MULTI_TENANT_REDIS_TLS" -}}{{- $redisTls = index $c "MULTI_TENANT_REDIS_TLS" -}}{{- end }} +MULTI_TENANT_REDIS_TLS: {{ $redisTls | quote }} {{- end }} {{- if .emitPool }} MULTI_TENANT_MAX_TENANT_POOLS: {{ index $c "MULTI_TENANT_MAX_TENANT_POOLS" | default "100" | quote }} diff --git a/charts/lerian-common/templates/_service_discovery.tpl b/charts/lerian-common/templates/_service_discovery.tpl index 716c00a23..2ed71b643 100644 --- a/charts/lerian-common/templates/_service_discovery.tpl +++ b/charts/lerian-common/templates/_service_discovery.tpl @@ -29,8 +29,13 @@ Inputs (dict): name (req) internal service DNS name (SD_INTERNAL_ADDRESS host) port (req) internal service port namespace (req) resolved namespace string - ingressHost (opt) external host; when non-empty, emits SD_EXTERNAL_* - (omit for consumer-only / internal-only instances) + ingressHost (opt) external host; when non-empty, derives SD_EXTERNAL_* + from it. The external endpoint is ALSO emitted (regardless + of ingressHost) when the operator supplies it explicitly via + legacy configmap.SD_EXTERNAL_ADDRESS / SD_EXTERNAL_PORT — + the on-prem-without-Ingress case. Omitted only for + consumer-only / internal-only instances (no ingressHost and + no legacy SD_EXTERNAL_* keys). configmap (opt) the component's legacy `.configmap` map. When a key is present here, its flat `configmap.SD_*` value WINS over the global/derived value below (backward-compat for the flat @@ -87,7 +92,7 @@ global.serviceDiscovery (all optional except address when enabled): {{- $internalAddr := (include "lerian-common.internalHost" (dict "name" .name "namespace" .namespace)) -}}{{- if hasKey $c "SD_INTERNAL_ADDRESS" -}}{{- $internalAddr = index $c "SD_INTERNAL_ADDRESS" -}}{{- end -}} {{- $internalPort := .port -}}{{- if hasKey $c "SD_INTERNAL_PORT" -}}{{- $internalPort = index $c "SD_INTERNAL_PORT" -}}{{- end -}} {{- $internalScheme := ($sd.internalScheme | default "http") -}}{{- if hasKey $c "SD_INTERNAL_SCHEME" -}}{{- $internalScheme = index $c "SD_INTERNAL_SCHEME" -}}{{- end -}} -{{- $externalAddr := (printf "https://%s" .ingressHost) -}}{{- if hasKey $c "SD_EXTERNAL_ADDRESS" -}}{{- $externalAddr = index $c "SD_EXTERNAL_ADDRESS" -}}{{- end -}} +{{- $externalAddr := "" -}}{{- if .ingressHost -}}{{- $externalAddr = (printf "https://%s" .ingressHost) -}}{{- end -}}{{- if hasKey $c "SD_EXTERNAL_ADDRESS" -}}{{- $externalAddr = index $c "SD_EXTERNAL_ADDRESS" -}}{{- end -}} {{- $externalPort := ($sd.externalPort | default 443) -}}{{- if hasKey $c "SD_EXTERNAL_PORT" -}}{{- $externalPort = index $c "SD_EXTERNAL_PORT" -}}{{- end -}} SD_ADDRESS: {{ $addr | quote }} SD_TLS: {{ $tls | quote }} @@ -97,10 +102,22 @@ SD_PREFER_VIEW: {{ $preferView | quote }} SD_INTERNAL_ADDRESS: {{ $internalAddr | quote }} SD_INTERNAL_PORT: {{ $internalPort | quote }} SD_INTERNAL_SCHEME: {{ $internalScheme | quote }} -{{- if .ingressHost }} +{{- /* Emit the external endpoint when it can be derived from an Ingress host + OR when the operator supplied it explicitly via legacy configmap.SD_EXTERNAL_* + keys (on-prem without Ingress). Honors the configmap.SD_* -> global -> default + precedence contract; omitted only for internal-only / consumer-only instances. */ -}} +{{- if or .ingressHost (hasKey $c "SD_EXTERNAL_ADDRESS") (hasKey $c "SD_EXTERNAL_PORT") }} SD_EXTERNAL_ADDRESS: {{ $externalAddr | quote }} SD_EXTERNAL_PORT: {{ $externalPort | quote }} {{- end }} +{{- /* Advanced tuning knobs: no grouped param / no global default — pure legacy + configmap passthrough. Emitted only when the operator sets them (clean when + absent), preserving backward-compat with the flat configmap.SD_* API. */ -}} +{{- range $tk := (list "SD_DIAL_TIMEOUT" "SD_TLS_HANDSHAKE_TIMEOUT" "SD_RESPONSE_HEADER_TIMEOUT" "SD_SEED_TIMEOUT" "SD_WATCH_WAIT_TIME" "SD_ALLOW_STALE") }} +{{- if hasKey $c $tk }} +{{ $tk }}: {{ index $c $tk | quote }} +{{- end }} +{{- end }} {{- end -}} {{- end -}} diff --git a/charts/lerian-common/templates/_streaming.tpl b/charts/lerian-common/templates/_streaming.tpl index a92e51295..f6ac1a054 100644 --- a/charts/lerian-common/templates/_streaming.tpl +++ b/charts/lerian-common/templates/_streaming.tpl @@ -49,21 +49,37 @@ global.streaming (all optional except brokers, which gates emission): over the global value (mirrors multiTenant.env / serviceDiscovery.env). Empty dict when omitted. */ -}} {{- $c := .configmap | default dict -}} -{{- if and .enabled $s.brokers -}} -STREAMING_BROKERS: {{ index $c "STREAMING_BROKERS" | default $s.brokers | quote }} -STREAMING_TLS_ENABLED: {{ index $c "STREAMING_TLS_ENABLED" | default ($s.tlsEnabled | default false) | quote }} -STREAMING_SASL_MECHANISM: {{ index $c "STREAMING_SASL_MECHANISM" | default ($s.saslMechanism | default "") | quote }} -STREAMING_SASL_USERNAME: {{ index $c "STREAMING_SASL_USERNAME" | default ($s.saslUsername | default "") | quote }} -STREAMING_SASL_ALLOW_PLAINTEXT: {{ index $c "STREAMING_SASL_ALLOW_PLAINTEXT" | default ($s.saslAllowPlaintext | default "false") | quote }} -STREAMING_COMPRESSION: {{ index $c "STREAMING_COMPRESSION" | default ($s.compression | default "lz4") | quote }} -STREAMING_REQUIRED_ACKS: {{ index $c "STREAMING_REQUIRED_ACKS" | default ($s.requiredAcks | default "all") | quote }} -STREAMING_BATCH_LINGER_MS: {{ index $c "STREAMING_BATCH_LINGER_MS" | default ($s.batchLingerMs | default "5") | quote }} -STREAMING_IMPORTANT_EMIT_TIMEOUT_MS: {{ index $c "STREAMING_IMPORTANT_EMIT_TIMEOUT_MS" | default ($s.importantEmitTimeoutMs | default "5000") | quote }} +{{- /* Activate when enabled AND brokers are configured — via EITHER the env-wide + global.streaming.brokers OR a legacy flat configmap.STREAMING_BROKERS (mirrors + serviceDiscovery.env). Each key resolves by PRESENCE (hasKey) so an explicit + configmap value survives even when it is a YAML false / 0 / "" — sprig `default` + would treat those as empty and wrongly fall back to the global/derived value. */ -}} +{{- if and .enabled (or $s.brokers (hasKey $c "STREAMING_BROKERS")) -}} +{{- $brokers := $s.brokers -}}{{- if hasKey $c "STREAMING_BROKERS" -}}{{- $brokers = index $c "STREAMING_BROKERS" -}}{{- end -}} +{{- $tlsEnabled := ($s.tlsEnabled | default false) -}}{{- if hasKey $c "STREAMING_TLS_ENABLED" -}}{{- $tlsEnabled = index $c "STREAMING_TLS_ENABLED" -}}{{- end -}} +{{- $saslMechanism := ($s.saslMechanism | default "") -}}{{- if hasKey $c "STREAMING_SASL_MECHANISM" -}}{{- $saslMechanism = index $c "STREAMING_SASL_MECHANISM" -}}{{- end -}} +{{- $saslUsername := ($s.saslUsername | default "") -}}{{- if hasKey $c "STREAMING_SASL_USERNAME" -}}{{- $saslUsername = index $c "STREAMING_SASL_USERNAME" -}}{{- end -}} +{{- $saslAllowPlaintext := ($s.saslAllowPlaintext | default "false") -}}{{- if hasKey $c "STREAMING_SASL_ALLOW_PLAINTEXT" -}}{{- $saslAllowPlaintext = index $c "STREAMING_SASL_ALLOW_PLAINTEXT" -}}{{- end -}} +{{- $compression := ($s.compression | default "lz4") -}}{{- if hasKey $c "STREAMING_COMPRESSION" -}}{{- $compression = index $c "STREAMING_COMPRESSION" -}}{{- end -}} +{{- $requiredAcks := ($s.requiredAcks | default "all") -}}{{- if hasKey $c "STREAMING_REQUIRED_ACKS" -}}{{- $requiredAcks = index $c "STREAMING_REQUIRED_ACKS" -}}{{- end -}} +{{- $batchLingerMs := ($s.batchLingerMs | default "5") -}}{{- if hasKey $c "STREAMING_BATCH_LINGER_MS" -}}{{- $batchLingerMs = index $c "STREAMING_BATCH_LINGER_MS" -}}{{- end -}} +{{- $importantEmitTimeoutMs := ($s.importantEmitTimeoutMs | default "5000") -}}{{- if hasKey $c "STREAMING_IMPORTANT_EMIT_TIMEOUT_MS" -}}{{- $importantEmitTimeoutMs = index $c "STREAMING_IMPORTANT_EMIT_TIMEOUT_MS" -}}{{- end -}} +STREAMING_BROKERS: {{ $brokers | quote }} +STREAMING_TLS_ENABLED: {{ $tlsEnabled | quote }} +STREAMING_SASL_MECHANISM: {{ $saslMechanism | quote }} +STREAMING_SASL_USERNAME: {{ $saslUsername | quote }} +STREAMING_SASL_ALLOW_PLAINTEXT: {{ $saslAllowPlaintext | quote }} +STREAMING_COMPRESSION: {{ $compression | quote }} +STREAMING_REQUIRED_ACKS: {{ $requiredAcks | quote }} +STREAMING_BATCH_LINGER_MS: {{ $batchLingerMs | quote }} +STREAMING_IMPORTANT_EMIT_TIMEOUT_MS: {{ $importantEmitTimeoutMs | quote }} {{- if hasKey . "clientId" }} -STREAMING_CLIENT_ID: {{ index $c "STREAMING_CLIENT_ID" | default .clientId | quote }} +{{- $clientId := .clientId -}}{{- if hasKey $c "STREAMING_CLIENT_ID" -}}{{- $clientId = index $c "STREAMING_CLIENT_ID" -}}{{- end }} +STREAMING_CLIENT_ID: {{ $clientId | quote }} {{- end }} {{- if hasKey . "cloudeventsSource" }} -STREAMING_CLOUDEVENTS_SOURCE: {{ index $c "STREAMING_CLOUDEVENTS_SOURCE" | default .cloudeventsSource | quote }} +{{- $cloudeventsSource := .cloudeventsSource -}}{{- if hasKey $c "STREAMING_CLOUDEVENTS_SOURCE" -}}{{- $cloudeventsSource = index $c "STREAMING_CLOUDEVENTS_SOURCE" -}}{{- end }} +STREAMING_CLOUDEVENTS_SOURCE: {{ $cloudeventsSource | quote }} {{- end }} {{- end -}} {{- end -}} diff --git a/charts/lerian-common/values.yaml b/charts/lerian-common/values.yaml index 580ae2b35..27a15e97a 100644 --- a/charts/lerian-common/values.yaml +++ b/charts/lerian-common/values.yaml @@ -22,7 +22,7 @@ global: {} # workload: "" # SD_WORKLOAD — per-env isolation key (provider+consumer must match) # preferView: external # SD_PREFER_VIEW — internal|external (lib default: external) # internalScheme: http # SD_INTERNAL_SCHEME - # externalPort: 443 # SD_EXTERNAL_PORT (emitted only when a component has an ingress host) + # externalPort: 443 # SD_EXTERNAL_PORT (emitted when a component has an ingress host OR sets legacy configmap.SD_EXTERNAL_*) # # -- Streaming (lib-streaming / RedPanda). Set once per environment. # streaming: