@descryy/runtime-controller 0.3.9 → 0.4.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/dist/attach-discovery.d.ts +120 -0
- package/dist/attach-discovery.d.ts.map +1 -0
- package/dist/attach-discovery.js +409 -0
- package/dist/attach-discovery.js.map +1 -0
- package/dist/attach-fencing.d.ts +1 -0
- package/dist/attach-fencing.d.ts.map +1 -1
- package/dist/attach-fencing.js +44 -22
- package/dist/attach-fencing.js.map +1 -1
- package/dist/attach-log-file.d.ts +21 -0
- package/dist/attach-log-file.d.ts.map +1 -0
- package/dist/attach-log-file.js +81 -0
- package/dist/attach-log-file.js.map +1 -0
- package/dist/bounded-file.d.ts +11 -0
- package/dist/bounded-file.d.ts.map +1 -0
- package/dist/bounded-file.js +41 -0
- package/dist/bounded-file.js.map +1 -0
- package/dist/bounded-output.d.ts +24 -0
- package/dist/bounded-output.d.ts.map +1 -0
- package/dist/bounded-output.js +79 -0
- package/dist/bounded-output.js.map +1 -0
- package/dist/container-sandbox.d.ts +7 -20
- package/dist/container-sandbox.d.ts.map +1 -1
- package/dist/container-sandbox.js +139 -8
- package/dist/container-sandbox.js.map +1 -1
- package/dist/controller.d.ts +24 -2
- package/dist/controller.d.ts.map +1 -1
- package/dist/controller.js +260 -84
- package/dist/controller.js.map +1 -1
- package/dist/dependency-version-check.d.ts +1 -0
- package/dist/dependency-version-check.d.ts.map +1 -1
- package/dist/dependency-version-check.js +43 -24
- package/dist/dependency-version-check.js.map +1 -1
- package/dist/environment-metadata.d.ts +13 -0
- package/dist/environment-metadata.d.ts.map +1 -1
- package/dist/environment-metadata.js +138 -24
- package/dist/environment-metadata.js.map +1 -1
- package/dist/environment-version-check.d.ts +1 -0
- package/dist/environment-version-check.d.ts.map +1 -1
- package/dist/environment-version-check.js +13 -7
- package/dist/environment-version-check.js.map +1 -1
- package/dist/execution-safety.d.ts +2 -0
- package/dist/execution-safety.d.ts.map +1 -1
- package/dist/execution-safety.js +36 -0
- package/dist/execution-safety.js.map +1 -1
- package/dist/index.d.ts +16 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/node-options.d.ts +3 -0
- package/dist/node-options.d.ts.map +1 -0
- package/dist/node-options.js +34 -0
- package/dist/node-options.js.map +1 -0
- package/dist/orphan-reaper-process.d.ts +2 -0
- package/dist/orphan-reaper-process.d.ts.map +1 -0
- package/dist/orphan-reaper-process.js +98 -0
- package/dist/orphan-reaper-process.js.map +1 -0
- package/dist/orphan-reaper.d.ts +25 -0
- package/dist/orphan-reaper.d.ts.map +1 -0
- package/dist/orphan-reaper.js +161 -0
- package/dist/orphan-reaper.js.map +1 -0
- package/dist/process-identity.d.ts +1 -0
- package/dist/process-identity.d.ts.map +1 -1
- package/dist/process-identity.js +18 -4
- package/dist/process-identity.js.map +1 -1
- package/dist/process-manager.d.ts +12 -9
- package/dist/process-manager.d.ts.map +1 -1
- package/dist/process-manager.js +316 -125
- package/dist/process-manager.js.map +1 -1
- package/dist/readiness.d.ts +1 -0
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +77 -11
- package/dist/readiness.js.map +1 -1
- package/dist/sandbox.d.ts +21 -8
- package/dist/sandbox.d.ts.map +1 -1
- package/dist/sandbox.js +359 -49
- package/dist/sandbox.js.map +1 -1
- package/dist/spawn-environment.d.ts +16 -0
- package/dist/spawn-environment.d.ts.map +1 -0
- package/dist/spawn-environment.js +35 -0
- package/dist/spawn-environment.js.map +1 -0
- package/dist/target-pid.d.ts +6 -0
- package/dist/target-pid.d.ts.map +1 -0
- package/dist/target-pid.js +18 -0
- package/dist/target-pid.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attach-mode discovery (H-attach-log-discovery): answers "what pid, if any,
|
|
3
|
+
* is listening on this port" and "where does that pid's own output go"
|
|
4
|
+
* from process/kernel state alone -- never by inferring what a framework
|
|
5
|
+
* logs, only by reading what the OS already knows. This is what lets
|
|
6
|
+
* `observe`'s attach mode work without the caller supplying a pid or a log
|
|
7
|
+
* file (`descry-core`'s own observe tool composes these two, once its pin on
|
|
8
|
+
* this package moves past the version that added them).
|
|
9
|
+
*
|
|
10
|
+
* Two independent lookups:
|
|
11
|
+
* - `findPortOwner` (port -> pid): reuses the same `/proc/net/tcp{,6}` +
|
|
12
|
+
* per-pid fd-table matching `process-identity.ts`'s `verifyListeningSocketOwner`
|
|
13
|
+
* already does for a DIFFERENT question (does a KNOWN pid own a port) --
|
|
14
|
+
* this asks the converse (which pid, if any, owns it), so a second, small,
|
|
15
|
+
* pure copy of the inode-matching core lives here rather than importing
|
|
16
|
+
* that module's private helpers across a real seam boundary (this file's
|
|
17
|
+
* own `reader` injection point, `process-identity.ts` has none).
|
|
18
|
+
* - `resolveLogSourceForPid` (pid -> log source descriptor): `readlink`s the
|
|
19
|
+
* pid's own fd 1 and fd 2. A regular file is the file-attach path this
|
|
20
|
+
* repo already tails with fencing (`attachManagedProcess`/
|
|
21
|
+
* `attachToRunningProcess`) -- returned as a path for the caller to feed
|
|
22
|
+
* into that machinery, not re-implemented here. A pipe or socket (a shell
|
|
23
|
+
* redirect, a container runtime, a terminal) can't be read by another
|
|
24
|
+
* process directly, so this falls back to the pid's own cgroup membership:
|
|
25
|
+
* a Docker container's cgroup path names it, a systemd unit's cgroup path
|
|
26
|
+
* names it. Building the actual stream source for those two
|
|
27
|
+
* (`docker logs -f` / `journalctl -f`) is `@descryy/runtime-orchestrator`'s
|
|
28
|
+
* job (`attach-log-sources.ts`) -- this package doesn't depend on the
|
|
29
|
+
* `ProcessOutputSource` contract at all, and doesn't need to.
|
|
30
|
+
*
|
|
31
|
+
* **Injectable `ProcReader`, not real `/proc`, in tests.** Real Docker/systemd
|
|
32
|
+
* cgroup membership can't be fabricated hermetically against the real
|
|
33
|
+
* filesystem, and even the plain-file/plain-port cases are easier to prove
|
|
34
|
+
* correct against a fake than a real, racy `/proc`. Both functions default to
|
|
35
|
+
* `REAL_PROC_READER` and take an injected one for tests.
|
|
36
|
+
*/
|
|
37
|
+
/** The subset of filesystem reads this module needs from `/proc` -- injectable so tests never touch the real one. */
|
|
38
|
+
export interface ProcReader {
|
|
39
|
+
readFile(path: string): string;
|
|
40
|
+
readdir(path: string): string[];
|
|
41
|
+
readlink(path: string): string;
|
|
42
|
+
/** `"dev:ino"` when `path` (symlinks followed) is a regular file, else `null` -- never a throw. */
|
|
43
|
+
regularFileIdentity(path: string): string | null;
|
|
44
|
+
}
|
|
45
|
+
export declare const REAL_PROC_READER: ProcReader;
|
|
46
|
+
export type PortOwnerLookup = {
|
|
47
|
+
readonly outcome: "found";
|
|
48
|
+
readonly pid: number;
|
|
49
|
+
} | {
|
|
50
|
+
readonly outcome: "nothing-listening";
|
|
51
|
+
} | {
|
|
52
|
+
readonly outcome: "several-owners";
|
|
53
|
+
readonly pids: readonly number[];
|
|
54
|
+
} | {
|
|
55
|
+
readonly outcome: "owned-by-docker-proxy";
|
|
56
|
+
readonly pid: number;
|
|
57
|
+
} | {
|
|
58
|
+
readonly outcome: "proc-unreadable";
|
|
59
|
+
readonly reason: string;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Who, if anyone, is listening on `port` right now -- a real kernel-state
|
|
63
|
+
* lookup (`/proc/net/tcp{,6}` plus each candidate pid's own fd table), not a
|
|
64
|
+
* guess. `owned-by-docker-proxy` is named separately from `found` rather than
|
|
65
|
+
* silently returned as one: a published Docker port is commonly fronted by a
|
|
66
|
+
* host-side `docker-proxy` process, not the container's own pid, and treating
|
|
67
|
+
* that pid as the target would attach to the wrong process entirely.
|
|
68
|
+
*/
|
|
69
|
+
export declare function findPortOwner(port: number, reader?: ProcReader, platform?: NodeJS.Platform): PortOwnerLookup;
|
|
70
|
+
export type LogSourceDescriptor = {
|
|
71
|
+
readonly kind: "file";
|
|
72
|
+
readonly path: string;
|
|
73
|
+
} | {
|
|
74
|
+
readonly kind: "docker";
|
|
75
|
+
readonly container: string;
|
|
76
|
+
} | {
|
|
77
|
+
readonly kind: "podman";
|
|
78
|
+
readonly container: string;
|
|
79
|
+
} | {
|
|
80
|
+
readonly kind: "kubernetes";
|
|
81
|
+
readonly podUid: string;
|
|
82
|
+
readonly containerId: string;
|
|
83
|
+
} | {
|
|
84
|
+
readonly kind: "systemd";
|
|
85
|
+
readonly unit: string;
|
|
86
|
+
} | {
|
|
87
|
+
readonly kind: "none";
|
|
88
|
+
readonly reason: string;
|
|
89
|
+
readonly remediation?: string;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Where `pid`'s own log output can be read from, without the caller naming a
|
|
93
|
+
* pid or a log file. `file` reuses this repo's existing fenced file-tail path
|
|
94
|
+
* (`attachManagedProcess`/`attachToRunningProcess`) -- returned as a path for
|
|
95
|
+
* the caller to feed into that machinery, not re-implemented here.
|
|
96
|
+
* `docker`/`systemd` name a stream-only source `@descryy/runtime-orchestrator`
|
|
97
|
+
* builds directly -- neither has pre-existing content to fence, since both
|
|
98
|
+
* start reading from "now" (see `DiscoveredAttachLogSource`'s own doc,
|
|
99
|
+
* `@descryy/runtime-contracts`).
|
|
100
|
+
*/
|
|
101
|
+
export declare function resolveLogSourceForPid(pid: number, reader?: ProcReader, platform?: NodeJS.Platform): LogSourceDescriptor;
|
|
102
|
+
export type KubectlRunner = (args: readonly string[]) => Promise<{
|
|
103
|
+
readonly ok: true;
|
|
104
|
+
readonly stdout: string;
|
|
105
|
+
} | {
|
|
106
|
+
readonly ok: false;
|
|
107
|
+
readonly error: string;
|
|
108
|
+
}>;
|
|
109
|
+
export type KubernetesContainerLookup = {
|
|
110
|
+
readonly outcome: "found";
|
|
111
|
+
readonly namespace: string;
|
|
112
|
+
readonly pod: string;
|
|
113
|
+
readonly container: string;
|
|
114
|
+
} | {
|
|
115
|
+
readonly outcome: "unresolved";
|
|
116
|
+
readonly reason: string;
|
|
117
|
+
};
|
|
118
|
+
export declare const REAL_KUBECTL: KubectlRunner;
|
|
119
|
+
export declare function resolveKubernetesContainer(podUid: string, containerId: string, kubectl?: KubectlRunner): Promise<KubernetesContainerLookup>;
|
|
120
|
+
//# sourceMappingURL=attach-discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attach-discovery.d.ts","sourceRoot":"","sources":["../src/attach-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAKH,qHAAqH;AACrH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,mGAAmG;IACnG,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAClD;AAED,eAAO,MAAM,gBAAgB,EAAE,UAY9B,CAAC;AA6DF,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,GACzC;IAAE,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,UAA6B,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,eAAe,CA0BhJ;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACtF;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAoLtF;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,UAA6B,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,mBAAmB,CAoC5J;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAElK,MAAM,MAAM,yBAAyB,GACjC;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC3G;IAAE,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAKhE,eAAO,MAAM,YAAY,EAAE,aAMvB,CAAC;AAgBL,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,aAA4B,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAwB/J"}
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attach-mode discovery (H-attach-log-discovery): answers "what pid, if any,
|
|
3
|
+
* is listening on this port" and "where does that pid's own output go"
|
|
4
|
+
* from process/kernel state alone -- never by inferring what a framework
|
|
5
|
+
* logs, only by reading what the OS already knows. This is what lets
|
|
6
|
+
* `observe`'s attach mode work without the caller supplying a pid or a log
|
|
7
|
+
* file (`descry-core`'s own observe tool composes these two, once its pin on
|
|
8
|
+
* this package moves past the version that added them).
|
|
9
|
+
*
|
|
10
|
+
* Two independent lookups:
|
|
11
|
+
* - `findPortOwner` (port -> pid): reuses the same `/proc/net/tcp{,6}` +
|
|
12
|
+
* per-pid fd-table matching `process-identity.ts`'s `verifyListeningSocketOwner`
|
|
13
|
+
* already does for a DIFFERENT question (does a KNOWN pid own a port) --
|
|
14
|
+
* this asks the converse (which pid, if any, owns it), so a second, small,
|
|
15
|
+
* pure copy of the inode-matching core lives here rather than importing
|
|
16
|
+
* that module's private helpers across a real seam boundary (this file's
|
|
17
|
+
* own `reader` injection point, `process-identity.ts` has none).
|
|
18
|
+
* - `resolveLogSourceForPid` (pid -> log source descriptor): `readlink`s the
|
|
19
|
+
* pid's own fd 1 and fd 2. A regular file is the file-attach path this
|
|
20
|
+
* repo already tails with fencing (`attachManagedProcess`/
|
|
21
|
+
* `attachToRunningProcess`) -- returned as a path for the caller to feed
|
|
22
|
+
* into that machinery, not re-implemented here. A pipe or socket (a shell
|
|
23
|
+
* redirect, a container runtime, a terminal) can't be read by another
|
|
24
|
+
* process directly, so this falls back to the pid's own cgroup membership:
|
|
25
|
+
* a Docker container's cgroup path names it, a systemd unit's cgroup path
|
|
26
|
+
* names it. Building the actual stream source for those two
|
|
27
|
+
* (`docker logs -f` / `journalctl -f`) is `@descryy/runtime-orchestrator`'s
|
|
28
|
+
* job (`attach-log-sources.ts`) -- this package doesn't depend on the
|
|
29
|
+
* `ProcessOutputSource` contract at all, and doesn't need to.
|
|
30
|
+
*
|
|
31
|
+
* **Injectable `ProcReader`, not real `/proc`, in tests.** Real Docker/systemd
|
|
32
|
+
* cgroup membership can't be fabricated hermetically against the real
|
|
33
|
+
* filesystem, and even the plain-file/plain-port cases are easier to prove
|
|
34
|
+
* correct against a fake than a real, racy `/proc`. Both functions default to
|
|
35
|
+
* `REAL_PROC_READER` and take an injected one for tests.
|
|
36
|
+
*/
|
|
37
|
+
import { execFile } from "node:child_process";
|
|
38
|
+
import { readFileSync, readdirSync, readlinkSync, statSync } from "node:fs";
|
|
39
|
+
export const REAL_PROC_READER = {
|
|
40
|
+
readFile: (path) => readFileSync(path, "utf8"),
|
|
41
|
+
readdir: (path) => readdirSync(path),
|
|
42
|
+
readlink: (path) => readlinkSync(path),
|
|
43
|
+
regularFileIdentity: (path) => {
|
|
44
|
+
try {
|
|
45
|
+
const stat = statSync(path);
|
|
46
|
+
return stat.isFile() ? `${String(stat.dev)}:${String(stat.ino)}` : null;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
function hexPort(port) {
|
|
54
|
+
return port.toString(16).toUpperCase().padStart(4, "0");
|
|
55
|
+
}
|
|
56
|
+
/** Every inode `/proc/net/tcp{,6}` records as LISTENing on `port`. A small, deliberate second copy of `process-identity.ts`'s private `listenInodesForPort` -- see this file's own header for why it isn't imported. */
|
|
57
|
+
function listenInodesForPort(reader, port) {
|
|
58
|
+
const inodes = new Set();
|
|
59
|
+
const targetPort = hexPort(port);
|
|
60
|
+
const TCP_LISTEN_STATE = "0A";
|
|
61
|
+
for (const path of ["/proc/net/tcp", "/proc/net/tcp6"]) {
|
|
62
|
+
let content;
|
|
63
|
+
try {
|
|
64
|
+
content = reader.readFile(path);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
for (const line of content.split("\n").slice(1)) {
|
|
70
|
+
const fields = line.trim().split(/\s+/);
|
|
71
|
+
const localAddress = fields[1];
|
|
72
|
+
const state = fields[3];
|
|
73
|
+
const inode = fields[9];
|
|
74
|
+
if (localAddress === undefined || state === undefined || inode === undefined)
|
|
75
|
+
continue;
|
|
76
|
+
if (state !== TCP_LISTEN_STATE)
|
|
77
|
+
continue;
|
|
78
|
+
if (localAddress.split(":")[1] === targetPort)
|
|
79
|
+
inodes.add(inode);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return inodes;
|
|
83
|
+
}
|
|
84
|
+
/** Whether `pid`'s fd table holds one of `inodes`. `false`, never a throw, for a pid whose fd table cannot be read (exited mid-scan, or a permission boundary) -- the same benign-race tolerance this repo's other `/proc` scanners apply. */
|
|
85
|
+
function ownsOneOf(reader, pid, inodes) {
|
|
86
|
+
let fds;
|
|
87
|
+
try {
|
|
88
|
+
fds = reader.readdir(`/proc/${pid}/fd`);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const SOCKET_FD_PATTERN = /^socket:\[(\d+)\]$/;
|
|
94
|
+
for (const fd of fds) {
|
|
95
|
+
let link;
|
|
96
|
+
try {
|
|
97
|
+
link = reader.readlink(`/proc/${pid}/fd/${fd}`);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const match = SOCKET_FD_PATTERN.exec(link);
|
|
103
|
+
if (match !== null && inodes.has(match[1]))
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
function commOf(reader, pid) {
|
|
109
|
+
try {
|
|
110
|
+
return reader.readFile(`/proc/${pid}/comm`).trim();
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Who, if anyone, is listening on `port` right now -- a real kernel-state
|
|
118
|
+
* lookup (`/proc/net/tcp{,6}` plus each candidate pid's own fd table), not a
|
|
119
|
+
* guess. `owned-by-docker-proxy` is named separately from `found` rather than
|
|
120
|
+
* silently returned as one: a published Docker port is commonly fronted by a
|
|
121
|
+
* host-side `docker-proxy` process, not the container's own pid, and treating
|
|
122
|
+
* that pid as the target would attach to the wrong process entirely.
|
|
123
|
+
*/
|
|
124
|
+
export function findPortOwner(port, reader = REAL_PROC_READER, platform = process.platform) {
|
|
125
|
+
if (platform !== "linux") {
|
|
126
|
+
return { outcome: "proc-unreadable", reason: `port ownership lookup requires /proc, which is Linux-only; not available on "${platform}"` };
|
|
127
|
+
}
|
|
128
|
+
const inodes = listenInodesForPort(reader, port);
|
|
129
|
+
if (inodes.size === 0)
|
|
130
|
+
return { outcome: "nothing-listening" };
|
|
131
|
+
let pidEntries;
|
|
132
|
+
try {
|
|
133
|
+
pidEntries = reader.readdir("/proc").filter((entry) => /^\d+$/.test(entry));
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
return {
|
|
137
|
+
outcome: "proc-unreadable",
|
|
138
|
+
reason: `could not list /proc to find the process listening on port ${String(port)}: ${error instanceof Error ? error.message : String(error)}`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const owners = pidEntries.filter((pid) => ownsOneOf(reader, pid, inodes)).map(Number);
|
|
142
|
+
if (owners.length === 0)
|
|
143
|
+
return { outcome: "nothing-listening" };
|
|
144
|
+
if (owners.length > 1)
|
|
145
|
+
return { outcome: "several-owners", pids: owners };
|
|
146
|
+
const pid = owners[0];
|
|
147
|
+
if (commOf(reader, String(pid)) === "docker-proxy") {
|
|
148
|
+
return { outcome: "owned-by-docker-proxy", pid };
|
|
149
|
+
}
|
|
150
|
+
return { outcome: "found", pid };
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The path of the regular file `pid` holds open on `fd`, or `null`. An absolute link target
|
|
154
|
+
* is not enough: a terminal (`/dev/pts/3`) and `/dev/null` are absolute too, and tailing a
|
|
155
|
+
* terminal device would read keystrokes, not logs. So the open file itself (`/proc/<pid>/fd/N`,
|
|
156
|
+
* which stat follows to the real inode) must be a regular file, and the path must still name
|
|
157
|
+
* that same inode -- after a log rotation the process keeps writing the old file while the path
|
|
158
|
+
* names a new one, and tailing the path would read a file nobody is writing to.
|
|
159
|
+
*/
|
|
160
|
+
function fileTargetOf(reader, pid, fd) {
|
|
161
|
+
const fdPath = `/proc/${String(pid)}/fd/${String(fd)}`;
|
|
162
|
+
let link;
|
|
163
|
+
try {
|
|
164
|
+
link = reader.readlink(fdPath);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
if (!link.startsWith("/"))
|
|
170
|
+
return null;
|
|
171
|
+
const held = reader.regularFileIdentity(fdPath);
|
|
172
|
+
if (held === null)
|
|
173
|
+
return null;
|
|
174
|
+
return reader.regularFileIdentity(link) === held ? link : null;
|
|
175
|
+
}
|
|
176
|
+
const CONTAINER_ID = "[0-9a-f]{12,64}";
|
|
177
|
+
const SCOPED_RUNTIMES = [
|
|
178
|
+
{ pattern: new RegExp(`^cri-containerd-(${CONTAINER_ID})\\.scope$`), runtime: "cri" },
|
|
179
|
+
{ pattern: new RegExp(`^crio-(${CONTAINER_ID})\\.scope$`), runtime: "cri" },
|
|
180
|
+
{ pattern: new RegExp(`^docker-(${CONTAINER_ID})\\.scope$`), runtime: "docker" },
|
|
181
|
+
{ pattern: new RegExp(`^libpod-(${CONTAINER_ID})(?:\\.scope)?$`), runtime: "podman" },
|
|
182
|
+
];
|
|
183
|
+
function podUidOf(components) {
|
|
184
|
+
for (const component of components) {
|
|
185
|
+
const match = /(?:^|-)pod([0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{12})(?:\.slice)?$/.exec(component);
|
|
186
|
+
if (match?.[1] !== undefined)
|
|
187
|
+
return match[1].replaceAll("_", "-");
|
|
188
|
+
}
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
function containerFromCgroupPath(path) {
|
|
192
|
+
const components = path.split("/").filter((component) => component !== "");
|
|
193
|
+
const underKubepods = components.some((component) => component === "kubepods" || component.includes("kubepods"));
|
|
194
|
+
for (let index = components.length - 1; index >= 0; index -= 1) {
|
|
195
|
+
const component = components[index];
|
|
196
|
+
let id;
|
|
197
|
+
let runtime;
|
|
198
|
+
for (const candidate of SCOPED_RUNTIMES) {
|
|
199
|
+
const match = candidate.pattern.exec(component);
|
|
200
|
+
if (match?.[1] !== undefined) {
|
|
201
|
+
id = match[1];
|
|
202
|
+
runtime = candidate.runtime;
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (id === undefined && new RegExp(`^${CONTAINER_ID}$`).test(component)) {
|
|
207
|
+
const parent = components[index - 1];
|
|
208
|
+
if (parent === "docker") {
|
|
209
|
+
id = component;
|
|
210
|
+
runtime = "docker";
|
|
211
|
+
}
|
|
212
|
+
else if (underKubepods) {
|
|
213
|
+
id = component;
|
|
214
|
+
runtime = "cri";
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (id === undefined || runtime === undefined)
|
|
218
|
+
continue;
|
|
219
|
+
if (runtime === "cri" || underKubepods) {
|
|
220
|
+
const podUid = podUidOf(components.slice(0, index));
|
|
221
|
+
return podUid === null ? { kind: "kubernetes-without-pod", containerId: id } : { kind: "kubernetes", podUid, containerId: id };
|
|
222
|
+
}
|
|
223
|
+
return runtime === "podman" ? { kind: "podman", container: id } : { kind: "docker", container: id };
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
function containerFromCgroup(cgroup) {
|
|
228
|
+
const lines = cgroup.split("\n").filter((line) => line.trim() !== "");
|
|
229
|
+
const ordered = [...lines.filter((line) => line.startsWith("0::")), ...lines.filter((line) => !line.startsWith("0::"))];
|
|
230
|
+
for (const line of ordered) {
|
|
231
|
+
const found = containerFromCgroupPath(line.slice(line.indexOf(":", line.indexOf(":") + 1) + 1));
|
|
232
|
+
if (found !== null)
|
|
233
|
+
return found;
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
const SHELL_SAFE = /^[A-Za-z0-9_/.:=@%+,-]+$/;
|
|
238
|
+
const SECRET_LOOKING_ARGUMENT_NAME = /(passw(or)?d|passwd|secret|token|api[-_]?key|apikey|auth|credential|private[-_]?key|access[-_]?key|(^|[-_])key($|[-_]))/i;
|
|
239
|
+
const URL_USERINFO_PASSWORD = /(:\/\/[^/\s:@]+:)[^/\s@]+@/g;
|
|
240
|
+
const REDACTED = "<redacted>";
|
|
241
|
+
function redactArgv(argv) {
|
|
242
|
+
const result = [];
|
|
243
|
+
let redacted = false;
|
|
244
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
245
|
+
const token = argv[index];
|
|
246
|
+
const assignment = /^(-{0,2}[A-Za-z_][A-Za-z0-9_.-]*)=(.*)$/s.exec(token);
|
|
247
|
+
if (assignment !== null) {
|
|
248
|
+
const [, name, value] = assignment;
|
|
249
|
+
if (SECRET_LOOKING_ARGUMENT_NAME.test(name) && value !== "") {
|
|
250
|
+
result.push(`${name}=${REDACTED}`);
|
|
251
|
+
redacted = true;
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
else if (/^-{1,2}[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(token) && SECRET_LOOKING_ARGUMENT_NAME.test(token)) {
|
|
256
|
+
result.push(token);
|
|
257
|
+
const next = argv[index + 1];
|
|
258
|
+
if (next !== undefined && !next.startsWith("-")) {
|
|
259
|
+
result.push(REDACTED);
|
|
260
|
+
redacted = true;
|
|
261
|
+
index += 1;
|
|
262
|
+
}
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const withoutUserinfo = token.replace(URL_USERINFO_PASSWORD, `$1${REDACTED}@`);
|
|
266
|
+
if (withoutUserinfo !== token)
|
|
267
|
+
redacted = true;
|
|
268
|
+
result.push(withoutUserinfo);
|
|
269
|
+
}
|
|
270
|
+
return { argv: result, redacted };
|
|
271
|
+
}
|
|
272
|
+
function shellQuote(word) {
|
|
273
|
+
return SHELL_SAFE.test(word) ? word : `'${word.replaceAll("'", "'\\''")}'`;
|
|
274
|
+
}
|
|
275
|
+
function restartAdvice(reader, pid) {
|
|
276
|
+
let command = null;
|
|
277
|
+
let redactedAny = false;
|
|
278
|
+
try {
|
|
279
|
+
const argv = reader
|
|
280
|
+
.readFile(`/proc/${String(pid)}/cmdline`)
|
|
281
|
+
.split("\0")
|
|
282
|
+
.filter((arg, index, all) => arg !== "" || index < all.length - 1);
|
|
283
|
+
if (argv.length > 0 && argv[0] !== "") {
|
|
284
|
+
const safe = redactArgv(argv);
|
|
285
|
+
redactedAny = safe.redacted;
|
|
286
|
+
command = safe.argv.map((word) => (word === REDACTED ? word : shellQuote(word))).join(" ");
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
command = null;
|
|
291
|
+
}
|
|
292
|
+
let cwd = null;
|
|
293
|
+
try {
|
|
294
|
+
const link = reader.readlink(`/proc/${String(pid)}/cwd`);
|
|
295
|
+
cwd = link.startsWith("/") ? link : null;
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
cwd = null;
|
|
299
|
+
}
|
|
300
|
+
const run = command === null ? "<the command you started it with>" : cwd === null ? command : `cd ${shellQuote(cwd)} && ${command}`;
|
|
301
|
+
return (`Restart it with its output in a file Descry can follow, then attach again: ${run} > descry-app.log 2>&1 ` +
|
|
302
|
+
(redactedAny ? `(values that look like secrets are shown as ${REDACTED}; put them back when you run it) ` : "") +
|
|
303
|
+
"(add `| tee` instead of `>` to keep seeing it in the terminal: ... 2>&1 | tee descry-app.log). " +
|
|
304
|
+
"Running it in a Docker or Podman container, a Kubernetes pod or a system service also works: Descry follows those logs itself.");
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* The system unit `pid` runs as, e.g. `myapp.service` from `0::/system.slice/myapp.service`.
|
|
308
|
+
* Only when that unit is the process's own cgroup leaf under `system.slice`: an app started
|
|
309
|
+
* from a desktop terminal sits under `user@1000.service/...`, the per-user manager, whose
|
|
310
|
+
* journal is every desktop app's output, and a user service's journal is not what
|
|
311
|
+
* `journalctl -u` reads. Either would attribute someone else's logs to the target, so
|
|
312
|
+
* both are `null` here and disclosed as unreadable rather than guessed.
|
|
313
|
+
*/
|
|
314
|
+
function systemdUnitFromCgroup(cgroup) {
|
|
315
|
+
for (const line of cgroup.split("\n")) {
|
|
316
|
+
const path = line.slice(line.indexOf(":", line.indexOf(":") + 1) + 1);
|
|
317
|
+
const match = /^\/system\.slice\/(?:[\w.@-]+\.slice\/)*([\w.@-]+\.service)$/.exec(path);
|
|
318
|
+
if (match?.[1] !== undefined)
|
|
319
|
+
return match[1];
|
|
320
|
+
}
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Where `pid`'s own log output can be read from, without the caller naming a
|
|
325
|
+
* pid or a log file. `file` reuses this repo's existing fenced file-tail path
|
|
326
|
+
* (`attachManagedProcess`/`attachToRunningProcess`) -- returned as a path for
|
|
327
|
+
* the caller to feed into that machinery, not re-implemented here.
|
|
328
|
+
* `docker`/`systemd` name a stream-only source `@descryy/runtime-orchestrator`
|
|
329
|
+
* builds directly -- neither has pre-existing content to fence, since both
|
|
330
|
+
* start reading from "now" (see `DiscoveredAttachLogSource`'s own doc,
|
|
331
|
+
* `@descryy/runtime-contracts`).
|
|
332
|
+
*/
|
|
333
|
+
export function resolveLogSourceForPid(pid, reader = REAL_PROC_READER, platform = process.platform) {
|
|
334
|
+
if (platform !== "linux") {
|
|
335
|
+
return { kind: "none", reason: `log-source discovery reads /proc, which is Linux-only; not available on "${platform}"` };
|
|
336
|
+
}
|
|
337
|
+
const filePath = fileTargetOf(reader, pid, 1) ?? fileTargetOf(reader, pid, 2);
|
|
338
|
+
if (filePath !== null)
|
|
339
|
+
return { kind: "file", path: filePath };
|
|
340
|
+
let cgroup;
|
|
341
|
+
try {
|
|
342
|
+
cgroup = reader.readFile(`/proc/${String(pid)}/cgroup`);
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
return {
|
|
346
|
+
kind: "none",
|
|
347
|
+
reason: `pid ${String(pid)}'s stdout/stderr is neither a regular file nor a terminal/pipe this process can name a container or service for, and its cgroup membership could not be read: ${error instanceof Error ? error.message : String(error)}`,
|
|
348
|
+
remediation: restartAdvice(reader, pid),
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
const container = containerFromCgroup(cgroup);
|
|
352
|
+
if (container?.kind === "kubernetes-without-pod") {
|
|
353
|
+
return {
|
|
354
|
+
kind: "none",
|
|
355
|
+
reason: `pid ${String(pid)} runs in Kubernetes container ${container.containerId}, but its cgroup path names no pod uid, so the pod whose logs those are cannot be named.`,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
if (container !== null)
|
|
359
|
+
return container;
|
|
360
|
+
const unit = systemdUnitFromCgroup(cgroup);
|
|
361
|
+
if (unit !== null)
|
|
362
|
+
return { kind: "systemd", unit };
|
|
363
|
+
return {
|
|
364
|
+
kind: "none",
|
|
365
|
+
reason: `pid ${String(pid)}'s stdout/stderr is a pipe or terminal, not a regular file -- another process cannot read it, and its cgroup names no Docker or Podman container, Kubernetes pod or systemd unit to follow instead.`,
|
|
366
|
+
remediation: restartAdvice(reader, pid),
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
const KUBECTL_TIMEOUT_MS = 15_000;
|
|
370
|
+
const KUBECTL_MAX_BUFFER = 64 * 1024 * 1024;
|
|
371
|
+
export const REAL_KUBECTL = (args) => new Promise((resolve) => {
|
|
372
|
+
execFile("kubectl", [...args], { timeout: KUBECTL_TIMEOUT_MS, maxBuffer: KUBECTL_MAX_BUFFER }, (error, stdout, stderr) => {
|
|
373
|
+
if (error !== null)
|
|
374
|
+
resolve({ ok: false, error: `${error.message}${stderr.trim() === "" ? "" : `: ${stderr.trim()}`}` });
|
|
375
|
+
else
|
|
376
|
+
resolve({ ok: true, stdout });
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
function statusesOf(value) {
|
|
380
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "object" && entry !== null) : [];
|
|
381
|
+
}
|
|
382
|
+
export async function resolveKubernetesContainer(podUid, containerId, kubectl = REAL_KUBECTL) {
|
|
383
|
+
const listed = await kubectl(["get", "pods", "--all-namespaces", "-o", "json"]);
|
|
384
|
+
if (!listed.ok) {
|
|
385
|
+
return { outcome: "unresolved", reason: `pod ${podUid}'s namespace and name come from \`kubectl get pods\`, which failed: ${listed.error}` };
|
|
386
|
+
}
|
|
387
|
+
let items;
|
|
388
|
+
try {
|
|
389
|
+
items = JSON.parse(listed.stdout).items;
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
return { outcome: "unresolved", reason: "the output of `kubectl get pods --all-namespaces -o json` could not be read as JSON" };
|
|
393
|
+
}
|
|
394
|
+
if (!Array.isArray(items))
|
|
395
|
+
return { outcome: "unresolved", reason: "the output of `kubectl get pods --all-namespaces -o json` could not be read: it has no items list" };
|
|
396
|
+
const pod = items.find((item) => typeof item === "object" && item !== null && item.metadata?.uid === podUid);
|
|
397
|
+
const namespace = pod?.metadata?.namespace;
|
|
398
|
+
const name = pod?.metadata?.name;
|
|
399
|
+
if (pod === undefined || typeof namespace !== "string" || typeof name !== "string") {
|
|
400
|
+
return { outcome: "unresolved", reason: `no pod with uid ${podUid} is listed in the current kubectl context, so the cluster running this process is not the one kubectl points at` };
|
|
401
|
+
}
|
|
402
|
+
const statuses = [pod.status?.containerStatuses, pod.status?.initContainerStatuses, pod.status?.ephemeralContainerStatuses].flatMap(statusesOf);
|
|
403
|
+
const container = statuses.find((status) => typeof status.containerID === "string" && status.containerID.replace(/^[a-z-]+:\/\//, "") === containerId);
|
|
404
|
+
if (container === undefined || typeof container.name !== "string") {
|
|
405
|
+
return { outcome: "unresolved", reason: `pod ${namespace}/${name} lists no container with id ${containerId}` };
|
|
406
|
+
}
|
|
407
|
+
return { outcome: "found", namespace, pod: name, container: container.name };
|
|
408
|
+
}
|
|
409
|
+
//# sourceMappingURL=attach-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attach-discovery.js","sourceRoot":"","sources":["../src/attach-discovery.ts"],"names":[],"mappings":"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"}
|
package/dist/attach-fencing.d.ts
CHANGED
|
@@ -98,6 +98,7 @@ export interface AttachFence {
|
|
|
98
98
|
/** See `detectOtherLogWriters` — computed once, at the moment of attach, against the pid this fence was built for. */
|
|
99
99
|
readonly otherWriters: OtherLogWriterCheck;
|
|
100
100
|
readonly attachedAt: string;
|
|
101
|
+
readonly backlogUnavailableReason?: string;
|
|
101
102
|
}
|
|
102
103
|
/**
|
|
103
104
|
* Snapshots the fence at the moment of attach. Never throws: a log file that
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attach-fencing.d.ts","sourceRoot":"","sources":["../src/attach-fencing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;
|
|
1
|
+
{"version":3,"file":"attach-fencing.d.ts","sourceRoot":"","sources":["../src/attach-fencing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAgCH,MAAM,MAAM,sBAAsB,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAwB3I;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,sBAAsB,CAiCvH;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACvE;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,mBAAmB,CA+C/I;AAED,MAAM,WAAW,WAAW;IAC1B,4JAA4J;IAC5J,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,mHAAmH;IACnH,QAAQ,CAAC,gBAAgB,EAAE,sBAAsB,CAAC;IAClD,sHAAsH;IACtH,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAC;CAC5C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,WAAW,CA4B9H"}
|