@rallycry/conveyor-k3 0.1.12 → 0.1.14
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/cli.js +2720 -1291
- package/dist/index.d.ts +85 -28
- package/dist/index.js +1533 -423
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -8,10 +8,14 @@ interface ClusterConnectionConfig {
|
|
|
8
8
|
/** Test-only overrides; production reads the host-written control aliases. */
|
|
9
9
|
readControlFile?: (path: string) => string | null;
|
|
10
10
|
controlFileExists?: (path: string) => boolean;
|
|
11
|
+
/** Dial again after the server closes the socket. The daemon's connection only. */
|
|
12
|
+
reconnectWhenReplaced?: boolean;
|
|
11
13
|
}
|
|
12
14
|
declare class ClusterConnection {
|
|
13
15
|
private socket;
|
|
14
16
|
private readonly config;
|
|
17
|
+
private redialDelayMs;
|
|
18
|
+
private redialTimer;
|
|
15
19
|
/** Called when Conveyor says the desired state changed. */
|
|
16
20
|
onSyncRequested: (() => void) | null;
|
|
17
21
|
/** Called when Conveyor asks the machine to remove itself. */
|
|
@@ -29,6 +33,8 @@ declare class ClusterConnection {
|
|
|
29
33
|
* instead of waiting out the stale window.
|
|
30
34
|
*/
|
|
31
35
|
sayGoodbye(timeoutMs?: number): Promise<void>;
|
|
36
|
+
/** Dial again after the server closed the socket, waiting longer each time. */
|
|
37
|
+
private redial;
|
|
32
38
|
disconnect(): void;
|
|
33
39
|
}
|
|
34
40
|
|
|
@@ -132,17 +138,31 @@ declare class ClusterDaemon {
|
|
|
132
138
|
private readonly localImageHashes;
|
|
133
139
|
/** How long the in-cluster registry has been not ready, across beats. */
|
|
134
140
|
private readonly registryWatch;
|
|
141
|
+
/**
|
|
142
|
+
* Whether pod isolation is in force, from the last reconcile; undefined
|
|
143
|
+
* while desired state does not ask for it. Every heartbeat checks it again
|
|
144
|
+
* against k3s's own settings before reporting it.
|
|
145
|
+
*/
|
|
146
|
+
private isolation;
|
|
147
|
+
/** Whether the pod slice's CPU cap is in force, from the last reconcile. */
|
|
148
|
+
private cpuQuotaApplied;
|
|
135
149
|
private timers;
|
|
136
150
|
/** When the last store walk started, so one that failed is not retried on every reconcile. */
|
|
137
151
|
private storeWalkStartedAt;
|
|
138
152
|
/** Serializes reconcile against itself — a sync nudge during a reconcile
|
|
139
153
|
* must queue, not interleave two kubectl applies of the same manifests. */
|
|
140
154
|
private reconciling;
|
|
155
|
+
/** The run queued behind the running one, until it starts. At most one waits. */
|
|
156
|
+
private queuedRun;
|
|
157
|
+
/** The next reconcile while pod isolation is not applied; `dueAt` 0 = none. */
|
|
158
|
+
private isolationRetry;
|
|
141
159
|
constructor(ports: DaemonPorts);
|
|
142
160
|
start(): Promise<void>;
|
|
143
161
|
stop(): Promise<void>;
|
|
144
162
|
/** Fetch the desired state and converge to it. Queued, never concurrent. */
|
|
145
163
|
syncAndReconcile(): Promise<void>;
|
|
164
|
+
/** Reconcile again later while pod isolation is not applied; stop once it is. */
|
|
165
|
+
private scheduleIsolationRetry;
|
|
146
166
|
private runReconcile;
|
|
147
167
|
/**
|
|
148
168
|
* The hourly clock: warm, re-pin, and reclaim if the pile justifies it.
|
|
@@ -229,6 +249,12 @@ interface PruneResult {
|
|
|
229
249
|
removed: number;
|
|
230
250
|
bytesReclaimed: number;
|
|
231
251
|
failures: string[];
|
|
252
|
+
/**
|
|
253
|
+
* Removals crictl stopped waiting for. containerd carries on deleting a
|
|
254
|
+
* multi-gigabyte image after crictl's deadline, so these are not failures:
|
|
255
|
+
* the next prune finds the image gone, or tries it again.
|
|
256
|
+
*/
|
|
257
|
+
pending: string[];
|
|
232
258
|
}
|
|
233
259
|
/** Remove the stranded images. Individual failures are reported, not thrown. */
|
|
234
260
|
declare function pruneStrandedImages(exec: Executor, inventory: ImageInventory, wantedImages: string[]): Promise<PruneResult>;
|
|
@@ -293,6 +319,12 @@ interface TelemetryState {
|
|
|
293
319
|
localImageHashes?: LocalImageHashCache;
|
|
294
320
|
/** Present while desired state turns the in-cluster registry on. */
|
|
295
321
|
localRegistry?: LocalRegistryWatch;
|
|
322
|
+
/** Present while desired state asks for pod isolation (a host-runtime machine). */
|
|
323
|
+
isolation?: {
|
|
324
|
+
applied: boolean;
|
|
325
|
+
};
|
|
326
|
+
/** Present while a host-runtime machine's desired state reserves CPU. */
|
|
327
|
+
cpuQuotaApplied?: boolean | undefined;
|
|
296
328
|
/**
|
|
297
329
|
* The last measured size of k3s's containerd store. Null (or absent) until
|
|
298
330
|
* the first measurement, and the heartbeat says null then: a 0 would read
|
|
@@ -395,6 +427,18 @@ interface ReconcileResult {
|
|
|
395
427
|
recreatedPriorityClass: boolean;
|
|
396
428
|
/** Empty pool namespaces of projects this machine no longer serves, removed. */
|
|
397
429
|
prunedNamespaces: string[];
|
|
430
|
+
/**
|
|
431
|
+
* Whether pod isolation is in force, while desired state asks for it (a
|
|
432
|
+
* host-runtime machine). Undefined otherwise. Reported on every heartbeat.
|
|
433
|
+
*/
|
|
434
|
+
isolation?: {
|
|
435
|
+
applied: boolean;
|
|
436
|
+
};
|
|
437
|
+
/**
|
|
438
|
+
* Whether the pod slice is hard-capped at the CPU the reserve leaves, on a
|
|
439
|
+
* host-runtime machine whose desired state reserves CPU. Undefined otherwise.
|
|
440
|
+
*/
|
|
441
|
+
cpuQuotaApplied?: boolean;
|
|
398
442
|
}
|
|
399
443
|
declare function reconcile(ctx: ReconcileContext, desired: PersonalClusterDesiredState): Promise<ReconcileResult>;
|
|
400
444
|
|
|
@@ -519,12 +563,11 @@ declare function ownerConfiguredKeys(ownerConfig: string | null): Set<string>;
|
|
|
519
563
|
* they chose, and last-writer-wins on their own file is exactly what this
|
|
520
564
|
* module exists not to do.
|
|
521
565
|
*/
|
|
522
|
-
declare function renderK3sDropIn(kubelet: PersonalClusterKubeletState, ownerConfig: string | null
|
|
523
|
-
/**
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
declare const renderKubeletDropIn: typeof renderK3sDropIn;
|
|
566
|
+
declare function renderK3sDropIn(kubelet: PersonalClusterKubeletState, ownerConfig: string | null,
|
|
567
|
+
/** False on an adopted k3s: its components stay as its owner set them. */
|
|
568
|
+
options?: {
|
|
569
|
+
disableComponents?: boolean;
|
|
570
|
+
}): DropInRenderResult;
|
|
528
571
|
|
|
529
572
|
interface UnitRenderOptions {
|
|
530
573
|
/** Absolute path to the installed `conveyor-k3` binary. */
|
|
@@ -585,6 +628,18 @@ interface MachineState {
|
|
|
585
628
|
*/
|
|
586
629
|
k3sStoreBytes?: number;
|
|
587
630
|
k3sStoreMeasuredAt?: string;
|
|
631
|
+
/**
|
|
632
|
+
* "host" once `conveyor-k3 host setup` or `host link` enrolled this machine
|
|
633
|
+
* as a host-runtime instance. Absent on a VM guest, including every state
|
|
634
|
+
* file written before the host runtime existed.
|
|
635
|
+
*/
|
|
636
|
+
runtime?: "host";
|
|
637
|
+
/**
|
|
638
|
+
* True once setup installed this machine's k3s. Absent on a k3s setup found
|
|
639
|
+
* already installed, and in every state file written before the field
|
|
640
|
+
* existed. See {@link managesK3s}.
|
|
641
|
+
*/
|
|
642
|
+
k3sInstalledByConveyor?: boolean;
|
|
588
643
|
}
|
|
589
644
|
declare function readState(fs: FileSystemPort$1): Promise<MachineState>;
|
|
590
645
|
declare function writeState(fs: FileSystemPort$1, state: MachineState): Promise<void>;
|
|
@@ -597,7 +652,7 @@ declare function writeState(fs: FileSystemPort$1, state: MachineState): Promise<
|
|
|
597
652
|
* help output below is part of the product: every verb states what it does to
|
|
598
653
|
* their machine, and `uninstall` states what it does not.
|
|
599
654
|
*/
|
|
600
|
-
declare const VERBS: readonly ["vm", "setup", "start", "stop", "status", "sync", "update", "registry", "runners", "uninstall", "daemon"];
|
|
655
|
+
declare const VERBS: readonly ["vm", "host", "setup", "start", "stop", "status", "sync", "update", "registry", "runners", "uninstall", "daemon"];
|
|
601
656
|
type Verb = (typeof VERBS)[number];
|
|
602
657
|
declare function isVerb(value: string): value is Verb;
|
|
603
658
|
interface ParsedArgs {
|
|
@@ -613,7 +668,7 @@ interface ParsedArgs {
|
|
|
613
668
|
* this surface is nine verbs and six flags, not a general CLI framework.
|
|
614
669
|
*/
|
|
615
670
|
declare function parseArgs(argv: readonly string[]): ParsedArgs;
|
|
616
|
-
declare const HELP = "conveyor-k3 \u2014
|
|
671
|
+
declare const HELP = "conveyor-k3 \u2014 Personal Compute for Conveyor\n\nUsage: conveyor-k3 <command> [options]\n\nOne product, two runtimes. Pick the one that fits the machine:\n\nOn your computer or server:\n vm Personal computer runtime: an isolated VM on macOS or\n Linux. Run conveyor-k3 vm for its commands.\n host Dedicated server runtime: k3s and the daemon on this\n Linux machine, with no VM. Root only. Run\n conveyor-k3 host for its commands.\n\nInside a linked machine (the VM guest, or the server itself):\n setup VM guest only: install and enrol this machine. Safe\n to re-run. On a server, use conveyor-k3 host setup.\n start Start the tunnel and the daemon.\n stop Stop both, and tell Conveyor at once so your next\n build goes straight to project compute.\n status [--json] What is running, what Conveyor knows, and what is\n missing.\n sync Re-read your settings from Conveyor and apply them.\n update Update conveyor-k3, cloudflared, and (when you have\n allowed it and nothing is running) k3s.\n registry list Which registry credentials are configured, and which\n ones your projects still need.\n registry add <host> Add one registry credential.\n --username <user>\n --password-stdin read the password from stdin\n --no-restart skip the required k3s restart\n registry gc Delete superseded shadow-bake images from the image\n registry inside this cluster. Runs daily on its own,\n and only while no Conveyor pod or bake is running.\n --dry-run list what it would delete\n runners list Which GitHub Actions runners this machine hosts, and\n whether each may import a locally baked image.\n runners grant <user>\u2026 Let those runner users import a locally baked image\n into this node and pin it. Writes one file under\n /etc/sudoers.d, checked with visudo first. Needed only\n when a project has Bake Locally turned on.\n uninstall VM guest only: remove Conveyor's units, environment,\n state, and image registry. Your k3s config, your own\n registries.yaml entries, your workloads, and the\n registry's data are left alone. On a server, use\n conveyor-k3 host uninstall: it also removes the\n device key.\n --purge-k3s --yes also remove k3s itself and the\n registry's data\n daemon Run in the foreground (what the systemd unit calls).\n\nOptions:\n --version Print the version.\n --help Print this message.\n\nDocs: https://conveyor.rallycryapp.com/docs/guides/managed-personal-compute\n";
|
|
617
672
|
|
|
618
673
|
/**
|
|
619
674
|
* `conveyor-k3 registry add|list|gc` — where an owner adds registry
|
|
@@ -687,27 +742,21 @@ interface UninstallResult {
|
|
|
687
742
|
declare function uninstall(ports: UninstallPorts, options?: UninstallOptions): Promise<UninstallResult>;
|
|
688
743
|
|
|
689
744
|
/**
|
|
690
|
-
*
|
|
691
|
-
*
|
|
692
|
-
*
|
|
693
|
-
*
|
|
694
|
-
*
|
|
695
|
-
*
|
|
696
|
-
*
|
|
697
|
-
*
|
|
698
|
-
*
|
|
699
|
-
*
|
|
700
|
-
*
|
|
701
|
-
* names, never `@latest` — the npm dist-tag is a root-execution channel on
|
|
702
|
-
* every enrolled machine, so a compromised publish would reach them all
|
|
703
|
-
* within a day. The daemon restarts only if the version actually moved.
|
|
704
|
-
* - **cloudflared.** `cloudflared update` exits 11 to mean "updated"; that is
|
|
705
|
-
* the only case that needs a tunnel restart.
|
|
706
|
-
* - **k3s.** Only when the owner allowed it AND nothing of Conveyor's is
|
|
707
|
-
* running. A k3s upgrade at the wrong moment interrupts someone's build, and
|
|
708
|
-
* no upgrade is worth that.
|
|
745
|
+
* Who keeps this machine's cloudflared current.
|
|
746
|
+
*
|
|
747
|
+
* `cloudflared update` only works on a binary cloudflared installed itself. A
|
|
748
|
+
* package-manager build refuses: it prints "cloudflared was installed by a
|
|
749
|
+
* package manager" and exits 0 — the same exit as "already current". Read by
|
|
750
|
+
* exit code alone, such a machine reports a current cloudflared forever while
|
|
751
|
+
* apt (or nothing) is what actually updates it.
|
|
752
|
+
*
|
|
753
|
+
* The literal path lies, too. On a server where `/usr/local/bin/cloudflared`
|
|
754
|
+
* is a symlink to apt's `/usr/bin/cloudflared` there is ONE binary, owned by
|
|
755
|
+
* dpkg, so the owner check runs against the resolved path.
|
|
709
756
|
*/
|
|
710
757
|
|
|
758
|
+
type CloudflaredUpdater = "conveyor" | "package-manager";
|
|
759
|
+
|
|
711
760
|
interface UpdatePorts {
|
|
712
761
|
exec: Executor;
|
|
713
762
|
log: (line: string) => void;
|
|
@@ -729,6 +778,12 @@ interface UpdateBinaries {
|
|
|
729
778
|
}
|
|
730
779
|
interface UpdateDecisionInput {
|
|
731
780
|
autoUpgradeK3s: boolean;
|
|
781
|
+
/**
|
|
782
|
+
* False on a server whose k3s setup did not install (`managesK3s`): the
|
|
783
|
+
* installer would turn off the owner's traefik and servicelb. Absent reads
|
|
784
|
+
* as true, which is every VM guest.
|
|
785
|
+
*/
|
|
786
|
+
managesK3s?: boolean;
|
|
732
787
|
/** Null when the count could not be read — treated exactly like "busy". */
|
|
733
788
|
runningConveyorPods: number | null;
|
|
734
789
|
installedK3s: [number, number] | null;
|
|
@@ -751,6 +806,8 @@ declare function decideK3sUpgrade(input: UpdateDecisionInput): K3sUpgradeDecisio
|
|
|
751
806
|
interface UpdateResult {
|
|
752
807
|
packageUpdated: boolean;
|
|
753
808
|
cloudflaredUpdated: boolean;
|
|
809
|
+
/** Who keeps cloudflared current; null when this run could not tell. */
|
|
810
|
+
cloudflaredUpdater: CloudflaredUpdater | null;
|
|
754
811
|
k3sUpgraded: boolean;
|
|
755
812
|
notes: string[];
|
|
756
813
|
}
|
|
@@ -959,4 +1016,4 @@ declare function pathsForRoot(root: string, instance?: string): {
|
|
|
959
1016
|
};
|
|
960
1017
|
type HostPaths = ReturnType<typeof pathsForRoot>;
|
|
961
1018
|
|
|
962
|
-
export { ClusterConnection, type ClusterConnectionConfig, ClusterDaemon, CommandError, type CrictlImage, DEFAULT_INSTANCE, type DaemonPorts, type Executor, type FileSystemPort$1 as FileSystemPort, type GuestDnsProvision, type GuestSrvRecord, HELP, type HostPaths, type ImageInventory, K3S_DISABLED_COMPONENTS, K3S_INSTALL_EXEC, type K3sUpgradeDecision, type MachineState, type NetworkEndpoint, type NetworkPolicy, type QemuNetworkPolicy, type ReconcileContext, type ReconcileResult, type RegistriesFile, type ResolvedNetwork, type ResolvedNetworkHost, type SRVLookup, type UninstallResult, type UnitRenderOptions, VERBS, type Verb, cloudflaredSrvRecords, collectHeartbeat, configuredAuthHosts, countRunningConveyorPods, createMemoryFileSystem, decideK3sUpgrade, hostPaths, isGloballyRoutableIPv4, isVerb, maximumGuestMemoryGiB, maximumGuestMemoryGiBWithin, meetsK3sMinimum, missingAuthHosts, nodeFileSystem, ownerConfiguredKeys, ownerConfiguredKubeletFlags, parseArgs, parseInstanceName, parseK3sVersion, parseRegistries, pruneStrandedImages, readImageInventory, readState, reconcile, registryAdd, registryList, renderAllUnits, renderGuestDnsProvision, renderK3sDropIn,
|
|
1019
|
+
export { ClusterConnection, type ClusterConnectionConfig, ClusterDaemon, CommandError, type CrictlImage, DEFAULT_INSTANCE, type DaemonPorts, type Executor, type FileSystemPort$1 as FileSystemPort, type GuestDnsProvision, type GuestSrvRecord, HELP, type HostPaths, type ImageInventory, K3S_DISABLED_COMPONENTS, K3S_INSTALL_EXEC, type K3sUpgradeDecision, type MachineState, type NetworkEndpoint, type NetworkPolicy, type QemuNetworkPolicy, type ReconcileContext, type ReconcileResult, type RegistriesFile, type ResolvedNetwork, type ResolvedNetworkHost, type SRVLookup, type UninstallResult, type UnitRenderOptions, VERBS, type Verb, cloudflaredSrvRecords, collectHeartbeat, configuredAuthHosts, countRunningConveyorPods, createMemoryFileSystem, decideK3sUpgrade, hostPaths, isGloballyRoutableIPv4, isVerb, maximumGuestMemoryGiB, maximumGuestMemoryGiBWithin, meetsK3sMinimum, missingAuthHosts, nodeFileSystem, ownerConfiguredKeys, ownerConfiguredKubeletFlags, parseArgs, parseInstanceName, parseK3sVersion, parseRegistries, pruneStrandedImages, readImageInventory, readState, reconcile, registryAdd, registryList, renderAllUnits, renderGuestDnsProvision, renderK3sDropIn, renderRegistryAuthSummary, resolveCloudflaredSrvRecords, resolveNetwork, rewriteQemuArgs, runOrThrow, runUpdate, selectStrandedImages, serializeRegistries, spawnExecutor, uninstall, upsertRegistryAuth, warmImages, writeState };
|