propellor spin
This commit is contained in:
parent
4d155864fa
commit
a4f04fcb02
|
@ -121,7 +121,7 @@ Library
|
||||||
Propellor.Ssh
|
Propellor.Ssh
|
||||||
Propellor.PrivData.Paths
|
Propellor.PrivData.Paths
|
||||||
Propellor.Protocol
|
Propellor.Protocol
|
||||||
Propellor.Property.Docker.Shim
|
Propellor.Shim
|
||||||
Utility.Applicative
|
Utility.Applicative
|
||||||
Utility.Data
|
Utility.Data
|
||||||
Utility.Directory
|
Utility.Directory
|
||||||
|
|
|
@ -15,7 +15,8 @@ import Propellor.Git
|
||||||
import Propellor.Ssh
|
import Propellor.Ssh
|
||||||
import Propellor.Server
|
import Propellor.Server
|
||||||
import qualified Propellor.Property.Docker as Docker
|
import qualified Propellor.Property.Docker as Docker
|
||||||
import qualified Propellor.Property.Docker.Shim as DockerShim
|
import qualified Propellor.Property.Chroot as Chroot
|
||||||
|
import qualified Propellor.Shim as Shim
|
||||||
import Utility.SafeCommand
|
import Utility.SafeCommand
|
||||||
|
|
||||||
usage :: Handle -> IO ()
|
usage :: Handle -> IO ()
|
||||||
|
@ -72,7 +73,7 @@ processCmdLine = go =<< getArgs
|
||||||
-- | Runs propellor on hosts, as controlled by command-line options.
|
-- | Runs propellor on hosts, as controlled by command-line options.
|
||||||
defaultMain :: [Host] -> IO ()
|
defaultMain :: [Host] -> IO ()
|
||||||
defaultMain hostlist = do
|
defaultMain hostlist = do
|
||||||
DockerShim.cleanEnv
|
Shim.cleanEnv
|
||||||
checkDebugMode
|
checkDebugMode
|
||||||
cmdline <- processCmdLine
|
cmdline <- processCmdLine
|
||||||
debug ["command line: ", show cmdline]
|
debug ["command line: ", show cmdline]
|
||||||
|
@ -85,6 +86,7 @@ defaultMain hostlist = do
|
||||||
go _ ListFields = listPrivDataFields hostlist
|
go _ ListFields = listPrivDataFields hostlist
|
||||||
go _ (AddKey keyid) = addKey keyid
|
go _ (AddKey keyid) = addKey keyid
|
||||||
go _ (DockerChain hn cid) = Docker.chain hostlist hn cid
|
go _ (DockerChain hn cid) = Docker.chain hostlist hn cid
|
||||||
|
go _ (ChrootChain hn loc) = Chroot.chain hostlist hn loc
|
||||||
go _ (DockerInit hn) = Docker.init hn
|
go _ (DockerInit hn) = Docker.init hn
|
||||||
go _ (GitPush fin fout) = gitPushHelper fin fout
|
go _ (GitPush fin fout) = gitPushHelper fin fout
|
||||||
go _ (Update _) = forceConsole >> fetchFirst (onlyprocess update)
|
go _ (Update _) = forceConsole >> fetchFirst (onlyprocess update)
|
||||||
|
|
|
@ -11,12 +11,15 @@ import "mtl" Control.Monad.Reader
|
||||||
import Control.Exception (bracket)
|
import Control.Exception (bracket)
|
||||||
import System.PosixCompat
|
import System.PosixCompat
|
||||||
import System.Posix.IO
|
import System.Posix.IO
|
||||||
|
import Data.Maybe
|
||||||
|
|
||||||
import Propellor.Types
|
import Propellor.Types
|
||||||
import Propellor.Message
|
import Propellor.Message
|
||||||
import Propellor.Exception
|
import Propellor.Exception
|
||||||
import Propellor.Info
|
import Propellor.Info
|
||||||
import Utility.Exception
|
import Utility.Exception
|
||||||
|
import Utility.PartialPrelude
|
||||||
|
import Utility.Monad
|
||||||
|
|
||||||
runPropellor :: Host -> Propellor a -> IO a
|
runPropellor :: Host -> Propellor a -> IO a
|
||||||
runPropellor host a = runReaderT (runWithHost a) host
|
runPropellor host a = runReaderT (runWithHost a) host
|
||||||
|
@ -62,3 +65,18 @@ onlyProcess lockfile a = bracket lock unlock (const a)
|
||||||
return l
|
return l
|
||||||
unlock = closeFd
|
unlock = closeFd
|
||||||
alreadyrunning = error "Propellor is already running on this host!"
|
alreadyrunning = error "Propellor is already running on this host!"
|
||||||
|
|
||||||
|
-- | Reads and displays each line from the Handle, except for the last line
|
||||||
|
-- which is a Result.
|
||||||
|
processChainOutput :: Handle -> IO Result
|
||||||
|
processChainOutput h = go Nothing
|
||||||
|
where
|
||||||
|
go lastline = do
|
||||||
|
v <- catchMaybeIO (hGetLine h)
|
||||||
|
case v of
|
||||||
|
Nothing -> pure $ fromMaybe FailedChange $
|
||||||
|
readish =<< lastline
|
||||||
|
Just s -> do
|
||||||
|
maybe noop putStrLn lastline
|
||||||
|
hFlush stdout
|
||||||
|
go (Just s)
|
||||||
|
|
|
@ -2,12 +2,17 @@ module Propellor.Property.Chroot (
|
||||||
Chroot,
|
Chroot,
|
||||||
chroot,
|
chroot,
|
||||||
provisioned,
|
provisioned,
|
||||||
|
chain,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Propellor
|
import Propellor
|
||||||
import qualified Propellor.Property.Debootstrap as Debootstrap
|
import qualified Propellor.Property.Debootstrap as Debootstrap
|
||||||
|
import qualified Propellor.Shim as Shim
|
||||||
|
import Utility.SafeCommand
|
||||||
|
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
|
import Data.List.Utils
|
||||||
|
import System.Posix.Directory
|
||||||
|
|
||||||
data Chroot = Chroot FilePath System Host
|
data Chroot = Chroot FilePath System Host
|
||||||
|
|
||||||
|
@ -35,8 +40,7 @@ provisioned c@(Chroot loc system _) = RevertableProperty
|
||||||
(propigateChrootInfo c (go "exists" setup))
|
(propigateChrootInfo c (go "exists" setup))
|
||||||
(go "removed" teardown)
|
(go "removed" teardown)
|
||||||
where
|
where
|
||||||
go desc a = property ("chroot " ++ loc ++ " " ++ desc) $ do
|
go desc a = property (chrootDesc c desc) $ ensureProperties [a]
|
||||||
ensureProperties [a]
|
|
||||||
|
|
||||||
setup = provisionChroot c `requires` built
|
setup = provisionChroot c `requires` built
|
||||||
|
|
||||||
|
@ -53,5 +57,71 @@ propigateChrootInfo c@(Chroot loc _ h) p = propigateInfo c p (<> chrootinfo)
|
||||||
where
|
where
|
||||||
chrootinfo = mempty $ mempty { _chroots = M.singleton loc h }
|
chrootinfo = mempty $ mempty { _chroots = M.singleton loc h }
|
||||||
|
|
||||||
|
-- | Propellor is run inside the chroot to provision it.
|
||||||
|
--
|
||||||
|
-- Strange and wonderful tricks let the host's /usr/local/propellor
|
||||||
|
-- be used inside the chroot, without needing to install anything.
|
||||||
provisionChroot :: Chroot -> Property
|
provisionChroot :: Chroot -> Property
|
||||||
provisionChroot = undefined
|
provisionChroot c@(Chroot loc _ _) = property (chrootDesc c "provisioned") $ do
|
||||||
|
let d = localdir </> shimdir c
|
||||||
|
let me = localdir </> "propellor"
|
||||||
|
shim <- liftIO $ ifM (doesDirectoryExist d)
|
||||||
|
( pure (Shim.file me d)
|
||||||
|
, Shim.setup me d
|
||||||
|
)
|
||||||
|
ifM (liftIO $ bindmount shim)
|
||||||
|
( chainprovision shim
|
||||||
|
, return FailedChange
|
||||||
|
)
|
||||||
|
where
|
||||||
|
bindmount shim = ifM (doesFileExist (loc ++ shim))
|
||||||
|
( return True
|
||||||
|
, do
|
||||||
|
let mntpnt = loc ++ localdir
|
||||||
|
createDirectoryIfMissing True mntpnt
|
||||||
|
boolSystem "mount"
|
||||||
|
[ Param "--bind"
|
||||||
|
, File localdir, File mntpnt
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
chainprovision shim = do
|
||||||
|
parenthost <- asks hostName
|
||||||
|
let p = inChrootProcess c
|
||||||
|
[ shim
|
||||||
|
, "--continue"
|
||||||
|
, show $ toChain parenthost c
|
||||||
|
]
|
||||||
|
liftIO $ withHandle StdoutHandle createProcessSuccess p
|
||||||
|
processChainOutput
|
||||||
|
|
||||||
|
toChain :: HostName -> Chroot -> CmdLine
|
||||||
|
toChain parenthost (Chroot loc _ _) = ChrootChain parenthost loc
|
||||||
|
|
||||||
|
chain :: [Host] -> HostName -> FilePath -> IO ()
|
||||||
|
chain hostlist hn loc = case findHostNoAlias hostlist hn of
|
||||||
|
Nothing -> errorMessage ("cannot find host " ++ hn)
|
||||||
|
Just parenthost -> case M.lookup loc (_chroots $ _chrootinfo $ hostInfo parenthost) of
|
||||||
|
Nothing -> errorMessage ("cannot find chroot " ++ loc ++ " on host " ++ hn)
|
||||||
|
Just h -> go h
|
||||||
|
where
|
||||||
|
go h = do
|
||||||
|
changeWorkingDirectory localdir
|
||||||
|
onlyProcess (provisioningLock loc) $ do
|
||||||
|
r <- runPropellor h $ ensureProperties $ hostProperties h
|
||||||
|
putStrLn $ "\n" ++ show r
|
||||||
|
|
||||||
|
inChrootProcess :: Chroot -> [String] -> CreateProcess
|
||||||
|
inChrootProcess (Chroot loc _ _) cmd = proc "chroot" (loc:cmd)
|
||||||
|
|
||||||
|
provisioningLock :: FilePath -> FilePath
|
||||||
|
provisioningLock containerloc = "chroot" </> mungeloc containerloc ++ ".lock"
|
||||||
|
|
||||||
|
shimdir :: Chroot -> FilePath
|
||||||
|
shimdir (Chroot loc _ _) = "chroot" </> mungeloc loc ++ ".shim"
|
||||||
|
|
||||||
|
mungeloc :: FilePath -> String
|
||||||
|
mungeloc = replace "/" "_"
|
||||||
|
|
||||||
|
chrootDesc :: Chroot -> String -> String
|
||||||
|
chrootDesc (Chroot loc _ _) desc = "chroot " ++ loc ++ " " ++ desc
|
||||||
|
|
|
@ -41,7 +41,7 @@ module Propellor.Property.Docker (
|
||||||
import Propellor hiding (init)
|
import Propellor hiding (init)
|
||||||
import qualified Propellor.Property.File as File
|
import qualified Propellor.Property.File as File
|
||||||
import qualified Propellor.Property.Apt as Apt
|
import qualified Propellor.Property.Apt as Apt
|
||||||
import qualified Propellor.Property.Docker.Shim as Shim
|
import qualified Propellor.Shim as Shim
|
||||||
import Utility.SafeCommand
|
import Utility.SafeCommand
|
||||||
import Utility.Path
|
import Utility.Path
|
||||||
import Utility.ThreadScheduler
|
import Utility.ThreadScheduler
|
||||||
|
@ -432,20 +432,10 @@ provisionContainer cid = containerDesc cid $ property "provisioned" $ liftIO $ d
|
||||||
[ if isConsole msgh then "-it" else "-i" ]
|
[ if isConsole msgh then "-it" else "-i" ]
|
||||||
(shim : params)
|
(shim : params)
|
||||||
r <- withHandle StdoutHandle createProcessSuccess p $
|
r <- withHandle StdoutHandle createProcessSuccess p $
|
||||||
processoutput Nothing
|
processChainOutput
|
||||||
when (r /= FailedChange) $
|
when (r /= FailedChange) $
|
||||||
setProvisionedFlag cid
|
setProvisionedFlag cid
|
||||||
return r
|
return r
|
||||||
where
|
|
||||||
processoutput lastline h = do
|
|
||||||
v <- catchMaybeIO (hGetLine h)
|
|
||||||
case v of
|
|
||||||
Nothing -> pure $ fromMaybe FailedChange $
|
|
||||||
readish =<< lastline
|
|
||||||
Just s -> do
|
|
||||||
maybe noop putStrLn lastline
|
|
||||||
hFlush stdout
|
|
||||||
processoutput (Just s) h
|
|
||||||
|
|
||||||
toChain :: ContainerId -> CmdLine
|
toChain :: ContainerId -> CmdLine
|
||||||
toChain cid = DockerChain (containerHostName cid) (fromContainerId cid)
|
toChain cid = DockerChain (containerHostName cid) (fromContainerId cid)
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
-- | Support for running propellor, as built outside a docker container,
|
-- | Support for running propellor, as built outside a container,
|
||||||
-- inside the container.
|
-- inside the container, without needing to install anything into the
|
||||||
|
-- container.
|
||||||
--
|
--
|
||||||
-- Note: This is currently Debian specific, due to glibcLibs.
|
-- Note: This is currently Debian specific, due to glibcLibs.
|
||||||
|
|
||||||
module Propellor.Property.Docker.Shim (setup, cleanEnv, file) where
|
module Propellor.Shim (setup, cleanEnv, file) where
|
||||||
|
|
||||||
import Propellor
|
import Propellor
|
||||||
import Utility.LinuxMkLibs
|
import Utility.LinuxMkLibs
|
|
@ -155,6 +155,7 @@ data CmdLine
|
||||||
| Update HostName
|
| Update HostName
|
||||||
| DockerInit HostName
|
| DockerInit HostName
|
||||||
| DockerChain HostName String
|
| DockerChain HostName String
|
||||||
|
| ChrootChain HostName FilePath
|
||||||
| GitPush Fd Fd
|
| GitPush Fd Fd
|
||||||
deriving (Read, Show, Eq)
|
deriving (Read, Show, Eq)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue