systemd-ts 0.3.1 → 0.3.3
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/index-DeNBLyGA.d.mts +2 -1
- package/dist/index-DeNBLyGA.d.mts.map +1 -0
- package/dist/main-BXq7TQdg.mjs +2 -0
- package/dist/main-BXq7TQdg.mjs.map +1 -0
- package/dist/test.d.mts +2 -1
- package/dist/test.d.mts.map +1 -0
- package/dist/test.mjs +2 -0
- package/dist/test.mjs.map +1 -0
- package/package.json +4 -3
- package/src/main/errors.ts +348 -0
- package/src/main/executable.ts +175 -0
- package/src/main/index.ts +76 -0
- package/src/main/internal.ts +406 -0
- package/src/main/notify.ts +67 -0
- package/src/main/systemctl.ts +326 -0
- package/src/main/systemd-service.ts +80 -0
- package/src/main/systemd-timer.ts +80 -0
- package/src/main/systemd.ts +991 -0
- package/src/main/types.ts +1231 -0
- package/src/test/harness.ts +107 -0
- package/src/test/host.ts +676 -0
- package/src/test/index.ts +17 -0
- package/src/test/sandbox.ts +94 -0
- package/src/test/systemd-container.Dockerfile +30 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import { getTestHostInfo, runGuestCommand } from "./host.ts";
|
|
4
|
+
|
|
5
|
+
export interface TestSandbox {
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly linkedUnitDir: string;
|
|
8
|
+
readonly namePrefix: string;
|
|
9
|
+
readonly rootDir: string;
|
|
10
|
+
readonly workDir: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface DestroyTestSandboxOptions {
|
|
14
|
+
readonly noisy?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let currentSandbox: TestSandbox | undefined;
|
|
18
|
+
|
|
19
|
+
export async function createTestSandbox(testName?: string): Promise<TestSandbox> {
|
|
20
|
+
const id = randomUUID().slice(0, 8);
|
|
21
|
+
const slug = slugify(testName ?? `sandbox`);
|
|
22
|
+
const namePrefix = `systemd-ts-${slug}-${id}`;
|
|
23
|
+
const rootDir = `${getTestHostInfo().stateRoot}/tests/${namePrefix}`;
|
|
24
|
+
const linkedUnitDir = `${rootDir}/linked-units`;
|
|
25
|
+
const workDir = `${rootDir}/work`;
|
|
26
|
+
|
|
27
|
+
await runGuestCommand(
|
|
28
|
+
`set -euo pipefail
|
|
29
|
+
rm -rf ${shellQuote(rootDir)}
|
|
30
|
+
mkdir -p ${shellQuote(linkedUnitDir)} ${shellQuote(workDir)}`,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
currentSandbox = {
|
|
34
|
+
id,
|
|
35
|
+
linkedUnitDir,
|
|
36
|
+
namePrefix,
|
|
37
|
+
rootDir,
|
|
38
|
+
workDir,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return currentSandbox;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function destroyCurrentTestSandbox(): Promise<void> {
|
|
45
|
+
if (currentSandbox === undefined) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const sandbox = currentSandbox;
|
|
50
|
+
currentSandbox = undefined;
|
|
51
|
+
|
|
52
|
+
const unitsOutput = await runGuestCommand(
|
|
53
|
+
`systemctl --user list-unit-files --all --no-legend ${shellQuote(`${sandbox.namePrefix}*`)} 2>/dev/null | awk '{print $1}' || true`,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const units = unitsOutput
|
|
57
|
+
.split(`\n`)
|
|
58
|
+
.map((unit) => unit.trim())
|
|
59
|
+
.filter((unit) => unit.length > 0);
|
|
60
|
+
|
|
61
|
+
if (units.length > 0) {
|
|
62
|
+
await runGuestCommand(`systemctl --user stop ${units.map(shellQuote).join(` `)} || true`);
|
|
63
|
+
|
|
64
|
+
await runGuestCommand(`systemctl --user disable ${units.map(shellQuote).join(` `)} || true`);
|
|
65
|
+
|
|
66
|
+
await runGuestCommand(
|
|
67
|
+
`systemctl --user reset-failed ${units.map(shellQuote).join(` `)} || true`,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
await runGuestCommand(`systemctl --user daemon-reload || true`);
|
|
72
|
+
|
|
73
|
+
await runGuestCommand(`rm -rf ${shellQuote(sandbox.rootDir)}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function useCurrentTestSandbox(): TestSandbox {
|
|
77
|
+
if (currentSandbox === undefined) {
|
|
78
|
+
throw new Error(`No active test sandbox is available`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return currentSandbox;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function shellQuote(value: string): string {
|
|
85
|
+
return `'${value.replaceAll(`'`, `'\\''`)}'`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function slugify(value: string): string {
|
|
89
|
+
return value
|
|
90
|
+
.toLowerCase()
|
|
91
|
+
.replaceAll(/[^a-z0-9]+/g, `-`)
|
|
92
|
+
.replaceAll(/^-+|-+$/g, ``)
|
|
93
|
+
.slice(0, 32);
|
|
94
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
FROM ubuntu:26.04
|
|
2
|
+
|
|
3
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
4
|
+
|
|
5
|
+
RUN apt-get update \
|
|
6
|
+
&& apt-get install --yes --no-install-recommends \
|
|
7
|
+
bash \
|
|
8
|
+
ca-certificates \
|
|
9
|
+
coreutils \
|
|
10
|
+
dbus \
|
|
11
|
+
dbus-user-session \
|
|
12
|
+
findutils \
|
|
13
|
+
gawk \
|
|
14
|
+
grep \
|
|
15
|
+
procps \
|
|
16
|
+
python3 \
|
|
17
|
+
sudo \
|
|
18
|
+
systemd \
|
|
19
|
+
systemd-sysv \
|
|
20
|
+
util-linux \
|
|
21
|
+
&& apt-get clean \
|
|
22
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
23
|
+
|
|
24
|
+
RUN useradd --create-home --shell /bin/bash runner \
|
|
25
|
+
&& printf 'runner ALL=(ALL) NOPASSWD:ALL\n' >/etc/sudoers.d/runner \
|
|
26
|
+
&& chmod 0440 /etc/sudoers.d/runner
|
|
27
|
+
|
|
28
|
+
STOPSIGNAL SIGRTMIN+3
|
|
29
|
+
|
|
30
|
+
CMD ["/sbin/init"]
|