packages feed

craft-0.0.0.1: src/Craft/SysV.hs

module Craft.SysV where

import           Control.Lens

import           Craft
import qualified Craft.File   as File


data Status = Running
            | Stopped
  deriving (Eq, Show)


data RunLevel = RunLevel0
              | RunLevel1
              | RunLevel2
              | RunLevel3
              | Runlevel4
              | Runlevel5
              | Runlevel6
              | RunlevelS
  deriving (Eq)


instance Show RunLevel where
  show RunLevel0 = "0"
  show RunLevel1 = "1"
  show RunLevel2 = "2"
  show RunLevel3 = "3"
  show Runlevel4 = "4"
  show Runlevel5 = "5"
  show Runlevel6 = "6"
  show RunlevelS = "S"


defaults :: [RunLevel]
defaults = [ RunLevel0
           , RunLevel1
           , RunLevel2
           , RunLevel3
           , Runlevel4
           , Runlevel5
           , Runlevel6
           ]


data Service = Service
  { _serviceName   :: String
  , _serviceStatus :: Status
  , _serviceAtBoot :: Maybe Bool
  }
  deriving (Eq, Show)
makeLenses ''Service


service :: String -> Service
service sn =
  Service
  { _serviceName   = sn
  , _serviceStatus = Running
  , _serviceAtBoot = Just True
  }


servicePath :: String -> Craft (Path Abs FileP)
servicePath sn = do
  fn <- parseRelFile sn
  return $ $(mkAbsDir "/etc/init.d")</>fn


get :: String -> Craft (Maybe Service)
get sn = do
  sp <- servicePath sn
  exists <- File.exists sp
  if exists then do
    status' <- exec (fromAbsFile sp) ["status"]>>= \case
                 (ExecFail _) -> return Stopped
                 (ExecSucc _) -> return Running
    return . Just $ Service { _serviceName   = sn
                            , _serviceStatus = status'
                            , _serviceAtBoot = Nothing
                            }
  else
    return Nothing


status :: Service -> Craft Status
status svc = do
  sp <- servicePath $ svc^.serviceName
  exec (fromAbsFile sp) ["status"] >>= \case
    (ExecFail _) -> return Stopped
    (ExecSucc _) -> return Running


run_ :: String -> Service -> Craft ()
run_ cmd svc = do
  sp <- servicePath $ svc^.serviceName
  exec_ (fromAbsFile sp) [cmd]


start :: Service -> Craft ()
start = run_ "start"


stop :: Service -> Craft ()
stop = run_ "stop"


restart :: Service -> Craft ()
restart = run_ "restart"


reload :: Service -> Craft ()
reload = run_ "reload"


updateRcD :: Service -> String -> Craft ()
updateRcD svc cmd =
  exec_ "update-rc.d" ["-f", svc^.serviceName, cmd]


instance Craftable Service Service where
  watchCraft svc = do
    whenJust (svc^.serviceAtBoot) $ \x ->
      updateRcD svc (if x then "defaults" else "remove")
    status' <- status svc
    case (svc^.serviceStatus, status') of
      (Running, Running) -> return (Unchanged, svc)
      (Stopped, Stopped) -> return (Unchanged, svc)
      (Running, Stopped) -> do
        start svc
        return (Updated, svc)
      (Stopped, Running) -> do
        stop svc
        return (Updated, svc)