From 8edc7ed3ae1062af745fbe21b0753df6ad83fe6a Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 1 Feb 2015 17:34:04 -0400 Subject: propellor spin --- config-joey.hs | 14 +++++---- debian/changelog | 4 ++- propellor.cabal | 2 +- src/Propellor/Property/Cron.hs | 35 ++++++++++++++++------ src/Propellor/Property/Obnam.hs | 6 ++-- .../Property/SiteSpecific/GitAnnexBuilder.hs | 10 +++---- src/Propellor/Property/SiteSpecific/JoeySites.hs | 26 ++++++++-------- 7 files changed, 60 insertions(+), 37 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 5862b5b4..4b8ec46c 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -119,8 +119,8 @@ orca = standardSystem "orca.kitenet.net" Unstable "amd64" & Docker.docked (GitAnnexBuilder.standardAutoBuilderContainer dockerImage "amd64" 15 "2h") & Docker.docked (GitAnnexBuilder.standardAutoBuilderContainer dockerImage "i386" 45 "2h") & Docker.docked (GitAnnexBuilder.armelCompanionContainer dockerImage) - & Docker.docked (GitAnnexBuilder.armelAutoBuilderContainer dockerImage "1 3 * * *" "5h") - & Docker.docked (GitAnnexBuilder.androidAutoBuilderContainer dockerImage "1 1 * * *" "3h") + & Docker.docked (GitAnnexBuilder.armelAutoBuilderContainer dockerImage (Cron.Times "1 3 * * *") "5h") + & Docker.docked (GitAnnexBuilder.androidAutoBuilderContainer dockerImage (Cron.Times "1 1 * * *") "3h") & Docker.garbageCollected `period` Daily & Apt.buildDep ["git-annex"] `period` Daily @@ -151,7 +151,7 @@ kite = standardSystemUnhardened "kite.kitenet.net" Testing "amd64" & Ssh.passwordAuthentication True -- Since ssh password authentication is allowed: & Apt.serviceInstalledRunning "fail2ban" - & Obnam.backupEncrypted "/" "33 1 * * *" + & Obnam.backupEncrypted "/" (Cron.Times "33 1 * * *") [ "--repository=sftp://joey@eubackup.kitenet.net/~/lib/backup/kite.obnam" , "--client-name=kitenet.net" , "--exclude=/var/cache" @@ -331,11 +331,15 @@ elephant = standardSystem "elephant.kitenet.net" Unstable "amd64" beaver :: Host beaver = host "beaver.kitenet.net" & ipv6 "2001:4830:1600:195::2" + & Apt.serviceInstalledRunning "aiccu" & Apt.installed ["ssh"] & Ssh.pubKey SshDsa "ssh-dss AAAAB3NzaC1kc3MAAACBAIrLX260fY0Jjj/p0syNhX8OyR8hcr6feDPGOj87bMad0k/w/taDSOzpXe0Wet7rvUTbxUjH+Q5wPd4R9zkaSDiR/tCb45OdG6JsaIkmqncwe8yrU+pqSRCxttwbcFe+UU+4AAcinjVedZjVRDj2rRaFPc9BXkPt7ffk8GwEJ31/AAAAFQCG/gOjObsr86vvldUZHCteaJttNQAAAIB5nomvcqOk/TD07DLaWKyG7gAcW5WnfY3WtnvLRAFk09aq1EuiJ6Yba99Zkb+bsxXv89FWjWDg/Z3Psa22JMyi0HEDVsOevy/1sEQ96AGH5ijLzFInfXAM7gaJKXASD7hPbVdjySbgRCdwu0dzmQWHtH+8i1CMVmA2/a5Y/wtlJAAAAIAUZj2US2D378jBwyX1Py7e4sJfea3WSGYZjn4DLlsLGsB88POuh32aOChd1yzF6r6C2sdoPBHQcWBgNGXcx4gF0B5UmyVHg3lIX2NVSG1ZmfuLNJs9iKNu4cHXUmqBbwFYQJBvB69EEtrOw4jSbiTKwHFmqdA/mw1VsMB+khUaVw==" - & alias "backup.kitenet.net" & alias "usbackup.kitenet.net" & JoeySites.backupsBackedupFrom hosts "eubackup.kitenet.net" "/home/joey/lib/backup" + & Apt.serviceInstalledRunning "anacron" + & Cron.niceJob "system disk backed up" Cron.Weekly "root" "/" + "rsync -a -x / /home/joey/lib/backup/beaver.kitenet.net/" + --' __|II| ,. ---- __|II|II|__ ( \_,/\ @@ -419,7 +423,7 @@ standardSystemUnhardened hn suite arch motd = host hn & Sudo.enabledFor "joey" & GitHome.installedFor "joey" & Apt.installed ["vim", "screen", "less"] - & Cron.runPropellor "30 * * * *" + & Cron.runPropellor (Cron.Times "30 * * * *") -- I use postfix, or no MTA. & Apt.removed ["exim4", "exim4-daemon-light", "exim4-config", "exim4-base"] `onChange` Apt.autoRemove diff --git a/debian/changelog b/debian/changelog index 9aef3d03..0076087c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,9 @@ -propellor (2.0.1) UNRELEASED; urgency=medium +propellor (2.1.0) UNRELEASED; urgency=medium * Additional tor properties, including support for making relays, and naming bridges, relays, etc. + * New Cron.Times data type, which allows Cron.job to install + * daily/monthly/weekly jobs that anacron can run. (API change) -- Joey Hess Thu, 29 Jan 2015 01:41:07 -0400 diff --git a/propellor.cabal b/propellor.cabal index 6f4dba2f..41520baa 100644 --- a/propellor.cabal +++ b/propellor.cabal @@ -1,5 +1,5 @@ Name: propellor -Version: 2.0.0 +Version: 2.1.0 Cabal-Version: >= 1.6 License: BSD3 Maintainer: Joey Hess diff --git a/src/Propellor/Property/Cron.hs b/src/Propellor/Property/Cron.hs index 15cdd983..e75f5ee3 100644 --- a/src/Propellor/Property/Cron.hs +++ b/src/Propellor/Property/Cron.hs @@ -8,18 +8,26 @@ import Utility.FileMode import Data.Char -type CronTimes = String +-- | When to run a cron job. +-- +-- The Daily, Monthly, and Weekly options allow the cron job to be run +-- by anacron, which is useful for non-servers. +data Times + = Times String -- ^ formatted as in crontab(5) + | Daily + | Weekly + | Monthly --- | Installs a cron job, run as a specified user, in a particular --- directory. Note that the Desc must be unique, as it is used for the --- cron.d/ filename. +-- | Installs a cron job, that will run as a specified user in a particular +-- directory. Note that the Desc must be unique, as it is used for the +-- cron job filename. -- -- Only one instance of the cron job is allowed to run at a time, no matter -- how long it runs. This is accomplished using flock locking of the cron -- job file. -- -- The cron job's output will only be emailed if it exits nonzero. -job :: Desc -> CronTimes -> UserName -> FilePath -> String -> Property NoInfo +job :: Desc -> Times -> UserName -> FilePath -> String -> Property NoInfo job desc times user cddir command = combineProperties ("cronned " ++ desc) [ cronjobfile `File.hasContent` [ "# Generated by propellor" @@ -27,7 +35,11 @@ job desc times user cddir command = combineProperties ("cronned " ++ desc) , "SHELL=/bin/sh" , "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" , "" - , times ++ "\t" ++ user ++ "\tchronic " ++ shellEscape scriptfile + , case times of + Times t -> t ++ "\t" ++ user ++ "\tchronic " ++ shellEscape scriptfile + _ -> case user of + "root" -> "chronic " ++ shellEscape scriptfile + _ -> "chronic su " ++ user ++ " -c " ++ shellEscape scriptfile ] -- Use a separate script because it makes the cron job name -- prettier in emails, and also allows running the job manually. @@ -44,7 +56,12 @@ job desc times user cddir command = combineProperties ("cronned " ++ desc) `requires` Apt.installed ["util-linux", "moreutils"] where cmdline = "cd " ++ cddir ++ " && ( " ++ command ++ " )" - cronjobfile = "/etc/cron.d/" ++ name + cronjobfile = "/etc" cronjobdir name + cronjobdir = case times of + Times _ -> "cron.d" + Daily -> "cron.daily" + Weekly -> "cron.weekly" + Monthly -> "cron.monthly" scriptfile = "/usr/local/bin/" ++ name ++ "_cronjob" name = map sanitize desc sanitize c @@ -52,10 +69,10 @@ job desc times user cddir command = combineProperties ("cronned " ++ desc) | otherwise = '_' -- | Installs a cron job, and runs it niced and ioniced. -niceJob :: Desc -> CronTimes -> UserName -> FilePath -> String -> Property NoInfo +niceJob :: Desc -> Times -> UserName -> FilePath -> String -> Property NoInfo niceJob desc times user cddir command = job desc times user cddir ("nice ionice -c 3 sh -c " ++ shellEscape command) -- | Installs a cron job to run propellor. -runPropellor :: CronTimes -> Property NoInfo +runPropellor :: Times -> Property NoInfo runPropellor times = niceJob "propellor" times "root" localdir "./propellor" diff --git a/src/Propellor/Property/Obnam.hs b/src/Propellor/Property/Obnam.hs index adaf255c..c066d9f7 100644 --- a/src/Propellor/Property/Obnam.hs +++ b/src/Propellor/Property/Obnam.hs @@ -36,7 +36,7 @@ data NumClients = OnlyClient | MultipleClients -- > `requires` Ssh.keyImported SshRsa "root" (Context hostname) -- -- How awesome is that? -backup :: FilePath -> Cron.CronTimes -> [ObnamParam] -> NumClients -> Property NoInfo +backup :: FilePath -> Cron.Times -> [ObnamParam] -> NumClients -> Property NoInfo backup dir crontimes params numclients = backup' dir crontimes params numclients `requires` restored dir params @@ -46,7 +46,7 @@ backup dir crontimes params numclients = -- -- The gpg secret key will be automatically imported -- into root's keyring using Propellor.Property.Gpg.keyImported -backupEncrypted :: FilePath -> Cron.CronTimes -> [ObnamParam] -> NumClients -> Gpg.GpgKeyId -> Property HasInfo +backupEncrypted :: FilePath -> Cron.Times -> [ObnamParam] -> NumClients -> Gpg.GpgKeyId -> Property HasInfo backupEncrypted dir crontimes params numclients keyid = backup dir crontimes params' numclients `requires` Gpg.keyImported keyid "root" @@ -54,7 +54,7 @@ backupEncrypted dir crontimes params numclients keyid = params' = ("--encrypt-with=" ++ Gpg.getGpgKeyId keyid) : params -- | Does a backup, but does not automatically restore. -backup' :: FilePath -> Cron.CronTimes -> [ObnamParam] -> NumClients -> Property NoInfo +backup' :: FilePath -> Cron.Times -> [ObnamParam] -> NumClients -> Property NoInfo backup' dir crontimes params numclients = cronjob `describe` desc where desc = dir ++ " backed up by obnam" diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 7fc523f9..102e6a1d 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -9,7 +9,7 @@ import qualified Propellor.Property.Cron as Cron import qualified Propellor.Property.Ssh as Ssh import qualified Propellor.Property.File as File import qualified Propellor.Property.Docker as Docker -import Propellor.Property.Cron (CronTimes) +import Propellor.Property.Cron (Times) builduser :: UserName builduser = "builder" @@ -25,7 +25,7 @@ builddir = gitbuilderdir "build" type TimeOut = String -- eg, 5h -autobuilder :: Architecture -> CronTimes -> TimeOut -> Property HasInfo +autobuilder :: Architecture -> Times -> TimeOut -> Property HasInfo autobuilder arch crontimes timeout = combineProperties "gitannexbuilder" $ props & Apt.serviceInstalledRunning "cron" & Cron.niceJob "gitannexbuilder" crontimes builduser gitbuilderdir @@ -102,10 +102,10 @@ standardAutoBuilderContainer dockerImage arch buildminute timeout = Docker.conta & User.accountFor builduser & tree arch & buildDepsApt - & autobuilder arch (show buildminute ++ " * * * *") timeout + & autobuilder arch (Cron.Times $ show buildminute ++ " * * * *") timeout & Docker.tweaked -androidAutoBuilderContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Docker.Container +androidAutoBuilderContainer :: (System -> Docker.Image) -> Times -> TimeOut -> Docker.Container androidAutoBuilderContainer dockerImage crontimes timeout = androidContainer dockerImage "android-git-annex-builder" (tree "android") builddir & Apt.unattendedUpgrades @@ -166,7 +166,7 @@ armelCompanionContainer dockerImage = Docker.container "armel-git-annex-builder- & Ssh.authorizedKeys builduser (Context "armel-git-annex-builder") & Docker.tweaked -armelAutoBuilderContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Docker.Container +armelAutoBuilderContainer :: (System -> Docker.Image) -> Times -> TimeOut -> Docker.Container armelAutoBuilderContainer dockerImage crontimes timeout = Docker.container "armel-git-annex-builder" (dockerImage $ System (Debian Unstable) "armel") & os (System (Debian Testing) "armel") diff --git a/src/Propellor/Property/SiteSpecific/JoeySites.hs b/src/Propellor/Property/SiteSpecific/JoeySites.hs index 9f960aba..32b19764 100644 --- a/src/Propellor/Property/SiteSpecific/JoeySites.hs +++ b/src/Propellor/Property/SiteSpecific/JoeySites.hs @@ -45,8 +45,8 @@ oldUseNetServer hosts = propertyList "olduse.net server" $ props & Apt.serviceInstalledRunning "openbsd-inetd" & File.notPresent "/etc/cron.daily/leafnode" & File.notPresent "/etc/cron.d/leafnode" - & Cron.niceJob "oldusenet-expire" "11 1 * * *" "news" newsspool expirecommand - & Cron.niceJob "oldusenet-uucp" "*/5 * * * *" "news" "/" uucpcommand + & Cron.niceJob "oldusenet-expire" (Cron.Times "11 1 * * *") "news" newsspool expirecommand + & Cron.niceJob "oldusenet-uucp" (Cron.Times "*/5 * * * *") "news" "/" uucpcommand & Apache.siteEnabled "nntp.olduse.net" nntpcfg where newsspool = "/var/spool/news" @@ -65,7 +65,7 @@ oldUseNetServer hosts = propertyList "olduse.net server" $ props , " " ] - oldUseNetBackup = Obnam.backup datadir "33 4 * * *" + oldUseNetBackup = Obnam.backup datadir (Cron.Times "33 4 * * *") [ "--repository=sftp://2318@usw-s002.rsync.net/~/olduse.net" , "--client-name=spool" ] Obnam.OnlyClient @@ -113,7 +113,7 @@ mumbleServer :: [Host] -> Property HasInfo mumbleServer hosts = combineProperties hn $ props & Apt.serviceInstalledRunning "mumble-server" & Obnam.latestVersion - & Obnam.backup "/var/lib/mumble-server" "55 5 * * *" + & Obnam.backup "/var/lib/mumble-server" (Cron.Times "55 5 * * *") [ "--repository=sftp://2318@usw-s002.rsync.net/~/" ++ hn ++ ".obnam" , "--client-name=mumble" ] Obnam.OnlyClient @@ -138,7 +138,7 @@ obnamLowMem = combineProperties "obnam tuned for low memory use" gitServer :: [Host] -> Property HasInfo gitServer hosts = propertyList "git.kitenet.net setup" $ props & Obnam.latestVersion - & Obnam.backupEncrypted "/srv/git" "33 3 * * *" + & Obnam.backupEncrypted "/srv/git" (Cron.Times "33 3 * * *") [ "--repository=sftp://2318@usw-s002.rsync.net/~/git.kitenet.net" , "--client-name=wren" -- historical ] Obnam.OnlyClient (Gpg.GpgKeyId "1B169BE1") @@ -297,7 +297,7 @@ twitRss = combineProperties "twitter rss" $ props & feed "http://twitter.com/search/realtime?q=olduse+OR+git-annex+OR+debhelper+OR+etckeeper+OR+ikiwiki+-ashley_ikiwiki" "twittergrep" where dir = "/srv/web/tmp.kitenet.net/twitrss" - crontime = "15 * * * *" + crontime = Cron.Times "15 * * * *" feed url desc = Cron.job desc crontime "joey" dir $ "./twitRss " ++ shellEscape url ++ " > " ++ shellEscape ("../" ++ desc ++ ".rss") compiled = userScriptProperty "joey" @@ -313,7 +313,7 @@ twitRss = combineProperties "twitter rss" $ props -- Work around for expired ssl cert. -- (no longer expired, TODO remove this and change urls) pumpRss :: Property NoInfo -pumpRss = Cron.job "pump rss" "15 * * * *" "joey" "/srv/web/tmp.kitenet.net/" +pumpRss = Cron.job "pump rss" (Cron.Times "15 * * * *") "joey" "/srv/web/tmp.kitenet.net/" "wget https://pump2rss.com/feed/joeyh@identi.ca.atom -O pump.atom --no-check-certificate 2>/dev/null" ircBouncer :: Property HasInfo @@ -323,7 +323,7 @@ ircBouncer = propertyList "IRC bouncer" $ props & File.dirExists (takeDirectory conf) & File.hasPrivContent conf anyContext & File.ownerGroup conf "znc" "znc" - & Cron.job "znconboot" "@reboot" "znc" "~" "znc" + & Cron.job "znconboot" (Cron.Times "@reboot") "znc" "~" "znc" -- ensure running if it was not already & trivial (userScriptProperty "znc" ["znc || true"]) `describe` "znc running" @@ -347,9 +347,9 @@ githubBackup :: Property HasInfo githubBackup = propertyList "github-backup box" $ props & Apt.installed ["github-backup", "moreutils"] & githubKeys - & Cron.niceJob "github-backup run" "30 4 * * *" "joey" + & Cron.niceJob "github-backup run" (Cron.Times "30 4 * * *") "joey" "/home/joey/lib/backup" backupcmd - & Cron.niceJob "gitriddance" "30 4 * * *" "joey" + & Cron.niceJob "gitriddance" (Cron.Times "30 4 * * *") "joey" "/home/joey/lib/backup" gitriddancecmd where backupcmd = intercalate "&&" $ @@ -385,13 +385,13 @@ githubMirrors = plzuseurl u = "please submit changes to " ++ u ++ " instead of using github pull requests" rsyncNetBackup :: [Host] -> Property NoInfo -rsyncNetBackup hosts = Cron.niceJob "rsync.net copied in daily" "30 5 * * *" +rsyncNetBackup hosts = Cron.niceJob "rsync.net copied in daily" (Cron.Times "30 5 * * *") "joey" "/home/joey/lib/backup" "mkdir -p rsync.net && rsync --delete -az 2318@usw-s002.rsync.net: rsync.net" `requires` Ssh.knownHost hosts "usw-s002.rsync.net" "joey" backupsBackedupFrom :: [Host] -> HostName -> FilePath -> Property NoInfo backupsBackedupFrom hosts srchost destdir = Cron.niceJob desc - "@reboot" "joey" "/" cmd + (Cron.Times "@reboot") "joey" "/" cmd `requires` Ssh.knownHost hosts srchost "joey" where desc = "backups copied from " ++ srchost ++ " on boot" @@ -408,7 +408,7 @@ obnamRepos rs = propertyList ("obnam repos for " ++ unwords rs) `before` File.ownerGroup d "joey" "joey" podcatcher :: Property NoInfo -podcatcher = Cron.niceJob "podcatcher run hourly" "55 * * * *" +podcatcher = Cron.niceJob "podcatcher run hourly" (Cron.Times "55 * * * *") "joey" "/home/joey/lib/sound/podcasts" "xargs git-annex importfeed -c annex.genmetadata=true < feeds; mr --quiet update" `requires` Apt.installed ["git-annex", "myrepos"] -- cgit v1.2.3