@kronos-integration/service-systemd 2.5.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/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2019-2021 by Kronos-Integration
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,107 @@
1
+ [![npm](https://img.shields.io/npm/v/@kronos-integration/service-systemd.svg)](https://www.npmjs.com/package/@kronos-integration/service-systemd)
2
+ [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
3
+ [![minified size](https://badgen.net/bundlephobia/min/@kronos-integration/service-systemd)](https://bundlephobia.com/result?p=@kronos-integration/service-systemd)
4
+ [![downloads](http://img.shields.io/npm/dm/@kronos-integration/service-systemd.svg?style=flat-square)](https://npmjs.org/package/@kronos-integration/service-systemd)
5
+ [![GitHub Issues](https://img.shields.io/github/issues/Kronos-Integration/service-systemd.svg?style=flat-square)](https://github.com/Kronos-Integration/service-systemd/issues)
6
+ [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2FKronos-Integration%2Fservice-systemd%2Fbadge\&style=flat)](https://actions-badge.atrox.dev/Kronos-Integration/service-systemd/goto)
7
+ [![Styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
8
+ [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
9
+ [![Known Vulnerabilities](https://snyk.io/test/github/Kronos-Integration/service-systemd/badge.svg)](https://snyk.io/test/github/Kronos-Integration/service-systemd)
10
+ [![Coverage Status](https://coveralls.io/repos/Kronos-Integration/service-systemd/badge.svg)](https://coveralls.io/github/Kronos-Integration/service-systemd)
11
+
12
+ # @kronos-integration/service-systemd
13
+
14
+ kronos systemd integration
15
+
16
+ * sync node state to systemd with notify (done)
17
+ * propagate config into kronos (done)
18
+ * propagate socket activations into kronos (partly)
19
+ * start / stop / restart / reload initiated from systemd (partly)
20
+ * log into journal (done)
21
+
22
+ # usage
23
+
24
+ # API
25
+
26
+ <!-- Generated by documentation.js. Update this documentation by updating the source code. -->
27
+
28
+ ### Table of Contents
29
+
30
+ * [JournalLogger](#journallogger)
31
+ * [FileDescriptor](#filedescriptor)
32
+ * [Properties](#properties)
33
+ * [SystemdConfig](#systemdconfig)
34
+ * [Properties](#properties-1)
35
+ * [listeningFileDescriptors](#listeningfiledescriptors)
36
+ * [loadConfig](#loadconfig)
37
+ * [ServiceSystemd](#servicesystemd)
38
+ * [endpoints](#endpoints)
39
+
40
+ ## JournalLogger
41
+
42
+ **Extends ServiceLogger**
43
+
44
+ Forward logs entries to the journal.
45
+
46
+ ## FileDescriptor
47
+
48
+ Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
49
+
50
+ ### Properties
51
+
52
+ * `name` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**
53
+ * `fd` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
54
+
55
+ ## SystemdConfig
56
+
57
+ **Extends ServiceConfig**
58
+
59
+ Provides config from CONFIGURATION_DIRECTORY.
60
+ Also injects listeningFileDescriptors into the config
61
+
62
+ ### Properties
63
+
64
+ * `configurationDirectory` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** taken from CONFIGURATION_DIRECTORY
65
+
66
+ ### listeningFileDescriptors
67
+
68
+ listeningFileDescriptors as passed in LISTEN_FDS and LISTEN_FDNAMES.
69
+
70
+ Returns **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[FileDescriptor](#filedescriptor)>**
71
+
72
+ ### loadConfig
73
+
74
+ Load config from configuration dir.
75
+ Additionally pass listeninfFileDescriptions into config.
76
+
77
+ ## ServiceSystemd
78
+
79
+ **Extends ServiceProviderMixin(Service, JournalLogger, SystemdConfig)**
80
+
81
+ Kronos bridge to systemd:
82
+
83
+ * sync node state to systemd with notify
84
+ * propagate config into kronos world
85
+ * propagate socket activations into kronos (partly)
86
+ * start / stop / restart / reload initiated from systemd
87
+ * log into journal
88
+
89
+ ### endpoints
90
+
91
+ Definition of the predefined endpoints.
92
+
93
+ * info *in*
94
+
95
+ Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** predefined endpoints
96
+
97
+ # install
98
+
99
+ With [npm](http://npmjs.org) do:
100
+
101
+ ```shell
102
+ npm install @kronos-integration/service-systemd
103
+ ```
104
+
105
+ # license
106
+
107
+ BSD-2-Clause
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@kronos-integration/service-systemd",
3
+ "version": "2.5.2",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "sideEffects": false,
8
+ "exports": {
9
+ ".": "./src/service.mjs"
10
+ },
11
+ "description": "kronos systemd integration",
12
+ "keywords": [
13
+ "journal",
14
+ "kronos-service",
15
+ "notify",
16
+ "systemd"
17
+ ],
18
+ "contributors": [
19
+ {
20
+ "name": "Markus Felten",
21
+ "email": "markus.felten@gmx.de"
22
+ }
23
+ ],
24
+ "license": "BSD-2-Clause",
25
+ "scripts": {
26
+ "test": "npm run test:ava",
27
+ "test:ava": "ava --timeout 2m tests/*.mjs",
28
+ "cover": "c8 -x 'tests/**/*' --temp-directory build/tmp ava --timeout 2m tests/*.mjs && c8 report -r lcov -o build/coverage --temp-directory build/tmp",
29
+ "docs": "documentation readme --section=API ./src/**/*.mjs",
30
+ "lint": "npm run lint:docs",
31
+ "lint:docs": "documentation lint ./src/**/*.mjs",
32
+ "build": "cmake-js compile"
33
+ },
34
+ "dependencies": {
35
+ "@kronos-integration/service": "^10.4.7",
36
+ "config-expander": "^12.0.1"
37
+ },
38
+ "devDependencies": {
39
+ "ava": "^3.15.0",
40
+ "c8": "^7.9.0",
41
+ "cmake-js": "^6.2.1",
42
+ "documentation": "^13.2.5",
43
+ "execa": "^5.1.1",
44
+ "node-addon-api": "^4.0.0",
45
+ "semantic-release": "^18.0.0"
46
+ },
47
+ "engines": {
48
+ "node": ">=16.10.0"
49
+ },
50
+ "os": [
51
+ "linux"
52
+ ],
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "https://github.com/Kronos-Integration/service-systemd.git"
56
+ },
57
+ "bugs": {
58
+ "url": "https://github.com/Kronos-Integration/service-systemd/issues"
59
+ },
60
+ "homepage": "https://github.com/Kronos-Integration/service-systemd#readme",
61
+ "native": "${dirname}/${basename}-${os}-${arch}.node",
62
+ "template": {
63
+ "inheritFrom": [
64
+ "arlac77/template-arlac77-github",
65
+ "arlac77/template-cmake",
66
+ "arlac77/template-kronos-component"
67
+ ]
68
+ }
69
+ }
@@ -0,0 +1,213 @@
1
+ import { expand } from "config-expander";
2
+ import {
3
+ ServiceProviderMixin,
4
+ Service,
5
+ ServiceLogger,
6
+ ServiceConfig
7
+ } from "@kronos-integration/service";
8
+ import { Module } from "module";
9
+ import { arch, constants } from "os";
10
+
11
+ const filename = new URL(`../systemd-linux-${arch()}.node`, import.meta.url)
12
+ .pathname;
13
+ const m = new Module(filename);
14
+ m.filename = filename;
15
+ process.dlopen(m, filename, constants.dlopen.RTLD_NOW);
16
+ const {
17
+ LISTEN_FDS_START,
18
+ notify_with_fds,
19
+ notify,
20
+ journal_print_object
21
+ } = m.exports;
22
+
23
+ export { notify, notify_with_fds, journal_print_object };
24
+
25
+ /**
26
+ * Forward logs entries to the journal.
27
+ */
28
+ class JournalLogger extends ServiceLogger {
29
+ static get name() {
30
+ return "systemd-logger";
31
+ }
32
+
33
+ static get description() {
34
+ return "Forward log entries into systemd journal";
35
+ }
36
+
37
+ logEntry(entry) {
38
+ journal_print_object(entry);
39
+ }
40
+ }
41
+
42
+ /**
43
+ *
44
+ * @typedef {Object} FileDescriptor
45
+ * @property {string?} name
46
+ * @property {number} fd
47
+ */
48
+
49
+ /**
50
+ * Provides config from CONFIGURATION_DIRECTORY.
51
+ * Also injects listeningFileDescriptors into the config
52
+ * @property {string} configurationDirectory taken from CONFIGURATION_DIRECTORY
53
+ */
54
+ class SystemdConfig extends ServiceConfig {
55
+ static get name() {
56
+ return "systemd-config";
57
+ }
58
+
59
+ static get description() {
60
+ return "Synchronize configuration with systemd";
61
+ }
62
+
63
+ configurationDirectory = process.env.CONFIGURATION_DIRECTORY;
64
+
65
+ /**
66
+ * listeningFileDescriptors as passed in LISTEN_FDS and LISTEN_FDNAMES.
67
+ * @return {FileDescriptor[]}
68
+ */
69
+ get listeningFileDescriptors() {
70
+ const count = Number(process.env.LISTEN_FDS) || 0;
71
+ const fdNames = (process.env.LISTEN_FDNAMES || "").split(":");
72
+ const arr = new Array(count);
73
+ for (let i = 0; i < count; i++) {
74
+ arr[i] = {
75
+ fd: LISTEN_FDS_START + i
76
+ };
77
+ if (fdNames[i]) {
78
+ arr[i].name = fdNames[i];
79
+ }
80
+ }
81
+ this.trace(`listeningFileDescriptors ${JSON.stringify(arr)}`);
82
+ return arr;
83
+ }
84
+
85
+ /**
86
+ * Load config from configuration dir.
87
+ * Additionally pass listeninfFileDescriptions into config.
88
+ */
89
+ async loadConfig() {
90
+ notify("RELOADING=1");
91
+ if (this.configurationDirectory) {
92
+ this.trace(`load: ${this.configurationDirectory}/config.json`);
93
+ await this.configure(
94
+ await expand("${include('config.json')}", {
95
+ constants: {
96
+ basedir: this.configurationDirectory
97
+ },
98
+ default: {}
99
+ })
100
+ );
101
+ }
102
+
103
+ for (const listener of this.listeningFileDescriptors) {
104
+ if (listener.name === undefined) {
105
+ this.warn(`listener without name ${JSON.stringify(listener)}`);
106
+ } else {
107
+ await this.configureValue(listener.name, listener);
108
+ }
109
+ }
110
+ }
111
+
112
+ async _stop() {
113
+ const lfd = this.listeningFileDescriptors;
114
+ const state = "FDSTORE=1" + lfd.map(l => `\nFDNAME=${l.name}`).join("");
115
+ const rc = notify_with_fds(state, lfd.map(l => l.fd));
116
+ this.info(`${state} (${rc})`);
117
+
118
+ return super._stop();
119
+ }
120
+
121
+ async _start() {
122
+ await super._start();
123
+
124
+ process.on("SIGHUP", async () => {
125
+ await this.loadConfig();
126
+ notify("READY=1");
127
+ });
128
+
129
+ await this.loadConfig();
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Kronos bridge to systemd:
135
+ * - sync node state to systemd with notify
136
+ * - propagate config into kronos world
137
+ * - propagate socket activations into kronos (partly)
138
+ * - start / stop / restart / reload initiated from systemd
139
+ * - log into journal
140
+ */
141
+ export class ServiceSystemd extends ServiceProviderMixin(
142
+ Service,
143
+ JournalLogger,
144
+ SystemdConfig
145
+ ) {
146
+ static get name() {
147
+ return "systemd";
148
+ }
149
+
150
+ static get description() {
151
+ return "Bridge to systemd";
152
+ }
153
+
154
+ get autostart() {
155
+ return true;
156
+ }
157
+
158
+ /**
159
+ * Definition of the predefined endpoints.
160
+ * - info _in_
161
+ * @return {Object} predefined endpoints
162
+ */
163
+ static get endpoints() {
164
+ return {
165
+ ...super.endpoints,
166
+ info: {
167
+ in: true,
168
+ receive: "info"
169
+ }
170
+ };
171
+ }
172
+
173
+ async _start() {
174
+ process.on("warning", warning => this.warn(warning));
175
+ process.on("SIGINT", () => {
176
+ this.info("SIGINT");
177
+ this.stop();
178
+ });
179
+ process.on("SIGTERM", async () => {
180
+ await this.stop();
181
+ process.exit(0);
182
+ });
183
+ process.on("beforeExit", code => this.stop());
184
+ process.on("exit", code => this.stop());
185
+ return super._start();
186
+ }
187
+
188
+ stateChanged(oldState, newState) {
189
+ super.stateChanged(oldState, newState);
190
+ switch (newState) {
191
+ case "running":
192
+ notify("READY=1");
193
+ break;
194
+
195
+ case "stopping":
196
+ notify("STOPPING=1");
197
+ break;
198
+ }
199
+ }
200
+
201
+ info()
202
+ {
203
+ return this.toJSONWithOptions({
204
+ includeRuntimeInfo: true,
205
+ includeDefaults: true,
206
+ includeName: true,
207
+ includeConfig: false,
208
+ includePrivate: false
209
+ });
210
+ }
211
+ }
212
+
213
+ export default ServiceSystemd;
Binary file