feat: add Generate Systemd Unit operation and tests
This commit is contained in:
parent
80286f1e6f
commit
de0ad1d4bf
@ -329,6 +329,7 @@
|
||||
"Find / Replace",
|
||||
"Regular expression",
|
||||
"Fuzzy Match",
|
||||
"Generate Systemd Unit",
|
||||
"Offset checker",
|
||||
"Hamming 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/GenerateDeBruijnSequence.mjs";
|
||||
import "./tests/GenerateQRCode.mjs";
|
||||
import "./tests/GenerateSystemdUnit.mjs";
|
||||
import "./tests/GetAllCasings.mjs";
|
||||
import "./tests/GOST.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