typekro 0.34.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/alchemy/clickhouse-schema/executor.d.ts +25 -0
- package/dist/alchemy/clickhouse-schema/executor.d.ts.map +1 -0
- package/dist/alchemy/clickhouse-schema/executor.js +144 -0
- package/dist/alchemy/clickhouse-schema/executor.js.map +1 -0
- package/dist/alchemy/clickhouse-schema/index.d.ts +12 -0
- package/dist/alchemy/clickhouse-schema/index.d.ts.map +1 -0
- package/dist/alchemy/clickhouse-schema/index.js +11 -0
- package/dist/alchemy/clickhouse-schema/index.js.map +1 -0
- package/dist/alchemy/clickhouse-schema/resource.d.ts +54 -0
- package/dist/alchemy/clickhouse-schema/resource.d.ts.map +1 -0
- package/dist/alchemy/clickhouse-schema/resource.js +158 -0
- package/dist/alchemy/clickhouse-schema/resource.js.map +1 -0
- package/dist/alchemy/clickhouse-schema/runner.d.ts +154 -0
- package/dist/alchemy/clickhouse-schema/runner.d.ts.map +1 -0
- package/dist/alchemy/clickhouse-schema/runner.js +613 -0
- package/dist/alchemy/clickhouse-schema/runner.js.map +1 -0
- package/dist/alchemy/clickhouse-schema/sql.d.ts +109 -0
- package/dist/alchemy/clickhouse-schema/sql.d.ts.map +1 -0
- package/dist/alchemy/clickhouse-schema/sql.js +368 -0
- package/dist/alchemy/clickhouse-schema/sql.js.map +1 -0
- package/dist/alchemy/clickhouse-schema/types.d.ts +394 -0
- package/dist/alchemy/clickhouse-schema/types.d.ts.map +1 -0
- package/dist/alchemy/clickhouse-schema/types.js +370 -0
- package/dist/alchemy/clickhouse-schema/types.js.map +1 -0
- package/dist/alchemy/index.d.ts +1 -0
- package/dist/alchemy/index.d.ts.map +1 -1
- package/dist/alchemy/index.js +2 -0
- package/dist/alchemy/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types, validation schema and errors for the `ClickHouseSchema` alchemy resource.
|
|
3
|
+
*
|
|
4
|
+
* The configurable surface is ArkType-first: {@link ClickHouseSchemaConfigSchema} is the
|
|
5
|
+
* single source of truth and the config types are INFERRED from it, so a field cannot
|
|
6
|
+
* exist in the type without existing in the schema that validates it. Only the two
|
|
7
|
+
* fields ArkType cannot express usefully are declared separately on
|
|
8
|
+
* {@link ClickHouseSchemaProps}: `kubeConfig` (a structural TypeScript type owned by the
|
|
9
|
+
* client provider) and `executor` (a runtime-only injection point, deliberately not
|
|
10
|
+
* serializable — mirroring `TypeKroResourceProps.deployer`).
|
|
11
|
+
*/
|
|
12
|
+
import { type } from 'arktype';
|
|
13
|
+
import { TypeKroError } from '../../core/errors.js';
|
|
14
|
+
import { extractStatementSecrets, validateOnClusterStatement } from './sql.js';
|
|
15
|
+
/**
|
|
16
|
+
* Accepted shape for a ClickHouse user or database name.
|
|
17
|
+
*
|
|
18
|
+
* Every value that reaches the container is embedded in a single-quoted `sh -c`
|
|
19
|
+
* word, so a value containing a quote could close that word. It cannot: names are
|
|
20
|
+
* restricted here to characters that are inert in both the shell and
|
|
21
|
+
* `clickhouse-client`'s own argument parsing, and the renderer single-quotes them
|
|
22
|
+
* anyway (defence in depth, the same pairing the S3 backup CronJob uses).
|
|
23
|
+
*/
|
|
24
|
+
const CLICKHOUSE_NAME_PATTERN = /^[A-Za-z0-9_][A-Za-z0-9_.-]*$/;
|
|
25
|
+
/** POSIX environment variable name — what `--password "$VAR"` can expand. */
|
|
26
|
+
const ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
27
|
+
/** `--<setting>=<value>` setting name, matching ClickHouse's own setting identifiers. */
|
|
28
|
+
const SETTING_NAME_PATTERN = /^[a-z_][a-z0-9_]*$/;
|
|
29
|
+
/** Setting value: scalars only. Anything needing quoting belongs in a statement. */
|
|
30
|
+
const SETTING_VALUE_PATTERN = /^[A-Za-z0-9_.,:+-]+$/;
|
|
31
|
+
/** Kubernetes label key: optional DNS-subdomain prefix plus a name segment. */
|
|
32
|
+
const LABEL_KEY_PATTERN = /^(?:[a-z0-9](?:[a-z0-9.-]{0,251}[a-z0-9])?\/)?[A-Za-z0-9](?:[A-Za-z0-9_.-]{0,61}[A-Za-z0-9])?$/;
|
|
33
|
+
/** Kubernetes label value: empty, or up to 63 alphanumeric-delimited characters. */
|
|
34
|
+
const LABEL_VALUE_PATTERN = /^(?:[A-Za-z0-9](?:[A-Za-z0-9_.-]{0,61}[A-Za-z0-9])?)?$/;
|
|
35
|
+
/**
|
|
36
|
+
* A plaintext credential must never be representable in props: it would be persisted
|
|
37
|
+
* verbatim into the alchemy state store. `client` therefore REJECTS undeclared keys, so
|
|
38
|
+
* `password` (and any near-miss spelling of it) fails validation instead of being
|
|
39
|
+
* silently dropped and leaving the author believing they configured authentication.
|
|
40
|
+
*/
|
|
41
|
+
export const ClickHouseSchemaClientSchema = type({
|
|
42
|
+
'user?': 'string > 0',
|
|
43
|
+
/**
|
|
44
|
+
* Name of the environment variable holding the password INSIDE the target container.
|
|
45
|
+
* The value is never read by TypeKro, never echoed, and never enters props or state.
|
|
46
|
+
*/
|
|
47
|
+
'passwordEnv?': 'string > 0',
|
|
48
|
+
'database?': 'string > 0',
|
|
49
|
+
'port?': 'number.integer > 0',
|
|
50
|
+
})
|
|
51
|
+
.onUndeclaredKey('reject')
|
|
52
|
+
.narrow((client, ctx) => {
|
|
53
|
+
if (client.user !== undefined && !CLICKHOUSE_NAME_PATTERN.test(client.user)) {
|
|
54
|
+
return ctx.mustBe('a ClickHouse user name matching [A-Za-z0-9_][A-Za-z0-9_.-]*');
|
|
55
|
+
}
|
|
56
|
+
if (client.database !== undefined && !CLICKHOUSE_NAME_PATTERN.test(client.database)) {
|
|
57
|
+
return ctx.mustBe('a ClickHouse database name matching [A-Za-z0-9_][A-Za-z0-9_.-]*');
|
|
58
|
+
}
|
|
59
|
+
if (client.passwordEnv !== undefined && !ENV_VAR_NAME_PATTERN.test(client.passwordEnv)) {
|
|
60
|
+
return ctx.mustBe('an environment variable name matching [A-Za-z_][A-Za-z0-9_]*');
|
|
61
|
+
}
|
|
62
|
+
if (client.port !== undefined && client.port > 65535) {
|
|
63
|
+
return ctx.mustBe('a TCP port <= 65535');
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
});
|
|
67
|
+
/** How to reach the ClickHouse server: a namespace, a label selector, and a container. */
|
|
68
|
+
export const ClickHouseSchemaTargetSchema = type({
|
|
69
|
+
namespace: 'string > 0',
|
|
70
|
+
/**
|
|
71
|
+
* Label selector for the server pods — e.g. the Altinity CHI label
|
|
72
|
+
* `{ 'clickhouse.altinity.com/chi': 'orders' }`.
|
|
73
|
+
*
|
|
74
|
+
* Which of the matching pods are used is the execution model's business, not the
|
|
75
|
+
* selector's: `fanout` executes against every matching pod and requires all of them to
|
|
76
|
+
* be Ready, `onCluster` against the first Ready one. A selector that also matches
|
|
77
|
+
* non-server pods therefore fails a `fanout` converge rather than quietly skipping them
|
|
78
|
+
* — narrow it. See {@link ClickHouseSchemaExecutionSchema}.
|
|
79
|
+
*/
|
|
80
|
+
podSelector: 'Record<string, string>',
|
|
81
|
+
/** Container to exec into. Defaults to the CHI server container, `clickhouse`. */
|
|
82
|
+
'container?': 'string > 0',
|
|
83
|
+
}).narrow((target, ctx) => {
|
|
84
|
+
const entries = Object.entries(target.podSelector);
|
|
85
|
+
if (entries.length === 0) {
|
|
86
|
+
return ctx.mustBe('a non-empty pod label selector');
|
|
87
|
+
}
|
|
88
|
+
for (const [key, value] of entries) {
|
|
89
|
+
if (!LABEL_KEY_PATTERN.test(key)) {
|
|
90
|
+
return ctx.mustBe(`a valid Kubernetes label key (got '${key}')`);
|
|
91
|
+
}
|
|
92
|
+
if (!LABEL_VALUE_PATTERN.test(value)) {
|
|
93
|
+
return ctx.mustBe(`a valid Kubernetes label value for '${key}'`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
});
|
|
98
|
+
/** Bounded wait for a Ready server pod before the first exec. */
|
|
99
|
+
export const ClickHouseSchemaWaitForPodSchema = type({
|
|
100
|
+
timeoutMs: 'number.integer > 0',
|
|
101
|
+
});
|
|
102
|
+
/** Bounded retry of TRANSIENT exec failures. A SQL error is never retried. */
|
|
103
|
+
export const ClickHouseSchemaRetrySchema = type({
|
|
104
|
+
'maxAttempts?': 'number.integer > 0',
|
|
105
|
+
'backoffMs?': 'number.integer >= 0',
|
|
106
|
+
});
|
|
107
|
+
/**
|
|
108
|
+
* How the statements reach EVERY server, not just the one the exec landed on.
|
|
109
|
+
*
|
|
110
|
+
* ClickHouse DDL is server-local by default. `CREATE TABLE …` executed on one pod creates
|
|
111
|
+
* that table on that pod and nowhere else, so on a multi-replica or multi-shard
|
|
112
|
+
* deployment a converge that touches a single pod reports success while the rest of the
|
|
113
|
+
* cluster has no schema — and then never tries again, because the fingerprint says the
|
|
114
|
+
* work is done. Two mechanisms make DDL cluster-wide, and this resource requires one of
|
|
115
|
+
* them to be chosen explicitly:
|
|
116
|
+
*
|
|
117
|
+
* - `fanout` (the default) — TypeKro runs the ordered statement list against EVERY pod
|
|
118
|
+
* matching the selector, in turn. It needs nothing from the cluster (no Keeper, no
|
|
119
|
+
* `Replicated` database engine) and leans on exactly the idempotence the statements
|
|
120
|
+
* already promise. It is ALL OR NOTHING: every matching pod that is not terminating or
|
|
121
|
+
* finished must become Ready within `waitForPod.timeoutMs` and must carry the requested
|
|
122
|
+
* container, or the converge fails — so a StatefulSet mid-rollout makes the resource
|
|
123
|
+
* wait, and then fail, rather than fingerprint a half-applied schema. The pod set is
|
|
124
|
+
* recorded in state, so a scale-out or a replaced pod re-applies even though the
|
|
125
|
+
* statements did not change. A single-replica installation is a one-pod fanout — which
|
|
126
|
+
* is why the default is also the correct setting there.
|
|
127
|
+
* - `onCluster` — the statements distribute themselves and TypeKro runs them ONCE, on the
|
|
128
|
+
* first Ready pod; pods that are still rolling are Keeper's problem, not this converge's,
|
|
129
|
+
* which is what makes this the right mode on a large cluster. That is only true if each
|
|
130
|
+
* statement actually says so, so every statement is validated at construction; see
|
|
131
|
+
* {@link ClickHouseSchemaConfigSchema}.
|
|
132
|
+
*
|
|
133
|
+
* @see https://clickhouse.com/docs/sql-reference/distributed-ddl
|
|
134
|
+
*/
|
|
135
|
+
export const ClickHouseSchemaExecutionSchema = type({ mode: "'fanout'" }).or({
|
|
136
|
+
mode: "'onCluster'",
|
|
137
|
+
/** The `ON CLUSTER` target — a CHI's `clusterName`, which defaults to `cluster`. */
|
|
138
|
+
cluster: 'string > 0',
|
|
139
|
+
});
|
|
140
|
+
/** Applied when an author declares no execution model. */
|
|
141
|
+
export const DEFAULT_EXECUTION = { mode: 'fanout' };
|
|
142
|
+
/**
|
|
143
|
+
* The configurable (serializable) surface of a `ClickHouseSchema` resource.
|
|
144
|
+
*
|
|
145
|
+
* IDEMPOTENCE IS THE AUTHOR'S CONTRACT. Every statement is re-run whenever the
|
|
146
|
+
* fingerprint changes, so each one must be safe to execute against a database where
|
|
147
|
+
* it has already been executed: `CREATE DATABASE IF NOT EXISTS`, `CREATE TABLE IF NOT
|
|
148
|
+
* EXISTS`, `CREATE OR REPLACE VIEW`, `ALTER TABLE ... ADD COLUMN IF NOT EXISTS`,
|
|
149
|
+
* `DROP ... IF EXISTS`. TypeKro cannot verify that property — it does not parse SQL —
|
|
150
|
+
* so a non-idempotent statement surfaces as a converge that fails the second time.
|
|
151
|
+
*/
|
|
152
|
+
export const ClickHouseSchemaConfigSchema = type({
|
|
153
|
+
target: ClickHouseSchemaTargetSchema,
|
|
154
|
+
'client?': ClickHouseSchemaClientSchema,
|
|
155
|
+
/** Ordered DDL. Executed in array order; each must be individually idempotent. */
|
|
156
|
+
statements: 'string[] > 0',
|
|
157
|
+
/** Passed to `clickhouse-client` as `--<setting>=<value>`. Identifiers validated. */
|
|
158
|
+
'settings?': 'Record<string, string | number>',
|
|
159
|
+
/**
|
|
160
|
+
* `retain` (the default) leaves every object in place on delete: a schema resource
|
|
161
|
+
* must never drop data because a stack was torn down. `run` executes
|
|
162
|
+
* {@link deleteStatements} instead, which is the only way to express a destructive
|
|
163
|
+
* teardown and requires spelling out exactly what gets dropped.
|
|
164
|
+
*/
|
|
165
|
+
onDelete: "'retain' | 'run' = 'retain'",
|
|
166
|
+
'deleteStatements?': 'string[]',
|
|
167
|
+
'waitForPod?': ClickHouseSchemaWaitForPodSchema,
|
|
168
|
+
/**
|
|
169
|
+
* `fanout` only: how many times an apply re-lists and applies to pods that appeared
|
|
170
|
+
* while it was running, before failing rather than recording a partial apply.
|
|
171
|
+
*
|
|
172
|
+
* Defaults to 3. A settled cluster costs exactly one pass, so raising this only matters
|
|
173
|
+
* on a cluster whose topology is moving throughout the converge; the whole loop is also
|
|
174
|
+
* bounded by `waitForPod.timeoutMs`, spent across the passes rather than renewed by each
|
|
175
|
+
* one. Deliberately NOT part of the fingerprint: like `waitForPod`, `retry` and
|
|
176
|
+
* `statementTimeoutMs`, it says how the apply is driven, not what is applied, so changing
|
|
177
|
+
* it must not re-run DDL. Ignored under `onCluster`, which has no coverage to reconcile.
|
|
178
|
+
*/
|
|
179
|
+
'maxReconcilePasses?': 'number.integer > 0',
|
|
180
|
+
/** Per-statement exec timeout. A long `CREATE MATERIALIZED VIEW ... POPULATE` may need more. */
|
|
181
|
+
'statementTimeoutMs?': 'number.integer > 0',
|
|
182
|
+
'retry?': ClickHouseSchemaRetrySchema,
|
|
183
|
+
/** How the DDL reaches every server. Defaults to `fanout`. */
|
|
184
|
+
execution: ClickHouseSchemaExecutionSchema.default(() => DEFAULT_EXECUTION),
|
|
185
|
+
})
|
|
186
|
+
// Undeclared keys are REJECTED, for the same reason `client` rejects them: a
|
|
187
|
+
// misunderstood option that is silently dropped leaves the author believing they
|
|
188
|
+
// configured something. It is also what retires `replicatedDatabases` — an allow-list
|
|
189
|
+
// that used to accept clause-free `onCluster` statements, and did so by inspecting a
|
|
190
|
+
// statement's references rather than its DDL target — loudly rather than by ignoring it.
|
|
191
|
+
.onUndeclaredKey('reject')
|
|
192
|
+
.narrow((config, ctx) => {
|
|
193
|
+
const blank = config.statements.findIndex((statement) => statement.trim().length === 0);
|
|
194
|
+
if (blank !== -1) {
|
|
195
|
+
return ctx.mustBe(`non-empty statements (statement ${blank} is blank)`);
|
|
196
|
+
}
|
|
197
|
+
if (config.onDelete === 'run') {
|
|
198
|
+
if (config.deleteStatements === undefined || config.deleteStatements.length === 0) {
|
|
199
|
+
return ctx.mustBe("accompanied by a non-empty 'deleteStatements' when onDelete is 'run'");
|
|
200
|
+
}
|
|
201
|
+
const blankDelete = config.deleteStatements.findIndex((s) => s.trim().length === 0);
|
|
202
|
+
if (blankDelete !== -1) {
|
|
203
|
+
return ctx.mustBe(`non-empty deleteStatements (statement ${blankDelete} is blank)`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else if (config.deleteStatements !== undefined) {
|
|
207
|
+
// Rejected rather than ignored: statements that can never run are a silent footgun,
|
|
208
|
+
// and the author who wrote them believes teardown is covered.
|
|
209
|
+
return ctx.mustBe("declared without 'deleteStatements' when onDelete is 'retain'");
|
|
210
|
+
}
|
|
211
|
+
for (const [name, value] of Object.entries(config.settings ?? {})) {
|
|
212
|
+
if (!SETTING_NAME_PATTERN.test(name)) {
|
|
213
|
+
return ctx.mustBe(`a ClickHouse setting name matching [a-z_][a-z0-9_]* (got '${name}')`);
|
|
214
|
+
}
|
|
215
|
+
if (!SETTING_VALUE_PATTERN.test(String(value))) {
|
|
216
|
+
return ctx.mustBe(`a scalar setting value for '${name}'`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// `onCluster` is a PROMISE that one execution reaches every server, and the ONLY thing
|
|
220
|
+
// accepted as proof is an explicit `ON CLUSTER <cluster>` clause. It is checked here,
|
|
221
|
+
// at construction, rather than at converge time: a statement that cannot keep the
|
|
222
|
+
// promise would otherwise apply to one replica, record a fingerprint, and never be
|
|
223
|
+
// retried. TypeKro validates and refuses — it never edits the author's SQL to make the
|
|
224
|
+
// promise true, and it never infers cluster-wideness from a statement's shape.
|
|
225
|
+
if (config.execution.mode === 'onCluster') {
|
|
226
|
+
const cluster = config.execution.cluster;
|
|
227
|
+
const lists = [
|
|
228
|
+
['statements', config.statements],
|
|
229
|
+
['deleteStatements', config.deleteStatements ?? []],
|
|
230
|
+
];
|
|
231
|
+
for (const [field, statements] of lists) {
|
|
232
|
+
for (const [index, statement] of statements.entries()) {
|
|
233
|
+
const reason = validateOnClusterStatement(statement, cluster);
|
|
234
|
+
if (reason !== undefined) {
|
|
235
|
+
return ctx.mustBe(`cluster-wide under execution.mode 'onCluster' (${field} ${index} ${reason})`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return true;
|
|
241
|
+
});
|
|
242
|
+
/**
|
|
243
|
+
* A statement failed, a pod never became Ready, or the transport gave up.
|
|
244
|
+
*
|
|
245
|
+
* SECURITY: the failing statement's TEXT is never carried on the error — only its
|
|
246
|
+
* INDEX. Statements should not contain credentials (bind them through the server's own
|
|
247
|
+
* configuration, as the S3 storage compiler does), but a `CREATE TABLE ... S3(...,
|
|
248
|
+
* aws_secret_access_key)` would, and ClickHouse echoes the offending fragment back in
|
|
249
|
+
* its own message. Every message that reaches this error is passed through
|
|
250
|
+
* {@link redactClickHouseText} first.
|
|
251
|
+
*/
|
|
252
|
+
export class ClickHouseSchemaError extends TypeKroError {
|
|
253
|
+
resourceId;
|
|
254
|
+
statementIndex;
|
|
255
|
+
clickHouseCode;
|
|
256
|
+
detail;
|
|
257
|
+
clickHouseException;
|
|
258
|
+
constructor(message,
|
|
259
|
+
/** The alchemy resource `id` — the logical name the author gave THIS schema. */
|
|
260
|
+
resourceId,
|
|
261
|
+
/** Index into `statements` (or `deleteStatements`), or `undefined` outside statement execution. */
|
|
262
|
+
statementIndex,
|
|
263
|
+
/** ClickHouse's own error code, parsed from `Code: <n>.`, when the server produced one. */
|
|
264
|
+
clickHouseCode,
|
|
265
|
+
/** Redacted, length-capped server output — see {@link redactClickHouseOutput}. */
|
|
266
|
+
detail,
|
|
267
|
+
/** ClickHouse's exception class (`DB::Exception`, `DB::NetException`, …). */
|
|
268
|
+
clickHouseException, options) {
|
|
269
|
+
super(message, 'CLICKHOUSE_SCHEMA_ERROR', { resourceId, statementIndex, clickHouseCode, clickHouseException, detail }, options);
|
|
270
|
+
this.resourceId = resourceId;
|
|
271
|
+
this.statementIndex = statementIndex;
|
|
272
|
+
this.clickHouseCode = clickHouseCode;
|
|
273
|
+
this.detail = detail;
|
|
274
|
+
this.clickHouseException = clickHouseException;
|
|
275
|
+
this.name = 'ClickHouseSchemaError';
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Patterns whose surroundings are redacted out of any text that leaves the container.
|
|
280
|
+
*
|
|
281
|
+
* Matched case-insensitively against a whole line, because ClickHouse reports a bad
|
|
282
|
+
* table definition by quoting the definition — which is precisely where a secret would
|
|
283
|
+
* be if one were ever written into a statement.
|
|
284
|
+
*
|
|
285
|
+
* This is the SECOND layer only. It cannot see a credential the server echoes without a
|
|
286
|
+
* nearby keyword, which is exactly what a positional table function produces:
|
|
287
|
+
* `S3('https://…', 'AKIA…', 'wJalr…', 'CSV')` has the secret in argument three and the
|
|
288
|
+
* word "secret" nowhere. {@link redactClickHouseOutput} is the first layer and does not
|
|
289
|
+
* rely on keywords at all.
|
|
290
|
+
*/
|
|
291
|
+
const SECRET_LINE_PATTERN = /password|secret|aws_secret|access_key|credential|token/i;
|
|
292
|
+
/** Replace every line that could carry a credential with a marker. */
|
|
293
|
+
export function redactClickHouseText(text) {
|
|
294
|
+
return text
|
|
295
|
+
.split('\n')
|
|
296
|
+
.map((line) => (SECRET_LINE_PATTERN.test(line) ? '[redacted]' : line))
|
|
297
|
+
.join('\n');
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Ceiling on the server text retained on an error (~2 KiB).
|
|
301
|
+
*
|
|
302
|
+
* An echo is a diagnostic aid, not a log sink: a `DESCRIBE`-sized dump or a multi-megabyte
|
|
303
|
+
* parser trace carried into alchemy state and every log line is a liability of its own,
|
|
304
|
+
* independent of whether it contains a secret.
|
|
305
|
+
*/
|
|
306
|
+
export const MAX_RETAINED_DETAIL_CHARS = 2048;
|
|
307
|
+
const TRUNCATION_MARKER = '… [truncated]';
|
|
308
|
+
/**
|
|
309
|
+
* What survives from a failed exec's captured output.
|
|
310
|
+
*
|
|
311
|
+
* The contract is NOT "server output with credentials filtered out" — that framing is how
|
|
312
|
+
* the keyword-matching version came to leak. It is: keep what identifies the failure, and
|
|
313
|
+
* treat every value the SUBMITTED statement contained as a secret.
|
|
314
|
+
*
|
|
315
|
+
* In order:
|
|
316
|
+
*
|
|
317
|
+
* 1. The statement text itself is replaced wherever the server echoed it back, so a
|
|
318
|
+
* definition quoted in full cannot smuggle its own literals through.
|
|
319
|
+
* 2. Every literal the statement contains — every single-quoted value, plus whatever
|
|
320
|
+
* follows `PASSWORD` / `IDENTIFIED BY` / `access_key_id` / `secret_access_key` /
|
|
321
|
+
* `aws_access_key_id` / `aws_secret_access_key` / `token` — is replaced with
|
|
322
|
+
* `<redacted>` wherever it appears. This is positional, so it catches the arguments
|
|
323
|
+
* keyword matching cannot name. Each literal is redacted in EVERY spelling it could be
|
|
324
|
+
* echoed in, longest first: the decoded value, the raw source slice between the quotes,
|
|
325
|
+
* and the value re-escaped both ways ClickHouse accepts (`\'` and `''`). A credential
|
|
326
|
+
* containing a quote is one secret with several spellings, and the server frequently
|
|
327
|
+
* quotes back the one it was given rather than the one it decoded.
|
|
328
|
+
* 3. The keyword line filter runs as a second layer, for text the statement did not
|
|
329
|
+
* account for.
|
|
330
|
+
* 4. The result is capped at {@link MAX_RETAINED_DETAIL_CHARS}.
|
|
331
|
+
*
|
|
332
|
+
* ClickHouse's error CODE and exception class are parsed out BEFORE any of this and
|
|
333
|
+
* carried separately on the error, so redaction never costs the caller the one part of
|
|
334
|
+
* the message that says what went wrong.
|
|
335
|
+
*/
|
|
336
|
+
export function redactClickHouseOutput(output, statement) {
|
|
337
|
+
let text = output;
|
|
338
|
+
if (statement !== undefined) {
|
|
339
|
+
const trimmed = statement.trim();
|
|
340
|
+
if (trimmed.length >= 8)
|
|
341
|
+
text = text.split(trimmed).join('<redacted>');
|
|
342
|
+
for (const secret of extractStatementSecrets(statement)) {
|
|
343
|
+
text = text.split(secret).join('<redacted>');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
text = redactClickHouseText(text);
|
|
347
|
+
return text.length <= MAX_RETAINED_DETAIL_CHARS
|
|
348
|
+
? text
|
|
349
|
+
: `${text.slice(0, MAX_RETAINED_DETAIL_CHARS)}${TRUNCATION_MARKER}`;
|
|
350
|
+
}
|
|
351
|
+
/** Parse ClickHouse's `Code: 62. DB::Exception: …` prefix out of server output. */
|
|
352
|
+
export function parseClickHouseErrorCode(text) {
|
|
353
|
+
const match = /Code:\s*(\d+)/.exec(text);
|
|
354
|
+
if (!match?.[1])
|
|
355
|
+
return undefined;
|
|
356
|
+
const code = Number.parseInt(match[1], 10);
|
|
357
|
+
return Number.isNaN(code) ? undefined : code;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Parse the exception CLASS (`DB::Exception`, `DB::NetException`, `Poco::Exception`) out
|
|
361
|
+
* of server output.
|
|
362
|
+
*
|
|
363
|
+
* Retained alongside the numeric code because the two say different things: the code
|
|
364
|
+
* names the condition, the class says which subsystem raised it — and neither can carry
|
|
365
|
+
* a credential, so both survive redaction intact.
|
|
366
|
+
*/
|
|
367
|
+
export function parseClickHouseExceptionName(text) {
|
|
368
|
+
return /\b([A-Za-z][A-Za-z0-9_]*(?:::[A-Za-z][A-Za-z0-9_]*)+)/.exec(text)?.[1];
|
|
369
|
+
}
|
|
370
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/alchemy/clickhouse-schema/types.ts"],"names":[],"mappings":"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"}
|
package/dist/alchemy/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Uses dynamic resource registration to avoid "Resource already exists" errors.
|
|
8
8
|
*/
|
|
9
|
+
export { applyClickHouseSchema, CLICKHOUSE_SCHEMA_RESOURCE_TYPE, type ClickHouseExecCommand, type ClickHouseExecResult, type ClickHouseExecutor, type ClickHousePodSummary, ClickHouseSchema, type ClickHouseSchemaAppliedPod, type ClickHouseSchemaClient, ClickHouseSchemaClientSchema, type ClickHouseSchemaConfig, type ClickHouseSchemaConfigInput, ClickHouseSchemaConfigSchema, ClickHouseSchemaError, type ClickHouseSchemaExecution, ClickHouseSchemaExecutionSchema, type ClickHouseSchemaProps, type ClickHouseSchemaR, type ClickHouseSchemaResourceProps, type ClickHouseSchemaRunContext, type ClickHouseSchemaRuntimeDeps, type ClickHouseSchemaState, type ClickHouseSchemaTarget, ClickHouseSchemaTargetSchema, type ClickHouseSqlToken, clickHouseSchema, clickHouseSchemaProvider, computeFingerprint, DEFAULT_CLICKHOUSE_CONTAINER, DEFAULT_CLICKHOUSE_DATABASE, DEFAULT_CLICKHOUSE_PASSWORD_ENV, DEFAULT_CLICKHOUSE_PORT, DEFAULT_CLICKHOUSE_USER, DEFAULT_EXECUTION, DEFAULT_MAX_RECONCILE_PASSES, DEFAULT_STATEMENT_TIMEOUT_MS, DEFAULT_WAIT_FOR_POD_TIMEOUT_MS, deleteClickHouseSchema, escapeClickHouseString, extractStatementSecrets, KubeExecClickHouseExecutor, leadingKeyword, MAX_RETAINED_DETAIL_CHARS, needsApply, parseClickHouseErrorCode, parseClickHouseExceptionName, redactClickHouseOutput, redactClickHouseText, renderClickHouseCommand, runStatements, selectExecutionPods, statementTargetsCluster, tokenizeClickHouseSql, validateOnClusterStatement, } from './clickhouse-schema/index.js';
|
|
9
10
|
export { DirectTypeKroDeployer, KroTypeKroDeployer } from './deployers.js';
|
|
10
11
|
export type { AlchemyPromise, AlchemyResolutionContext, AlchemyResource } from './resolver.js';
|
|
11
12
|
export { buildResourceGraphWithDeferredResolution, containsAlchemyPromises, createAlchemyReferenceResolver, createAlchemyResourceConfig, createAlchemyResourceConfigs, extractAlchemyPromises, hasMixedDependencies, isAlchemyPromise, isAlchemyResource, resolveAlchemyPromise, resolveAllReferences, resolveAllReferencesInAlchemyContext, resolveReferencesWithAlchemy, resolveTypeKroReferencesOnly, } from './resolver.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/alchemy/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,YAAY,EAAE,cAAc,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAG/F,OAAO,EACL,wCAAwC,EACxC,uBAAuB,EACvB,8BAA8B,EAC9B,2BAA2B,EAC3B,4BAA4B,EAC5B,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,oCAAoC,EACpC,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG/D,OAAO,EACL,6BAA6B,EAC7B,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,mCAAmC,EAAE,MAAM,qBAAqB,CAAC;AAE1E,YAAY,EACV,sBAAsB,EACtB,0BAA0B,EAC1B,oBAAoB,EACpB,kCAAkC,EAClC,6BAA6B,EAC7B,eAAe,EACf,eAAe,EACf,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/alchemy/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,qBAAqB,EACrB,+BAA+B,EAC/B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,gBAAgB,EAChB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,4BAA4B,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAChC,4BAA4B,EAC5B,qBAAqB,EACrB,KAAK,yBAAyB,EAC9B,+BAA+B,EAC/B,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,6BAA6B,EAClC,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,4BAA4B,EAC5B,KAAK,kBAAkB,EACvB,gBAAgB,EAChB,wBAAwB,EACxB,kBAAkB,EAClB,4BAA4B,EAC5B,2BAA2B,EAC3B,+BAA+B,EAC/B,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,EACjB,4BAA4B,EAC5B,4BAA4B,EAC5B,+BAA+B,EAC/B,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,0BAA0B,EAC1B,cAAc,EACd,yBAAyB,EACzB,UAAU,EACV,wBAAwB,EACxB,4BAA4B,EAC5B,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,EACvB,aAAa,EACb,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,YAAY,EAAE,cAAc,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAG/F,OAAO,EACL,wCAAwC,EACxC,uBAAuB,EACvB,8BAA8B,EAC9B,2BAA2B,EAC3B,4BAA4B,EAC5B,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,oCAAoC,EACpC,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG/D,OAAO,EACL,6BAA6B,EAC7B,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,mCAAmC,EAAE,MAAM,qBAAqB,CAAC;AAE1E,YAAY,EACV,sBAAsB,EACtB,0BAA0B,EAC1B,oBAAoB,EACpB,kCAAkC,EAClC,6BAA6B,EAC7B,eAAe,EACf,eAAe,EACf,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/alchemy/index.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Uses dynamic resource registration to avoid "Resource already exists" errors.
|
|
8
8
|
*/
|
|
9
|
+
// ClickHouse schema management: converge-time DDL applied through `pods/exec`.
|
|
10
|
+
export { applyClickHouseSchema, CLICKHOUSE_SCHEMA_RESOURCE_TYPE, ClickHouseSchema, ClickHouseSchemaClientSchema, ClickHouseSchemaConfigSchema, ClickHouseSchemaError, ClickHouseSchemaExecutionSchema, ClickHouseSchemaTargetSchema, clickHouseSchema, clickHouseSchemaProvider, computeFingerprint, DEFAULT_CLICKHOUSE_CONTAINER, DEFAULT_CLICKHOUSE_DATABASE, DEFAULT_CLICKHOUSE_PASSWORD_ENV, DEFAULT_CLICKHOUSE_PORT, DEFAULT_CLICKHOUSE_USER, DEFAULT_EXECUTION, DEFAULT_MAX_RECONCILE_PASSES, DEFAULT_STATEMENT_TIMEOUT_MS, DEFAULT_WAIT_FOR_POD_TIMEOUT_MS, deleteClickHouseSchema, escapeClickHouseString, extractStatementSecrets, KubeExecClickHouseExecutor, leadingKeyword, MAX_RETAINED_DETAIL_CHARS, needsApply, parseClickHouseErrorCode, parseClickHouseExceptionName, redactClickHouseOutput, redactClickHouseText, renderClickHouseCommand, runStatements, selectExecutionPods, statementTargetsCluster, tokenizeClickHouseSql, validateOnClusterStatement, } from './clickhouse-schema/index.js';
|
|
9
11
|
// Deployer implementations
|
|
10
12
|
export { DirectTypeKroDeployer, KroTypeKroDeployer } from './deployers.js';
|
|
11
13
|
// Reference resolution
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/alchemy/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,2BAA2B;AAC3B,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAG3E,uBAAuB;AACvB,OAAO,EACL,wCAAwC,EACxC,uBAAuB,EACvB,8BAA8B,EAC9B,2BAA2B,EAC3B,4BAA4B,EAC5B,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,oCAAoC,EACpC,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,eAAe,CAAC;AAEvB,wFAAwF;AACxF,uFAAuF;AACvF,OAAO,EACL,6BAA6B,EAC7B,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AACpC,iBAAiB;AACjB,OAAO,EAAE,mCAAmC,EAAE,MAAM,qBAAqB,CAAC;AAa1E,oBAAoB;AACpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,oBAAoB;AACpB,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/alchemy/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,+EAA+E;AAC/E,OAAO,EACL,qBAAqB,EACrB,+BAA+B,EAK/B,gBAAgB,EAGhB,4BAA4B,EAG5B,4BAA4B,EAC5B,qBAAqB,EAErB,+BAA+B,EAQ/B,4BAA4B,EAE5B,gBAAgB,EAChB,wBAAwB,EACxB,kBAAkB,EAClB,4BAA4B,EAC5B,2BAA2B,EAC3B,+BAA+B,EAC/B,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,EACjB,4BAA4B,EAC5B,4BAA4B,EAC5B,+BAA+B,EAC/B,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,0BAA0B,EAC1B,cAAc,EACd,yBAAyB,EACzB,UAAU,EACV,wBAAwB,EACxB,4BAA4B,EAC5B,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,EACvB,aAAa,EACb,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC;AACtC,2BAA2B;AAC3B,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAG3E,uBAAuB;AACvB,OAAO,EACL,wCAAwC,EACxC,uBAAuB,EACvB,8BAA8B,EAC9B,2BAA2B,EAC3B,4BAA4B,EAC5B,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,oCAAoC,EACpC,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,eAAe,CAAC;AAEvB,wFAAwF;AACxF,uFAAuF;AACvF,OAAO,EACL,6BAA6B,EAC7B,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AACpC,iBAAiB;AACjB,OAAO,EAAE,mCAAmC,EAAE,MAAM,qBAAqB,CAAC;AAa1E,oBAAoB;AACpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,oBAAoB;AACpB,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC"}
|