Skip to content

fix(common): harden legacy configmap.* passthrough for productized env helpers (SD + streaming + MT) - #1791

Merged
guimoreirar merged 5 commits into
mainfrom
fix/sd-external-without-ingress
Jul 31, 2026
Merged

fix(common): harden legacy configmap.* passthrough for productized env helpers (SD + streaming + MT)#1791
guimoreirar merged 5 commits into
mainfrom
fix/sd-external-without-ingress

Conversation

@guimoreirar

Copy link
Copy Markdown
Member

Follow-up to #1779, addressing the RED blocker raised on #1741.

Problem

The serviceDiscovery.env helper emitted SD_EXTERNAL_ADDRESS / SD_EXTERNAL_PORT only when an Ingress host could be derived ({{- if .ingressHost }}). On an on-prem install with ingress.enabled=false, an operator who supplied the external endpoint explicitly via the legacy configmap.SD_EXTERNAL_ADDRESS / SD_EXTERNAL_PORT keys had those values silently dropped — breaking the documented configmap.SD_*global.* → default precedence for the external view.

Repro (SD enabled, explicit address + external endpoint in configmap, no Ingress):

  • main keeps both external fields
  • pre-fix helper removes both (Ledger and CRM)

Fix

  • Emit the external block when it can be derived from an Ingress host OR when the legacy configmap.SD_EXTERNAL_ADDRESS / SD_EXTERNAL_PORT keys are present, independent of ingressHost.
  • $externalAddr no longer defaults to https:// (empty ingressHost) — it stays empty unless an Ingress host or an explicit configmap value provides it.
  • Internal-only / consumer-only instances (no host, no legacy keys) still omit the block → no-Ingress internal renders unchanged.

Validation

Rendered the helper across three scenarios (probe chart including the patched lib):

