From f164f19d954cf41c763272db913850dbb12251ee Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Wed, 6 Mar 2024 23:18:28 +0000 Subject: [PATCH] service starts and stops --- pkgs/ifwait/ifwait.fnl | 25 ++++++-- pkgs/ifwait/test-ifwait.fnl | 115 ++++++++++++++++++++++++++++-------- 2 files changed, 110 insertions(+), 30 deletions(-) diff --git a/pkgs/ifwait/ifwait.fnl b/pkgs/ifwait/ifwait.fnl index 3677252..9af41f9 100644 --- a/pkgs/ifwait/ifwait.fnl +++ b/pkgs/ifwait/ifwait.fnl @@ -1,9 +1,8 @@ (local nl (require :anoia.nl)) +(local { : assoc : system } (require :anoia)) ; (local { : view} (require :fennel)) -(local { : assoc : system } (require :anoia)) - (fn parse-args [args] (match args ["-v" & rest] (assoc (parse-args rest) :verbose true) @@ -31,9 +30,19 @@ _ {})] - (. got params.expecting))) + (not (not (. got params.expecting))))) + +(var up :unknown) +(fn toggle-service [service wanted?] + (when (not (= up wanted?)) + (set up + (if wanted? + (pcall system (.. "s6-rc -u change " service)) + (not (pcall system (.. "s6-rc -d change " service))))) + )) (fn run [args event-fn] + (set up :unknown) (let [parameters (assert (parse-args args) (.. "Usage: ifwait [-v] ifname [present|up|running]"))] @@ -41,9 +50,13 @@ (print (.. "ifwait: waiting for " parameters.link " to be " parameters.expecting))) - (each [e (event-fn) - &until (event-matches? parameters e)] - true))) + (if parameters.service + (each [e (event-fn)] + (if (= e.name parameters.link) + (toggle-service parameters.service (event-matches? parameters e)))) + (each [e (event-fn) + &until (event-matches? parameters e)] + true)))) (when (not (= (. arg 0) "test")) (run arg #(nl.events {:link true}))) diff --git a/pkgs/ifwait/test-ifwait.fnl b/pkgs/ifwait/test-ifwait.fnl index eef6acd..3381b5a 100644 --- a/pkgs/ifwait/test-ifwait.fnl +++ b/pkgs/ifwait/test-ifwait.fnl @@ -4,6 +4,14 @@ (var fake-system (fn [s] (print "executing " s))) (tset anoia :system #(fake-system $1)) +(macro expect= [actual expected] + `(let [ve# (view ,expected) + va# (view ,actual)] + (when (not (= ve# va#)) + (assert false + (.. "\nexpected " ve# "\ngot " va#) + )))) + (fn event-generator [events] (coroutine.wrap (fn [] @@ -19,34 +27,93 @@ (local ifwait (require :ifwait)) (let [gen (event-generator (file-events "events-fixture"))] - (ifwait.run ["-v" "dummy0" "up"] #gen) + (ifwait.run ["dummy0" "up"] #gen) (match (pcall gen) (true _) true (false msg) (error "didn't detect dummy0 up event"))) -(var succeeded? false) +(var upsies []) (set fake-system (fn [s] - (print "exec" s) - (if (s:match "addmember") (set succeeded? true)))) + (if (s:match "-u change addmember") + (table.insert upsies :u) + (s:match "-d change addmember") + (table.insert upsies :d)))) -(let [events - [{:event "newlink" - :hwaddr "b6:7d:5c:38:89:1d" - :index 21 - :mtu 1500 - :name "dummy0" - :running "no" - :stamp 857161382 - :up "no"} - {:event "newlink" - :hwaddr "52:f0:46:da:0c:0c" - :index 22 - :mtu 1500 - :name "dummy0" - :running "no" - :stamp 857161383 - :up "yes"}] - gen (event-generator events)] - (ifwait.run ["-v" "-s" "addmember" "dummy0" "up"] #gen) - (assert succeeded?)) +(fn newlink [name up running] + {:event "newlink" + :hwaddr "b6:7d:5c:38:89:1d" + :index (string.unpack ">i2" name) + :mtu 1500 + : name + : running + :stamp 857161382 + : up }) + +"when it gets events that don't match the interface, nothing happens" + +(let [gen (-> [(newlink "eth1" "no" "no")] event-generator)] + (set upsies []) + (ifwait.run [ "-s" "addmember" "dummy0" "up"] #gen) + (expect= upsies [])) + +"when it gets an event that should start the service, the service starts" + +(let [gen (-> + [(newlink "dummy0" "no" "no") + (newlink "dummy0" "yes" "no") + (newlink "eth1" "no" "no")] + event-generator)] + (set upsies []) + (ifwait.run ["-s" "addmember" "dummy0" "up"] #gen) + (expect= upsies [:d :u])) + +"when it gets an event that should stop the service, the service stops" + +(let [gen (-> + [(newlink "dummy0" "no" "no") + (newlink "dummy0" "yes" "no") + (newlink "dummy0" "no" "no") + ] + event-generator)] + (set upsies []) + (ifwait.run ["-s" "addmember" "dummy0" "up"] #gen) + (expect= upsies [:d :u :d])) + +"it does not call s6-rc again if the service is already in required state" + +(let [gen (-> + [(newlink "dummy0" "no" "no") + (newlink "dummy0" "yes" "no") + (newlink "dummy0" "yes" "yes") + (newlink "dummy0" "yes" "yes") + (newlink "dummy0" "yes" "no") + (newlink "dummy0" "no" "no") + ] + event-generator)] + (set upsies []) + (ifwait.run ["-s" "addmember" "dummy0" "up"] #gen) + (expect= upsies [:d :u :d])) + +"it handles an error return from s6-rc" + +(set fake-system + (fn [s] + (if (s:match "-u change addmember") + (table.insert upsies :u) + (s:match "-d change addmember") + (table.insert upsies :d)) + (error "false") + )) + +(let [gen (-> + [(newlink "dummy0" "yes" "no") + (newlink "dummy0" "yes" "yes") + (newlink "dummy0" "yes" "yes") + (newlink "dummy0" "yes" "no") + (newlink "dummy0" "no" "no") + ] + event-generator)] + (set upsies []) + (ifwait.run ["-s" "addmember" "dummy0" "up"] #gen) + (expect= upsies [:u :u :u :u]))