propellor

propellor config for hosts.
git clone git://git.ricketyspace.net/propellor.git
Log | Files | Refs | LICENSE

Cmd.hs (3377B)


      1 {-# LANGUAGE PackageImports #-}
      2 
      3 -- | This module lets you construct Properties by running commands and
      4 -- scripts. To get from an `UncheckedProperty` to a `Property`, it's
      5 -- up to the user to check if the command made a change to the system. 
      6 --
      7 -- The best approach is to `check` a property, so that the command is only
      8 -- run when it needs to be. With this method, you avoid running the
      9 -- `cmdProperty` unnecessarily.
     10 --
     11 -- > check (not <$> userExists "bob")
     12 -- > 	(cmdProperty "useradd" ["bob"])
     13 --
     14 -- Sometimes it's just as expensive to check a property as it would be to
     15 -- run the command that ensures the property. So you can let the command
     16 -- run every time, and use `changesFile` or `checkResult` to determine if
     17 -- anything changed:
     18 --
     19 -- > cmdProperty "chmod" ["600", "/etc/secret"]
     20 -- > 	`changesFile` "/etc/secret"
     21 --
     22 -- Or you can punt and `assume` a change was made, but then propellor will
     23 -- always say it make a change, and `onChange` will always fire.
     24 --
     25 -- > cmdProperty "service" ["foo", "reload"]
     26 -- > 	`assume` MadeChange
     27 
     28 module Propellor.Property.Cmd (
     29 	-- * Constricting properties running commands and scripts
     30 	cmdProperty,
     31 	cmdProperty',
     32 	cmdPropertyEnv,
     33 	Script,
     34 	scriptProperty,
     35 	userScriptProperty,
     36 	cmdResult,
     37 	-- * Lower-level interface for running commands
     38 	CommandParam(..),
     39 	boolSystem,
     40 	boolSystemEnv,
     41 	safeSystem,
     42 	safeSystemEnv,
     43 	shellEscape,
     44 	createProcess,
     45 	waitForProcess,
     46 ) where
     47 
     48 import Data.List
     49 import "mtl" Control.Monad.Reader
     50 import Control.Applicative
     51 import Prelude
     52 
     53 import Propellor.Types
     54 import Propellor.Property
     55 import Utility.SafeCommand
     56 import Utility.Env
     57 import Utility.Process (createProcess, CreateProcess, waitForProcess)
     58 
     59 -- | A property that can be satisfied by running a command.
     60 --
     61 -- The command must exit 0 on success.
     62 cmdProperty :: String -> [String] -> UncheckedProperty UnixLike
     63 cmdProperty cmd params = cmdProperty' cmd params id
     64 
     65 cmdProperty' :: String -> [String] -> (CreateProcess -> CreateProcess) -> UncheckedProperty UnixLike
     66 cmdProperty' cmd params mkprocess = unchecked $ property desc $ liftIO $
     67 	cmdResult <$> boolSystem' cmd (map Param params) mkprocess
     68   where
     69 	desc = unwords $ cmd : params
     70 
     71 cmdResult :: Bool -> Result
     72 cmdResult False = FailedChange
     73 cmdResult True = NoChange
     74 
     75 -- | A property that can be satisfied by running a command,
     76 -- with added environment variables in addition to the standard
     77 -- environment.
     78 cmdPropertyEnv :: String -> [String] -> [(String, String)] -> UncheckedProperty UnixLike
     79 cmdPropertyEnv cmd params env = unchecked $ property desc $ liftIO $ do
     80 	env' <- addEntries env <$> getEnvironment
     81 	cmdResult <$> boolSystemEnv cmd (map Param params) (Just env')
     82   where
     83 	desc = unwords $ cmd : params
     84 
     85 -- | A series of shell commands. (Without a leading hashbang.)
     86 type Script = [String]
     87 
     88 -- | A property that can be satisfied by running a script.
     89 scriptProperty :: Script -> UncheckedProperty UnixLike
     90 scriptProperty script = cmdProperty "sh" ["-c", shellcmd]
     91   where
     92 	shellcmd = intercalate " ; " ("set -e" : script)
     93 
     94 -- | A property that can satisfied by running a script
     95 -- as user (cd'd to their home directory).
     96 userScriptProperty :: User -> Script -> UncheckedProperty UnixLike
     97 userScriptProperty (User user) script = cmdProperty "su"
     98 	["--login", "--shell", "/bin/sh", "-c", shellcmd, user]
     99   where
    100 	shellcmd = intercalate " ; " ("set -e" : "cd" : script)