{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} module HNormalise.Config ( Config(..) , loadConfig ) where -------------------------------------------------------------------------------- import Control.Monad (mplus) import Data.Aeson (defaultOptions) import Data.Aeson.TH (deriveJSON) import qualified Data.ByteString as B import Data.Monoid ((<>)) import Data.Text (Text) import qualified Data.Yaml as Y import System.Directory -------------------------------------------------------------------------------- data Config = Config { listenPort :: !(Maybe Int) -- ^ port for incoming messages , listenHost :: !(Maybe Text) -- ^ binding to this host specification (TODO: needs support for HostPreference) , successPort :: !(Maybe Int) -- ^ port to send rsyslog with successfully parsed and normalised msg part , successHost :: !(Maybe Text) -- ^ host to send normalised data to , failPort :: !(Maybe Int) -- ^ port to send rsyslog messges that failed to parse , failHost :: !(Maybe Text) -- ^ host to send original data to when parsing failed } deriving (Show) -------------------------------------------------------------------------------- instance Monoid Config where mempty = Config Nothing Nothing Nothing Nothing Nothing Nothing mappend l r = Config { listenPort = listenPort l `mplus` listenPort r , listenHost = listenHost l `mplus` listenHost r , successPort = successPort l `mplus` successPort r , successHost = successHost l `mplus` successHost r , failPort = failPort l `mplus` failPort r , failHost = failHost l `mplus` failHost r } -------------------------------------------------------------------------------- defaultConfig = Config { listenPort = Just 4019 , listenHost = Just "localhost" , successPort = Just 26002 , successHost = Just "localhost" , failPort = Just 4018 , failHost = Just "localhost" } -------------------------------------------------------------------------------- systemConfigFileLocation :: FilePath systemConfigFileLocation = "/etc/hnormalise.yaml" -------------------------------------------------------------------------------- readConfig :: FilePath -> IO Config readConfig fp = do exists <- doesFileExist fp if exists then do contents <- B.readFile fp case Y.decodeEither contents of Left err -> error $ "HNormalise.Config.readConfig: " ++ err Right config -> return (config :: Config) else return mempty -------------------------------------------------------------------------------- loadConfig :: Maybe FilePath -> IO Config loadConfig fp = do userConfig <- case fp of Just fp' -> readConfig fp' Nothing -> return mempty systemConfig <- readConfig systemConfigFileLocation return $ userConfig <> systemConfig <> defaultConfig -------------------------------------------------------------------------------- $(deriveJSON defaultOptions ''Config)