@kici-dev/orchestrator 0.13.0 → 0.14.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/agent/dispatcher.d.ts +17 -0
- package/dist/cancel/peer-job-cancel.d.ts +12 -0
- package/dist/cli/api-client.d.ts +73 -0
- package/dist/cli/commands/cluster-settings.d.ts +31 -1
- package/dist/cli/commands/peer.d.ts +27 -1
- package/dist/cli/commands/scaler.d.ts +40 -4
- package/dist/cli.js +2210 -933
- package/dist/cluster/cluster-settings-reader.d.ts +8 -2
- package/dist/cluster/coordinator.d.ts +34 -8
- package/dist/cluster/peer-client.d.ts +37 -4
- package/dist/cluster/peer-forget.d.ts +138 -0
- package/dist/cluster/peer-handler.d.ts +18 -1
- package/dist/cluster/scaler-orphans-peer.d.ts +40 -0
- package/dist/cluster/settings-propagation.d.ts +85 -0
- package/dist/cluster/worker-cluster-settings.d.ts +29 -0
- package/dist/config.d.ts +9 -0
- package/dist/db/migrations/154_cluster_settings_firecracker_api_socket_wait.d.ts +4 -0
- package/dist/db/migrations/155_org_settings_reroute_spawn_retry.d.ts +17 -0
- package/dist/db/migrations/156_kici_events_match_outcome.d.ts +17 -0
- package/dist/db/types.d.ts +16 -0
- package/dist/events/event-router.d.ts +7 -1
- package/dist/events/event-store.d.ts +20 -3
- package/dist/events/types.d.ts +45 -0
- package/dist/helpers/windows-batch.d.ts +59 -0
- package/dist/index.js +60 -0
- package/dist/metrics/prometheus.d.ts +2 -0
- package/dist/orchestrator-core.d.ts +7 -0
- package/dist/registration/registration-store.d.ts +10 -0
- package/dist/routes/admin-cluster-settings.d.ts +13 -1
- package/dist/routes/admin-event-inspect.d.ts +36 -0
- package/dist/routes/admin-peer-forget.d.ts +43 -0
- package/dist/routes/admin-scaler-orphans.d.ts +64 -0
- package/dist/routes/admin.d.ts +23 -0
- package/dist/scaler/backend-factory.d.ts +6 -1
- package/dist/scaler/bare-metal-backend.d.ts +17 -15
- package/dist/scaler/bare-metal-launch.d.ts +90 -0
- package/dist/scaler/firecracker-backend.d.ts +181 -7
- package/dist/scaler/live-vms.d.ts +57 -0
- package/dist/scaler/manager.d.ts +112 -3
- package/dist/scaler/orphan-requests.d.ts +23 -0
- package/dist/scaler/overlay-template.d.ts +38 -0
- package/dist/scaler/scaler-state-store.d.ts +7 -0
- package/dist/scaler/spawn-errors.d.ts +17 -0
- package/dist/scaler/startup-orphan-sweep.d.ts +15 -0
- package/dist/scaler/types.d.ts +21 -2
- package/dist/scaler/vm-job-bindings.d.ts +17 -0
- package/dist/secrets/rbac.d.ts +7 -1
- package/dist/server.js +5498 -2193
- package/dist/standalone.js +10754 -7451
- package/dist/worker/in-memory-execution-tracker.d.ts +5 -0
- package/dist/worker/in-memory-job-queue.d.ts +21 -1
- package/dist/worker/queued-reroute-release.d.ts +39 -0
- package/dist/worker/reroute-spawn-control.d.ts +58 -0
- package/dist/worker/spawn-retry-budget.d.ts +87 -0
- package/dist/worker-core.d.ts +11 -2
- package/installer-image-digests.json +3 -3
- package/package.json +4 -4
- package/sbom.spdx.json +53 -53
|
@@ -300,6 +300,23 @@ export declare class Dispatcher {
|
|
|
300
300
|
* @returns the number of jobs that entered `spawning`.
|
|
301
301
|
*/
|
|
302
302
|
retryPendingScaleRequests(maxJobs?: number, trigger?: ScalerRedispatchTrigger): Promise<number>;
|
|
303
|
+
/**
|
|
304
|
+
* Re-offer ONE pending job to the scaler: a worker's spawn-retry backoff ending.
|
|
305
|
+
*
|
|
306
|
+
* Outside the batch's single-flight on purpose: a wake-up that lands during a
|
|
307
|
+
* batch pass would otherwise be dropped, and a worker runs no pending-scale
|
|
308
|
+
* sweep to pick it up. The worker's per-job attempt gate is what keeps this
|
|
309
|
+
* from starting a second spawn for the same job.
|
|
310
|
+
*
|
|
311
|
+
* @returns true when a spawn started.
|
|
312
|
+
*/
|
|
313
|
+
redrivePendingJob(jobId: string): Promise<boolean>;
|
|
314
|
+
/**
|
|
315
|
+
* Offer one pending job to the scaler through the same `onNoMatchingAgent` →
|
|
316
|
+
* `requestScale` path a dispatch uses, or settle it when its sealed secrets
|
|
317
|
+
* cannot be opened here.
|
|
318
|
+
*/
|
|
319
|
+
private offerPendingToScaler;
|
|
303
320
|
/**
|
|
304
321
|
* Release the slot claimed for a direct dispatch the queue refused because
|
|
305
322
|
* the job's run has stopped. Nothing is sent to the agent. The queue already
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
* only to `dispatch_queue.agent_id`. So the agent is resolved from the
|
|
9
9
|
* dispatcher first and from the dispatch record second, and a cancel that
|
|
10
10
|
* cannot be delivered is logged with the reason.
|
|
11
|
+
*
|
|
12
|
+
* On a worker the receiver also removes the jobs of the cancel that are still
|
|
13
|
+
* queued (waiting for an agent spawn), and stop-marks the dispatched ones so a
|
|
14
|
+
* requeue cannot bring them back. A removed job is reported `dequeued`.
|
|
11
15
|
*/
|
|
12
16
|
import type { Kysely } from 'kysely';
|
|
13
17
|
import { z } from 'zod';
|
|
@@ -18,6 +22,7 @@ import type { Dispatcher } from '../agent/dispatcher.js';
|
|
|
18
22
|
export declare const PeerCancelOutcome: z.ZodEnum<{
|
|
19
23
|
"agent-not-connected": "agent-not-connected";
|
|
20
24
|
delivered: "delivered";
|
|
25
|
+
dequeued: "dequeued";
|
|
21
26
|
"lookup-failed": "lookup-failed";
|
|
22
27
|
"not-tracked": "not-tracked";
|
|
23
28
|
}>;
|
|
@@ -35,6 +40,13 @@ export interface PeerJobCancelDeps {
|
|
|
35
40
|
registry: Pick<AgentRegistry, 'get'>;
|
|
36
41
|
/** The durable dispatch record. Absent on a worker, which has no database. */
|
|
37
42
|
lookupDispatched?: (runId: string, jobId: string | undefined) => Promise<DispatchedAgent[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Remove this process's queued (not yet dispatched) jobs of the cancel, and
|
|
45
|
+
* stop-mark its dispatched ones so a requeue cannot bring them back. Wired only
|
|
46
|
+
* on a worker, whose queue lives in memory; a coordinator's queue rows are
|
|
47
|
+
* settled by its own run-cancel path.
|
|
48
|
+
*/
|
|
49
|
+
releaseQueued?: (runId: string, jobId: string | undefined) => Promise<string[]>;
|
|
38
50
|
logger: {
|
|
39
51
|
info(message: string, meta?: object): unknown;
|
|
40
52
|
warn(message: string, meta?: object): unknown;
|
package/dist/cli/api-client.d.ts
CHANGED
|
@@ -5,6 +5,42 @@
|
|
|
5
5
|
* All methods are thin wrappers around fetch() that handle JSON serialization,
|
|
6
6
|
* error formatting, and URL construction.
|
|
7
7
|
*/
|
|
8
|
+
import type { PeerForgetOutcome, ScalerLiveVm, ScalerVmStopResult } from '@kici-dev/engine';
|
|
9
|
+
/** `POST /api/v1/admin/peers/forget`: one result per coordinator, this one first. */
|
|
10
|
+
export interface PeerForgetResponseBody {
|
|
11
|
+
instanceId: string;
|
|
12
|
+
results: Array<{
|
|
13
|
+
coordinator: string;
|
|
14
|
+
outcome: PeerForgetOutcome;
|
|
15
|
+
detail: string;
|
|
16
|
+
}>;
|
|
17
|
+
/** Set when the coordinator kept the peer only for want of the backstop acknowledgement. */
|
|
18
|
+
acknowledgementRequired?: boolean;
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
21
|
+
/** The node a scaler orphans request answered for. */
|
|
22
|
+
export interface ScalerOrphansNode {
|
|
23
|
+
instanceId: string;
|
|
24
|
+
/** The node's cluster role; `unknown` for a peer the coordinator has no role for. */
|
|
25
|
+
role: 'coordinator' | 'worker' | 'unknown';
|
|
26
|
+
/** The node's Firecracker scaler names; empty when it runs none. */
|
|
27
|
+
firecrackerScalers: string[];
|
|
28
|
+
/**
|
|
29
|
+
* Coordinator peers the cluster expects but the answering coordinator has no
|
|
30
|
+
* live link to. While any is listed, no VM is `orphaned`.
|
|
31
|
+
*/
|
|
32
|
+
disconnectedCoordinators?: string[];
|
|
33
|
+
}
|
|
34
|
+
/** `GET /api/v1/admin/scaler/orphans`: every live Firecracker VM on the node. */
|
|
35
|
+
export interface ScalerOrphansListResponse {
|
|
36
|
+
node: ScalerOrphansNode;
|
|
37
|
+
vms: ScalerLiveVm[];
|
|
38
|
+
}
|
|
39
|
+
/** `POST /api/v1/admin/scaler/orphans/stop`: one result per requested VM. */
|
|
40
|
+
export interface ScalerOrphansStopResponse {
|
|
41
|
+
node: ScalerOrphansNode;
|
|
42
|
+
results: ScalerVmStopResult[];
|
|
43
|
+
}
|
|
8
44
|
/** A node in the fleet topology returned by GET /admin/fleet-topology. */
|
|
9
45
|
export interface FleetTopologyNodeResponse {
|
|
10
46
|
kind: 'orchestrator' | 'agent';
|
|
@@ -384,6 +420,29 @@ export declare class AdminApiClient {
|
|
|
384
420
|
draining: boolean;
|
|
385
421
|
jobsRunning: number;
|
|
386
422
|
}>;
|
|
423
|
+
/** Forget a departed peer on this coordinator and every connected sibling. */
|
|
424
|
+
/**
|
|
425
|
+
* Forget a departed peer on this coordinator and every connected sibling. A
|
|
426
|
+
* refusal that only needs the backstop acknowledgement comes back as a body
|
|
427
|
+
* with `acknowledgementRequired`, so the caller can ask and retry; every
|
|
428
|
+
* other failure throws.
|
|
429
|
+
*/
|
|
430
|
+
forgetPeer(body: {
|
|
431
|
+
instanceId: string;
|
|
432
|
+
timeoutMs?: number;
|
|
433
|
+
acknowledgeBackstop?: boolean;
|
|
434
|
+
}): Promise<PeerForgetResponseBody>;
|
|
435
|
+
/** List the live Firecracker VMs on this coordinator, or on the `target` peer. */
|
|
436
|
+
listScalerOrphans(opts?: {
|
|
437
|
+
target?: string;
|
|
438
|
+
timeoutMs?: number;
|
|
439
|
+
}): Promise<ScalerOrphansListResponse>;
|
|
440
|
+
/** Stop the named VMs on this coordinator, or on the `target` peer. */
|
|
441
|
+
stopScalerOrphans(body: {
|
|
442
|
+
target?: string;
|
|
443
|
+
vmIds: string[];
|
|
444
|
+
timeoutMs?: number;
|
|
445
|
+
}): Promise<ScalerOrphansStopResponse>;
|
|
387
446
|
createApiKey(opts: {
|
|
388
447
|
label?: string;
|
|
389
448
|
routingKeys?: string[];
|
|
@@ -547,6 +606,20 @@ export declare class AdminApiClient {
|
|
|
547
606
|
includePayload?: boolean;
|
|
548
607
|
routingKey?: string;
|
|
549
608
|
}): Promise<Record<string, unknown>>;
|
|
609
|
+
/** List internal events, newest first (`GET /api/v1/admin/events`). */
|
|
610
|
+
listEvents(opts?: {
|
|
611
|
+
name?: string;
|
|
612
|
+
outcome?: string;
|
|
613
|
+
since?: string;
|
|
614
|
+
before?: string;
|
|
615
|
+
limit?: number;
|
|
616
|
+
}): Promise<{
|
|
617
|
+
events: Array<Record<string, unknown>>;
|
|
618
|
+
limit: number;
|
|
619
|
+
nextCursor: string | null;
|
|
620
|
+
}>;
|
|
621
|
+
/** One internal event with its redacted payload and dispatched runs. */
|
|
622
|
+
getEvent(id: string): Promise<Record<string, unknown>>;
|
|
550
623
|
listAccessLog(opts?: {
|
|
551
624
|
orgId?: string;
|
|
552
625
|
actorType?: string;
|
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Talks to the orchestrator admin API directly (not the Platform dashboard
|
|
7
7
|
* proxy), so the CLI stays operable even when Platform is unavailable. Backed
|
|
8
|
-
* by `packages/orchestrator/src/routes/admin-cluster-settings.ts`.
|
|
8
|
+
* by `packages/orchestrator/src/routes/admin-cluster-settings.ts`. `show` also
|
|
9
|
+
* lists which settings version each coordinator and worker applied.
|
|
9
10
|
*
|
|
10
11
|
* These knobs are fleet-wide (a single `cluster_settings` row), not per-tenant.
|
|
11
12
|
* For per-tenant knobs use `kici-admin org-settings`.
|
|
12
13
|
*/
|
|
13
14
|
import type { Command } from 'commander';
|
|
14
15
|
import type { AdminApiClient } from '../api-client.js';
|
|
16
|
+
import { type SettingsPropagationReport } from '../../cluster/settings-propagation.js';
|
|
15
17
|
/**
|
|
16
18
|
* One text knob. Kept separate from {@link KnobSpec} because the value parser,
|
|
17
19
|
* the PATCH body type, and the `show` formatter all differ — a string knob has
|
|
@@ -36,8 +38,36 @@ interface BooleanKnobSpec {
|
|
|
36
38
|
flag: string;
|
|
37
39
|
label: string;
|
|
38
40
|
}
|
|
41
|
+
type ClusterSettings = Record<string, number | string | boolean | null>;
|
|
39
42
|
/** camelCase → value (null clears the override). */
|
|
40
43
|
type PatchBody = Record<string, number | string | boolean | null>;
|
|
44
|
+
/** The outcome of the propagation request `show` makes after the settings read. */
|
|
45
|
+
export type PropagationFetch = {
|
|
46
|
+
kind: 'ok';
|
|
47
|
+
report: SettingsPropagationReport;
|
|
48
|
+
} | {
|
|
49
|
+
kind: 'unsupported';
|
|
50
|
+
} | {
|
|
51
|
+
kind: 'error';
|
|
52
|
+
reason: string;
|
|
53
|
+
};
|
|
54
|
+
export declare const PROPAGATION_UNSUPPORTED_NOTE: string;
|
|
55
|
+
/**
|
|
56
|
+
* Fetch the propagation report. A 404 means the orchestrator predates the
|
|
57
|
+
* route; `show` then prints the settings alone, because this CLI may be newer
|
|
58
|
+
* than the orchestrator it talks to.
|
|
59
|
+
*/
|
|
60
|
+
export declare function fetchPropagation(client: AdminApiClient): Promise<PropagationFetch>;
|
|
61
|
+
/** The table section: one row per orchestrator, lagging ones in upper case. */
|
|
62
|
+
export declare function formatPropagation(report: SettingsPropagationReport): string;
|
|
63
|
+
/**
|
|
64
|
+
* What `show` prints. The JSON keeps the flat settings map exactly as before
|
|
65
|
+
* and adds one `propagation` key, so scripts that read knob keys keep working.
|
|
66
|
+
*/
|
|
67
|
+
export declare function renderShow(settings: ClusterSettings, propagation: PropagationFetch, format: string): {
|
|
68
|
+
stdout: string;
|
|
69
|
+
stderr: string | null;
|
|
70
|
+
};
|
|
41
71
|
/**
|
|
42
72
|
* Parse an integer CLI flag against its knob's bounds, exiting on failure.
|
|
43
73
|
*
|
|
@@ -5,9 +5,35 @@
|
|
|
5
5
|
* peer create-token Create a join token for a new peer
|
|
6
6
|
* peer list List active peer credentials
|
|
7
7
|
* peer revoke Revoke a specific peer's credential
|
|
8
|
+
* peer forget Drop a departed peer from every coordinator's live
|
|
9
|
+
* peer registry (admin HTTP API; credential untouched)
|
|
8
10
|
* peer revoke-all Revoke all peer credentials
|
|
9
11
|
*/
|
|
10
12
|
import type { Command } from 'commander';
|
|
11
13
|
import type { AdminApiClient } from '../api-client.js';
|
|
12
|
-
|
|
14
|
+
/** Where `peer forget` writes its results. */
|
|
15
|
+
export interface PeerForgetIo {
|
|
16
|
+
out: (line: string) => void;
|
|
17
|
+
/** Asks the operator; resolves true on yes. */
|
|
18
|
+
confirm: (prompt: string) => Promise<boolean>;
|
|
19
|
+
/** Whether an operator can answer a prompt (stdin is a terminal). */
|
|
20
|
+
interactive: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* `kici-admin peer forget`: drop a departed peer from this coordinator's live
|
|
24
|
+
* peer registry and every connected sibling's. Exits 1 when any coordinator
|
|
25
|
+
* kept it (connected, heard from recently, or no answer).
|
|
26
|
+
*
|
|
27
|
+
* When the forget would switch a coordinator's event-provision backstop back
|
|
28
|
+
* on, the operator confirms that consequence first; `--yes` acknowledges it up
|
|
29
|
+
* front, and without a terminal the command refuses instead of asking.
|
|
30
|
+
*
|
|
31
|
+
* @returns the process exit code
|
|
32
|
+
*/
|
|
33
|
+
export declare function runPeerForget(client: Pick<AdminApiClient, 'forgetPeer'>, instanceId: string, opts: {
|
|
34
|
+
json: boolean;
|
|
35
|
+
timeout: string;
|
|
36
|
+
yes: boolean;
|
|
37
|
+
}, io: PeerForgetIo): Promise<number>;
|
|
38
|
+
export declare function registerPeerCommands(program: Command, getClient: () => AdminApiClient): void;
|
|
13
39
|
//# sourceMappingURL=peer.d.ts.map
|
|
@@ -1,18 +1,54 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Scaler maintenance commands for kici-admin.
|
|
3
3
|
*
|
|
4
|
+
* scaler orphans List the live Firecracker VMs a node's running
|
|
5
|
+
* orchestrator does not track and, with --stop, stop
|
|
6
|
+
* them. Goes through the admin HTTP API; `--target`
|
|
7
|
+
* reaches a worker through the coordinator.
|
|
4
8
|
* scaler reap-orphans Free leaked Firecracker/container resources WITHOUT a
|
|
5
9
|
* running orchestrator (recovery for a wedged node whose
|
|
6
10
|
* data disk is full).
|
|
7
11
|
*
|
|
8
|
-
*
|
|
9
|
-
* and runs the liveness-driven reaper. It is the sanctioned operator path for
|
|
12
|
+
* `reap-orphans` loads the orchestrator's LOCAL config (no HTTP admin API, no
|
|
13
|
+
* DB) and runs the liveness-driven reaper, which spares every live VM. It is the sanctioned operator path for
|
|
10
14
|
* the ENOSPC bootstrap deadlock: when the data disk is 100% full the
|
|
11
15
|
* orchestrator crash-loops before its in-process orphan sweep can run, so a
|
|
12
16
|
* tool that frees disk WITHOUT the orchestrator is required.
|
|
13
17
|
*/
|
|
14
18
|
import type { Command } from 'commander';
|
|
19
|
+
import type { AdminApiClient } from '../api-client.js';
|
|
15
20
|
/** Probe the local orchestrator /health endpoint. Healthy => it reaps itself. */
|
|
16
21
|
export declare function isOrchestratorHealthy(port: number, basePath: string): Promise<boolean>;
|
|
17
|
-
|
|
22
|
+
/** The `scaler orphans` options as Commander parses them. */
|
|
23
|
+
export interface ScalerOrphansOptions {
|
|
24
|
+
target?: string;
|
|
25
|
+
all: boolean;
|
|
26
|
+
stop: boolean;
|
|
27
|
+
vm: string[];
|
|
28
|
+
yes: boolean;
|
|
29
|
+
dryRun: boolean;
|
|
30
|
+
/** Seconds to wait for a `--target` node. */
|
|
31
|
+
timeout: string;
|
|
32
|
+
json: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** Where `scaler orphans` reads its confirmation and writes its output. */
|
|
35
|
+
export interface ScalerOrphansIo {
|
|
36
|
+
confirm: (prompt: string) => Promise<boolean>;
|
|
37
|
+
/** The listing, the results, or the JSON body. */
|
|
38
|
+
out: (line: string) => void;
|
|
39
|
+
/** Progress and the confirmation context; stderr, so `--json` output stays parseable. */
|
|
40
|
+
err: (line: string) => void;
|
|
41
|
+
}
|
|
42
|
+
type OrphansClient = Pick<AdminApiClient, 'listScalerOrphans' | 'stopScalerOrphans'>;
|
|
43
|
+
/** `45s`, `12m3s`, `1h2m`, `3d4h`. */
|
|
44
|
+
export declare function formatAge(seconds: number): string;
|
|
45
|
+
/**
|
|
46
|
+
* `kici-admin scaler orphans`: list the live Firecracker VMs a node's
|
|
47
|
+
* orchestrator does not track, and with `--stop` stop the orphaned ones.
|
|
48
|
+
*
|
|
49
|
+
* @returns the process exit code
|
|
50
|
+
*/
|
|
51
|
+
export declare function runScalerOrphans(client: OrphansClient, opts: ScalerOrphansOptions, io: ScalerOrphansIo): Promise<number>;
|
|
52
|
+
export declare function registerScalerCommands(program: Command, getClient: () => AdminApiClient): void;
|
|
53
|
+
export {};
|
|
18
54
|
//# sourceMappingURL=scaler.d.ts.map
|