module B9.B9Config.SystemdNspawn
( systemdNspawnConfigToCPDocument,
defaultSystemdNspawnConfig,
parseSystemdNspawnConfig,
SystemdNspawnConfig (..),
SystemdNspawnConsole (..),
systemdNspawnCapabilities,
systemdNspawnUseSudo,
systemdNspawnMaxLifetimeSeconds,
systemdNspawnExtraArgs,
systemdNspawnExecutable,
systemdNspawnConsole,
)
where
import B9.B9Config.Container
import Control.Lens (makeLenses)
import Data.ConfigFile.B9Extras
import qualified Text.ParserCombinators.ReadP as ReadP
import qualified Text.ParserCombinators.ReadPrec as ReadPrec
import Text.Read
import Test.QuickCheck (Arbitrary(arbitrary))
import qualified Test.QuickCheck as QuickCheck
import B9.QCUtil (smaller, arbitraryFilePath)
data SystemdNspawnConfig
= SystemdNspawnConfig
{ _systemdNspawnCapabilities :: [ContainerCapability],
_systemdNspawnUseSudo :: Bool,
_systemdNspawnMaxLifetimeSeconds :: Maybe Int,
_systemdNspawnExtraArgs :: Maybe String,
_systemdNspawnExecutable :: Maybe FilePath,
_systemdNspawnConsole :: SystemdNspawnConsole
}
deriving (Read, Show, Eq)
instance Arbitrary SystemdNspawnConfig where
arbitrary =
SystemdNspawnConfig
<$> smaller arbitrary
<*> smaller arbitrary
<*> smaller arbitrary
<*> smaller arbitrary
<*> smaller (QuickCheck.oneof [pure Nothing, Just <$> arbitraryFilePath])
<*> smaller arbitrary
data SystemdNspawnConsole
= SystemdNspawnInteractive
| SystemdNspawnReadOnly
| SystemdNspawnPassive
| SystemdNspawnPipe
deriving (Eq)
instance Arbitrary SystemdNspawnConsole where
arbitrary =
QuickCheck.elements
[ SystemdNspawnInteractive
, SystemdNspawnReadOnly
, SystemdNspawnPassive
, SystemdNspawnPipe
]
instance Show SystemdNspawnConsole where
show x = case x of
SystemdNspawnInteractive -> "interactive"
SystemdNspawnReadOnly -> "read-only"
SystemdNspawnPassive -> "passive"
SystemdNspawnPipe -> "pipe"
instance Read SystemdNspawnConsole where
readPrec =
do
Ident "interactive" <- lexP
return SystemdNspawnInteractive
+++ ReadPrec.lift
( do
ReadP.skipSpaces
_ <- ReadP.string "read-only"
return SystemdNspawnReadOnly
)
+++ do
Ident "passive" <- lexP
return SystemdNspawnPassive
+++ do
Ident "pipe" <- lexP
return SystemdNspawnPipe
makeLenses ''SystemdNspawnConfig
defaultSystemdNspawnConfig :: SystemdNspawnConfig
defaultSystemdNspawnConfig =
SystemdNspawnConfig
[ CAP_MKNOD,
CAP_SYS_ADMIN,
CAP_SYS_CHROOT,
CAP_SETGID,
CAP_SETUID,
CAP_NET_BIND_SERVICE,
CAP_SETPCAP,
CAP_SYS_PTRACE,
CAP_SYS_MODULE
]
True
(Just (4 * 3600))
Nothing
Nothing
SystemdNspawnReadOnly
cfgFileSection :: String
cfgFileSection = "systemdNspawn"
useSudoK :: String
useSudoK = "use_sudo"
maxLifetimeSecondsK :: String
maxLifetimeSecondsK = "max_lifetime_seconds"
extraArgsK :: String
extraArgsK = "extra_args"
executableK :: String
executableK = "executable"
consoleK :: String
consoleK = "console"
systemdNspawnConfigToCPDocument ::
SystemdNspawnConfig -> CPDocument -> Either CPError CPDocument
systemdNspawnConfigToCPDocument c cp = do
cp1 <- addSectionCP cp cfgFileSection
cp2 <-
containerCapsToCPDocument cp1 cfgFileSection $
_systemdNspawnCapabilities c
cp3 <- setShowCP cp2 cfgFileSection useSudoK $ _systemdNspawnUseSudo c
cp4 <- setShowCP cp3 cfgFileSection maxLifetimeSecondsK $ _systemdNspawnMaxLifetimeSeconds c
cp5 <- setShowCP cp4 cfgFileSection extraArgsK $ _systemdNspawnExtraArgs c
cp6 <- setShowCP cp5 cfgFileSection executableK $ _systemdNspawnExecutable c
setShowCP cp6 cfgFileSection consoleK $ _systemdNspawnConsole c
parseSystemdNspawnConfig :: CPDocument -> Either CPError SystemdNspawnConfig
parseSystemdNspawnConfig cp =
let getr :: (CPGet a) => CPOptionSpec -> Either CPError a
getr = readCP cp cfgFileSection
in SystemdNspawnConfig
<$> parseContainerCapabilities cp cfgFileSection
<*> getr useSudoK
<*> getr maxLifetimeSecondsK
<*> getr extraArgsK
<*> getr executableK
<*> getr consoleK