Skip to content
19 changes: 10 additions & 9 deletions charts/insight/templates/secrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,9 @@ stringData:
{{- end }}
---
# Identity Resolution (epic #1602) leaf config. Same gears-rust
# env-override convention as analytics (`APP__gears__<gear>__config__*`; the
# gear name contains a hyphen — valid in Secret keys and envFrom). Points at
# env-override convention as analytics (`APP__gears__<gear>__config__*`). The
# YAML gear name is `identity-resolution`; its environment-key segment is
# `identity_resolution`, which the toolkit remaps to the YAML name. Points at
# the MariaDB `identity` database it owns and migrates, and at the ClickHouse
# `identity.identity_inputs` seed input over the HTTP protocol (the shared
# insight-clickhouse client).
Expand All @@ -250,29 +251,29 @@ metadata:
{{- include "insight.labels" . | nindent 4 }}
type: Opaque
stringData:
APP__gears__identity-resolution__config__database_url: {{ printf "mysql://%s:%s@%s:%v/%s"
APP__gears__identity_resolution__config__database_url: {{ printf "mysql://%s:%s@%s:%v/%s"
(required "mariadb.username is required" .Values.mariadb.username | urlquery)
($mdbPass | urlquery)
(include "insight.mariadb.host" .)
(include "insight.mariadb.port" .)
(required "identityResolution.databaseName is required" .Values.identityResolution.databaseName)
| quote }}
APP__gears__identity-resolution__config__clickhouse_url: {{ include "insight.clickhouse.url" . | quote }}
APP__gears__identity-resolution__config__clickhouse_database: {{ include "insight.clickhouse.database" . | quote }}
APP__gears__identity-resolution__config__clickhouse_user: {{ required "clickhouse.username is required" .Values.clickhouse.username | quote }}
APP__gears__identity-resolution__config__clickhouse_password: {{ $chPass | quote }}
APP__gears__identity_resolution__config__clickhouse_url: {{ include "insight.clickhouse.url" . | quote }}
APP__gears__identity_resolution__config__clickhouse_database: {{ include "insight.clickhouse.database" . | quote }}
APP__gears__identity_resolution__config__clickhouse_user: {{ required "clickhouse.username is required" .Values.clickhouse.username | quote }}
APP__gears__identity_resolution__config__clickhouse_password: {{ $chPass | quote }}
{{- with (default "" (default dict .Values.global).tenantDefaultId) }}
# Sourced from `global.tenantDefaultId` — same single source of truth the
# rest of the platform keys on. Feeds the first-admin bootstrap in the
# migrate initContainer.
APP__gears__identity-resolution__config__tenant_default_id: {{ . | quote }}
APP__gears__identity_resolution__config__tenant_default_id: {{ . | quote }}
{{- end }}
{{- with .Values.identityResolution.bootstrapAdminPersonId }}
# First-admin seed for the OrgChart Visibility tables (#346 step 5): the
# configured person UUID gets minted as `admin` in `person_roles`. Applied
# by the migrate initContainer, idempotently. Empty value disables the
# runner.
APP__gears__identity-resolution__config__bootstrap_admin_person_id: {{ . | quote }}
APP__gears__identity_resolution__config__bootstrap_admin_person_id: {{ . | quote }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
{{- end }}
{{- end }}

Expand Down
2 changes: 1 addition & 1 deletion charts/insight/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ identityResolution:
# exist in `persons` for that tenant. Empty string disables the runner.
bootstrapAdminPersonId: ""
# The umbrella generates `insight-identity-resolution-config` with every
# APP__gears__identity-resolution__config__* env var filled in from the
# APP__gears__identity_resolution__config__* env var filled in from the
# auto-generated credentials (see templates/secrets.yaml). The subchart
# consumes it via envFrom (overriding its mounted config ConfigMap).
existingSecret: "insight-identity-resolution-config"
Expand Down
14 changes: 7 additions & 7 deletions deploy/gitops/scripts/compose-app-secrets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -268,19 +268,19 @@ metadata:
helm.sh/resource-policy: keep # see analytics-config rationale above
type: Opaque
stringData:
APP__gears__identity-resolution__config__database_url: "mysql://${MDB_USER}:${MDB_PW}@${MDB_HOST}:${MDB_PORT}/${IDENTITY_RESOLUTION_DB}"
APP__gears__identity-resolution__config__clickhouse_url: "http://${CH_HOST}:${CH_PORT}"
APP__gears__identity-resolution__config__clickhouse_database: "${CH_DB}"
APP__gears__identity-resolution__config__clickhouse_user: "${CH_USER}"
APP__gears__identity-resolution__config__clickhouse_password: "${CH_PW}"
APP__gears__identity_resolution__config__database_url: "mysql://${MDB_USER}:${MDB_PW}@${MDB_HOST}:${MDB_PORT}/${IDENTITY_RESOLUTION_DB}"
APP__gears__identity_resolution__config__clickhouse_url: "http://${CH_HOST}:${CH_PORT}"
APP__gears__identity_resolution__config__clickhouse_database: "${CH_DB}"
APP__gears__identity_resolution__config__clickhouse_user: "${CH_USER}"
APP__gears__identity_resolution__config__clickhouse_password: "${CH_PW}"
EOF
# First-admin bootstrap inputs (migrate initContainer): mirror the
# chart-side block in charts/insight/templates/secrets.yaml.
if [ -n "$TENANT_DEFAULT" ] && [ "$TENANT_DEFAULT" != "null" ]; then
echo " APP__gears__identity-resolution__config__tenant_default_id: \"${TENANT_DEFAULT}\""
echo " APP__gears__identity_resolution__config__tenant_default_id: \"${TENANT_DEFAULT}\""
fi
if [ -n "$IDENTITY_RESOLUTION_BOOTSTRAP_ADMIN" ] && [ "$IDENTITY_RESOLUTION_BOOTSTRAP_ADMIN" != "null" ]; then
echo " APP__gears__identity-resolution__config__bootstrap_admin_person_id: \"${IDENTITY_RESOLUTION_BOOTSTRAP_ADMIN}\""
echo " APP__gears__identity_resolution__config__bootstrap_admin_person_id: \"${IDENTITY_RESOLUTION_BOOTSTRAP_ADMIN}\""
fi
} | kubectl -n "$NS_APP" apply -f - >/dev/null
echo "composed → $NS_APP/insight-identity-resolution-config"
Expand Down
14 changes: 7 additions & 7 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ services:
depends_on:
mariadb: {condition: service_healthy, required: false}
environment:
APP__gears__identity-resolution__config__database_url: "mysql://${MARIADB_USER:-insight}:${MARIADB_PASSWORD:-insight-local}@${MARIADB_HOST:-mariadb}:${MARIADB_INTERNAL_PORT:-3306}/identity"
APP__gears__identity_resolution__config__database_url: "mysql://${MARIADB_USER:-insight}:${MARIADB_PASSWORD:-insight-local}@${MARIADB_HOST:-mariadb}:${MARIADB_INTERNAL_PORT:-3306}/identity"
volumes:
- type: bind
source: ./deploy/compose/build/identity-resolution/identity-resolution
Expand Down Expand Up @@ -304,13 +304,13 @@ services:
# gears-rust host: structural config (gears list, oidc-authn-plugin
# full-auth wiring) lives in the bind-mounted
# deploy/compose/identity-resolution-fullauth.yaml; these
# APP__gears__identity-resolution__config__* env vars override the
# APP__gears__identity_resolution__config__* env vars override the
# deployment-specific leaf values.
APP__gears__identity-resolution__config__database_url: "mysql://${MARIADB_USER:-insight}:${MARIADB_PASSWORD:-insight-local}@${MARIADB_HOST:-mariadb}:${MARIADB_INTERNAL_PORT:-3306}/identity"
APP__gears__identity-resolution__config__clickhouse_url: "http://${CLICKHOUSE_HOST:-clickhouse}:${CLICKHOUSE_INTERNAL_HTTP_PORT:-8123}"
APP__gears__identity-resolution__config__clickhouse_database: "${CLICKHOUSE_DATABASE:-insight}"
APP__gears__identity-resolution__config__clickhouse_user: "${CLICKHOUSE_USER:-insight}"
APP__gears__identity-resolution__config__clickhouse_password: "${CLICKHOUSE_PASSWORD:-insight-local}"
APP__gears__identity_resolution__config__database_url: "mysql://${MARIADB_USER:-insight}:${MARIADB_PASSWORD:-insight-local}@${MARIADB_HOST:-mariadb}:${MARIADB_INTERNAL_PORT:-3306}/identity"
APP__gears__identity_resolution__config__clickhouse_url: "http://${CLICKHOUSE_HOST:-clickhouse}:${CLICKHOUSE_INTERNAL_HTTP_PORT:-8123}"
APP__gears__identity_resolution__config__clickhouse_database: "${CLICKHOUSE_DATABASE:-insight}"
APP__gears__identity_resolution__config__clickhouse_user: "${CLICKHOUSE_USER:-insight}"
APP__gears__identity_resolution__config__clickhouse_password: "${CLICKHOUSE_PASSWORD:-insight-local}"
volumes:
- type: bind
source: ./deploy/compose/build/identity-resolution/identity-resolution
Expand Down
14 changes: 7 additions & 7 deletions src/backend/services/identity-resolution/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ Reuse the exact connection string the deployed identity service uses, rewriting
the host to localhost:
```bash
URL=$(kubectl -n insight get secret insight-identity-resolution-config \
-o jsonpath='{.data.APP__gears__identity-resolution__config__database_url}' | base64 -d \
-o jsonpath='{.data.APP__gears__identity_resolution__config__database_url}' | base64 -d \
| sed 's#@[^/]*/#@127.0.0.1:3306/#')
# → mysql://insight:<password>@127.0.0.1:3306/identity
```

### 3. Run the service — from `src/backend`
Pass the DB URL as an env override. **Use `env "NAME=VALUE" …`, not `export`** —
the gear name contains a hyphen (`identity-resolution`), which a shell `export`
variable name cannot contain.
Pass the DB URL as an env override. The toolkit maps the underscored
`identity_resolution` environment-key segment to the hyphenated
`identity-resolution` YAML gear name.
```bash
cd src/backend
env "APP__gears__identity-resolution__config__database_url=$URL" \
cargo run -p identity-resolution -- -c services/identity-resolution/config/insight.yaml
export APP__gears__identity_resolution__config__database_url="$URL"
cargo run -p identity-resolution -- -c services/identity-resolution/config/insight.yaml
```
Startup log should show `connected to MariaDB` and `HTTP server bound on 0.0.0.0:8082`.

Expand All @@ -57,7 +57,7 @@ open http://localhost:8082/docs # OpenAPI docs page
- `database_url` is left **empty** in `config/insight.yaml` — no credentials are
committed. It is injected via the env override above (or, in a real deploy,
from the umbrella Secret).
- Config env-override convention: `APP__gears__identity-resolution__config__<field>`
- Config env-override convention: `APP__gears__identity_resolution__config__<field>`
(double underscore between path segments).
- If the service fails at init with `gear 'identity-resolution' not found`, the
`gears.identity-resolution.config` section is missing from the config YAML.
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ gears:
identity-resolution:
config:
# MariaDB connection URL. Injected per-deployment via env override
# APP__gears__identity-resolution__config__database_url. Left empty
# APP__gears__identity_resolution__config__database_url. Left empty
# here so no credential is committed.
database_url: ""
# Source instance whose org_chart edges drive the parent/supervisor +
Expand All @@ -118,7 +118,7 @@ gears:
max_depth: 16
# ClickHouse (persons-seed input: identity.identity_inputs). URL/creds are
# injected per-deployment via env overrides
# APP__gears__identity-resolution__config__clickhouse_*. Empty here so no
# APP__gears__identity_resolution__config__clickhouse_*. Empty here so no
# endpoint/credential is committed.
clickhouse_url: ""
clickhouse_database: "identity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ spec:
envFrom:
# Operator MUST pre-create this Secret (umbrella does it
# automatically as `insight-identity-resolution-config`). Provides
# the APP__gears__identity-resolution__config__* leaf overrides.
# the APP__gears__identity_resolution__config__* leaf overrides.
- secretRef:
name: {{ required "existingSecret is required (umbrella provides `insight-identity-resolution-config`; standalone installs supply their own)" .Values.existingSecret | quote }}
securityContext:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ spec:
# Standalone installs that don't carry the tenant in their
# Secret set this; the umbrella wires the Secret from
# global.tenantDefaultId instead and validates it at render.
- name: APP__gears__identity-resolution__config__tenant_default_id
- name: APP__gears__identity_resolution__config__tenant_default_id
value: {{ . | quote }}
{{- end }}
securityContext:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ spec:
env:
# Explicit tenant for the JOURNAL row (the copy itself is
# tenant-agnostic). Same override semantics as the seed's.
- name: APP__gears__identity-resolution__config__tenant_default_id
- name: APP__gears__identity_resolution__config__tenant_default_id
value: {{ . | quote }}
{{- end }}
securityContext:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def test_tenant_value_overrides_the_secret_via_env(default_docs, job: str) -> No
docs = _subchart_docs("--set", f"{job}.tenantDefaultId={TENANT}")
container = _job_container(_cronjob(docs, job))
env = {e["name"]: e["value"] for e in container["env"]}
assert env == {"APP__gears__identity-resolution__config__tenant_default_id": TENANT}
assert env == {"APP__gears__identity_resolution__config__tenant_default_id": TENANT}


@pytest.mark.parametrize("job", JOBS)
Expand Down Expand Up @@ -285,7 +285,7 @@ def test_umbrella_accepts_the_explicit_seed_tenant_alone(umbrella_deps) -> None:
assert rc == 0, err
container = _job_container(_cronjob(_docs(out), "seed"))
env = {e["name"]: e["value"] for e in container.get("env", [])}
assert env.get("APP__gears__identity-resolution__config__tenant_default_id") == TENANT
assert env.get("APP__gears__identity_resolution__config__tenant_default_id") == TENANT


def test_umbrella_disabled_seed_needs_no_tenant(umbrella_deps) -> None:
Expand Down
8 changes: 4 additions & 4 deletions src/backend/services/identity-resolution/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ resources:

# Pre-provisioned Secret carrying the gears-rust host's leaf-config overrides
# (injected via envFrom; they override the mounted config ConfigMap):
# APP__gears__identity-resolution__config__database_url
# APP__gears__identity-resolution__config__clickhouse_url|_database|_user|_password
# APP__gears__identity-resolution__config__tenant_default_id (optional)
# APP__gears__identity-resolution__config__bootstrap_admin_person_id (optional)
# APP__gears__identity_resolution__config__database_url
# APP__gears__identity_resolution__config__clickhouse_url|_database|_user|_password
# APP__gears__identity_resolution__config__tenant_default_id (optional)
# APP__gears__identity_resolution__config__bootstrap_admin_person_id (optional)
#
# The two optional fields drive the first-admin bootstrap in the migrate
# initContainer (port of the .NET BootstrapAdminRunner): the configured person
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#
# Assumes the service is reachable at $BASE_URL and the bootstrap admin
# has already been minted (the identity-resolution migrate step seeds it
# when APP__gears__identity-resolution__config__bootstrap_admin_person_id
# when APP__gears__identity_resolution__config__bootstrap_admin_person_id
# is set).
#
# Usage:
Expand Down
2 changes: 1 addition & 1 deletion src/backend/services/identity-resolution/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! Loaded via `GearCtx::config::<GearConfig>()` from the
//! `gears.identity-resolution.config` YAML section. Env overrides are
//! `APP__gears__identity-resolution__config__<field>`.
//! `APP__gears__identity_resolution__config__<field>`.

use serde::Deserialize;

Expand Down
2 changes: 1 addition & 1 deletion src/backend/services/identity-resolution/src/gear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::config::GearConfig;

/// Identity-resolution gear. Capability: `rest` (HTTP surface). Config key is
/// the gear name `identity-resolution`; env overrides are
/// `APP__gears__identity-resolution__config__*`.
/// `APP__gears__identity_resolution__config__*`.
#[derive(Default)]
#[toolkit::gear(name = "identity-resolution", capabilities = [rest])]
pub struct IdentityResolutionGear {
Expand Down
2 changes: 1 addition & 1 deletion src/ingestion/tests/e2e/identity/test_persons_seed.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ def test_seed_cli_failure_exits_1_and_journals(identity_inputs, identity_svc, co
force=True,
# Closed port → fast connection refusal on the identity_inputs read,
# which happens after the operations row is enqueued.
extra_env={"APP__gears__identity-resolution__config__clickhouse_url": "http://127.0.0.1:1"},
extra_env={"APP__gears__identity_resolution__config__clickhouse_url": "http://127.0.0.1:1"},
)
assert res.returncode == 1, f"rc={res.returncode}\n{res.stdout}\n{res.stderr}"

Expand Down
17 changes: 8 additions & 9 deletions src/ingestion/tests/e2e/lib/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def run_sync_cli(
cmd = locate_rust_app(self.cfg)
env = self._rust_env()
if tenant is not None:
env["APP__gears__identity-resolution__config__tenant_default_id"] = tenant
env["APP__gears__identity_resolution__config__tenant_default_id"] = tenant
if extra_env:
env.update(extra_env)
args = [*cmd, "-c", str(self._rig_config_path), "sync"]
Expand Down Expand Up @@ -293,7 +293,7 @@ def run_seed_cli(
cmd = locate_rust_app(self.cfg)
env = self._rust_env()
if tenant is not None:
env["APP__gears__identity-resolution__config__tenant_default_id"] = tenant
env["APP__gears__identity_resolution__config__tenant_default_id"] = tenant
if extra_env:
env.update(extra_env)
args = [*cmd, "-c", str(self._rig_config_path), "seed"]
Expand All @@ -318,20 +318,19 @@ def start(self) -> None:
# -- rust ---------------------------------------------------------------

def _rust_env(self) -> dict[str, str]:
"""Leaf-config env overrides for the gears host (direct Popen execve
preserves the hyphenated gear-name segments)."""
"""Leaf-config env overrides for the gears host."""
env = os.environ.copy()
env.update(
{
"APP__gears__api-gateway__config__bind_addr": f"127.0.0.1:{self.port}",
"APP__gears__grpc-hub__config__listen_addr": f"uds:///tmp/identity-resolution-grpc-{self.port}.sock",
"APP__gears__identity-resolution__config__database_url": identity_dsn(self.cfg),
"APP__gears__identity_resolution__config__database_url": identity_dsn(self.cfg),
# The Rust service reads ClickHouse over HTTP (the shared
# insight-clickhouse client).
"APP__gears__identity-resolution__config__clickhouse_url": self.cfg.ch_http_url,
"APP__gears__identity-resolution__config__clickhouse_database": self.cfg.ch_database,
"APP__gears__identity-resolution__config__clickhouse_user": self.cfg.ch_user,
"APP__gears__identity-resolution__config__clickhouse_password": self.cfg.ch_password,
"APP__gears__identity_resolution__config__clickhouse_url": self.cfg.ch_http_url,
"APP__gears__identity_resolution__config__clickhouse_database": self.cfg.ch_database,
"APP__gears__identity_resolution__config__clickhouse_user": self.cfg.ch_user,
"APP__gears__identity_resolution__config__clickhouse_password": self.cfg.ch_password,
"RUST_LOG": env.get("RUST_LOG", "info"),
}
)
Expand Down
Loading