{-# LANGUAGE PackageImports #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}

module Propellor.PrivData (
	withPrivData,
	withSomePrivData,
	addPrivData,
	setPrivData,
	unsetPrivData,
	unsetPrivDataUnused,
	dumpPrivData,
	editPrivData,
	filterPrivData,
	listPrivDataFields,
	makePrivDataDir,
	decryptPrivData,
	readPrivData,
	readPrivDataFile,
	PrivMap,
	PrivInfo,
	forceHostContext,
) where

import System.IO
import Data.Maybe
import Data.List
import Data.Typeable
import Control.Monad
import Control.Monad.IfElse
import "mtl" Control.Monad.Reader
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.ByteString.Lazy as L
import Control.Applicative
import Data.Monoid
import Data.Semigroup as Sem
import Prelude

import Propellor.Types
import Propellor.Types.PrivData
import Propellor.Types.MetaTypes
import Propellor.Types.Info
import Propellor.Message
import Propellor.Info
import Propellor.Gpg
import Propellor.PrivData.Paths
import Utility.Monad
import Utility.PartialPrelude
import Utility.Exception
import Utility.Tmp
import Utility.SafeCommand
import Utility.Process.NonConcurrent
import Utility.Misc
import Utility.FileMode
import Utility.Env
import Utility.Table
import Utility.Directory

-- | Allows a Property to access the value of a specific PrivDataField,
-- for use in a specific Context or HostContext.
--
-- Example use:
--
-- > withPrivData (PrivFile pemfile) (Context "joeyh.name") $ \getdata ->
-- >     property "joeyh.name ssl cert" $ getdata $ \privdata ->
-- >       liftIO $ writeFile pemfile (privDataVal privdata)
-- >   where pemfile = "/etc/ssl/certs/web.pem"
-- 
-- Note that if the value is not available, the action is not run
-- and instead it prints a message to help the user make the necessary
-- private data available.
--
-- The resulting Property includes Info about the PrivDataField
-- being used, which is necessary to ensure that the privdata is sent to
-- the remote host by propellor.
withPrivData
	::
		( IsContext c
		, IsPrivDataSource s
		, IncludesInfo metatypes ~ 'True
		)
	=> s
	-> c
	-> (((PrivData -> Propellor Result) -> Propellor Result) -> Property metatypes)
	-> Property metatypes
withPrivData :: forall c s metatypes.
(IsContext c, IsPrivDataSource s,
 IncludesInfo metatypes ~ 'True) =>
s
-> c
-> (((PrivData -> Propellor Result) -> Propellor Result)
    -> Property metatypes)
-> Property metatypes
withPrivData s
s = ((PrivDataField, PrivData) -> PrivData)
-> [s]
-> c
-> (((PrivData -> Propellor Result) -> Propellor Result)
    -> Property metatypes)
-> Property metatypes
forall c s metatypes v.
(IsContext c, IsPrivDataSource s,
 IncludesInfo metatypes ~ 'True) =>
((PrivDataField, PrivData) -> v)
-> [s]
-> c
-> (((v -> Propellor Result) -> Propellor Result)
    -> Property metatypes)
-> Property metatypes
withPrivData' (PrivDataField, PrivData) -> PrivData
forall a b. (a, b) -> b
snd [s
s]

-- Like withPrivData, but here any one of a list of PrivDataFields can be used.
withSomePrivData
	::
		( IsContext c
		, IsPrivDataSource s
		, IncludesInfo metatypes ~ 'True
		)
	=> [s]
	-> c
	-> ((((PrivDataField, PrivData) -> Propellor Result) -> Propellor Result) -> Property metatypes)
	-> Property metatypes
withSomePrivData :: forall c s metatypes.
(IsContext c, IsPrivDataSource s,
 IncludesInfo metatypes ~ 'True) =>
[s]
-> c
-> ((((PrivDataField, PrivData) -> Propellor Result)
     -> Propellor Result)
    -> Property metatypes)
-> Property metatypes
withSomePrivData = ((PrivDataField, PrivData) -> (PrivDataField, PrivData))
-> [s]
-> c
-> ((((PrivDataField, PrivData) -> Propellor Result)
     -> Propellor Result)
    -> Property metatypes)
-> Property metatypes
forall c s metatypes v.
(IsContext c, IsPrivDataSource s,
 IncludesInfo metatypes ~ 'True) =>
((PrivDataField, PrivData) -> v)
-> [s]
-> c
-> (((v -> Propellor Result) -> Propellor Result)
    -> Property metatypes)
-> Property metatypes
withPrivData' (PrivDataField, PrivData) -> (PrivDataField, PrivData)
forall a. a -> a
id

withPrivData' 
	::
		( IsContext c
		, IsPrivDataSource s
		, IncludesInfo metatypes ~ 'True
		)
	=> ((PrivDataField, PrivData) -> v)
	-> [s]
	-> c
	-> (((v -> Propellor Result) -> Propellor Result) -> Property metatypes)
	-> Property metatypes
withPrivData' :: forall c s metatypes v.
(IsContext c, IsPrivDataSource s,
 IncludesInfo metatypes ~ 'True) =>
((PrivDataField, PrivData) -> v)
-> [s]
-> c
-> (((v -> Propellor Result) -> Propellor Result)
    -> Property metatypes)
-> Property metatypes
withPrivData' (PrivDataField, PrivData) -> v
feed [s]
srclist c
c ((v -> Propellor Result) -> Propellor Result) -> Property metatypes
mkprop = Property metatypes -> Property metatypes
addinfo (Property metatypes -> Property metatypes)
-> Property metatypes -> Property metatypes
forall a b. (a -> b) -> a -> b
$ ((v -> Propellor Result) -> Propellor Result) -> Property metatypes
mkprop (((v -> Propellor Result) -> Propellor Result)
 -> Property metatypes)
-> ((v -> Propellor Result) -> Propellor Result)
-> Property metatypes
forall a b. (a -> b) -> a -> b
$ \v -> Propellor Result
a ->
	Propellor Result
-> ((PrivDataField, PrivData) -> Propellor Result)
-> Maybe (PrivDataField, PrivData)
-> Propellor Result
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Propellor Result
missing (v -> Propellor Result
a (v -> Propellor Result)
-> ((PrivDataField, PrivData) -> v)
-> (PrivDataField, PrivData)
-> Propellor Result
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PrivDataField, PrivData) -> v
feed) (Maybe (PrivDataField, PrivData) -> Propellor Result)
-> Propellor (Maybe (PrivDataField, PrivData)) -> Propellor Result
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (PrivDataField -> Propellor (Maybe (PrivDataField, PrivData)))
-> [PrivDataField] -> Propellor (Maybe (PrivDataField, PrivData))
forall (m :: * -> *) a b.
Monad m =>
(a -> m (Maybe b)) -> [a] -> m (Maybe b)
getM PrivDataField -> Propellor (Maybe (PrivDataField, PrivData))
get [PrivDataField]
fieldlist
  where
  	get :: PrivDataField -> Propellor (Maybe (PrivDataField, PrivData))
get PrivDataField
field = do
		Context
context <- HostContext -> PrivDataSourceDesc -> Context
mkHostContext HostContext
hc (PrivDataSourceDesc -> Context)
-> Propellor PrivDataSourceDesc -> Propellor Context
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Host -> PrivDataSourceDesc) -> Propellor PrivDataSourceDesc
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Host -> PrivDataSourceDesc
hostName
		Maybe (PrivDataField, PrivData)
-> (PrivData -> Maybe (PrivDataField, PrivData))
-> Maybe PrivData
-> Maybe (PrivDataField, PrivData)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Maybe (PrivDataField, PrivData)
forall a. Maybe a
Nothing (\PrivData
privdata -> (PrivDataField, PrivData) -> Maybe (PrivDataField, PrivData)
forall a. a -> Maybe a
Just (PrivDataField
field, PrivData
privdata))
			(Maybe PrivData -> Maybe (PrivDataField, PrivData))
-> Propellor (Maybe PrivData)
-> Propellor (Maybe (PrivDataField, PrivData))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Maybe PrivData) -> Propellor (Maybe PrivData)
forall a. IO a -> Propellor a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (PrivDataField -> Context -> IO (Maybe PrivData)
getLocalPrivData PrivDataField
field Context
context)
	missing :: Propellor Result
missing = do
		Context PrivDataSourceDesc
cname <- HostContext -> PrivDataSourceDesc -> Context
mkHostContext HostContext
hc (PrivDataSourceDesc -> Context)
-> Propellor PrivDataSourceDesc -> Propellor Context
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Host -> PrivDataSourceDesc) -> Propellor PrivDataSourceDesc
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Host -> PrivDataSourceDesc
hostName
		PrivDataSourceDesc -> Propellor ()
forall (m :: * -> *). MonadIO m => PrivDataSourceDesc -> m ()
warningMessage (PrivDataSourceDesc -> Propellor ())
-> PrivDataSourceDesc -> Propellor ()
forall a b. (a -> b) -> a -> b
$ PrivDataSourceDesc
"Missing privdata " PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataSourceDesc -> [PrivDataSourceDesc] -> PrivDataSourceDesc
forall a. [a] -> [[a]] -> [a]
intercalate PrivDataSourceDesc
" or " [PrivDataSourceDesc]
fieldnames PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataSourceDesc
" (for " PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataSourceDesc
cname PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataSourceDesc
")"
		[PrivDataSourceDesc] -> Propellor ()
forall (m :: * -> *). MonadIO m => [PrivDataSourceDesc] -> m ()
infoMessage ([PrivDataSourceDesc] -> Propellor ())
-> [PrivDataSourceDesc] -> Propellor ()
forall a b. (a -> b) -> a -> b
$ 
			PrivDataSourceDesc
"Fix this by running:" PrivDataSourceDesc -> [PrivDataSourceDesc] -> [PrivDataSourceDesc]
forall a. a -> [a] -> [a]
:
			[(PrivDataField, Context, Maybe PrivDataSourceDesc)]
-> [PrivDataSourceDesc]
showSet ((s -> (PrivDataField, Context, Maybe PrivDataSourceDesc))
-> [s] -> [(PrivDataField, Context, Maybe PrivDataSourceDesc)]
forall a b. (a -> b) -> [a] -> [b]
map (\s
s -> (s -> PrivDataField
forall s. IsPrivDataSource s => s -> PrivDataField
privDataField s
s, PrivDataSourceDesc -> Context
Context PrivDataSourceDesc
cname, s -> Maybe PrivDataSourceDesc
forall s. IsPrivDataSource s => s -> Maybe PrivDataSourceDesc
describePrivDataSource s
s)) [s]
srclist)
		Result -> Propellor Result
forall a. a -> Propellor a
forall (m :: * -> *) a. Monad m => a -> m a
return Result
FailedChange
	addinfo :: Property metatypes -> Property metatypes
addinfo Property metatypes
p = Property metatypes
p Property metatypes -> Info -> Property metatypes
forall metatypes.
(IncludesInfo metatypes ~ 'True) =>
Property metatypes -> Info -> Property metatypes
`addInfoProperty` (PrivInfo -> Info
forall v. IsInfo v => v -> Info
toInfo PrivInfo
privset)
	privset :: PrivInfo
privset = Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> PrivInfo
PrivInfo (Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
 -> PrivInfo)
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> PrivInfo
forall a b. (a -> b) -> a -> b
$ [(PrivDataField, Maybe PrivDataSourceDesc, HostContext)]
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
forall a. Ord a => [a] -> Set a
S.fromList ([(PrivDataField, Maybe PrivDataSourceDesc, HostContext)]
 -> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext))
-> [(PrivDataField, Maybe PrivDataSourceDesc, HostContext)]
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
forall a b. (a -> b) -> a -> b
$
		(s -> (PrivDataField, Maybe PrivDataSourceDesc, HostContext))
-> [s] -> [(PrivDataField, Maybe PrivDataSourceDesc, HostContext)]
forall a b. (a -> b) -> [a] -> [b]
map (\s
s -> (s -> PrivDataField
forall s. IsPrivDataSource s => s -> PrivDataField
privDataField s
s, s -> Maybe PrivDataSourceDesc
forall s. IsPrivDataSource s => s -> Maybe PrivDataSourceDesc
describePrivDataSource s
s, HostContext
hc)) [s]
srclist
	fieldnames :: [PrivDataSourceDesc]
fieldnames = (PrivDataField -> PrivDataSourceDesc)
-> [PrivDataField] -> [PrivDataSourceDesc]
forall a b. (a -> b) -> [a] -> [b]
map PrivDataField -> PrivDataSourceDesc
forall a. Show a => a -> PrivDataSourceDesc
show [PrivDataField]
fieldlist
	fieldlist :: [PrivDataField]
fieldlist = (s -> PrivDataField) -> [s] -> [PrivDataField]
forall a b. (a -> b) -> [a] -> [b]
map s -> PrivDataField
forall s. IsPrivDataSource s => s -> PrivDataField
privDataField [s]
srclist
	hc :: HostContext
hc = c -> HostContext
forall c. IsContext c => c -> HostContext
asHostContext c
c

showSet :: [(PrivDataField, Context, Maybe PrivDataSourceDesc)] -> [String]
showSet :: [(PrivDataField, Context, Maybe PrivDataSourceDesc)]
-> [PrivDataSourceDesc]
showSet = ((PrivDataField, Context, Maybe PrivDataSourceDesc)
 -> [PrivDataSourceDesc])
-> [(PrivDataField, Context, Maybe PrivDataSourceDesc)]
-> [PrivDataSourceDesc]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (PrivDataField, Context, Maybe PrivDataSourceDesc)
-> [PrivDataSourceDesc]
forall {a}.
Show a =>
(a, Context, Maybe PrivDataSourceDesc) -> [PrivDataSourceDesc]
go
  where
	go :: (a, Context, Maybe PrivDataSourceDesc) -> [PrivDataSourceDesc]
go (a
f, Context PrivDataSourceDesc
c, Maybe PrivDataSourceDesc
md) = [Maybe PrivDataSourceDesc] -> [PrivDataSourceDesc]
forall a. [Maybe a] -> [a]
catMaybes
		[ PrivDataSourceDesc -> Maybe PrivDataSourceDesc
forall a. a -> Maybe a
Just (PrivDataSourceDesc -> Maybe PrivDataSourceDesc)
-> PrivDataSourceDesc -> Maybe PrivDataSourceDesc
forall a b. (a -> b) -> a -> b
$ PrivDataSourceDesc
"  propellor --set '" PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ a -> PrivDataSourceDesc
forall a. Show a => a -> PrivDataSourceDesc
show a
f PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataSourceDesc
"' '" PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataSourceDesc
c PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataSourceDesc
"' \\"
		, Maybe PrivDataSourceDesc
-> (PrivDataSourceDesc -> Maybe PrivDataSourceDesc)
-> Maybe PrivDataSourceDesc
-> Maybe PrivDataSourceDesc
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Maybe PrivDataSourceDesc
forall a. Maybe a
Nothing (\PrivDataSourceDesc
d -> PrivDataSourceDesc -> Maybe PrivDataSourceDesc
forall a. a -> Maybe a
Just (PrivDataSourceDesc -> Maybe PrivDataSourceDesc)
-> PrivDataSourceDesc -> Maybe PrivDataSourceDesc
forall a b. (a -> b) -> a -> b
$ PrivDataSourceDesc
"    " PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataSourceDesc
d) Maybe PrivDataSourceDesc
md
		, PrivDataSourceDesc -> Maybe PrivDataSourceDesc
forall a. a -> Maybe a
Just PrivDataSourceDesc
""
		]

addPrivData :: (PrivDataField, Maybe PrivDataSourceDesc, HostContext) -> Property (HasInfo + UnixLike)
addPrivData :: (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> Property (HasInfo + UnixLike)
addPrivData (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
v = PrivDataSourceDesc -> PrivInfo -> Property (HasInfo + UnixLike)
forall v.
IsInfo v =>
PrivDataSourceDesc -> v -> Property (HasInfo + UnixLike)
pureInfoProperty ((PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> PrivDataSourceDesc
forall a. Show a => a -> PrivDataSourceDesc
show (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
v) (Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> PrivInfo
PrivInfo ((PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
forall a. a -> Set a
S.singleton (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
v))

{- Gets the requested field's value, in the specified context if it's
 - available, from the host's local privdata cache. -}
getLocalPrivData :: PrivDataField -> Context -> IO (Maybe PrivData)
getLocalPrivData :: PrivDataField -> Context -> IO (Maybe PrivData)
getLocalPrivData PrivDataField
field Context
context =
	PrivDataField -> Context -> PrivMap -> Maybe PrivData
getPrivData PrivDataField
field Context
context (PrivMap -> Maybe PrivData)
-> (Maybe PrivMap -> PrivMap) -> Maybe PrivMap -> Maybe PrivData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrivMap -> Maybe PrivMap -> PrivMap
forall a. a -> Maybe a -> a
fromMaybe PrivMap
forall k a. Map k a
M.empty (Maybe PrivMap -> Maybe PrivData)
-> IO (Maybe PrivMap) -> IO (Maybe PrivData)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Maybe PrivMap)
localcache
  where
	localcache :: IO (Maybe PrivMap)
localcache = Maybe PrivMap -> IO (Maybe PrivMap) -> IO (Maybe PrivMap)
forall (m :: * -> *) a. MonadCatch m => a -> m a -> m a
catchDefaultIO Maybe PrivMap
forall a. Maybe a
Nothing (IO (Maybe PrivMap) -> IO (Maybe PrivMap))
-> IO (Maybe PrivMap) -> IO (Maybe PrivMap)
forall a b. (a -> b) -> a -> b
$ PrivDataSourceDesc -> Maybe PrivMap
forall a. Read a => PrivDataSourceDesc -> Maybe a
readish (PrivDataSourceDesc -> Maybe PrivMap)
-> IO PrivDataSourceDesc -> IO (Maybe PrivMap)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PrivDataSourceDesc -> IO PrivDataSourceDesc
readFile PrivDataSourceDesc
privDataLocal

type PrivMap = M.Map (PrivDataField, Context) String

-- | Get only the set of PrivData that the Host's Info says it uses.
filterPrivData :: Host -> PrivMap -> PrivMap
filterPrivData :: Host -> PrivMap -> PrivMap
filterPrivData Host
host = ((PrivDataField, Context) -> PrivDataSourceDesc -> Bool)
-> PrivMap -> PrivMap
forall k a. (k -> a -> Bool) -> Map k a -> Map k a
M.filterWithKey (\(PrivDataField, Context)
k PrivDataSourceDesc
_v -> (PrivDataField, Context) -> Set (PrivDataField, Context) -> Bool
forall a. Ord a => a -> Set a -> Bool
S.member (PrivDataField, Context)
k Set (PrivDataField, Context)
used)
  where
	used :: Set (PrivDataField, Context)
used = ((PrivDataField, Maybe PrivDataSourceDesc, HostContext)
 -> (PrivDataField, Context))
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> Set (PrivDataField, Context)
forall b a. Ord b => (a -> b) -> Set a -> Set b
S.map (\(PrivDataField
f, Maybe PrivDataSourceDesc
_, HostContext
c) -> (PrivDataField
f, HostContext -> PrivDataSourceDesc -> Context
mkHostContext HostContext
c (Host -> PrivDataSourceDesc
hostName Host
host))) (Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
 -> Set (PrivDataField, Context))
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> Set (PrivDataField, Context)
forall a b. (a -> b) -> a -> b
$
		PrivInfo
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
fromPrivInfo (PrivInfo
 -> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext))
-> PrivInfo
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
forall a b. (a -> b) -> a -> b
$ Info -> PrivInfo
forall v. IsInfo v => Info -> v
fromInfo (Info -> PrivInfo) -> Info -> PrivInfo
forall a b. (a -> b) -> a -> b
$ Host -> Info
hostInfo Host
host

getPrivData :: PrivDataField -> Context -> PrivMap -> Maybe PrivData
getPrivData :: PrivDataField -> Context -> PrivMap -> Maybe PrivData
getPrivData PrivDataField
field Context
context PrivMap
m = do
	PrivDataSourceDesc
s <- (PrivDataField, Context) -> PrivMap -> Maybe PrivDataSourceDesc
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup (PrivDataField
field, Context
context) PrivMap
m
	PrivData -> Maybe PrivData
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (PrivDataSourceDesc -> PrivData
PrivData PrivDataSourceDesc
s)

setPrivData :: PrivDataField -> Context -> IO ()
setPrivData :: PrivDataField -> Context -> IO ()
setPrivData PrivDataField
field Context
context = do
	PrivDataSourceDesc -> IO ()
putStrLn PrivDataSourceDesc
"Enter private data on stdin; ctrl-D when done:"
	PrivDataField -> Context -> PrivData -> IO ()
setPrivDataTo PrivDataField
field Context
context (PrivData -> IO ())
-> (PrivDataSourceDesc -> PrivData) -> PrivDataSourceDesc -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrivDataSourceDesc -> PrivData
PrivData (PrivDataSourceDesc -> IO ()) -> IO PrivDataSourceDesc -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Handle -> IO PrivDataSourceDesc
hGetContentsStrict Handle
stdin

unsetPrivData :: PrivDataField -> Context -> IO ()
unsetPrivData :: PrivDataField -> Context -> IO ()
unsetPrivData PrivDataField
field Context
context = do
	(PrivMap -> PrivMap) -> IO ()
modifyPrivData ((PrivMap -> PrivMap) -> IO ()) -> (PrivMap -> PrivMap) -> IO ()
forall a b. (a -> b) -> a -> b
$ (PrivDataField, Context) -> PrivMap -> PrivMap
forall k a. Ord k => k -> Map k a -> Map k a
M.delete (PrivDataField
field, Context
context)
	PrivDataField -> Context -> IO ()
descUnset PrivDataField
field Context
context

descUnset :: PrivDataField -> Context -> IO ()
descUnset :: PrivDataField -> Context -> IO ()
descUnset PrivDataField
field Context
context =
	PrivDataSourceDesc -> IO ()
putStrLn (PrivDataSourceDesc -> IO ()) -> PrivDataSourceDesc -> IO ()
forall a b. (a -> b) -> a -> b
$ PrivDataSourceDesc
"Private data unset: " PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataField -> PrivDataSourceDesc
forall a. Show a => a -> PrivDataSourceDesc
show PrivDataField
field PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataSourceDesc
" " PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ Context -> PrivDataSourceDesc
forall a. Show a => a -> PrivDataSourceDesc
show Context
context

unsetPrivDataUnused :: [Host] -> IO ()
unsetPrivDataUnused :: [Host] -> IO ()
unsetPrivDataUnused [Host]
hosts = do
	[(PrivDataField, Context)]
deleted <- (PrivMap -> (PrivMap, [(PrivDataField, Context)]))
-> IO [(PrivDataField, Context)]
forall a. (PrivMap -> (PrivMap, a)) -> IO a
modifyPrivData' ((PrivMap -> (PrivMap, [(PrivDataField, Context)]))
 -> IO [(PrivDataField, Context)])
-> (PrivMap -> (PrivMap, [(PrivDataField, Context)]))
-> IO [(PrivDataField, Context)]
forall a b. (a -> b) -> a -> b
$ \PrivMap
m ->
		let (PrivMap
keep, PrivMap
del) = ((PrivDataField, Context) -> PrivDataSourceDesc -> Bool)
-> PrivMap -> (PrivMap, PrivMap)
forall k a. (k -> a -> Bool) -> Map k a -> (Map k a, Map k a)
M.partitionWithKey (\(PrivDataField, Context)
k PrivDataSourceDesc
_ -> (PrivDataField, Context)
k (PrivDataField, Context)
-> Map (PrivDataField, Context) [PrivDataSourceDesc] -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`M.member` Map (PrivDataField, Context) [PrivDataSourceDesc]
usedby) PrivMap
m
		in (PrivMap
keep, PrivMap -> [(PrivDataField, Context)]
forall k a. Map k a -> [k]
M.keys PrivMap
del)
	((PrivDataField, Context) -> IO ())
-> [(PrivDataField, Context)] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((PrivDataField -> Context -> IO ())
-> (PrivDataField, Context) -> IO ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry PrivDataField -> Context -> IO ()
descUnset) [(PrivDataField, Context)]
deleted
  where
	usedby :: Map (PrivDataField, Context) [PrivDataSourceDesc]
usedby = [Host] -> Map (PrivDataField, Context) [PrivDataSourceDesc]
mkUsedByMap [Host]
hosts

dumpPrivData :: PrivDataField -> Context -> IO ()
dumpPrivData :: PrivDataField -> Context -> IO ()
dumpPrivData PrivDataField
field Context
context = do
	IO () -> (PrivData -> IO ()) -> Maybe PrivData -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (PrivDataSourceDesc -> IO ()
forall a. HasCallStack => PrivDataSourceDesc -> a
error PrivDataSourceDesc
"Requested privdata is not set.")
		(Handle -> ByteString -> IO ()
L.hPut Handle
stdout (ByteString -> IO ())
-> (PrivData -> ByteString) -> PrivData -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrivData -> ByteString
privDataByteString)
		(Maybe PrivData -> IO ()) -> IO (Maybe PrivData) -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (PrivDataField -> Context -> PrivMap -> Maybe PrivData
getPrivData PrivDataField
field Context
context (PrivMap -> Maybe PrivData) -> IO PrivMap -> IO (Maybe PrivData)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO PrivMap
decryptPrivData)

editPrivData :: PrivDataField -> Context -> IO ()
editPrivData :: PrivDataField -> Context -> IO ()
editPrivData PrivDataField
field Context
context = do
	Maybe PrivData
v <- PrivDataField -> Context -> PrivMap -> Maybe PrivData
getPrivData PrivDataField
field Context
context (PrivMap -> Maybe PrivData) -> IO PrivMap -> IO (Maybe PrivData)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO PrivMap
decryptPrivData
	PrivData
v' <- PrivDataSourceDesc
-> (PrivDataSourceDesc -> Handle -> IO PrivData) -> IO PrivData
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
PrivDataSourceDesc -> (PrivDataSourceDesc -> Handle -> m a) -> m a
withTmpFile PrivDataSourceDesc
"propellorXXXX" ((PrivDataSourceDesc -> Handle -> IO PrivData) -> IO PrivData)
-> (PrivDataSourceDesc -> Handle -> IO PrivData) -> IO PrivData
forall a b. (a -> b) -> a -> b
$ \PrivDataSourceDesc
f Handle
th -> do
		Handle -> IO ()
hClose Handle
th
		IO () -> (PrivData -> IO ()) -> Maybe PrivData -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
forall (m :: * -> *). Monad m => m ()
noop (\PrivData
p -> PrivDataSourceDesc -> (Handle -> IO ()) -> IO ()
writeFileProtected' PrivDataSourceDesc
f (Handle -> ByteString -> IO ()
`L.hPut` PrivData -> ByteString
privDataByteString PrivData
p)) Maybe PrivData
v
		PrivDataSourceDesc
editor <- PrivDataSourceDesc -> PrivDataSourceDesc -> IO PrivDataSourceDesc
getEnvDefault PrivDataSourceDesc
"EDITOR" PrivDataSourceDesc
"vi"
		IO Bool -> IO () -> IO ()
forall {m :: * -> *}. Monad m => m Bool -> m () -> m ()
unlessM (PrivDataSourceDesc -> [CommandParam] -> IO Bool
boolSystemNonConcurrent PrivDataSourceDesc
editor [PrivDataSourceDesc -> CommandParam
File PrivDataSourceDesc
f]) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
			PrivDataSourceDesc -> IO ()
forall a. HasCallStack => PrivDataSourceDesc -> a
error PrivDataSourceDesc
"Editor failed; aborting."
		PrivDataSourceDesc -> PrivData
PrivData (PrivDataSourceDesc -> PrivData)
-> IO PrivDataSourceDesc -> IO PrivData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PrivDataSourceDesc -> IO PrivDataSourceDesc
readFile PrivDataSourceDesc
f
	PrivDataField -> Context -> PrivData -> IO ()
setPrivDataTo PrivDataField
field Context
context PrivData
v'

listPrivDataFields :: [Host] -> IO ()
listPrivDataFields :: [Host] -> IO ()
listPrivDataFields [Host]
hosts = do
	PrivMap
m <- IO PrivMap
decryptPrivData
	
	PrivDataSourceDesc -> IO ()
section PrivDataSourceDesc
"Currently set data:"
	[[PrivDataSourceDesc]] -> IO ()
showtable ([[PrivDataSourceDesc]] -> IO ())
-> [[PrivDataSourceDesc]] -> IO ()
forall a b. (a -> b) -> a -> b
$ ((PrivDataField, Context) -> [PrivDataSourceDesc])
-> [(PrivDataField, Context)] -> [[PrivDataSourceDesc]]
forall a b. (a -> b) -> [a] -> [b]
map (PrivDataField, Context) -> [PrivDataSourceDesc]
mkrow (PrivMap -> [(PrivDataField, Context)]
forall k a. Map k a -> [k]
M.keys PrivMap
m)
	let missing :: [(PrivDataField, Context)]
missing = PrivMap -> [(PrivDataField, Context)]
forall k a. Map k a -> [k]
M.keys (PrivMap -> [(PrivDataField, Context)])
-> PrivMap -> [(PrivDataField, Context)]
forall a b. (a -> b) -> a -> b
$ PrivMap -> PrivMap -> PrivMap
forall k a b. Ord k => Map k a -> Map k b -> Map k a
M.difference PrivMap
wantedmap PrivMap
m
	
	Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([(PrivDataField, Context)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(PrivDataField, Context)]
missing) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
		PrivDataSourceDesc -> IO ()
section PrivDataSourceDesc
"Missing data that would be used if set:"
		[[PrivDataSourceDesc]] -> IO ()
showtable ([[PrivDataSourceDesc]] -> IO ())
-> [[PrivDataSourceDesc]] -> IO ()
forall a b. (a -> b) -> a -> b
$ ((PrivDataField, Context) -> [PrivDataSourceDesc])
-> [(PrivDataField, Context)] -> [[PrivDataSourceDesc]]
forall a b. (a -> b) -> [a] -> [b]
map (PrivDataField, Context) -> [PrivDataSourceDesc]
mkrow [(PrivDataField, Context)]
missing

		PrivDataSourceDesc -> IO ()
section PrivDataSourceDesc
"How to set missing data:"
		(PrivDataSourceDesc -> IO ()) -> [PrivDataSourceDesc] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ PrivDataSourceDesc -> IO ()
putStrLn ([PrivDataSourceDesc] -> IO ()) -> [PrivDataSourceDesc] -> IO ()
forall a b. (a -> b) -> a -> b
$ [(PrivDataField, Context, Maybe PrivDataSourceDesc)]
-> [PrivDataSourceDesc]
showSet ([(PrivDataField, Context, Maybe PrivDataSourceDesc)]
 -> [PrivDataSourceDesc])
-> [(PrivDataField, Context, Maybe PrivDataSourceDesc)]
-> [PrivDataSourceDesc]
forall a b. (a -> b) -> a -> b
$
			((PrivDataField, Context)
 -> (PrivDataField, Context, Maybe PrivDataSourceDesc))
-> [(PrivDataField, Context)]
-> [(PrivDataField, Context, Maybe PrivDataSourceDesc)]
forall a b. (a -> b) -> [a] -> [b]
map (\(PrivDataField
f, Context
c) -> (PrivDataField
f, Context
c, Maybe (Maybe PrivDataSourceDesc) -> Maybe PrivDataSourceDesc
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Maybe (Maybe PrivDataSourceDesc) -> Maybe PrivDataSourceDesc)
-> Maybe (Maybe PrivDataSourceDesc) -> Maybe PrivDataSourceDesc
forall a b. (a -> b) -> a -> b
$ (PrivDataField, Context)
-> Map (PrivDataField, Context) (Maybe PrivDataSourceDesc)
-> Maybe (Maybe PrivDataSourceDesc)
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup (PrivDataField
f, Context
c) Map (PrivDataField, Context) (Maybe PrivDataSourceDesc)
descmap)) [(PrivDataField, Context)]
missing
  where
	header :: [PrivDataSourceDesc]
header = [PrivDataSourceDesc
"Field", PrivDataSourceDesc
"Context", PrivDataSourceDesc
"Used by"]
	mkrow :: (PrivDataField, Context) -> [PrivDataSourceDesc]
mkrow k :: (PrivDataField, Context)
k@(PrivDataField
field, Context PrivDataSourceDesc
context) =
		[ PrivDataSourceDesc -> PrivDataSourceDesc
shellEscape (PrivDataSourceDesc -> PrivDataSourceDesc)
-> PrivDataSourceDesc -> PrivDataSourceDesc
forall a b. (a -> b) -> a -> b
$ PrivDataField -> PrivDataSourceDesc
forall a. Show a => a -> PrivDataSourceDesc
show PrivDataField
field
		, PrivDataSourceDesc -> PrivDataSourceDesc
shellEscape PrivDataSourceDesc
context
		, PrivDataSourceDesc -> [PrivDataSourceDesc] -> PrivDataSourceDesc
forall a. [a] -> [[a]] -> [a]
intercalate PrivDataSourceDesc
", " ([PrivDataSourceDesc] -> PrivDataSourceDesc)
-> [PrivDataSourceDesc] -> PrivDataSourceDesc
forall a b. (a -> b) -> a -> b
$ [PrivDataSourceDesc] -> [PrivDataSourceDesc]
forall a. Ord a => [a] -> [a]
sort ([PrivDataSourceDesc] -> [PrivDataSourceDesc])
-> [PrivDataSourceDesc] -> [PrivDataSourceDesc]
forall a b. (a -> b) -> a -> b
$ [PrivDataSourceDesc]
-> Maybe [PrivDataSourceDesc] -> [PrivDataSourceDesc]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [PrivDataSourceDesc] -> [PrivDataSourceDesc])
-> Maybe [PrivDataSourceDesc] -> [PrivDataSourceDesc]
forall a b. (a -> b) -> a -> b
$ (PrivDataField, Context)
-> Map (PrivDataField, Context) [PrivDataSourceDesc]
-> Maybe [PrivDataSourceDesc]
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup (PrivDataField, Context)
k Map (PrivDataField, Context) [PrivDataSourceDesc]
usedby
		]
	usedby :: Map (PrivDataField, Context) [PrivDataSourceDesc]
usedby = [Host] -> Map (PrivDataField, Context) [PrivDataSourceDesc]
mkUsedByMap [Host]
hosts
	wantedmap :: PrivMap
wantedmap = [((PrivDataField, Context), PrivDataSourceDesc)] -> PrivMap
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([((PrivDataField, Context), PrivDataSourceDesc)] -> PrivMap)
-> [((PrivDataField, Context), PrivDataSourceDesc)] -> PrivMap
forall a b. (a -> b) -> a -> b
$ [(PrivDataField, Context)]
-> [PrivDataSourceDesc]
-> [((PrivDataField, Context), PrivDataSourceDesc)]
forall a b. [a] -> [b] -> [(a, b)]
zip (Map (PrivDataField, Context) [PrivDataSourceDesc]
-> [(PrivDataField, Context)]
forall k a. Map k a -> [k]
M.keys Map (PrivDataField, Context) [PrivDataSourceDesc]
usedby) (PrivDataSourceDesc -> [PrivDataSourceDesc]
forall a. a -> [a]
repeat PrivDataSourceDesc
"")
	descmap :: Map (PrivDataField, Context) (Maybe PrivDataSourceDesc)
descmap = [Map (PrivDataField, Context) (Maybe PrivDataSourceDesc)]
-> Map (PrivDataField, Context) (Maybe PrivDataSourceDesc)
forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
f (Map k a) -> Map k a
M.unions ([Map (PrivDataField, Context) (Maybe PrivDataSourceDesc)]
 -> Map (PrivDataField, Context) (Maybe PrivDataSourceDesc))
-> [Map (PrivDataField, Context) (Maybe PrivDataSourceDesc)]
-> Map (PrivDataField, Context) (Maybe PrivDataSourceDesc)
forall a b. (a -> b) -> a -> b
$ (Host -> Map (PrivDataField, Context) (Maybe PrivDataSourceDesc))
-> [Host]
-> [Map (PrivDataField, Context) (Maybe PrivDataSourceDesc)]
forall a b. (a -> b) -> [a] -> [b]
map (Host
-> (Maybe PrivDataSourceDesc -> Maybe PrivDataSourceDesc)
-> Map (PrivDataField, Context) (Maybe PrivDataSourceDesc)
forall a.
Host
-> (Maybe PrivDataSourceDesc -> a)
-> Map (PrivDataField, Context) a
`mkPrivDataMap` Maybe PrivDataSourceDesc -> Maybe PrivDataSourceDesc
forall a. a -> a
id) [Host]
hosts
	section :: PrivDataSourceDesc -> IO ()
section PrivDataSourceDesc
desc = PrivDataSourceDesc -> IO ()
putStrLn (PrivDataSourceDesc -> IO ()) -> PrivDataSourceDesc -> IO ()
forall a b. (a -> b) -> a -> b
$ PrivDataSourceDesc
"\n" PrivDataSourceDesc -> PrivDataSourceDesc -> PrivDataSourceDesc
forall a. [a] -> [a] -> [a]
++ PrivDataSourceDesc
desc
	showtable :: [[PrivDataSourceDesc]] -> IO ()
showtable [[PrivDataSourceDesc]]
rows = do
		PrivDataSourceDesc -> IO ()
putStr (PrivDataSourceDesc -> IO ()) -> PrivDataSourceDesc -> IO ()
forall a b. (a -> b) -> a -> b
$ [PrivDataSourceDesc] -> PrivDataSourceDesc
unlines ([PrivDataSourceDesc] -> PrivDataSourceDesc)
-> [PrivDataSourceDesc] -> PrivDataSourceDesc
forall a b. (a -> b) -> a -> b
$ [[PrivDataSourceDesc]] -> [PrivDataSourceDesc]
formatTable ([[PrivDataSourceDesc]] -> [PrivDataSourceDesc])
-> [[PrivDataSourceDesc]] -> [PrivDataSourceDesc]
forall a b. (a -> b) -> a -> b
$ [PrivDataSourceDesc]
-> [[PrivDataSourceDesc]] -> [[PrivDataSourceDesc]]
tableWithHeader [PrivDataSourceDesc]
header [[PrivDataSourceDesc]]
rows

mkUsedByMap :: [Host] -> M.Map (PrivDataField, Context) [HostName]
mkUsedByMap :: [Host] -> Map (PrivDataField, Context) [PrivDataSourceDesc]
mkUsedByMap = ([PrivDataSourceDesc]
 -> [PrivDataSourceDesc] -> [PrivDataSourceDesc])
-> [Map (PrivDataField, Context) [PrivDataSourceDesc]]
-> Map (PrivDataField, Context) [PrivDataSourceDesc]
forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
(a -> a -> a) -> f (Map k a) -> Map k a
M.unionsWith [PrivDataSourceDesc]
-> [PrivDataSourceDesc] -> [PrivDataSourceDesc]
forall a. [a] -> [a] -> [a]
(++) ([Map (PrivDataField, Context) [PrivDataSourceDesc]]
 -> Map (PrivDataField, Context) [PrivDataSourceDesc])
-> ([Host] -> [Map (PrivDataField, Context) [PrivDataSourceDesc]])
-> [Host]
-> Map (PrivDataField, Context) [PrivDataSourceDesc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Host -> Map (PrivDataField, Context) [PrivDataSourceDesc])
-> [Host] -> [Map (PrivDataField, Context) [PrivDataSourceDesc]]
forall a b. (a -> b) -> [a] -> [b]
map (\Host
h -> Host
-> (Maybe PrivDataSourceDesc -> [PrivDataSourceDesc])
-> Map (PrivDataField, Context) [PrivDataSourceDesc]
forall a.
Host
-> (Maybe PrivDataSourceDesc -> a)
-> Map (PrivDataField, Context) a
mkPrivDataMap Host
h ((Maybe PrivDataSourceDesc -> [PrivDataSourceDesc])
 -> Map (PrivDataField, Context) [PrivDataSourceDesc])
-> (Maybe PrivDataSourceDesc -> [PrivDataSourceDesc])
-> Map (PrivDataField, Context) [PrivDataSourceDesc]
forall a b. (a -> b) -> a -> b
$ [PrivDataSourceDesc]
-> Maybe PrivDataSourceDesc -> [PrivDataSourceDesc]
forall a b. a -> b -> a
const [Host -> PrivDataSourceDesc
hostName Host
h])

mkPrivDataMap :: Host -> (Maybe PrivDataSourceDesc -> a) -> M.Map (PrivDataField, Context) a
mkPrivDataMap :: forall a.
Host
-> (Maybe PrivDataSourceDesc -> a)
-> Map (PrivDataField, Context) a
mkPrivDataMap Host
host Maybe PrivDataSourceDesc -> a
mkv = [((PrivDataField, Context), a)] -> Map (PrivDataField, Context) a
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([((PrivDataField, Context), a)] -> Map (PrivDataField, Context) a)
-> [((PrivDataField, Context), a)]
-> Map (PrivDataField, Context) a
forall a b. (a -> b) -> a -> b
$
	((PrivDataField, Maybe PrivDataSourceDesc, HostContext)
 -> ((PrivDataField, Context), a))
-> [(PrivDataField, Maybe PrivDataSourceDesc, HostContext)]
-> [((PrivDataField, Context), a)]
forall a b. (a -> b) -> [a] -> [b]
map (\(PrivDataField
f, Maybe PrivDataSourceDesc
d, HostContext
c) -> ((PrivDataField
f, HostContext -> PrivDataSourceDesc -> Context
mkHostContext HostContext
c (Host -> PrivDataSourceDesc
hostName Host
host)), Maybe PrivDataSourceDesc -> a
mkv Maybe PrivDataSourceDesc
d))
		(Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> [(PrivDataField, Maybe PrivDataSourceDesc, HostContext)]
forall a. Set a -> [a]
S.toList (Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
 -> [(PrivDataField, Maybe PrivDataSourceDesc, HostContext)])
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> [(PrivDataField, Maybe PrivDataSourceDesc, HostContext)]
forall a b. (a -> b) -> a -> b
$ PrivInfo
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
fromPrivInfo (PrivInfo
 -> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext))
-> PrivInfo
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
forall a b. (a -> b) -> a -> b
$ Info -> PrivInfo
forall v. IsInfo v => Info -> v
fromInfo (Info -> PrivInfo) -> Info -> PrivInfo
forall a b. (a -> b) -> a -> b
$ Host -> Info
hostInfo Host
host)

setPrivDataTo :: PrivDataField -> Context -> PrivData -> IO ()
setPrivDataTo :: PrivDataField -> Context -> PrivData -> IO ()
setPrivDataTo PrivDataField
field Context
context (PrivData PrivDataSourceDesc
value) = do
	(PrivMap -> PrivMap) -> IO ()
modifyPrivData PrivMap -> PrivMap
set
	PrivDataSourceDesc -> IO ()
putStrLn PrivDataSourceDesc
"Private data set."
  where
	set :: PrivMap -> PrivMap
set = (PrivDataField, Context)
-> PrivDataSourceDesc -> PrivMap -> PrivMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert (PrivDataField
field, Context
context) PrivDataSourceDesc
value

modifyPrivData :: (PrivMap -> PrivMap) -> IO ()
modifyPrivData :: (PrivMap -> PrivMap) -> IO ()
modifyPrivData PrivMap -> PrivMap
f = (PrivMap -> (PrivMap, ())) -> IO ()
forall a. (PrivMap -> (PrivMap, a)) -> IO a
modifyPrivData' (\PrivMap
m -> (PrivMap -> PrivMap
f PrivMap
m, ()))

modifyPrivData' :: (PrivMap -> (PrivMap, a)) -> IO a
modifyPrivData' :: forall a. (PrivMap -> (PrivMap, a)) -> IO a
modifyPrivData' PrivMap -> (PrivMap, a)
f = do
	IO ()
makePrivDataDir
	PrivMap
m <- IO PrivMap
decryptPrivData
	let (PrivMap
m', a
r) = PrivMap -> (PrivMap, a)
f PrivMap
m
	PrivDataSourceDesc
privdata <- IO PrivDataSourceDesc
privDataFile
	PrivDataSourceDesc -> PrivDataSourceDesc -> IO ()
gpgEncrypt PrivDataSourceDesc
privdata (PrivMap -> PrivDataSourceDesc
forall a. Show a => a -> PrivDataSourceDesc
show PrivMap
m')
	IO Bool -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO Bool -> IO ()) -> IO Bool -> IO ()
forall a b. (a -> b) -> a -> b
$ PrivDataSourceDesc -> [CommandParam] -> IO Bool
boolSystem PrivDataSourceDesc
"git" [PrivDataSourceDesc -> CommandParam
Param PrivDataSourceDesc
"add", PrivDataSourceDesc -> CommandParam
File PrivDataSourceDesc
privdata]
	a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
r

decryptPrivData :: IO PrivMap
decryptPrivData :: IO PrivMap
decryptPrivData = PrivDataSourceDesc -> PrivMap
readPrivData (PrivDataSourceDesc -> PrivMap)
-> IO PrivDataSourceDesc -> IO PrivMap
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (PrivDataSourceDesc -> IO PrivDataSourceDesc
gpgDecrypt (PrivDataSourceDesc -> IO PrivDataSourceDesc)
-> IO PrivDataSourceDesc -> IO PrivDataSourceDesc
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO PrivDataSourceDesc
privDataFile)

readPrivData :: String -> PrivMap
readPrivData :: PrivDataSourceDesc -> PrivMap
readPrivData = PrivMap -> Maybe PrivMap -> PrivMap
forall a. a -> Maybe a -> a
fromMaybe PrivMap
forall k a. Map k a
M.empty (Maybe PrivMap -> PrivMap)
-> (PrivDataSourceDesc -> Maybe PrivMap)
-> PrivDataSourceDesc
-> PrivMap
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrivDataSourceDesc -> Maybe PrivMap
forall a. Read a => PrivDataSourceDesc -> Maybe a
readish

readPrivDataFile :: FilePath -> IO PrivMap
readPrivDataFile :: PrivDataSourceDesc -> IO PrivMap
readPrivDataFile PrivDataSourceDesc
f = PrivDataSourceDesc -> PrivMap
readPrivData (PrivDataSourceDesc -> PrivMap)
-> IO PrivDataSourceDesc -> IO PrivMap
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PrivDataSourceDesc -> IO PrivDataSourceDesc
readFileStrict PrivDataSourceDesc
f

makePrivDataDir :: IO ()
makePrivDataDir :: IO ()
makePrivDataDir = Bool -> PrivDataSourceDesc -> IO ()
createDirectoryIfMissing Bool
False PrivDataSourceDesc
privDataDir

newtype PrivInfo = PrivInfo
	{ PrivInfo
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
fromPrivInfo :: S.Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext) }
	deriving (PrivInfo -> PrivInfo -> Bool
(PrivInfo -> PrivInfo -> Bool)
-> (PrivInfo -> PrivInfo -> Bool) -> Eq PrivInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PrivInfo -> PrivInfo -> Bool
== :: PrivInfo -> PrivInfo -> Bool
$c/= :: PrivInfo -> PrivInfo -> Bool
/= :: PrivInfo -> PrivInfo -> Bool
Eq, Eq PrivInfo
Eq PrivInfo
-> (PrivInfo -> PrivInfo -> Ordering)
-> (PrivInfo -> PrivInfo -> Bool)
-> (PrivInfo -> PrivInfo -> Bool)
-> (PrivInfo -> PrivInfo -> Bool)
-> (PrivInfo -> PrivInfo -> Bool)
-> (PrivInfo -> PrivInfo -> PrivInfo)
-> (PrivInfo -> PrivInfo -> PrivInfo)
-> Ord PrivInfo
PrivInfo -> PrivInfo -> Bool
PrivInfo -> PrivInfo -> Ordering
PrivInfo -> PrivInfo -> PrivInfo
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PrivInfo -> PrivInfo -> Ordering
compare :: PrivInfo -> PrivInfo -> Ordering
$c< :: PrivInfo -> PrivInfo -> Bool
< :: PrivInfo -> PrivInfo -> Bool
$c<= :: PrivInfo -> PrivInfo -> Bool
<= :: PrivInfo -> PrivInfo -> Bool
$c> :: PrivInfo -> PrivInfo -> Bool
> :: PrivInfo -> PrivInfo -> Bool
$c>= :: PrivInfo -> PrivInfo -> Bool
>= :: PrivInfo -> PrivInfo -> Bool
$cmax :: PrivInfo -> PrivInfo -> PrivInfo
max :: PrivInfo -> PrivInfo -> PrivInfo
$cmin :: PrivInfo -> PrivInfo -> PrivInfo
min :: PrivInfo -> PrivInfo -> PrivInfo
Ord, Int -> PrivInfo -> PrivDataSourceDesc -> PrivDataSourceDesc
[PrivInfo] -> PrivDataSourceDesc -> PrivDataSourceDesc
PrivInfo -> PrivDataSourceDesc
(Int -> PrivInfo -> PrivDataSourceDesc -> PrivDataSourceDesc)
-> (PrivInfo -> PrivDataSourceDesc)
-> ([PrivInfo] -> PrivDataSourceDesc -> PrivDataSourceDesc)
-> Show PrivInfo
forall a.
(Int -> a -> PrivDataSourceDesc -> PrivDataSourceDesc)
-> (a -> PrivDataSourceDesc)
-> ([a] -> PrivDataSourceDesc -> PrivDataSourceDesc)
-> Show a
$cshowsPrec :: Int -> PrivInfo -> PrivDataSourceDesc -> PrivDataSourceDesc
showsPrec :: Int -> PrivInfo -> PrivDataSourceDesc -> PrivDataSourceDesc
$cshow :: PrivInfo -> PrivDataSourceDesc
show :: PrivInfo -> PrivDataSourceDesc
$cshowList :: [PrivInfo] -> PrivDataSourceDesc -> PrivDataSourceDesc
showList :: [PrivInfo] -> PrivDataSourceDesc -> PrivDataSourceDesc
Show, Typeable, NonEmpty PrivInfo -> PrivInfo
PrivInfo -> PrivInfo -> PrivInfo
(PrivInfo -> PrivInfo -> PrivInfo)
-> (NonEmpty PrivInfo -> PrivInfo)
-> (forall b. Integral b => b -> PrivInfo -> PrivInfo)
-> Semigroup PrivInfo
forall b. Integral b => b -> PrivInfo -> PrivInfo
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: PrivInfo -> PrivInfo -> PrivInfo
<> :: PrivInfo -> PrivInfo -> PrivInfo
$csconcat :: NonEmpty PrivInfo -> PrivInfo
sconcat :: NonEmpty PrivInfo -> PrivInfo
$cstimes :: forall b. Integral b => b -> PrivInfo -> PrivInfo
stimes :: forall b. Integral b => b -> PrivInfo -> PrivInfo
Sem.Semigroup, Semigroup PrivInfo
PrivInfo
Semigroup PrivInfo
-> PrivInfo
-> (PrivInfo -> PrivInfo -> PrivInfo)
-> ([PrivInfo] -> PrivInfo)
-> Monoid PrivInfo
[PrivInfo] -> PrivInfo
PrivInfo -> PrivInfo -> PrivInfo
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: PrivInfo
mempty :: PrivInfo
$cmappend :: PrivInfo -> PrivInfo -> PrivInfo
mappend :: PrivInfo -> PrivInfo -> PrivInfo
$cmconcat :: [PrivInfo] -> PrivInfo
mconcat :: [PrivInfo] -> PrivInfo
Monoid)

-- PrivInfo always propagates out of containers, so that propellor
-- can see which hosts need it.
instance IsInfo PrivInfo where
	propagateInfo :: PrivInfo -> PropagateInfo
propagateInfo PrivInfo
_ = PropagateInfo
PropagatePrivData

-- | Sets the context of any privdata that uses HostContext to the
-- provided name.
forceHostContext :: String -> PrivInfo -> PrivInfo
forceHostContext :: PrivDataSourceDesc -> PrivInfo -> PrivInfo
forceHostContext PrivDataSourceDesc
name PrivInfo
i = Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> PrivInfo
PrivInfo (Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
 -> PrivInfo)
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> PrivInfo
forall a b. (a -> b) -> a -> b
$ ((PrivDataField, Maybe PrivDataSourceDesc, HostContext)
 -> (PrivDataField, Maybe PrivDataSourceDesc, HostContext))
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
forall b a. Ord b => (a -> b) -> Set a -> Set b
S.map (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
go (PrivInfo
-> Set (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
fromPrivInfo PrivInfo
i)
  where
	go :: (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
-> (PrivDataField, Maybe PrivDataSourceDesc, HostContext)
go (PrivDataField
f, Maybe PrivDataSourceDesc
d, HostContext PrivDataSourceDesc -> Context
ctx) = (PrivDataField
f, Maybe PrivDataSourceDesc
d, (PrivDataSourceDesc -> Context) -> HostContext
HostContext (Context -> PrivDataSourceDesc -> Context
forall a b. a -> b -> a
const (Context -> PrivDataSourceDesc -> Context)
-> Context -> PrivDataSourceDesc -> Context
forall a b. (a -> b) -> a -> b
$ PrivDataSourceDesc -> Context
ctx PrivDataSourceDesc
name))