module B9.B9Config.Container
  ( parseContainerCapabilities,
    ContainerCapability (..),
    containerCapsToCPDocument,
  )
where

import Data.ConfigFile.B9Extras
import Test.QuickCheck (Arbitrary(arbitrary))
import qualified Test.QuickCheck as QuickCheck

-- | Available capabilities for Linux containers. This maps directly to the
-- capabilities defined in 'man 7 capabilities'.
data ContainerCapability
  = CAP_MKNOD
  | CAP_AUDIT_CONTROL
  | CAP_AUDIT_READ
  | CAP_AUDIT_WRITE
  | CAP_BLOCK_SUSPEND
  | CAP_CHOWN
  | CAP_DAC_OVERRIDE
  | CAP_DAC_READ_SEARCH
  | CAP_FOWNER
  | CAP_FSETID
  | CAP_IPC_LOCK
  | CAP_IPC_OWNER
  | CAP_KILL
  | CAP_LEASE
  | CAP_LINUX_IMMUTABLE
  | CAP_MAC_ADMIN
  | CAP_MAC_OVERRIDE
  | CAP_NET_ADMIN
  | CAP_NET_BIND_SERVICE
  | CAP_NET_BROADCAST
  | CAP_NET_RAW
  | CAP_SETGID
  | CAP_SETFCAP
  | CAP_SETPCAP
  | CAP_SETUID
  | CAP_SYS_ADMIN
  | CAP_SYS_BOOT
  | CAP_SYS_CHROOT
  | CAP_SYS_MODULE
  | CAP_SYS_NICE
  | CAP_SYS_PACCT
  | CAP_SYS_PTRACE
  | CAP_SYS_RAWIO
  | CAP_SYS_RESOURCE
  | CAP_SYS_TIME
  | CAP_SYS_TTY_CONFIG
  | CAP_SYSLOG
  | CAP_WAKE_ALARM
  deriving (ReadPrec [ContainerCapability]
ReadPrec ContainerCapability
Int -> ReadS ContainerCapability
ReadS [ContainerCapability]
(Int -> ReadS ContainerCapability)
-> ReadS [ContainerCapability]
-> ReadPrec ContainerCapability
-> ReadPrec [ContainerCapability]
-> Read ContainerCapability
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [ContainerCapability]
$creadListPrec :: ReadPrec [ContainerCapability]
readPrec :: ReadPrec ContainerCapability
$creadPrec :: ReadPrec ContainerCapability
readList :: ReadS [ContainerCapability]
$creadList :: ReadS [ContainerCapability]
readsPrec :: Int -> ReadS ContainerCapability
$creadsPrec :: Int -> ReadS ContainerCapability
Read, Int -> ContainerCapability -> ShowS
[ContainerCapability] -> ShowS
ContainerCapability -> String
(Int -> ContainerCapability -> ShowS)
-> (ContainerCapability -> String)
-> ([ContainerCapability] -> ShowS)
-> Show ContainerCapability
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ContainerCapability] -> ShowS
$cshowList :: [ContainerCapability] -> ShowS
show :: ContainerCapability -> String
$cshow :: ContainerCapability -> String
showsPrec :: Int -> ContainerCapability -> ShowS
$cshowsPrec :: Int -> ContainerCapability -> ShowS
Show, ContainerCapability -> ContainerCapability -> Bool
(ContainerCapability -> ContainerCapability -> Bool)
-> (ContainerCapability -> ContainerCapability -> Bool)
-> Eq ContainerCapability
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ContainerCapability -> ContainerCapability -> Bool
$c/= :: ContainerCapability -> ContainerCapability -> Bool
== :: ContainerCapability -> ContainerCapability -> Bool
$c== :: ContainerCapability -> ContainerCapability -> Bool
Eq, Int -> ContainerCapability
ContainerCapability -> Int
ContainerCapability -> [ContainerCapability]
ContainerCapability -> ContainerCapability
ContainerCapability -> ContainerCapability -> [ContainerCapability]
ContainerCapability
-> ContainerCapability
-> ContainerCapability
-> [ContainerCapability]
(ContainerCapability -> ContainerCapability)
-> (ContainerCapability -> ContainerCapability)
-> (Int -> ContainerCapability)
-> (ContainerCapability -> Int)
-> (ContainerCapability -> [ContainerCapability])
-> (ContainerCapability
    -> ContainerCapability -> [ContainerCapability])
