propellor spin
This commit is contained in:
parent
549df2612c
commit
c246a8ee74
|
@ -31,6 +31,7 @@ module Propellor (
|
||||||
, module Propellor.Property.Cmd
|
, module Propellor.Property.Cmd
|
||||||
, module Propellor.PrivData
|
, module Propellor.PrivData
|
||||||
, module Propellor.Engine
|
, module Propellor.Engine
|
||||||
|
, module Propellor.Message
|
||||||
|
|
||||||
, module X
|
, module X
|
||||||
) where
|
) where
|
||||||
|
@ -40,6 +41,7 @@ import Propellor.Property
|
||||||
import Propellor.Engine
|
import Propellor.Engine
|
||||||
import Propellor.Property.Cmd
|
import Propellor.Property.Cmd
|
||||||
import Propellor.PrivData
|
import Propellor.PrivData
|
||||||
|
import Propellor.Message
|
||||||
|
|
||||||
import Utility.PartialPrelude as X
|
import Utility.PartialPrelude as X
|
||||||
import Utility.Process as X
|
import Utility.Process as X
|
||||||
|
|
|
@ -38,15 +38,15 @@ processCmdLine = go =<< getArgs
|
||||||
go ("--add-key":k:[]) = return $ AddKey k
|
go ("--add-key":k:[]) = return $ AddKey k
|
||||||
go ("--set":h:f:[]) = case readish f of
|
go ("--set":h:f:[]) = case readish f of
|
||||||
Just pf -> return $ Set h pf
|
Just pf -> return $ Set h pf
|
||||||
Nothing -> error $ "Unknown privdata field " ++ f
|
Nothing -> errorMessage $ "Unknown privdata field " ++ f
|
||||||
go ("--continue":s:[]) =case readish s of
|
go ("--continue":s:[]) =case readish s of
|
||||||
Just cmdline -> return $ Continue cmdline
|
Just cmdline -> return $ Continue cmdline
|
||||||
Nothing -> error "--continue serialization failure"
|
Nothing -> errorMessage "--continue serialization failure"
|
||||||
go (h:[]) = return $ Run h
|
go (h:[]) = return $ Run h
|
||||||
go [] = do
|
go [] = do
|
||||||
s <- takeWhile (/= '\n') <$> readProcess "hostname" ["-f"]
|
s <- takeWhile (/= '\n') <$> readProcess "hostname" ["-f"]
|
||||||
if null s
|
if null s
|
||||||
then error "Cannot determine hostname! Pass it on the command line."
|
then errorMessage "Cannot determine hostname! Pass it on the command line."
|
||||||
else return $ Run s
|
else return $ Run s
|
||||||
go _ = usage
|
go _ = usage
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ defaultMain getprops = go True =<< processCmdLine
|
||||||
withprops host a = maybe (unknownhost host) a (getprops host)
|
withprops host a = maybe (unknownhost host) a (getprops host)
|
||||||
|
|
||||||
unknownhost :: HostName -> IO a
|
unknownhost :: HostName -> IO a
|
||||||
unknownhost h = error $ unwords
|
unknownhost h = errorMessage $ unwords
|
||||||
[ "Unknown host:", h
|
[ "Unknown host:", h
|
||||||
, "(perhaps you should specify the real hostname on the command line?)"
|
, "(perhaps you should specify the real hostname on the command line?)"
|
||||||
]
|
]
|
||||||
|
@ -96,7 +96,7 @@ updateFirst cmdline next = do
|
||||||
then do
|
then do
|
||||||
putStrLn $ "git branch " ++ originbranch ++ " gpg signature verified; merging"
|
putStrLn $ "git branch " ++ originbranch ++ " gpg signature verified; merging"
|
||||||
hFlush stdout
|
hFlush stdout
|
||||||
else error $ "git branch " ++ originbranch ++ " is not signed with a trusted gpg key; refusing to deploy it!"
|
else errorMessage $ "git branch " ++ originbranch ++ " is not signed with a trusted gpg key; refusing to deploy it!"
|
||||||
|
|
||||||
oldsha <- getCurrentGitSha1 branchref
|
oldsha <- getCurrentGitSha1 branchref
|
||||||
void $ boolSystem "git" [Param "merge", Param originbranch]
|
void $ boolSystem "git" [Param "merge", Param originbranch]
|
||||||
|
@ -104,12 +104,9 @@ updateFirst cmdline next = do
|
||||||
|
|
||||||
if oldsha == newsha
|
if oldsha == newsha
|
||||||
then next
|
then next
|
||||||
else do
|
else ifM (actionMessage "Rebuilding propellor" $ boolSystem "make" [Param "build"])
|
||||||
putStrLn "Rebuilding propeller.."
|
|
||||||
hFlush stdout
|
|
||||||
ifM (boolSystem "make" [Param "build"])
|
|
||||||
( void $ boolSystem "./propellor" [Param "--continue", Param (show cmdline)]
|
( void $ boolSystem "./propellor" [Param "--continue", Param (show cmdline)]
|
||||||
, error "Propellor build failed!"
|
, errorMessage "Propellor build failed!"
|
||||||
)
|
)
|
||||||
|
|
||||||
getCurrentGitSha1 :: String -> IO String
|
getCurrentGitSha1 :: String -> IO String
|
||||||
|
@ -131,7 +128,7 @@ spin host = do
|
||||||
void $ tryIO $ forever $
|
void $ tryIO $ forever $
|
||||||
showremote =<< hGetLine fromh
|
showremote =<< hGetLine fromh
|
||||||
hClose fromh
|
hClose fromh
|
||||||
status <- getstatus fromh `catchIO` error "protocol error"
|
status <- getstatus fromh `catchIO` (const $ errorMessage "protocol error")
|
||||||
case status of
|
case status of
|
||||||
Ready -> finish
|
Ready -> finish
|
||||||
NeedGitClone -> do
|
NeedGitClone -> do
|
||||||
|
@ -166,22 +163,22 @@ spin host = do
|
||||||
Just status -> return status
|
Just status -> return status
|
||||||
|
|
||||||
showremote s = putStrLn s
|
showremote s = putStrLn s
|
||||||
senddata toh f marker s = do
|
senddata toh f marker s = void $
|
||||||
putStr $ "Sending " ++ f ++ " (" ++ show (length s) ++ " bytes) to " ++ host ++ "..."
|
actionMessage ("Sending " ++ f ++ " (" ++ show (length s) ++ " bytes) to " ++ host) $ do
|
||||||
hFlush stdout
|
hFlush stdout
|
||||||
hPutStrLn toh $ toMarked marker s
|
hPutStrLn toh $ toMarked marker s
|
||||||
hFlush toh
|
hFlush toh
|
||||||
putStrLn "done"
|
return True
|
||||||
|
|
||||||
sendGitClone :: HostName -> String -> IO ()
|
sendGitClone :: HostName -> String -> IO ()
|
||||||
sendGitClone host url = do
|
sendGitClone host url = void $ actionMessage ("Pushing git repository to " ++ host) $
|
||||||
putStrLn $ "Pushing git repository to " ++ host
|
withTmpFile "gitbundle" $ \tmp _ -> allM id
|
||||||
withTmpFile "gitbundle" $ \tmp _ -> do
|
|
||||||
-- TODO: ssh connection caching, or better push method
|
-- TODO: ssh connection caching, or better push method
|
||||||
-- with less connections.
|
-- with less connections.
|
||||||
void $ boolSystem "git" [Param "bundle", Param "create", Param "-2", File tmp, Param "HEAD"]
|
[ boolSystem "git" [Param "bundle", Param "create", Param "-2", File tmp, Param "HEAD"]
|
||||||
void $ boolSystem "scp" [File tmp, Param ("root@"++host++":"++remotebundle)]
|
, boolSystem "scp" [File tmp, Param ("root@"++host++":"++remotebundle)]
|
||||||
void $ boolSystem "ssh" [Param ("root@"++host), Param unpackcmd]
|
, boolSystem "ssh" [Param ("root@"++host), Param unpackcmd]
|
||||||
|
]
|
||||||
where
|
where
|
||||||
remotebundle = "/usr/local/propellor.git"
|
remotebundle = "/usr/local/propellor.git"
|
||||||
unpackcmd = shellWrap $ intercalate " && "
|
unpackcmd = shellWrap $ intercalate " && "
|
||||||
|
@ -265,10 +262,10 @@ localdir :: FilePath
|
||||||
localdir = "/usr/local/propellor"
|
localdir = "/usr/local/propellor"
|
||||||
|
|
||||||
getUrl :: IO String
|
getUrl :: IO String
|
||||||
getUrl = fromMaybe nourl <$> getM get urls
|
getUrl = maybe nourl return =<< getM get urls
|
||||||
where
|
where
|
||||||
urls = ["remote.deploy.url", "remote.origin.url"]
|
urls = ["remote.deploy.url", "remote.origin.url"]
|
||||||
nourl = error $ "Cannot find deploy url in " ++ show urls
|
nourl = errorMessage $ "Cannot find deploy url in " ++ show urls
|
||||||
get u = do
|
get u = do
|
||||||
v <- catchMaybeIO $
|
v <- catchMaybeIO $
|
||||||
takeWhile (/= '\n')
|
takeWhile (/= '\n')
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
module Propellor.Engine where
|
module Propellor.Engine where
|
||||||
|
|
||||||
import System.Console.ANSI
|
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import System.IO
|
import System.IO
|
||||||
import Data.Monoid
|
import Data.Monoid
|
||||||
|
import System.Console.ANSI
|
||||||
|
|
||||||
import Propellor.Types
|
import Propellor.Types
|
||||||
|
import Propellor.Message
|
||||||
import Utility.Exception
|
import Utility.Exception
|
||||||
|
|
||||||
ensureProperty :: Property -> IO Result
|
ensureProperty :: Property -> IO Result
|
||||||
|
@ -25,29 +26,5 @@ ensureProperties' ps = ensure ps NoChange
|
||||||
where
|
where
|
||||||
ensure [] rs = return rs
|
ensure [] rs = return rs
|
||||||
ensure (l:ls) rs = do
|
ensure (l:ls) rs = do
|
||||||
setTitle $ propertyDesc l
|
r <- actionMessage (propertyDesc l) (ensureProperty l)
|
||||||
hFlush stdout
|
|
||||||
r <- ensureProperty l
|
|
||||||
clearFromCursorToLineBeginning
|
|
||||||
setCursorColumn 0
|
|
||||||
putStr $ propertyDesc l ++ "... "
|
|
||||||
case r of
|
|
||||||
FailedChange -> do
|
|
||||||
setSGR [SetColor Foreground Vivid Red]
|
|
||||||
putStrLn "failed"
|
|
||||||
NoChange -> do
|
|
||||||
setSGR [SetColor Foreground Dull Green]
|
|
||||||
putStrLn "unchanged"
|
|
||||||
MadeChange -> do
|
|
||||||
setSGR [SetColor Foreground Vivid Green]
|
|
||||||
putStrLn "done"
|
|
||||||
setSGR []
|
|
||||||
hFlush stdout
|
|
||||||
ensure ls (r <> rs)
|
ensure ls (r <> rs)
|
||||||
|
|
||||||
warningMessage :: String -> IO ()
|
|
||||||
warningMessage s = do
|
|
||||||
setSGR [SetColor Foreground Vivid Red]
|
|
||||||
putStrLn $ "** warning: " ++ s
|
|
||||||
setSGR []
|
|
||||||
hFlush stdout
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
module Propellor.Message where
|
||||||
|
|
||||||
|
import System.Console.ANSI
|
||||||
|
import System.IO
|
||||||
|
|
||||||
|
import Propellor.Types
|
||||||
|
|
||||||
|
-- | Shows a message while performing an action, with a colored status
|
||||||
|
-- display.
|
||||||
|
actionMessage :: ActionResult r => Desc -> IO r -> IO r
|
||||||
|
actionMessage desc a = do
|
||||||
|
setTitle desc
|
||||||
|
showdesc
|
||||||
|
putStrLn "starting"
|
||||||
|
hFlush stdout
|
||||||
|
|
||||||
|
r <- a
|
||||||
|
|
||||||
|
let (msg, intensity, color) = getActionResult r
|
||||||
|
showdesc
|
||||||
|
setSGR [SetColor Foreground intensity color]
|
||||||
|
putStrLn msg
|
||||||
|
setSGR []
|
||||||
|
hFlush stdout
|
||||||
|
|
||||||
|
return r
|
||||||
|
where
|
||||||
|
showdesc = putStr $ desc ++ " ... "
|
||||||
|
|
||||||
|
warningMessage :: String -> IO ()
|
||||||
|
warningMessage s = do
|
||||||
|
setSGR [SetColor Foreground Vivid Red]
|
||||||
|
putStrLn $ "** warning: " ++ s
|
||||||
|
setSGR []
|
||||||
|
hFlush stdout
|
||||||
|
|
||||||
|
errorMessage :: String -> IO a
|
||||||
|
errorMessage s = do
|
||||||
|
warningMessage s
|
||||||
|
error "Propellor failed!"
|
|
@ -9,7 +9,7 @@ import Data.Maybe
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
|
|
||||||
import Propellor.Types
|
import Propellor.Types
|
||||||
import Propellor.Engine
|
import Propellor.Message
|
||||||
import Utility.Monad
|
import Utility.Monad
|
||||||
import Utility.PartialPrelude
|
import Utility.PartialPrelude
|
||||||
import Utility.Exception
|
import Utility.Exception
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module Propellor.Types where
|
module Propellor.Types where
|
||||||
|
|
||||||
import Data.Monoid
|
import Data.Monoid
|
||||||
|
import System.Console.ANSI
|
||||||
|
|
||||||
type HostName = String
|
type HostName = String
|
||||||
type UserName = String
|
type UserName = String
|
||||||
|
@ -24,3 +25,15 @@ instance Monoid Result where
|
||||||
mappend MadeChange _ = MadeChange
|
mappend MadeChange _ = MadeChange
|
||||||
mappend _ MadeChange = MadeChange
|
mappend _ MadeChange = MadeChange
|
||||||
mappend NoChange NoChange = NoChange
|
mappend NoChange NoChange = NoChange
|
||||||
|
|
||||||
|
class ActionResult a where
|
||||||
|
getActionResult :: a -> (String, ColorIntensity, Color)
|
||||||
|
|
||||||
|
instance ActionResult Bool where
|
||||||
|
getActionResult False = ("ok", Vivid, Red)
|
||||||
|
getActionResult True = ("failed", Vivid, Green)
|
||||||
|
|
||||||
|
instance ActionResult Result where
|
||||||
|
getActionResult NoChange = ("unchanged", Dull, Green)
|
||||||
|
getActionResult MadeChange = ("done", Vivid, Green)
|
||||||
|
getActionResult FailedChange = ("failed", Vivid, Red)
|
||||||
|
|
|
@ -60,6 +60,7 @@ Library
|
||||||
Propellor.Property.Tor
|
Propellor.Property.Tor
|
||||||
Propellor.Property.User
|
Propellor.Property.User
|
||||||
Propellor.CmdLine
|
Propellor.CmdLine
|
||||||
|
Propellor.Message
|
||||||
Propellor.PrivData
|
Propellor.PrivData
|
||||||
Propellor.Engine
|
Propellor.Engine
|
||||||
Propellor.Types
|
Propellor.Types
|
||||||
|
|
Loading…
Reference in New Issue