module Web.Mackerel.Config
( Config(..)
, HostStatusConfig(..)
, loadConfig
, parseConfig
, loadClient
, mackerelRoot
, confFile
, pidFile
) where
import Data.Aeson
import Data.Aeson.Types (Value(..), Result(..), typeMismatch)
import Data.Default (Default(..))
import Data.List (isPrefixOf, isInfixOf)
import Data.Maybe (fromMaybe)
import qualified Data.Text as Text
import qualified Data.Text.IO as Text
import System.Directory (getHomeDirectory)
import System.FilePath ((</>))
import System.Info (os)
import Text.Toml (parseTomlDoc)
import Web.Mackerel.Client
import Web.Mackerel.Types.Host
data Config
= Config {
configApiBase :: Maybe String,
configApiKey :: Maybe String,
configRoot :: Maybe String,
configPidfile :: Maybe String,
configRoles :: Maybe [String],
configVerbose :: Maybe Bool,
configDiagnostic :: Maybe Bool,
configDisplayname :: Maybe String,
configHostStatus :: Maybe HostStatusConfig,
configHttpProxy :: Maybe String
} deriving (Eq, Show)
instance FromJSON Config where
parseJSON (Object o)
= Config <$> o .:? "apibase" <*> o .:? "apikey" <*> o .:? "root"
<*> o .:? "pidfile" <*> o .:? "roles" <*> o .:? "verbose"
<*> o .:? "diagnostic" <*> o .:? "display_name" <*> o .:? "host_status"
<*> o .:? "http_proxy"
parseJSON o = typeMismatch "Config" o
instance Default Config where
def = Config def def def def def def def def def def
data HostStatusConfig
= HostStatusConfig {
hostStatusOnStart :: Maybe HostStatus,
hostStatusOnStop :: Maybe HostStatus
} deriving (Eq, Show)
instance FromJSON HostStatusConfig where
parseJSON (Object o)
= HostStatusConfig <$> o .:? "on_start" <*> o .:? "on_stop"
parseJSON o = typeMismatch "HostStatusConfig" o
instance Default HostStatusConfig where
def = HostStatusConfig def def
agentName :: String
agentName = "mackerel-agent"
loadConfig :: IO (Either String Config)
loadConfig = parseConfig <$> (Text.readFile =<< confFile)
parseConfig :: Text.Text -> Either String Config
parseConfig cnt
= case parseTomlDoc "" cnt of
Left _ -> Left "toml parse error"
Right res -> case fromJSON $ toJSON res of
Error err -> Left err
Success r -> Right r
loadClient :: IO (Either String Client)
loadClient = fmap (\c -> def { apiKey = fromMaybe (apiKey def) $ configApiKey c,
apiBase = fromMaybe (apiBase def) $ configApiBase c }) <$> loadConfig
mackerelRoot :: IO FilePath
mackerelRoot | isBSD || isDarwin = getHomeDirectory >>= \home -> return $ home </> "Library" </> agentName
| isWindows = error "Windows is not supported yet."
| otherwise = return "/var/lib/mackerel-agent"
confFile :: IO FilePath
confFile | isLinux = return $ "/etc" </> agentName </> agentName ++ ".conf"
| otherwise = mackerelRoot >>= \root -> return $ root </> agentName ++ ".conf"
pidFile :: IO FilePath
pidFile | isLinux = return "/var/run/mackerel-agent.pid"
| otherwise = mackerelRoot >>= \root -> return $ root </> agentName ++ ".pid"
isBSD :: Bool
isBSD = "bsd" `isInfixOf` os
isDarwin :: Bool
isDarwin = os == "darwin"
isWindows :: Bool
isWindows = "mingw" `isPrefixOf` os
isLinux :: Bool
isLinux = not isBSD && not isDarwin && not isWindows