From 536d9fec70eb3343e51200915555ac651a57f3f4 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 30 May 2015 14:02:25 -0400 Subject: propellor spin --- src/Propellor/Spin.hs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/Propellor') diff --git a/src/Propellor/Spin.hs b/src/Propellor/Spin.hs index 3ff1ec21..9685a486 100644 --- a/src/Propellor/Spin.hs +++ b/src/Propellor/Spin.hs @@ -102,6 +102,7 @@ getSshTarget target hst go (Left e) = useip (show e) go (Right addrinfos) = do configaddrinfos <- catMaybes <$> mapM iptoaddr configips + print (configips, configaddrinfos, map addrAddress addrinfos) if any (`elem` configaddrinfos) (map addrAddress addrinfos) then return target else useip ("DNS lookup did not return any of the expected addresses " ++ show configips) -- cgit v1.2.3 From 7b8b77936096e9a081494bce2756b9793d98a345 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 30 May 2015 14:03:23 -0400 Subject: revert test --- config-joey.hs | 2 +- src/Propellor/Spin.hs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/Propellor') diff --git a/config-joey.hs b/config-joey.hs index 0219c5f2..73c9687b 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -145,7 +145,7 @@ orca = standardSystem "orca.kitenet.net" Unstable "amd64" honeybee :: Host honeybee = standardSystem "honeybee.kitenet.net" Testing "armhf" [ "Arm git-annex build box." ] - & ipv6 "2001:4830:1600:187::3" + & ipv6 "2001:4830:1600:187::2" -- No unattended upgrades as there is currently no console access. -- (Also, system is not currently running a stock kernel, diff --git a/src/Propellor/Spin.hs b/src/Propellor/Spin.hs index 9685a486..3ff1ec21 100644 --- a/src/Propellor/Spin.hs +++ b/src/Propellor/Spin.hs @@ -102,7 +102,6 @@ getSshTarget target hst go (Left e) = useip (show e) go (Right addrinfos) = do configaddrinfos <- catMaybes <$> mapM iptoaddr configips - print (configips, configaddrinfos, map addrAddress addrinfos) if any (`elem` configaddrinfos) (map addrAddress addrinfos) then return target else useip ("DNS lookup did not return any of the expected addresses " ++ show configips) -- cgit v1.2.3 From 446a2e4c9a3fe27782fd6d5d3228fc83a83fe82a Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 13:55:07 -0400 Subject: update --- config-joey.hs | 19 +++-- .../Property/SiteSpecific/GitAnnexBuilder.hs | 88 +++++++--------------- 2 files changed, 40 insertions(+), 67 deletions(-) (limited to 'src/Propellor') diff --git a/config-joey.hs b/config-joey.hs index 73c9687b..8e4ee9dc 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -133,9 +133,11 @@ orca = standardSystem "orca.kitenet.net" Unstable "amd64" & Apt.serviceInstalledRunning "ntp" & Systemd.persistentJournal - & Systemd.nspawned (GitAnnexBuilder.standardAutoBuilderContainer + & Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer + GitAnnexBuilder.standardAutoBuilder (System (Debian Testing) "amd64") fifteenpast "2h") - & Systemd.nspawned (GitAnnexBuilder.standardAutoBuilderContainer + & Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer + GitAnnexBuilder.standardAutoBuilder (System (Debian Testing) "i386") fifteenpast "2h") & Systemd.nspawned (GitAnnexBuilder.androidAutoBuilderContainer (Cron.Times "1 1 * * *") "3h") @@ -151,15 +153,20 @@ honeybee = standardSystem "honeybee.kitenet.net" Testing "armhf" -- (Also, system is not currently running a stock kernel, -- although it should be able to.) & Postfix.satellite - & Apt.serviceInstalledRunning "ntp" & Apt.serviceInstalledRunning "aiccu" + & Apt.serviceInstalledRunning "swapspace" + & Apt.serviceInstalledRunning "ntp" -- Not using systemd-nspawn because it's broken (kernel issue?) - -- & Systemd.nspawned (GitAnnexBuilder.standardAutoBuilderContainer - -- osver Cron.Daily "22h") + -- & Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer + -- GitAnnexBuilder.armAutoBuilder + -- builderos Cron.Daily "22h") & Chroot.provisioned (Chroot.debootstrapped builderos mempty "/var/lib/container/armel-git-annex-builder" - & GitAnnexBuilder.standardAutoBuilder builderos Cron.Daily "22h") + & "/etc/timezone" `File.hasContent` ["America/New_York"] + & GitAnnexBuilder.armAutoBuilder + builderos (Cron.Times "1 1 * * *") "12h" + ) where -- Using unstable to get new enough ghc for TH on arm. builderos = System (Debian Unstable) "armel" diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index 3c638721..d64852aa 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -6,9 +6,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.Ssh as Ssh import qualified Propellor.Property.File as File -import qualified Propellor.Property.Docker as Docker import qualified Propellor.Property.Systemd as Systemd import qualified Propellor.Property.Chroot as Chroot import Propellor.Property.Cron (Times) @@ -50,8 +48,6 @@ autobuilder arch crontimes timeout = combineProperties "gitannexbuilder" $ props tree :: Architecture -> Property HasInfo tree buildarch = combineProperties "gitannexbuilder tree" $ props & Apt.installed ["git"] - -- gitbuilderdir directory already exists when docker volume is used, - -- but with wrong owner. & File.dirExists gitbuilderdir & File.ownerGroup gitbuilderdir (User builduser) (Group builduser) & gitannexbuildercloned @@ -86,6 +82,13 @@ buildDepsNoHaskellLibs = Apt.installed "alex", "happy", "c2hs" ] +haskellPkgsInstalled :: String -> Property NoInfo +haskellPkgsInstalled dir = flagFile go ("/haskellpkgsinstalled") + where + go = userScriptProperty (User builduser) + [ "cd " ++ builddir ++ " && ./standalone/ " ++ dir ++ "/install-haskell-packages" + ] + -- Installs current versions of git-annex's deps from cabal, but only -- does so once. cabalDeps :: Property NoInfo @@ -94,23 +97,36 @@ cabalDeps = flagFile go cabalupdated go = userScriptProperty (User builduser) ["cabal update && cabal install git-annex --only-dependencies || true"] cabalupdated = homedir ".cabal" "packages" "hackage.haskell.org" "00-index.cache" -standardAutoBuilderContainer :: System -> Times -> TimeOut -> Systemd.Container -standardAutoBuilderContainer osver@(System _ arch) crontime timeout = +autoBuilderContainer :: (System -> Property HasInfo) -> System -> Times -> TimeOut -> Systemd.Container +autoBuilderContainer mkprop osver@(System _ arch) crontime timeout = Systemd.container name bootstrap - & standardAutoBuilder osver crontime timeout + & mkprop osver + & buildDepsApt + & autobuilder arch crontime timeout where name = arch ++ "-git-annex-builder" bootstrap = Chroot.debootstrapped osver mempty -standardAutoBuilder :: System -> Times -> TimeOut -> Property HasInfo -standardAutoBuilder osver@(System _ arch) crontime timeout = +standardAutoBuilder :: System -> Property HasInfo +standardAutoBuilder osver@(System _ arch) = propertyList "git-annex-builder" $ props & os osver & Apt.stdSourcesList & Apt.unattendedUpgrades & User.accountFor (User builduser) & tree arch - & buildDepsApt + +armAutoBuilder :: System -> Times -> TimeOut -> Property HasInfo +armAutoBuilder osver@(System _ arch) crontime timeout = + propertyList "git-annex-builder (arm)" $ props + & standardAutoBuilder osver + & buildDepsNoHaskellLibs + -- Works around ghc crash with parallel builds on arm. + & (homedir ".cabal" "config") + `File.lacksLine` "jobs: $ncpus" + -- Install patched haskell packages for portability to + -- arm NAS's using old kernel versions. + & haskellPkgsInstalled "linux" & autobuilder arch crontime timeout androidAutoBuilderContainer :: Times -> TimeOut -> Systemd.Container @@ -135,7 +151,7 @@ androidContainer name setupgitannexdir gitannexdir = Systemd.container name boot & flagFile chrootsetup ("/chrootsetup") `requires` setupgitannexdir & buildDepsApt - & flagFile haskellpkgsinstalled ("/haskellpkgsinstalled") + & haskellPkgsInstalled "android" where -- Use git-annex's android chroot setup script, which will install -- ghc-android and the NDK, all build deps, etc, in the home @@ -143,55 +159,5 @@ androidContainer name setupgitannexdir gitannexdir = Systemd.container name boot chrootsetup = scriptProperty [ "cd " ++ gitannexdir ++ " && ./standalone/android/buildchroot-inchroot" ] - haskellpkgsinstalled = userScriptProperty (User builduser) - [ "cd " ++ gitannexdir ++ " && ./standalone/android/install-haskell-packages" - ] osver = System (Debian Testing) "i386" bootstrap = Chroot.debootstrapped osver mempty - --- 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) -> Docker.Container -armelCompanionContainer dockerImage = Docker.container "armel-git-annex-builder-companion" - (dockerImage $ System (Debian Unstable) "amd64") - & os (System (Debian Testing) "amd64") - & Apt.stdSourcesList - & Apt.installed ["systemd"] - -- This volume is shared with the armel builder. - & Docker.volume gitbuilderdir - & User.accountFor (User builduser) - -- Install current versions of build deps from cabal. - & tree "armel" - & buildDepsNoHaskellLibs - & cabalDeps - -- The armel builder can ssh to this companion. - & Docker.expose "22" - & Apt.serviceInstalledRunning "ssh" - & Ssh.authorizedKeys (User builduser) (Context "armel-git-annex-builder") - & Docker.tweaked - -armelAutoBuilderContainer :: (System -> Docker.Image) -> Times -> TimeOut -> Docker.Container -armelAutoBuilderContainer dockerImage crontimes timeout = Docker.container "armel-git-annex-builder" - (dockerImage $ System (Debian Unstable) "armel") - & os (System (Debian Testing) "armel") - & Apt.stdSourcesList - & Apt.installed ["systemd"] - & Apt.installed ["openssh-client"] - & Docker.link "armel-git-annex-builder-companion" "companion" - & Docker.volumes_from "armel-git-annex-builder-companion" - & User.accountFor (User builduser) - -- TODO: automate installing haskell libs - -- (Currently have to run - -- git-annex/standalone/linux/install-haskell-packages - -- which is not fully automated.) - & buildDepsNoHaskellLibs - & autobuilder "armel" crontimes timeout - `requires` tree "armel" - & Ssh.keyImported SshRsa (User builduser) (Context "armel-git-annex-builder") - & trivial writecompanionaddress - & Docker.tweaked - where - writecompanionaddress = scriptProperty - [ "echo \"$COMPANION_PORT_22_TCP_ADDR\" > " ++ homedir "companion_address" - ] `describe` "companion_address file" -- cgit v1.2.3 From a5bb972d94b2e29f73ecfa4abab275400d0caeef Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 13:56:30 -0400 Subject: remove Params constructor Before it gets into released API... --- src/Propellor/Ssh.hs | 5 +++-- src/Utility/SafeCommand.hs | 14 ++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'src/Propellor') diff --git a/src/Propellor/Ssh.hs b/src/Propellor/Ssh.hs index ac9295d1..3fe78f7a 100644 --- a/src/Propellor/Ssh.hs +++ b/src/Propellor/Ssh.hs @@ -22,7 +22,8 @@ sshCachingParams hn = do let ps = [ Param "-o" , Param ("ControlPath=" ++ socketfile) - , Params "-o ControlMaster=auto -o ControlPersist=yes" + , Param "-o", Param "ControlMaster=auto" + , Param "-o", Param "ControlPersist=yes" ] maybe noop (expireold ps socketfile) @@ -37,7 +38,7 @@ sshCachingParams hn = do then touchFile f else do void $ boolSystem "ssh" $ - [ Params "-O stop" ] ++ ps ++ + [ Param "-O", Param "stop" ] ++ ps ++ [ Param "localhost" ] nukeFile f tenminutes = 600 diff --git a/src/Utility/SafeCommand.hs b/src/Utility/SafeCommand.hs index 82e35049..9102b726 100644 --- a/src/Utility/SafeCommand.hs +++ b/src/Utility/SafeCommand.hs @@ -19,25 +19,23 @@ import Prelude -- | Parameters that can be passed to a shell command. data CommandParam - = Params String -- ^ Contains multiple parameters, separated by whitespace - | Param String -- ^ A single parameter + = Param String -- ^ A parameter | File FilePath -- ^ The name of a file deriving (Eq, Show, Ord) -- | Used to pass a list of CommandParams to a function that runs -- a command and expects Strings. -} toCommand :: [CommandParam] -> [String] -toCommand = concatMap unwrap +toCommand = map unwrap where - unwrap (Param s) = [s] - unwrap (Params s) = filter (not . null) (split " " s) + unwrap (Param s) = s -- Files that start with a non-alphanumeric that is not a path -- separator are modified to avoid the command interpreting them as -- options or other special constructs. unwrap (File s@(h:_)) - | isAlphaNum h || h `elem` pathseps = [s] - | otherwise = ["./" ++ s] - unwrap (File s) = [s] + | isAlphaNum h || h `elem` pathseps = s + | otherwise = "./" ++ s + unwrap (File s) = s -- '/' is explicitly included because it's an alternative -- path separator on Windows. pathseps = pathSeparator:"./" -- cgit v1.2.3 From 65357750d212ac3d8faaad0340f8259d74913810 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 14:18:36 -0400 Subject: Added publish property for systemd-spawn containers. (Needs systemd version 220.) --- debian/changelog | 2 ++ src/Propellor/Property/Systemd.hs | 46 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) (limited to 'src/Propellor') diff --git a/debian/changelog b/debian/changelog index 6a105804..9b75e118 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,8 @@ propellor (2.5.0) UNRELEASED; urgency=medium * Mount /proc inside a chroot before provisioning it, to work around #787227 * --spin now works when given a short hostname that only resolves to an ipv6 address. + * Added publish property for systemd-spawn containers. + (Needs systemd version 220.) -- Joey Hess Thu, 07 May 2015 12:08:34 -0400 diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index c698f780..21b66cb8 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -1,22 +1,30 @@ module Propellor.Property.Systemd ( + -- * Services module Propellor.Property.Systemd.Core, ServiceName, - MachineName, started, stopped, enabled, disabled, restarted, - persistentJournal, + -- * Configuration Option, configured, - journaldConfigured, daemonReloaded, + -- * Journal + persistentJournal, + journaldConfigured, + -- * Containers + MachineName, Container, container, nspawned, + -- * Container configuration containerCfg, resolvConfed, + publish, + Proto(..), + publish' ) where import Propellor @@ -24,6 +32,7 @@ import Propellor.Types.Chroot import qualified Propellor.Property.Chroot as Chroot import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.File as File +import Propellor.Property.Firewall (Port) import Propellor.Property.Systemd.Core import Utility.FileMode @@ -270,3 +279,34 @@ containerCfg p = RevertableProperty (mk True) (mk False) -- This property is enabled by default. Revert it to disable it. resolvConfed :: RevertableProperty resolvConfed = containerCfg "bind=/etc/resolv.conf" + +-- | Disconnect networking of the container from the host. +privateNetwork :: RevertableProperty +privateNetwork = containerCfg "private-network" + +-- | Publish a container's (tcp) port to same port on the host. +-- +-- This automatically enables privateNetwork, so all non-published ports +-- will not be accessible outside the container. +-- +-- Note that this feature was first added in systemd version 220. +publish :: Port -> RevertableProperty +publish p = publish' TCP p p + `requires` privateNetwork + +data Proto = TCP | UDP + +publish' + :: Proto + -> Port -- ^ Host port + -> Port -- ^ Container port + -> RevertableProperty +publish' proto hostport containerport = containerCfg $ "--port=" ++ + intercalate ":" + [ sproto proto + , show hostport + , show containerport + ] + where + sproto TCP = "tcp" + sproto UDP = "udp" -- cgit v1.2.3 From a7045f737efe76c7346a1ac34f10d0d8d311ff89 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 14:51:56 -0400 Subject: propellor spin --- config-joey.hs | 32 ++++++++++++++++++-------------- src/Propellor/Property/Systemd.hs | 17 ++++++++++++++++- 2 files changed, 34 insertions(+), 15 deletions(-) (limited to 'src/Propellor') diff --git a/config-joey.hs b/config-joey.hs index 8fb03f01..56f1eb93 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -76,7 +76,6 @@ darkstar = host "darkstar.kitenet.net" & ipv6 "2001:4830:1600:187::2" -- sixxs tunnel & Apt.buildDep ["git-annex"] `period` Daily - & Docker.configured & JoeySites.postfixClientRelay (Context "darkstar.kitenet.net") & JoeySites.dkimMilter @@ -84,7 +83,6 @@ darkstar = host "darkstar.kitenet.net" gnu :: Host gnu = host "gnu.kitenet.net" & Apt.buildDep ["git-annex"] `period` Daily - & Docker.configured & JoeySites.postfixClientRelay (Context "gnu.kitenet.net") & JoeySites.dkimMilter @@ -256,9 +254,6 @@ kite = standardSystemUnhardened "kite.kitenet.net" Testing "amd64" , "zsh" ] - & Docker.configured - & Docker.garbageCollected `period` Daily - & alias "nntp.olduse.net" & JoeySites.oldUseNetServer hosts @@ -414,8 +409,8 @@ iabak = host "iabak.archiveteam.org" -- Simple web server, publishing the outside host's /var/www webserver :: Systemd.Container webserver = standardStableContainer "webserver" - & Docker.publish "80:80" - & Docker.volume "/var/www:/var/www" + & Systemd.publish 80 + & Systemd.bind "/var/www" & Apt.serviceInstalledRunning "apache2" webserver' :: Docker.Container @@ -449,7 +444,7 @@ oldusenetShellBox = standardStableDockerContainer "oldusenet-shellbox" & JoeySites.oldUseNetShellBox jerryPlay :: Docker.Container -jerryPlay = standardContainer "jerryplay" Unstable "amd64" +jerryPlay = standardDockerContainer "jerryplay" Unstable "amd64" & alias "jerryplay.kitenet.net" & Docker.publish "2202:22" & Docker.publish "8001:80" @@ -491,16 +486,25 @@ standardSystemUnhardened hn suite arch motd = host hn & Apt.removed ["exim4", "exim4-daemon-light", "exim4-config", "exim4-base"] `onChange` Apt.autoRemove +-- This is my standard container setup, Featuring automatic upgrades. +standardContainer :: Systemd.MachineName -> DebianSuite -> Architecture -> Systemd.Container +standardContainer name suite arch = Systemd.container name chroot + & os system + & Apt.stdSourcesList `onChange` Apt.upgrade + & Apt.unattendedUpgrades + & Apt.cacheCleaned + where + system = System (Debian suite) arch + chroot = Chroot.debootstrapped system mempty + standardStableContainer :: Systemd.MachineName -> Systemd.Container -standardStableContainer name = Systemd.container name $ - Chroot.debootstrapped (System (Debian (Stable "jessie")) "amd64") mempty +standardStableContainer name = standardContainer name (Stable "jessie") "amd64" standardStableDockerContainer :: Docker.ContainerName -> Docker.Container -standardStableDockerContainer name = standardContainer name (Stable "jessie") "amd64" +standardStableDockerContainer name = standardDockerContainer name (Stable "jessie") "amd64" --- This is my standard container setup, Featuring automatic upgrades. -standardContainer :: Docker.ContainerName -> DebianSuite -> Architecture -> Docker.Container -standardContainer name suite arch = Docker.container name (dockerImage system) +standardDockerContainer :: Docker.ContainerName -> DebianSuite -> Architecture -> Docker.Container +standardDockerContainer name suite arch = Docker.container name (dockerImage system) & os system & Apt.stdSourcesList `onChange` Apt.upgrade & Apt.unattendedUpgrades diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 21b66cb8..973314ac 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -24,7 +24,9 @@ module Propellor.Property.Systemd ( resolvConfed, publish, Proto(..), - publish' + publish', + bind, + bindRo, ) where import Propellor @@ -274,6 +276,8 @@ containerCfg p = RevertableProperty (mk True) (mk False) ('-':_) -> p _ -> "--" ++ p + + -- | Bind mounts from the host into the container. -- -- This property is enabled by default. Revert it to disable it. @@ -310,3 +314,14 @@ publish' proto hostport containerport = containerCfg $ "--port=" ++ where sproto TCP = "tcp" sproto UDP = "udp" + +-- | Bind mount a file or directory from the host into the container. +-- +-- The parameter can be a FilePath, or a colon-separated pair of +-- hostpath:containerpath. +bind :: FilePath -> RevertableProperty +bind f = containerCfg $ "--bind=" ++ f + +-- | Read-only mind mount. +bindRo :: FilePath -> RevertableProperty +bindRo f = containerCfg $ "--bind-ro=" ++ f -- cgit v1.2.3 From a50edc3d9f1fc630ba5f72aba6cfec9aca71c204 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 16:05:31 -0400 Subject: better types for systemd port publishing --- config-joey.hs | 4 +-- debian/changelog | 5 ++-- src/Propellor/Property/Systemd.hs | 59 ++++++++++++++++++++++----------------- 3 files changed, 39 insertions(+), 29 deletions(-) (limited to 'src/Propellor') diff --git a/config-joey.hs b/config-joey.hs index 56f1eb93..ff06333d 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -104,8 +104,8 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64" & Docker.garbageCollected `period` Daily ! Docker.docked webserver' & File.dirExists "/var/www/html" - & File.notPresent "/var/www/html/index.html" - & "/var/www/index.html" `File.hasContent` ["hello, world"] + & File.notPresent "/var/www/index.html" + & "/var/www/html/index.html" `File.hasContent` ["hello, world"] & alias "helloworld.kitenet.net" & Docker.docked oldusenetShellBox diff --git a/debian/changelog b/debian/changelog index 9b75e118..a4c40ea5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,15 +8,16 @@ propellor (2.5.0) UNRELEASED; urgency=medium * createProcess from Propellor.Property.Cmd, so they are available for use in constricting your own Properties when using propellor as a library. - * Improve enter-machine scripts for nspawn containers to unset most + * Improve enter-machine scripts for systemd-nspawn containers to unset most environment variables. * Fix Postfix.satellite bug; the default relayhost was set to the domain, not to smtp.domain as documented. * Mount /proc inside a chroot before provisioning it, to work around #787227 * --spin now works when given a short hostname that only resolves to an ipv6 address. - * Added publish property for systemd-spawn containers. + * Added publish and publish' properties for systemd-spawn containers. (Needs systemd version 220.) + * Added bind and bindRo properties for systemd-spawn containers. -- Joey Hess Thu, 07 May 2015 12:08:34 -0400 diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 973314ac..34e51ba9 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE TypeSynonymInstances #-} + module Propellor.Property.Systemd ( -- * Services module Propellor.Property.Systemd.Core, @@ -22,9 +24,12 @@ module Propellor.Property.Systemd ( -- * Container configuration containerCfg, resolvConfed, - publish, + Publishable(..), + privateNetwork, + ForwardedPort(..), Proto(..), - publish', + PortSpec(..), + publish, bind, bindRo, ) where @@ -288,32 +293,36 @@ resolvConfed = containerCfg "bind=/etc/resolv.conf" privateNetwork :: RevertableProperty privateNetwork = containerCfg "private-network" --- | Publish a container's (tcp) port to same port on the host. --- --- This automatically enables privateNetwork, so all non-published ports --- will not be accessible outside the container. --- --- Note that this feature was first added in systemd version 220. -publish :: Port -> RevertableProperty -publish p = publish' TCP p p - `requires` privateNetwork +class Publishable a where + toPublish :: a -> String + +instance Publishable Port where + toPublish p = show p + +data ForwardedPort = ForwardedPort + { hostPort :: Port + , containerPort :: Port + } + +instance Publishable ForwardedPort where + toPublish fp = show (hostPort fp) ++ ":" ++ show (containerPort fp) data Proto = TCP | UDP -publish' - :: Proto - -> Port -- ^ Host port - -> Port -- ^ Container port - -> RevertableProperty -publish' proto hostport containerport = containerCfg $ "--port=" ++ - intercalate ":" - [ sproto proto - , show hostport - , show containerport - ] - where - sproto TCP = "tcp" - sproto UDP = "udp" +data PortSpec = PortSpec Proto ForwardedPort + +instance Publishable PortSpec where + toPublish (PortSpec TCP fp) = "tcp:" ++ toPublish fp + toPublish (PortSpec UDP fp) = "udp:" ++ toPublish fp + +-- | Publish a port from the container on the host. +-- +-- Note that this will only work if the container's network is set up +-- by other properties. +-- +-- This feature was first added in systemd version 220. +publish :: Publishable p => p -> RevertableProperty +publish p = containerCfg $ "--port=" ++ toPublish p -- | Bind mount a file or directory from the host into the container. -- -- cgit v1.2.3 From 85c3d110882f0f9d70316235221ba8b20754661f Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 16:12:21 -0400 Subject: reorganize Port type for systemd can use it --- config-joey.hs | 2 +- debian/changelog | 3 +++ src/Propellor/Property/Firewall.hs | 23 ++++++++++------------- src/Propellor/Property/Systemd.hs | 9 +++------ src/Propellor/Types/OS.hs | 4 ++++ 5 files changed, 21 insertions(+), 20 deletions(-) (limited to 'src/Propellor') diff --git a/config-joey.hs b/config-joey.hs index ff06333d..83eb5430 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -409,7 +409,7 @@ iabak = host "iabak.archiveteam.org" -- Simple web server, publishing the outside host's /var/www webserver :: Systemd.Container webserver = standardStableContainer "webserver" - & Systemd.publish 80 + & Systemd.publish (Port 80) & Systemd.bind "/var/www" & Apt.serviceInstalledRunning "apache2" diff --git a/debian/changelog b/debian/changelog index a4c40ea5..599143d8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -18,6 +18,9 @@ propellor (2.5.0) UNRELEASED; urgency=medium * Added publish and publish' properties for systemd-spawn containers. (Needs systemd version 220.) * Added bind and bindRo properties for systemd-spawn containers. + * Firewall: Port was changed to a newtype, and the Port and PortRange + constructors of Rules were changed to DPort and DportRange, respectively. + (API change) -- Joey Hess Thu, 07 May 2015 12:08:34 -0400 diff --git a/src/Propellor/Property/Firewall.hs b/src/Propellor/Property/Firewall.hs index ab57b122..d643b185 100644 --- a/src/Propellor/Property/Firewall.hs +++ b/src/Propellor/Property/Firewall.hs @@ -9,7 +9,6 @@ module Propellor.Property.Firewall ( Target(..), Proto(..), Rules(..), - Port, ConnectionState(..) ) where @@ -45,8 +44,8 @@ toIpTable r = map Param $ toIpTableArg :: Rules -> [String] toIpTableArg Everything = [] toIpTableArg (Proto proto) = ["-p", map toLower $ show proto] -toIpTableArg (Port port) = ["--dport", show port] -toIpTableArg (PortRange (f,t)) = ["--dport", show f ++ ":" ++ show t] +toIpTableArg (DPort port) = ["--dport", show port] +toIpTableArg (DPortRange (f,t)) = ["--dport", show f ++ ":" ++ show t] toIpTableArg (IFace iface) = ["-i", iface] toIpTableArg (Ctstate states) = ["-m", "conntrack","--ctstate", concat $ intersperse "," (map show states)] toIpTableArg (r :- r') = toIpTableArg r <> toIpTableArg r' @@ -55,33 +54,31 @@ data Rule = Rule { ruleChain :: Chain , ruleTarget :: Target , ruleRules :: Rules - } deriving (Eq, Show, Read) + } deriving (Eq, Show) data Chain = INPUT | OUTPUT | FORWARD - deriving (Eq,Show,Read) + deriving (Eq, Show) data Target = ACCEPT | REJECT | DROP | LOG - deriving (Eq,Show,Read) + deriving (Eq, Show) data Proto = TCP | UDP | ICMP - deriving (Eq,Show,Read) - -type Port = Int + deriving (Eq, Show) data ConnectionState = ESTABLISHED | RELATED | NEW | INVALID - deriving (Eq,Show,Read) + deriving (Eq, Show) data Rules = Everything | Proto Proto -- ^There is actually some order dependency between proto and port so this should be a specific -- data type with proto + ports - | Port Port - | PortRange (Port,Port) + | DPort Port + | DPortRange (Port,Port) | IFace Network.Interface | Ctstate [ ConnectionState ] | Rules :- Rules -- ^Combine two rules - deriving (Eq,Show,Read) + deriving (Eq, Show) infixl 0 :- diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 34e51ba9..9e5ca432 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -1,5 +1,3 @@ -{-# LANGUAGE TypeSynonymInstances #-} - module Propellor.Property.Systemd ( -- * Services module Propellor.Property.Systemd.Core, @@ -24,11 +22,11 @@ module Propellor.Property.Systemd ( -- * Container configuration containerCfg, resolvConfed, - Publishable(..), privateNetwork, ForwardedPort(..), Proto(..), PortSpec(..), + Publishable, publish, bind, bindRo, @@ -39,7 +37,6 @@ import Propellor.Types.Chroot import qualified Propellor.Property.Chroot as Chroot import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.File as File -import Propellor.Property.Firewall (Port) import Propellor.Property.Systemd.Core import Utility.FileMode @@ -297,7 +294,7 @@ class Publishable a where toPublish :: a -> String instance Publishable Port where - toPublish p = show p + toPublish (Port n) = show n data ForwardedPort = ForwardedPort { hostPort :: Port @@ -305,7 +302,7 @@ data ForwardedPort = ForwardedPort } instance Publishable ForwardedPort where - toPublish fp = show (hostPort fp) ++ ":" ++ show (containerPort fp) + toPublish fp = toPublish (hostPort fp) ++ ":" ++ toPublish (containerPort fp) data Proto = TCP | UDP diff --git a/src/Propellor/Types/OS.hs b/src/Propellor/Types/OS.hs index 58bd809a..c46d9a28 100644 --- a/src/Propellor/Types/OS.hs +++ b/src/Propellor/Types/OS.hs @@ -10,6 +10,7 @@ module Propellor.Types.OS ( User(..), Group(..), userGroup, + Port(..), ) where import Network.BSD (HostName) @@ -42,3 +43,6 @@ newtype Group = Group String -- | Makes a Group with the same name as the User. userGroup :: User -> Group userGroup (User u) = Group u + +newtype Port = Port Int + deriving (Eq, Show) -- cgit v1.2.3 From c0b9c708c93b104dfca1bff80e082e2d2b0ad0a6 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 16:22:15 -0400 Subject: don't mount /proc when provisioning systemd-nspawn container While needed for chroot provisioning, it confuses system when systemd-nspawn runs it inside the container. --- src/Propellor/Property/Chroot.hs | 23 ++++++++++++----------- src/Propellor/Property/Systemd.hs | 4 ++-- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'src/Propellor') diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs index 0e9d00d8..7e7d1611 100644 --- a/src/Propellor/Property/Chroot.hs +++ b/src/Propellor/Property/Chroot.hs @@ -95,7 +95,7 @@ chrootInfo (Chroot loc _ _ h) = mempty { _chrootinfo = mempty { _chroots = M.singleton loc h } } -- | Propellor is run inside the chroot to provision it. -propellChroot :: Chroot -> ([String] -> CreateProcess) -> Bool -> Property NoInfo +propellChroot :: Chroot -> ([String] -> IO CreateProcess) -> Bool -> Property NoInfo propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "provisioned") $ do let d = localdir shimdir c let me = localdir "propellor" @@ -103,7 +103,6 @@ propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c " ( pure (Shim.file me d) , Shim.setup me Nothing d ) - liftIO mountproc ifM (liftIO $ bindmount shim) ( chainprovision shim , return FailedChange @@ -119,18 +118,12 @@ propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c " , File localdir, File mntpnt ] ) - - -- /proc needs to be mounted in the chroot for the linker to use - -- /proc/self/exe which is necessary for some commands to work - mountproc = unlessM (elem procloc <$> mountPointsBelow loc) $ - void $ mount "proc" "proc" procloc - procloc = loc "proc" chainprovision shim = do parenthost <- asks hostName cmd <- liftIO $ toChain parenthost c systemdonly pe <- liftIO standardPathEnv - let p = mkproc + p <- liftIO $ mkproc [ shim , "--continue" , show cmd @@ -164,8 +157,16 @@ chain hostlist (ChrootChain hn loc systemdonly onconsole) = putStrLn $ "\n" ++ show r chain _ _ = errorMessage "bad chain command" -inChrootProcess :: Chroot -> [String] -> CreateProcess -inChrootProcess (Chroot loc _ _ _) cmd = proc "chroot" (loc:cmd) +inChrootProcess :: Chroot -> [String] -> IO CreateProcess +inChrootProcess (Chroot loc _ _ _) cmd = do + mountproc + return $ proc "chroot" (loc:cmd) + where + -- /proc needs to be mounted in the chroot for the linker to use + -- /proc/self/exe which is necessary for some commands to work + mountproc = unlessM (elem procloc <$> mountPointsBelow loc) $ + void $ mount "proc" "proc" procloc + procloc = loc "proc" provisioningLock :: FilePath -> FilePath provisioningLock containerloc = "chroot" mungeloc containerloc ++ ".lock" diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 9e5ca432..c2446b2e 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -250,8 +250,8 @@ enterScript c@(Container name _ _) = setup teardown enterScriptFile :: Container -> FilePath enterScriptFile (Container name _ _ ) = "/usr/local/bin/enter-" ++ mungename name -enterContainerProcess :: Container -> [String] -> CreateProcess -enterContainerProcess = proc . enterScriptFile +enterContainerProcess :: Container -> [String] -> IO CreateProcess +enterContainerProcess c ps = pure $ proc (enterScriptFile c) ps nspawnServiceName :: MachineName -> ServiceName nspawnServiceName name = "systemd-nspawn@" ++ name ++ ".service" -- cgit v1.2.3 From 06ebb4593acb0ae70e9413ee63df41eb250adb92 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 17:00:57 -0400 Subject: propellor spin --- debian/changelog | 2 +- src/Propellor/Property/Systemd.hs | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src/Propellor') diff --git a/debian/changelog b/debian/changelog index 599143d8..c262eadf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,7 +15,7 @@ propellor (2.5.0) UNRELEASED; urgency=medium * Mount /proc inside a chroot before provisioning it, to work around #787227 * --spin now works when given a short hostname that only resolves to an ipv6 address. - * Added publish and publish' properties for systemd-spawn containers. + * Added publish property for systemd-spawn containers, for port publishing. (Needs systemd version 220.) * Added bind and bindRo properties for systemd-spawn containers. * Firewall: Port was changed to a newtype, and the Port and PortRange diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index c2446b2e..ea8c994e 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -38,6 +38,7 @@ import qualified Propellor.Property.Chroot as Chroot import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.File as File import Propellor.Property.Systemd.Core +import Propellor.Property.Mount import Utility.FileMode import Data.List @@ -165,8 +166,19 @@ nspawned c@(Container name (Chroot.Chroot loc system builderconf _) h) = -- Chroot provisioning is run in systemd-only mode, -- which sets up the chroot and ensures systemd and dbus are -- installed, but does not handle the other provisions. - chrootprovisioned = Chroot.provisioned' - (Chroot.propigateChrootInfo chroot) chroot True + chrootprovisioned = + (toProp provisioner `onChange` umountProc) + + (toProp (revert provisioner)) + provisioner = Chroot.provisioned' (Chroot.propigateChrootInfo chroot) chroot True + + -- The chroot's /proc is left mounted by the chroot provisioning, + -- but that will prevent systemd-nspawn from starting systemd in + -- it, so unmount. + umountProc = check (elem procloc <$> mountPointsBelow loc) $ + property (procloc ++ " unmounted") $ do + makeChange $ umountLazy procloc + procloc = loc "proc" -- Use nsenter to enter container and and run propellor to -- finish provisioning. -- cgit v1.2.3 From b4503a782bfafd5b08c51f00e4c90539cae34009 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 17:44:37 -0400 Subject: explicitly speciy params for systemd-nspawn ExecStart It was using whatever was in /lib/systemd/system/systemd-nspawn@.service, but systemd 220 added --network-veth to that, which can break existing setups. So don't do that. --- src/Propellor/Property/Systemd.hs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/Propellor') diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index ea8c994e..87290fc0 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -202,8 +202,14 @@ nspawnService (Container name _ _) cfg = setup teardown return $ unlines $ "# deployed by propellor" : map addparams ls addparams l - | "ExecStart=" `isPrefixOf` l = - l ++ " " ++ unwords (nspawnServiceParams cfg) + | "ExecStart=" `isPrefixOf` l = unwords $ + [ "ExecStart = /usr/bin/systemd-nspawn" + , "--quiet" + , "--keep-unit" + , "--boot" + , "--link-journal=try-guest" + , "--directory=/var/lib/container/%i" + ] ++ nspawnServiceParams cfg | otherwise = l goodservicefile = (==) @@ -290,8 +296,6 @@ containerCfg p = RevertableProperty (mk True) (mk False) ('-':_) -> p _ -> "--" ++ p - - -- | Bind mounts from the host into the container. -- -- This property is enabled by default. Revert it to disable it. -- cgit v1.2.3 From 6d36de695ce187ed08b6fe8893c5e3cda1577d96 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 17:51:20 -0400 Subject: add linkJournal property so it can be reverted to disable --- src/Propellor/Property/Systemd.hs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/Propellor') diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 87290fc0..83cc1eaa 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -22,6 +22,7 @@ module Propellor.Property.Systemd ( -- * Container configuration containerCfg, resolvConfed, + linkJournal, privateNetwork, ForwardedPort(..), Proto(..), @@ -136,6 +137,7 @@ container :: MachineName -> (FilePath -> Chroot.Chroot) -> Container container name mkchroot = Container name c h & os system & resolvConfed + & linkJournal where c@(Chroot.Chroot _ system _ _) = mkchroot (containerDir name) h = Host name [] mempty @@ -207,7 +209,6 @@ nspawnService (Container name _ _) cfg = setup teardown , "--quiet" , "--keep-unit" , "--boot" - , "--link-journal=try-guest" , "--directory=/var/lib/container/%i" ] ++ nspawnServiceParams cfg | otherwise = l @@ -302,6 +303,13 @@ containerCfg p = RevertableProperty (mk True) (mk False) resolvConfed :: RevertableProperty resolvConfed = containerCfg "bind=/etc/resolv.conf" +-- | Link the container's journal to the host's if possible. +-- (Only works if the host has persistent journal enabled.) +-- +-- This property is enabled by default. Revert it to disable it. +linkJournal :: RevertableProperty +linkJournal = containerCfg "link-journal=try-guest" + -- | Disconnect networking of the container from the host. privateNetwork :: RevertableProperty privateNetwork = containerCfg "private-network" -- cgit v1.2.3 From ef1307652e502882cecdccdfc1773f4cf390ad17 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 18:14:47 -0400 Subject: another try at unmounting /proc for systemd-nspawn --- src/Propellor/Property/Chroot.hs | 24 ++++++++++++++++-------- src/Propellor/Property/Systemd.hs | 24 ++++++------------------ 2 files changed, 22 insertions(+), 26 deletions(-) (limited to 'src/Propellor') diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs index 7e7d1611..ded108bc 100644 --- a/src/Propellor/Property/Chroot.hs +++ b/src/Propellor/Property/Chroot.hs @@ -16,10 +16,10 @@ import Propellor import Propellor.Types.CmdLine import Propellor.Types.Chroot import Propellor.Property.Chroot.Util -import Propellor.Property.Mount import qualified Propellor.Property.Debootstrap as Debootstrap import qualified Propellor.Property.Systemd.Core as Systemd import qualified Propellor.Shim as Shim +import Propellor.Property.Mount import qualified Data.Map as M import Data.List.Utils @@ -70,7 +70,7 @@ provisioned' propigator c@(Chroot loc system builderconf _) systemdonly = where go desc a = propertyList (chrootDesc c desc) [a] - setup = propellChroot c (inChrootProcess c) systemdonly + setup = propellChroot c (inChrootProcess (not systemdonly) c) systemdonly `requires` toProp built built = case (system, builderconf) of @@ -95,7 +95,7 @@ chrootInfo (Chroot loc _ _ h) = mempty { _chrootinfo = mempty { _chroots = M.singleton loc h } } -- | Propellor is run inside the chroot to provision it. -propellChroot :: Chroot -> ([String] -> IO CreateProcess) -> Bool -> Property NoInfo +propellChroot :: Chroot -> ([String] -> IO (CreateProcess, IO ())) -> Bool -> Property NoInfo propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "provisioned") $ do let d = localdir shimdir c let me = localdir "propellor" @@ -123,14 +123,16 @@ propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c " parenthost <- asks hostName cmd <- liftIO $ toChain parenthost c systemdonly pe <- liftIO standardPathEnv - p <- liftIO $ mkproc + (p, cleanup) <- liftIO $ mkproc [ shim , "--continue" , show cmd ] let p' = p { env = Just pe } - liftIO $ withHandle StdoutHandle createProcessSuccess p' + r <- liftIO $ withHandle StdoutHandle createProcessSuccess p' processChainOutput + liftIO cleanup + return r toChain :: HostName -> Chroot -> Bool -> IO CmdLine toChain parenthost (Chroot loc _ _ _) systemdonly = do @@ -157,17 +159,23 @@ chain hostlist (ChrootChain hn loc systemdonly onconsole) = putStrLn $ "\n" ++ show r chain _ _ = errorMessage "bad chain command" -inChrootProcess :: Chroot -> [String] -> IO CreateProcess -inChrootProcess (Chroot loc _ _ _) cmd = do +inChrootProcess :: Bool -> Chroot -> [String] -> IO (CreateProcess, IO ()) +inChrootProcess keepprocmounted (Chroot loc _ _ _) cmd = do mountproc - return $ proc "chroot" (loc:cmd) + return (proc "chroot" (loc:cmd), cleanup) where -- /proc needs to be mounted in the chroot for the linker to use -- /proc/self/exe which is necessary for some commands to work mountproc = unlessM (elem procloc <$> mountPointsBelow loc) $ void $ mount "proc" "proc" procloc + procloc = loc "proc" + cleanup + | keepprocmounted = noop + | otherwise = whenM (elem procloc <$> mountPointsBelow loc) $ + umountLazy procloc + provisioningLock :: FilePath -> FilePath provisioningLock containerloc = "chroot" mungeloc containerloc ++ ".lock" diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 83cc1eaa..a46fe4f8 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -39,7 +39,6 @@ import qualified Propellor.Property.Chroot as Chroot import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.File as File import Propellor.Property.Systemd.Core -import Propellor.Property.Mount import Utility.FileMode import Data.List @@ -168,19 +167,7 @@ nspawned c@(Container name (Chroot.Chroot loc system builderconf _) h) = -- Chroot provisioning is run in systemd-only mode, -- which sets up the chroot and ensures systemd and dbus are -- installed, but does not handle the other provisions. - chrootprovisioned = - (toProp provisioner `onChange` umountProc) - - (toProp (revert provisioner)) - provisioner = Chroot.provisioned' (Chroot.propigateChrootInfo chroot) chroot True - - -- The chroot's /proc is left mounted by the chroot provisioning, - -- but that will prevent systemd-nspawn from starting systemd in - -- it, so unmount. - umountProc = check (elem procloc <$> mountPointsBelow loc) $ - property (procloc ++ " unmounted") $ do - makeChange $ umountLazy procloc - procloc = loc "proc" + chrootprovisioned = Chroot.provisioned' (Chroot.propigateChrootInfo chroot) chroot True -- Use nsenter to enter container and and run propellor to -- finish provisioning. @@ -269,8 +256,8 @@ enterScript c@(Container name _ _) = setup teardown enterScriptFile :: Container -> FilePath enterScriptFile (Container name _ _ ) = "/usr/local/bin/enter-" ++ mungename name -enterContainerProcess :: Container -> [String] -> IO CreateProcess -enterContainerProcess c ps = pure $ proc (enterScriptFile c) ps +enterContainerProcess :: Container -> [String] -> IO (CreateProcess, IO ()) +enterContainerProcess c ps = pure (proc (enterScriptFile c) ps, noop) nspawnServiceName :: MachineName -> ServiceName nspawnServiceName name = "systemd-nspawn@" ++ name ++ ".service" @@ -338,8 +325,9 @@ instance Publishable PortSpec where -- | Publish a port from the container on the host. -- --- Note that this will only work if the container's network is set up --- by other properties. +-- Note that this will only work if the container is set up to use +-- private networking. If the container does not use private networking, +-- this property is not needed. -- -- This feature was first added in systemd version 220. publish :: Publishable p => p -> RevertableProperty -- cgit v1.2.3 From 87a116d5db28322d52adcf99de5e3cbd7dc43110 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 18:33:49 -0400 Subject: use --machine needed by systemd 220 for machined to see the container as a machine --- src/Propellor/Property/Systemd.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Propellor') diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index a46fe4f8..0015276d 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -196,7 +196,7 @@ nspawnService (Container name _ _) cfg = setup teardown , "--quiet" , "--keep-unit" , "--boot" - , "--directory=/var/lib/container/%i" + , "--machine=%i" ] ++ nspawnServiceParams cfg | otherwise = l -- cgit v1.2.3 From 802f3c968df2ea623bf24102f21b22808f52d9ee Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 18:34:15 -0400 Subject: descs --- src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/Propellor') diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs index d64852aa..70075968 100644 --- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs +++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs @@ -109,7 +109,7 @@ autoBuilderContainer mkprop osver@(System _ arch) crontime timeout = standardAutoBuilder :: System -> Property HasInfo standardAutoBuilder osver@(System _ arch) = - propertyList "git-annex-builder" $ props + propertyList "standard git-annex autobuilder" $ props & os osver & Apt.stdSourcesList & Apt.unattendedUpgrades @@ -118,7 +118,7 @@ standardAutoBuilder osver@(System _ arch) = armAutoBuilder :: System -> Times -> TimeOut -> Property HasInfo armAutoBuilder osver@(System _ arch) crontime timeout = - propertyList "git-annex-builder (arm)" $ props + propertyList "arm git-annex autobuilder" $ props & standardAutoBuilder osver & buildDepsNoHaskellLibs -- Works around ghc crash with parallel builds on arm. -- cgit v1.2.3 From 6241a16772649d3b918085ec4f113665fcf53459 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 22:07:05 -0400 Subject: propellor spin --- src/Propellor/Property/Systemd.hs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/Propellor') diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 0015276d..055c02ed 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -196,6 +196,7 @@ nspawnService (Container name _ _) cfg = setup teardown , "--quiet" , "--keep-unit" , "--boot" + , "--directory=" ++ containerDir name , "--machine=%i" ] ++ nspawnServiceParams cfg | otherwise = l -- cgit v1.2.3 From 765367dab9b61a512e07268c921f950677af4f27 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 23:16:25 -0400 Subject: add Bound --- propellor.cabal | 1 + src/Propellor/Property/Systemd.hs | 44 ++++++++++++++++++++------------------- src/Propellor/Types/Container.hs | 30 ++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 21 deletions(-) create mode 100644 src/Propellor/Types/Container.hs (limited to 'src/Propellor') diff --git a/propellor.cabal b/propellor.cabal index 16dffe31..9edc1436 100644 --- a/propellor.cabal +++ b/propellor.cabal @@ -121,6 +121,7 @@ Library Propellor.Exception Propellor.Types Propellor.Types.Chroot + Propellor.Types.Container Propellor.Types.Docker Propellor.Types.Dns Propellor.Types.Empty diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 055c02ed..1d03d557 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE FlexibleInstances #-} + module Propellor.Property.Systemd ( -- * Services module Propellor.Property.Systemd.Core, @@ -24,17 +26,18 @@ module Propellor.Property.Systemd ( resolvConfed, linkJournal, privateNetwork, - ForwardedPort(..), + module Propellor.Types.Container, Proto(..), - PortSpec(..), Publishable, publish, + Bindable, bind, bindRo, ) where import Propellor import Propellor.Types.Chroot +import Propellor.Types.Container import qualified Propellor.Property.Chroot as Chroot import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.File as File @@ -308,21 +311,14 @@ class Publishable a where instance Publishable Port where toPublish (Port n) = show n -data ForwardedPort = ForwardedPort - { hostPort :: Port - , containerPort :: Port - } - -instance Publishable ForwardedPort where - toPublish fp = toPublish (hostPort fp) ++ ":" ++ toPublish (containerPort fp) +instance Publishable (Bound Port) where + toPublish v = toPublish (hostSide v) ++ ":" ++ toPublish (containerSide v) data Proto = TCP | UDP -data PortSpec = PortSpec Proto ForwardedPort - -instance Publishable PortSpec where - toPublish (PortSpec TCP fp) = "tcp:" ++ toPublish fp - toPublish (PortSpec UDP fp) = "udp:" ++ toPublish fp +instance Publishable (Proto, Bound Port) where + toPublish (TCP, fp) = "tcp:" ++ toPublish fp + toPublish (UDP, fp) = "udp:" ++ toPublish fp -- | Publish a port from the container on the host. -- @@ -334,13 +330,19 @@ instance Publishable PortSpec where publish :: Publishable p => p -> RevertableProperty publish p = containerCfg $ "--port=" ++ toPublish p +class Bindable a where + toBind :: a -> String + +instance Bindable FilePath where + toBind f = f + +instance Bindable (Bound FilePath) where + toBind v = hostSide v ++ ":" ++ containerSide v + -- | Bind mount a file or directory from the host into the container. --- --- The parameter can be a FilePath, or a colon-separated pair of --- hostpath:containerpath. -bind :: FilePath -> RevertableProperty -bind f = containerCfg $ "--bind=" ++ f +bind :: Bindable p => p -> RevertableProperty +bind p = containerCfg $ "--bind=" ++ toBind p -- | Read-only mind mount. -bindRo :: FilePath -> RevertableProperty -bindRo f = containerCfg $ "--bind-ro=" ++ f +bindRo :: Bindable p => p -> RevertableProperty +bindRo p = containerCfg $ "--bind-ro=" ++ toBind p diff --git a/src/Propellor/Types/Container.hs b/src/Propellor/Types/Container.hs new file mode 100644 index 00000000..d21bada7 --- /dev/null +++ b/src/Propellor/Types/Container.hs @@ -0,0 +1,30 @@ +{-# LANGUAGE TypeFamilies #-} + +module Propellor.Types.Container where + +-- | A value that can be bound between the host and a container. +-- +-- For example, a Bound Port is a Port on the container that is bound to +-- a Port on the host. +data Bound v = Bound + { hostSide :: v + , containerSide :: v + } + +-- | Create a Bound value, from two different values for the host and +-- container. +-- +-- For example, @Port 8080 -<- Port 80@ means that port 8080 on the host +-- is bound to port 80 from the container. +(-<-) :: (hostv ~ v, containerv ~ v) => hostv -> containerv -> Bound v +(-<-) hostv containerv = Bound hostv containerv + +-- | Flipped version of -<- with the container value first and host value +-- second. +(->-) :: (containerv ~ v, hostv ~ v) => hostv -> containerv -> Bound v +(->-) containerv hostv = Bound hostv containerv + +-- | Create a Bound value, that is the same on both the host and container. +same :: v -> Bound v +same v = Bound v v + -- cgit v1.2.3 From c9dc306016d22bba092412d90e1375254caffe7b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 23:41:07 -0400 Subject: more systemd improvements --- src/Propellor/Property/Systemd.hs | 54 +++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 11 deletions(-) (limited to 'src/Propellor') diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 1d03d557..e50ef9cd 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -2,14 +2,17 @@ module Propellor.Property.Systemd ( -- * Services - module Propellor.Property.Systemd.Core, ServiceName, started, stopped, enabled, disabled, + running, restarted, + networkd, + journald, -- * Configuration + installed, Option, configured, daemonReloaded, @@ -61,6 +64,9 @@ instance PropAccum Container where getProperties (Container _ _ h) = hostProperties h -- | Starts a systemd service. +-- +-- Note that this does not configure systemd to start the service on boot, +-- it only ensures that the service is currently running. started :: ServiceName -> Property NoInfo started n = trivial $ cmdProperty "systemctl" ["start", n] `describe` ("service " ++ n ++ " started") @@ -71,6 +77,9 @@ stopped n = trivial $ cmdProperty "systemctl" ["stop", n] `describe` ("service " ++ n ++ " stopped") -- | Enables a systemd service. +-- +-- This does not ensure the service is started, it only configures systemd +-- to start it on boot. enabled :: ServiceName -> Property NoInfo enabled n = trivial $ cmdProperty "systemctl" ["enable", n] `describe` ("service " ++ n ++ " enabled") @@ -80,11 +89,23 @@ disabled :: ServiceName -> Property NoInfo disabled n = trivial $ cmdProperty "systemctl" ["disable", n] `describe` ("service " ++ n ++ " disabled") +-- | Ensures that a service is both enabled and started +running :: ServiceName -> Property NoInfo +running n = trivial $ started n `requires` enabled n + -- | Restarts a systemd service. restarted :: ServiceName -> Property NoInfo restarted n = trivial $ cmdProperty "systemctl" ["restart", n] `describe` ("service " ++ n ++ " restarted") +-- | The systemd-networkd service. +networkd :: ServiceName +networkd = "systemd-networkd" + +-- | The systemd-journald service. +journald :: ServiceName +journald = "systemd-journald" + -- | Enables persistent storage of the journal. persistentJournal :: Property NoInfo persistentJournal = check (not <$> doesDirectoryExist dir) $ @@ -118,15 +139,15 @@ configured cfgfile option value = combineProperties desc | setting `isPrefixOf` l = Nothing | otherwise = Just l +-- | Causes systemd to reload its configuration files. +daemonReloaded :: Property NoInfo +daemonReloaded = trivial $ cmdProperty "systemctl" ["daemon-reload"] + -- | Configures journald, restarting it so the changes take effect. journaldConfigured :: Option -> String -> Property NoInfo journaldConfigured option value = configured "/etc/systemd/journald.conf" option value - `onChange` restarted "systemd-journald" - --- | Causes systemd to reload its configuration files. -daemonReloaded :: Property NoInfo -daemonReloaded = trivial $ cmdProperty "systemctl" ["daemon-reload"] + `onChange` restarted journald -- | Defines a container with a given machine name. -- @@ -320,13 +341,24 @@ instance Publishable (Proto, Bound Port) where toPublish (TCP, fp) = "tcp:" ++ toPublish fp toPublish (UDP, fp) = "udp:" ++ toPublish fp --- | Publish a port from the container on the host. +-- | Publish a port from the container to the host. +-- +-- This feature was first added in systemd version 220. -- --- Note that this will only work if the container is set up to use --- private networking. If the container does not use private networking, --- this property is not needed. +-- This property is only needed (and will only work) if the container +-- is configured private networking. Also, networkd should be enabled +-- both inside the container, and on the host. For example: -- --- This feature was first added in systemd version 220. +-- > foo :: Host +-- > foo = host "foo.example.com" +-- > & Systemd.running Systemd.networkd +-- > & Systemd.nspawned webserver +-- > +-- > webserver :: Systemd.container +-- > webserver = Systemd.container "webserver" (Chroot.debootstrapped (System (Debian Testing) "amd64") mempty) +-- > & Systemd.running Systemd.networkd +-- > & Systemd.publish (Port 80 ->- Port 8080) +-- > & Apt.installedRunning "apache2" publish :: Publishable p => p -> RevertableProperty publish p = containerCfg $ "--port=" ++ toPublish p -- cgit v1.2.3 From e11c68cf1e515746e3bd0256a949e182ae735f99 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 1 Jun 2015 23:57:33 -0400 Subject: Docker: volume and publish accept Bound FilePath and Bound Port, respectively. They also continue to accept Strings, for backwards compatability. --- debian/changelog | 3 +++ src/Propellor/Property/Docker.hs | 36 +++++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 7 deletions(-) (limited to 'src/Propellor') diff --git a/debian/changelog b/debian/changelog index c262eadf..f4459a2c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -21,6 +21,9 @@ propellor (2.5.0) UNRELEASED; urgency=medium * Firewall: Port was changed to a newtype, and the Port and PortRange constructors of Rules were changed to DPort and DportRange, respectively. (API change) + * Docker: volume and publish accept Bound FilePath and Bound Port, + respectively. They also continue to accept Strings, for backwards + compatability. -- Joey Hess Thu, 07 May 2015 12:08:34 -0400 diff --git a/src/Propellor/Property/Docker.hs b/src/Propellor/Property/Docker.hs index fd7e37b2..1dcc3522 100644 --- a/src/Propellor/Property/Docker.hs +++ b/src/Propellor/Property/Docker.hs @@ -23,9 +23,11 @@ module Propellor.Property.Docker ( -- * Container configuration dns, hostname, + Publishable, publish, expose, user, + Mountable, volume, volumes_from, workdir, @@ -43,6 +45,7 @@ module Propellor.Property.Docker ( import Propellor hiding (init) import Propellor.Types.Docker +import Propellor.Types.Container import Propellor.Types.CmdLine import qualified Propellor.Property.File as File import qualified Propellor.Property.Apt as Apt @@ -254,10 +257,19 @@ hostname = runProp "hostname" name :: String -> Property HasInfo name = runProp "name" +class Publishable p where + toPublish :: p -> String + +instance Publishable (Bound Port) where + toPublish p = show (hostSide p) ++ ":" ++ show (containerSide p) + +-- | string format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort +instance Publishable String where + toPublish = id + -- | Publish a container's port to the host --- (format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort) -publish :: String -> Property HasInfo -publish = runProp "publish" +publish :: Publishable p => p -> Property HasInfo +publish = runProp "publish" . toPublish -- | Expose a container's port without publishing it. expose :: String -> Property HasInfo @@ -267,11 +279,21 @@ expose = runProp "expose" user :: String -> Property HasInfo user = runProp "user" --- | Mount a volume --- Create a bind mount with: [host-dir]:[container-dir]:[rw|ro] +class Mountable p where + toMount :: p -> String + +instance Mountable (Bound FilePath) where + toMount p = hostSide p ++ ":" ++ containerSide p + +-- | string format: [host-dir]:[container-dir]:[rw|ro] +-- -- With just a directory, creates a volume in the container. -volume :: String -> Property HasInfo -volume = runProp "volume" +instance Mountable String where + toMount = id + +-- | Mount a volume +volume :: Mountable v => v -> Property HasInfo +volume = runProp "volume" . toMount -- | Mount a volume from the specified container into the current -- container. -- cgit v1.2.3 From af450d89c8c78c544ad0329501a5bbc535079a18 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 2 Jun 2015 00:14:08 -0400 Subject: fix example --- src/Propellor/Property/Systemd.hs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/Propellor') diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index e50ef9cd..fa40868b 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -356,6 +356,7 @@ instance Publishable (Proto, Bound Port) where -- > -- > webserver :: Systemd.container -- > webserver = Systemd.container "webserver" (Chroot.debootstrapped (System (Debian Testing) "amd64") mempty) +-- > & Systemd.privateNetwork -- > & Systemd.running Systemd.networkd -- > & Systemd.publish (Port 80 ->- Port 8080) -- > & Apt.installedRunning "apache2" -- cgit v1.2.3 From fd9d172bcd9f217b67a60ed2e694bad4f6602d32 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 2 Jun 2015 00:37:17 -0400 Subject: wording --- src/Propellor/Property/Systemd.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Propellor') diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index fa40868b..17849980 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -346,7 +346,7 @@ instance Publishable (Proto, Bound Port) where -- This feature was first added in systemd version 220. -- -- This property is only needed (and will only work) if the container --- is configured private networking. Also, networkd should be enabled +-- is configured to use private networking. Also, networkd should be enabled -- both inside the container, and on the host. For example: -- -- > foo :: Host -- cgit v1.2.3