Fix ClickHouse listen_host/logging and create-org.mjs shell-quoting bug#8
Open
dintorf wants to merge 2 commits into
Open
Conversation
The chart's ClickHouse config currently produces a server that listens on
127.0.0.1 only (no <listen_host> override → ClickHouse defaults to
localhost-only). That works for single-pod scenarios but breaks any
deployment where another pod needs to reach it — including the chart's own
post-install migrator-clickhouse Job, the web pod, and the worker pod.
It also writes logs to /var/log/clickhouse-server/ as XML, which means
Kubernetes log aggregators (Fluent Bit, Vector, Groundcover, etc.) tailing
stdout get nothing.
Adds two opt-in values that preserve current behavior by default:
clickhouse.listenHost: ""
Set to "0.0.0.0" to listen on all interfaces. Required for most
real Kubernetes deployments.
clickhouse.logging.structuredStdout.enabled: false
When true, configures the ClickHouse logger to emit JSON-formatted
logs to stdout (with the standard set of fields: date, time,
thread_id, level, query_id, logger_name, message, source_file,
source_line) and disables file logging. K8s log aggregators
typically tail stdout.
clickhouse.logging.structuredStdout.level: "information"
Log level when structured stdout is enabled.
`helm template` with defaults produces byte-identical output to before
this change; the new XML elements only render when the values are set.
The previous runSQL() composed a kubectl exec command that nested double- and single-quoted strings, and escaped only single quotes inside the SQL. The very first query selects FROM "user" (double-quoted because user is a reserved word in PostgreSQL). Those double quotes terminated the outer bash -c "..." string, so the unquoted identifier reached the server and was parsed as the current_user reserved keyword. The query failed with "column id does not exist" → the script reported "No admin users found" even when admins existed. The fix rewrites runSQL to feed the SQL to the server via stdin (kubectl exec -i + execSync input option). That eliminates SQL-side escaping entirely — identifiers like "user" and string literals with apostrophes pass through unchanged. Shell arguments (namespace, pod, db name, password) are now single-quoted with a safe escape helper. Matches the pattern grant-admin.sh already uses (heredoc), just in Node.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two unrelated-but-related fixes hit while standing up a production deployment of this chart. Filing together for review convenience; happy to split into two PRs if preferred.
1. ClickHouse: opt-in listen_host + K8s-friendly stdout logging
The chart's bundled ClickHouse StatefulSet starts a server that listens on
127.0.0.1only — the chart never sets<listen_host>inconfig.d/, so ClickHouse's stock default takes effect. That works for single-pod scenarios, but in any deployment where another pod has to reach ClickHouse (which includes this chart's ownpost-installmigrator-clickhouseJob, plus the web and worker pods), the connection lands on the pod IP, ClickHouse rejects it because it's not bound there, and the migrator fails with connection-refused.Reproduces on any vanilla
task up/helm installagainst a multi-node K8s cluster.It also writes XML-formatted logs to
/var/log/clickhouse-server/, so K8s log aggregators that tail stdout (Fluent Bit, Vector, Groundcover, OTel collectors) see nothing from the ClickHouse pod.Changes
Adds two opt-in values that preserve current chart behavior when unset:
The configmap template conditionally renders
<listen_host>and a<logger>block (JSON format, file logging disabled, console enabled) when these values are set. When both are at defaults,helm templateoutput is byte-identical to before this change — verified locally for both scenarios.2.
create-org.mjs: shell-quoting bug inrunSQLThe script's
runSQLhelper composes akubectl exec ... -- bash -c "..."command that nests double + single quoted strings and escapes only single quotes inside the SQL body. The very first query the script runs is:useris a reserved word in PostgreSQL, hence the required"user"quoting. Those double quotes terminate the outerbash -c "..."string, so the SQL that reaches the server is:PostgreSQL parses unquoted
useras thecurrent_userreserved keyword (returns the username as a scalar),idis not a column of a scalar, and the query fails with:The script catches the failure and reports "No admin users found" — misleading, since admins do exist.
Fix
Rewrites
runSQLto:kubectl exec -i+execSync'sinputoption). Identifiers like"user"and string literals with apostrophes pass through unchanged — no SQL-side escaping at all.This matches the pattern
grant-admin.shalready uses (heredoc-into-psql), just expressed in Node.Testing
helm template . --show-only templates/clickhouse-configmap.yamlproduces byte-identical output tomainwith default values.--set clickhouse.listenHost=0.0.0.0 --set clickhouse.logging.structuredStdout.enabled=trueproduces the expected<listen_host>and<logger>XML.node --check helm/scripts/create-org.mjspasses.0.0.0.0and emits structured JSON to stdout;task org:createwalks through admin selection and inserts the org+member rows without error.