configurator-pg: Reduced parser for configurator-ng config files

[ bsd3, configuration, data, library ] [ Propose Tags ]

This module provides a simplified and updated interface to the configuration file format of configurator and configurator-ng. Its aim is primarily to allow updating programs that depend on configurator-ng to new versions of GHC without changing the configuration file format.


[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

Versions [RSS] 0.1.0.0, 0.1.0.1, 0.1.0.2, 0.1.0.3, 0.1.0.4, 0.1.0.5, 0.1.0.6, 0.2.0, 0.2.1, 0.2.2, 0.2.3, 0.2.4, 0.2.5, 0.2.6, 0.2.7, 0.2.8, 0.2.9, 0.2.10
Change log CHANGELOG.md
Dependencies base (>=4.9 && <4.15), containers (>=0.5.6.2 && <0.7), megaparsec (>=7.0.0 && <9.1), protolude (>=0.1.10 && <0.4), scientific (>=0.3.4.9 && <0.4), text (>=1.2.2.2 && <1.3) [details]
License BSD-3-Clause
Copyright Copyright 2011 MailRank, Inc. Copyright 2011-2014 Bryan O'Sullivan Copyright 2015-2016 Leon P Smith Copyright 2019 Robert Vollmert
Author Robert Vollmert
Maintainer rob@vllmrt.net
Category Configuration, Data
Home page https://github.com/robx/configurator-pg
Bug tracker https://github.com/robx/configurator-pg/issues
Uploaded by vollmert at 2020-10-26T10:46:06Z
Distributions Arch:0.2.9, LTSHaskell:0.2.10, NixOS:0.2.10, Stackage:0.2.10
Reverse Dependencies 1 direct, 2 indirect [details]
Downloads 6836 total (86 in the last 30 days)
Rating 2.0 (votes: 1) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2020-10-26 [all 1 reports]

Readme for configurator-pg-0.2.5

[back to package description]

What is this?

This is a simplified version of the resting configurator-ng, aimed particularly to offer users of configurator-ng such as PostgREST an easy path to migrate to a package that compiles with modern GHC versions and that continues to read existing configuration files.

Changes

configurator-pg skips some of configurator-ng's features, and changes the API in other places:

  • No configuration file reloading.
  • Simplified parsing API:
    • There is no type-class based value parsing; you need to supply explicit value parsers.
    • There's only load to read and evaluate a configuration file, and runParser to extract configuration values.
  • Simpler error handling and improved logging of parse errors.
  • Simplified handling of configuration subsets. There's subassocs and the unit tests pass, but the author didn't attempt to understand the original implementation fully.

Credits

The original configurator-ng is due to MailRank, Inc., Bryan O'Sullivan and Leon P Smith.

The low-level parser (Data.Configurator.Syntax) was initially mostly unchanged, but has since been rewritten with Megaparsec for better error messages. The evaluation (Data.Configurator.Load) is still close to the original. The high-level parser (Data.Configurator.Parser) is original.

File format

In short, the file format supports:

  • A simple but flexible configuration language that supports several of the most commonly needed types of data, along with interpolation of strings from the configuration or the system environment (e.g. $(HOME)).

  • An import directive allows the configuration of a complex application to be split across several smaller files, or common configuration data to be shared across several applications.

The format is more fully documented in the packages configurator and configurator-ng.

Here's an example:

# listen address
hostname = "localhost"
port = 8000

logdir = "$(HOME)/logs"
logfile = "$(logdir)/log.txt"
loglevels = [1, 4, 5]

users {
  alice = "alice@example.com"
  bob   = "bob@example.com"
}

# passwords.txt might contain
#   alice = "12345"
#   bob   = "sesame"
passwords {
  import "secrets/passwords.txt"
}

Usage

The following code can be used to parse the example above.

import Data.Configurator

data Settings = Settings
  { hostname  :: Text
  , port      :: Int
  , logfile   :: Maybe FilePath
  , loglevels :: Maybe [Int]
  , users     :: [(Text, Text)]
  , passwords :: [(Text, Text)]
  }

settingsParser :: Parser Config Settings
settingsParser =
  Settings
    <$> required "hostname" string
    <*> (Maybe.withDefault 1234 <$> optional "port" int)
    <*> optional "logfile" (pack <$> string)
    <*> optional "loglevels" (list int)
    <*> subassocs "users" string
    <*> subassocs "passwords" string

loadSettings :: IO Settings
loadSettings = do
  cfg <- load "settings.cfg"
  case runParser settingsParser cfg of
    Left err       -> die $ "reading config: " <> err
    Right settings -> return settings

Though note that for no apparent reason, subassocs returns the full key, whence the parsed list of users will be

    [ ("users.alice", "alice@example.com")
    , ("users.bob", "bob@example.com")
    ]