module Test.Sandbox.Compose.Core (
setupServices
, runServices
, runService
, killServices
, killService
) where
import Control.Monad
import Data.Maybe
import qualified Data.Map as M
import qualified Data.ByteString.Char8 as B
import Test.Sandbox.Compose.Type
import Test.Sandbox.Compose.Template
import Test.Sandbox
import Test.Sandbox.Internals
import qualified Data.Yaml as Y
import System.Process
import System.Exit
getList :: (Service -> [a]) -> Services -> [(ServiceName,a)]
getList func services =
concat
$ map (\(k,v) -> map ((,) k) $ func v)
$ M.toList services
getPortList :: Services -> [(ServiceName, PortName)]
getPortList = getList $ fromMaybe [] . sPorts
getTempList :: Services -> [(ServiceName, TempFileName)]
getTempList = getList $ fromMaybe [] . sTempFiles
getDirList :: Services -> [(ServiceName, DirName)]
getDirList = getList $ fromMaybe [] . sDirs
getConfList :: Services -> [(ServiceName, (ConfName, ConfContent))]
getConfList = getList $ (M.toList . fromMaybe M.empty . sConfs)
setupServices :: Services -> Sandbox (Maybe Services)
setupServices services = do
ports <- forM (map (\(s,p) -> (s++"_port_"++p)) $ getPortList services) $ \portname -> do
portnum <- getPort portname
return (portname,show portnum) :: Sandbox (String,String)
temps <- forM (map (\(s,p) -> s++"_temp_"++p) $ getTempList services) $ \tempname -> do
filename <- setFile tempname []
return (tempname,show filename) :: Sandbox (String,String)
dirs <- forM (map (\(s,p) -> s++"_dir_"++p) $ getDirList services) $ \dirname -> do
dir <- getDataDir
return (dirname,dir++"/"++dirname) :: Sandbox (String,String)
let params = ports ++ temps ++ dirs
mPreServices <- updateServices params (Just services)
case mPreServices of
Nothing -> return Nothing
Just preServices -> do
confs <- forM (getConfList preServices) $ \(s,(cn,_)) -> do
let tempname = s++"_conf_"++cn
filename <- setFile tempname ""
return (tempname,filename) :: Sandbox (String,String)
mServices <- updateServices confs mPreServices
case mServices of
Nothing -> return Nothing
Just services' -> do
forM_ (getConfList services') $ \(s,(cn,cc)) -> do
let tempname = s++"_conf_"++cn
filename <- getFile tempname
liftIO $ writeFile filename cc
forM_ (M.toList services') $ \(sname,sconf) -> do
registerService sname sconf
return mServices
where
updateServices _ Nothing = return Nothing
updateServices params (Just service) = do
service' <- liftIO $ applyTemplate params $ B.unpack $ Y.encode service
return $ Y.decode $ B.pack service'
runServices :: Services -> Sandbox ()
runServices services = do
forM_ (M.toList services) $ \(k,_) -> do
runService k services
registerService :: ServiceName -> Service -> Sandbox ()
registerService serviceName service = do
dir <- getDataDir
let k = serviceName
let v = service
void $ register k (sCmd v) (sArgs v) (def{psWait = Just 3,psCapture=Just (CaptureBothWithFile (dir ++ "/" ++ k ++ "_out.txt") (dir ++ "/" ++ k ++ "_err.txt"))})
runService :: ServiceName -> Services -> Sandbox ()
runService serviceName services = do
let k = serviceName
let v = services M.! serviceName
case sBeforeScript v of
Just script -> do
r@(c,_,_) <- liftIO $ readProcessWithExitCode "bash" ["-c",script] []
when (c /= ExitSuccess) $ do
error $ "BeforeScript Error:\n" ++ show r
Nothing -> return ()
void $ start k
case sAfterScript v of
Just script -> do
r@(c,_,_) <- liftIO $ readProcessWithExitCode "bash" ["-c",script] []
when (c /= ExitSuccess) $ do
error $ "AfterScript Error:\n" ++ show r
Nothing -> return ()
killService :: ServiceName -> Sandbox ()
killService k = stop k
killServices :: Sandbox ()
killServices = do
stopAll
cleanUpProcesses