@adecore/service 0.23.1 → 0.24.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/definitions.js +68 -3
- package/package.json +1 -1
- package/src/definitions.ts +67 -5
package/dist/definitions.js
CHANGED
|
@@ -59,11 +59,76 @@ export function systemdUnit(spec) {
|
|
|
59
59
|
];
|
|
60
60
|
return lines.join('\n');
|
|
61
61
|
}
|
|
62
|
+
/* Only keys of the outer plist dictionary identify the executable; nested environment keys are data. */
|
|
63
|
+
function launchAgentProgram(definition) {
|
|
64
|
+
const xml = definition.replace(/<!--[\s\S]*?-->/g, '');
|
|
65
|
+
if (xml.includes('<!--')) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const entries = new Map();
|
|
69
|
+
let depth = 0;
|
|
70
|
+
let key = null;
|
|
71
|
+
let start = 0;
|
|
72
|
+
for (const token of xml.matchAll(/<(\/?)(dict|array)\s*>|<key>([^<]*)<\/key>/g)) {
|
|
73
|
+
if (token[3] !== undefined) {
|
|
74
|
+
if (depth !== 1) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (key !== null) {
|
|
78
|
+
entries.set(key, xml.slice(start, token.index));
|
|
79
|
+
}
|
|
80
|
+
key = token[3];
|
|
81
|
+
if (entries.has(key)) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
start = token.index + token[0].length;
|
|
85
|
+
}
|
|
86
|
+
else if (token[1] === '') {
|
|
87
|
+
depth++;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
depth--;
|
|
91
|
+
if (depth === 0) {
|
|
92
|
+
if (key !== null) {
|
|
93
|
+
entries.set(key, xml.slice(start, token.index));
|
|
94
|
+
}
|
|
95
|
+
const program = entries.get('Program');
|
|
96
|
+
return program !== undefined
|
|
97
|
+
? (/^\s*<string>([^<]*)<\/string>\s*$/.exec(program)?.[1] ?? null)
|
|
98
|
+
: (/^\s*<array>\s*<string>([^<]*)<\/string>/.exec(entries.get('ProgramArguments') ?? '')?.[1] ?? null);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
function systemdRunsProgram(definition, program) {
|
|
105
|
+
let service = false;
|
|
106
|
+
let commands = [];
|
|
107
|
+
for (const raw of definition.split('\n')) {
|
|
108
|
+
const line = raw.trim();
|
|
109
|
+
if (line.startsWith('#') || line.startsWith(';')) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (/^\[.*\]$/.test(line)) {
|
|
113
|
+
service = line === '[Service]';
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const command = service ? /^ExecStart\s*=\s*(.*)$/.exec(line)?.[1] : undefined;
|
|
117
|
+
if (command !== undefined) {
|
|
118
|
+
if (command === '') {
|
|
119
|
+
commands = [];
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
commands.push(command);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const executable = unitWord(program, true);
|
|
127
|
+
return commands.length > 0 && commands.every((command) => command === executable || command.startsWith(`${executable} `));
|
|
128
|
+
}
|
|
62
129
|
/*
|
|
63
130
|
* Callers sharing a service identity can check executable ownership before replacing its definition.
|
|
64
131
|
*/
|
|
65
132
|
export function definitionRunsProgram(definition, program) {
|
|
66
|
-
return
|
|
67
|
-
definition.includes(`ExecStart=${unitWord(program, true)} `) ||
|
|
68
|
-
definition.includes(`ExecStart=${unitWord(program, true)}\n`));
|
|
133
|
+
return definition.trimStart().startsWith('<') ? launchAgentProgram(definition) === xmlText(program) : systemdRunsProgram(definition, program);
|
|
69
134
|
}
|
package/package.json
CHANGED
package/src/definitions.ts
CHANGED
|
@@ -92,13 +92,75 @@ export function systemdUnit(spec: ServiceSpec): string {
|
|
|
92
92
|
return lines.join('\n');
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/* Only keys of the outer plist dictionary identify the executable; nested environment keys are data. */
|
|
96
|
+
function launchAgentProgram(definition: string): string | null {
|
|
97
|
+
const xml = definition.replace(/<!--[\s\S]*?-->/g, '');
|
|
98
|
+
if (xml.includes('<!--')) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const entries = new Map<string, string>();
|
|
102
|
+
let depth = 0;
|
|
103
|
+
let key: string | null = null;
|
|
104
|
+
let start = 0;
|
|
105
|
+
for (const token of xml.matchAll(/<(\/?)(dict|array)\s*>|<key>([^<]*)<\/key>/g)) {
|
|
106
|
+
if (token[3] !== undefined) {
|
|
107
|
+
if (depth !== 1) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (key !== null) {
|
|
111
|
+
entries.set(key, xml.slice(start, token.index));
|
|
112
|
+
}
|
|
113
|
+
key = token[3];
|
|
114
|
+
if (entries.has(key)) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
start = token.index + token[0].length;
|
|
118
|
+
} else if (token[1] === '') {
|
|
119
|
+
depth++;
|
|
120
|
+
} else {
|
|
121
|
+
depth--;
|
|
122
|
+
if (depth === 0) {
|
|
123
|
+
if (key !== null) {
|
|
124
|
+
entries.set(key, xml.slice(start, token.index));
|
|
125
|
+
}
|
|
126
|
+
const program = entries.get('Program');
|
|
127
|
+
return program !== undefined
|
|
128
|
+
? (/^\s*<string>([^<]*)<\/string>\s*$/.exec(program)?.[1] ?? null)
|
|
129
|
+
: (/^\s*<array>\s*<string>([^<]*)<\/string>/.exec(entries.get('ProgramArguments') ?? '')?.[1] ?? null);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function systemdRunsProgram(definition: string, program: string): boolean {
|
|
137
|
+
let service = false;
|
|
138
|
+
let commands: string[] = [];
|
|
139
|
+
for (const raw of definition.split('\n')) {
|
|
140
|
+
const line = raw.trim();
|
|
141
|
+
if (line.startsWith('#') || line.startsWith(';')) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (/^\[.*\]$/.test(line)) {
|
|
145
|
+
service = line === '[Service]';
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const command = service ? /^ExecStart\s*=\s*(.*)$/.exec(line)?.[1] : undefined;
|
|
149
|
+
if (command !== undefined) {
|
|
150
|
+
if (command === '') {
|
|
151
|
+
commands = [];
|
|
152
|
+
} else {
|
|
153
|
+
commands.push(command);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const executable = unitWord(program, true);
|
|
158
|
+
return commands.length > 0 && commands.every((command) => command === executable || command.startsWith(`${executable} `));
|
|
159
|
+
}
|
|
160
|
+
|
|
95
161
|
/*
|
|
96
162
|
* Callers sharing a service identity can check executable ownership before replacing its definition.
|
|
97
163
|
*/
|
|
98
164
|
export function definitionRunsProgram(definition: string, program: string): boolean {
|
|
99
|
-
return (
|
|
100
|
-
definition.includes(`<string>${xmlText(program)}</string>`) ||
|
|
101
|
-
definition.includes(`ExecStart=${unitWord(program, true)} `) ||
|
|
102
|
-
definition.includes(`ExecStart=${unitWord(program, true)}\n`)
|
|
103
|
-
);
|
|
165
|
+
return definition.trimStart().startsWith('<') ? launchAgentProgram(definition) === xmlText(program) : systemdRunsProgram(definition, program);
|
|
104
166
|
}
|