iobroker.bee 0.0.0-stage → 0.2.2

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 CHANGED
@@ -1,3 +1,112 @@
1
- # Temporary Holding Version
1
+ ![Logo](admin/bee.svg)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ # ioBroker.bee
4
+
5
+ Fleet agent for ioBroker. It connects a delivered ioBroker system (in a house, a radio station in the mountains, a vehicle, a machine in the field, …) to a **beekeeper** fleet server: it reports the inventory, receives the desired version profile and converges the system to it, locally and at the right time.
6
+
7
+ > Prototype. The server (beekeeper) is a separate, closed product. This adapter only reports, reads, executes and verifies; it holds no secrets besides its own device certificate.
8
+
9
+ ## How it works
10
+
11
+ 1. **Enrollment.** The factory image contains the enrollment URL and a one-time token bound to the asset (the managed installation). On first start the agent sends the token and the system UUID and receives its own device certificate. The token is used up.
12
+ 2. **Control channel.** MQTT over TLS with the device certificate, to the platform's own broker. The broker certificate may come from the platform CA (handed out at enrollment) or from a public CA such as Let's Encrypt; for the latter the agent uses the public root certificates shipped with Node.js. Heartbeat and Last Will report online status, the inventory is sent completely on connect and as a diff afterwards, all payloads gzip-compressed. Keepalive and heartbeat are configurable to keep mobile data low.
13
+ 3. **Desired state instead of commands.** The server publishes the desired profile as a retained message. A system that was offline for months reads the current profile, not a backlog of orders.
14
+ 4. **Reconciliation.** The agent compares the profile with the installed versions and plans install, upgrade, downgrade (and removal only when the server asks for it on return to managed mode). It never touches adapters that are not in the profile.
15
+ 5. **Preflight.** Emergency stop, dependencies of the target versions (`io-package.json` of the target version, `engines.node`), free space, maintenance window and configurable conditions on ioBroker states (installation not in use, battery charged, no roaming, vehicle standing, …). Conditions that change by themselves mean *waiting*, everything that needs a human means *blocked*.
16
+ 6. **Execution.** A detached runner process performs backup (`iobroker backup`) and the steps (`iobroker add/upgrade/del`) one by one. It survives restarts of the adapter, including the update of the agent itself, which always comes last.
17
+ 7. **Verification.** Versions must match, all enabled daemon instances of the changed adapters must be alive, and no new errors may appear in their log during the observation time. Otherwise the agent rolls back the changed adapters to their previous versions and reports *blocked*. A blocked job is not repeated until the fleet manager releases a new attempt.
18
+
19
+ ### Behaviour without server
20
+
21
+ - **Unknown means self-stop.** If the server explicitly rejects the device (unknown token, revoked certificate), the agent writes the reason to `bee.0.info.status`, raises a notification and terminates. It does not keep knocking.
22
+ - **Network errors are no reason to stop.** Without connection the distance between attempts grows up to a daily rhythm. Jobs that were started continue and report later.
23
+
24
+ ### Managed and self-managed
25
+
26
+ If the owner installs adapters that are not part of the profile, the agent reports them, stops automatic updates and informs the owner via an ioBroker notification. The fleet manager sees the installation in the deviation list and can bring it back to managed mode (removing the own adapters or tolerating them as exceptions).
27
+
28
+ ### Remote access to admin, vis-2 and the console
29
+
30
+ A technician of the fleet manager can open admin or vis-2 of the system from the fleet management, without ioBroker.pro and without open ports on the device:
31
+
32
+ 1. The server sends the job `tunnel` over MQTT with a one-time ticket, the kind (admin or vis-2), the technician, the purpose and the end of the session (at most 4 hours).
33
+ 2. The agent checks that the tunnel URL belongs to its own server (same host as enrollment or broker, `wss://` only) and opens an outgoing WebSocket to it.
34
+ 3. The server carries the connections of the technician's browser through this WebSocket. The agent connects them to an enabled admin instance (or web instance for vis-2, only with vis-2 installed) on this host and nowhere else. It reports these instances with port, HTTPS and login mode in the inventory; with several, the technician chooses one, and the agent accepts only one from its own list.
35
+
36
+ The owner can switch off each kind in the tab *Remote access*; the agent then refuses the session and the fleet management shows why. Running sessions are visible in `info.remoteAccess`. After a connection loss the agent reconnects until the session expires, also across restarts of the adapter. The server ends the session early when the technician ends it or the device is revoked.
37
+
38
+ **Console.** Off until the owner allows it (*Allow the console*), and only on Linux with `script` of util-linux (part of every Debian). Then every terminal the technician opens in the browser is a login shell on this system, as the user ioBroker runs as (usually `iobroker`), started in the ioBroker directory. No native module: `script` gives the shell a pseudo terminal, `stty` sets the size of its window. At most 4 shells per session; when the session or the connection ends, the shells get SIGHUP. `info.remoteAccessBy` shows how many shells are open. Whatever the shell may do beyond the rights of that user belongs in a sudo allow list for single commands, not in a general sudo. Note that the list the ioBroker installer writes (`/etc/sudoers.d/iobroker`) contains `apt`, `apt-get` and `dpkg` without password, which makes the console effectively root on a standard installation. Systems installed with `--hardened` have no sudo; there the OS updates below do not work either.
39
+
40
+ ### Commands from the fleet management
41
+
42
+ From the asset detail a technician (permission `operate`) can start, stop and restart instances on this host, restart ioBroker, and install updates of operating system packages. The agent answers on the topic `reply`; the fleet management logs who did what.
43
+
44
+ - Instances: the same way admin does it, through the instance object (`common.enabled`, or rewriting it for a restart). Only instances of this host; `bee` itself can be restarted but not stopped from afar.
45
+ - Restart of ioBroker: host command `restartController` of js-controller.
46
+ - OS updates: js-controller (6 and newer, Linux) lists upgradeable packages (`apt list --upgradeable`) on every update of the repository, admin triggers that daily, and writes them to `system.host.<host>.osPackageUpdates`. The agent reports this list in the inventory, together with `/var/run/reboot-required`, and on request passes the chosen packages to the host command `upgradeOsPackages`, which runs apt (with sudo if ioBroker does not run as root). Packages that js-controller did not list are refused.
47
+ - Nothing of this while a job (update) is running, and one command at a time.
48
+
49
+ ## Configuration
50
+
51
+ | Tab | Setting | Meaning |
52
+ | --- | --- | --- |
53
+ | Enrollment | Enrollment URL, token | from the factory image or the fleet manager; the URL is preset to `https://bee.iobroker.click`, the token is stored encrypted |
54
+ | | comment | free text shown in the fleet management next to the installation, e.g. `Womo Mercedes KA-1525`; sent on enrollment and with the inventory. It helps to recognize the installation but proves nothing: the identity is the device certificate |
55
+ | Maintenance window | start, end | daily window for updates, may span midnight (e.g. 22:00–05:00) |
56
+ | | conditions | table of `state operator value`, e.g. `victron.0.soc >= 50`, `modem.0.roaming == false`, `presence.0.home == false` |
57
+ | | minimum free space | for download, unpacking and backup |
58
+ | Advanced | heartbeat, check interval, MQTT keepalive | trade-off between reaction time and mobile data |
59
+ | | observation after update, start timeout | verification of a rollout |
60
+ | | backup before every update | only disable for tests |
61
+ | Remote access | allow admin, allow vis-2 | whether the fleet manager may open the interface remotely (both allowed by default) |
62
+ | | allow the console | a shell on this system for the fleet manager (off by default, Linux only) |
63
+
64
+ ## States
65
+
66
+ | State | Meaning |
67
+ | --- | --- |
68
+ | `info.connection` | connected to the beekeeper broker |
69
+ | `info.status` | readable status, including the reason of a rejection |
70
+ | `info.deviceId`, `info.assetId` | identity assigned by the server |
71
+ | `info.mode`, `info.profile`, `info.onTarget` | managed/self, desired profile, system matches it |
72
+ | `job.state`, `job.detail`, `job.steps` | current or last job |
73
+ | `control.halted` | emergency stop of the fleet is active |
74
+ | `control.refresh`, `control.check` | buttons: send inventory, check desired state now |
75
+ | `info.remoteAccess`, `info.remoteAccessBy` | remote access running now, and by whom with which purpose |
76
+
77
+ Files in `iobroker-data/bee.0/`: `device.json` (certificate and key, mode 0600), `desired.json`, `job.json`, `runner.json`, `runner.log` (complete CLI output of all jobs), `tunnels.json` (running remote access sessions, resumed after a restart).
78
+
79
+ ## Not in this version
80
+
81
+ Platform updates of js-controller and Node.js (with a systemd watchdog outside ioBroker), vis-2 project distribution, recording of console sessions, signed artifacts. See the concept of the beekeeper project.
82
+
83
+ ## Development
84
+
85
+ ```bash
86
+ npm install
87
+ npm run build
88
+ npm test # unit tests of planner, preflight and diff
89
+ ```
90
+
91
+ `src/lib/protocol.ts` and `src/lib/tunnel.ts` are shared with the server and must stay identical to `beekeeper-server/src/protocol.ts` and `beekeeper-server/src/tunnel.ts`.
92
+
93
+ ## Changelog
94
+
95
+ ### 0.2.2 (2026-11-10)
96
+
97
+ - Console: a shell on this system for the fleet management, in the browser of the technician; off unless the owner allows it, Linux with `script` (util-linux) only
98
+ - Enrollment URL preset to `https://bee.iobroker.click` (new instances)
99
+ - Commands from the fleet management: start, stop and restart instances, restart ioBroker, install OS updates listed by js-controller (6 and newer)
100
+
101
+ ### 0.2.0 (2026-11-10)
102
+
103
+ - Remote access to admin and vis-2 through a tunnel to the fleet server, switchable per kind by the owner
104
+ - Versions set per asset by the fleet server, also adapter packages (tgz) loaded from the own server, checked by SHA-256 and installed with `iobroker url`
105
+
106
+ ### 0.1.0 (2026-09-18)
107
+
108
+ - Initial prototype: enrollment, inventory, desired state via MQTT, adapter rollout with preflight, backup, verification and rollback
109
+
110
+ ## License
111
+
112
+ Proprietary (UNLICENSED). Copyright (c) 2026 Denis Haev. All rights reserved.
package/admin/bee.svg ADDED
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M32 4 56 18v28L32 60 8 46V18z" fill="#e0a100"/><path d="M20 26h24M19 33h26M22 40h20" stroke="#1a1400" stroke-width="4" stroke-linecap="round"/><path d="M26 18c-3-6-9-7-12-4M38 18c3-6 9-7 12-4" stroke="#1a1400" stroke-width="2.5" fill="none" stroke-linecap="round"/></svg>
@@ -0,0 +1,321 @@
1
+ {
2
+ "i18n": false,
3
+ "type": "tabs",
4
+ "items": {
5
+ "connection": {
6
+ "type": "panel",
7
+ "label": { "en": "Enrollment", "de": "Anmeldung" },
8
+ "items": {
9
+ "hdr1": {
10
+ "type": "staticText",
11
+ "text": {
12
+ "en": "Enrollment URL and one-time token come with the factory image or from the fleet manager. After the first successful contact the device holds its own certificate; the token is used up.",
13
+ "de": "Enrollment-URL und Einmal-Token kommen mit dem Werksimage oder vom Flottenverwalter. Nach dem ersten erfolgreichen Kontakt hat das Gerät ein eigenes Zertifikat; das Token ist verbraucht."
14
+ },
15
+ "xs": 12,
16
+ "sm": 12,
17
+ "md": 12,
18
+ "lg": 12,
19
+ "xl": 12
20
+ },
21
+ "enrollUrl": {
22
+ "type": "text",
23
+ "label": { "en": "Enrollment URL", "de": "Enrollment-URL" },
24
+ "placeholder": "https://bee.iobroker.click",
25
+ "xs": 12,
26
+ "sm": 12,
27
+ "md": 6,
28
+ "lg": 6,
29
+ "xl": 6,
30
+ "newLine": true
31
+ },
32
+ "enrollToken": {
33
+ "type": "password",
34
+ "label": { "en": "Enrollment token", "de": "Enrollment-Token" },
35
+ "xs": 12,
36
+ "sm": 12,
37
+ "md": 6,
38
+ "lg": 6,
39
+ "xl": 6
40
+ },
41
+ "comment": {
42
+ "type": "text",
43
+ "label": { "en": "Comment", "de": "Kommentar" },
44
+ "help": {
45
+ "en": "Shown in the fleet management next to this installation, e.g. \"Womo Mercedes KA-1525\" (max. 200 characters)",
46
+ "de": "Erscheint in der Flottenverwaltung bei dieser Anlage, z. B. \"Womo Mercedes KA-1525\" (höchstens 200 Zeichen)"
47
+ },
48
+ "maxLength": 200,
49
+ "newLine": true,
50
+ "xs": 12,
51
+ "sm": 12,
52
+ "md": 12,
53
+ "lg": 12,
54
+ "xl": 12
55
+ },
56
+ "_status": {
57
+ "type": "state",
58
+ "oid": "info.status",
59
+ "label": { "en": "Status", "de": "Status" },
60
+ "newLine": true,
61
+ "xs": 12,
62
+ "sm": 12,
63
+ "md": 12,
64
+ "lg": 12,
65
+ "xl": 12
66
+ }
67
+ }
68
+ },
69
+ "remote": {
70
+ "type": "panel",
71
+ "label": { "en": "Remote access", "de": "Fernzugriff" },
72
+ "items": {
73
+ "hdr3": {
74
+ "type": "staticText",
75
+ "text": {
76
+ "en": "Service staff of the fleet management can open admin or vis-2 of this system from afar, without ioBroker.pro and without open ports: on request, this adapter connects to the fleet server for the duration of the access. Every access is logged with person and purpose, and is shown below while it lasts. Changing these settings ends running accesses. The console is off until you allow it here.",
77
+ "de": "Servicepersonal der Flottenverwaltung kann admin oder vis-2 dieses Systems aus der Ferne öffnen, ohne ioBroker.pro und ohne offene Ports: auf Anforderung verbindet sich dieser Adapter für die Dauer des Zugriffs mit dem Flottenserver. Jeder Zugriff wird mit Person und Zweck protokolliert und unten angezeigt, solange er läuft. Eine Änderung dieser Einstellungen beendet laufende Zugriffe. Die Konsole ist aus, bis Sie sie hier erlauben."
78
+ },
79
+ "xs": 12,
80
+ "sm": 12,
81
+ "md": 12,
82
+ "lg": 12,
83
+ "xl": 12
84
+ },
85
+ "allowAdmin": {
86
+ "type": "checkbox",
87
+ "label": { "en": "Allow remote access to admin", "de": "Fernzugriff auf admin erlauben" },
88
+ "help": {
89
+ "en": "admin means full access to the system",
90
+ "de": "admin bedeutet vollen Zugriff auf das System"
91
+ },
92
+ "newLine": true,
93
+ "xs": 12,
94
+ "sm": 12,
95
+ "md": 6,
96
+ "lg": 6,
97
+ "xl": 6
98
+ },
99
+ "allowVis": {
100
+ "type": "checkbox",
101
+ "label": { "en": "Allow remote access to vis-2 (web)", "de": "Fernzugriff auf vis-2 (web) erlauben" },
102
+ "help": {
103
+ "en": "vis-2 shows the values of this system, e.g. consumption",
104
+ "de": "vis-2 zeigt die Werte dieses Systems, z. B. Verbräuche"
105
+ },
106
+ "xs": 12,
107
+ "sm": 12,
108
+ "md": 6,
109
+ "lg": 6,
110
+ "xl": 6
111
+ },
112
+ "allowConsole": {
113
+ "type": "checkbox",
114
+ "label": { "en": "Allow the console (a shell on this system)", "de": "Konsole erlauben (Shell auf diesem System)" },
115
+ "help": {
116
+ "en": "Only Linux. The shell runs as the user of ioBroker: full access to ioBroker, its data and, depending on the setup, to the system",
117
+ "de": "Nur Linux. Die Shell läuft als Nutzer von ioBroker: voller Zugriff auf ioBroker, seine Daten und, je nach Einrichtung, auf das System"
118
+ },
119
+ "newLine": true,
120
+ "xs": 12,
121
+ "sm": 12,
122
+ "md": 6,
123
+ "lg": 6,
124
+ "xl": 6
125
+ },
126
+ "_remoteAccessBy": {
127
+ "type": "state",
128
+ "oid": "info.remoteAccessBy",
129
+ "label": { "en": "Access right now", "de": "Zugriff gerade" },
130
+ "newLine": true,
131
+ "xs": 12,
132
+ "sm": 12,
133
+ "md": 12,
134
+ "lg": 12,
135
+ "xl": 12
136
+ }
137
+ }
138
+ },
139
+ "maintenance": {
140
+ "type": "panel",
141
+ "label": { "en": "Maintenance window", "de": "Wartungsfenster" },
142
+ "items": {
143
+ "hdr2": {
144
+ "type": "staticText",
145
+ "text": {
146
+ "en": "Updates only run inside the maintenance window and when all conditions are met (e.g. installation not in use, battery charged, no roaming, vehicle standing).",
147
+ "de": "Updates laufen nur im Wartungsfenster und wenn alle Bedingungen erfüllt sind (z. B. Anlage nicht in Benutzung, Batterie geladen, kein Roaming, Fahrzeug steht)."
148
+ },
149
+ "xs": 12,
150
+ "sm": 12,
151
+ "md": 12,
152
+ "lg": 12,
153
+ "xl": 12
154
+ },
155
+ "windowStart": {
156
+ "type": "text",
157
+ "label": { "en": "Window start (HH:MM)", "de": "Fenster Beginn (HH:MM)" },
158
+ "xs": 6,
159
+ "sm": 6,
160
+ "md": 3,
161
+ "lg": 3,
162
+ "xl": 3,
163
+ "newLine": true
164
+ },
165
+ "windowEnd": {
166
+ "type": "text",
167
+ "label": { "en": "Window end (HH:MM)", "de": "Fenster Ende (HH:MM)" },
168
+ "xs": 6,
169
+ "sm": 6,
170
+ "md": 3,
171
+ "lg": 3,
172
+ "xl": 3
173
+ },
174
+ "ignoreWindow": {
175
+ "type": "checkbox",
176
+ "label": { "en": "Ignore window (testing only)", "de": "Fenster ignorieren (nur für Tests)" },
177
+ "xs": 12,
178
+ "sm": 12,
179
+ "md": 6,
180
+ "lg": 6,
181
+ "xl": 6
182
+ },
183
+ "minFreeMb": {
184
+ "type": "number",
185
+ "min": 100,
186
+ "label": { "en": "Minimum free space (MB)", "de": "Mindestens freier Speicher (MB)" },
187
+ "xs": 12,
188
+ "sm": 6,
189
+ "md": 3,
190
+ "lg": 3,
191
+ "xl": 3,
192
+ "newLine": true
193
+ },
194
+ "conditions": {
195
+ "type": "table",
196
+ "label": { "en": "Conditions for updates", "de": "Bedingungen für Updates" },
197
+ "newLine": true,
198
+ "xs": 12,
199
+ "sm": 12,
200
+ "md": 12,
201
+ "lg": 12,
202
+ "xl": 12,
203
+ "items": [
204
+ {
205
+ "type": "text",
206
+ "attr": "label",
207
+ "title": { "en": "Label", "de": "Bezeichnung" },
208
+ "width": "25%"
209
+ },
210
+ {
211
+ "type": "objectId",
212
+ "attr": "stateId",
213
+ "title": { "en": "State", "de": "Datenpunkt" },
214
+ "width": "40%"
215
+ },
216
+ {
217
+ "type": "select",
218
+ "attr": "op",
219
+ "title": { "en": "Operator", "de": "Vergleich" },
220
+ "options": [
221
+ { "label": "==", "value": "==" },
222
+ { "label": "!=", "value": "!=" },
223
+ { "label": ">=", "value": ">=" },
224
+ { "label": ">", "value": ">" },
225
+ { "label": "<=", "value": "<=" },
226
+ { "label": "<", "value": "<" }
227
+ ],
228
+ "default": "==",
229
+ "width": "15%"
230
+ },
231
+ {
232
+ "type": "text",
233
+ "attr": "value",
234
+ "title": { "en": "Value", "de": "Wert" },
235
+ "width": "20%"
236
+ }
237
+ ]
238
+ }
239
+ }
240
+ },
241
+ "advanced": {
242
+ "type": "panel",
243
+ "label": { "en": "Advanced", "de": "Erweitert" },
244
+ "items": {
245
+ "heartbeatMinutes": {
246
+ "type": "number",
247
+ "min": 5,
248
+ "label": { "en": "Heartbeat interval (min)", "de": "Heartbeat-Intervall (min)" },
249
+ "xs": 12,
250
+ "sm": 6,
251
+ "md": 3,
252
+ "lg": 3,
253
+ "xl": 3
254
+ },
255
+ "checkMinutes": {
256
+ "type": "number",
257
+ "min": 1,
258
+ "label": { "en": "Check interval (min)", "de": "Prüfintervall (min)" },
259
+ "xs": 12,
260
+ "sm": 6,
261
+ "md": 3,
262
+ "lg": 3,
263
+ "xl": 3
264
+ },
265
+ "keepaliveSeconds": {
266
+ "type": "number",
267
+ "min": 30,
268
+ "label": { "en": "MQTT keepalive (s)", "de": "MQTT-Keepalive (s)" },
269
+ "help": { "en": "Longer saves mobile data", "de": "Länger spart Mobilfunkvolumen" },
270
+ "xs": 12,
271
+ "sm": 6,
272
+ "md": 3,
273
+ "lg": 3,
274
+ "xl": 3
275
+ },
276
+ "signalStateId": {
277
+ "type": "objectId",
278
+ "label": { "en": "State with signal quality (optional)", "de": "Datenpunkt mit Signalqualität (optional)" },
279
+ "xs": 12,
280
+ "sm": 12,
281
+ "md": 6,
282
+ "lg": 6,
283
+ "xl": 6,
284
+ "newLine": true
285
+ },
286
+ "verifySeconds": {
287
+ "type": "number",
288
+ "min": 10,
289
+ "label": { "en": "Observation after update (s)", "de": "Beobachtung nach Update (s)" },
290
+ "help": { "en": "No new errors in the log during this time", "de": "In dieser Zeit keine neuen Fehler im Log" },
291
+ "xs": 12,
292
+ "sm": 6,
293
+ "md": 3,
294
+ "lg": 3,
295
+ "xl": 3,
296
+ "newLine": true
297
+ },
298
+ "startTimeoutSeconds": {
299
+ "type": "number",
300
+ "min": 30,
301
+ "label": { "en": "Start timeout of instances (s)", "de": "Startfrist der Instanzen (s)" },
302
+ "xs": 12,
303
+ "sm": 6,
304
+ "md": 3,
305
+ "lg": 3,
306
+ "xl": 3
307
+ },
308
+ "backupBeforeUpdate": {
309
+ "type": "checkbox",
310
+ "label": { "en": "Backup before every update", "de": "Sicherung vor jedem Update" },
311
+ "help": { "en": "Disable for tests only", "de": "Nur für Tests abschalten" },
312
+ "xs": 12,
313
+ "sm": 12,
314
+ "md": 6,
315
+ "lg": 6,
316
+ "xl": 6
317
+ }
318
+ }
319
+ }
320
+ }
321
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ACTION_DONE = exports.REBOOT_REQUIRED = void 0;
4
+ exports.supportedCommands = supportedCommands;
5
+ exports.osUpdatesFrom = osUpdatesFrom;
6
+ exports.instanceRefusal = instanceRefusal;
7
+ exports.chooseOsPackages = chooseOsPackages;
8
+ const protocol_1 = require("./protocol");
9
+ const util_1 = require("./util");
10
+ /**
11
+ * Commands of the fleet management to this system: start, stop or restart an instance (as admin does it,
12
+ * through the instance object), restart ioBroker, upgrade packages of the operating system. The last two
13
+ * are done by js-controller (host commands restartController and upgradeOsPackages); the agent only passes
14
+ * them on, and only packages js-controller listed itself as upgradeable.
15
+ */
16
+ /** Exists on Debian and Ubuntu when an update asks for a reboot of the system */
17
+ exports.REBOOT_REQUIRED = '/var/run/reboot-required';
18
+ /** What this system can do: OS updates need Linux and js-controller 6 (it lists them and runs apt) */
19
+ function supportedCommands(jsController, platform = process.platform) {
20
+ const commands = ['instance', 'restart'];
21
+ if (platform === 'linux' && jsController && (0, util_1.compareVersions)(jsController, '6.0.0') >= 0) {
22
+ commands.push('osUpgrade');
23
+ }
24
+ return commands;
25
+ }
26
+ /**
27
+ * OS updates from the state system.host.<host>.osPackageUpdates, which js-controller writes on every update
28
+ * of the repository: a JSON list of lines of `apt list --upgradeable`. Undefined if there is no such state.
29
+ *
30
+ * @param state the state of js-controller
31
+ * @param rebootRequired whether the system asks for a reboot
32
+ */
33
+ function osUpdatesFrom(state, rebootRequired) {
34
+ if (!state || typeof state.val !== 'string') {
35
+ return undefined;
36
+ }
37
+ let lines;
38
+ try {
39
+ lines = JSON.parse(state.val);
40
+ }
41
+ catch {
42
+ return undefined;
43
+ }
44
+ if (!Array.isArray(lines)) {
45
+ return undefined;
46
+ }
47
+ const packages = lines
48
+ .filter((l) => typeof l === 'string')
49
+ .map(protocol_1.parseOsPackage)
50
+ .filter((p) => !!p);
51
+ return { packages, checkedAt: state.ts || null, rebootRequired };
52
+ }
53
+ /**
54
+ * Why a command for an instance is not carried out, or null.
55
+ *
56
+ * @param id instance, e.g. "javascript.0"
57
+ * @param action start, stop or restart
58
+ * @param own the instance of the agent itself (bee.0)
59
+ * @param obj the object system.adapter.<id>
60
+ * @param host the host of the agent
61
+ */
62
+ function instanceRefusal(id, action, own, obj, host) {
63
+ if (typeof id !== 'string' || !protocol_1.INSTANCE_ID.test(id)) {
64
+ return `Ungültige Instanz ${String(id)}`;
65
+ }
66
+ if (action !== 'start' && action !== 'stop' && action !== 'restart') {
67
+ return `Unbekannte Aktion ${String(action)}`;
68
+ }
69
+ if (!obj || obj.type !== 'instance') {
70
+ return `Instanz ${id} gibt es auf dem Gerät nicht`;
71
+ }
72
+ if (obj.common.host !== host) {
73
+ return `Instanz ${id} gehört zum Host ${obj.common.host}, nicht zu ${host}`;
74
+ }
75
+ if (id === own && action === 'stop') {
76
+ return 'bee stoppen trennt die Anlage von der Flottenverwaltung; das geht nur am Gerät';
77
+ }
78
+ if (action === 'restart' && !obj.common.enabled) {
79
+ return `Instanz ${id} ist ausgeschaltet; starten statt neu starten`;
80
+ }
81
+ return null;
82
+ }
83
+ exports.ACTION_DONE = {
84
+ start: 'gestartet',
85
+ stop: 'gestoppt',
86
+ restart: 'neu gestartet',
87
+ };
88
+ /** The packages of a request that js-controller listed, or the names it did not list */
89
+ function chooseOsPackages(listed, wanted) {
90
+ const names = Array.isArray(wanted) ? wanted.filter((n) => typeof n === 'string') : [];
91
+ return {
92
+ packages: listed.filter(p => names.includes(p.name)),
93
+ unknown: names.filter(n => !listed.some(p => p.name === n)),
94
+ };
95
+ }
96
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/lib/commands.ts"],"names":[],"mappings":";;;AAqBA,8CAMC;AASD,sCAqBC;AAWD,0CA0BC;AASD,4CAMC;AA7GD,yCAOoB;AACpB,iCAAyC;AAEzC;;;;;GAKG;AAEH,iFAAiF;AACpE,QAAA,eAAe,GAAG,0BAA0B,CAAC;AAE1D,sGAAsG;AACtG,SAAgB,iBAAiB,CAAC,YAAoB,EAAE,WAAmB,OAAO,CAAC,QAAQ;IACvF,MAAM,QAAQ,GAAmB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACzD,IAAI,QAAQ,KAAK,OAAO,IAAI,YAAY,IAAI,IAAA,sBAAe,EAAC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtF,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,aAAa,CACzB,KAAwC,EACxC,cAAuB;IAEvB,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK;SACjB,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;SACjD,GAAG,CAAC,yBAAc,CAAC;SACnB,MAAM,CAAC,CAAC,CAAC,EAAkB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI,EAAE,cAAc,EAAE,CAAC;AACrE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,eAAe,CAC3B,EAAW,EACX,MAAe,EACf,GAAW,EACX,GAAuC,EACvC,IAAY;IAEZ,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,sBAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAClD,OAAO,qBAAqB,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IAC7C,CAAC;IACD,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAClE,OAAO,qBAAqB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IACjD,CAAC;IACD,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,WAAW,EAAE,8BAA8B,CAAC;IACvD,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,WAAW,EAAE,oBAAoB,GAAG,CAAC,MAAM,CAAC,IAAI,cAAc,IAAI,EAAE,CAAC;IAChF,CAAC;IACD,IAAI,EAAE,KAAK,GAAG,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QAClC,OAAO,gFAAgF,CAAC;IAC5F,CAAC;IACD,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAC9C,OAAO,WAAW,EAAE,+CAA+C,CAAC;IACxE,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAEY,QAAA,WAAW,GAAmC;IACvD,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,eAAe;CAC3B,CAAC;AAEF,wFAAwF;AACxF,SAAgB,gBAAgB,CAAC,MAAmB,EAAE,MAAe;IACjE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpG,OAAO;QACH,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpD,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;KAC9D,CAAC;AACN,CAAC"}