feat: add Generate Systemd Unit operation and tests
This commit is contained in:
parent
80286f1e6f
commit
de0ad1d4bf
@ -329,6 +329,7 @@
|
|||||||
"Find / Replace",
|
"Find / Replace",
|
||||||
"Regular expression",
|
"Regular expression",
|
||||||
"Fuzzy Match",
|
"Fuzzy Match",
|
||||||
|
"Generate Systemd Unit",
|
||||||
"Offset checker",
|
"Offset checker",
|
||||||
"Hamming Distance",
|
"Hamming Distance",
|
||||||
"Levenshtein Distance",
|
"Levenshtein Distance",
|
||||||
|
|||||||
126
src/core/operations/GenerateSystemdUnit.mjs
Normal file
126
src/core/operations/GenerateSystemdUnit.mjs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/**
|
||||||
|
* @author 0xff1ce [github.com/0xff1ce]
|
||||||
|
* @copyright Crown Copyright 2026
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
|
||||||
|
const RESTART_OPTIONS = ["no", "on-sucess", "on-failure", "on-abnormal", "on-watchdog", "on-abort", "always"];
|
||||||
|
const TYPE_OPTIONS = ["simple", "exec", "forking", "oneshot", "dbus", "notify", "idle"];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GenerateSystemdUnit operation
|
||||||
|
*/
|
||||||
|
class GenerateSystemdUnit extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GenerateSystemdUnit constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Generate Systemd Unit";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Generates a systemd unit file based on provided inputs";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Description",
|
||||||
|
"type": "string",
|
||||||
|
"value": "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "After",
|
||||||
|
"type": "string",
|
||||||
|
"value": "network.target",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Wants",
|
||||||
|
"type": "string",
|
||||||
|
"value": "network-online.target",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Restart",
|
||||||
|
"type": "option",
|
||||||
|
"value": RESTART_OPTIONS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Type",
|
||||||
|
"type": "option",
|
||||||
|
"value": TYPE_OPTIONS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ExecStart",
|
||||||
|
"type": "string",
|
||||||
|
"value": "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Environment",
|
||||||
|
"type": "string",
|
||||||
|
"value": "KEY=VALUE",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "User",
|
||||||
|
"type": "string",
|
||||||
|
"value": "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "WorkingDirectory",
|
||||||
|
"type": "string",
|
||||||
|
"value": "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "WantedBy",
|
||||||
|
"type": "string",
|
||||||
|
"value": "multi-user.target",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(_, args) {
|
||||||
|
const description = args[0];
|
||||||
|
const after = args[1];
|
||||||
|
const wants = args[2];
|
||||||
|
const restart = args[3];
|
||||||
|
const type = args[4];
|
||||||
|
const execStart = args[5];
|
||||||
|
const environment = args[6];
|
||||||
|
const user = args[7];
|
||||||
|
const workingDirectory = args[8];
|
||||||
|
const wantedBy = args[9];
|
||||||
|
|
||||||
|
const lines = [];
|
||||||
|
|
||||||
|
// [Unit] section
|
||||||
|
lines.push("[Unit]");
|
||||||
|
if (description) lines.push(`Description=${description}`);
|
||||||
|
if (after) lines.push(`After=${after}`);
|
||||||
|
if (wants) lines.push(`Wants=${wants}`);
|
||||||
|
|
||||||
|
// [Service] section
|
||||||
|
lines.push("");
|
||||||
|
lines.push("[Service]");
|
||||||
|
if (restart) lines.push(`Restart=${restart}`);
|
||||||
|
if (type) lines.push(`Type=${type}`);
|
||||||
|
if (execStart) lines.push(`ExecStart=${execStart}`);
|
||||||
|
if (environment) lines.push(`Environment=${environment}`);
|
||||||
|
if (user) lines.push(`User=${user}`);
|
||||||
|
if (workingDirectory) lines.push(`WorkingDirectory=${workingDirectory}`);
|
||||||
|
|
||||||
|
// [Install] section
|
||||||
|
lines.push("");
|
||||||
|
lines.push("[Install]");
|
||||||
|
if (wantedBy) lines.push(`WantedBy=${wantedBy}`);
|
||||||
|
|
||||||
|
return lines.join("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GenerateSystemdUnit;
|
||||||
@ -80,6 +80,7 @@ import "./tests/GenerateAllChecksums.mjs";
|
|||||||
import "./tests/GenerateAllHashes.mjs";
|
import "./tests/GenerateAllHashes.mjs";
|
||||||
import "./tests/GenerateDeBruijnSequence.mjs";
|
import "./tests/GenerateDeBruijnSequence.mjs";
|
||||||
import "./tests/GenerateQRCode.mjs";
|
import "./tests/GenerateQRCode.mjs";
|
||||||
|
import "./tests/GenerateSystemdUnit.mjs";
|
||||||
import "./tests/GetAllCasings.mjs";
|
import "./tests/GetAllCasings.mjs";
|
||||||
import "./tests/GOST.mjs";
|
import "./tests/GOST.mjs";
|
||||||
import "./tests/Gunzip.mjs";
|
import "./tests/Gunzip.mjs";
|
||||||
|
|||||||
100
tests/operations/tests/GenerateSystemdUnit.mjs
Normal file
100
tests/operations/tests/GenerateSystemdUnit.mjs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/**
|
||||||
|
* GenerateSystemdUnit tests.
|
||||||
|
*
|
||||||
|
* @author 0xff1ce
|
||||||
|
* @copyright Crown Copyright 2026
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Generate minimal systemd unit with required defaults",
|
||||||
|
input: "",
|
||||||
|
expectedMatch: /\[Unit\]\nAfter=network\.target\nWants=network-online\.target\n\n\[Service\]\nEnvironment=KEY=VALUE\n\n\[Install\]\nWantedBy=multi-user\.target/,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Generate Systemd Unit",
|
||||||
|
args: [
|
||||||
|
"", // Description
|
||||||
|
"network.target", // After
|
||||||
|
"network-online.target", // Wants
|
||||||
|
"", // Restart
|
||||||
|
"", // Type
|
||||||
|
"", // ExecStart
|
||||||
|
"KEY=VALUE", // Environment
|
||||||
|
"", // User
|
||||||
|
"", // WorkingDirectory
|
||||||
|
"multi-user.target" // WantedBy
|
||||||
|
]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Generate full systemd unit with all fields populated",
|
||||||
|
input: "",
|
||||||
|
expectedMatch: /\[Unit\]\nDescription=My Service\nAfter=network\.target\nWants=network-online\.target\n\n\[Service\]\nRestart=always\nType=simple\nExecStart=\/usr\/bin\/node app\.js\nEnvironment=NODE_ENV=production\nUser=www-data\nWorkingDirectory=\/var\/www\n\n\[Install\]\nWantedBy=multi-user\.target/,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Generate Systemd Unit",
|
||||||
|
args: [
|
||||||
|
"My Service",
|
||||||
|
"network.target",
|
||||||
|
"network-online.target",
|
||||||
|
"always",
|
||||||
|
"simple",
|
||||||
|
"/usr/bin/node app.js",
|
||||||
|
"NODE_ENV=production",
|
||||||
|
"www-data",
|
||||||
|
"/var/www",
|
||||||
|
"multi-user.target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Generate unit without optional Service fields",
|
||||||
|
input: "",
|
||||||
|
expectedMatch: /\[Unit\]\nDescription=Test\nAfter=network\.target\nWants=network-online\.target\n\n\[Service\]\nEnvironment=KEY=VALUE\n\n\[Install\]\nWantedBy=multi-user\.target/,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Generate Systemd Unit",
|
||||||
|
args: [
|
||||||
|
"Test",
|
||||||
|
"network.target",
|
||||||
|
"network-online.target",
|
||||||
|
"", // Restart
|
||||||
|
"", // Type
|
||||||
|
"", // ExecStart
|
||||||
|
"KEY=VALUE",
|
||||||
|
"", // User
|
||||||
|
"", // WorkingDirectory
|
||||||
|
"multi-user.target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Generate unit with custom dependencies and install target",
|
||||||
|
input: "",
|
||||||
|
expectedMatch: /\[Unit\]\nDescription=Custom\nAfter=docker\.service\nWants=network\.target\n\n\[Service\]\nRestart=on-failure\nType=exec\nExecStart=\/bin\/bash start\.sh\nEnvironment=ENV=dev\n\n\[Install\]\nWantedBy=graphical\.target/,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Generate Systemd Unit",
|
||||||
|
args: [
|
||||||
|
"Custom",
|
||||||
|
"docker.service",
|
||||||
|
"network.target",
|
||||||
|
"on-failure",
|
||||||
|
"exec",
|
||||||
|
"/bin/bash start.sh",
|
||||||
|
"ENV=dev",
|
||||||
|
"", // User
|
||||||
|
"", // WorkingDirectory
|
||||||
|
"graphical.target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]);
|
||||||
Loading…
x
Reference in New Issue
Block a user