From b4302c3fe8b0631433d716e50eaff75ce99c4a71 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Fri, 24 Nov 2023 19:13:04 +0200 Subject: [PATCH] WiP! Synit support --- README.md | 1 + nixproc/backends/synit/build-synit-env.nix | 37 ++++ .../backends/synit/generate-synit-service.nix | 30 +++ .../backends/synit/preserves-generator.nix | 52 +++++ .../create-managed-process-universal.nix | 6 + tools/default.nix | 4 + tools/synit/default.nix | 20 ++ tools/synit/nixproc-synit-deploy.in | 132 ++++++++++++ tools/synit/nixproc-synit-switch.in | 192 ++++++++++++++++++ 9 files changed, 474 insertions(+) create mode 100644 nixproc/backends/synit/build-synit-env.nix create mode 100644 nixproc/backends/synit/generate-synit-service.nix create mode 100644 nixproc/backends/synit/preserves-generator.nix create mode 100644 tools/synit/default.nix create mode 100644 tools/synit/nixproc-synit-deploy.in create mode 100644 tools/synit/nixproc-synit-switch.in diff --git a/README.md b/README.md index dfe410f..96f38bf 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Currently, the following process managers are supported: * `cygrunsrv`: Cygwin's [cygrunsrv](http://web.mit.edu/cygwin/cygwin_v1.3.2/usr/doc/Cygwin/cygrunsrv.README) * `s6-rc`: [s6-rc](https://skarnet.org/software/s6-rc) for managing services supervised by [s6](https://skarnet.org/software/s6) +* `synit`: [Synit](https://synit.org/) It can also work with the following solutions that are technically not categorized as process managers (but can still be used as such): diff --git a/nixproc/backends/synit/build-synit-env.nix b/nixproc/backends/synit/build-synit-env.nix new file mode 100644 index 0000000..7d5ae53 --- /dev/null +++ b/nixproc/backends/synit/build-synit-env.nix @@ -0,0 +1,37 @@ +{ pkgs ? import { inherit system; } +, system ? builtins.currentSystem +, stateDir ? "/var" +, runtimeDir ? "${stateDir}/run" +, logDir ? "${stateDir}/log" +, cacheDir ? "${stateDir}/cache" +, spoolDir ? "${stateDir}/spool" +, lockDir ? "${stateDir}/lock" +, libDir ? "${stateDir}/lib" +, tmpDir ? (if stateDir == "/var" then "/tmp" else "${stateDir}/tmp") +, forceDisableUserChange ? false +, callingUser ? null +, callingGroup ? null +, extraParams ? {} +, exprFile ? null +}@args: + +let + processesFun = import exprFile; + + processesFormalArgs = builtins.functionArgs processesFun; + + processesArgs = builtins.intersectAttrs processesFormalArgs (args // { + processManager = "synit"; + } // extraParams); + + processes = if exprFile == null then {} else processesFun processesArgs; +in +pkgs.buildEnv { + name = "synit"; + paths = map (processName: + let + process = builtins.getAttr processName processes; + in + process.pkg + ) (builtins.attrNames processes); +} diff --git a/nixproc/backends/synit/generate-synit-service.nix b/nixproc/backends/synit/generate-synit-service.nix new file mode 100644 index 0000000..7337fa0 --- /dev/null +++ b/nixproc/backends/synit/generate-synit-service.nix @@ -0,0 +1,30 @@ +{ stdenv, lib, execline, writeTextFile }: + +{ name, description, initialize, daemon, daemonArgs, instanceName, pidFile +, foregroundProcess, foregroundProcessArgs, path, environment, directory, umask +, nice, user, dependencies, credentials, overrides, postInstall }: + +let + util = import ../util { inherit lib; }; + + generator = import ./preserves-generator.nix { inherit lib; }; + toPreserves = generator.toPreserves { }; + + escapeArgs = args: + lib.concatMapStringsSep " " + (arg: ''"${lib.replaceStrings [ ''"'' ] [ ''\"'' ] (toString arg)}"'') args; + + processSpec = { + argv = "${daemon} ${toString daemonArgs}"; + env = environment; + } // (lib.attrsets.optionalAttrs (directory != null) { dir = directory; }); + +in writeTextFile { + name = "services-${name}"; + destination = "/services/${name}.pr"; + text = '' + { description: "${description}" }> + > + + ''; +} diff --git a/nixproc/backends/synit/preserves-generator.nix b/nixproc/backends/synit/preserves-generator.nix new file mode 100644 index 0000000..bc6a50d --- /dev/null +++ b/nixproc/backends/synit/preserves-generator.nix @@ -0,0 +1,52 @@ +{ lib }: + +let inherit (lib) isAttrs isBool isFunction isList; +in rec { + /* Generates text-encoded Preserves from an arbitrary value. + + Records are generated for lists with a final element in + the form of `{ record = «label»; }`. + + Type: toPreserves :: a -> string + + Example: + toPreserves { } [{ a = 0; b = 1; } "c" [ true false ] { record = "foo"; }] + => "" + */ + toPreserves = { }@args: + let + toPreserves' = toPreserves args; + concatItems = toString; + recordLabel = list: + with builtins; + let len = length list; + in if len == 0 then + null + else + let end = elemAt list (len - 1); + in if (isAttrs end) && (attrNames end) == [ "record" ] then + end + else + null; + in v: + if isAttrs v then + "{ ${ + concatItems + (lib.attrsets.mapAttrsToList (key: val: "${key}: ${toPreserves' val}") + v) + } }" + else if isList v then + let label = recordLabel v; + in if label == null then + "[ ${concatItems (map toPreserves' v)} ]" + else + "<${label.record} ${concatItems (map toPreserves' (lib.lists.init v))}>" + else if isBool v then + (if v then "#t" else "#f") + else if isFunction v then + abort "generators.toPreserves: cannot convert a function to Preserves" + else if isNull v then + "null" + else + builtins.toJSON v; +} diff --git a/nixproc/create-managed-process/universal/create-managed-process-universal.nix b/nixproc/create-managed-process/universal/create-managed-process-universal.nix index 157176d..ddc1429 100644 --- a/nixproc/create-managed-process/universal/create-managed-process-universal.nix +++ b/nixproc/create-managed-process/universal/create-managed-process-universal.nix @@ -113,6 +113,11 @@ let inherit (pkgs) stdenv writeTextFile lib execline s6; inherit s6-rc basePackages tmpDir runtimeDir forceDisableUserChange; }; + + generateSynitService = import ../../backends/synit/generate-synit-service.nix { + inherit (pkgs) stdenv lib execline writeTextFile; + }; + in import ../agnostic/create-managed-process.nix { inherit processManager; @@ -128,5 +133,6 @@ import ../agnostic/create-managed-process.nix { supervisord = generateSupervisordProgram; systemd = generateSystemdService; sysvinit = generateSystemVInitScript; + synit = generateSynitService; }; } diff --git a/tools/default.nix b/tools/default.nix index 4ee549e..d68d23d 100644 --- a/tools/default.nix +++ b/tools/default.nix @@ -47,6 +47,10 @@ rec { inherit (pkgs) stdenv getopt; }; + synit = import ./synit { + inherit (pkgs) stdenv getopt; + }; + systemd = import ./systemd { inherit (pkgs) stdenv getopt; }; diff --git a/tools/synit/default.nix b/tools/synit/default.nix new file mode 100644 index 0000000..1880a98 --- /dev/null +++ b/tools/synit/default.nix @@ -0,0 +1,20 @@ +{ stdenv, getopt }: + +stdenv.mkDerivation { + name = "nixproc-synit-tools"; + buildCommand = '' + mkdir -p $out/bin + + sed -e "s|/bin/bash|$SHELL|" \ + -e "s|@getopt@|${getopt}/bin/getopt|" \ + -e "s|@commonchecks@|${../commonchecks}|" \ + ${./nixproc-synit-switch.in} > $out/bin/nixproc-synit-switch + chmod +x $out/bin/nixproc-synit-switch + + sed -e "s|/bin/bash|$SHELL|" \ + -e "s|@getopt@|${getopt}/bin/getopt|" \ + -e "s|@commonchecks@|${../commonchecks}|" \ + ${./nixproc-synit-deploy.in} > $out/bin/nixproc-synit-deploy + chmod +x $out/bin/nixproc-synit-deploy + ''; +} diff --git a/tools/synit/nixproc-synit-deploy.in b/tools/synit/nixproc-synit-deploy.in new file mode 100644 index 0000000..aeafae9 --- /dev/null +++ b/tools/synit/nixproc-synit-deploy.in @@ -0,0 +1,132 @@ +#!/bin/bash -e + +showUsage() +{ + me="$(basename "$0")" + + cat <