azubi-0.2.0.0: 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 String [Argument] (Maybe Comment)
| FileContent Path [String]
| CreateSymlink Path Target
| CreateFolder Path
| Remove Path
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 String [Argument] (Maybe Comment)
| AlwaysYes
-- | Opposite result of a 'Check'
| Not Check
-- | Check if 'Path' has content
| HasFileContent Path [String]
-- | Check if a Symbolic link exists to a specific target
| SymlinkExists Path Target
-- | Check if a folder exists
| FolderExists Path
-- | Check if something exists at path
| DoesExist Path
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 [Check] [Command] (Maybe Comment)
-- | To create depended states
-- which should stop being executed
-- when a previous state fails
| States [Check] [State] (Maybe Comment)
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)