-> (ContainerCapability
    -> ContainerCapability -> [ContainerCapability])
-> (ContainerCapability
    -> ContainerCapability
    -> ContainerCapability
    -> [ContainerCapability])
-> Enum ContainerCapability
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: ContainerCapability
-> ContainerCapability
-> ContainerCapability
-> [ContainerCapability]
$cenumFromThenTo :: ContainerCapability
-> ContainerCapability
-> ContainerCapability
-> [ContainerCapability]
enumFromTo :: ContainerCapability -> ContainerCapability -> [ContainerCapability]
$cenumFromTo :: ContainerCapability -> ContainerCapability -> [ContainerCapability]
enumFromThen :: ContainerCapability -> ContainerCapability -> [ContainerCapability]
$cenumFromThen :: ContainerCapability -> ContainerCapability -> [ContainerCapability]
enumFrom :: ContainerCapability -> [ContainerCapability]
$cenumFrom :: ContainerCapability -> [ContainerCapability]
fromEnum :: ContainerCapability -> Int
$cfromEnum :: ContainerCapability -> Int
toEnum :: Int -> ContainerCapability
$ctoEnum :: Int -> ContainerCapability
pred :: ContainerCapability -> ContainerCapability
$cpred :: ContainerCapability -> ContainerCapability
succ :: ContainerCapability -> ContainerCapability
$csucc :: ContainerCapability -> ContainerCapability
Enum, ContainerCapability
ContainerCapability
-> ContainerCapability -> Bounded ContainerCapability
forall a. a -> a -> Bounded a
maxBound :: ContainerCapability
$cmaxBound :: ContainerCapability
minBound :: ContainerCapability
$cminBound :: ContainerCapability
Bounded)

instance Arbitrary ContainerCapability where 
  arbitrary :: Gen ContainerCapability
arbitrary = 
    [ContainerCapability] -> Gen ContainerCapability
forall a. [a] -> Gen a
QuickCheck.elements 
      (ContainerCapability -> ContainerCapability -> [ContainerCapability]
forall a. Enum a => a -> a -> [a]
enumFromTo ContainerCapability
forall a. Bounded a => a
minBound ContainerCapability
forall a. Bounded a => a
maxBound :: [ContainerCapability])

containerCapabilitiesK :: String
containerCapabilitiesK :: String
containerCapabilitiesK = String
"guest_capabilities"

containerCapsToCPDocument ::
  CPDocument -> CPSectionSpec -> [ContainerCapability] -> Either CPError CPDocument
containerCapsToCPDocument :: CPDocument
-> String -> [ContainerCapability] -> Either CPError CPDocument
containerCapsToCPDocument CPDocument
cp String
cfgFileSection [ContainerCapability]
c =
  CPDocument
-> String
-> String
-> [ContainerCapability]
-> Either CPError CPDocument
forall a (m :: * -> *).
(Show a, MonadError CPError m) =>
CPDocument -> String -> String -> a -> m CPDocument
setShowCP CPDocument
cp String
cfgFileSection String
containerCapabilitiesK [ContainerCapability]
c

parseContainerCapabilities :: CPDocument -> CPSectionSpec -> Either CPError [ContainerCapability]
parseContainerCapabilities :: CPDocument -> String -> Either CPError [ContainerCapability]
parseContainerCapabilities CPDocument
cp String
cfgFileSection =
  CPDocument
-> String -> String -> Either CPError [ContainerCapability]
forall a (m :: * -> *).
(CPGet a, MonadError CPError m) =>
CPDocument -> String -> String -> m a
readCP CPDocument
cp String
cfgFileSection String
containerCapabilitiesK
-- TODO make a generic container config data type