domain/architecture/system/deployment/nix_darwin/service/ops.bend

near-v-framework@0.7.0.0 · 111 lines · 0 definitions

1import Base
2import near-v-framework@0.7.0.0/domain/architecture/system/deployment/nix_darwin/service/type.bend as Sv
3
4def container(s: Sv.Service) -> String:
5  match s:
6    case Sv.Service{c, _, _, _, _, _, _, _, _}:
7      c
8
9def label(s: Sv.Service) -> String:
10  match s:
11    case Sv.Service{_, l, _, _, _, _, _, _, _}:
12      l
13
14def port(s: Sv.Service) -> U32:
15  match s:
16    case Sv.Service{_, _, _, _, _, _, _, _, p}:
17      p
18
19def start(s: Sv.Service) -> Sv.Start:
20  match s:
21    case Sv.Service{_, _, _, _, _, _, _, st, _}:
22      st
23
24def labels(xs: List<&2, Sv.Service>) -> List<&2, String>:
25  match xs:
26    case []:
27      []
28    case s <> rest:
29      label(s) <> labels(rest)
30
31def at_login(s: Sv.Start) -> Bool:
32  match s:
33    case Sv.AtLogin{}:
34      True{}
35    case Sv.AtBoot{}:
36      False{}
37
38# Whether any service needs a user session to start.
39def needs_login(xs: List<&2, Sv.Service>) -> Bool:
40  match xs:
41    case []:
42      False{}
43    case s <> rest:
44      at_login(start(s)) || needs_login(rest)
45
46# ---- a service as a nix-darwin launchd job ----
47# The program's path in the Nix store.
48def program(p: Sv.Program) -> String:
49  match p:
50    case Sv.RunNode{}:
51      "\"${pkgs.nodejs_24}/bin/node\""
52    case Sv.RunPython{}:
53      "\"${pkgs.python3.withPackages (ps: [ ps.watchdog ])}/bin/python3\""
54    case Sv.RunBash{}:
55      "\"${pkgs.bash}/bin/bash\""
56
57def quoted(xs: List<&2, String>) -> String:
58  match xs:
59    case []:
60      ""
61    case x <> rest:
62      " \"" ++ x ++ "\"" ++ quoted(rest)
63
64def env(e: Sv.Env) -> String:
65  match e:
66    case Sv.Plain{k, v}:
67      " " ++ k ++ " = \"" ++ v ++ "\";"
68    case Sv.Expr{k, x}:
69      " " ++ k ++ " = " ++ x ++ ";"
70
71def envs(xs: List<&2, Sv.Env>) -> String:
72  match xs:
73    case []:
74      ""
75    case e <> rest:
76      env(e) ++ envs(rest)
77
78# At login: a launch agent in the user's session. At boot: a launch daemon that runs as the user.
79def job_kind(s: Sv.Start) -> String:
80  match s:
81    case Sv.AtLogin{}:
82      "launchd.user.agents"
83    case Sv.AtBoot{}:
84      "launchd.daemons"
85
86def user_name(s: Sv.Start, +user: String) -> String:
87  match s:
88    case Sv.AtLogin{}:
89      ""
90    case Sv.AtBoot{}:
91      " UserName = \"" ++ user ++ "\";"
92
93def job(s: Sv.Service, +user: String, +logs: String) -> String:
94  match s:
95    case Sv.Service{_, +l, p, args, dir, e, +log, +st, _}:
96      "      " ++ job_kind(st) ++ ".\"" ++ l ++ "\".serviceConfig = {\n" ++
97      "        Label = \"" ++ l ++ "\";" ++ user_name(st, user) ++ "\n" ++
98      "        ProgramArguments = [ " ++ program(p) ++ quoted(args) ++ " ];\n" ++
99      "        WorkingDirectory = \"" ++ dir ++ "\";\n" ++
100      "        EnvironmentVariables = {" ++ envs(e) ++ " };\n" ++
101      "        RunAtLoad = true; KeepAlive = true; ThrottleInterval = 10;\n" ++
102      "        StandardOutPath = \"" ++ logs ++ "/" ++ log ++ ".log\";\n" ++
103      "        StandardErrorPath = \"" ++ logs ++ "/" ++ log ++ ".log\";\n" ++
104      "      };\n"
105
106def jobs(xs: List<&2, Sv.Service>, +user: String, +logs: String) -> String:
107  match xs:
108    case []:
109      ""
110    case s <> rest:
111      job(s, user, logs) ++ jobs(rest, user, logs)