From 031151d1923156b37e1a4e3ce0ba7c5d1cbc9ca0 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 18 May 2014 14:18:56 -0400 Subject: [PATCH 01/75] propellor spin From 705f4fe1c54b5bdeebdf5b47afa62186c91a5071 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 18 May 2014 14:20:17 -0400 Subject: [PATCH 02/75] propellor spin From 5e46463a1065a95fff82ec566aa0ee0fb06c91c5 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 10:46:33 -0400 Subject: [PATCH 03/75] propellor spin From 8ab6799d4868ffc9430353597d903d7b19904f44 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 10:51:28 -0400 Subject: [PATCH 04/75] Ensure that kernel hostname is same as /etc/hostname when configuring hostname. --- debian/changelog | 2 ++ src/Propellor/Property/Hostname.hs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 70d66e0..9d1d9a1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,8 @@ propellor (0.5.3) UNRELEASED; urgency=medium * Fix unattended-upgrades config for !stable. + * Ensure that kernel hostname is same as /etc/hostname when configuring + hostname. -- Joey Hess Sun, 18 May 2014 13:44:00 -0400 diff --git a/src/Propellor/Property/Hostname.hs b/src/Propellor/Property/Hostname.hs index 031abb9..d5af32a 100644 --- a/src/Propellor/Property/Hostname.hs +++ b/src/Propellor/Property/Hostname.hs @@ -13,7 +13,6 @@ sane = property ("sane hostname") (ensureProperty . setTo =<< getHostName) setTo :: HostName -> Property setTo hn = combineProperties desc go - `onChange` cmdProperty "hostname" [basehost] where desc = "hostname " ++ hn (basehost, domain) = separate (== '.') hn @@ -24,6 +23,7 @@ setTo hn = combineProperties desc go then Nothing else Just $ File.fileProperty desc addhostline "/etc/hosts" + , cmdProperty "hostname" [basehost] ] hostip = "127.0.1.1" From 533ac36412d6366f536f8817ade7fd78fa84cbd7 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 10:52:00 -0400 Subject: [PATCH 05/75] propellor spin --- src/Propellor/Property/Hostname.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Propellor/Property/Hostname.hs b/src/Propellor/Property/Hostname.hs index d5af32a..a924801 100644 --- a/src/Propellor/Property/Hostname.hs +++ b/src/Propellor/Property/Hostname.hs @@ -23,7 +23,7 @@ setTo hn = combineProperties desc go then Nothing else Just $ File.fileProperty desc addhostline "/etc/hosts" - , cmdProperty "hostname" [basehost] + , Just $ cmdProperty "hostname" [basehost] ] hostip = "127.0.1.1" From 02783c8290d71fdf754228222beceffb26281641 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 11:10:05 -0400 Subject: [PATCH 06/75] tags workaround --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fba684d..1956e9d 100644 --- a/Makefile +++ b/Makefile @@ -30,8 +30,10 @@ clean: find -name \*.hi -exec rm {} \; # hothasktags chokes on some template haskell etc, so ignore errors +# duplicate tags with Propellor.Property. removed from the start, as we +# often import qualified by just the module base name. tags: - find . | grep -v /.git/ | grep -v /tmp/ | grep -v /dist/ | grep -v /doc/ | egrep '\.hs$$' | xargs hothasktags > tags 2>/dev/null + find . | grep -v /.git/ | grep -v /tmp/ | grep -v /dist/ | grep -v /doc/ | egrep '\.hs$$' | xargs hothasktags | perl -ne 'print; s/Propellor\.Property\.//; print' > tags 2>/dev/null # Upload to hackage. hackage: From 389aa748d48d7f8a47b9563c4e2e6240dcec6b7b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 13:31:31 -0400 Subject: [PATCH 07/75] propellor spin From 2e050607079393c3bdac789c0751a203a2a2faf9 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 16:52:06 -0400 Subject: [PATCH 08/75] sort tags --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1956e9d..2f339a8 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ clean: # duplicate tags with Propellor.Property. removed from the start, as we # often import qualified by just the module base name. tags: - find . | grep -v /.git/ | grep -v /tmp/ | grep -v /dist/ | grep -v /doc/ | egrep '\.hs$$' | xargs hothasktags | perl -ne 'print; s/Propellor\.Property\.//; print' > tags 2>/dev/null + find . | grep -v /.git/ | grep -v /tmp/ | grep -v /dist/ | grep -v /doc/ | egrep '\.hs$$' | xargs hothasktags | perl -ne 'print; s/Propellor\.Property\.//; print' | sort > tags 2>/dev/null # Upload to hackage. hackage: From c8a653af5dfd6f876d2c5d77ef047ba47274e3d7 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 17:27:21 -0400 Subject: [PATCH 09/75] propellor spin --- config-joey.hs | 25 +++++--- src/Propellor/Property/Docker.hs | 4 ++ .../Property/SiteSpecific/GitAnnexBuilder.hs | 59 +++++++++++++------ 3 files changed, 62 insertions(+), 26 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 4580589..3d464e3 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -189,28 +189,37 @@ hosts = -- (o) ` (Just "remotes/origin/old-kitenet.net") -- git-annex autobuilder containers - , gitAnnexBuilder "amd64" 15 - , gitAnnexBuilder "i386" 45 - -- armel builder has a companion container that run amd64 and + , standardGitAnnexBuilder "amd64" 15 "2h" + , standardGitAnnexBuilder "i386" 45 "2h" + -- armel builder has a companion container using amd64 that -- runs the build first to get TH splices. They share a home -- directory, and need to have the same versions of all haskell - -- libraries installed. + -- libraries installed. The armel builder can ssh in to the + -- companion. , Docker.container "armel-git-annex-builder-companion" (image $ System (Debian Unstable) "amd64") & Docker.volume GitAnnexBuilder.homedir & Apt.unattendedUpgrades + & GitAnnexBuilder.treeDeps "armel" + & GitAnnexBuilder.cabalDeps + & GitAnnexBuilder.sshKeyGen + & Docker.expose "22" + & Apt.serviceInstalledRunning "ssh" , Docker.container "armel-git-annex-builder" (image $ System (Debian Unstable) "armel") & Docker.link "armel-git-annex-builder-companion" "companion" & Docker.volumes_from "armel-git-annex-builder-companion" --- & GitAnnexBuilder.builder "armel" "15 * * * *" True + & GitAnnexBuilder.builder "armel" "1 3 * * *" "5h" True + -- TODO: automate installing haskell libs + -- (Currently have to run + -- git-annex/standalone/linux/install-haskell-packages) & Apt.unattendedUpgrades ] ++ monsters -gitAnnexBuilder :: Architecture -> Int -> Host -gitAnnexBuilder arch buildminute = Docker.container (arch ++ "-git-annex-builder") +standardGitAnnexBuilder :: Architecture -> Int -> GitAnnexBuilder.TimeOut -> Host +standardGitAnnexBuilder arch buildminute timeout = Docker.container (arch ++ "-git-annex-builder") (image $ System (Debian Unstable) arch) - & GitAnnexBuilder.builder arch (show buildminute ++ " * * * *") True + & GitAnnexBuilder.builder arch (show buildminute ++ " * * * *") timeout True & Apt.unattendedUpgrades -- This is my standard system setup. diff --git a/src/Propellor/Property/Docker.hs b/src/Propellor/Property/Docker.hs index 09d7d6a..68fbced 100644 --- a/src/Propellor/Property/Docker.hs +++ b/src/Propellor/Property/Docker.hs @@ -156,6 +156,10 @@ name = runProp "name" publish :: String -> Property publish = runProp "publish" +-- | Expose a container's port without publishing it. +expose :: String -> Property +expose = runProp "expose" + -- | Username or UID for container. user :: String -> Property user = runProp "user" diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 677aa76..9754d4f 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -18,25 +18,14 @@ gitbuilderdir = homedir "gitbuilder" builddir :: FilePath builddir = gitbuilderdir "build" -builder :: Architecture -> CronTimes -> Bool -> Property -builder arch crontimes rsyncupload = combineProperties "gitannexbuilder" - [ Apt.stdSourcesList Unstable - , Apt.buildDep ["git-annex"] - , Apt.installed ["git", "rsync", "moreutils", "ca-certificates", - "liblockfile-simple-perl", "cabal-install", "vim", "less"] +type TimeOut = String -- eg, 5h + +builder :: Architecture -> CronTimes -> TimeOut -> Bool -> Property +builder buildarch crontimes timeout rsyncupload = combineProperties "gitannexbuilder" + [ treeDeps buildarch , Apt.serviceInstalledRunning "cron" - , User.accountFor builduser - , check (not <$> doesDirectoryExist gitbuilderdir) $ userScriptProperty builduser - [ "git clone git://git.kitenet.net/gitannexbuilder " ++ gitbuilderdir - , "cd " ++ gitbuilderdir - , "git checkout " ++ arch - ] - `describe` "gitbuilder setup" - , check (not <$> doesDirectoryExist builddir) $ userScriptProperty builduser - [ "git clone git://git-annex.branchable.com/ " ++ builddir - ] - , "git-annex source build deps installed" ==> Apt.buildDepIn builddir - , Cron.niceJob "gitannexbuilder" crontimes builduser gitbuilderdir "git pull ; ./autobuild" + , Cron.niceJob "gitannexbuilder" crontimes builduser gitbuilderdir $ + "git pull ; timeout " ++ timeout ++ " ./autobuild" -- The builduser account does not have a password set, -- instead use the password privdata to hold the rsync server -- password used to upload the built image. @@ -55,3 +44,37 @@ builder arch crontimes rsyncupload = combineProperties "gitannexbuilder" , makeChange $ writeFile f "no password configured" ) ] + +treeDeps :: Architecture -> Property +treeDeps buildarch = combineProperties "gitannexbuilder" + [ Apt.stdSourcesList Unstable + , Apt.buildDep ["git-annex"] + , Apt.installed ["git", "rsync", "moreutils", "ca-certificates", + "liblockfile-simple-perl", "cabal-install", "vim", "less"] + , User.accountFor builduser + , check (not <$> doesDirectoryExist gitbuilderdir) $ userScriptProperty builduser + [ "git clone git://git.kitenet.net/gitannexbuilder " ++ gitbuilderdir + , "cd " ++ gitbuilderdir + , "git checkout " ++ buildarch + ] + `describe` "gitbuilder setup" + , check (not <$> doesDirectoryExist builddir) $ userScriptProperty builduser + [ "git clone git://git-annex.branchable.com/ " ++ builddir + ] + , "git-annex source build deps installed" ==> Apt.buildDepIn builddir + ] + +-- Installs current versions of git-annex's deps from cabal, but only +-- does so once. +cabalDeps :: Property +cabalDeps = flagFile go cabalupdated + where + go = userScriptProperty builduser ["cabal update && cabal install git-annex --only-dependencies || true"] + cabalupdated = homedir ".cabal" "packages" "hackage.haskell.org" "00-index.cache" + +-- Ensure a ssh key is set up. +sshKeyGen :: Property +sshKeyGen = flagFile gen f + where + gen = userScriptProperty builduser ["ssh-keygen -t RSA -N '' -f " ++ f] + f = homedir ".ssh" "id_rsa" From e1df0634c864c90bb923af5d9edc99275c5faad4 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 17:29:46 -0400 Subject: [PATCH 10/75] hostname setting is trivial property --- src/Propellor/Property/Hostname.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Propellor/Property/Hostname.hs b/src/Propellor/Property/Hostname.hs index a924801..3859649 100644 --- a/src/Propellor/Property/Hostname.hs +++ b/src/Propellor/Property/Hostname.hs @@ -23,7 +23,7 @@ setTo hn = combineProperties desc go then Nothing else Just $ File.fileProperty desc addhostline "/etc/hosts" - , Just $ cmdProperty "hostname" [basehost] + , Just $ trivial $ cmdProperty "hostname" [basehost] ] hostip = "127.0.1.1" From 9695eac0ebfec9b3bd1a180f04a40fd25f9fb60e Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 18:27:37 -0400 Subject: [PATCH 11/75] propellor spin From 3de92ad174879c81d2017cdd2f5dc2e14207b7a3 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 18:31:21 -0400 Subject: [PATCH 12/75] propellor spin From 9822babea750dc038422ac9a781d816068c3c87b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 18:43:23 -0400 Subject: [PATCH 13/75] propellor spin --- config-joey.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index 3d464e3..9fa5dba 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -208,7 +208,7 @@ hosts = -- (o) ` , Docker.container "armel-git-annex-builder" (image $ System (Debian Unstable) "armel") & Docker.link "armel-git-annex-builder-companion" "companion" - & Docker.volumes_from "armel-git-annex-builder-companion" + & Docker.volumes_from GitAnnexBuilder.homedir & GitAnnexBuilder.builder "armel" "1 3 * * *" "5h" True -- TODO: automate installing haskell libs -- (Currently have to run From ef3260af9542fdfbde3ac1e15098478a55d0c137 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 18:49:36 -0400 Subject: [PATCH 14/75] propellor spin --- config-joey.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 9fa5dba..9bf8f1a 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -207,8 +207,8 @@ hosts = -- (o) ` & Apt.serviceInstalledRunning "ssh" , Docker.container "armel-git-annex-builder" (image $ System (Debian Unstable) "armel") - & Docker.link "armel-git-annex-builder-companion" "companion" - & Docker.volumes_from GitAnnexBuilder.homedir + & Docker.link "armel-git-annex-builder-companion.orca.kitenet.net.propellor" "companion" + & Docker.volumes_from "armel-git-annex-builder-companion.orca.kitenet.net.propellor" & GitAnnexBuilder.builder "armel" "1 3 * * *" "5h" True -- TODO: automate installing haskell libs -- (Currently have to run From fea5a229833ca07b2fabbba58a80323700d722ee Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 18:52:20 -0400 Subject: [PATCH 15/75] propellor spin From c8b59684cd45ef2736a4e492e659844ea74e2c85 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 18:53:56 -0400 Subject: [PATCH 16/75] propellor spin --- config-joey.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 9bf8f1a..3d464e3 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -207,8 +207,8 @@ hosts = -- (o) ` & Apt.serviceInstalledRunning "ssh" , Docker.container "armel-git-annex-builder" (image $ System (Debian Unstable) "armel") - & Docker.link "armel-git-annex-builder-companion.orca.kitenet.net.propellor" "companion" - & Docker.volumes_from "armel-git-annex-builder-companion.orca.kitenet.net.propellor" + & Docker.link "armel-git-annex-builder-companion" "companion" + & Docker.volumes_from "armel-git-annex-builder-companion" & GitAnnexBuilder.builder "armel" "1 3 * * *" "5h" True -- TODO: automate installing haskell libs -- (Currently have to run From e2c67a6e18a27faab46f5842535d87ae26f167be Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 19 May 2014 19:32:16 -0400 Subject: [PATCH 17/75] propellor spin --- config-joey.hs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 3d464e3..5e731dc 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -192,28 +192,33 @@ hosts = -- (o) ` , standardGitAnnexBuilder "amd64" 15 "2h" , standardGitAnnexBuilder "i386" 45 "2h" -- armel builder has a companion container using amd64 that - -- runs the build first to get TH splices. They share a home - -- directory, and need to have the same versions of all haskell - -- libraries installed. The armel builder can ssh in to the - -- companion. + -- runs the build first to get TH splices. They need + -- to have the same versions of all haskell libraries installed. , Docker.container "armel-git-annex-builder-companion" (image $ System (Debian Unstable) "amd64") - & Docker.volume GitAnnexBuilder.homedir & Apt.unattendedUpgrades + -- This volume is shared with the armel builder. + & Docker.volume GitAnnexBuilder.homedir + & File.ownerGroup GitAnnexBuilder.homedir GitAnnexBuilder.builduser GitAnnexBuilder.builduser + -- Install current versions of build deps from cabal. & GitAnnexBuilder.treeDeps "armel" & GitAnnexBuilder.cabalDeps - & GitAnnexBuilder.sshKeyGen + -- The armel builder can ssh to this companion, + -- using $COMPANION_PORT_22_TCP_ADDR as the hostname, & Docker.expose "22" & Apt.serviceInstalledRunning "ssh" + -- ssh key is shared via the home directory volume + & GitAnnexBuilder.sshKeyGen , Docker.container "armel-git-annex-builder" (image $ System (Debian Unstable) "armel") + & Apt.unattendedUpgrades + & Apt.installed ["openssh-client"] & Docker.link "armel-git-annex-builder-companion" "companion" & Docker.volumes_from "armel-git-annex-builder-companion" - & GitAnnexBuilder.builder "armel" "1 3 * * *" "5h" True -- TODO: automate installing haskell libs -- (Currently have to run -- git-annex/standalone/linux/install-haskell-packages) - & Apt.unattendedUpgrades + & GitAnnexBuilder.builder "armel" "1 3 * * *" "5h" True ] ++ monsters standardGitAnnexBuilder :: Architecture -> Int -> GitAnnexBuilder.TimeOut -> Host From 5ace43fb4ad8b01bbff011ee307667d52ae71eba Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 20 May 2014 13:14:13 -0400 Subject: [PATCH 18/75] propellor spin --- config-joey.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index 5e731dc..782c579 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -217,7 +217,8 @@ hosts = -- (o) ` & Docker.volumes_from "armel-git-annex-builder-companion" -- TODO: automate installing haskell libs -- (Currently have to run - -- git-annex/standalone/linux/install-haskell-packages) + -- git-annex/standalone/linux/install-haskell-packages + -- which is not fully automated.) & GitAnnexBuilder.builder "armel" "1 3 * * *" "5h" True ] ++ monsters From 7eeb58dab91eeb73d9491a89313bb28aa00ee833 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 20 May 2014 13:37:03 -0400 Subject: [PATCH 19/75] fix ssh authorizied_keys --- .../Property/SiteSpecific/GitAnnexBuilder.hs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 9754d4f..ddb6138 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -72,9 +72,15 @@ cabalDeps = flagFile go cabalupdated go = userScriptProperty builduser ["cabal update && cabal install git-annex --only-dependencies || true"] cabalupdated = homedir ".cabal" "packages" "hackage.haskell.org" "00-index.cache" --- Ensure a ssh key is set up. +-- Ensure a ssh key is set up, and allow it to be used to ssh in sshKeyGen :: Property -sshKeyGen = flagFile gen f +sshKeyGen = combineProperties "sshkeygen" + [ flagFile gen privkey + , flagFile auth authkeys + ] where gen = userScriptProperty builduser ["ssh-keygen -t RSA -N '' -f " ++ f] - f = homedir ".ssh" "id_rsa" + auth = userScriptProperty builduser ["cp " ++ pubkey ++ " " ++ authkeys] + privkey = homedir ".ssh" "id_rsa" + pubkey = privkey ++ ".pub" + authkeys = homedir ".ssh" "authorized_keys" From 9acd70eb4c2eb680eed5affda4be8eb59b7507f6 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 20 May 2014 18:28:13 -0400 Subject: [PATCH 20/75] propellor spin --- config-joey.hs | 9 ++--- .../Property/SiteSpecific/GitAnnexBuilder.hs | 33 +++++++++++++------ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 782c579..7f32d8b 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -94,8 +94,8 @@ hosts = -- (o) ` & Docker.configured & Docker.docked hosts "amd64-git-annex-builder" & Docker.docked hosts "i386-git-annex-builder" - & Docker.docked hosts "armel-git-annex-builder-companion" - & Docker.docked hosts "armel-git-annex-builder" + ! Docker.docked hosts "armel-git-annex-builder-companion" + ! Docker.docked hosts "armel-git-annex-builder" & Docker.garbageCollected `period` Daily & Apt.buildDep ["git-annex"] `period` Daily @@ -201,7 +201,8 @@ hosts = -- (o) ` & Docker.volume GitAnnexBuilder.homedir & File.ownerGroup GitAnnexBuilder.homedir GitAnnexBuilder.builduser GitAnnexBuilder.builduser -- Install current versions of build deps from cabal. - & GitAnnexBuilder.treeDeps "armel" + & GitAnnexBuilder.tree "armel" + & GitAnnexBuilder.buildDepsNoHaskellLibs & GitAnnexBuilder.cabalDeps -- The armel builder can ssh to this companion, -- using $COMPANION_PORT_22_TCP_ADDR as the hostname, @@ -219,7 +220,7 @@ hosts = -- (o) ` -- (Currently have to run -- git-annex/standalone/linux/install-haskell-packages -- which is not fully automated.) - & GitAnnexBuilder.builder "armel" "1 3 * * *" "5h" True + & GitAnnexBuilder.builder' GitAnnexBuilder.buildDepsNoHaskellLibs "armel" "1 3 * * *" "5h" True ] ++ monsters standardGitAnnexBuilder :: Architecture -> Int -> GitAnnexBuilder.TimeOut -> Host diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index ddb6138..1dbdbca 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -21,8 +21,12 @@ builddir = gitbuilderdir "build" type TimeOut = String -- eg, 5h builder :: Architecture -> CronTimes -> TimeOut -> Bool -> Property -builder buildarch crontimes timeout rsyncupload = combineProperties "gitannexbuilder" - [ treeDeps buildarch +builder = builder' buildDeps + +builder' :: Property -> Architecture -> CronTimes -> TimeOut -> Bool -> Property +builder' buildepsprop buildarch crontimes timeout rsyncupload = combineProperties "gitannexbuilder" + [ tree buildarch + , buildepsprop , Apt.serviceInstalledRunning "cron" , Cron.niceJob "gitannexbuilder" crontimes builduser gitbuilderdir $ "git pull ; timeout " ++ timeout ++ " ./autobuild" @@ -45,13 +49,10 @@ builder buildarch crontimes timeout rsyncupload = combineProperties "gitannexbui ) ] -treeDeps :: Architecture -> Property -treeDeps buildarch = combineProperties "gitannexbuilder" - [ Apt.stdSourcesList Unstable - , Apt.buildDep ["git-annex"] - , Apt.installed ["git", "rsync", "moreutils", "ca-certificates", - "liblockfile-simple-perl", "cabal-install", "vim", "less"] - , User.accountFor builduser +tree :: Architecture -> Property +tree buildarch = combineProperties "gitannexbuilder tree" + [ User.accountFor builduser + , Apt.installed ["git"] , check (not <$> doesDirectoryExist gitbuilderdir) $ userScriptProperty builduser [ "git clone git://git.kitenet.net/gitannexbuilder " ++ gitbuilderdir , "cd " ++ gitbuilderdir @@ -61,9 +62,21 @@ treeDeps buildarch = combineProperties "gitannexbuilder" , check (not <$> doesDirectoryExist builddir) $ userScriptProperty builduser [ "git clone git://git-annex.branchable.com/ " ++ builddir ] + ] + +buildDeps :: Property +buildDeps = combineProperties "gitannexbuilder build deps" + [ Apt.stdSourcesList Unstable + , Apt.buildDep ["git-annex"] + , buildDepsNoHaskellLibs , "git-annex source build deps installed" ==> Apt.buildDepIn builddir ] +buildDepsNoHaskellLibs :: Property +buildDepsNoHaskellLibs = Apt.installed ["git", "rsync", "moreutils", "ca-certificates", + "debhelper", "ghc", "curl", "openssh-client", "git-remote-gcrypt", + "liblockfile-simple-perl", "cabal-install", "vim", "less"] + -- Installs current versions of git-annex's deps from cabal, but only -- does so once. cabalDeps :: Property @@ -79,7 +92,7 @@ sshKeyGen = combineProperties "sshkeygen" , flagFile auth authkeys ] where - gen = userScriptProperty builduser ["ssh-keygen -t RSA -N '' -f " ++ f] + gen = userScriptProperty builduser ["ssh-keygen -t RSA -N '' -f " ++ privkey] auth = userScriptProperty builduser ["cp " ++ pubkey ++ " " ++ authkeys] privkey = homedir ".ssh" "id_rsa" pubkey = privkey ++ ".pub" From e78d357dbe164269b5f41b26f651b7d3ae234a50 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 20 May 2014 18:31:28 -0400 Subject: [PATCH 21/75] propellor spin --- config-joey.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 7f32d8b..10e19a0 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -94,8 +94,8 @@ hosts = -- (o) ` & Docker.configured & Docker.docked hosts "amd64-git-annex-builder" & Docker.docked hosts "i386-git-annex-builder" - ! Docker.docked hosts "armel-git-annex-builder-companion" - ! Docker.docked hosts "armel-git-annex-builder" + & Docker.docked hosts "armel-git-annex-builder-companion" + & Docker.docked hosts "armel-git-annex-builder" & Docker.garbageCollected `period` Daily & Apt.buildDep ["git-annex"] `period` Daily From 8f9ab315e6460166eab17c414ddf0a581dc1250b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 20 May 2014 18:49:03 -0400 Subject: [PATCH 22/75] propellor spin --- config-joey.hs | 1 - src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index 10e19a0..9972d5d 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -199,7 +199,6 @@ hosts = -- (o) ` & Apt.unattendedUpgrades -- This volume is shared with the armel builder. & Docker.volume GitAnnexBuilder.homedir - & File.ownerGroup GitAnnexBuilder.homedir GitAnnexBuilder.builduser GitAnnexBuilder.builduser -- Install current versions of build deps from cabal. & GitAnnexBuilder.tree "armel" & GitAnnexBuilder.buildDepsNoHaskellLibs diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 1dbdbca..0cd5d3c 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -4,6 +4,7 @@ import Propellor import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.User as User import qualified Propellor.Property.Cron as Cron +import qualified Propellor.Property.File as File import Propellor.Property.Cron (CronTimes) builduser :: UserName @@ -52,6 +53,8 @@ builder' buildepsprop buildarch crontimes timeout rsyncupload = combinePropertie tree :: Architecture -> Property tree buildarch = combineProperties "gitannexbuilder tree" [ User.accountFor builduser + -- Home directory already exists when docker volume is used. + , File.ownerGroup homedir builduser builduser , Apt.installed ["git"] , check (not <$> doesDirectoryExist gitbuilderdir) $ userScriptProperty builduser [ "git clone git://git.kitenet.net/gitannexbuilder " ++ gitbuilderdir From 1fa9a382282d0d444b7fdf796bc51ce5f8926e7d Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 20 May 2014 18:52:00 -0400 Subject: [PATCH 23/75] propellor spin From eeb2d688bdf435158929bb3cbfea6fb68076de9e Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 20 May 2014 19:49:07 -0400 Subject: [PATCH 24/75] propellor spin --- config-joey.hs | 5 ++++- src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 9972d5d..f495004 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -196,6 +196,7 @@ hosts = -- (o) ` -- to have the same versions of all haskell libraries installed. , Docker.container "armel-git-annex-builder-companion" (image $ System (Debian Unstable) "amd64") + & Apt.stdSourcesList Unstable & Apt.unattendedUpgrades -- This volume is shared with the armel builder. & Docker.volume GitAnnexBuilder.homedir @@ -211,6 +212,7 @@ hosts = -- (o) ` & GitAnnexBuilder.sshKeyGen , Docker.container "armel-git-annex-builder" (image $ System (Debian Unstable) "armel") + & Apt.stdSourcesList Unstable & Apt.unattendedUpgrades & Apt.installed ["openssh-client"] & Docker.link "armel-git-annex-builder-companion" "companion" @@ -225,8 +227,9 @@ hosts = -- (o) ` standardGitAnnexBuilder :: Architecture -> Int -> GitAnnexBuilder.TimeOut -> Host standardGitAnnexBuilder arch buildminute timeout = Docker.container (arch ++ "-git-annex-builder") (image $ System (Debian Unstable) arch) - & GitAnnexBuilder.builder arch (show buildminute ++ " * * * *") timeout True + & Apt.stdSourcesList Unstable & Apt.unattendedUpgrades + & GitAnnexBuilder.builder arch (show buildminute ++ " * * * *") timeout True -- This is my standard system setup. standardSystem :: HostName -> DebianSuite -> Architecture -> Host diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 0cd5d3c..428b3d0 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -69,8 +69,7 @@ tree buildarch = combineProperties "gitannexbuilder tree" buildDeps :: Property buildDeps = combineProperties "gitannexbuilder build deps" - [ Apt.stdSourcesList Unstable - , Apt.buildDep ["git-annex"] + [ Apt.buildDep ["git-annex"] , buildDepsNoHaskellLibs , "git-annex source build deps installed" ==> Apt.buildDepIn builddir ] @@ -78,7 +77,11 @@ buildDeps = combineProperties "gitannexbuilder build deps" buildDepsNoHaskellLibs :: Property buildDepsNoHaskellLibs = Apt.installed ["git", "rsync", "moreutils", "ca-certificates", "debhelper", "ghc", "curl", "openssh-client", "git-remote-gcrypt", - "liblockfile-simple-perl", "cabal-install", "vim", "less"] + "liblockfile-simple-perl", "cabal-install", "vim", "less", + "alex", "happy", "c2hs", + -- these haskell libs depend on C libs and don't use TH + "libghc-dbus-dev", "libghc-fdo-notify-dev", "libghc-network-protocol-xmpp-dev" + ] -- Installs current versions of git-annex's deps from cabal, but only -- does so once. From 7ac991635c0dbdb2ace19480fcac22dae36e5409 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 12:58:53 -0400 Subject: [PATCH 25/75] propellor spin --- config-joey.hs | 10 +++--- .../Property/SiteSpecific/GitAnnexBuilder.hs | 32 +++++++------------ 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index f495004..386e590 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -94,8 +94,8 @@ hosts = -- (o) ` & Docker.configured & Docker.docked hosts "amd64-git-annex-builder" & Docker.docked hosts "i386-git-annex-builder" - & Docker.docked hosts "armel-git-annex-builder-companion" - & Docker.docked hosts "armel-git-annex-builder" + ! Docker.docked hosts "armel-git-annex-builder-companion" + ! Docker.docked hosts "armel-git-annex-builder" & Docker.garbageCollected `period` Daily & Apt.buildDep ["git-annex"] `period` Daily @@ -199,7 +199,7 @@ hosts = -- (o) ` & Apt.stdSourcesList Unstable & Apt.unattendedUpgrades -- This volume is shared with the armel builder. - & Docker.volume GitAnnexBuilder.homedir + & Docker.volume GitAnnexBuilder.gitbuilderdir -- Install current versions of build deps from cabal. & GitAnnexBuilder.tree "armel" & GitAnnexBuilder.buildDepsNoHaskellLibs @@ -208,8 +208,7 @@ hosts = -- (o) ` -- using $COMPANION_PORT_22_TCP_ADDR as the hostname, & Docker.expose "22" & Apt.serviceInstalledRunning "ssh" - -- ssh key is shared via the home directory volume - & GitAnnexBuilder.sshKeyGen + & Ssh.authorizedKeys GitAnnexBuilder.builduser , Docker.container "armel-git-annex-builder" (image $ System (Debian Unstable) "armel") & Apt.stdSourcesList Unstable @@ -217,6 +216,7 @@ hosts = -- (o) ` & Apt.installed ["openssh-client"] & Docker.link "armel-git-annex-builder-companion" "companion" & Docker.volumes_from "armel-git-annex-builder-companion" + & Ssh.keyImported SshRsa GitAnnexBuilder.builduser -- TODO: automate installing haskell libs -- (Currently have to run -- git-annex/standalone/linux/install-haskell-packages diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 428b3d0..acf122a 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -53,15 +53,18 @@ builder' buildepsprop buildarch crontimes timeout rsyncupload = combinePropertie tree :: Architecture -> Property tree buildarch = combineProperties "gitannexbuilder tree" [ User.accountFor builduser - -- Home directory already exists when docker volume is used. - , File.ownerGroup homedir builduser builduser , Apt.installed ["git"] - , check (not <$> doesDirectoryExist gitbuilderdir) $ userScriptProperty builduser - [ "git clone git://git.kitenet.net/gitannexbuilder " ++ gitbuilderdir - , "cd " ++ gitbuilderdir - , "git checkout " ++ buildarch - ] - `describe` "gitbuilder setup" + -- gitbuilderdir directory already exists when docker volume is used, + -- but with wrong owner. + , File.dirExists gitbuilderdir + , File.ownerGroup gitbuilderdir builduser builduser + , check (not <$> (doesDirectoryExist (gitbuilderdir ".git"))) $ + userScriptProperty builduser + [ "git clone git://git.kitenet.net/gitannexbuilder " ++ gitbuilderdir + , "cd " ++ gitbuilderdir + , "git checkout " ++ buildarch + ] + `describe` "gitbuilder setup" , check (not <$> doesDirectoryExist builddir) $ userScriptProperty builduser [ "git clone git://git-annex.branchable.com/ " ++ builddir ] @@ -90,16 +93,3 @@ cabalDeps = flagFile go cabalupdated where go = userScriptProperty builduser ["cabal update && cabal install git-annex --only-dependencies || true"] cabalupdated = homedir ".cabal" "packages" "hackage.haskell.org" "00-index.cache" - --- Ensure a ssh key is set up, and allow it to be used to ssh in -sshKeyGen :: Property -sshKeyGen = combineProperties "sshkeygen" - [ flagFile gen privkey - , flagFile auth authkeys - ] - where - gen = userScriptProperty builduser ["ssh-keygen -t RSA -N '' -f " ++ privkey] - auth = userScriptProperty builduser ["cp " ++ pubkey ++ " " ++ authkeys] - privkey = homedir ".ssh" "id_rsa" - pubkey = privkey ++ ".pub" - authkeys = homedir ".ssh" "authorized_keys" From 576a4a2ef589191a5dc635537a9d287e26461b35 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 13:02:01 -0400 Subject: [PATCH 26/75] propellor spin From 497eb871e15683597b86619146db2364ff0d2cc4 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 13:07:36 -0400 Subject: [PATCH 27/75] propellor spin --- config-joey.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 386e590..68bbcbb 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -94,8 +94,8 @@ hosts = -- (o) ` & Docker.configured & Docker.docked hosts "amd64-git-annex-builder" & Docker.docked hosts "i386-git-annex-builder" - ! Docker.docked hosts "armel-git-annex-builder-companion" - ! Docker.docked hosts "armel-git-annex-builder" + & Docker.docked hosts "armel-git-annex-builder-companion" + & Docker.docked hosts "armel-git-annex-builder" & Docker.garbageCollected `period` Daily & Apt.buildDep ["git-annex"] `period` Daily From 267f1e98d1f8c1e7af9151b86ef636e6fe65fe58 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 13:51:59 -0400 Subject: [PATCH 28/75] propellor spin From 450d1870d1f16da957a89dcec5bfd1e4cd0c6a40 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 13:58:53 -0400 Subject: [PATCH 29/75] propellor spin --- privdata/orca.kitenet.net.gpg | 71 ++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/privdata/orca.kitenet.net.gpg b/privdata/orca.kitenet.net.gpg index c1a2e9f..26dd268 100644 --- a/privdata/orca.kitenet.net.gpg +++ b/privdata/orca.kitenet.net.gpg @@ -1,22 +1,57 @@ -----BEGIN PGP MESSAGE----- Version: GnuPG v1 -hQIMA7ODiaEXBlRZARAAvqd3qX/p4dXrvDxK49gUGydT2/47k9f3BQQTWDtG1uUq -3QBbJbBAx2LXyRtfsioxDgMx6hdg/pHSjrcIsdd6SeaOzU9NJ8TQe2OsnSg6SY2h -GCc4bxFcMnyOWpWkr0FcuQ6uiGZvStYq7HPMPdeRR2BETkU4ONVgdZOo1QiUU+85 -AM/slTKRLp7syX00aFZVXQydSAekvTaJgwbo6n4pdPhDq+ztUsrwhFKzveOvJAKe -36tjzaqN/XUa3v1X7eqZUwAw2lwPro02jYnkYTGtl1SPd2iFNcOb1GO9rCq0lKjH -pqqkhFSMKZcvvgghZgUga6HnLo/IHSP7lzCxmsznMy5ns2Qrh64Z9vf40LElILPY -/hFN4Bsi5DTFgSsxydS8EL7H2MY3hUgWuBxo5Xj0e/3txv87QGMPM6PDW7OzMOl0 -1qB8pqe7oCnBq+yyd0ftdrhbMtz5JsifFN4/KLlAm9XOzysX0GylZ9Iy3QKbLQUp -hQBXX8XE2mCCbOwpzC9Z1eMUksL6YOiSIz/EVwLbqr6AulicNxTf488gJGj+vf6D -ihFj477BYQPkZ3S6nIEyKi6r/vLZkLMgwni0axBD9yzoVk0O/e4WAJMyJWhVXRzF -OQipN+vnp6HlqwBuUTezFzdwtimy0phBLd5x22qN2WooAaUExXpHgnc/M6WmqRrS -wF4BIvJBD5gLq9GKT5bdENpO1+W5zj4af5fT7LSgobiCSgpjz1/mbfN5QVBUB2z1 -FqQVv7gN1AIbcorx1ke4BOwpvZA3iaU+9Cd51ME04x75uSyFc7Xb7wtcGPymEgXI -X7ZO1mtJJ48BY1vYN3ER0h+MK/d27v0JASFfCwuLSA8M8FAoQLPpEG/7qiAxoQtP -EshdoeZZhK0bsG2+Uf1ixNnRy1/SazrUXTo/e+IVN/BOL7qINjkI+2hPGz3r2gLP -EavegXtJ5RGdqvBD+C4ph85bOvjOlR8klZ1nGnlAnGu1OEYv8zv/yJ6dq6/HaLkB -p8MqZXY1qH0ywoPnkW34TN83k9YncyS4Bj2gNN2iggU+/LQViitsVxLkQ9sxdjlS -=usce +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 +E61aknSkeMlS0WT07bvrS7w4xA== +=q6pD -----END PGP MESSAGE----- From 58e85f40197b3812efa39f214cd8f9149a4e39c1 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 14:00:53 -0400 Subject: [PATCH 30/75] propellor spin --- config-joey.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index 68bbcbb..318d5d9 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -216,12 +216,12 @@ hosts = -- (o) ` & Apt.installed ["openssh-client"] & Docker.link "armel-git-annex-builder-companion" "companion" & Docker.volumes_from "armel-git-annex-builder-companion" - & Ssh.keyImported SshRsa GitAnnexBuilder.builduser -- TODO: automate installing haskell libs -- (Currently have to run -- git-annex/standalone/linux/install-haskell-packages -- which is not fully automated.) & GitAnnexBuilder.builder' GitAnnexBuilder.buildDepsNoHaskellLibs "armel" "1 3 * * *" "5h" True + & Ssh.keyImported SshRsa GitAnnexBuilder.builduser ] ++ monsters standardGitAnnexBuilder :: Architecture -> Int -> GitAnnexBuilder.TimeOut -> Host From 3b91f5bba315ebbb252dfd71528009c32aa54644 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 14:13:39 -0400 Subject: [PATCH 31/75] propellor spin --- src/Propellor/Property/Ssh.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Propellor/Property/Ssh.hs b/src/Propellor/Property/Ssh.hs index a4f8767..516525a 100644 --- a/src/Propellor/Property/Ssh.hs +++ b/src/Propellor/Property/Ssh.hs @@ -109,7 +109,8 @@ keyImported keytype user = combineProperties desc ( noChange , ensureProperty $ combineProperties desc [ property desc $ - withPrivData p $ \key -> makeChange $ + withPrivData p $ \key -> makeChange $ do + createDirectoryIfMissing True (takeDirectory f) writer f key , File.ownerGroup f user user ] From 76bccf751281e108a9a7138cf5b314b785ff55f0 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 14:34:33 -0400 Subject: [PATCH 32/75] propellor spin From 575bfec60b5166f04ecbfebea2b6905d567a88fc Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 14:36:55 -0400 Subject: [PATCH 33/75] propellor spin From 38bba6c8ed2d0855c1a44e123a6721a9a287e208 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 14:39:24 -0400 Subject: [PATCH 34/75] propellor spin From 07d3d359d27089739ff30cbcefd038986ecef641 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 May 2014 14:57:04 -0400 Subject: [PATCH 35/75] fix dir owner --- src/Propellor/Property/Ssh.hs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Propellor/Property/Ssh.hs b/src/Propellor/Property/Ssh.hs index 516525a..061f440 100644 --- a/src/Propellor/Property/Ssh.hs +++ b/src/Propellor/Property/Ssh.hs @@ -107,12 +107,13 @@ keyImported keytype user = combineProperties desc f <- liftIO $ keyfile ext ifM (liftIO $ doesFileExist f) ( noChange - , ensureProperty $ combineProperties desc + , ensureProperties [ property desc $ withPrivData p $ \key -> makeChange $ do createDirectoryIfMissing True (takeDirectory f) writer f key , File.ownerGroup f user user + , File.ownerGroup (takeDirectory f) user user ] ) keyfile ext = do @@ -150,4 +151,7 @@ authorizedKeys user = property (user ++ " has authorized_keys") $ liftIO $ do createDirectoryIfMissing True (takeDirectory f) writeFileProtected f v - ensureProperty $ File.ownerGroup f user user + ensureProperties + [ File.ownerGroup f user user + , File.ownerGroup (takeDirectory f) user user + ] From 424ba1229ba0a786d6090d69739defe47d0612c8 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 22 May 2014 21:42:57 -0400 Subject: [PATCH 36/75] refactor --- config-joey.hs | 54 ++++--------------- .../Property/SiteSpecific/GitAnnexBuilder.hs | 44 +++++++++++++++ 2 files changed, 53 insertions(+), 45 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 318d5d9..fafc409 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -189,48 +189,12 @@ hosts = -- (o) ` (Just "remotes/origin/old-kitenet.net") -- git-annex autobuilder containers - , standardGitAnnexBuilder "amd64" 15 "2h" - , standardGitAnnexBuilder "i386" 45 "2h" - -- armel builder has a companion container using amd64 that - -- runs the build first to get TH splices. They need - -- to have the same versions of all haskell libraries installed. - , Docker.container "armel-git-annex-builder-companion" - (image $ System (Debian Unstable) "amd64") - & Apt.stdSourcesList Unstable - & Apt.unattendedUpgrades - -- This volume is shared with the armel builder. - & Docker.volume GitAnnexBuilder.gitbuilderdir - -- Install current versions of build deps from cabal. - & GitAnnexBuilder.tree "armel" - & GitAnnexBuilder.buildDepsNoHaskellLibs - & GitAnnexBuilder.cabalDeps - -- The armel builder can ssh to this companion, - -- using $COMPANION_PORT_22_TCP_ADDR as the hostname, - & Docker.expose "22" - & Apt.serviceInstalledRunning "ssh" - & Ssh.authorizedKeys GitAnnexBuilder.builduser - , Docker.container "armel-git-annex-builder" - (image $ System (Debian Unstable) "armel") - & Apt.stdSourcesList Unstable - & Apt.unattendedUpgrades - & Apt.installed ["openssh-client"] - & Docker.link "armel-git-annex-builder-companion" "companion" - & Docker.volumes_from "armel-git-annex-builder-companion" - -- TODO: automate installing haskell libs - -- (Currently have to run - -- git-annex/standalone/linux/install-haskell-packages - -- which is not fully automated.) - & GitAnnexBuilder.builder' GitAnnexBuilder.buildDepsNoHaskellLibs "armel" "1 3 * * *" "5h" True - & Ssh.keyImported SshRsa GitAnnexBuilder.builduser + , GitAnnexBuilder.standardContainer dockerImage "amd64" 15 "2h" + , GitAnnexBuilder.standardContainer dockerImage "i386" 45 "2h" + , GitAnnexBuilder.armelCompanionContainer dockerImage + , GitAnnexBuilder.armelContainer dockerImage "1 3 * * *" "5h" ] ++ monsters -standardGitAnnexBuilder :: Architecture -> Int -> GitAnnexBuilder.TimeOut -> Host -standardGitAnnexBuilder arch buildminute timeout = Docker.container (arch ++ "-git-annex-builder") - (image $ System (Debian Unstable) arch) - & Apt.stdSourcesList Unstable - & Apt.unattendedUpgrades - & GitAnnexBuilder.builder arch (show buildminute ++ " * * * *") timeout True - -- This is my standard system setup. standardSystem :: HostName -> DebianSuite -> Architecture -> Host standardSystem hn suite arch = host hn @@ -257,7 +221,7 @@ standardSystem hn suite arch = host hn -- This is my standard container setup, featuring automatic upgrades. standardContainer :: Docker.ContainerName -> DebianSuite -> Architecture -> Host -standardContainer name suite arch = Docker.container name (image system) +standardContainer name suite arch = Docker.container name (dockerImage system) & os (System (Debian suite) arch) & Apt.stdSourcesList suite & Apt.unattendedUpgrades @@ -265,10 +229,10 @@ standardContainer name suite arch = Docker.container name (image system) system = System (Debian suite) arch -- Docker images I prefer to use. -image :: System -> Docker.Image -image (System (Debian Unstable) arch) = "joeyh/debian-unstable-" ++ arch -image (System (Debian Stable) arch) = "joeyh/debian-stable-" ++ arch -image _ = "debian-stable-official" -- does not currently exist! +dockerImage :: System -> Docker.Image +dockerImage (System (Debian Unstable) arch) = "joeyh/debian-unstable-" ++ arch +dockerImage (System (Debian Stable) arch) = "joeyh/debian-stable-" ++ arch +dockerImage _ = "debian-stable-official" -- does not currently exist! -- Digital Ocean does not provide any way to boot -- the kernel provided by the distribution, except using kexec. diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index acf122a..80877fa 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -4,7 +4,9 @@ import Propellor import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.User as User 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) builduser :: UserName @@ -93,3 +95,45 @@ cabalDeps = flagFile go cabalupdated where go = userScriptProperty builduser ["cabal update && cabal install git-annex --only-dependencies || true"] cabalupdated = homedir ".cabal" "packages" "hackage.haskell.org" "00-index.cache" + +standardContainer :: (System -> Docker.Image) -> Architecture -> Int -> TimeOut -> Host +standardContainer dockerImage arch buildminute timeout = Docker.container (arch ++ "-git-annex-builder") + (dockerImage $ System (Debian Unstable) arch) + & Apt.stdSourcesList Unstable + & Apt.unattendedUpgrades + & builder arch (show buildminute ++ " * * * *") timeout True + +-- armel builder has a companion container using amd64 that +-- runs the build first to get TH splices. They need +-- to have the same versions of all haskell libraries installed. +armelCompanionContainer :: (System -> Docker.Image) -> Host +armelCompanionContainer dockerImage = Docker.container "armel-git-annex-builder-companion" + (dockerImage $ System (Debian Unstable) "amd64") + & Apt.stdSourcesList Unstable + & Apt.unattendedUpgrades + -- This volume is shared with the armel builder. + & Docker.volume gitbuilderdir + -- Install current versions of build deps from cabal. + & tree "armel" + & buildDepsNoHaskellLibs + & cabalDeps + -- The armel builder can ssh to this companion, + -- using $COMPANION_PORT_22_TCP_ADDR as the hostname, + & Docker.expose "22" + & Apt.serviceInstalledRunning "ssh" + & Ssh.authorizedKeys builduser + +armelContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Host +armelContainer dockerImage crontimes timeout = Docker.container "armel-git-annex-builder" + (dockerImage $ System (Debian Unstable) "armel") + & Apt.stdSourcesList Unstable + & Apt.unattendedUpgrades + & Apt.installed ["openssh-client"] + & Docker.link "armel-git-annex-builder-companion" "companion" + & Docker.volumes_from "armel-git-annex-builder-companion" + -- TODO: automate installing haskell libs + -- (Currently have to run + -- git-annex/standalone/linux/install-haskell-packages + -- which is not fully automated.) + & builder' buildDepsNoHaskellLibs "armel" crontimes timeout True + & Ssh.keyImported SshRsa builduser From 4f239d1360c87b069279ce1b100db4a057f94e48 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 23 May 2014 10:46:25 -0400 Subject: [PATCH 37/75] propellor spin --- src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 80877fa..56123b6 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -117,8 +117,7 @@ armelCompanionContainer dockerImage = Docker.container "armel-git-annex-builder- & tree "armel" & buildDepsNoHaskellLibs & cabalDeps - -- The armel builder can ssh to this companion, - -- using $COMPANION_PORT_22_TCP_ADDR as the hostname, + -- The armel builder can ssh to this companion. & Docker.expose "22" & Apt.serviceInstalledRunning "ssh" & Ssh.authorizedKeys builduser @@ -137,3 +136,8 @@ armelContainer dockerImage crontimes timeout = Docker.container "armel-git-annex -- which is not fully automated.) & builder' buildDepsNoHaskellLibs "armel" crontimes timeout True & Ssh.keyImported SshRsa builduser + & trivial writecompanionaddress + where + writecompanionaddress = scriptProperty + [ "echo \"$COMPANION_PORT_22_TCP_ADDR\" > " ++ homedir "companion_address" + ] From 0ec565a590e0b5e70af4f4f922925e5b0b718376 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 23 May 2014 12:30:25 -0400 Subject: [PATCH 38/75] propellor spin --- config-joey.hs | 37 ++----------------- debian/changelog | 1 + propellor.cabal | 2 + .../Property/HostingProvider/CloudAtCost.hs | 24 ++++++++++++ .../Property/HostingProvider/DigitalOcean.hs | 21 +++++++++++ .../Property/SiteSpecific/GitAnnexBuilder.hs | 2 +- 6 files changed, 53 insertions(+), 34 deletions(-) create mode 100644 src/Propellor/Property/HostingProvider/CloudAtCost.hs create mode 100644 src/Propellor/Property/HostingProvider/DigitalOcean.hs diff --git a/config-joey.hs b/config-joey.hs index fafc409..2f84fbb 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -21,6 +21,8 @@ import qualified Propellor.Property.Git as Git import qualified Propellor.Property.Apache as Apache import qualified Propellor.Property.Postfix as Postfix import qualified Propellor.Property.Service as Service +import qualified Propellor.Property.HostingProvider.DigitalOcean as DigitalOcean +import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost import qualified Propellor.Property.SiteSpecific.GitHome as GitHome import qualified Propellor.Property.SiteSpecific.GitAnnexBuilder as GitAnnexBuilder import qualified Propellor.Property.SiteSpecific.JoeySites as JoeySites @@ -46,7 +48,7 @@ hosts = -- (o) ` & ipv4 "162.248.143.249" & ipv6 "2002:5044:5531::1" - & cleanCloudAtCost + & CloudAtCost.decruft & Apt.unattendedUpgrades & Network.ipv6to4 & Tor.isBridge @@ -103,6 +105,7 @@ hosts = -- (o) ` , standardSystem "diatom.kitenet.net" Stable "amd64" & ipv4 "107.170.31.195" + & DigitalOcean.distroKernel & Hostname.sane & Ssh.hostKey SshDsa & Ssh.hostKey SshRsa @@ -234,38 +237,6 @@ dockerImage (System (Debian Unstable) arch) = "joeyh/debian-unstable-" ++ arch dockerImage (System (Debian Stable) arch) = "joeyh/debian-stable-" ++ arch dockerImage _ = "debian-stable-official" -- does not currently exist! --- Digital Ocean does not provide any way to boot --- the kernel provided by the distribution, except using kexec. --- Without this, some old, and perhaps insecure kernel will be used. --- --- Note that this only causes the new kernel to be loaded on reboot. --- If the power is cycled, the old kernel still boots up. --- TODO: detect this and reboot immediately? -digitalOceanDistroKernel :: Property -digitalOceanDistroKernel = propertyList "digital ocean distro kernel hack" - [ Apt.installed ["grub-pc", "kexec-tools"] - , "/etc/default/kexec" `File.containsLines` - [ "LOAD_KEXEC=true" - , "USE_GRUB_CONFIG=true" - ] - ] - --- Clean up a system as installed by cloudatcost.com -cleanCloudAtCost :: Property -cleanCloudAtCost = propertyList "cloudatcost cleanup" - [ Hostname.sane - , Ssh.randomHostKeys - , "worked around grub/lvm boot bug #743126" ==> - "/etc/default/grub" `File.containsLine` "GRUB_DISABLE_LINUX_UUID=true" - `onChange` cmdProperty "update-grub" [] - `onChange` cmdProperty "update-initramfs" ["-u"] - , combineProperties "nuked cloudatcost cruft" - [ File.notPresent "/etc/rc.local" - , File.notPresent "/etc/init.d/S97-setup.sh" - , User.nuked "user" User.YesReallyDeleteHome - ] - ] - myDnsSecondary :: Property myDnsSecondary = propertyList "dns secondary for all my domains" $ map toProp [ Dns.secondary hosts "kitenet.net" diff --git a/debian/changelog b/debian/changelog index 9d1d9a1..a3dc103 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,7 @@ propellor (0.5.3) UNRELEASED; urgency=medium * Fix unattended-upgrades config for !stable. * Ensure that kernel hostname is same as /etc/hostname when configuring hostname. + * Added modules for some hosting providers (DigitalOcean, CloudAtCost). -- Joey Hess Sun, 18 May 2014 13:44:00 -0400 diff --git a/propellor.cabal b/propellor.cabal index 9d0612e..da9a630 100644 --- a/propellor.cabal +++ b/propellor.cabal @@ -92,6 +92,8 @@ Library Propellor.Property.Sudo Propellor.Property.Tor Propellor.Property.User + Propellor.Property.HostingProvider.DigitalOcean + Propellor.Property.HostingProvider.CloudAtCost Propellor.Property.SiteSpecific.GitHome Propellor.Property.SiteSpecific.JoeySites Propellor.Property.SiteSpecific.GitAnnexBuilder diff --git a/src/Propellor/Property/HostingProvider/CloudAtCost.hs b/src/Propellor/Property/HostingProvider/CloudAtCost.hs new file mode 100644 index 0000000..003bd3c --- /dev/null +++ b/src/Propellor/Property/HostingProvider/CloudAtCost.hs @@ -0,0 +1,24 @@ +module Propellor.Property.HostingProvider.CloudAtCost where + +import Propellor +import qualified Propellor.Property.Hostname as Hostname +import qualified Propellor.Property.File as File +import qualified Propellor.Property.Ssh as Ssh +import qualified Propellor.Property.User as User + +-- Clean up a system as installed by cloudatcost.com +decruft :: Property +decruft = propertyList "cloudatcost cleanup" + [ Hostname.sane + , Ssh.randomHostKeys + , "worked around grub/lvm boot bug #743126" ==> + "/etc/default/grub" `File.containsLine` "GRUB_DISABLE_LINUX_UUID=true" + `onChange` cmdProperty "update-grub" [] + `onChange` cmdProperty "update-initramfs" ["-u"] + , combineProperties "nuked cloudatcost cruft" + [ File.notPresent "/etc/rc.local" + , File.notPresent "/etc/init.d/S97-setup.sh" + , User.nuked "user" User.YesReallyDeleteHome + ] + ] + diff --git a/src/Propellor/Property/HostingProvider/DigitalOcean.hs b/src/Propellor/Property/HostingProvider/DigitalOcean.hs new file mode 100644 index 0000000..24dfd35 --- /dev/null +++ b/src/Propellor/Property/HostingProvider/DigitalOcean.hs @@ -0,0 +1,21 @@ +module Propellor.Property.HostingProvider.DigitalOcean where + +import Propellor +import qualified Propellor.Property.Apt as Apt +import qualified Propellor.Property.File as File + +-- Digital Ocean does not provide any way to boot +-- the kernel provided by the distribution, except using kexec. +-- Without this, some old, and perhaps insecure kernel will be used. +-- +-- Note that this only causes the new kernel to be loaded on reboot. +-- If the power is cycled, the old kernel still boots up. +-- TODO: detect this and reboot immediately? +distroKernel :: Property +distroKernel = propertyList "digital ocean distro kernel hack" + [ Apt.installed ["grub-pc", "kexec-tools"] + , "/etc/default/kexec" `File.containsLines` + [ "LOAD_KEXEC=true" + , "USE_GRUB_CONFIG=true" + ] + ] diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 56123b6..8055a60 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -140,4 +140,4 @@ armelContainer dockerImage crontimes timeout = Docker.container "armel-git-annex where writecompanionaddress = scriptProperty [ "echo \"$COMPANION_PORT_22_TCP_ADDR\" > " ++ homedir "companion_address" - ] + ] `describe` "companion_address file" From aba5e143f20f0ef8e3b278c11d351be9fe256bcc Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 23 May 2014 12:31:42 -0400 Subject: [PATCH 39/75] desc --- src/Propellor/Property/HostingProvider/DigitalOcean.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Propellor/Property/HostingProvider/DigitalOcean.hs b/src/Propellor/Property/HostingProvider/DigitalOcean.hs index 24dfd35..4565935 100644 --- a/src/Propellor/Property/HostingProvider/DigitalOcean.hs +++ b/src/Propellor/Property/HostingProvider/DigitalOcean.hs @@ -17,5 +17,5 @@ distroKernel = propertyList "digital ocean distro kernel hack" , "/etc/default/kexec" `File.containsLines` [ "LOAD_KEXEC=true" , "USE_GRUB_CONFIG=true" - ] + ] `describe` "kexec configured" ] From 60ea130321e23dd7b36337388d6627661c116548 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 24 May 2014 00:05:47 -0400 Subject: [PATCH 40/75] propellor spin --- config-joey.hs | 2 ++ .../Property/SiteSpecific/GitAnnexBuilder.hs | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/config-joey.hs b/config-joey.hs index 2f84fbb..1f5ce0d 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -98,6 +98,7 @@ hosts = -- (o) ` & Docker.docked hosts "i386-git-annex-builder" & Docker.docked hosts "armel-git-annex-builder-companion" & Docker.docked hosts "armel-git-annex-builder" + & Docker.docked hosts "android-git-annex-builder" & Docker.garbageCollected `period` Daily & Apt.buildDep ["git-annex"] `period` Daily @@ -196,6 +197,7 @@ hosts = -- (o) ` , GitAnnexBuilder.standardContainer dockerImage "i386" 45 "2h" , GitAnnexBuilder.armelCompanionContainer dockerImage , GitAnnexBuilder.armelContainer dockerImage "1 3 * * *" "5h" + , GitAnnexBuilder.androidContainer dockerImage "1 1 * * *" "3h" ] ++ monsters -- This is my standard system setup. diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 8055a60..13f1ac1 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -103,6 +103,24 @@ standardContainer dockerImage arch buildminute timeout = Docker.container (arch & Apt.unattendedUpgrades & builder arch (show buildminute ++ " * * * *") timeout True +-- Android is cross-built in a Debian i386 container, using the Android NDK. +androidContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Host +androidContainer dockerImage crontimes timeout = Docker.container "android-git-annex-builder" + (dockerImage $ System (Debian Stable) "i386") + & Apt.stdSourcesList Stable + & Apt.unattendedUpgrades + & builder "android" crontimes timeout True + -- Use git-annex's android chroot setup script, which will install + -- ghc-android and the NDK, etc, in the home directory of the + -- builder user. + & scriptProperty + [ "cd " ++ builddir ++ " && ./standalone/android/buildchroot-inchroot" + ] + -- TODO: automate installing haskell libs + -- (Currently have to run + -- git-annex/standalone/android/install-haskell-packages + -- which is not fully automated.) + -- armel builder has a companion container using amd64 that -- runs the build first to get TH splices. They need -- to have the same versions of all haskell libraries installed. From 7004b34a718de4c4ed8e79679e40e2907aa7e310 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 24 May 2014 00:06:38 -0400 Subject: [PATCH 41/75] use a license name that cabal recognises --- propellor.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/propellor.cabal b/propellor.cabal index da9a630..18d63c9 100644 --- a/propellor.cabal +++ b/propellor.cabal @@ -1,7 +1,7 @@ Name: propellor Version: 0.5.2 Cabal-Version: >= 1.6 -License: BSD +License: BSD3 Maintainer: Joey Hess Author: Joey Hess Stability: Stable From cc46cb19421d99f93fdc78cda50761dba3556b21 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 24 May 2014 00:09:58 -0400 Subject: [PATCH 42/75] propellor spin --- src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 13f1ac1..7941d7b 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -88,6 +88,9 @@ buildDepsNoHaskellLibs = Apt.installed ["git", "rsync", "moreutils", "ca-certifi "libghc-dbus-dev", "libghc-fdo-notify-dev", "libghc-network-protocol-xmpp-dev" ] +noBuildDeps :: Property +noBuildDeps = propertyList "no build deps" [] + -- Installs current versions of git-annex's deps from cabal, but only -- does so once. cabalDeps :: Property @@ -109,10 +112,10 @@ androidContainer dockerImage crontimes timeout = Docker.container "android-git-a (dockerImage $ System (Debian Stable) "i386") & Apt.stdSourcesList Stable & Apt.unattendedUpgrades - & builder "android" crontimes timeout True + & builder' noBuildDeps "android" crontimes timeout True -- Use git-annex's android chroot setup script, which will install - -- ghc-android and the NDK, etc, in the home directory of the - -- builder user. + -- ghc-android and the NDK, all build deps, etc, in the home + -- directory of the builder user. & scriptProperty [ "cd " ++ builddir ++ " && ./standalone/android/buildchroot-inchroot" ] From 321a45a1ba1800241abacaaf1e0d1530360b9204 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 24 May 2014 00:52:37 -0400 Subject: [PATCH 43/75] propellor spin --- .../Property/SiteSpecific/GitAnnexBuilder.hs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 7941d7b..b872987 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -113,16 +113,18 @@ androidContainer dockerImage crontimes timeout = Docker.container "android-git-a & Apt.stdSourcesList Stable & Apt.unattendedUpgrades & builder' noBuildDeps "android" crontimes timeout True - -- Use git-annex's android chroot setup script, which will install - -- ghc-android and the NDK, all build deps, etc, in the home - -- directory of the builder user. - & scriptProperty - [ "cd " ++ builddir ++ " && ./standalone/android/buildchroot-inchroot" - ] + & flagFile chrootsetup ("/chrootsetup") -- TODO: automate installing haskell libs -- (Currently have to run -- git-annex/standalone/android/install-haskell-packages -- which is not fully automated.) + where + -- Use git-annex's android chroot setup script, which will install + -- ghc-android and the NDK, all build deps, etc, in the home + -- directory of the builder user. + chrootsetup = scriptProperty + [ "cd " ++ builddir ++ " && ./standalone/android/buildchroot-inchroot" + ] -- armel builder has a companion container using amd64 that -- runs the build first to get TH splices. They need From 0f3ad20dfb4bf1e41aebf3cb982d775bc2b670c8 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 24 May 2014 02:10:57 -0400 Subject: [PATCH 44/75] propellor spin From e52f3de6c39ba08cc1bf930c9f78083dd7c61e94 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 24 May 2014 12:24:50 -0400 Subject: [PATCH 45/75] propellor spin From 31a93019f91d25ec3f1f932160f6aad44ca3d2a7 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 24 May 2014 12:27:13 -0400 Subject: [PATCH 46/75] propellor spin From c9a20304ccbbe7ffaba1d6b3bfc45599bfc06d14 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 24 May 2014 16:51:46 -0400 Subject: [PATCH 47/75] propellor spin --- config-joey.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index 1f5ce0d..84cc716 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -302,7 +302,6 @@ monsters = -- but do want to track their public keys etc. & alias "wortroot.kitenet.net" & alias "www.wortroot.kitenet.net" & alias "joey.kitenet.net" - & alias "annex.kitenet.net" & alias "ipv6.kitenet.net" & alias "bitlbee.kitenet.net" , host "mouse.kitenet.net" From 28d717c880b5a33136244ff9c9d840897fe9da57 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 24 May 2014 19:37:38 -0400 Subject: [PATCH 48/75] propellor spin From 94bc4f1567f37e77b501dd7ba4b96de80cf5c763 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 25 May 2014 11:10:09 -0400 Subject: [PATCH 49/75] propellor spin From 1e30dab979bdda6292c80b5bc3cfc5bb9b569be3 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 25 May 2014 11:11:10 -0400 Subject: [PATCH 50/75] propellor spin From ceae27f3c19078c058c95e748afa3358d7ad0086 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 25 May 2014 12:22:19 -0400 Subject: [PATCH 51/75] propellor spin From 4342f7d39734c9774b975ab6174466a087bc50c5 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 25 May 2014 14:14:48 -0400 Subject: [PATCH 52/75] propellor spin From 48ce182a88a904b875d169af6c44379cbf0bb0f3 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 25 May 2014 14:15:40 -0400 Subject: [PATCH 53/75] propellor spin From 897457e27e7510c36653913a92826f9b4e5ced01 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 25 May 2014 15:02:26 -0400 Subject: [PATCH 54/75] propellor spin From b8463c52ef3e051ba245a1fb0002eee67562d975 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 25 May 2014 15:37:57 -0400 Subject: [PATCH 55/75] propellor spin From e71bed664002a577c1dab6a411fbaaaf76383de6 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 26 May 2014 11:55:30 -0400 Subject: [PATCH 56/75] propellor spin --- src/Propellor/Property/SiteSpecific/JoeySites.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Propellor/Property/SiteSpecific/JoeySites.hs b/src/Propellor/Property/SiteSpecific/JoeySites.hs index 28b3dff..5f054ea 100644 --- a/src/Propellor/Property/SiteSpecific/JoeySites.hs +++ b/src/Propellor/Property/SiteSpecific/JoeySites.hs @@ -141,7 +141,10 @@ gitServer hosts = propertyList "git.kitenet.net setup" `requires` Ssh.knownHost hosts "usw-s002.rsync.net" "root" `requires` Ssh.authorizedKeys "family" `requires` User.accountFor "family" - , Apt.installed ["git", "rsync", "kgb-client-git", "gitweb"] + , Apt.installed ["git", "rsync", "gitweb"] + -- backport avoids channel flooding on branch merge + , Apt.installedBackport ["kgb-client"] + -- backport supports ssh event notification , Apt.installedBackport ["git-annex"] , File.hasPrivContentExposed "/etc/kgb-bot/kgb-client.conf" , toProp $ Git.daemonRunning "/srv/git" From 9fa0393f386977637fe16e93f31b835cc457d87d Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 26 May 2014 18:46:42 -0400 Subject: [PATCH 57/75] propellor spin --- .../Property/SiteSpecific/GitAnnexBuilder.hs | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index b872987..a154c92 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -75,21 +75,24 @@ tree buildarch = combineProperties "gitannexbuilder tree" buildDeps :: Property buildDeps = combineProperties "gitannexbuilder build deps" [ Apt.buildDep ["git-annex"] - , buildDepsNoHaskellLibs + , buildDepsFewHaskellLibs , "git-annex source build deps installed" ==> Apt.buildDepIn builddir ] -buildDepsNoHaskellLibs :: Property -buildDepsNoHaskellLibs = Apt.installed ["git", "rsync", "moreutils", "ca-certificates", - "debhelper", "ghc", "curl", "openssh-client", "git-remote-gcrypt", - "liblockfile-simple-perl", "cabal-install", "vim", "less", - "alex", "happy", "c2hs", +buildDepsFewHaskellLibs :: Property +buildDepsFewHaskellLibs = combineProperties "gitannexbuilder build deps" + [ buildDepsNoHaskellLibs -- these haskell libs depend on C libs and don't use TH - "libghc-dbus-dev", "libghc-fdo-notify-dev", "libghc-network-protocol-xmpp-dev" + , Apt.installed ["libghc-dbus-dev", "libghc-fdo-notify-dev", "libghc-network-protocol-xmpp-dev"] ] -noBuildDeps :: Property -noBuildDeps = propertyList "no build deps" [] +buildDepsNoHaskellLibs :: Property +buildDepsNoHaskellLibs = Apt.installed + ["git", "rsync", "moreutils", "ca-certificates", + "debhelper", "ghc", "curl", "openssh-client", "git-remote-gcrypt", + "liblockfile-simple-perl", "cabal-install", "vim", "less", + "alex", "happy", "c2hs" + ] -- Installs current versions of git-annex's deps from cabal, but only -- does so once. @@ -112,7 +115,7 @@ androidContainer dockerImage crontimes timeout = Docker.container "android-git-a (dockerImage $ System (Debian Stable) "i386") & Apt.stdSourcesList Stable & Apt.unattendedUpgrades - & builder' noBuildDeps "android" crontimes timeout True + & builder' buildDepsNoHaskellLibs "android" crontimes timeout True & flagFile chrootsetup ("/chrootsetup") -- TODO: automate installing haskell libs -- (Currently have to run @@ -138,7 +141,7 @@ armelCompanionContainer dockerImage = Docker.container "armel-git-annex-builder- & Docker.volume gitbuilderdir -- Install current versions of build deps from cabal. & tree "armel" - & buildDepsNoHaskellLibs + & buildDepsFewHaskellLibs & cabalDeps -- The armel builder can ssh to this companion. & Docker.expose "22" @@ -157,7 +160,7 @@ armelContainer dockerImage crontimes timeout = Docker.container "armel-git-annex -- (Currently have to run -- git-annex/standalone/linux/install-haskell-packages -- which is not fully automated.) - & builder' buildDepsNoHaskellLibs "armel" crontimes timeout True + & builder' buildDepsFewHaskellLibs "armel" crontimes timeout True & Ssh.keyImported SshRsa builduser & trivial writecompanionaddress where From 01b8f812b8a67b7cd4a4426696a5926401898fdf Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 26 May 2014 18:50:10 -0400 Subject: [PATCH 58/75] propellor spin --- privdata/diatom.kitenet.net.gpg | 724 ++++++++++++++++---------------- privdata/orca.kitenet.net.gpg | 106 ++--- 2 files changed, 415 insertions(+), 415 deletions(-) diff --git a/privdata/diatom.kitenet.net.gpg b/privdata/diatom.kitenet.net.gpg index f03e91c..af35aa4 100644 --- a/privdata/diatom.kitenet.net.gpg +++ b/privdata/diatom.kitenet.net.gpg @@ -1,366 +1,366 @@ -----BEGIN PGP MESSAGE----- Version: GnuPG v1 -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 -ZeWCt3M2QDPYox2/qZBR23+JUsiT -=n+YJ +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 +=RrAw -----END PGP MESSAGE----- diff --git a/privdata/orca.kitenet.net.gpg b/privdata/orca.kitenet.net.gpg index 26dd268..51114c7 100644 --- a/privdata/orca.kitenet.net.gpg +++ b/privdata/orca.kitenet.net.gpg @@ -1,57 +1,57 @@ -----BEGIN PGP MESSAGE----- Version: GnuPG v1 -hQIMA7ODiaEXBlRZARAAnvF9rQPZHZ04YTyCYggtf7wXU0PcCsxf9tJKPtdzYa3z -BAF2GAGRefrUtXclwEHEKAI6/kLuobUZ/ZXOKrZgGuaEwBK89CzafAkPrZ8tue91 -l1iOrZdGgXHLxCORxX2215q9wbg2u1xG3MkwRjHEb37C3tkS2QAQD+8ogsRggMhp -hLND3to2q6uv+zOw2mm9MpQUT/8KWRNKy1AbeVpluLhHGExMB+QvCN8ZMhVMzytS -4Kc2hMvSPqEkXD13El64SYUYy/m73sVJnCyOMuAyS7dBTV3AIjYhYlAQFBGPSpYB -u3YpwnTadR9O/FOTZF4NEvA5BtnHUBE0i4Zt+HJUrGJ5+rnb7sAnCSXz90dJkZvV -qgp/RJ62ywU5RsqRDD5Oz4xn+OuEauyyJo0F05X0A3GpIZAcmiJVLsDKS1seuruk -OTo/isvzyMlv7Xy+FTY6IE4vSd+1j9xhnUz9+jgMWxsZCOSR1bAKKFrYCNB3IOzw -T3+JbykuvkXmgPL6P3gwAqewHI/c1k/uhjp2ed/UTMndvsuI7XPlXhuRUwRvHAf7 -uQ9DtHvsmMQnuhpUD32PqdbagnPhd4Q9QZmbPhW2bY9k+HGCFsxrDnohWJOH1aod -rn5GsEn0RKXpXp9krgeOciP6crsu6TcZUncG1ZMZUNKgD0TtL6DaH8XSqFuDA6/S -6gHxO5txjvm7h5ZRIQEGWtgX2kLWfb6V5u/tYVI1kNixyXV5zPO6UMxDR6MFUmji -E+Z+4ACB2066fiIGTvlae9nqa0LXTVrnTXOHvna/hHI6kmwBXiW2wqVj5rt+yZ71 -DCfRCVH6t6u7PwDH2MGSKBlDLM3ssNDpwiw/lBRPCu1D+M5C99Vv/LwDSVZ67PnJ -zo1DWp+J6dGuvSgICQHyA5rdol/Fmn2lmArUOGwWbbuLyDEYiaRwuzQ8gnhTVV1Y -RdDsUFRumiq/EFWsqOFyz8r5m7/CzhXgZB7uA04u9YvCe2RqqLneg0eg/JlwBmjK -tRLZXQPWtmREmtBe8BneDuypEyLN2gpnADPz5sqke7Ow92EeKxWUIfEEw8YyQssQ -wmBVGe3kRy8kqaKFRa7rH13SE7hy/w/wp2745fFyAHt0nuGnodCmdm8+eiDIiBTt -++erO/MB2LAQIP8B7+UnNH6uLf9F02jDRPdVrVjQDIzlAMnMwvBZt0vD4zodL0Yk -Dfd06QK+1TLLfCY5+EMG081bdg2tMrUY5sW4GKm4AKTnk7/k3NurAyJUpRjjb6I+ -oTppbqL1BZ5ig8JDtQ3qmdRPsXDfc7/WBW++mPxG5CN+fZVEV0bHzuftlK7nlsyA -SAknzgFu+kDuC9DpTu4PQlSMEVFVHmLlmiF+PO7qAKkvDAiNCp13Lbaitmpj6DX/ -FlHD4ccPP6n6UQ+Xj3aCF24VwlxIvoqT/m3j/LNlj6z7CyBxTqb1mGVAV5aY01ZT -5V9v7emYxdWXejo1RzJLJREAd/idJ22camrtXV4Xs+x4c+JJB6e3iqbD61aS1vwd -A33/3+s143EEBhNeYwB91dssmtmCFJrMhi1tD/kHoVO7M8IZt+86fGVOTSNxKfi6 -1UOp5NYm3z3HeGobT2SQ9YOwQb6/x+2D981gKG0YTedQG7SS63I1r+WAP0TvujZQ -cgp4rENBCnjWipiuHxIf5vi2h3ycUEz0WLB4d2uFZSiuI68M621/WT3CDBLFI0d0 -nSXM1M4wCL1bGqWRK+h2J48WrNbcghZONtSrK5lhkOQoOTnulYuy4fZk0O0e8ygy -fF2JaDcRY4bAqDO2JUsKAI2+9Qvg5PU0qAW+mQIMFKskBVjl5aWt6wqeOhA/jjhz -+3rDcM3OOopgOdqDN/hLeQODO06g47wj/quUWYBhML1sjjqMhVHTG6e0ierhWuaX -UdODqcrCL40WVQJDr8AgzeV6n0xGR3agdmJgTG7PLDWhYgqgaVMS7dh3jU51BrUj -s7SJ60dxxdI3Rj6HwBAy6Gp93b3oaylcLIzyjYBwU6sJ45Ac5A3nPSlL750NaqL4 -iQpXRg8xZ+ljuRtUH2iKyRjp2W6PAiER3viSsHM8HsJANbpmics7QzRcAIeSleKZ -FhPl5f9O3D69CRFQOqBXmdMO/FuSu8sTLy87BYaqBLVkuABCnEC6YPCSogo53u2p -qFUfnHVkN5bf5P0EplesR+x5MVJHf9swsQPwcx/bBxD9FBqAGiPQKkkc8f6TtwfQ -5dS+geEa/EG7wvdDlaUVXYJI0cqityBIhKcMs8XT8LXX+ohJSWl3guhyNaiFaGeg -CMrnVnlMetAy4Krg9Avb6suLe2rT8LGJ9wL1DgjVzAqsh/uhC4loMo1sEa3xaIcy -I16zPeRSiBr+dS43ombTtIC8NM7zADWrR37HyJotwFIwkufBzgrXXo8HjmVonCNU -L+wRP9p2TgrnHN9fAKHxtWpJQYnFg2uzV7dLEtnIwmJ76schWZNnaViaB3lIvV5w -J4VrcjT/z497tS/KdYe1LitKW6CkRDPYrJZUmolmZue83VWKLtl79bXbZHR8BEjU -+rR0GHO98rJs2AMOyWLK8jTDNGu1TpxGyUBMTBi3ihy0/ssdBbMY0JZ2D0Wo+bKH -zqxpx7Z90Lf6r2esy83SeJIjVxJy9OoEOQzLg+CxkRLHdUrH5sNeWyDHHeGqhhJ0 -pChFbO3YtCqJJetttleOv/bZR7el5aXqA7PI3ypDiuBnMZp42svP8IzeitpYmfHK -0/fAz8ZVkqAPYj3HJetdxVxuEXNkKw6rBQJ/Qy0LsmGuX9CzWeX2AYzWW18nK0a+ -wmh7VLh15UQBctqG+3JNlRV3C2vw+QhktK5BF8sf7NGUAPT1QMO+5avIxHJjihfs -6K2rPTWsyJrVUt/fR8CHIHrxyhiLeS617J9lcb7N+l4j9Ug4s1KsJRuj8odhud6z -A5sfeRvzqR0c3BtF525NwdUBPEJKoToC0KKdLyKxjPOkoxifmIW6x0myli0CpkzA -3tw6J4TPt3opwqDz1Ts7mzagzOx0TDB9hKYsSfJv7sKp0Q3q8isDx75Ci500BfnB -VqetHONIBnmkYvHzNUPKo+e4OcOBNvbZwzjXk1e5EBP5ytG3BPczMYFVkM0ln0DM -UbXDJHQKi9yIbhlLmhWtU+RU69h0nFBPbS7Rlyhcw4W/GEeDcmgQlwf2eluoSHG1 -MFd/WcLqxVVnXrYNoSvO/DjHKQIBvtSXKXrAoOKvdlVE4n4nPAo6xI0iaPISFdWD -E61aknSkeMlS0WT07bvrS7w4xA== -=q6pD +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 +=ZBoU -----END PGP MESSAGE----- From ea3d55913cbbb03e41ff72a9f0f0c237897940a0 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 26 May 2014 18:53:42 -0400 Subject: [PATCH 59/75] propellor spin From 757c54ee6e1fa60f6c301d8d5ca46329c368dcce Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 26 May 2014 18:57:04 -0400 Subject: [PATCH 60/75] propellor spin From fe685d2660ca04226330a1955705dff458a49b2c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 26 May 2014 18:59:13 -0400 Subject: [PATCH 61/75] propellor spin --- src/Propellor/Property/SiteSpecific/JoeySites.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Propellor/Property/SiteSpecific/JoeySites.hs b/src/Propellor/Property/SiteSpecific/JoeySites.hs index 5f054ea..587e16a 100644 --- a/src/Propellor/Property/SiteSpecific/JoeySites.hs +++ b/src/Propellor/Property/SiteSpecific/JoeySites.hs @@ -267,9 +267,11 @@ gitAnnexDistributor :: Property gitAnnexDistributor = combineProperties "git-annex distributor, including rsync server and signer" [ Apt.installed ["rsync"] , File.hasPrivContent "/etc/rsyncd.conf" + `onChange` Service.restarted "rsync" , File.hasPrivContent "/etc/rsyncd.secrets" + `onChange` Service.restarted "rsync" , "/etc/default/rsync" `File.containsLine` "RSYNC_ENABLE=true" - `onChange` Service.running "rsync" + `onChange` Service.running "rsync" , endpoint "/srv/web/downloads.kitenet.net/git-annex/autobuild" , endpoint "/srv/web/downloads.kitenet.net/git-annex/autobuild/x86_64-apple-mavericks" -- git-annex distribution signing key From 16fbf3c6f67f1eed11a9d189e2c7c2723ef5969a Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 27 May 2014 21:17:53 -0400 Subject: [PATCH 62/75] reorg git-annex android builder, and put a dev container on my laptop --- config-joey.hs | 13 ++++--- .../Property/SiteSpecific/GitAnnexBuilder.hs | 35 ++++++++++--------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 84cc716..6c4dff7 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -42,6 +42,7 @@ hosts = -- (o) ` & ipv6 "2001:4830:1600:187::2" -- sixxs tunnel & Docker.configured & Apt.buildDep ["git-annex"] `period` Daily + & Docker.docked hosts "android-git-annex" -- Nothing super-important lives here. , standardSystem "clam.kitenet.net" Unstable "amd64" @@ -193,11 +194,15 @@ hosts = -- (o) ` (Just "remotes/origin/old-kitenet.net") -- git-annex autobuilder containers - , GitAnnexBuilder.standardContainer dockerImage "amd64" 15 "2h" - , GitAnnexBuilder.standardContainer dockerImage "i386" 45 "2h" + , GitAnnexBuilder.standardAutoBuilderContainer dockerImage "amd64" 15 "2h" + , GitAnnexBuilder.standardAutoBuilderContainer dockerImage "i386" 45 "2h" , GitAnnexBuilder.armelCompanionContainer dockerImage - , GitAnnexBuilder.armelContainer dockerImage "1 3 * * *" "5h" - , GitAnnexBuilder.androidContainer dockerImage "1 1 * * *" "3h" + , GitAnnexBuilder.armelAutoBuilderContainer dockerImage "1 3 * * *" "5h" + , GitAnnexBuilder.androidAutoBuilderContainer dockerImage "1 1 * * *" "3h" + + -- for development of git-annex for android + , GitAnnexBuilder.androidContainer dockerImage "android-git-annex" + & Docker.volume ("/home/joey/src/git-annex:" ++ GitAnnexBuilder.homedir "git-annex") ] ++ monsters -- This is my standard system setup. diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index a154c92..15e4e6c 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -24,12 +24,8 @@ builddir = gitbuilderdir "build" type TimeOut = String -- eg, 5h builder :: Architecture -> CronTimes -> TimeOut -> Bool -> Property -builder = builder' buildDeps - -builder' :: Property -> Architecture -> CronTimes -> TimeOut -> Bool -> Property -builder' buildepsprop buildarch crontimes timeout rsyncupload = combineProperties "gitannexbuilder" +builder buildarch crontimes timeout rsyncupload = combineProperties "gitannexbuilder" [ tree buildarch - , buildepsprop , Apt.serviceInstalledRunning "cron" , Cron.niceJob "gitannexbuilder" crontimes builduser gitbuilderdir $ "git pull ; timeout " ++ timeout ++ " ./autobuild" @@ -72,8 +68,8 @@ tree buildarch = combineProperties "gitannexbuilder tree" ] ] -buildDeps :: Property -buildDeps = combineProperties "gitannexbuilder build deps" +buildDepsApt :: Property +buildDepsApt = combineProperties "gitannexbuilder build deps" [ Apt.buildDep ["git-annex"] , buildDepsFewHaskellLibs , "git-annex source build deps installed" ==> Apt.buildDepIn builddir @@ -102,20 +98,26 @@ cabalDeps = flagFile go cabalupdated go = userScriptProperty builduser ["cabal update && cabal install git-annex --only-dependencies || true"] cabalupdated = homedir ".cabal" "packages" "hackage.haskell.org" "00-index.cache" -standardContainer :: (System -> Docker.Image) -> Architecture -> Int -> TimeOut -> Host -standardContainer dockerImage arch buildminute timeout = Docker.container (arch ++ "-git-annex-builder") +standardAutoBuilderContainer :: (System -> Docker.Image) -> Architecture -> Int -> TimeOut -> Host +standardAutoBuilderContainer dockerImage arch buildminute timeout = Docker.container (arch ++ "-git-annex-builder") (dockerImage $ System (Debian Unstable) arch) & Apt.stdSourcesList Unstable & Apt.unattendedUpgrades + & buildDepsApt & builder arch (show buildminute ++ " * * * *") timeout True +androidAutoBuilderContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Host +androidAutoBuilderContainer dockerImage crontimes timeout = + androidContainer dockerImage "android-git-annex-builder" + & Apt.unattendedUpgrades + & builder "android" crontimes timeout True + -- Android is cross-built in a Debian i386 container, using the Android NDK. -androidContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Host -androidContainer dockerImage crontimes timeout = Docker.container "android-git-annex-builder" +androidContainer :: (System -> Docker.Image) -> Docker.ContainerName -> Host +androidContainer dockerImage name = Docker.container name (dockerImage $ System (Debian Stable) "i386") & Apt.stdSourcesList Stable - & Apt.unattendedUpgrades - & builder' buildDepsNoHaskellLibs "android" crontimes timeout True + & buildDepsNoHaskellLibs & flagFile chrootsetup ("/chrootsetup") -- TODO: automate installing haskell libs -- (Currently have to run @@ -148,8 +150,8 @@ armelCompanionContainer dockerImage = Docker.container "armel-git-annex-builder- & Apt.serviceInstalledRunning "ssh" & Ssh.authorizedKeys builduser -armelContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Host -armelContainer dockerImage crontimes timeout = Docker.container "armel-git-annex-builder" +armelAutoBuilderContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Host +armelAutoBuilderContainer dockerImage crontimes timeout = Docker.container "armel-git-annex-builder" (dockerImage $ System (Debian Unstable) "armel") & Apt.stdSourcesList Unstable & Apt.unattendedUpgrades @@ -160,7 +162,8 @@ armelContainer dockerImage crontimes timeout = Docker.container "armel-git-annex -- (Currently have to run -- git-annex/standalone/linux/install-haskell-packages -- which is not fully automated.) - & builder' buildDepsFewHaskellLibs "armel" crontimes timeout True + & buildDepsFewHaskellLibs + & builder "armel" crontimes timeout True & Ssh.keyImported SshRsa builduser & trivial writecompanionaddress where From a0b808e8923c2ceb598bf56f8f2628c802574765 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 28 May 2014 01:32:54 -0400 Subject: [PATCH 63/75] comment fun --- config-joey.hs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index 6c4dff7..e145a39 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -27,16 +27,13 @@ import qualified Propellor.Property.SiteSpecific.GitHome as GitHome import qualified Propellor.Property.SiteSpecific.GitAnnexBuilder as GitAnnexBuilder import qualified Propellor.Property.SiteSpecific.JoeySites as JoeySites -main :: IO () -main = defaultMain hosts - - -- _ ______`| ,-.__ - {- Propellor -- / \___-=O`/|O`/__| (____.' - Deployed -} -- \ / | / ) _.-"-._ - -- `/-==__ _/__|/__=-| ( \_ -hosts :: [Host] -- * \ | | '--------' -hosts = -- (o) ` +main :: IO () -- _ ______`| ,-.__ +main = defaultMain hosts -- / \___-=O`/|O`/__| (____.' + {- Propellor -- \ / | / ) _.-"-._ + Deployed -} -- `/-==__ _/__|/__=-| ( \_ +hosts :: [Host] -- * \ | | '--------' +hosts = -- (o) ` -- My laptop [ host "darkstar.kitenet.net" & ipv6 "2001:4830:1600:187::2" -- sixxs tunnel From 2066292be9490fe2d8bc433e4c21b0a1907455e6 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 28 May 2014 10:38:29 -0400 Subject: [PATCH 64/75] propellor spin --- config-joey.hs | 8 ++++-- src/Propellor/Property.hs | 3 ++ .../Property/SiteSpecific/GitAnnexBuilder.hs | 28 ++++++++++--------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index e145a39..7d0a4e8 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -197,9 +197,11 @@ hosts = -- (o) ` , GitAnnexBuilder.armelAutoBuilderContainer dockerImage "1 3 * * *" "5h" , GitAnnexBuilder.androidAutoBuilderContainer dockerImage "1 1 * * *" "3h" - -- for development of git-annex for android - , GitAnnexBuilder.androidContainer dockerImage "android-git-annex" - & Docker.volume ("/home/joey/src/git-annex:" ++ GitAnnexBuilder.homedir "git-annex") + -- for development of git-annex for android, using my git-annex + -- work tree + , let gitannexdir = GitAnnexBuilder.homedir "git-annex" + in GitAnnexBuilder.androidContainer dockerImage "android-git-annex" doNothing gitannexdir + & Docker.volume ("/home/joey/src/git-annex:" ++ gitannexdir) ] ++ monsters -- This is my standard system setup. diff --git a/src/Propellor/Property.hs b/src/Propellor/Property.hs index 2449465..0728932 100644 --- a/src/Propellor/Property.hs +++ b/src/Propellor/Property.hs @@ -103,6 +103,9 @@ trivial p = adjustProperty p $ \satisfy -> do then return NoChange else return r +doNothing :: Property +doNothing = property "noop property" noChange + -- | Makes a property that is satisfied differently depending on the host's -- operating system. -- diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 15e4e6c..4f086a7 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -23,10 +23,9 @@ builddir = gitbuilderdir "build" type TimeOut = String -- eg, 5h -builder :: Architecture -> CronTimes -> TimeOut -> Bool -> Property -builder buildarch crontimes timeout rsyncupload = combineProperties "gitannexbuilder" - [ tree buildarch - , Apt.serviceInstalledRunning "cron" +autobuilder :: CronTimes -> TimeOut -> Bool -> Property +autobuilder crontimes timeout rsyncupload = combineProperties "gitannexbuilder" + [ Apt.serviceInstalledRunning "cron" , Cron.niceJob "gitannexbuilder" crontimes builduser gitbuilderdir $ "git pull ; timeout " ++ timeout ++ " ./autobuild" -- The builduser account does not have a password set, @@ -50,8 +49,7 @@ builder buildarch crontimes timeout rsyncupload = combineProperties "gitannexbui tree :: Architecture -> Property tree buildarch = combineProperties "gitannexbuilder tree" - [ User.accountFor builduser - , Apt.installed ["git"] + [ Apt.installed ["git"] -- gitbuilderdir directory already exists when docker volume is used, -- but with wrong owner. , File.dirExists gitbuilderdir @@ -104,21 +102,24 @@ standardAutoBuilderContainer dockerImage arch buildminute timeout = Docker.conta & Apt.stdSourcesList Unstable & Apt.unattendedUpgrades & buildDepsApt - & builder arch (show buildminute ++ " * * * *") timeout True + & autobuilder (show buildminute ++ " * * * *") timeout True + `requires` tree arch androidAutoBuilderContainer :: (System -> Docker.Image) -> Cron.CronTimes -> TimeOut -> Host androidAutoBuilderContainer dockerImage crontimes timeout = - androidContainer dockerImage "android-git-annex-builder" + androidContainer dockerImage "android-git-annex-builder" (tree "android") builddir & Apt.unattendedUpgrades - & builder "android" crontimes timeout True + & autobuilder crontimes timeout True -- Android is cross-built in a Debian i386 container, using the Android NDK. -androidContainer :: (System -> Docker.Image) -> Docker.ContainerName -> Host -androidContainer dockerImage name = Docker.container name +androidContainer :: (System -> Docker.Image) -> Docker.ContainerName -> Property -> FilePath -> Host +androidContainer dockerImage name setupgitannexdir gitannexdir = Docker.container name (dockerImage $ System (Debian Stable) "i386") & Apt.stdSourcesList Stable + & User.accountFor builduser & buildDepsNoHaskellLibs & flagFile chrootsetup ("/chrootsetup") + `requires` setupgitannexdir -- TODO: automate installing haskell libs -- (Currently have to run -- git-annex/standalone/android/install-haskell-packages @@ -128,7 +129,7 @@ androidContainer dockerImage name = Docker.container name -- ghc-android and the NDK, all build deps, etc, in the home -- directory of the builder user. chrootsetup = scriptProperty - [ "cd " ++ builddir ++ " && ./standalone/android/buildchroot-inchroot" + [ "cd " ++ gitannexdir ++ " && ./standalone/android/buildchroot-inchroot" ] -- armel builder has a companion container using amd64 that @@ -163,7 +164,8 @@ armelAutoBuilderContainer dockerImage crontimes timeout = Docker.container "arme -- git-annex/standalone/linux/install-haskell-packages -- which is not fully automated.) & buildDepsFewHaskellLibs - & builder "armel" crontimes timeout True + & autobuilder crontimes timeout True + `requires` tree "armel" & Ssh.keyImported SshRsa builduser & trivial writecompanionaddress where From 378fbf8020b94e137139e554a4ba3d4980b29a3b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 28 May 2014 10:40:12 -0400 Subject: [PATCH 65/75] propellor spin From 8c1848b897d5b5591db50bbc2e62e4f4f4b220b9 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 28 May 2014 11:10:55 -0400 Subject: [PATCH 66/75] propellor spin --- src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 4f086a7..bc3e874 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -117,6 +117,8 @@ androidContainer dockerImage name setupgitannexdir gitannexdir = Docker.containe (dockerImage $ System (Debian Stable) "i386") & Apt.stdSourcesList Stable & User.accountFor builduser + & File.dirExists gitbuilderdir + & File.ownerGroup gitbuilderdir builduser builduser & buildDepsNoHaskellLibs & flagFile chrootsetup ("/chrootsetup") `requires` setupgitannexdir From 3c7816cac0b922205aa5331223c08105518faf9b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 28 May 2014 11:20:45 -0400 Subject: [PATCH 67/75] propellor spin --- src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index bc3e874..3dcafa3 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -118,7 +118,7 @@ androidContainer dockerImage name setupgitannexdir gitannexdir = Docker.containe & Apt.stdSourcesList Stable & User.accountFor builduser & File.dirExists gitbuilderdir - & File.ownerGroup gitbuilderdir builduser builduser + & File.ownerGroup homedir builduser builduser & buildDepsNoHaskellLibs & flagFile chrootsetup ("/chrootsetup") `requires` setupgitannexdir From ffa3bf0f92d8168d1d6f99afa137416efa918517 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 28 May 2014 13:00:27 -0400 Subject: [PATCH 68/75] propellor spin From 800df3b97c03d9640e036622845af2ea178c48f5 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 28 May 2014 13:01:12 -0400 Subject: [PATCH 69/75] propellor spin From b419da71544bf6dd06e00b27d839341efcd5b05a Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 28 May 2014 16:26:21 -0400 Subject: [PATCH 70/75] no need for existentials anymore --- src/Propellor/Types.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Propellor/Types.hs b/src/Propellor/Types.hs index 22df9dd..8a4bd3d 100644 --- a/src/Propellor/Types.hs +++ b/src/Propellor/Types.hs @@ -1,6 +1,5 @@ {-# LANGUAGE PackageImports #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} -{-# LANGUAGE ExistentialQuantification #-} module Propellor.Types ( Host(..) @@ -35,6 +34,8 @@ import Propellor.Types.Attr import Propellor.Types.OS import Propellor.Types.Dns +-- | Everything Propellor knows about a system: Its properties and +-- attributes. data Host = Host [Property] SetAttr -- | Propellor's monad provides read-only access to attributes of the From d29932be8ec3122f6953b548e5cef9bd5824e7c0 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 29 May 2014 13:08:33 -0400 Subject: [PATCH 71/75] propellor spin From f79c03fe618c4e11a61b7ee8d80f61fbcb4547bb Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 29 May 2014 13:11:43 -0400 Subject: [PATCH 72/75] propellor spin From 71ca868f08bdf8f75f4f4545f233749cc19fcc3d Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 29 May 2014 13:14:34 -0400 Subject: [PATCH 73/75] propellor spin From fba1ee74fa0c91b1020686e40ee17d147396418e Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 29 May 2014 14:26:58 -0400 Subject: [PATCH 74/75] propellor spin From ead04c65e06ed47a175624922582a33082585f6d Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 29 May 2014 14:29:23 -0400 Subject: [PATCH 75/75] merge from git-annex --- src/Utility/Process.hs | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/Utility/Process.hs b/src/Utility/Process.hs index 549ae57..cd3826d 100644 --- a/src/Utility/Process.hs +++ b/src/Utility/Process.hs @@ -167,10 +167,10 @@ processTranscript :: String -> [String] -> (Maybe String) -> IO (String, Bool) processTranscript cmd opts input = processTranscript' cmd opts Nothing input processTranscript' :: String -> [String] -> Maybe [(String, String)] -> (Maybe String) -> IO (String, Bool) +processTranscript' cmd opts environ input = do #ifndef mingw32_HOST_OS {- This implementation interleves stdout and stderr in exactly the order - the process writes them. -} -processTranscript' cmd opts environ input = do (readf, writef) <- createPipe readh <- fdToHandle readf writeh <- fdToHandle writef @@ -184,24 +184,13 @@ processTranscript' cmd opts environ input = do hClose writeh get <- mkreader readh - - -- now write and flush any input - case input of - Just s -> do - let inh = stdinHandle p - unless (null s) $ do - hPutStr inh s - hFlush inh - hClose inh - Nothing -> return () - + writeinput input p transcript <- get ok <- checkSuccessProcess pid return (transcript, ok) #else {- This implementation for Windows puts stderr after stdout. -} -processTranscript' cmd opts environ input = do p@(_, _, _, pid) <- createProcess $ (proc cmd opts) { std_in = if isJust input then CreatePipe else Inherit @@ -212,17 +201,9 @@ processTranscript' cmd opts environ input = do getout <- mkreader (stdoutHandle p) geterr <- mkreader (stderrHandle p) - - case input of - Just s -> do - let inh = stdinHandle p - unless (null s) $ do - hPutStr inh s - hFlush inh - hClose inh - Nothing -> return () - + writeinput input p transcript <- (++) <$> getout <*> geterr + ok <- checkSuccessProcess pid return (transcript, ok) #endif @@ -237,6 +218,14 @@ processTranscript' cmd opts environ input = do takeMVar v return s + writeinput (Just s) p = do + let inh = stdinHandle p + unless (null s) $ do + hPutStr inh s + hFlush inh + hClose inh + writeinput Nothing _ = return () + {- Runs a CreateProcessRunner, on a CreateProcess structure, that - is adjusted to pipe only from/to a single StdHandle, and passes - the resulting Handle to an action. -}