aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2021-07-20 15:43:13 -0700
committerSean Whitton <spwhitton@spwhitton.name>2021-07-24 12:00:33 -0700
commit4e2ff7598371eff45fd750ff5838e6259204e33a (patch)
treefd0c3d4598b4e0f8ef62edf5260b4bf0096725c8
parent5f69000e489b3840e07925a5b2f21ce3bc8adbd6 (diff)
downloadconsfigurator-4e2ff7598371eff45fd750ff5838e6259204e33a.tar.gz
add CRON:USER-CRONTAB
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
-rw-r--r--src/package.lisp6
-rw-r--r--src/property/cron.lisp36
2 files changed, 40 insertions, 2 deletions
diff --git a/src/package.lisp b/src/package.lisp
index 32056c4..f233b2b 100644
--- a/src/package.lisp
+++ b/src/package.lisp
@@ -721,13 +721,15 @@
(defpackage :consfigurator.property.cron
(:use #:cl #:consfigurator)
- (:local-nicknames (#:service #:consfigurator.property.service)
+ (:local-nicknames (#:re #:cl-ppcre)
+ (#:service #:consfigurator.property.service)
(#:apt #:consfigurator.property.apt)
(#:os #:consfigurator.property.os)
(#:file #:consfigurator.property.file))
(:export #:system-job
#:nice-system-job
- #:runs-consfigurator))
+ #:runs-consfigurator
+ #:user-crontab))
(defpackage :consfigurator.property.lets-encrypt
(:use #:cl #:alexandria #:consfigurator)
diff --git a/src/property/cron.lisp b/src/property/cron.lisp
index 3076967..f568e14 100644
--- a/src/property/cron.lisp
+++ b/src/property/cron.lisp
@@ -105,3 +105,39 @@ HOSTDEPLOY etc."
(nice-system-job
"consfigurator" when "root"
"${XDG_CACHE_HOME:-$HOME/.cache}/consfigurator/images/latest"))
+
+(defprop user-crontab :posix (env &rest jobs)
+ "Set the contents of the current user's crontab. ENV is like the ENV argument
+to RUN/MRUN, except that the environment variables will be set at the top of
+the generated crontab. Each of JOBS is a line for the body of the crontab.
+In both ENV and JOBS, the string \"$HOME\" is replaced with the remote home
+directory."
+ ;; We set the contents of the whole file rather than providing properties to
+ ;; specify individual jobs, because then it is straightforward to
+ ;; incrementally develop jobs without having to unapply old versions first.
+ (:desc "Crontab populated")
+ (:apply
+ (unless (member :path env)
+ (setq env
+ (list*
+ :path
+ (if (zerop (get-connattr :remote-uid))
+ "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
+ "/usr/local/bin:/bin:/usr/bin")
+ env)))
+ (let* ((home (drop-trailing-slash
+ (unix-namestring (get-connattr :remote-home))))
+ (old (runlines :may-fail "crontab" "-l"))
+ (new
+ (mapcar
+ (lambda (line) (re:regex-replace-all #?/\$HOME/ line home))
+ (nconc
+ (list "# Automatically updated by Consfigurator; do not edit" "")
+ (loop for (k v) on env by #'cddr
+ collect (strcat (symbol-name k) "=" v))
+ (list "")
+ jobs))))
+ (if (tree-equal old new :test #'string=)
+ :no-change
+ (mrun :input (unlines new)
+ "crontab" "-u" (get-connattr :remote-user) "-")))))