propellor/src/Propellor/Engine.hs

93 lines
2.5 KiB
Haskell
Raw Normal View History

{-# LANGUAGE PackageImports #-}
2014-03-31 05:06:44 +00:00
module Propellor.Engine where
import System.Exit
import System.IO
2014-03-31 14:36:45 +00:00
import Data.Monoid
import Control.Applicative
2014-03-31 22:31:08 +00:00
import System.Console.ANSI
import "mtl" Control.Monad.Reader
import Control.Exception (bracket)
import System.PosixCompat
import System.Posix.IO
2014-11-23 02:24:09 +00:00
import System.FilePath
import System.Directory
2014-03-31 05:06:44 +00:00
import Propellor.Types
2014-03-31 22:31:08 +00:00
import Propellor.Message
import Propellor.Exception
2014-06-09 05:45:58 +00:00
import Propellor.Info
import Utility.Exception
2014-11-20 19:15:28 +00:00
import Utility.PartialPrelude
import Utility.Monad
2014-03-31 05:06:44 +00:00
runPropellor :: Host -> Propellor a -> IO a
runPropellor host a = runReaderT (runWithHost a) host
2014-03-31 05:06:44 +00:00
mainProperties :: Host -> IO ()
mainProperties host = do
r <- runPropellor host $
ensureProperties [Property "overall" (ensureProperties $ hostProperties host) mempty]
h <- mkMessageHandle
whenConsole h $
setTitle "propellor: done"
2014-03-31 05:19:40 +00:00
hFlush stdout
2014-03-31 05:06:44 +00:00
case r of
FailedChange -> exitWith (ExitFailure 1)
_ -> exitWith ExitSuccess
ensureProperties :: [Property] -> Propellor Result
ensureProperties ps = ensure ps NoChange
2014-03-31 05:06:44 +00:00
where
ensure [] rs = return rs
ensure (l:ls) rs = do
2014-06-01 00:48:23 +00:00
hn <- asks hostName
2014-05-31 22:52:42 +00:00
r <- actionMessageOn hn (propertyDesc l) (ensureProperty l)
2014-03-31 14:36:45 +00:00
ensure ls (r <> rs)
ensureProperty :: Property -> Propellor Result
ensureProperty = catchPropellor . propertySatisfy
-- | Lifts an action into a different host.
--
-- For example, `fromHost hosts "otherhost" getSshPubKey`
fromHost :: [Host] -> HostName -> Propellor a -> Propellor (Maybe a)
fromHost l hn getter = case findHost l hn of
2014-07-23 16:27:38 +00:00
Nothing -> return Nothing
2014-07-23 16:33:44 +00:00
Just h -> liftIO $ Just <$>
runReaderT (runWithHost getter) h
onlyProcess :: FilePath -> IO a -> IO a
onlyProcess lockfile a = bracket lock unlock (const a)
where
lock = do
2014-11-23 02:24:09 +00:00
createDirectoryIfMissing True (takeDirectory lockfile)
l <- createFile lockfile stdFileMode
setLock l (WriteLock, AbsoluteSeek, 0, 0)
`catchIO` const alreadyrunning
return l
unlock = closeFd
alreadyrunning = error "Propellor is already running on this host!"
2014-11-20 19:15:28 +00:00
-- | 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 -> case lastline of
Nothing -> pure FailedChange
Just l -> case readish l of
Just r -> pure r
Nothing -> do
putStrLn l
hFlush stdout
return FailedChange
2014-11-20 19:15:28 +00:00
Just s -> do
2014-11-20 20:07:57 +00:00
maybe noop (\l -> unless (null l) (putStrLn l)) lastline
2014-11-20 19:15:28 +00:00
hFlush stdout
go (Just s)