{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Puppet.Preferences (
dfPreferences
, HasPreferences(..)
, Preferences(Preferences)
, PuppetDirPaths
, HasPuppetDirPaths(..)
) where
import Control.Lens
import Control.Monad (mzero)
import Data.Aeson
import qualified Data.HashMap.Strict as HM
import qualified Data.HashSet as HS
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import System.Posix (fileExist)
import qualified System.Log.Logger as LOG
import Puppet.Interpreter.Types
import Puppet.NativeTypes
import Puppet.NativeTypes.Helpers
import Puppet.Stdlib
import Puppet.Paths
import qualified Puppet.Puppetlabs as Puppetlabs
import Puppet.Utils
import PuppetDB.Dummy
data Preferences m = Preferences
{ _prefPuppetPaths :: PuppetDirPaths
, _prefPDB :: PuppetDBAPI m
, _prefNatTypes :: Container NativeTypeMethods -- ^ The list of native types.
, _prefExtFuncs :: Container ( [PValue] -> InterpreterMonad PValue )
, _prefHieraPath :: Maybe FilePath
, _prefIgnoredmodules :: HS.HashSet Text
, _prefStrictness :: Strictness
, _prefExtraTests :: Bool
, _prefKnownusers :: [Text]
, _prefKnowngroups :: [Text]
, _prefExternalmodules :: HS.HashSet Text
, _prefPuppetSettings :: Container Text
, _prefFactsOverride :: Container PValue
, _prefFactsDefault :: Container PValue
, _prefLogLevel :: LOG.Priority
}
data Defaults = Defaults
{ _dfKnownusers :: Maybe [Text]
, _dfKnowngroups :: Maybe [Text]
, _dfIgnoredmodules :: Maybe [Text]
, _dfStrictness :: Maybe Strictness
, _dfExtratests :: Maybe Bool
, _dfExternalmodules :: Maybe [Text]
, _dfPuppetSettings :: Maybe (Container Text)
, _dfFactsDefault :: Maybe (Container PValue)
, _dfFactsOverride :: Maybe (Container PValue)
} deriving Show
makeClassy ''Preferences
instance FromJSON Defaults where
parseJSON (Object v) = Defaults
<$> v .:? "knownusers"
<*> v .:? "knowngroups"
<*> v .:? "ignoredmodules"
<*> v .:? "strict"
<*> v .:? "extratests"
<*> v .:? "externalmodules"
<*> v .:? "settings"
<*> v .:? "factsdefault"
<*> v .:? "factsoverride"
parseJSON _ = mzero
-- | generate default preferences
dfPreferences :: FilePath
-> IO (Preferences IO)
dfPreferences basedir = do
let dirpaths = puppetPaths basedir
modulesdir = dirpaths ^. modulesPath
testdir = dirpaths ^. testPath
typenames <- fmap (map takeBaseName) (getFiles (T.pack modulesdir) "lib/puppet/type" ".rb")
defaults <- loadDefaults (testdir ++ "/defaults.yaml")
labsFunctions <- Puppetlabs.extFunctions modulesdir
let loadedTypes = HM.fromList (map defaulttype typenames)
return $ Preferences dirpaths
dummyPuppetDB (baseNativeTypes `HM.union` loadedTypes)
(HM.union stdlibFunctions labsFunctions)
(Just (basedir <> "/hiera.yaml"))
(getIgnoredmodules defaults)
(getStrictness defaults)
(getExtraTests defaults)
(getKnownusers defaults)
(getKnowngroups defaults)
(getExternalmodules defaults)
(getPuppetSettings dirpaths defaults)
(getFactsOverride defaults)
(getFactsDefault defaults)
LOG.NOTICE -- good default as INFO is quite noisy
loadDefaults :: FilePath -> IO (Maybe Defaults)
loadDefaults fp = do
p <- fileExist fp
if p then loadYamlFile fp else return Nothing
-- Utilities for getting default values from the yaml file
-- It provides (the same) static defaults (see the 'Nothing' case) when
-- no default yaml file or
-- not key/value for the option has been provided
getKnownusers :: Maybe Defaults -> [Text]
getKnownusers = fromMaybe ["mysql", "vagrant","nginx", "nagios", "postgres", "puppet", "root", "syslog", "www-data"] . (>>= _dfKnownusers)
getKnowngroups :: Maybe Defaults -> [Text]
getKnowngroups = fromMaybe ["adm", "syslog", "mysql", "nagios","postgres", "puppet", "root", "www-data", "postfix"] . (>>= _dfKnowngroups)
getStrictness :: Maybe Defaults -> Strictness
getStrictness = fromMaybe Permissive . (>>= _dfStrictness)
getIgnoredmodules :: Maybe Defaults -> HS.HashSet Text
getIgnoredmodules = maybe mempty HS.fromList . (>>= _dfIgnoredmodules)
getExtraTests :: Maybe Defaults -> Bool
getExtraTests = fromMaybe True . (>>= _dfExtratests)
getExternalmodules :: Maybe Defaults -> HS.HashSet Text
getExternalmodules = maybe mempty HS.fromList . (>>= _dfExternalmodules)
getPuppetSettings :: PuppetDirPaths -> Maybe Defaults -> Container Text
getPuppetSettings dirpaths = fromMaybe df . (>>= _dfPuppetSettings)
where
df :: Container Text
df = HM.fromList [ ("confdir", T.pack $ dirpaths^.baseDir)
, ("strict_variables", "true")
]
getFactsOverride :: Maybe Defaults -> Container PValue
getFactsOverride = fromMaybe mempty . (>>= _dfFactsOverride)
getFactsDefault :: Maybe Defaults -> Container PValue
getFactsDefault = fromMaybe mempty . (>>= _dfFactsDefault)