liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

watch-outputs.fnl (3384B)


      1 (local { : %% : system : assoc : split : table= : dig } (require :anoia))
      2 (local svc (require :anoia.svc))
      3 (local { : kill &as ll} (require :lualinux))
      4 (import-macros { : define-tests : expect : expect= } :anoia.assert)
      5 
      6 (local { : view } (require :fennel))
      7 
      8 (fn output-refs [outputs]
      9   (let [result {}]
     10     (each [_ v (ipairs outputs)]
     11       (let [[service path] (split ":" v)
     12             paths (or (. result service) [])]
     13         (table.insert paths (split "/" path ))
     14         (tset result service paths)))
     15     result))
     16 
     17 (fn parse-args [args]
     18   (match args
     19     ["-r" service & rest] (assoc (parse-args rest)
     20                                  :controlled-service service
     21                                  :action :restart)
     22     ["-R" service & rest] (assoc (parse-args rest)
     23                                  :controlled-service service
     24                                  :action :restart-all)
     25     ["-s" signal service & rest] (assoc (parse-args rest)
     26                                         :controlled-service service
     27                                         :action [:signal signal])
     28     outputs { :output-references (output-refs outputs) } ))
     29 
     30 (define-tests
     31   (expect= (parse-args ["-r" "daemon"
     32                         "/nix/store/s1:out1"
     33                         "/nix/store/s2:out1" "/nix/store/s2:out2/ifname"])
     34            {:action "restart"
     35             :controlled-service "daemon"
     36             :output-references
     37             {"/nix/store/s1" [["out1"]]
     38              "/nix/store/s2" [["out1"] ["out2" "ifname"]]}}
     39            ))
     40 
     41 (fn changed? [paths old-tree new-tree]
     42   (accumulate [changed? false
     43                _ path (ipairs paths)]
     44     (or changed? (not (table= (dig old-tree path) (dig new-tree path))))))
     45 
     46 (define-tests
     47   (expect (changed? [["ifname"]] {:ifname "true"} {:ifindex 2}))
     48   (expect (changed? [["ifname"]] {:ifname "true"} {:ifname "false"}))
     49   (expect (not (changed? [["ifname"]] {:ifname "true"} {:ifname "true"})))
     50   (expect (not (changed? [["mtu"]] {:ifname "true"} {:ifname "false"})))
     51   (expect (not (changed? [["mtu"]] {:ifname "true"} {:ifname "false"})))
     52   )
     53 
     54 (fn do-action [action service]
     55   (case action
     56     :restart (system (%% "s6-svc -r /run/service/%s" service))
     57     :restart-all (system (%% "s6-rc -b -d change %q; s6-rc-up-tree %q" service service))
     58     [:signal n] (system (%% "s6-svc -s %q /run/service/%s" n service))))
     59 
     60 (local POLLIN  0x0001)
     61 (local POLLHUP 0x0010)
     62 
     63 (fn wait-for-change [services]
     64   (let [pollfds (collect [s _p (ipairs services)]
     65                   (bor (lshift (s:fileno) 32)
     66                        (lshift (bor POLLIN POLLHUP) 16)))]
     67     (ll.poll pollfds)))
     68 
     69 (fn open-services [output-references]
     70   (collect [s p (pairs output-references)]
     71     (values (svc.open s) p)))
     72 
     73 (fn run []
     74   (let [trees {}
     75         {
     76          : output-references
     77          : controlled-service
     78          : action
     79          : watched-service
     80          : paths } (parse-args arg)
     81         services (open-services output-references)]
     82     (while true
     83       (when
     84           (accumulate [changed false
     85                        service paths (pairs services)]
     86             (let [new-tree (service:output ".")]
     87               (if (changed? paths (or (. trees service) {}) new-tree)
     88                   (do (tset trees service new-tree) true)
     89                   changed)))
     90         (do-action action controlled-service))
     91       (wait-for-change services))))
     92 
     93 
     94 
     95 
     96 { : run }