Configuration file feature
ExternalReality opened this issue · 4 comments
As a user I would like to be able to specify whether the database type, store path and database connection string get read from a configuration file or from the environment.
Implementing this brings up a few behavioral issues:
- What should Moo read by default, the environment or the config file?
- Configuration file by default with option to specify something like --config-file=[path] or --env (for environment)
- Environment default; --config-file=[path] optional argument
- What command line options specify the desired behavior?
- If the user chooses to read from a config file and does not specify a path where does Moo look?
- What configuration format(s) are acceptable? (?? YAML ??)
DBM_DATABASE_TYPE: "postgresql"
DBM_DATABASE: "a=beautiful; connection=string"
DBM_MIGRATION_STORE: "Path to a migration store"
A simple implementation using Data.Yaml in the applicative. (Data.Yaml is based on Aeson and the names haven't changed yet.)
module Moo.ConfigParser where
import Data.Yaml
import Moo.Core
parseConfigOptions :: FilePath -> IO ConfigData
parseConfigOptions configFilePath = do
configContents <- decodeFile configFilePath
case configContents of
Nothing -> error "Failed Parsing Yaml"
Just a -> return a
module Moo.Core where
import Control.Applicative ( (<$>), (<*>) )
import Data.Yaml ( FromJSON( parseJSON ), Value ( Object ), (.:) )
...
-- |ConfigOptions are those options read from configuration file
-- or environment.
data ConfigData = ConfigData { _dbTypeStr :: String
, _dbConnStr :: String
, _fileStorePath :: String
}
instance FromJSON ConfigData where
parseJSON (Object v) = ConfigData <$>
v .: "DBM_DATABASE_TYPE" <*>
v .: "DBM_DATABASE" <*>
v .: "DBM_MIGRATION_STORE"
parseJSON _ = mzero
module Moo.CommandInterface
...
commandOptions :: [ OptDescr (CommandOptions -> IO CommandOptions) ]
commandOptions = [ optionConfigFile
, optionTest
, optionNoAsk
]
optionConfigFile :: OptDescr (CommandOptions -> IO CommandOptions)
optionConfigFile = Option "c" ["config-file"]
(ReqArg (\arg opt ->
return opt { _configFilePath = Just arg }) "FILE")
"Specify location of configuration file"
The rest would depend on the answers to the questions above I suppose.
On the default behavior, I'd say look at the environment unless --config
is specified. If --config
is given and the config file doesn't exist or can't be read for any reason, that should constitute an error; otherwise, transparent fallback to the environment could be very, very confusing. As for the format, I think YAML would be the least jarring change as it is already the format used by the migration files. I'd be open to other format options (such as ini-style files as supported by the hsini
package), but at the moment I don't see how that could provide enough extra benefit to justify using two different formats.
Given your recent pull request, it looks like we can close this. Is there anything else that needs doing on this?
Yes, this issue can be closed.
Great! Thanks for contributing the feature! :)