@pleri/olam-cli 0.1.152 → 0.1.153
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/commands/doctor.d.ts +24 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +36 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/host-cp.d.ts.map +1 -1
- package/dist/commands/host-cp.js +17 -0
- package/dist/commands/host-cp.js.map +1 -1
- package/dist/commands/services.d.ts.map +1 -1
- package/dist/commands/services.js +9 -26
- package/dist/commands/services.js.map +1 -1
- package/dist/commands/substrate.d.ts +19 -1
- package/dist/commands/substrate.d.ts.map +1 -1
- package/dist/commands/substrate.js +19 -11
- package/dist/commands/substrate.js.map +1 -1
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +11 -0
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/image-digests.json +7 -7
- package/dist/index.js +13326 -12904
- package/dist/lib/auth-refresh-kubernetes.d.ts +3 -0
- package/dist/lib/auth-refresh-kubernetes.d.ts.map +1 -1
- package/dist/lib/auth-refresh-kubernetes.js +6 -17
- package/dist/lib/auth-refresh-kubernetes.js.map +1 -1
- package/dist/lib/health-probes.d.ts +20 -0
- package/dist/lib/health-probes.d.ts.map +1 -1
- package/dist/lib/health-probes.js +55 -0
- package/dist/lib/health-probes.js.map +1 -1
- package/dist/lib/k8s-bootstrap.d.ts +120 -0
- package/dist/lib/k8s-bootstrap.d.ts.map +1 -0
- package/dist/lib/k8s-bootstrap.js +193 -0
- package/dist/lib/k8s-bootstrap.js.map +1 -0
- package/dist/lib/k8s-secret-render.d.ts +139 -0
- package/dist/lib/k8s-secret-render.d.ts.map +1 -0
- package/dist/lib/k8s-secret-render.js +281 -0
- package/dist/lib/k8s-secret-render.js.map +1 -0
- package/dist/lib/kubectl-context.d.ts +38 -0
- package/dist/lib/kubectl-context.d.ts.map +1 -0
- package/dist/lib/kubectl-context.js +43 -0
- package/dist/lib/kubectl-context.js.map +1 -0
- package/dist/lib/upgrade-kubernetes.d.ts +23 -0
- package/dist/lib/upgrade-kubernetes.d.ts.map +1 -1
- package/dist/lib/upgrade-kubernetes.js +67 -22
- package/dist/lib/upgrade-kubernetes.js.map +1 -1
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* k8s-secret-render.ts — render `REPLACE_ME_FROM_*` placeholders in the
|
|
3
|
+
* shipped k8s Secret templates with real values, and persist the rendered
|
|
4
|
+
* set so reapply is idempotent.
|
|
5
|
+
*
|
|
6
|
+
* B5 of olam-issue-npm-only-k3s (npm-only operator bootstrap completion).
|
|
7
|
+
*
|
|
8
|
+
* The templates at `packages/host-cp/k8s/templates/*-secret-template.yaml`
|
|
9
|
+
* carry placeholders like `REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_SECRET`. The
|
|
10
|
+
* source-of-truth value for each placeholder is documented in the template
|
|
11
|
+
* comment block; it's either a host-side file in `~/.olam/` (the compose
|
|
12
|
+
* bootstrap path) or a subprocess output (e.g. `gh auth token`).
|
|
13
|
+
*
|
|
14
|
+
* Source resolution per placeholder:
|
|
15
|
+
*
|
|
16
|
+
* placeholder → source
|
|
17
|
+
* REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_SECRET → file ~/.olam/auth-secret (generate if missing)
|
|
18
|
+
* REPLACE_ME_FROM_GH_AUTH_TOKEN → subprocess `gh auth token` (warn + skip if absent)
|
|
19
|
+
* REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_DB_SECRET → file ~/.olam/auth-db-secret (generate if missing)
|
|
20
|
+
* REPLACE_ME_FROM_HOME_DOTOLAM_MCP_AUTH_JWT_SECRET → file ~/.olam/mcp-auth-jwt-secret (generate if missing)
|
|
21
|
+
* REPLACE_ME_FROM_HOME_DOTOLAM_KG_BEARER_TOKEN → file ~/.olam/kg-bearer-token (generate if missing)
|
|
22
|
+
* REPLACE_ME_FROM_HOME_DOTOLAM_MEMORY_BEARER_SECRET → file ~/.olam/memory-bearer-secret (generate if missing)
|
|
23
|
+
*
|
|
24
|
+
* State persistence: `~/.olam/k8s-secrets-state.json` records the rendered
|
|
25
|
+
* Secret set so re-runs (idempotent reapply) reuse the same values. Without
|
|
26
|
+
* the state file every `olam upgrade` would rotate tokens silently, breaking
|
|
27
|
+
* worlds that have cached the previous value. Operator opts in to rotation
|
|
28
|
+
* via `--rotate-secrets`.
|
|
29
|
+
*
|
|
30
|
+
* D20 stdin-safe design: rendered YAML is built in-process and applied via
|
|
31
|
+
* stdin to `kubectl apply -f -`. Placeholder values are NEVER inlined into
|
|
32
|
+
* subprocess argv (audit:auth-callers + general security hygiene).
|
|
33
|
+
*/
|
|
34
|
+
export declare const K8S_SECRETS_STATE_PATH: string;
|
|
35
|
+
/**
|
|
36
|
+
* One template's placeholder set + the per-host-file source it reads from.
|
|
37
|
+
* Hardcoded mapping — every secret template's `# Source:` comment names the
|
|
38
|
+
* file; the audit:cli-bundle-k8s gate ensures the templates stay in sync.
|
|
39
|
+
*/
|
|
40
|
+
export interface SecretTemplateBinding {
|
|
41
|
+
readonly secretName: string;
|
|
42
|
+
readonly templateRelPath: string;
|
|
43
|
+
readonly placeholders: ReadonlyArray<{
|
|
44
|
+
readonly placeholder: string;
|
|
45
|
+
readonly key: string;
|
|
46
|
+
readonly source: {
|
|
47
|
+
readonly kind: 'file';
|
|
48
|
+
readonly hostFile: string;
|
|
49
|
+
} | {
|
|
50
|
+
readonly kind: 'gh-token';
|
|
51
|
+
};
|
|
52
|
+
}>;
|
|
53
|
+
}
|
|
54
|
+
/** Canonical mapping for the 5 secret templates that ship with the CLI. */
|
|
55
|
+
export declare const SECRET_TEMPLATE_BINDINGS: ReadonlyArray<SecretTemplateBinding>;
|
|
56
|
+
/** Per-secret state record — keys map to RENDERED values reused on re-apply. */
|
|
57
|
+
export interface RenderedSecret {
|
|
58
|
+
readonly keys: Record<string, string>;
|
|
59
|
+
readonly skipped?: ReadonlyArray<string>;
|
|
60
|
+
}
|
|
61
|
+
/** State file shape. version=1 lets us migrate the schema without breaking older state. */
|
|
62
|
+
export interface K8sSecretsState {
|
|
63
|
+
readonly version: 1;
|
|
64
|
+
readonly context: string;
|
|
65
|
+
readonly namespace: string;
|
|
66
|
+
readonly generatedAt: string;
|
|
67
|
+
readonly secrets: Record<string, RenderedSecret>;
|
|
68
|
+
}
|
|
69
|
+
/** Injectable deps so tests don't touch the real filesystem / shell. */
|
|
70
|
+
export interface RenderDeps {
|
|
71
|
+
readonly olamHome?: string;
|
|
72
|
+
readonly statePath?: string;
|
|
73
|
+
readonly readFile?: (path: string, enc: 'utf8') => string;
|
|
74
|
+
readonly writeFile?: (path: string, data: string, mode: number) => void;
|
|
75
|
+
readonly fileExists?: (path: string) => boolean;
|
|
76
|
+
readonly genRandomHex?: () => string;
|
|
77
|
+
readonly runGhTokenCmd?: () => {
|
|
78
|
+
ok: boolean;
|
|
79
|
+
token: string;
|
|
80
|
+
};
|
|
81
|
+
readonly readState?: () => K8sSecretsState | null;
|
|
82
|
+
readonly writeState?: (state: K8sSecretsState) => void;
|
|
83
|
+
readonly stderr?: NodeJS.WritableStream;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Read the state file. Returns null when missing OR when the version doesn't match (forward-compat).
|
|
87
|
+
*/
|
|
88
|
+
export declare function readSecretsState(statePath?: string): K8sSecretsState | null;
|
|
89
|
+
/** Atomically write the state file (0600). */
|
|
90
|
+
export declare function writeSecretsState(state: K8sSecretsState, statePath?: string): void;
|
|
91
|
+
/**
|
|
92
|
+
* Result of rendering one Secret. Either:
|
|
93
|
+
* - resolved: every placeholder got a value (rendered YAML is ready to apply).
|
|
94
|
+
* - skipped: at least one source was unavailable AND not generatable (e.g.
|
|
95
|
+
* gh auth token absent); the operator must apply this secret
|
|
96
|
+
* manually OR install gh + retry.
|
|
97
|
+
*/
|
|
98
|
+
export interface RenderResult {
|
|
99
|
+
readonly secretName: string;
|
|
100
|
+
readonly status: 'resolved' | 'skipped';
|
|
101
|
+
readonly renderedYaml?: string;
|
|
102
|
+
readonly keys: Record<string, string>;
|
|
103
|
+
readonly missingSources: ReadonlyArray<string>;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Substitute the placeholder strings in the template YAML with real values.
|
|
107
|
+
* Builds a fresh Secret YAML string (does NOT touch the template on disk).
|
|
108
|
+
*
|
|
109
|
+
* The templates hold ONE placeholder per stringData key; literal string
|
|
110
|
+
* substitution suffices. We avoid YAML parsing to keep the template comment
|
|
111
|
+
* block (which carries operator-facing documentation) intact in the rendered
|
|
112
|
+
* output.
|
|
113
|
+
*/
|
|
114
|
+
export declare function substitutePlaceholders(templateYaml: string, values: Record<string, string>): string;
|
|
115
|
+
/**
|
|
116
|
+
* Render ONE secret template. Reads the template YAML from `templatesRoot`
|
|
117
|
+
* (resolved by the caller to either source or install-mode location),
|
|
118
|
+
* resolves each placeholder, persists generated values to host files,
|
|
119
|
+
* substitutes, and returns the rendered YAML.
|
|
120
|
+
*
|
|
121
|
+
* `reuse` carries the prior state's per-key values when an unrotated
|
|
122
|
+
* re-apply is requested; null means "this is the first apply or operator
|
|
123
|
+
* asked for rotation."
|
|
124
|
+
*/
|
|
125
|
+
export declare function renderOneSecret(binding: SecretTemplateBinding, templatesRoot: string, reuse: RenderedSecret | null, deps?: RenderDeps, rotate?: boolean): RenderResult;
|
|
126
|
+
/**
|
|
127
|
+
* Render the full set of shipped Secret templates. `rotate=true` discards
|
|
128
|
+
* the on-disk state and regenerates every value; `rotate=false` reuses
|
|
129
|
+
* state for unchanged secrets so worlds caching old tokens don't break.
|
|
130
|
+
*/
|
|
131
|
+
export declare function renderAllSecrets(templatesRoot: string, opts: {
|
|
132
|
+
rotate: boolean;
|
|
133
|
+
context: string;
|
|
134
|
+
namespace: string;
|
|
135
|
+
}, deps?: RenderDeps): {
|
|
136
|
+
results: ReadonlyArray<RenderResult>;
|
|
137
|
+
nextState: K8sSecretsState;
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=k8s-secret-render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"k8s-secret-render.d.ts","sourceRoot":"","sources":["../../src/lib/k8s-secret-render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* k8s-secret-render.ts — render `REPLACE_ME_FROM_*` placeholders in the
|
|
3
|
+
* shipped k8s Secret templates with real values, and persist the rendered
|
|
4
|
+
* set so reapply is idempotent.
|
|
5
|
+
*
|
|
6
|
+
* B5 of olam-issue-npm-only-k3s (npm-only operator bootstrap completion).
|
|
7
|
+
*
|
|
8
|
+
* The templates at `packages/host-cp/k8s/templates/*-secret-template.yaml`
|
|
9
|
+
* carry placeholders like `REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_SECRET`. The
|
|
10
|
+
* source-of-truth value for each placeholder is documented in the template
|
|
11
|
+
* comment block; it's either a host-side file in `~/.olam/` (the compose
|
|
12
|
+
* bootstrap path) or a subprocess output (e.g. `gh auth token`).
|
|
13
|
+
*
|
|
14
|
+
* Source resolution per placeholder:
|
|
15
|
+
*
|
|
16
|
+
* placeholder → source
|
|
17
|
+
* REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_SECRET → file ~/.olam/auth-secret (generate if missing)
|
|
18
|
+
* REPLACE_ME_FROM_GH_AUTH_TOKEN → subprocess `gh auth token` (warn + skip if absent)
|
|
19
|
+
* REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_DB_SECRET → file ~/.olam/auth-db-secret (generate if missing)
|
|
20
|
+
* REPLACE_ME_FROM_HOME_DOTOLAM_MCP_AUTH_JWT_SECRET → file ~/.olam/mcp-auth-jwt-secret (generate if missing)
|
|
21
|
+
* REPLACE_ME_FROM_HOME_DOTOLAM_KG_BEARER_TOKEN → file ~/.olam/kg-bearer-token (generate if missing)
|
|
22
|
+
* REPLACE_ME_FROM_HOME_DOTOLAM_MEMORY_BEARER_SECRET → file ~/.olam/memory-bearer-secret (generate if missing)
|
|
23
|
+
*
|
|
24
|
+
* State persistence: `~/.olam/k8s-secrets-state.json` records the rendered
|
|
25
|
+
* Secret set so re-runs (idempotent reapply) reuse the same values. Without
|
|
26
|
+
* the state file every `olam upgrade` would rotate tokens silently, breaking
|
|
27
|
+
* worlds that have cached the previous value. Operator opts in to rotation
|
|
28
|
+
* via `--rotate-secrets`.
|
|
29
|
+
*
|
|
30
|
+
* D20 stdin-safe design: rendered YAML is built in-process and applied via
|
|
31
|
+
* stdin to `kubectl apply -f -`. Placeholder values are NEVER inlined into
|
|
32
|
+
* subprocess argv (audit:auth-callers + general security hygiene).
|
|
33
|
+
*/
|
|
34
|
+
import { spawnSync } from 'node:child_process';
|
|
35
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync, statSync } from 'node:fs';
|
|
36
|
+
import { join, dirname } from 'node:path';
|
|
37
|
+
import { randomBytes } from 'node:crypto';
|
|
38
|
+
import { OLAM_HOME } from './config.js';
|
|
39
|
+
export const K8S_SECRETS_STATE_PATH = join(OLAM_HOME, 'k8s-secrets-state.json');
|
|
40
|
+
const SECRET_HEX_BYTES = 32; // 64-char hex tokens — mirrors memory-secret.ts SECRET_LEN_BYTES.
|
|
41
|
+
/** Canonical mapping for the 5 secret templates that ship with the CLI. */
|
|
42
|
+
export const SECRET_TEMPLATE_BINDINGS = [
|
|
43
|
+
{
|
|
44
|
+
secretName: 'olam-host-cp-secret',
|
|
45
|
+
templateRelPath: 'templates/40-secret-template.yaml',
|
|
46
|
+
placeholders: [
|
|
47
|
+
{
|
|
48
|
+
placeholder: 'REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_SECRET',
|
|
49
|
+
key: 'OLAM_AUTH_SECRET',
|
|
50
|
+
source: { kind: 'file', hostFile: 'auth-secret' },
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
placeholder: 'REPLACE_ME_FROM_GH_AUTH_TOKEN',
|
|
54
|
+
key: 'GH_TOKEN',
|
|
55
|
+
source: { kind: 'gh-token' },
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
secretName: 'olam-auth-service-secret',
|
|
61
|
+
templateRelPath: 'templates/auth-service-secret-template.yaml',
|
|
62
|
+
placeholders: [
|
|
63
|
+
{
|
|
64
|
+
placeholder: 'REPLACE_ME_FROM_HOME_DOTOLAM_AUTH_DB_SECRET',
|
|
65
|
+
key: 'OLAM_AUTH_DB_SECRET',
|
|
66
|
+
source: { kind: 'file', hostFile: 'auth-db-secret' },
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
secretName: 'olam-mcp-auth-service-secret',
|
|
72
|
+
templateRelPath: 'templates/mcp-auth-service-secret-template.yaml',
|
|
73
|
+
placeholders: [
|
|
74
|
+
{
|
|
75
|
+
placeholder: 'REPLACE_ME_FROM_HOME_DOTOLAM_MCP_AUTH_JWT_SECRET',
|
|
76
|
+
key: 'OLAM_MCP_AUTH_JWT_SECRET',
|
|
77
|
+
source: { kind: 'file', hostFile: 'mcp-auth-jwt-secret' },
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
secretName: 'olam-kg-service-secret',
|
|
83
|
+
templateRelPath: 'templates/kg-service-secret-template.yaml',
|
|
84
|
+
placeholders: [
|
|
85
|
+
{
|
|
86
|
+
placeholder: 'REPLACE_ME_FROM_HOME_DOTOLAM_KG_BEARER_TOKEN',
|
|
87
|
+
key: 'OLAM_KG_BEARER_TOKEN',
|
|
88
|
+
source: { kind: 'file', hostFile: 'kg-bearer-token' },
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
secretName: 'olam-memory-service-secret',
|
|
94
|
+
templateRelPath: 'templates/memory-service-secret-template.yaml',
|
|
95
|
+
placeholders: [
|
|
96
|
+
{
|
|
97
|
+
placeholder: 'REPLACE_ME_FROM_HOME_DOTOLAM_MEMORY_BEARER_SECRET',
|
|
98
|
+
key: 'OLAM_MEMORY_BEARER_SECRET',
|
|
99
|
+
source: { kind: 'file', hostFile: 'memory-bearer-secret' },
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
const defaultGenRandomHex = () => randomBytes(SECRET_HEX_BYTES).toString('hex');
|
|
105
|
+
const defaultRunGhTokenCmd = () => {
|
|
106
|
+
const r = spawnSync('gh', ['auth', 'token'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
107
|
+
if (r.status === 0 && r.stdout.trim().length > 0) {
|
|
108
|
+
return { ok: true, token: r.stdout.trim() };
|
|
109
|
+
}
|
|
110
|
+
return { ok: false, token: '' };
|
|
111
|
+
};
|
|
112
|
+
const defaultReadFile = (p, enc) => readFileSync(p, enc);
|
|
113
|
+
const defaultWriteFile = (p, data, mode) => {
|
|
114
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
115
|
+
writeFileSync(p, data, { encoding: 'utf8', mode });
|
|
116
|
+
// writeFileSync's mode is umask-respecting; chmod explicitly to be safe.
|
|
117
|
+
chmodSync(p, mode);
|
|
118
|
+
};
|
|
119
|
+
const defaultFileExists = (p) => existsSync(p);
|
|
120
|
+
/**
|
|
121
|
+
* Read the state file. Returns null when missing OR when the version doesn't match (forward-compat).
|
|
122
|
+
*/
|
|
123
|
+
export function readSecretsState(statePath = K8S_SECRETS_STATE_PATH) {
|
|
124
|
+
if (!existsSync(statePath))
|
|
125
|
+
return null;
|
|
126
|
+
try {
|
|
127
|
+
const raw = readFileSync(statePath, 'utf8');
|
|
128
|
+
const parsed = JSON.parse(raw);
|
|
129
|
+
if (parsed.version !== 1)
|
|
130
|
+
return null;
|
|
131
|
+
return parsed;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** Atomically write the state file (0600). */
|
|
138
|
+
export function writeSecretsState(state, statePath = K8S_SECRETS_STATE_PATH) {
|
|
139
|
+
mkdirSync(dirname(statePath), { recursive: true });
|
|
140
|
+
const tmp = `${statePath}.tmp.${process.pid}`;
|
|
141
|
+
writeFileSync(tmp, JSON.stringify(state, null, 2) + '\n', { encoding: 'utf8', mode: 0o600 });
|
|
142
|
+
chmodSync(tmp, 0o600);
|
|
143
|
+
// renameSync is atomic on POSIX
|
|
144
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
145
|
+
require('node:fs').renameSync(tmp, statePath);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Resolve a single placeholder's value. Returns null when the source is
|
|
149
|
+
* absent AND not generatable (gh-token only). For file-sourced placeholders
|
|
150
|
+
* we always generate if missing — that's the npm-only operator path.
|
|
151
|
+
*/
|
|
152
|
+
function resolveSourceValue(source, olamHome, reuseFromState, rotate, deps) {
|
|
153
|
+
if (!rotate && reuseFromState !== undefined && reuseFromState !== '') {
|
|
154
|
+
return { ok: true, value: reuseFromState };
|
|
155
|
+
}
|
|
156
|
+
if (source.kind === 'file') {
|
|
157
|
+
const filePath = join(olamHome, source.hostFile);
|
|
158
|
+
// Rotation: always generate fresh value, overwrite the host file.
|
|
159
|
+
if (rotate) {
|
|
160
|
+
const fresh = deps.genRandomHex();
|
|
161
|
+
deps.writeFile(filePath, fresh, 0o600);
|
|
162
|
+
return { ok: true, value: fresh };
|
|
163
|
+
}
|
|
164
|
+
if (deps.fileExists(filePath)) {
|
|
165
|
+
const value = deps.readFile(filePath, 'utf8').trim();
|
|
166
|
+
if (value.length > 0)
|
|
167
|
+
return { ok: true, value };
|
|
168
|
+
}
|
|
169
|
+
// Missing or empty — generate, persist, return.
|
|
170
|
+
const fresh = deps.genRandomHex();
|
|
171
|
+
deps.writeFile(filePath, fresh, 0o600);
|
|
172
|
+
return { ok: true, value: fresh };
|
|
173
|
+
}
|
|
174
|
+
// kind === 'gh-token' — not generatable; warn + skip if absent.
|
|
175
|
+
// Rotation reads gh CLI again (gh manages its own session rotation).
|
|
176
|
+
const r = deps.runGhTokenCmd();
|
|
177
|
+
if (r.ok)
|
|
178
|
+
return { ok: true, value: r.token };
|
|
179
|
+
return { ok: false, reason: 'gh CLI not authenticated; run `gh auth login` then re-run' };
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Substitute the placeholder strings in the template YAML with real values.
|
|
183
|
+
* Builds a fresh Secret YAML string (does NOT touch the template on disk).
|
|
184
|
+
*
|
|
185
|
+
* The templates hold ONE placeholder per stringData key; literal string
|
|
186
|
+
* substitution suffices. We avoid YAML parsing to keep the template comment
|
|
187
|
+
* block (which carries operator-facing documentation) intact in the rendered
|
|
188
|
+
* output.
|
|
189
|
+
*/
|
|
190
|
+
export function substitutePlaceholders(templateYaml, values) {
|
|
191
|
+
let out = templateYaml;
|
|
192
|
+
for (const [placeholder, value] of Object.entries(values)) {
|
|
193
|
+
// Use split/join rather than .replace to avoid regex escaping pitfalls.
|
|
194
|
+
out = out.split(`"${placeholder}"`).join(`"${value}"`);
|
|
195
|
+
}
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Render ONE secret template. Reads the template YAML from `templatesRoot`
|
|
200
|
+
* (resolved by the caller to either source or install-mode location),
|
|
201
|
+
* resolves each placeholder, persists generated values to host files,
|
|
202
|
+
* substitutes, and returns the rendered YAML.
|
|
203
|
+
*
|
|
204
|
+
* `reuse` carries the prior state's per-key values when an unrotated
|
|
205
|
+
* re-apply is requested; null means "this is the first apply or operator
|
|
206
|
+
* asked for rotation."
|
|
207
|
+
*/
|
|
208
|
+
export function renderOneSecret(binding, templatesRoot, reuse, deps = {}, rotate = false) {
|
|
209
|
+
const olamHome = deps.olamHome ?? OLAM_HOME;
|
|
210
|
+
const readFile = deps.readFile ?? defaultReadFile;
|
|
211
|
+
const writeFile = deps.writeFile ?? defaultWriteFile;
|
|
212
|
+
const fileExists = deps.fileExists ?? defaultFileExists;
|
|
213
|
+
const genRandomHex = deps.genRandomHex ?? defaultGenRandomHex;
|
|
214
|
+
const runGhTokenCmd = deps.runGhTokenCmd ?? defaultRunGhTokenCmd;
|
|
215
|
+
const templatePath = join(templatesRoot, binding.templateRelPath);
|
|
216
|
+
const templateYaml = readFile(templatePath, 'utf8');
|
|
217
|
+
const keys = {};
|
|
218
|
+
const placeholderToValue = {};
|
|
219
|
+
const missingSources = [];
|
|
220
|
+
for (const p of binding.placeholders) {
|
|
221
|
+
const resolved = resolveSourceValue(p.source, olamHome, reuse?.keys[p.key], rotate, { readFile, writeFile, fileExists, genRandomHex, runGhTokenCmd });
|
|
222
|
+
if (!resolved.ok) {
|
|
223
|
+
missingSources.push(`${p.key}: ${resolved.reason}`);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
keys[p.key] = resolved.value;
|
|
227
|
+
placeholderToValue[p.placeholder] = resolved.value;
|
|
228
|
+
}
|
|
229
|
+
if (missingSources.length > 0) {
|
|
230
|
+
return {
|
|
231
|
+
secretName: binding.secretName,
|
|
232
|
+
status: 'skipped',
|
|
233
|
+
keys,
|
|
234
|
+
missingSources,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
const renderedYaml = substitutePlaceholders(templateYaml, placeholderToValue);
|
|
238
|
+
return {
|
|
239
|
+
secretName: binding.secretName,
|
|
240
|
+
status: 'resolved',
|
|
241
|
+
renderedYaml,
|
|
242
|
+
keys,
|
|
243
|
+
missingSources: [],
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Render the full set of shipped Secret templates. `rotate=true` discards
|
|
248
|
+
* the on-disk state and regenerates every value; `rotate=false` reuses
|
|
249
|
+
* state for unchanged secrets so worlds caching old tokens don't break.
|
|
250
|
+
*/
|
|
251
|
+
export function renderAllSecrets(templatesRoot, opts, deps = {}) {
|
|
252
|
+
const readState = deps.readState ?? (() => readSecretsState(deps.statePath ?? K8S_SECRETS_STATE_PATH));
|
|
253
|
+
const writeState = deps.writeState ?? ((s) => writeSecretsState(s, deps.statePath ?? K8S_SECRETS_STATE_PATH));
|
|
254
|
+
const prior = opts.rotate ? null : readState();
|
|
255
|
+
const results = [];
|
|
256
|
+
const nextSecrets = {};
|
|
257
|
+
for (const binding of SECRET_TEMPLATE_BINDINGS) {
|
|
258
|
+
const reuse = prior?.secrets[binding.secretName] ?? null;
|
|
259
|
+
const r = renderOneSecret(binding, templatesRoot, reuse, deps, opts.rotate);
|
|
260
|
+
results.push(r);
|
|
261
|
+
nextSecrets[binding.secretName] = {
|
|
262
|
+
keys: r.keys,
|
|
263
|
+
...(r.missingSources.length > 0 ? { skipped: r.missingSources } : {}),
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
const nextState = {
|
|
267
|
+
version: 1,
|
|
268
|
+
context: opts.context,
|
|
269
|
+
namespace: opts.namespace,
|
|
270
|
+
generatedAt: new Date().toISOString(),
|
|
271
|
+
secrets: nextSecrets,
|
|
272
|
+
};
|
|
273
|
+
// Only persist when at least one secret resolved — avoids an empty state file
|
|
274
|
+
// on a wholly-failed first run (where every gh-token source was absent and
|
|
275
|
+
// the operator hadn't yet generated `~/.olam/*` files).
|
|
276
|
+
if (results.some((r) => r.status === 'resolved')) {
|
|
277
|
+
writeState(nextState);
|
|
278
|
+
}
|
|
279
|
+
return { results, nextState };
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=k8s-secret-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"k8s-secret-render.js","sourceRoot":"","sources":["../../src/lib/k8s-secret-render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kubectl-context.ts — shared kubectl-context resolver.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the D1 / SEC-NEW-003 context-resolution
|
|
5
|
+
* policy. Extracted so `upgrade-kubernetes.ts`, `auth-refresh-kubernetes.ts`,
|
|
6
|
+
* `services.ts`, and any future kubernetes-substrate consumer can call the
|
|
7
|
+
* same helper instead of duplicating it.
|
|
8
|
+
*
|
|
9
|
+
* Policy (matches the pre-existing auth-refresh-kubernetes.ts and services.ts
|
|
10
|
+
* behaviour — see also docs/architecture/peripheral-services-on-k3s.md):
|
|
11
|
+
*
|
|
12
|
+
* 1. `host.kubectl_context_pinned` in `~/.olam/config.json` (preferred,
|
|
13
|
+
* persistent — the doc-recommended way).
|
|
14
|
+
* 2. `OLAM_K8S_CONTEXT_ACK` env var (deprecated fallback; emits a
|
|
15
|
+
* deprecation warning to nudge operators toward (1)).
|
|
16
|
+
* 3. Both absent → error result with actionable remediation.
|
|
17
|
+
*
|
|
18
|
+
* No `fs` reads in this module beyond what `readConfig` does; no kubectl
|
|
19
|
+
* invocations. Pure resolution. Safe to call from any layer.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Result shape mirrors `auth-refresh-kubernetes.ts`'s pre-existing public
|
|
23
|
+
* `resolveKubectlContext` so callers there can be migrated without source
|
|
24
|
+
* changes. Exactly one of `context` or `error` is set.
|
|
25
|
+
*/
|
|
26
|
+
export interface KubectlContextResolution {
|
|
27
|
+
readonly context?: string;
|
|
28
|
+
readonly deprecationWarning?: string;
|
|
29
|
+
readonly error?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the operator's kubectl context name. See module docstring for policy.
|
|
33
|
+
*
|
|
34
|
+
* `configPath` lets callers (and tests) point at a non-default config file.
|
|
35
|
+
* Returns a `KubectlContextResolution` — callers branch on `error` vs `context`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveKubectlContext(configPath?: string): KubectlContextResolution;
|
|
38
|
+
//# sourceMappingURL=kubectl-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kubectl-context.d.ts","sourceRoot":"","sources":["../../src/lib/kubectl-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AASD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,wBAAwB,CAcnF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kubectl-context.ts — shared kubectl-context resolver.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the D1 / SEC-NEW-003 context-resolution
|
|
5
|
+
* policy. Extracted so `upgrade-kubernetes.ts`, `auth-refresh-kubernetes.ts`,
|
|
6
|
+
* `services.ts`, and any future kubernetes-substrate consumer can call the
|
|
7
|
+
* same helper instead of duplicating it.
|
|
8
|
+
*
|
|
9
|
+
* Policy (matches the pre-existing auth-refresh-kubernetes.ts and services.ts
|
|
10
|
+
* behaviour — see also docs/architecture/peripheral-services-on-k3s.md):
|
|
11
|
+
*
|
|
12
|
+
* 1. `host.kubectl_context_pinned` in `~/.olam/config.json` (preferred,
|
|
13
|
+
* persistent — the doc-recommended way).
|
|
14
|
+
* 2. `OLAM_K8S_CONTEXT_ACK` env var (deprecated fallback; emits a
|
|
15
|
+
* deprecation warning to nudge operators toward (1)).
|
|
16
|
+
* 3. Both absent → error result with actionable remediation.
|
|
17
|
+
*
|
|
18
|
+
* No `fs` reads in this module beyond what `readConfig` does; no kubectl
|
|
19
|
+
* invocations. Pure resolution. Safe to call from any layer.
|
|
20
|
+
*/
|
|
21
|
+
import { readConfig } from './config.js';
|
|
22
|
+
const DEPRECATION_WARNING = 'OLAM_K8S_CONTEXT_ACK is deprecated; set host.kubectl_context_pinned in ~/.olam/config.json';
|
|
23
|
+
const NO_CONTEXT_ERROR = 'kubectl_context_pinned is not set in ~/.olam/config.json and OLAM_K8S_CONTEXT_ACK is not set.\n' +
|
|
24
|
+
' Set host.kubectl_context_pinned in ~/.olam/config.json to your kubectl context name.';
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the operator's kubectl context name. See module docstring for policy.
|
|
27
|
+
*
|
|
28
|
+
* `configPath` lets callers (and tests) point at a non-default config file.
|
|
29
|
+
* Returns a `KubectlContextResolution` — callers branch on `error` vs `context`.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveKubectlContext(configPath) {
|
|
32
|
+
const cfg = readConfig({ configPath });
|
|
33
|
+
const raw = cfg.host['kubectl_context_pinned'];
|
|
34
|
+
if (typeof raw === 'string' && raw.length > 0) {
|
|
35
|
+
return { context: raw };
|
|
36
|
+
}
|
|
37
|
+
const ack = process.env['OLAM_K8S_CONTEXT_ACK'];
|
|
38
|
+
if (typeof ack === 'string' && ack.length > 0) {
|
|
39
|
+
return { context: ack, deprecationWarning: DEPRECATION_WARNING };
|
|
40
|
+
}
|
|
41
|
+
return { error: NO_CONTEXT_ERROR };
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=kubectl-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kubectl-context.js","sourceRoot":"","sources":["../../src/lib/kubectl-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAazC,MAAM,mBAAmB,GACvB,4FAA4F,CAAC;AAE/F,MAAM,gBAAgB,GACpB,iGAAiG;IACjG,wFAAwF,CAAC;AAE3F;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAmB;IACvD,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IACvC,MAAM,GAAG,GAAI,GAAG,CAAC,IAAgC,CAAC,wBAAwB,CAAC,CAAC;IAE5E,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAC1B,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAChD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,CAAC;IACnE,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -44,6 +44,7 @@ import { kubectlWrap } from './kubectl-wrap.js';
|
|
|
44
44
|
import { spawnPortForward, spawnAllPeripheralPortForwards, probePortForwardLiveness, type PortForwardDeps, type PeripheralPortForwardDeps } from './port-forward.js';
|
|
45
45
|
import { emitUpgradeComplete, type EmitOpts } from './instrumentation.js';
|
|
46
46
|
import { runManifestRefresh, seedManifestsFromBundle, type SeedManifestsDeps } from './manifest-refresh.js';
|
|
47
|
+
import { ensureK8sBootstrap, type BootstrapDeps as K8sBootstrapDeps } from './k8s-bootstrap.js';
|
|
47
48
|
export declare const OLAM_K8S_MANIFESTS_DIR: string;
|
|
48
49
|
export declare const K8S_NAMESPACE = "olam";
|
|
49
50
|
export declare const HOST_CP_SECRET_NAME = "olam-host-cp-secret";
|
|
@@ -99,10 +100,32 @@ export interface UpgradeKubernetesDeps {
|
|
|
99
100
|
* Tests inject a mock to avoid real kubectl invocations.
|
|
100
101
|
*/
|
|
101
102
|
readonly checkDockerSocketImpl?: (context: string) => Promise<boolean>;
|
|
103
|
+
/**
|
|
104
|
+
* B3: override config path passed to resolveKubectlContext (tests use a
|
|
105
|
+
* tmpdir fixture). Defaults to the real ~/.olam/config.json.
|
|
106
|
+
*/
|
|
107
|
+
readonly configPath?: string;
|
|
108
|
+
/**
|
|
109
|
+
* B4: override the k8s-bootstrap step (tests inject a mock so kubectl
|
|
110
|
+
* isn't called). When omitted defaults to the real `ensureK8sBootstrap`.
|
|
111
|
+
*/
|
|
112
|
+
readonly k8sBootstrapImpl?: typeof ensureK8sBootstrap;
|
|
113
|
+
/** B4: pass-through deps for `ensureK8sBootstrap`. */
|
|
114
|
+
readonly k8sBootstrapDeps?: K8sBootstrapDeps;
|
|
102
115
|
}
|
|
103
116
|
export interface UpgradeKubernetesOpts {
|
|
104
117
|
readonly forceRefreshManifests?: boolean;
|
|
105
118
|
readonly acceptSecurityRegression?: boolean;
|
|
119
|
+
/** B4/B5: regenerate all rendered Secret values (overwrites k8s-secrets-state.json). */
|
|
120
|
+
readonly rotateSecrets?: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* B4: run the namespace + RBAC + secret bootstrap step BEFORE step 1.
|
|
123
|
+
* Default is `false` for direct lib callers (preserves existing test
|
|
124
|
+
* ordering invariants); the CLI command in `upgrade.ts` passes `true` so
|
|
125
|
+
* npm-only operators get the bootstrap automatically. Operators who
|
|
126
|
+
* manage secrets out-of-band (GitOps) can disable via `--skip-k8s-bootstrap`.
|
|
127
|
+
*/
|
|
128
|
+
readonly runK8sBootstrap?: boolean;
|
|
106
129
|
}
|
|
107
130
|
export interface UpgradeKubernetesResult {
|
|
108
131
|
readonly exitCode: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upgrade-kubernetes.d.ts","sourceRoot":"","sources":["../../src/lib/upgrade-kubernetes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAQ9B,OAAO,EAAE,WAAW,EAAwB,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,8BAA8B,EAAE,wBAAwB,EAAE,KAAK,eAAe,EAAE,KAAK,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AACrK,OAAO,EAAE,mBAAmB,EAAE,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAA4B,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAItI,eAAO,MAAM,sBAAsB,QAA2C,CAAC;AAC/E,eAAO,MAAM,aAAa,SAAS,CAAC;AACpC,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AACzD,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AACtD,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAC1D,eAAO,MAAM,kBAAkB,kCAAkC,CAAC;AAElE,oDAAoD;AACpD,eAAO,MAAM,mBAAmB,QAAqD,CAAC;AAwItF,MAAM,WAAW,qBAAqB;IACpC,uCAAuC;IACvC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,WAAW,CAAC;IAC9C,2CAA2C;IAC3C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,gBAAgB,CAAC;IACxD,yDAAyD;IACzD,QAAQ,CAAC,kCAAkC,CAAC,EAAE,OAAO,8BAA8B,CAAC;IACpF,mDAAmD;IACnD,QAAQ,CAAC,4BAA4B,CAAC,EAAE,OAAO,wBAAwB,CAAC;IACxE,wDAAwD;IACxD,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5E,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,mBAAmB,CAAC;IAC/C,2CAA2C;IAC3C,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,kBAAkB,CAAC;IACzD,2CAA2C;IAC3C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,uBAAuB,CAAC;IAC5D,sFAAsF;IACtF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAC/C,6CAA6C;IAC7C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,yEAAyE;IACzE,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C,iGAAiG;IACjG,QAAQ,CAAC,yBAAyB,CAAC,EAAE,yBAAyB,CAAC;IAC/D,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B,iCAAiC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IACxC,iCAAiC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IACxC,oEAAoE;IACpE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC,YAAY,CAAC;IACnD,yDAAyD;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAChE;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"upgrade-kubernetes.d.ts","sourceRoot":"","sources":["../../src/lib/upgrade-kubernetes.ts"],"names":[],"mappings":"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"}
|