azubi-0.2.0.3: src/Azubi/Core/Model.hs
{-|
Module : Azubi.Core.Model
Description : Core low level Model of Azubi
Copyright : (c) Ingolf Wagner, 2017
License : GPL-3
Maintainer : azubi@ingolf-wagner.de
Stability : experimental
Portability : POSIX
This is the lowest level of Azubi.
It should deliver only the bare
minimum to create 'State' evaluation
and 'State' enforcement.
The 'State' object is the element
a user should use to formulate more complex
situations.
The idea here is to create a simple AST which
can be run on different setups.
* export to Script
* run on the Machine (Linux, OSX and (maybe) Windows)
* run over SSH on another computer
-}
module Azubi.Core.Model where
type Path = String
type Target = String
type Argument = String
type Comment = String
{-|
A command is something that will be run.
In a normal case you put a 'Check' before
using a 'State'
When a Command get executed,
it will create a 'CommandResult'.
@ command -> exit code -> 'CommandResult' @
-}
data Command
= Run { command :: String
, commandArguments :: [String]
, commandComment :: Maybe String }
| FileContent { filePath :: String
, fileContent :: [String] }
| CreateSymlink { linkPath :: String
, linkTarget :: String }
| CreateFolder { folderPath :: String }
| Remove { removePath :: String }
deriving (Show, Eq)
{-|
The Result of a 'Command' will be matched
to a 'CommandResult'. The basic rule is
@
0 -> 'Success'
_ -> 'Failure'
@
-}
data CommandResult
= Success
| Failure
deriving (Show, Enum, Eq)
{-|
Gather information about a situation.
@
check -> success/failure
check -> exit code -> success/failure
@
-}
data Check
{-|
Check if command returns exit status
@
0 -> Yes
_ -> No
@
-}
= Check { checkCommand :: String
, checkArguments :: [String]
, checkComment :: Maybe String }
-- | Will return `No` to "skip" the Checks.
| SkipChecks
-- | Opposite result of a 'Check'
| Not Check
-- | Check if 'Path' has content
| HasFileContent { pathToCheck :: String
, contentToCheck :: [String] }
-- | Check if a Symbolic link exists to a specific target
| SymlinkExists { pathToCheck :: String
, targetToCheck :: String }
-- | Check if a folder exists
| FolderExists { pathToCheck :: String }
-- | Check if something exists at path
| DoesExist { pathToCheck :: String }
deriving (Show, Eq)
{-|
The result of a 'Check'.
-}
data CheckResult
= Yes
| No
deriving (Show, Enum, Eq)
{-|
The low level element to formulate a state on a machine.
If the check returns 'No' the 'Command's will run.
So the author should make sure the 'Command' will result
in a 'Yes' the next time this state will run.
All 'Check's have to return 'Yes' to avoid the 'Command's
to be run.
If a 'Command' returns a 'Failure' the following commands
will not be called.
Same holdes for 'States' if one of the states fail,
the following 'State's will not be /run/.
-}
data State
-- | State contains checks and commands
-- if one command failed
-- the following commands will not be
-- executed.
= State { stateChecks :: [Check]
, stateCommands :: [Command]
, stateComment :: Maybe String }
-- | To create depended states
-- which should stop being executed
-- when a previous state fails
| States { stateChecks :: [Check]
, subStates :: [State]
, stateComment :: Maybe String }
deriving (Show, Eq)
{-|
When a 'State' is /run/ it returns one of the 'StateResult's.
* positive 'CheckResult's will result in 'Fulfilled'.
* negative 'CheckResult's with positive 'CommandResult's will result in 'Fulfilled'.
* negative 'CheckResult's with negative 'CommandResult's will result in 'Unfulfilled'.
-}
data StateResult
= Fulfilled
| Unfulfilled
deriving (Show, Eq, Enum)