@glassmkr/crucible 0.8.1 → 0.9.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 +92 -26
- package/dist/__tests__/cli.test.js +42 -0
- package/dist/__tests__/cli.test.js.map +1 -1
- package/dist/__tests__/init.test.d.ts +1 -0
- package/dist/__tests__/init.test.js +187 -0
- package/dist/__tests__/init.test.js.map +1 -0
- package/dist/cli.d.ts +12 -1
- package/dist/cli.js +91 -0
- package/dist/cli.js.map +1 -1
- package/dist/collect/ipmi.js +8 -1
- package/dist/collect/ipmi.js.map +1 -1
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +60 -0
- package/dist/init.js +254 -0
- package/dist/init.js.map +1 -0
- package/dist/lib/__tests__/ipmi-sensor-filter.test.d.ts +1 -0
- package/dist/lib/__tests__/ipmi-sensor-filter.test.js +85 -0
- package/dist/lib/__tests__/ipmi-sensor-filter.test.js.map +1 -0
- package/dist/lib/ipmi-sensor-filter.d.ts +11 -0
- package/dist/lib/ipmi-sensor-filter.js +74 -0
- package/dist/lib/ipmi-sensor-filter.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
[](LICENSE)
|
|
4
4
|
[](https://www.npmjs.com/package/@glassmkr/crucible)
|
|
5
5
|
|
|
6
|
+
<!-- Canonical rule count: see RULES_COUNT.md in the Glassmkr monorepo. -->
|
|
6
7
|
Lightweight bare metal server monitoring agent. Collects hardware and OS health every 5 minutes and pushes snapshots to a [Forge](https://forge.glassmkr.com) dashboard, which evaluates 38 alert rules and sends notifications.
|
|
7
8
|
|
|
8
9
|
Open source. MIT licensed. Built by [Glassmkr](https://glassmkr.com). See also [Bench](https://github.com/glassmkr/bench), the MCP server collection.
|
|
@@ -24,16 +25,27 @@ Open source. MIT licensed. Built by [Glassmkr](https://glassmkr.com). See also [
|
|
|
24
25
|
|
|
25
26
|
## Install
|
|
26
27
|
|
|
28
|
+
The fastest path: bootstrap script. Detects Node and npm, installs the
|
|
29
|
+
agent, and runs `glassmkr-crucible init` to validate your key, write
|
|
30
|
+
`/etc/glassmkr/collector.yaml`, write the systemd unit, and start the
|
|
31
|
+
service.
|
|
32
|
+
|
|
27
33
|
```bash
|
|
28
|
-
|
|
34
|
+
curl -sf https://forge.glassmkr.com/install | bash -s -- --api-key gmk_cru_live_<your-key>
|
|
29
35
|
```
|
|
30
36
|
|
|
31
|
-
Or
|
|
37
|
+
Or run the steps yourself:
|
|
32
38
|
|
|
33
39
|
```bash
|
|
34
|
-
|
|
40
|
+
sudo npm install -g @glassmkr/crucible
|
|
41
|
+
sudo glassmkr-crucible init --api-key gmk_cru_live_<your-key>
|
|
35
42
|
```
|
|
36
43
|
|
|
44
|
+
`init` is the canonical first-run path. It validates the key shape,
|
|
45
|
+
optionally probes the ingest endpoint, writes config + systemd unit
|
|
46
|
+
with the right binary path for your distro, and enables the service.
|
|
47
|
+
Run `glassmkr-crucible init --help` for the full flag list.
|
|
48
|
+
|
|
37
49
|
## Docker
|
|
38
50
|
|
|
39
51
|
```bash
|
|
@@ -65,33 +77,31 @@ Images are published to [ghcr.io/glassmkr/crucible](https://github.com/glassmkr/
|
|
|
65
77
|
|
|
66
78
|
## Quick Start
|
|
67
79
|
|
|
68
|
-
1. Create an API key in the Forge dashboard (Servers
|
|
69
|
-
2.
|
|
70
|
-
|
|
71
|
-
```yaml
|
|
72
|
-
server_name: "web-01"
|
|
73
|
-
collection:
|
|
74
|
-
interval_seconds: 300
|
|
75
|
-
ipmi: true
|
|
76
|
-
smart: true
|
|
77
|
-
forge:
|
|
78
|
-
enabled: true
|
|
79
|
-
url: "https://forge.glassmkr.com"
|
|
80
|
-
api_key: "col_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
3. Run as a systemd service (recommended) or directly:
|
|
80
|
+
1. Create an API key in the Forge dashboard (Servers → Add server).
|
|
81
|
+
2. Run `init`:
|
|
84
82
|
|
|
85
83
|
```bash
|
|
86
|
-
sudo glassmkr-crucible
|
|
84
|
+
sudo glassmkr-crucible init --api-key gmk_cru_live_<your-key>
|
|
87
85
|
```
|
|
88
86
|
|
|
89
|
-
|
|
87
|
+
This writes `/etc/glassmkr/collector.yaml`, writes the systemd unit,
|
|
88
|
+
and starts the service. Pass `--name` to override the dashboard
|
|
89
|
+
server name (defaults to the host's hostname). Pass `--no-start` if
|
|
90
|
+
you want to inspect the unit before enabling it. Pass `--api-key -`
|
|
91
|
+
to read the key from stdin (handy for password-manager pipes).
|
|
92
|
+
|
|
93
|
+
Snapshots appear in the Forge dashboard within seconds of the first
|
|
94
|
+
push.
|
|
95
|
+
|
|
96
|
+
If you can't or won't run `init` (config-management is doing it for
|
|
97
|
+
you, or you're customising the systemd unit), the manual flow is in
|
|
98
|
+
the **Manual install** section below.
|
|
90
99
|
|
|
91
100
|
## CLI Reference
|
|
92
101
|
|
|
93
102
|
```
|
|
94
103
|
glassmkr-crucible [options]
|
|
104
|
+
glassmkr-crucible init --api-key <K> [--name <N>] [--ingest-url <U>] [--no-start] [--force] [--no-verify]
|
|
95
105
|
glassmkr-crucible mark-reboot [--reason TEXT] [--ttl DURATION]
|
|
96
106
|
glassmkr-crucible reboot [--reason TEXT] [--ttl DURATION]
|
|
97
107
|
|
|
@@ -103,6 +113,39 @@ Options:
|
|
|
103
113
|
|
|
104
114
|
`--config=PATH` and the legacy positional form `glassmkr-crucible /path/to.yaml` both work. Without options, Crucible runs as a long-lived collector daemon.
|
|
105
115
|
|
|
116
|
+
## Configuration
|
|
117
|
+
|
|
118
|
+
`init` writes `/etc/glassmkr/collector.yaml`. The schema:
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
server_name: "web-01"
|
|
122
|
+
collection:
|
|
123
|
+
interval_seconds: 300
|
|
124
|
+
ipmi: true
|
|
125
|
+
smart: true
|
|
126
|
+
forge:
|
|
127
|
+
enabled: true
|
|
128
|
+
url: "https://forge.glassmkr.com"
|
|
129
|
+
api_key: "gmk_cru_live_<...>_<4>"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Hand-edit any time. The agent re-reads on restart. Run
|
|
133
|
+
`glassmkr-crucible init --help` for the full flag list.
|
|
134
|
+
|
|
135
|
+
### Migrating from a manual install
|
|
136
|
+
|
|
137
|
+
Existing 0.9.0 installs with a hand-written `collector.yaml` and
|
|
138
|
+
systemd unit continue working unchanged on 0.9.1. No migration is
|
|
139
|
+
required.
|
|
140
|
+
|
|
141
|
+
For new boxes, prefer `init`. To migrate an existing manual install
|
|
142
|
+
to the canonical layout, stop the service, run `init --force`, restart:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
sudo systemctl stop glassmkr-crucible
|
|
146
|
+
sudo glassmkr-crucible init --api-key <K> --force
|
|
147
|
+
```
|
|
148
|
+
|
|
106
149
|
## Rebooting without noise
|
|
107
150
|
|
|
108
151
|
Crucible distinguishes planned reboots from unplanned ones and gives each rule a short grace period after boot so that transient conditions (bond slave still negotiating, clock not synced yet) do not page you.
|
|
@@ -126,11 +169,27 @@ The marker is single-use and expires 10 minutes after it is written (override wi
|
|
|
126
169
|
|
|
127
170
|
Per-rule grace windows are applied separately: bond-slave-down and CPU-temperature get 60 s, interface errors 120 s, clock-sync / NTP 300 s, others 0 s. Suppressed evaluations are recorded in alert history with status `suppressed_boot_grace` or `suppressed_planned_reboot` so you can audit exactly why a rule didn't fire during a given boot.
|
|
128
171
|
|
|
129
|
-
##
|
|
172
|
+
## Manual install
|
|
173
|
+
|
|
174
|
+
The canonical install path is `glassmkr-crucible init` (see "Install"
|
|
175
|
+
above). For ops engineers writing config-management modules, `init`
|
|
176
|
+
gives you a stable interface that's covered by the test suite; prefer
|
|
177
|
+
it over hand-rolling the equivalent.
|
|
130
178
|
|
|
131
|
-
|
|
179
|
+
If you need or want to do this by hand, the npm prefix differs across
|
|
180
|
+
distros: Ubuntu's global npm puts binaries in `/usr/bin/`, while
|
|
181
|
+
Debian's defaults to `/usr/local/bin/`. The systemd unit's
|
|
182
|
+
`ExecStart` must point at wherever `glassmkr-crucible` actually landed
|
|
183
|
+
on your host, so detect the path before writing the unit:
|
|
132
184
|
|
|
133
|
-
```
|
|
185
|
+
```bash
|
|
186
|
+
BIN_PATH=$(command -v glassmkr-crucible)
|
|
187
|
+
if [ -z "$BIN_PATH" ]; then
|
|
188
|
+
echo "ERROR: glassmkr-crucible binary not found on PATH after npm install. Aborting." >&2
|
|
189
|
+
exit 1
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
sudo tee /etc/systemd/system/glassmkr-crucible.service >/dev/null <<UNIT
|
|
134
193
|
[Unit]
|
|
135
194
|
Description=Glassmkr Crucible - Bare Metal Monitoring
|
|
136
195
|
After=network.target
|
|
@@ -138,12 +197,13 @@ After=network.target
|
|
|
138
197
|
[Service]
|
|
139
198
|
Type=simple
|
|
140
199
|
User=root
|
|
141
|
-
ExecStart
|
|
200
|
+
ExecStart=$BIN_PATH /etc/glassmkr/collector.yaml
|
|
142
201
|
Restart=on-failure
|
|
143
202
|
RestartSec=10
|
|
144
203
|
|
|
145
204
|
[Install]
|
|
146
205
|
WantedBy=multi-user.target
|
|
206
|
+
UNIT
|
|
147
207
|
```
|
|
148
208
|
|
|
149
209
|
Enable and start:
|
|
@@ -154,6 +214,11 @@ sudo systemctl enable --now glassmkr-crucible
|
|
|
154
214
|
sudo systemctl status glassmkr-crucible
|
|
155
215
|
```
|
|
156
216
|
|
|
217
|
+
If you ever upgrade `@glassmkr/crucible` and the binary moves (rare, but
|
|
218
|
+
possible on a distro change), re-run the `command -v` step and update the
|
|
219
|
+
unit file. The bootstrap script at `https://forge.glassmkr.com/install` does
|
|
220
|
+
this detection automatically; the manual flow above is just the equivalent.
|
|
221
|
+
|
|
157
222
|
## What It Collects
|
|
158
223
|
|
|
159
224
|
| Module | Data |
|
|
@@ -173,6 +238,7 @@ sudo systemctl status glassmkr-crucible
|
|
|
173
238
|
| NTP | Sync state and source |
|
|
174
239
|
| File descriptors | System-wide allocation |
|
|
175
240
|
|
|
241
|
+
<!-- Canonical rule count: see RULES_COUNT.md in the Glassmkr monorepo. -->
|
|
176
242
|
Forge evaluates 38 alert rules server-side across OS, Storage, Network, Hardware, ZFS, Security, and Service Health, with priorities P1 Urgent through P4 Low. Full list: [forge.glassmkr.com/docs/alerts](https://forge.glassmkr.com/docs/alerts).
|
|
177
243
|
|
|
178
244
|
## Requirements
|
|
@@ -186,7 +252,7 @@ Forge evaluates 38 alert rules server-side across OS, Storage, Network, Hardware
|
|
|
186
252
|
|
|
187
253
|
- [Getting Started](https://forge.glassmkr.com/docs/getting-started)
|
|
188
254
|
- [Configuration Reference](https://forge.glassmkr.com/docs/configuration)
|
|
189
|
-
- [Alert Rules (
|
|
255
|
+
- [Alert Rules (38)](https://forge.glassmkr.com/docs/alerts)
|
|
190
256
|
- [Troubleshooting](https://forge.glassmkr.com/docs/troubleshooting)
|
|
191
257
|
- [API Reference](https://forge.glassmkr.com/docs/api)
|
|
192
258
|
|
|
@@ -60,5 +60,47 @@ describe("helpText", () => {
|
|
|
60
60
|
expect(txt).toContain("-h, --help");
|
|
61
61
|
expect(txt).toContain("-c, --config");
|
|
62
62
|
});
|
|
63
|
+
it("lists init in the subcommands section", () => {
|
|
64
|
+
const txt = helpText("0.9.1");
|
|
65
|
+
expect(txt).toContain("init");
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe("init subcommand parsing", () => {
|
|
69
|
+
it("init --api-key K -> mode=init with the key captured", () => {
|
|
70
|
+
const { result } = parseCliArgs(["init", "--api-key", "gmk_cru_live_abc"], "0.9.1");
|
|
71
|
+
expect(result.mode).toBe("init");
|
|
72
|
+
expect(result.init?.apiKey).toBe("gmk_cru_live_abc");
|
|
73
|
+
expect(result.init?.noStart).toBe(false);
|
|
74
|
+
expect(result.init?.force).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
it("init --api-key=K equals form works", () => {
|
|
77
|
+
const { result } = parseCliArgs(["init", "--api-key=col_xyz"], "0.9.1");
|
|
78
|
+
expect(result.init?.apiKey).toBe("col_xyz");
|
|
79
|
+
});
|
|
80
|
+
it("init --api-key - (stdin marker) is preserved as the literal -", () => {
|
|
81
|
+
const { result } = parseCliArgs(["init", "--api-key", "-"], "0.9.1");
|
|
82
|
+
expect(result.init?.apiKey).toBe("-");
|
|
83
|
+
});
|
|
84
|
+
it("init --no-start --force --no-verify flags toggle correctly", () => {
|
|
85
|
+
const { result } = parseCliArgs(["init", "--api-key", "k", "--no-start", "--force", "--no-verify"], "0.9.1");
|
|
86
|
+
expect(result.init?.noStart).toBe(true);
|
|
87
|
+
expect(result.init?.force).toBe(true);
|
|
88
|
+
expect(result.init?.noVerify).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
it("init --name and --ingest-url and --config-path are captured", () => {
|
|
91
|
+
const { result } = parseCliArgs([
|
|
92
|
+
"init", "--api-key", "k", "--name", "web-01", "--ingest-url", "https://forge.example.com/api/v1/ingest", "--config-path", "/etc/x.yaml",
|
|
93
|
+
], "0.9.1");
|
|
94
|
+
expect(result.init?.name).toBe("web-01");
|
|
95
|
+
expect(result.init?.ingestUrl).toBe("https://forge.example.com/api/v1/ingest");
|
|
96
|
+
expect(result.init?.configPath).toBe("/etc/x.yaml");
|
|
97
|
+
});
|
|
98
|
+
it("init --help returns help text instead of running init", () => {
|
|
99
|
+
const { result, output } = parseCliArgs(["init", "--help"], "0.9.1");
|
|
100
|
+
expect(result.mode).toBe("help");
|
|
101
|
+
expect(output).toContain("glassmkr-crucible init");
|
|
102
|
+
expect(output).toContain("--api-key");
|
|
103
|
+
expect(output).toContain("--no-start");
|
|
104
|
+
});
|
|
63
105
|
});
|
|
64
106
|
//# sourceMappingURL=cli.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../src/__tests__/cli.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../src/__tests__/cli.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
+
import { runInit, isValidApiKey, buildCollectorYaml, buildSystemdUnit, SYSTEMD_UNIT_PATH } from "../init.js";
|
|
3
|
+
const VALID_NEW_KEY = "gmk_cru_live_abcdefghijklmnopqrstuvwx_a1b2";
|
|
4
|
+
const VALID_LEGACY_KEY = "col_abcdef0123456789abcdef0123456789ab";
|
|
5
|
+
function makeDeps(opts) {
|
|
6
|
+
const fs = { files: new Map(), dirs: new Set() };
|
|
7
|
+
for (const f of opts?.preExistingFiles ?? [])
|
|
8
|
+
fs.files.set(f, { data: "stale", mode: 0o600 });
|
|
9
|
+
const logs = [];
|
|
10
|
+
const warns = [];
|
|
11
|
+
const errors = [];
|
|
12
|
+
const systemctlCalls = [];
|
|
13
|
+
const deps = {
|
|
14
|
+
fs: {
|
|
15
|
+
existsSync: (p) => fs.files.has(p),
|
|
16
|
+
mkdirSync: (p) => { fs.dirs.add(p); },
|
|
17
|
+
writeFileSync: (p, data, o) => { fs.files.set(p, { data, mode: o?.mode ?? 0o644 }); },
|
|
18
|
+
chmodSync: (p, mode) => {
|
|
19
|
+
const f = fs.files.get(p);
|
|
20
|
+
if (f)
|
|
21
|
+
f.mode = mode;
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
exec: (cmd, args) => {
|
|
25
|
+
if (cmd === "command" && args[0] === "-v" && args[1] === "glassmkr-crucible") {
|
|
26
|
+
return { stdout: opts?.binPath === null ? "" : `${opts?.binPath ?? "/usr/local/bin/glassmkr-crucible"}\n`, status: 0 };
|
|
27
|
+
}
|
|
28
|
+
if (cmd === "which" && args[0] === "glassmkr-crucible") {
|
|
29
|
+
return { stdout: opts?.binPath === null ? "" : `${opts?.binPath ?? "/usr/local/bin/glassmkr-crucible"}\n`, status: 0 };
|
|
30
|
+
}
|
|
31
|
+
if (cmd === "systemctl") {
|
|
32
|
+
systemctlCalls.push(args);
|
|
33
|
+
return { stdout: "", status: opts?.systemctlExitCode ?? 0 };
|
|
34
|
+
}
|
|
35
|
+
return { stdout: "", status: 0 };
|
|
36
|
+
},
|
|
37
|
+
hostname: () => "test-host-01",
|
|
38
|
+
log: (m) => logs.push(m),
|
|
39
|
+
warn: (m) => warns.push(m),
|
|
40
|
+
error: (m) => errors.push(m),
|
|
41
|
+
fetch: async () => {
|
|
42
|
+
if (opts?.fetchThrows)
|
|
43
|
+
throw new Error("network down");
|
|
44
|
+
return { status: opts?.fetchStatus ?? 200 };
|
|
45
|
+
},
|
|
46
|
+
readStdin: async () => opts?.stdin ?? "",
|
|
47
|
+
};
|
|
48
|
+
return { deps, fs, logs, warns, errors, systemctlCalls };
|
|
49
|
+
}
|
|
50
|
+
describe("isValidApiKey", () => {
|
|
51
|
+
it("accepts the new gmk_cru_live_<...>_<4> format", () => {
|
|
52
|
+
expect(isValidApiKey(VALID_NEW_KEY)).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
it("accepts the legacy col_<hex> format", () => {
|
|
55
|
+
expect(isValidApiKey(VALID_LEGACY_KEY)).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
it("rejects forge_ session tokens", () => {
|
|
58
|
+
expect(isValidApiKey("forge_abc123")).toBe(false);
|
|
59
|
+
});
|
|
60
|
+
it("rejects random strings", () => {
|
|
61
|
+
expect(isValidApiKey("just-some-string")).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
it("rejects empty / whitespace", () => {
|
|
64
|
+
expect(isValidApiKey("")).toBe(false);
|
|
65
|
+
expect(isValidApiKey(" ")).toBe(false);
|
|
66
|
+
expect(isValidApiKey("gmk_cru_live_abc def_1234")).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe("buildCollectorYaml", () => {
|
|
70
|
+
it("emits a parseable YAML with name, url, key", () => {
|
|
71
|
+
const y = buildCollectorYaml("web-01", "https://forge.glassmkr.com/api/v1/ingest", VALID_NEW_KEY);
|
|
72
|
+
expect(y).toContain('server_name: "web-01"');
|
|
73
|
+
expect(y).toContain('url: "https://forge.glassmkr.com"');
|
|
74
|
+
expect(y).toContain(`api_key: "${VALID_NEW_KEY}"`);
|
|
75
|
+
});
|
|
76
|
+
it("strips /api/v1/ingest from the URL when present", () => {
|
|
77
|
+
const y = buildCollectorYaml("h", "https://forge.example.com/api/v1/ingest", VALID_NEW_KEY);
|
|
78
|
+
expect(y).toContain('url: "https://forge.example.com"');
|
|
79
|
+
expect(y).not.toContain("/api/v1/ingest");
|
|
80
|
+
});
|
|
81
|
+
it("escapes embedded double quotes in name", () => {
|
|
82
|
+
const y = buildCollectorYaml('we"ird', "https://x", VALID_NEW_KEY);
|
|
83
|
+
expect(y).toContain('server_name: "we\\"ird"');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe("buildSystemdUnit", () => {
|
|
87
|
+
it("references the dynamic binary path with the config path", () => {
|
|
88
|
+
const u = buildSystemdUnit("/usr/local/bin/glassmkr-crucible", "/etc/glassmkr/collector.yaml");
|
|
89
|
+
expect(u).toContain("ExecStart=/usr/local/bin/glassmkr-crucible /etc/glassmkr/collector.yaml");
|
|
90
|
+
expect(u).toContain("Type=simple");
|
|
91
|
+
expect(u).toContain("Restart=always");
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe("runInit", () => {
|
|
95
|
+
let configPath;
|
|
96
|
+
beforeEach(() => { configPath = "/tmp/init-test-collector.yaml"; });
|
|
97
|
+
it("rejects malformed --api-key with exit code 2", async () => {
|
|
98
|
+
const { deps, errors } = makeDeps();
|
|
99
|
+
const code = await runInit({ apiKey: "nope", configPath, noVerify: true }, deps);
|
|
100
|
+
expect(code).toBe(2);
|
|
101
|
+
expect(errors[0]).toContain("invalid --api-key");
|
|
102
|
+
});
|
|
103
|
+
it("happy path: writes config (0600) + systemd unit (0644), enables service", async () => {
|
|
104
|
+
const { deps, fs, systemctlCalls } = makeDeps();
|
|
105
|
+
const code = await runInit({ apiKey: VALID_NEW_KEY, configPath, noVerify: true }, deps);
|
|
106
|
+
expect(code).toBe(0);
|
|
107
|
+
const yaml = fs.files.get(configPath);
|
|
108
|
+
expect(yaml?.mode).toBe(0o600);
|
|
109
|
+
expect(yaml?.data).toContain(VALID_NEW_KEY);
|
|
110
|
+
const unit = fs.files.get(SYSTEMD_UNIT_PATH);
|
|
111
|
+
expect(unit?.mode).toBe(0o644);
|
|
112
|
+
expect(unit?.data).toContain("ExecStart=/usr/local/bin/glassmkr-crucible /tmp/init-test-collector.yaml");
|
|
113
|
+
expect(systemctlCalls).toContainEqual(["daemon-reload"]);
|
|
114
|
+
expect(systemctlCalls).toContainEqual(["enable", "--now", "glassmkr-crucible"]);
|
|
115
|
+
});
|
|
116
|
+
it("--no-start: skips enable but still daemon-reloads", async () => {
|
|
117
|
+
const { deps, systemctlCalls } = makeDeps();
|
|
118
|
+
const code = await runInit({ apiKey: VALID_NEW_KEY, configPath, noVerify: true, noStart: true }, deps);
|
|
119
|
+
expect(code).toBe(0);
|
|
120
|
+
expect(systemctlCalls).toContainEqual(["daemon-reload"]);
|
|
121
|
+
expect(systemctlCalls.find((c) => c[0] === "enable")).toBeUndefined();
|
|
122
|
+
});
|
|
123
|
+
it("refuses to overwrite an existing config without --force", async () => {
|
|
124
|
+
const { deps, errors } = makeDeps({ preExistingFiles: [configPath] });
|
|
125
|
+
const code = await runInit({ apiKey: VALID_NEW_KEY, configPath, noVerify: true }, deps);
|
|
126
|
+
expect(code).toBe(4);
|
|
127
|
+
expect(errors[0]).toContain("config already exists");
|
|
128
|
+
});
|
|
129
|
+
it("--force overwrites an existing config", async () => {
|
|
130
|
+
const { deps, fs } = makeDeps({ preExistingFiles: [configPath] });
|
|
131
|
+
const code = await runInit({ apiKey: VALID_NEW_KEY, configPath, noVerify: true, force: true }, deps);
|
|
132
|
+
expect(code).toBe(0);
|
|
133
|
+
expect(fs.files.get(configPath)?.data).toContain(VALID_NEW_KEY);
|
|
134
|
+
});
|
|
135
|
+
it("reads --api-key from stdin when value is '-'", async () => {
|
|
136
|
+
const { deps, fs } = makeDeps({ stdin: VALID_LEGACY_KEY + "\n" });
|
|
137
|
+
const code = await runInit({ apiKey: "-", configPath, noVerify: true }, deps);
|
|
138
|
+
expect(code).toBe(0);
|
|
139
|
+
expect(fs.files.get(configPath)?.data).toContain(VALID_LEGACY_KEY);
|
|
140
|
+
});
|
|
141
|
+
it("aborts when binary not on PATH (exit code 7)", async () => {
|
|
142
|
+
const { deps, errors } = makeDeps({ binPath: null });
|
|
143
|
+
const code = await runInit({ apiKey: VALID_NEW_KEY, configPath, noVerify: true }, deps);
|
|
144
|
+
expect(code).toBe(7);
|
|
145
|
+
expect(errors[errors.length - 1]).toContain("could not locate the glassmkr-crucible binary");
|
|
146
|
+
});
|
|
147
|
+
it("connectivity probe: 401 from ingest endpoint -> exit code 3", async () => {
|
|
148
|
+
const { deps, errors } = makeDeps({ fetchStatus: 401 });
|
|
149
|
+
const code = await runInit({ apiKey: VALID_NEW_KEY, configPath }, deps);
|
|
150
|
+
expect(code).toBe(3);
|
|
151
|
+
expect(errors[0]).toContain("api key rejected");
|
|
152
|
+
});
|
|
153
|
+
it("connectivity probe: 5xx warns but continues", async () => {
|
|
154
|
+
const { deps, warns } = makeDeps({ fetchStatus: 502 });
|
|
155
|
+
const code = await runInit({ apiKey: VALID_NEW_KEY, configPath }, deps);
|
|
156
|
+
expect(code).toBe(0);
|
|
157
|
+
expect(warns.some((w) => w.includes("502"))).toBe(true);
|
|
158
|
+
});
|
|
159
|
+
it("connectivity probe: network error warns and continues", async () => {
|
|
160
|
+
const { deps, warns } = makeDeps({ fetchThrows: true });
|
|
161
|
+
const code = await runInit({ apiKey: VALID_NEW_KEY, configPath }, deps);
|
|
162
|
+
expect(code).toBe(0);
|
|
163
|
+
expect(warns.some((w) => w.includes("connectivity probe failed"))).toBe(true);
|
|
164
|
+
});
|
|
165
|
+
it("--name overrides hostname", async () => {
|
|
166
|
+
const { deps, fs } = makeDeps();
|
|
167
|
+
await runInit({ apiKey: VALID_NEW_KEY, name: "custom-name", configPath, noVerify: true }, deps);
|
|
168
|
+
expect(fs.files.get(configPath)?.data).toContain('server_name: "custom-name"');
|
|
169
|
+
});
|
|
170
|
+
it("falls back to hostname when --name not provided", async () => {
|
|
171
|
+
const { deps, fs } = makeDeps();
|
|
172
|
+
await runInit({ apiKey: VALID_NEW_KEY, configPath, noVerify: true }, deps);
|
|
173
|
+
expect(fs.files.get(configPath)?.data).toContain('server_name: "test-host-01"');
|
|
174
|
+
});
|
|
175
|
+
it("--ingest-url override is reflected in collector.yaml", async () => {
|
|
176
|
+
const { deps, fs } = makeDeps();
|
|
177
|
+
await runInit({ apiKey: VALID_NEW_KEY, ingestUrl: "https://forge.example.com/api/v1/ingest", configPath, noVerify: true }, deps);
|
|
178
|
+
expect(fs.files.get(configPath)?.data).toContain('url: "https://forge.example.com"');
|
|
179
|
+
});
|
|
180
|
+
it("systemctl enable failure surfaces as exit code 9", async () => {
|
|
181
|
+
const { deps, errors } = makeDeps({ systemctlExitCode: 1 });
|
|
182
|
+
const code = await runInit({ apiKey: VALID_NEW_KEY, configPath, noVerify: true }, deps);
|
|
183
|
+
expect(code).toBe(9);
|
|
184
|
+
expect(errors[errors.length - 1]).toContain("systemctl enable --now");
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
//# sourceMappingURL=init.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.test.js","sourceRoot":"","sources":["../../src/__tests__/init.test.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
export type CliMode = "version" | "help" | "run" | "mark-reboot" | "reboot";
|
|
1
|
+
export type CliMode = "version" | "help" | "run" | "mark-reboot" | "reboot" | "init";
|
|
2
2
|
export interface CliArgs {
|
|
3
3
|
mode: CliMode;
|
|
4
4
|
configPath: string;
|
|
5
5
|
reason?: string;
|
|
6
6
|
ttl?: string;
|
|
7
|
+
init?: InitFlags;
|
|
8
|
+
}
|
|
9
|
+
export interface InitFlags {
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
ingestUrl?: string;
|
|
13
|
+
configPath?: string;
|
|
14
|
+
noStart: boolean;
|
|
15
|
+
force: boolean;
|
|
16
|
+
noVerify: boolean;
|
|
7
17
|
}
|
|
8
18
|
export declare const DEFAULT_CONFIG_PATH = "/etc/glassmkr/collector.yaml";
|
|
9
19
|
export declare function parseCliArgs(argv: string[], version: string): {
|
|
@@ -11,3 +21,4 @@ export declare function parseCliArgs(argv: string[], version: string): {
|
|
|
11
21
|
output: string | null;
|
|
12
22
|
};
|
|
13
23
|
export declare function helpText(version: string): string;
|
|
24
|
+
export declare function initHelp(version: string): string;
|
package/dist/cli.js
CHANGED
|
@@ -5,6 +5,61 @@ export const DEFAULT_CONFIG_PATH = "/etc/glassmkr/collector.yaml";
|
|
|
5
5
|
export function parseCliArgs(argv, version) {
|
|
6
6
|
// argv is typically process.argv.slice(2)
|
|
7
7
|
let configPath = DEFAULT_CONFIG_PATH;
|
|
8
|
+
// Subcommand dispatch: `init` takes its own flag set.
|
|
9
|
+
if (argv[0] === "init") {
|
|
10
|
+
const flags = { noStart: false, force: false, noVerify: false };
|
|
11
|
+
for (let i = 1; i < argv.length; i++) {
|
|
12
|
+
const a = argv[i];
|
|
13
|
+
if (a === "--help" || a === "-h") {
|
|
14
|
+
return { result: { mode: "help", configPath: "" }, output: initHelp(version) };
|
|
15
|
+
}
|
|
16
|
+
if (a === "--api-key") {
|
|
17
|
+
flags.apiKey = argv[++i];
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (a.startsWith("--api-key=")) {
|
|
21
|
+
flags.apiKey = a.slice("--api-key=".length);
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (a === "--name") {
|
|
25
|
+
flags.name = argv[++i];
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (a.startsWith("--name=")) {
|
|
29
|
+
flags.name = a.slice("--name=".length);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (a === "--ingest-url") {
|
|
33
|
+
flags.ingestUrl = argv[++i];
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (a.startsWith("--ingest-url=")) {
|
|
37
|
+
flags.ingestUrl = a.slice("--ingest-url=".length);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (a === "--config-path") {
|
|
41
|
+
flags.configPath = argv[++i];
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (a.startsWith("--config-path=")) {
|
|
45
|
+
flags.configPath = a.slice("--config-path=".length);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (a === "--no-start") {
|
|
49
|
+
flags.noStart = true;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (a === "--force") {
|
|
53
|
+
flags.force = true;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (a === "--no-verify") {
|
|
57
|
+
flags.noVerify = true;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return { result: { mode: "init", configPath: "", init: flags }, output: null };
|
|
62
|
+
}
|
|
8
63
|
// Subcommand dispatch: `mark-reboot` and `reboot` take their own flags
|
|
9
64
|
// (--reason, --ttl) but re-use --help.
|
|
10
65
|
if (argv[0] === "mark-reboot" || argv[0] === "reboot") {
|
|
@@ -70,6 +125,7 @@ export function helpText(version) {
|
|
|
70
125
|
"",
|
|
71
126
|
"Usage:",
|
|
72
127
|
" glassmkr-crucible [options]",
|
|
128
|
+
" glassmkr-crucible init --api-key <K> [--name <N>] [--ingest-url <U>] [--no-start] [--force]",
|
|
73
129
|
" glassmkr-crucible mark-reboot [--reason TEXT] [--ttl DURATION]",
|
|
74
130
|
" glassmkr-crucible reboot [--reason TEXT] [--ttl DURATION]",
|
|
75
131
|
"",
|
|
@@ -79,6 +135,9 @@ export function helpText(version) {
|
|
|
79
135
|
` -c, --config Path to config file (default: ${DEFAULT_CONFIG_PATH})`,
|
|
80
136
|
"",
|
|
81
137
|
"Subcommands:",
|
|
138
|
+
" init First-run setup: validate API key, write",
|
|
139
|
+
" collector.yaml + systemd unit, enable service.",
|
|
140
|
+
" See 'glassmkr-crucible init --help'.",
|
|
82
141
|
" mark-reboot Write a planned-reboot marker so the next boot",
|
|
83
142
|
" does not fire `server_rebooted_unexpectedly`.",
|
|
84
143
|
" You run the reboot yourself afterwards.",
|
|
@@ -88,6 +147,38 @@ export function helpText(version) {
|
|
|
88
147
|
"Docs: https://github.com/glassmkr/crucible",
|
|
89
148
|
].join("\n");
|
|
90
149
|
}
|
|
150
|
+
export function initHelp(version) {
|
|
151
|
+
return [
|
|
152
|
+
`glassmkr-crucible init - first-run setup wizard`,
|
|
153
|
+
"",
|
|
154
|
+
"Usage:",
|
|
155
|
+
" glassmkr-crucible init --api-key <KEY> [options]",
|
|
156
|
+
" glassmkr-crucible init --api-key - [options] # read key from stdin",
|
|
157
|
+
"",
|
|
158
|
+
"Required:",
|
|
159
|
+
" --api-key <KEY> gmk_cru_live_<...>_<4> or col_<hex>. Use - to read from stdin.",
|
|
160
|
+
"",
|
|
161
|
+
"Options:",
|
|
162
|
+
" --name <NAME> Server name in the Forge dashboard. Defaults to the host's hostname.",
|
|
163
|
+
" --ingest-url <URL> Ingest endpoint (default: https://forge.glassmkr.com/api/v1/ingest).",
|
|
164
|
+
" --config-path <P> Where to write collector.yaml (default: /etc/glassmkr/collector.yaml).",
|
|
165
|
+
" --no-start Write config + unit, daemon-reload, but do not enable/start the service.",
|
|
166
|
+
" --force Overwrite an existing config file.",
|
|
167
|
+
" --no-verify Skip the connectivity probe against the ingest endpoint.",
|
|
168
|
+
" -h, --help Print this help and exit.",
|
|
169
|
+
"",
|
|
170
|
+
"What this does:",
|
|
171
|
+
" 1. Validates the api key format and (unless --no-verify) checks it against the ingest endpoint.",
|
|
172
|
+
" 2. Writes /etc/glassmkr/collector.yaml (mode 0600).",
|
|
173
|
+
" 3. Writes /etc/systemd/system/glassmkr-crucible.service (mode 0644) with",
|
|
174
|
+
" ExecStart pointing at the dynamically-detected binary path.",
|
|
175
|
+
" 4. Runs systemctl daemon-reload.",
|
|
176
|
+
" 5. Unless --no-start, runs systemctl enable --now glassmkr-crucible.",
|
|
177
|
+
"",
|
|
178
|
+
"Requires root for the filesystem and systemd writes (sudo).",
|
|
179
|
+
`v${version}`,
|
|
180
|
+
].join("\n");
|
|
181
|
+
}
|
|
91
182
|
function subcommandHelp(mode, version) {
|
|
92
183
|
const action = mode === "reboot"
|
|
93
184
|
? "Write a planned-reboot marker and invoke `systemctl reboot`."
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6EAA6E;AAC7E,8EAA8E;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|