paratix 0.0.1 → 0.1.0
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 +81 -3
- package/dist/chunk-DUIGEB2J.js +439 -0
- package/dist/chunk-DUIGEB2J.js.map +1 -0
- package/dist/chunk-G3BMCQKU.js +1706 -0
- package/dist/chunk-G3BMCQKU.js.map +1 -0
- package/dist/chunk-ULJMW23T.js +4961 -0
- package/dist/chunk-ULJMW23T.js.map +1 -0
- package/dist/cli.d.ts +62 -0
- package/dist/cli.js +779 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +201 -0
- package/dist/index.js +620 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/index.d.ts +1332 -0
- package/dist/modules/index.js +56 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/types-BPzPHfax.d.ts +252 -0
- package/llm-guide.md +607 -0
- package/package.json +35 -2
package/dist/index.js
ADDED
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
import {
|
|
2
|
+
printCommandFailure,
|
|
3
|
+
printModuleResult,
|
|
4
|
+
printRecipeHeader,
|
|
5
|
+
runSignalModules,
|
|
6
|
+
startModuleSpinner,
|
|
7
|
+
withRecipeOutputScope
|
|
8
|
+
} from "./chunk-DUIGEB2J.js";
|
|
9
|
+
import {
|
|
10
|
+
NEEDS_APPLY,
|
|
11
|
+
apt,
|
|
12
|
+
archive,
|
|
13
|
+
command,
|
|
14
|
+
compose,
|
|
15
|
+
cron,
|
|
16
|
+
download,
|
|
17
|
+
failed,
|
|
18
|
+
failedCommand,
|
|
19
|
+
file,
|
|
20
|
+
git,
|
|
21
|
+
group,
|
|
22
|
+
hostname,
|
|
23
|
+
mount,
|
|
24
|
+
net,
|
|
25
|
+
op,
|
|
26
|
+
pkg,
|
|
27
|
+
releaseUpgrade,
|
|
28
|
+
rsync,
|
|
29
|
+
script,
|
|
30
|
+
service,
|
|
31
|
+
ssh,
|
|
32
|
+
sshd,
|
|
33
|
+
sysctl,
|
|
34
|
+
system,
|
|
35
|
+
systemd,
|
|
36
|
+
ufw,
|
|
37
|
+
user
|
|
38
|
+
} from "./chunk-ULJMW23T.js";
|
|
39
|
+
import {
|
|
40
|
+
CommandError,
|
|
41
|
+
assertValidModuleMetaEntries,
|
|
42
|
+
assertValidModuleMetaEntry,
|
|
43
|
+
diffEnvironmentToMetaEntries,
|
|
44
|
+
environmentMeta,
|
|
45
|
+
environmentToMetaEntries,
|
|
46
|
+
isBooleanEnvironmentMetaEntry,
|
|
47
|
+
isEnvironmentMetaEntry,
|
|
48
|
+
isLazyEnvironmentMetaEntry,
|
|
49
|
+
isNumberEnvironmentMetaEntry,
|
|
50
|
+
isSshdPortMetaEntry,
|
|
51
|
+
isStringEnvironmentMetaEntry,
|
|
52
|
+
isSystemHostMetaEntry,
|
|
53
|
+
isSystemRebootMetaEntry,
|
|
54
|
+
mergeEnvironmentFromMeta,
|
|
55
|
+
meta,
|
|
56
|
+
shellQuote,
|
|
57
|
+
sshdPortMeta,
|
|
58
|
+
systemHostMeta,
|
|
59
|
+
systemRebootMeta,
|
|
60
|
+
validateSshConfig
|
|
61
|
+
} from "./chunk-G3BMCQKU.js";
|
|
62
|
+
|
|
63
|
+
// src/builtins.ts
|
|
64
|
+
function assert(condition, message) {
|
|
65
|
+
return {
|
|
66
|
+
_dryRunBlocker: true,
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
68
|
+
async apply(_ssh, environment) {
|
|
69
|
+
if (condition(environment)) {
|
|
70
|
+
return { status: "ok" };
|
|
71
|
+
}
|
|
72
|
+
return failed(`[assert] ${message}`);
|
|
73
|
+
},
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
75
|
+
async check(_ssh, environment) {
|
|
76
|
+
return condition(environment) ? "ok" : NEEDS_APPLY;
|
|
77
|
+
},
|
|
78
|
+
name: `assert: ${message}`
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function debug(message) {
|
|
82
|
+
return {
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
84
|
+
async apply() {
|
|
85
|
+
console.log(` [debug] ${message}`);
|
|
86
|
+
return { status: "ok" };
|
|
87
|
+
},
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
89
|
+
async check() {
|
|
90
|
+
return NEEDS_APPLY;
|
|
91
|
+
},
|
|
92
|
+
name: `debug: ${message}`
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function fail(message) {
|
|
96
|
+
return {
|
|
97
|
+
_dryRunBlocker: true,
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
99
|
+
async apply() {
|
|
100
|
+
return failed(`[fail] ${message}`);
|
|
101
|
+
},
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
103
|
+
async check() {
|
|
104
|
+
return NEEDS_APPLY;
|
|
105
|
+
},
|
|
106
|
+
name: `fail: ${message}`
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function pause(message) {
|
|
110
|
+
return {
|
|
111
|
+
async apply() {
|
|
112
|
+
const promptText = message ?? "Press enter to continue...";
|
|
113
|
+
process.stdout.write(` [pause] ${promptText} `);
|
|
114
|
+
await new Promise((resolve) => {
|
|
115
|
+
process.stdin.once("data", () => {
|
|
116
|
+
process.stdin.pause();
|
|
117
|
+
resolve();
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
return { status: "ok" };
|
|
121
|
+
},
|
|
122
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
123
|
+
async check() {
|
|
124
|
+
return NEEDS_APPLY;
|
|
125
|
+
},
|
|
126
|
+
name: message == null ? "pause" : `pause: ${message}`
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function isFirstRunEnabled(environment) {
|
|
130
|
+
return environment.PARATIX_FIRST_RUN === "true" || environment.FIRST_RUN === true;
|
|
131
|
+
}
|
|
132
|
+
var firstRun = {
|
|
133
|
+
/**
|
|
134
|
+
* Stop the current run successfully when Paratix was invoked with `--first-run`.
|
|
135
|
+
* Useful as an explicit stage boundary in scaffolded playbooks.
|
|
136
|
+
*
|
|
137
|
+
* @param message - Optional note shown in the module name.
|
|
138
|
+
* @returns A local module that stops the run only during first-run execution.
|
|
139
|
+
*/
|
|
140
|
+
stop(message) {
|
|
141
|
+
const moduleName = message == null ? "firstRun.stop" : `firstRun.stop: ${message}`;
|
|
142
|
+
return {
|
|
143
|
+
_dryRunBlocker: true,
|
|
144
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
145
|
+
async apply(_ssh, environment) {
|
|
146
|
+
if (!isFirstRunEnabled(environment)) {
|
|
147
|
+
return { status: "ok" };
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
_dryRunDetail: "(first-run stop)",
|
|
151
|
+
_stopRun: true,
|
|
152
|
+
status: "ok"
|
|
153
|
+
};
|
|
154
|
+
},
|
|
155
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
156
|
+
async check(_ssh, environment) {
|
|
157
|
+
return isFirstRunEnabled(environment) ? NEEDS_APPLY : "ok";
|
|
158
|
+
},
|
|
159
|
+
local: true,
|
|
160
|
+
name: moduleName
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
var signals = {
|
|
165
|
+
/**
|
|
166
|
+
* Flush all currently pending signals for the active scope.
|
|
167
|
+
* Signals remain scope-local:
|
|
168
|
+
* - in a recipe, this flushes that recipe's signals
|
|
169
|
+
* - at top level, this flushes `server(...).signals`
|
|
170
|
+
*
|
|
171
|
+
* @param message - Optional note shown in the module name.
|
|
172
|
+
* @returns A local control module that requests an immediate signal flush.
|
|
173
|
+
*/
|
|
174
|
+
flush(message) {
|
|
175
|
+
const moduleName = message == null ? "signals.flush" : `signals.flush: ${message}`;
|
|
176
|
+
return {
|
|
177
|
+
_dryRunBlocker: true,
|
|
178
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
179
|
+
async apply() {
|
|
180
|
+
return {
|
|
181
|
+
_dryRunDetail: "(dry-run, pending signals not executed)",
|
|
182
|
+
_flushSignals: true,
|
|
183
|
+
status: "ok"
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- Interface requires async
|
|
187
|
+
async check() {
|
|
188
|
+
return NEEDS_APPLY;
|
|
189
|
+
},
|
|
190
|
+
local: true,
|
|
191
|
+
name: moduleName
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
async function applyConditionalModules(parameters) {
|
|
196
|
+
const { dryRun = false, modules, ssh: ssh2 } = parameters;
|
|
197
|
+
let state = createConditionalApplyState(parameters.environment);
|
|
198
|
+
for (const currentModule of modules) {
|
|
199
|
+
const checkResult = await currentModule.check(ssh2, state.environment);
|
|
200
|
+
if (checkResult === "ok") continue;
|
|
201
|
+
if (!shouldExecuteConditionalApply(currentModule, dryRun)) {
|
|
202
|
+
state = markConditionalApplyChanged(state);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const result = await executeConditionalApply({
|
|
206
|
+
dryRun,
|
|
207
|
+
environment: state.environment,
|
|
208
|
+
module: currentModule,
|
|
209
|
+
ssh: ssh2
|
|
210
|
+
});
|
|
211
|
+
if (result.status === "failed") return result;
|
|
212
|
+
state = await mergeConditionalApplyState(state, result);
|
|
213
|
+
if (state.stopRun === true) break;
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
_flushSignals: state.flushSignals,
|
|
217
|
+
_stopRun: state.stopRun,
|
|
218
|
+
meta: state.meta.length === 0 ? void 0 : state.meta,
|
|
219
|
+
status: state.status
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function shouldExecuteConditionalApply(module, dryRun) {
|
|
223
|
+
if (!dryRun) return true;
|
|
224
|
+
return module._applyDryRun != null || module._dryRunBlocker === true || module._dryRunMetaProducer === true;
|
|
225
|
+
}
|
|
226
|
+
function createConditionalApplyState(environment) {
|
|
227
|
+
return { environment: { ...environment }, meta: [], status: "ok" };
|
|
228
|
+
}
|
|
229
|
+
function markConditionalApplyChanged(state) {
|
|
230
|
+
return { ...state, status: "changed" };
|
|
231
|
+
}
|
|
232
|
+
async function executeConditionalApply(parameters) {
|
|
233
|
+
const { dryRun, environment, module, ssh: ssh2 } = parameters;
|
|
234
|
+
if (dryRun && module._applyDryRun != null) {
|
|
235
|
+
return module._applyDryRun(ssh2, environment);
|
|
236
|
+
}
|
|
237
|
+
return module.apply(ssh2, environment);
|
|
238
|
+
}
|
|
239
|
+
function whenNeedsDryRunApply(modules) {
|
|
240
|
+
return modules.some((module) => shouldExecuteConditionalDryRun(module));
|
|
241
|
+
}
|
|
242
|
+
function shouldExecuteConditionalDryRun(module) {
|
|
243
|
+
return module._applyDryRun != null || module._dryRunBlocker === true || module._dryRunMetaProducer === true;
|
|
244
|
+
}
|
|
245
|
+
async function mergeConditionalApplyState(state, result) {
|
|
246
|
+
const environment = await mergeEnvironmentFromMeta(state.environment, result.meta);
|
|
247
|
+
return {
|
|
248
|
+
environment,
|
|
249
|
+
flushSignals: result._flushSignals === true ? true : state.flushSignals,
|
|
250
|
+
meta: result.meta == null ? state.meta : [...state.meta, ...result.meta],
|
|
251
|
+
status: result.status === "changed" ? "changed" : state.status,
|
|
252
|
+
stopRun: result._stopRun === true ? true : state.stopRun
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function createWhenDryRunApply(condition, modules, needsDryRunApply) {
|
|
256
|
+
if (!needsDryRunApply) return void 0;
|
|
257
|
+
return async (ssh2, environment) => {
|
|
258
|
+
if (!condition(environment)) {
|
|
259
|
+
return { status: "skipped" };
|
|
260
|
+
}
|
|
261
|
+
return applyConditionalModules({ dryRun: true, environment, modules, ssh: ssh2 });
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function when(condition, ...modules) {
|
|
265
|
+
const needsDryRunApply = whenNeedsDryRunApply(modules);
|
|
266
|
+
const applyDryRun = createWhenDryRunApply(condition, modules, needsDryRunApply);
|
|
267
|
+
return {
|
|
268
|
+
...modules.some((module) => module._dryRunBlocker === true) ? { _dryRunBlocker: true } : {},
|
|
269
|
+
...modules.some((module) => module._dryRunMetaProducer === true) ? { _dryRunMetaProducer: true } : {},
|
|
270
|
+
...applyDryRun == null ? {} : { _applyDryRun: applyDryRun },
|
|
271
|
+
async apply(ssh2, environment) {
|
|
272
|
+
if (!condition(environment)) {
|
|
273
|
+
return { status: "skipped" };
|
|
274
|
+
}
|
|
275
|
+
return applyConditionalModules({ environment, modules, ssh: ssh2 });
|
|
276
|
+
},
|
|
277
|
+
async check(ssh2, environment) {
|
|
278
|
+
if (!condition(environment)) {
|
|
279
|
+
return "ok";
|
|
280
|
+
}
|
|
281
|
+
const currentEnvironment = { ...environment };
|
|
282
|
+
for (const currentModule of modules) {
|
|
283
|
+
const result = await currentModule.check(ssh2, currentEnvironment);
|
|
284
|
+
if (result === NEEDS_APPLY) {
|
|
285
|
+
return NEEDS_APPLY;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return "ok";
|
|
289
|
+
},
|
|
290
|
+
name: `when: conditional (${modules.length} modules)`
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// src/recipe.ts
|
|
295
|
+
var INTERRUPTED_BEFORE_APPLY = /* @__PURE__ */ Symbol("recipe-interrupted-before-apply");
|
|
296
|
+
function applyRecipeStepToState(state, step, preserveControlPlaneMeta) {
|
|
297
|
+
let stepMeta;
|
|
298
|
+
if (step.meta == null) {
|
|
299
|
+
stepMeta = void 0;
|
|
300
|
+
} else if (preserveControlPlaneMeta) {
|
|
301
|
+
stepMeta = step.meta;
|
|
302
|
+
} else {
|
|
303
|
+
stepMeta = step.meta.filter(isEnvironmentMetaEntry);
|
|
304
|
+
}
|
|
305
|
+
const nextMeta = stepMeta == null ? state.meta ?? [] : [...state.meta ?? [], ...stepMeta];
|
|
306
|
+
let nextStatus = state.status;
|
|
307
|
+
if (step.status === "failed") nextStatus = "failed";
|
|
308
|
+
else if (step.status === "changed") nextStatus = "changed";
|
|
309
|
+
return {
|
|
310
|
+
env: step.env,
|
|
311
|
+
meta: nextMeta,
|
|
312
|
+
signalsPending: step.status === "changed" ? true : state.signalsPending,
|
|
313
|
+
status: nextStatus,
|
|
314
|
+
stopRun: step._stopRun === true ? true : state.stopRun
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
async function executeOneModule(parameters) {
|
|
318
|
+
const { currentEnvironment, ssh: ssh2, targetModule } = parameters;
|
|
319
|
+
const verbose = parameters.verbose ?? false;
|
|
320
|
+
const connection = targetModule.local === true ? null : ssh2;
|
|
321
|
+
const checkResult = await checkRecipeChild(targetModule, connection, currentEnvironment);
|
|
322
|
+
if (checkResult === "ok") {
|
|
323
|
+
printModuleResult(targetModule.name, "ok");
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
if ((parameters.shutdownSignal?.() ?? null) != null) {
|
|
327
|
+
return INTERRUPTED_BEFORE_APPLY;
|
|
328
|
+
}
|
|
329
|
+
const result = await targetModule.apply(connection, currentEnvironment);
|
|
330
|
+
printModuleResult(targetModule.name, result.status);
|
|
331
|
+
if (result.status === "failed" && result.error != null) {
|
|
332
|
+
printCommandFailure(result.error, verbose);
|
|
333
|
+
}
|
|
334
|
+
const environment = await mergeEnvironmentFromMeta(currentEnvironment, result.meta);
|
|
335
|
+
return {
|
|
336
|
+
_flushSignals: result._flushSignals,
|
|
337
|
+
_stopRun: result._stopRun,
|
|
338
|
+
env: environment,
|
|
339
|
+
meta: result.meta,
|
|
340
|
+
status: result.status
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
async function checkRecipeChild(targetModule, connection, currentEnvironment) {
|
|
344
|
+
startModuleSpinner(targetModule.name);
|
|
345
|
+
return targetModule.check(connection, currentEnvironment);
|
|
346
|
+
}
|
|
347
|
+
async function applyExecutedRecipeStep(parameters) {
|
|
348
|
+
if (parameters.step == null) return parameters.state;
|
|
349
|
+
if (parameters.step === INTERRUPTED_BEFORE_APPLY) return null;
|
|
350
|
+
if (parameters.onChildStep != null) {
|
|
351
|
+
await parameters.onChildStep(parameters.step);
|
|
352
|
+
}
|
|
353
|
+
return applyRecipeStepToState(
|
|
354
|
+
parameters.state,
|
|
355
|
+
parameters.step,
|
|
356
|
+
parameters.preserveControlPlaneMeta
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
function failedRecipeState(environment) {
|
|
360
|
+
return {
|
|
361
|
+
env: environment,
|
|
362
|
+
meta: void 0,
|
|
363
|
+
signalsPending: false,
|
|
364
|
+
status: "failed"
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
function annotateRecipeChildError(moduleName, error) {
|
|
368
|
+
const prefix = `[${moduleName}] `;
|
|
369
|
+
if (error instanceof CommandError) {
|
|
370
|
+
return new CommandError(`${prefix}${error.message}`, error.fullStdout, error.fullStderr);
|
|
371
|
+
}
|
|
372
|
+
if (error instanceof Error) {
|
|
373
|
+
return new Error(`${prefix}${error.message}`);
|
|
374
|
+
}
|
|
375
|
+
return new Error(`${prefix}${String(error)}`);
|
|
376
|
+
}
|
|
377
|
+
async function executeRecipeChildStep(parameters) {
|
|
378
|
+
try {
|
|
379
|
+
return { kind: "step", step: await executeOneModule(parameters) };
|
|
380
|
+
} catch (error) {
|
|
381
|
+
if (parameters.shutdownSignal() != null) {
|
|
382
|
+
return { kind: "step", step: INTERRUPTED_BEFORE_APPLY };
|
|
383
|
+
}
|
|
384
|
+
printModuleResult(parameters.targetModule.name, "failed");
|
|
385
|
+
printCommandFailure(error, parameters.verbose);
|
|
386
|
+
return { kind: "failed", state: failedRecipeState(parameters.currentEnvironment) };
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
async function processRecipeStep(parameters) {
|
|
390
|
+
if (parameters.step.kind === "failed") {
|
|
391
|
+
return { kind: "break", state: parameters.step.state };
|
|
392
|
+
}
|
|
393
|
+
const nextState = await applyExecutedRecipeStep({
|
|
394
|
+
onChildStep: parameters.onChildStep,
|
|
395
|
+
preserveControlPlaneMeta: parameters.preserveControlPlaneMeta,
|
|
396
|
+
state: parameters.state,
|
|
397
|
+
step: parameters.step.step
|
|
398
|
+
});
|
|
399
|
+
if (nextState == null) {
|
|
400
|
+
return { kind: "break", state: parameters.state };
|
|
401
|
+
}
|
|
402
|
+
let state = nextState;
|
|
403
|
+
if (shouldFlushRecipeSignals(parameters.step.step, state, parameters.signals)) {
|
|
404
|
+
const signalStatus = await flushPendingRecipeSignals({
|
|
405
|
+
environment: state.env,
|
|
406
|
+
onSignalStep: parameters.onSignalStep,
|
|
407
|
+
shutdownSignal: parameters.shutdownSignal,
|
|
408
|
+
signalHooks: parameters.signalHooks,
|
|
409
|
+
signals: parameters.signals,
|
|
410
|
+
ssh: parameters.ssh,
|
|
411
|
+
verbose: parameters.verbose
|
|
412
|
+
});
|
|
413
|
+
state = applyRecipeSignalStatus(state, signalStatus);
|
|
414
|
+
}
|
|
415
|
+
if (state.status === "failed" || state.stopRun === true) {
|
|
416
|
+
return { kind: "break", state };
|
|
417
|
+
}
|
|
418
|
+
return { kind: "continue", state };
|
|
419
|
+
}
|
|
420
|
+
async function executeModules(modules, ssh2, parameters) {
|
|
421
|
+
const onChildStep = parameters.onChildStep;
|
|
422
|
+
const preserveControlPlaneMeta = onChildStep == null;
|
|
423
|
+
const shutdownSignal = parameters.shutdownSignal ?? (() => null);
|
|
424
|
+
const verbose = parameters.verbose ?? false;
|
|
425
|
+
let state = {
|
|
426
|
+
env: { ...parameters.environment },
|
|
427
|
+
meta: void 0,
|
|
428
|
+
signalsPending: false,
|
|
429
|
+
status: "ok"
|
|
430
|
+
};
|
|
431
|
+
for (const currentModule of modules) {
|
|
432
|
+
if (shutdownSignal() != null) break;
|
|
433
|
+
const step = await executeRecipeChildStep({
|
|
434
|
+
currentEnvironment: state.env,
|
|
435
|
+
shutdownSignal,
|
|
436
|
+
ssh: ssh2,
|
|
437
|
+
targetModule: currentModule,
|
|
438
|
+
verbose
|
|
439
|
+
});
|
|
440
|
+
const processedStep = await processRecipeStep({
|
|
441
|
+
onChildStep,
|
|
442
|
+
onSignalStep: parameters.onSignalStep,
|
|
443
|
+
preserveControlPlaneMeta,
|
|
444
|
+
shutdownSignal,
|
|
445
|
+
signalHooks: parameters.signalHooks,
|
|
446
|
+
signals: parameters.signals,
|
|
447
|
+
ssh: ssh2,
|
|
448
|
+
state,
|
|
449
|
+
step,
|
|
450
|
+
verbose
|
|
451
|
+
});
|
|
452
|
+
state = processedStep.state;
|
|
453
|
+
if (processedStep.kind === "break") return state;
|
|
454
|
+
}
|
|
455
|
+
return state;
|
|
456
|
+
}
|
|
457
|
+
async function triggerSignals(parameters) {
|
|
458
|
+
return runSignalModules({
|
|
459
|
+
environment: parameters.environment,
|
|
460
|
+
hooks: parameters.signalHooks,
|
|
461
|
+
onSignalStep: parameters.onSignalStep,
|
|
462
|
+
shutdownSignal: parameters.shutdownSignal,
|
|
463
|
+
signals: parameters.signals,
|
|
464
|
+
ssh: parameters.ssh,
|
|
465
|
+
verbose: parameters.verbose
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
function shouldFlushRecipeSignals(step, state, signals2) {
|
|
469
|
+
return step != null && step !== INTERRUPTED_BEFORE_APPLY && step._flushSignals === true && state.signalsPending && signals2 != null;
|
|
470
|
+
}
|
|
471
|
+
function applyRecipeSignalStatus(state, signalStatus) {
|
|
472
|
+
return {
|
|
473
|
+
...state,
|
|
474
|
+
signalsPending: false,
|
|
475
|
+
status: signalStatus === "failed" ? "failed" : state.status
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
async function flushPendingRecipeSignals(parameters) {
|
|
479
|
+
return triggerSignals(parameters);
|
|
480
|
+
}
|
|
481
|
+
async function applyRecipe(parameters) {
|
|
482
|
+
return withRecipeOutputScope(async () => {
|
|
483
|
+
const shutdownSignal = parameters.options?.shutdownSignal;
|
|
484
|
+
const verbose = parameters.options?.verbose ?? false;
|
|
485
|
+
printRecipeHeader(parameters.name);
|
|
486
|
+
const state = await executeModules(parameters.modules, parameters.ssh, {
|
|
487
|
+
environment: parameters.environment,
|
|
488
|
+
onChildStep: parameters.options?.onChildStep,
|
|
489
|
+
onSignalStep: parameters.options?.onSignalStep,
|
|
490
|
+
shutdownSignal,
|
|
491
|
+
signalHooks: parameters.options?.signalHooks,
|
|
492
|
+
signals: parameters.signals,
|
|
493
|
+
verbose
|
|
494
|
+
});
|
|
495
|
+
if (shouldRunRecipeSignalsAtEnd(state, parameters.signals)) {
|
|
496
|
+
state.status = await triggerSignals({
|
|
497
|
+
environment: state.env,
|
|
498
|
+
onSignalStep: parameters.options?.onSignalStep,
|
|
499
|
+
shutdownSignal,
|
|
500
|
+
signalHooks: parameters.options?.signalHooks,
|
|
501
|
+
signals: parameters.signals,
|
|
502
|
+
ssh: parameters.ssh,
|
|
503
|
+
verbose
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
return {
|
|
507
|
+
_stopRun: state.stopRun,
|
|
508
|
+
meta: state.meta,
|
|
509
|
+
status: state.status
|
|
510
|
+
};
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
function shouldRunRecipeSignalsAtEnd(state, signals2) {
|
|
514
|
+
return state.signalsPending && state.status === "changed" && signals2 != null;
|
|
515
|
+
}
|
|
516
|
+
function recipe(name, modules, options) {
|
|
517
|
+
return {
|
|
518
|
+
_isRecipe: true,
|
|
519
|
+
_modules: modules,
|
|
520
|
+
_signals: options?.signals,
|
|
521
|
+
async apply(ssh2, environment, parameters) {
|
|
522
|
+
return applyRecipe({
|
|
523
|
+
environment,
|
|
524
|
+
modules,
|
|
525
|
+
name,
|
|
526
|
+
options: parameters,
|
|
527
|
+
signals: options?.signals,
|
|
528
|
+
ssh: ssh2
|
|
529
|
+
});
|
|
530
|
+
},
|
|
531
|
+
async check(ssh2, environment) {
|
|
532
|
+
for (const childModule of modules) {
|
|
533
|
+
const connection = childModule.local === true ? null : ssh2;
|
|
534
|
+
let result;
|
|
535
|
+
try {
|
|
536
|
+
result = await childModule.check(connection, environment);
|
|
537
|
+
} catch (error) {
|
|
538
|
+
throw annotateRecipeChildError(childModule.name, error);
|
|
539
|
+
}
|
|
540
|
+
if (result === NEEDS_APPLY) return NEEDS_APPLY;
|
|
541
|
+
}
|
|
542
|
+
return "ok";
|
|
543
|
+
},
|
|
544
|
+
name
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// src/server.ts
|
|
549
|
+
function server(config) {
|
|
550
|
+
if (config.host.length === 0) {
|
|
551
|
+
throw new Error("ServerDefinition: host is required");
|
|
552
|
+
}
|
|
553
|
+
if (config.name.length === 0) {
|
|
554
|
+
throw new Error("ServerDefinition: name is required");
|
|
555
|
+
}
|
|
556
|
+
validateSshConfig(config.ssh);
|
|
557
|
+
if (config.run.length === 0) {
|
|
558
|
+
throw new Error("ServerDefinition: run must contain at least one module");
|
|
559
|
+
}
|
|
560
|
+
return config;
|
|
561
|
+
}
|
|
562
|
+
export {
|
|
563
|
+
NEEDS_APPLY,
|
|
564
|
+
apt,
|
|
565
|
+
archive,
|
|
566
|
+
assert,
|
|
567
|
+
assertValidModuleMetaEntries,
|
|
568
|
+
assertValidModuleMetaEntry,
|
|
569
|
+
command,
|
|
570
|
+
compose,
|
|
571
|
+
cron,
|
|
572
|
+
debug,
|
|
573
|
+
diffEnvironmentToMetaEntries,
|
|
574
|
+
download,
|
|
575
|
+
environmentMeta,
|
|
576
|
+
environmentToMetaEntries,
|
|
577
|
+
fail,
|
|
578
|
+
failed,
|
|
579
|
+
failedCommand,
|
|
580
|
+
file,
|
|
581
|
+
firstRun,
|
|
582
|
+
git,
|
|
583
|
+
group,
|
|
584
|
+
hostname,
|
|
585
|
+
isBooleanEnvironmentMetaEntry,
|
|
586
|
+
isEnvironmentMetaEntry,
|
|
587
|
+
isLazyEnvironmentMetaEntry,
|
|
588
|
+
isNumberEnvironmentMetaEntry,
|
|
589
|
+
isSshdPortMetaEntry,
|
|
590
|
+
isStringEnvironmentMetaEntry,
|
|
591
|
+
isSystemHostMetaEntry,
|
|
592
|
+
isSystemRebootMetaEntry,
|
|
593
|
+
mergeEnvironmentFromMeta,
|
|
594
|
+
meta,
|
|
595
|
+
mount,
|
|
596
|
+
net,
|
|
597
|
+
op,
|
|
598
|
+
pkg as package,
|
|
599
|
+
pause,
|
|
600
|
+
recipe,
|
|
601
|
+
releaseUpgrade,
|
|
602
|
+
rsync,
|
|
603
|
+
script,
|
|
604
|
+
server,
|
|
605
|
+
service,
|
|
606
|
+
shellQuote,
|
|
607
|
+
signals,
|
|
608
|
+
ssh,
|
|
609
|
+
sshd,
|
|
610
|
+
sshdPortMeta,
|
|
611
|
+
sysctl,
|
|
612
|
+
system,
|
|
613
|
+
systemHostMeta,
|
|
614
|
+
systemRebootMeta,
|
|
615
|
+
systemd,
|
|
616
|
+
ufw,
|
|
617
|
+
user,
|
|
618
|
+
when
|
|
619
|
+
};
|
|
620
|
+
//# sourceMappingURL=index.js.map
|