-- | Maintainer: 2016 Evan Cofsky <evan@theunixman.com>
-- 
-- Functions defining zfs Properties.

module Propellor.Property.ZFS.Properties (
	ZFSOS,
	zfsExists,
	zfsSetProperties
) where

import Propellor.Base
import Data.List (intercalate)
import qualified Propellor.Property.ZFS.Process as ZP

-- | OS's that support ZFS
type ZFSOS = Linux + FreeBSD

-- | Will ensure that a ZFS volume exists with the specified mount point.
-- This requires the pool to exist as well, but we don't create pools yet.
zfsExists :: ZFS -> Property ZFSOS
zfsExists :: ZFS -> Property ZFSOS
zfsExists ZFS
z = forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (Bool -> Bool
not forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ZFS -> IO Bool
ZP.zfsExists ZFS
z) UncheckedProperty UnixLike
create
	forall p. IsProp p => p -> Desc -> p
`describe` [Desc] -> Desc
unwords [Desc
"Creating", ZFS -> Desc
zfsName ZFS
z]
  where
	(Desc
p, [Desc]
a) = Desc -> [Maybe Desc] -> ZFS -> (Desc, [Desc])
ZP.zfsCommand Desc
"create" [forall a. Maybe a
Nothing] ZFS
z
	create :: UncheckedProperty UnixLike
create = Desc -> [Desc] -> UncheckedProperty UnixLike
cmdProperty Desc
p [Desc]
a

-- | Sets the given properties. Returns True if all were successfully changed, False if not.
zfsSetProperties :: ZFS -> ZFSProperties -> Property ZFSOS
zfsSetProperties :: ZFS -> ZFSProperties -> Property ZFSOS
zfsSetProperties ZFS
z ZFSProperties
setProperties = Property UnixLike
setall
	forall x y. Combines x y => x -> y -> CombinedType x y
`requires` ZFS -> Property ZFSOS
zfsExists ZFS
z
  where
	spcmd :: String -> String -> (String, [String])
	spcmd :: Desc -> Desc -> (Desc, [Desc])
spcmd Desc
p Desc
v = Desc -> [Maybe Desc] -> ZFS -> (Desc, [Desc])
ZP.zfsCommand Desc
"set" [forall a. a -> Maybe a
Just (forall a. [a] -> [[a]] -> [a]
intercalate Desc
"=" [Desc
p, Desc
v]), forall a. Maybe a
Nothing] ZFS
z

	setprop :: (String, String) -> Property ZFSOS
	setprop :: (Desc, Desc) -> Property ZFSOS
setprop (Desc
p, Desc
v) = forall (p :: * -> *) i (m :: * -> *).
(Checkable p i, LiftPropellor m) =>
m Bool -> p i -> Property i
check (ZFS -> IO Bool
ZP.zfsExists ZFS
z) forall a b. (a -> b) -> a -> b
$
		Desc -> [Desc] -> UncheckedProperty UnixLike
cmdProperty (forall a b. (a, b) -> a
fst (Desc -> Desc -> (Desc, [Desc])
spcmd Desc
p Desc
v)) (forall a b. (a, b) -> b
snd (Desc -> Desc -> (Desc, [Desc])
spcmd Desc
p Desc
v))

	setall :: Property UnixLike
setall = forall {k} (metatypes :: k).
SingI metatypes =>
Desc
-> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
combineProperties ([Desc] -> Desc
unwords [Desc
"Setting properties on", ZFS -> Desc
zfsName ZFS
z]) forall a b. (a -> b) -> a -> b
$
		forall {k} (metatypes :: k).
[Property (MetaTypes metatypes)] -> Props (MetaTypes metatypes)
toProps forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (Desc, Desc) -> Property ZFSOS
setprop forall a b. (a -> b) -> a -> b
$ ZFSProperties -> [(Desc, Desc)]
toPropertyList ZFSProperties
setProperties