Scenario SD_EXTERNAL_*
on-prem, no Ingress, configmap.SD_EXTERNAL_* set ✅ preserved (https://ledger.onprem.local : 8443)
internal-only (no Ingress, no external keys) omitted (clean)
Ingress host present ✅ derived (https://<host> : 443) — unchanged

helm lint passes.

The consuming render test (on-prem-no-Ingress case in the midaz render-values) lands with the re-pin in #1741 — the helper is a library and is exercised through its consumers.

…ngress

The service-discovery helper only emitted SD_EXTERNAL_ADDRESS/SD_EXTERNAL_PORT
when an Ingress host could be derived, silently dropping an operator-supplied
external endpoint on on-prem installs with ingress.enabled=false. This broke
the documented configmap.SD_* -> global -> default precedence for the external
view.

Emit the external endpoint when it can be derived from an Ingress host OR when
the legacy configmap.SD_EXTERNAL_ADDRESS / SD_EXTERNAL_PORT keys are present,
independent of ingressHost. Internal-only / consumer-only instances (no host,
no legacy keys) still omit the block, so no-Ingress internal renders are
unchanged.
@guimoreirar
guimoreirar requested a review from a team as a code owner July 31, 2026 18:05
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The shared Helm helpers now use presence-based legacy configuration overrides. Service discovery supports Ingress-derived or explicitly configured external endpoints and tuning values. Multi-tenant, streaming, and datastore helpers retain explicit values and support component-specific inputs.

Changes

Shared configuration precedence

Layer / File(s) Summary
External endpoint fallback and precedence
charts/lerian-common/templates/_service_discovery.tpl, charts/lerian-common/README.md, charts/lerian-common/docs/UPGRADE-1.0.md, charts/lerian-common/values.yaml
The template derives external addresses from ingressHost when available. Legacy configmap.SD_EXTERNAL_ADDRESS and SD_EXTERNAL_PORT values override derived values. The external block supports legacy-only configuration and advanced tuning values. The documentation describes these conditions.
Multi-tenant override resolution
charts/lerian-common/templates/_multi_tenant.tpl
Component overrides for URLs, service names, Redis settings, ports, and TLS use key presence. Explicit false, 0, and empty values remain valid. Global and default fallbacks and required-host validation remain unchanged.
Streaming override resolution
charts/lerian-common/templates/_streaming.tpl
Streaming activates when brokers come from global settings or legacy configmap.STREAMING_BROKERS. Legacy values use key-presence precedence for streaming settings and optional client identity values.
Dedicated datastore resolution
charts/lerian-common/templates/_datastore.tpl
The datastore helper accepts an optional dedicated map for monolithic parent charts. It falls back to .context.Values.datastores when the map is omitted. Dedicated values retain precedence over shared values after native configmap keys.

Possibly related PRs

  • LerianStudio/helm#1779: Both changes update service discovery handling for legacy configmap.SD_* values and precedence.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/sd-external-without-ingress

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@charts/lerian-common/templates/_service_discovery.tpl`:
- Around line 105-109: Update the SD_EXTERNAL_PORT documentation comment in
values.yaml to state that the external endpoint may also be emitted when legacy
configmap.SD_EXTERNAL_ADDRESS or configmap.SD_EXTERNAL_PORT is configured, even
without an Ingress host. Keep the documented precedence and
internal-only/consumer-only exclusions consistent with the helper condition in
the service-discovery template.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 49804baa-d546-407c-ad11-b962a4b84b83

📥 Commits

Reviewing files that changed from the base of the PR and between 7a3a0ce and c77496a.

📒 Files selected for processing (2)
  • charts/lerian-common/README.md
  • charts/lerian-common/templates/_service_discovery.tpl

Comment thread charts/lerian-common/templates/_service_discovery.tpl
@guimoreirar guimoreirar changed the title fix(lerian-common): preserve legacy configmap.SD_EXTERNAL_* without Ingress fix(common): preserve legacy configmap.SD_EXTERNAL_* without Ingress Jul 31, 2026
The productized serviceDiscovery.env helper emitted only its known SD_* keys,
silently dropping six advanced tuning knobs that main exposed as flat
configmap.SD_* passthrough: SD_DIAL_TIMEOUT, SD_TLS_HANDSHAKE_TIMEOUT,
SD_RESPONSE_HEADER_TIMEOUT, SD_SEED_TIMEOUT, SD_WATCH_WAIT_TIME, SD_ALLOW_STALE.
An operator who tuned these via configmap would lose them on upgrade.

Emit each from configmap when present (hasKey-gated), so they survive backward
-compat while the block stays clean when unset.
@guimoreirar guimoreirar changed the title fix(common): preserve legacy configmap.SD_EXTERNAL_* without Ingress fix(common): preserve all legacy configmap.SD_* passthrough (external + tuning) without Ingress Jul 31, 2026
@guimoreirar

Copy link
Copy Markdown
Member Author

Broadened scope after a full render-parity audit of #1741 (main vs PR, all 213 configmap passthrough keys under identical inputs).

Second gap found — same class as the external-endpoint one: the grouped helper also dropped six advanced SD tuning knobs that main exposed as flat configmap.SD_* passthrough (no grouped param / no global):
SD_DIAL_TIMEOUT, SD_TLS_HANDSHAKE_TIMEOUT, SD_RESPONSE_HEADER_TIMEOUT, SD_SEED_TIMEOUT, SD_WATCH_WAIT_TIME, SD_ALLOW_STALE.

Fixed in 475a97aa: each passes through from configmap when present (hasKey-gated), emitted only when set so the block stays clean by default. Validated via probe (all six preserved when set; absent when unset).

Audit result: of 213 passthrough keys (163 ledger + 50 crm), the PR dropped only these 8 SD keys (2 external + 6 tuning) — all now covered here. Every other key + all shared values render identically.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@charts/lerian-common/README.md`:
- Around line 19-23: The upgrade guide’s legacy external endpoint section still
documents the old Ingress-only behavior. Update the relevant section of
UPGRADE-1.0.md to describe the configmap.SD_EXTERNAL_* fallback, including its
precedence relative to global values and defaults, and remove the outdated
SD_EXTERNAL_PORT-only wording.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8fb2adcc-6d61-4dad-8a11-3893f53539de

📥 Commits

Reviewing files that changed from the base of the PR and between c77496a and 475a97a.

📒 Files selected for processing (2)
  • charts/lerian-common/README.md
  • charts/lerian-common/templates/_service_discovery.tpl

Comment thread charts/lerian-common/README.md
Apply the same presence-based (hasKey) resolution that #1779 gave serviceDiscovery
to streaming.env and multiTenant.env:

- streaming.env activation now also triggers from legacy configmap.STREAMING_BROKERS
  (not only global.streaming.brokers) — mirrors the SD gate fix.
- Per-key resolution uses hasKey instead of sprig default for every global/param
  -derived key, so an explicit configmap value survives even as a YAML false / 0 /
  empty string. Previously e.g. configmap STREAMING_TLS_ENABLED: false was silently
  overridden to the global true; MULTI_TENANT_REDIS_PORT: 0 became 6379.
- Literal-default keys are left untouched (byte-identical to main).

Backward-compat verified: with no configmap the derived/global values render
unchanged.
@guimoreirar guimoreirar changed the title fix(common): preserve all legacy configmap.SD_* passthrough (external + tuning) without Ingress fix(common): harden legacy configmap.* passthrough for productized env helpers (SD + streaming + MT) Jul 31, 2026
@guimoreirar

Copy link
Copy Markdown
Member Author

Extended once more to close the last gap from the full parity audit — folding the streaming/multiTenant hardening here so a single lib bump → single midaz re-pin covers all backward-compat passthrough fixes (was the out-of-scope follow-up noted on #1779).

Gap: truthiness footgun in streaming.env + multiTenant.env (27d6eede)
Same class as the SD fix. The helpers resolved each key with sprig default, so an explicit configmap value that is a YAML false / 0 / "" was treated as empty and silently overridden by the global/derived default. Confirmed real (not theoretical):

Input (global set, configmap overrides) Before After
STREAMING_TLS_ENABLED: false (global tlsEnabled: true) "true" "false"
STREAMING_BATCH_LINGER_MS: 0 "5" "0"
MULTI_TENANT_REDIS_TLS: false (global redisTls: true) "true" "false"
MULTI_TENANT_REDIS_PORT: 0 "6379" "0"

Also fixed a Blocker-1-class activation gate in streaming.env: it gated on global.streaming.brokers, so a legacy configmap.STREAMING_BROKERS-only activation emitted nothing — now it activates from either source (mirrors the SD gate).

Scope discipline: only global/param-derived keys switched to hasKey; literal-default keys are left as-is (byte-identical to main, same footgun main already has → no divergence). Backward-compat verified: with no configmap, all values render unchanged. helm lint passes.

This PR now covers, per the audit of #1741 (main vs PR, all 213 passthrough keys):

  1. SD_EXTERNAL_* preserved without Ingress (on-prem)
  2. 6 SD tuning knobs passthrough
  3. streaming.env / multiTenant.env presence-based resolution + streaming activation gate

Only 8 keys diverged in the whole audit; all closed here. ENABLE_TELEMETRY default + OTEL staging declaration are handled on #1741 directly.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@charts/lerian-common/templates/_multi_tenant.tpl`:
- Around line 58-65: Update the MULTI_TENANT_URL resolution in the template, and
apply the same change to MULTI_TENANT_REDIS_HOST: apply the empty-string
fallback to the global value before the hasKey-based component override, then
quote the resolved value directly without another default. Preserve explicit
component values such as false, 0, or "" through the override path, while
keeping the requiredUrl validation unchanged.

In `@charts/lerian-common/templates/_streaming.tpl`:
- Around line 59-60: Align the SASL mechanism input used by the streaming.secret
helper with the precedence already implemented for $saslMechanism in
_streaming.tpl: use configmap.STREAMING_SASL_MECHANISM when present, otherwise
fall back to the global mechanism value. Update the helper inputs consistently
before adding any executable consumer.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: aab8bbfe-03d9-4c69-887b-359b0b3cdca2

📥 Commits

Reviewing files that changed from the base of the PR and between 475a97a and 27d6eed.

📒 Files selected for processing (2)
  • charts/lerian-common/templates/_multi_tenant.tpl
  • charts/lerian-common/templates/_streaming.tpl

Comment thread charts/lerian-common/templates/_multi_tenant.tpl Outdated
Comment thread charts/lerian-common/templates/_streaming.tpl
…ithic charts

The dedicated tier read only .context.Values.datastores, which resolves to the
per-product block ONLY in a subchart. In a monolithic parent chart (midaz), the
per-component masks live at <component>.datastores (ledger.datastores /
crm.datastores) and were never consulted — the documented DEDICATED API was inert.

Accept an optional dedicated map param; when passed it is the dedicated source,
else fall back to .context.Values.datastores (subchart mode, unchanged). Precedence
stays configmap > dedicated > global > default.
- multiTenant.env: MULTI_TENANT_URL / MULTI_TENANT_REDIS_HOST applied the global
  fallback via a trailing 'default ""' AFTER the hasKey override, which re-collapsed
  an explicit component false/0 back to empty — defeating the presence-based
  passthrough. Move the fallback onto the global value before the override and quote
  the resolved value directly.
- Update the values.yaml + UPGRADE-1.0 notes: SD_EXTERNAL_* is emitted with an
  Ingress host OR when legacy configmap.SD_EXTERNAL_* is set (on-prem).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@charts/lerian-common/docs/UPGRADE-1.0.md`:
- Line 66: Do not edit the generated UPGRADE-1.0.md file directly; update the
shared migration template that produces the SD_EXTERNAL_PORT documentation, then
run the release generation process to regenerate this file and keep the
generated upgrade guide synchronized.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a4be0112-b959-4b28-9dc5-ebc5d4332ca9

📥 Commits

Reviewing files that changed from the base of the PR and between 7d3a4b9 and fc68858.

📒 Files selected for processing (3)
  • charts/lerian-common/docs/UPGRADE-1.0.md
  • charts/lerian-common/templates/_multi_tenant.tpl
  • charts/lerian-common/values.yaml

Comment thread charts/lerian-common/docs/UPGRADE-1.0.md
@guimoreirar
guimoreirar merged commit 762a688 into main Jul 31, 2026
5 checks passed
@guimoreirar
guimoreirar deleted the fix/sd-external-without-ingress branch July 31, 2026 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant