@jr2/cli 0.4.1 → 0.5.1
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/README.md +3 -2
- package/package.json +3 -3
- package/src/agents-md.ts +149 -0
- package/src/assembly.ts +1 -1
- package/src/build.ts +24 -7
- package/src/cli.ts +20 -45
- package/src/client.ts +19 -1
- package/src/command-table.ts +641 -0
- package/src/commands/check.ts +37 -0
- package/src/commands/down.ts +7 -17
- package/src/commands/gc.ts +2 -11
- package/src/commands/init.ts +73 -17
- package/src/commands/kit.ts +6 -11
- package/src/commands/logs.ts +4 -9
- package/src/commands/run.ts +14 -15
- package/src/commands/runs.ts +13 -28
- package/src/commands/send.ts +4 -18
- package/src/commands/status.ts +47 -11
- package/src/commands/up.ts +841 -374
- package/src/commands/version.ts +9 -13
- package/src/deploy.ts +223 -23
- package/src/index.ts +26 -0
- package/src/instance-check.ts +309 -0
- package/src/instance.ts +3 -9
- package/src/kit-version.ts +27 -17
- package/src/kube.ts +334 -67
- package/src/nodes.ts +7 -1
- package/src/output.ts +1 -1
- package/src/repo-sweep.ts +1 -1
- package/src/sweep.ts +6 -5
package/src/commands/version.ts
CHANGED
|
@@ -13,17 +13,17 @@
|
|
|
13
13
|
// A REPORT verb, not a result verb: the human table goes to stdout, `--json` swaps in the one object.
|
|
14
14
|
|
|
15
15
|
import { basename } from "node:path";
|
|
16
|
-
import {
|
|
17
|
-
import { IMAGES_CONFIGMAP, IMAGES_KEY, INSTANCE_SECRET, loadConfig, type ImageRefs } from "@jr2/orchestrator";
|
|
16
|
+
import { IMAGES_CONFIGMAP, IMAGES_KEY, INSTANCE_SECRET, loadConfig, type ImageRefs } from "@jr2/orchestrator/internal";
|
|
18
17
|
import { detectKitCheckout, KIT_IMAGE_HOME } from "../build.ts";
|
|
19
18
|
import type { InstanceIdentity } from "../client.ts";
|
|
20
19
|
import { compareVersions, LABEL_VERSION, OPERATOR_DEPLOYMENT, OPERATOR_NAMESPACE } from "../deploy.ts";
|
|
21
20
|
import { handedOffFrom } from "../handoff.ts";
|
|
22
|
-
import {
|
|
21
|
+
import { targetOptions, type TargetOptions } from "../instance.ts";
|
|
23
22
|
import { checkKitVersion, CLI_ROOT, CLI_VERSION } from "../kit-version.ts";
|
|
24
23
|
import { kubectlAdmin, kubectlKube, ORCHESTRATOR_PORT, ORCHESTRATOR_SERVICE, type KubeObject } from "../kube.ts";
|
|
25
24
|
import { activity, result, type Io } from "../output.ts";
|
|
26
25
|
import { findRoot } from "../root.ts";
|
|
26
|
+
import { parseCommand } from "../command-table.ts";
|
|
27
27
|
|
|
28
28
|
/** A package as the report names it: the number and the real path, so the path says WHICH copy. */
|
|
29
29
|
export type Copy = { version: string; path: string };
|
|
@@ -79,12 +79,7 @@ export type VersionReport = {
|
|
|
79
79
|
type Orchestrator = { version?: string; hash?: string; image?: string } | { error: string };
|
|
80
80
|
|
|
81
81
|
export async function version(args: string[], io: Io): Promise<number> {
|
|
82
|
-
const { values } =
|
|
83
|
-
args,
|
|
84
|
-
allowPositionals: true,
|
|
85
|
-
strict: false,
|
|
86
|
-
options: { ...TARGET_ARGS, local: { type: "boolean" }, json: { type: "boolean" } },
|
|
87
|
-
});
|
|
82
|
+
const { values } = parseCommand("version", args);
|
|
88
83
|
const opts = targetOptions(values);
|
|
89
84
|
const report = await versionReport(io, opts, { local: values.local === true });
|
|
90
85
|
if (values.json === true) result(io, report);
|
|
@@ -258,7 +253,7 @@ const copy = (c: Copy): string => `${c.version.padEnd(8)} ${c.path}`;
|
|
|
258
253
|
export function render(r: VersionReport): string {
|
|
259
254
|
const rows: Row[] = [["cli", copy(r.cli)]];
|
|
260
255
|
if (r.global) rows.push(["global", copy(r.global)]);
|
|
261
|
-
if (r.kit) rows.push(["kit", renderKit(r.kit)]);
|
|
256
|
+
if (r.kit) rows.push(["kit", renderKit(r.kit, r.cli)]);
|
|
262
257
|
if (r.instance) {
|
|
263
258
|
const i = r.instance;
|
|
264
259
|
const mode = i.mode === "checkout" ? `kit checkout at ${i.kitCheckout}` : `installed kit → ${i.kitRegistry}`;
|
|
@@ -273,14 +268,15 @@ export function render(r: VersionReport): string {
|
|
|
273
268
|
return rows.map(([label, value]) => (label ? `${`${label}:`.padEnd(width)}${value}` : "")).join("\n") + "\n";
|
|
274
269
|
}
|
|
275
270
|
|
|
276
|
-
function renderKit(k: NonNullable<VersionReport["kit"]
|
|
271
|
+
function renderKit(k: NonNullable<VersionReport["kit"]>, cli: Copy): string {
|
|
277
272
|
const pinned = k.pinned !== undefined ? `; package.json pins ${k.pinned} — reinstall` : "";
|
|
278
273
|
if (k.check === "unresolved") return `not installed${pinned}`;
|
|
279
274
|
const head = copy({ version: k.version!, path: k.path! });
|
|
280
275
|
if (k.check === "ok") return `${head} ok${pinned}`;
|
|
276
|
+
// The CLI's own number is named: one copy at another version is a mismatch too (ADR-0056).
|
|
281
277
|
const against = k.against
|
|
282
|
-
? `this jr2 runs against ${k.against.version} (${k.against.path})`
|
|
283
|
-
:
|
|
278
|
+
? `this jr2 (${cli.version}) runs against ${k.against.version} (${k.against.path})`
|
|
279
|
+
: `this jr2 (${cli.version}) has no @jr2/orchestrator beside it`;
|
|
284
280
|
return `${head} MISMATCH — ${against}${pinned}`;
|
|
285
281
|
}
|
|
286
282
|
|
package/src/deploy.ts
CHANGED
|
@@ -62,7 +62,7 @@ import {
|
|
|
62
62
|
type HeldManifest,
|
|
63
63
|
type PriorityClasses,
|
|
64
64
|
type SandboxPlacement,
|
|
65
|
-
} from "@jr2/orchestrator";
|
|
65
|
+
} from "@jr2/orchestrator/internal";
|
|
66
66
|
import type { Pem } from "./held-pki.ts";
|
|
67
67
|
|
|
68
68
|
export {
|
|
@@ -163,6 +163,8 @@ export const KIT_POD_SIZES = {
|
|
|
163
163
|
repoCache: { requests: { cpu: "50m", memory: "128Mi" }, limits: { memory: "1Gi" } },
|
|
164
164
|
/** The Instance Effector (ADR-0068): one http call at a time per Effect, its text body bounded. */
|
|
165
165
|
instanceEffector: { requests: { cpu: "50m", memory: "128Mi" }, limits: { memory: "128Mi" } },
|
|
166
|
+
/** The provider preflight's check container (ADR-0019): one Node.js process, pi-ai, one call at a time. */
|
|
167
|
+
checkContainer: { requests: { cpu: "100m", memory: "512Mi" }, limits: { memory: "512Mi" } },
|
|
166
168
|
} as const;
|
|
167
169
|
|
|
168
170
|
/** A fresh copy, so no manifest shares an object with another (or with the constant). */
|
|
@@ -366,28 +368,7 @@ export function instanceObjects(opts: {
|
|
|
366
368
|
kind: "ConfigMap",
|
|
367
369
|
metadata: meta(HARNESS_CONFIGMAP),
|
|
368
370
|
data: {
|
|
369
|
-
[HARNESS_CONFIG_KEY]:
|
|
370
|
-
{
|
|
371
|
-
// apiKey is deliberately dropped: it is a held secret (ADR-0059) — the Custodian holds
|
|
372
|
-
// it, the Harness's env holds its Stand-in, and a ConfigMap is no place for either.
|
|
373
|
-
provider: opts.harness?.provider
|
|
374
|
-
? {
|
|
375
|
-
id: opts.harness.provider.id,
|
|
376
|
-
api: opts.harness.provider.api,
|
|
377
|
-
baseUrl: opts.harness.provider.baseUrl,
|
|
378
|
-
// Token limits are model properties, not credentials — they ride the ConfigMap
|
|
379
|
-
// so the Harness can register the provider with them.
|
|
380
|
-
contextWindow: opts.harness.provider.contextWindow,
|
|
381
|
-
maxTokens: opts.harness.provider.maxTokens,
|
|
382
|
-
models: opts.harness.provider.models,
|
|
383
|
-
}
|
|
384
|
-
: undefined,
|
|
385
|
-
// Where pi's catalog providers send their calls (ADR-0059): endpoints, not keys.
|
|
386
|
-
catalog: opts.harness?.catalog,
|
|
387
|
-
},
|
|
388
|
-
null,
|
|
389
|
-
2,
|
|
390
|
-
),
|
|
371
|
+
[HARNESS_CONFIG_KEY]: harnessConfigJson(opts.harness),
|
|
391
372
|
},
|
|
392
373
|
},
|
|
393
374
|
{
|
|
@@ -1062,6 +1043,225 @@ export function instanceHarnessObjects(opts: {
|
|
|
1062
1043
|
return JSON.stringify({ apiVersion: "v1", kind: "List", items });
|
|
1063
1044
|
}
|
|
1064
1045
|
|
|
1046
|
+
/** What the Instance can REACH (ADR-0018), as the `jr2-harness` ConfigMap carries it to every
|
|
1047
|
+
* Harness container: the custom provider without its key and the catalog gateways. The check pod
|
|
1048
|
+
* carries the same text in its own ConfigMap (ADR-0019). */
|
|
1049
|
+
export function harnessConfigJson(harness: HarnessConfig | undefined): string {
|
|
1050
|
+
return JSON.stringify(
|
|
1051
|
+
{
|
|
1052
|
+
// apiKey is deliberately dropped: it is a held secret (ADR-0059) — the Custodian holds
|
|
1053
|
+
// it, the Harness's env holds its Stand-in, and a ConfigMap is no place for either.
|
|
1054
|
+
provider: harness?.provider
|
|
1055
|
+
? {
|
|
1056
|
+
id: harness.provider.id,
|
|
1057
|
+
api: harness.provider.api,
|
|
1058
|
+
baseUrl: harness.provider.baseUrl,
|
|
1059
|
+
// Token limits are model properties, not credentials — they ride the ConfigMap
|
|
1060
|
+
// so the Harness can register the provider with them.
|
|
1061
|
+
contextWindow: harness.provider.contextWindow,
|
|
1062
|
+
maxTokens: harness.provider.maxTokens,
|
|
1063
|
+
models: harness.provider.models,
|
|
1064
|
+
}
|
|
1065
|
+
: undefined,
|
|
1066
|
+
// Where pi's catalog providers send their calls (ADR-0059): endpoints, not keys.
|
|
1067
|
+
catalog: harness?.catalog,
|
|
1068
|
+
},
|
|
1069
|
+
null,
|
|
1070
|
+
2,
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
/** The provider preflight's objects (ADR-0019): a check pod and its own copies of what it reads,
|
|
1075
|
+
* each named `jr2-provider-preflight-<run>-<n>` or that name and a suffix, unique to one `jr2 up`. */
|
|
1076
|
+
export const PROVIDER_PREFLIGHT = "jr2-provider-preflight";
|
|
1077
|
+
/** The label every one of them carries, its value the `jr2 up` run: how a later run finds the
|
|
1078
|
+
* leftovers of a run that did not end, and leaves another run's objects alone. */
|
|
1079
|
+
export const LABEL_PROVIDER_PREFLIGHT = "jr2.dev/provider-preflight";
|
|
1080
|
+
/** The check container in that pod, whose output `jr2 up` reads. An older `jr2 up` named it `probe`. */
|
|
1081
|
+
export const CHECK_CONTAINER = "check";
|
|
1082
|
+
|
|
1083
|
+
/** Every object of one check pod (`checkPodObjects`), for its deletion. */
|
|
1084
|
+
export function checkPodObjectNames(object: string): Array<{ kind: string; name: string }> {
|
|
1085
|
+
return [
|
|
1086
|
+
{ kind: "pod", name: object },
|
|
1087
|
+
{ kind: "configmap", name: object },
|
|
1088
|
+
{ kind: "configmap", name: `${object}-ca` },
|
|
1089
|
+
{ kind: "secret", name: object },
|
|
1090
|
+
{ kind: "secret", name: `${object}-tls` },
|
|
1091
|
+
{ kind: "secret", name: `${object}-env` },
|
|
1092
|
+
];
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
/**
|
|
1096
|
+
* One check pod of the provider preflight (ADR-0019, ADR-0059): a Harness pod with no Harness in
|
|
1097
|
+
* it, and its own copies of every object a Harness pod reads. So a check pod writes nothing that a
|
|
1098
|
+
* running pod of the Instance reads, and a check that fails leaves the Instance as it was.
|
|
1099
|
+
*
|
|
1100
|
+
* - `<object>` (ConfigMap): the Custodian's bootstrap and script, the program and the harness config
|
|
1101
|
+
* (`harnessConfigJson`).
|
|
1102
|
+
* - `<object>-ca` (ConfigMap): the trust bundles, as `jr2-ca` would carry them.
|
|
1103
|
+
* - `<object>` (Secret): the Custodian's token, a value the Orchestrator never signed (the check pod
|
|
1104
|
+
* reads no Menu), and the LITERAL values of the keys it holds, from the host. A `valueFrom` key
|
|
1105
|
+
* stays a reference to the user's Secret. The values are in this Secret for the check pod's life.
|
|
1106
|
+
* - `<object>-tls` (Secret): the leaves of the bound hosts. `<object>-env` (Secret): the literal
|
|
1107
|
+
* `harness.env` values, which `jr2-harness-env` would carry.
|
|
1108
|
+
*
|
|
1109
|
+
* The Custodian is composed by the function every Harness pod's is (`custodianComposition`). With
|
|
1110
|
+
* no binding, it holds nothing and the check pod's HTTPS goes direct, as in a Harness pod that holds no
|
|
1111
|
+
* secret. The check container runs the stock Harness image's `provider-preflight.ts` with the Harness
|
|
1112
|
+
* container's env, so the call is the one a Turn makes, and the key never enters that container,
|
|
1113
|
+
* its argv or its log. The argv is the model specifiers alone.
|
|
1114
|
+
*
|
|
1115
|
+
* The pod has the placement and the priority class of the Harness pods it stands for (ADR-0052,
|
|
1116
|
+
* ADR-0060). Its labels are its own and match no Harness pod's: the Instance Harness Service
|
|
1117
|
+
* selects by label, and would send Turns to it. The Custodian is a native sidecar with a startup
|
|
1118
|
+
* probe, so the check starts only once Envoy serves and the pod ends when the check does.
|
|
1119
|
+
*/
|
|
1120
|
+
export function checkPodObjects(opts: {
|
|
1121
|
+
name: string;
|
|
1122
|
+
namespace: string;
|
|
1123
|
+
/** This check pod's object name (`jr2-provider-preflight-<run>-<n>`) and its run, for the label. */
|
|
1124
|
+
object: string;
|
|
1125
|
+
run: string;
|
|
1126
|
+
/** The resolved stock Harness ref: the image a Turn's Harness runs, with pi-ai at the pin. */
|
|
1127
|
+
harnessImage: string;
|
|
1128
|
+
custodianImage: string;
|
|
1129
|
+
/** The bindings of the keys this check pod holds: each a part of a held pod's manifest. */
|
|
1130
|
+
held: HeldManifest;
|
|
1131
|
+
/** The literal values of those keys, by name, from the host. */
|
|
1132
|
+
values: Record<string, string>;
|
|
1133
|
+
/** The leaves of their bound hosts, by file stem. */
|
|
1134
|
+
leaves: Record<string, Pem>;
|
|
1135
|
+
/** The trust bundles (`ca.crt`, `extra.crt`, `bundle.crt`, `upstream.crt`), as `jr2-ca` has them. */
|
|
1136
|
+
trust: Record<string, string>;
|
|
1137
|
+
/** The Custodian's two files, rendered from `held`. */
|
|
1138
|
+
custodian: CustodianFiles;
|
|
1139
|
+
token: string;
|
|
1140
|
+
/** The literal `harness.env` values. */
|
|
1141
|
+
harnessEnvData: Record<string, string>;
|
|
1142
|
+
/** The `<provider>/<model>` specifiers to check, in order. */
|
|
1143
|
+
models: readonly string[];
|
|
1144
|
+
/** The node predicate of the Harness pods this check pod stands for. */
|
|
1145
|
+
placement?: SandboxPlacement;
|
|
1146
|
+
priorityClassName: string;
|
|
1147
|
+
harness?: HarnessConfig;
|
|
1148
|
+
caBundle?: boolean;
|
|
1149
|
+
/** The pod's whole budget: the kubelet ends it at this deadline, even when `jr2 up` is gone. */
|
|
1150
|
+
deadlineSeconds: number;
|
|
1151
|
+
}): string {
|
|
1152
|
+
const labels = {
|
|
1153
|
+
[LABEL_INSTANCE]: opts.name,
|
|
1154
|
+
"app.kubernetes.io/managed-by": "jr2",
|
|
1155
|
+
[LABEL_PROVIDER_PREFLIGHT]: opts.run,
|
|
1156
|
+
};
|
|
1157
|
+
const meta = (name: string) => ({ name, namespace: opts.namespace, labels });
|
|
1158
|
+
const o = opts.object;
|
|
1159
|
+
const custodian = custodianComposition(opts.held, {
|
|
1160
|
+
image: opts.custodianImage,
|
|
1161
|
+
pod: o,
|
|
1162
|
+
reads: { literals: o, tls: `${o}-tls`, trust: `${o}-ca`, program: o },
|
|
1163
|
+
config: o,
|
|
1164
|
+
token: { secret: o, key: "token" },
|
|
1165
|
+
caBundle: opts.caBundle === true,
|
|
1166
|
+
resources: sized(KIT_POD_SIZES.instanceCustodian),
|
|
1167
|
+
});
|
|
1168
|
+
const ready = custodian.custodianContainer.readinessProbe as { httpGet: unknown };
|
|
1169
|
+
const pod = {
|
|
1170
|
+
apiVersion: "v1",
|
|
1171
|
+
kind: "Pod",
|
|
1172
|
+
metadata: { ...meta(o), labels: { ...labels, app: PROVIDER_PREFLIGHT } },
|
|
1173
|
+
spec: {
|
|
1174
|
+
restartPolicy: "Never",
|
|
1175
|
+
activeDeadlineSeconds: opts.deadlineSeconds,
|
|
1176
|
+
automountServiceAccountToken: false,
|
|
1177
|
+
priorityClassName: opts.priorityClassName,
|
|
1178
|
+
...(opts.placement?.nodeSelector ? { nodeSelector: opts.placement.nodeSelector } : {}),
|
|
1179
|
+
...(opts.placement?.tolerations?.length ? { tolerations: opts.placement.tolerations } : {}),
|
|
1180
|
+
// The Instance Harness pod's baseline, and its `fsGroup` for the same reason: the
|
|
1181
|
+
// Custodian's values are group-readable, and Envoy runs as its own uid.
|
|
1182
|
+
securityContext: {
|
|
1183
|
+
runAsNonRoot: true,
|
|
1184
|
+
seccompProfile: { type: "RuntimeDefault" },
|
|
1185
|
+
fsGroup: INSTANCE_HARNESS_FS_GROUP,
|
|
1186
|
+
},
|
|
1187
|
+
initContainers: [
|
|
1188
|
+
{
|
|
1189
|
+
...custodian.custodianContainer,
|
|
1190
|
+
restartPolicy: "Always",
|
|
1191
|
+
startupProbe: { httpGet: ready.httpGet, periodSeconds: 1, failureThreshold: 60 },
|
|
1192
|
+
},
|
|
1193
|
+
],
|
|
1194
|
+
containers: [
|
|
1195
|
+
{
|
|
1196
|
+
name: CHECK_CONTAINER,
|
|
1197
|
+
image: opts.harnessImage,
|
|
1198
|
+
imagePullPolicy: "IfNotPresent",
|
|
1199
|
+
// Under tini, as the Harness runs (ADR-0061): PID 1 reaps, and forwards a stop.
|
|
1200
|
+
command: [
|
|
1201
|
+
"/opt/jr2/bin/tini",
|
|
1202
|
+
"--",
|
|
1203
|
+
"/opt/jr2/bin/node",
|
|
1204
|
+
"/opt/jr2/src/provider-preflight.ts",
|
|
1205
|
+
...opts.models,
|
|
1206
|
+
],
|
|
1207
|
+
// The Harness container's env, in its order (`instanceHarnessObjects`): no credential.
|
|
1208
|
+
env: [
|
|
1209
|
+
{ name: "JR2_HARNESS_JSON", valueFrom: { configMapKeyRef: { name: o, key: HARNESS_CONFIG_KEY } } },
|
|
1210
|
+
...(opts.harness?.env ?? []).filter((v) => v.valueFrom !== undefined),
|
|
1211
|
+
...custodian.harnessEnv,
|
|
1212
|
+
],
|
|
1213
|
+
envFrom: [{ secretRef: { name: `${o}-env` } }, ...(opts.harness?.envFrom ?? [])],
|
|
1214
|
+
volumeMounts: custodian.harnessMounts,
|
|
1215
|
+
resources: sized(KIT_POD_SIZES.checkContainer),
|
|
1216
|
+
securityContext: {
|
|
1217
|
+
runAsNonRoot: true,
|
|
1218
|
+
allowPrivilegeEscalation: false,
|
|
1219
|
+
capabilities: { drop: ["ALL"] },
|
|
1220
|
+
seccompProfile: { type: "RuntimeDefault" },
|
|
1221
|
+
},
|
|
1222
|
+
},
|
|
1223
|
+
],
|
|
1224
|
+
volumes: custodian.volumes,
|
|
1225
|
+
},
|
|
1226
|
+
};
|
|
1227
|
+
const secret = (name: string, stringData: Record<string, string>): KubeManifest => ({
|
|
1228
|
+
apiVersion: "v1",
|
|
1229
|
+
kind: "Secret",
|
|
1230
|
+
metadata: meta(name),
|
|
1231
|
+
type: "Opaque",
|
|
1232
|
+
stringData,
|
|
1233
|
+
});
|
|
1234
|
+
const leaves: Record<string, string> = {};
|
|
1235
|
+
for (const stem of new Set(opts.held.secrets.flatMap((s) => s.hosts.map((h) => h.leaf)))) {
|
|
1236
|
+
const pem = opts.leaves[stem];
|
|
1237
|
+
if (!pem) throw new Error(`no leaf for a bound host of the provider preflight (${stem}) — a jr2 defect`);
|
|
1238
|
+
leaves[`${stem}.crt`] = pem.cert;
|
|
1239
|
+
leaves[`${stem}.key`] = pem.key;
|
|
1240
|
+
}
|
|
1241
|
+
const literals = Object.fromEntries(
|
|
1242
|
+
opts.held.secrets.filter((s) => s.source.kind === "literal").map((s) => [s.name, opts.values[s.name] ?? ""]),
|
|
1243
|
+
);
|
|
1244
|
+
const items: KubeManifest[] = [
|
|
1245
|
+
{
|
|
1246
|
+
apiVersion: "v1",
|
|
1247
|
+
kind: "ConfigMap",
|
|
1248
|
+
metadata: meta(o),
|
|
1249
|
+
data: {
|
|
1250
|
+
[CUSTODIAN_BOOTSTRAP_KEY]: opts.custodian.bootstrap,
|
|
1251
|
+
[CUSTODIAN_SCRIPT_KEY]: opts.custodian.script,
|
|
1252
|
+
[CUSTODIAN_PROGRAM_KEY]: CUSTODIAN_PROGRAM,
|
|
1253
|
+
[HARNESS_CONFIG_KEY]: harnessConfigJson(opts.harness),
|
|
1254
|
+
},
|
|
1255
|
+
},
|
|
1256
|
+
{ apiVersion: "v1", kind: "ConfigMap", metadata: meta(`${o}-ca`), data: opts.trust },
|
|
1257
|
+
secret(o, { token: opts.token, ...literals }),
|
|
1258
|
+
secret(`${o}-tls`, leaves),
|
|
1259
|
+
secret(`${o}-env`, opts.harnessEnvData),
|
|
1260
|
+
pod,
|
|
1261
|
+
];
|
|
1262
|
+
return JSON.stringify({ apiVersion: "v1", kind: "List", items });
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1065
1265
|
/** The Orchestrator's pod template digest of the Instance Secret: it rolls the pod when a value
|
|
1066
1266
|
* the process reads through `envFrom` changes (ADR-0069). */
|
|
1067
1267
|
export const ANNOTATION_SECRET_DIGEST = "jr2.dev/secret-digest";
|
package/src/index.ts
CHANGED
|
@@ -14,3 +14,29 @@ export type { KubePort } from "./kube.ts";
|
|
|
14
14
|
// test can issue its own fixtures the same way (the @kind tier's HTTPS model provider).
|
|
15
15
|
export { issueCa, issueLeaf } from "./held-pki.ts";
|
|
16
16
|
export type { Pem } from "./held-pki.ts";
|
|
17
|
+
// The command table (ADR-0072): every verb as data, and the renderers `--help` prints with — what the
|
|
18
|
+
// docs' CLI Reference is generated from, so the help and the site cannot disagree.
|
|
19
|
+
export {
|
|
20
|
+
COMMANDS,
|
|
21
|
+
GLOBAL,
|
|
22
|
+
GLOBAL_OPTIONS,
|
|
23
|
+
HELP_FLAG,
|
|
24
|
+
SECTIONS,
|
|
25
|
+
EXIT_CODES,
|
|
26
|
+
nameOf,
|
|
27
|
+
synopsis,
|
|
28
|
+
renderHelp,
|
|
29
|
+
renderCommand,
|
|
30
|
+
} from "./command-table.ts";
|
|
31
|
+
export type {
|
|
32
|
+
Command,
|
|
33
|
+
CommandName,
|
|
34
|
+
Flag,
|
|
35
|
+
Arg,
|
|
36
|
+
EnvVar,
|
|
37
|
+
Form,
|
|
38
|
+
Output,
|
|
39
|
+
OutputKind,
|
|
40
|
+
GlobalOption,
|
|
41
|
+
Section,
|
|
42
|
+
} from "./command-table.ts";
|