diff options
author | Daniil Baturin <daniil@baturin.org> | 2016-12-14 10:21:27 +0600 |
---|---|---|
committer | Daniil Baturin <daniil@baturin.org> | 2016-12-14 10:21:27 +0600 |
commit | 42307e6b1a240f6378ab309b45ee308e97b5ff1a (patch) | |
tree | c9ac6bdbeb68e422ef78429195654676675a3833 | |
parent | a3c11884b97e89e93ac55f47c0d9c412b645ba5d (diff) | |
download | vyconf-42307e6b1a240f6378ab309b45ee308e97b5ff1a.tar.gz vyconf-42307e6b1a240f6378ab309b45ee308e97b5ff1a.zip |
T210: use TOML for the vyconf config file.
Add an example of the file too.
-rw-r--r-- | _oasis | 4 | ||||
-rw-r--r-- | data/examples/vyconfd.conf | 17 | ||||
-rw-r--r-- | src/vyconf_config.ml | 66 | ||||
-rw-r--r-- | src/vyconf_config.mli | 7 |
4 files changed, 87 insertions, 7 deletions
@@ -53,7 +53,7 @@ Library "vyconf_config" Path: src Modules: Vyconf_config FindlibParent: vyconf - BuildDepends: ppx_deriving_yojson + BuildDepends: toml, ppx_deriving.show Library "message" Path: src @@ -65,7 +65,7 @@ Executable "vyconfd" Path: src MainIs: vyconfd.ml CompiledObject: best - BuildDepends: ppx_deriving.runtime, ppx_deriving_yojson.runtime, lwt, lwt.unix, lwt.ppx, vyconf + BuildDepends: ppx_deriving.runtime, ppx_deriving_yojson.runtime, lwt, lwt.unix, lwt.ppx, toml, vyconf Executable "vytree_test" Path: test diff --git a/data/examples/vyconfd.conf b/data/examples/vyconfd.conf new file mode 100644 index 0000000..85a4523 --- /dev/null +++ b/data/examples/vyconfd.conf @@ -0,0 +1,17 @@ +[appliance] + +name = "Test Appliance" + +data_dir = "/usr/share/testappliance" +program_dir = "/usr/libexec/testappliance" +config_dir = "/etc/testappliance" + +# paths relative to config_dir +primary_config = "config.boot" +fallback_config = "config.failsafe" + +[vyconf] + +socket = "/var/run/vyconfd.sock" +pid_file = "/var/run/vyconfd.pid" +log_file = "/var/log/vyconfd.log" diff --git a/src/vyconf_config.ml b/src/vyconf_config.ml index 92fcbb0..21c23ee 100644 --- a/src/vyconf_config.ml +++ b/src/vyconf_config.ml @@ -1,14 +1,72 @@ +exception Missing_field of string + type vyconf_config = { app_name: string; - app_dir: string; + data_dir: string; + program_dir: string; config_dir: string; primary_config: string; fallback_config: string; socket: string; -} [@@deriving yojson] + pid_file: string; + log_file: string option; +} [@@deriving show] + +(* XXX: there should be a better way than to fully initialize it + with garbage just to update it later *) +let empty_config = { + app_name = ""; + data_dir = ""; + program_dir = ""; + config_dir = ""; + primary_config = ""; + fallback_config = ""; + socket = ""; + pid_file = ""; + log_file = None; +} + + +(* XXX: We assume that nesting in TOML config files never goes beyond two levels *) + +let get_field conf tbl_name field_name = + (* NB: TomlLenses module uses "table" and "field" names for function names, + hence tbl_name and field_name + *) + TomlLenses.(get conf (key tbl_name |-- table |-- key field_name |-- string)) + +let mandatory_field conf table field = + let value = get_field conf table field in + match value with + | Some value -> value + | None -> raise @@ Missing_field (Printf.sprintf "Invalid config: Missing mandatory field \"%s\" in section [%s]" field table) +let optional_field default conf table field = + let value = get_field conf table field in + match value with + | Some value -> value + | None -> default let load filename = - try Yojson.Safe.from_file filename |> vyconf_config_of_yojson - with Sys_error msg -> Result.Error msg + try + let open Defaults in + let conf_toml = Toml.Parser.from_filename filename |> Toml.Parser.unsafe in + let conf = empty_config in + (* Mandatory fields *) + let conf = {conf with app_name = mandatory_field conf_toml "appliance" "name"} in + let conf = {conf with data_dir = mandatory_field conf_toml "appliance" "data_dir"} in + let conf = {conf with config_dir = mandatory_field conf_toml "appliance" "config_dir"} in + let conf = {conf with program_dir = mandatory_field conf_toml "appliance" "program_dir"} in + let conf = {conf with primary_config = mandatory_field conf_toml "appliance" "primary_config"} in + let conf = {conf with fallback_config = mandatory_field conf_toml "appliance" "fallback_config"} in + (* Optional fields *) + let conf = {conf with pid_file = optional_field defaults.pid_file conf_toml "vyconf" "pid_file"} in + let conf = {conf with socket = optional_field defaults.socket conf_toml "vyconf" "socket"} in + (* log_file is already string option, so we don't need to unwrap *) + let conf = {conf with log_file = get_field conf_toml "vyconf" "log_file"} in + Result.Ok conf + with + | Sys_error msg -> Result.Error msg + | Toml.Parser.Error (msg, _) -> Result.Error msg +let dump = show_vyconf_config diff --git a/src/vyconf_config.mli b/src/vyconf_config.mli index 30d8ea7..bd70652 100644 --- a/src/vyconf_config.mli +++ b/src/vyconf_config.mli @@ -1,10 +1,15 @@ type vyconf_config = { app_name: string; - app_dir: string; + data_dir: string; + program_dir: string; config_dir: string; primary_config: string; fallback_config: string; socket: string; + pid_file: string; + log_file: string option; } val load : string -> (vyconf_config, string) Result.result + +val dump : vyconf_config -> string |