128 lines
3.5 KiB
Markdown
128 lines
3.5 KiB
Markdown
# Gmconfig - A JSON-SCHEMA-based configuration management support library
|
|
|
|
## Introduction
|
|
|
|
This library offers the basic support functions for the Gajumaru configuration
|
|
management subsystem. It is based on JSON-Schema, and includes, among other things:
|
|
|
|
* A reasonably complete JSON-Schema validator
|
|
* Validating user configurations against the schema
|
|
* In-service update of the user config
|
|
* Caching of the user config (and schema) as persistent terms
|
|
* Fast config lookups using key paths
|
|
* Lookups can handle both schema defaults and user-provided defaults
|
|
* Optional type coercion during validation
|
|
* Optional conversion of enums to atoms
|
|
* Optional extensions with custom validator funs
|
|
|
|
## JSON-Schema validator
|
|
|
|
The main thing the validator currently doesn't support is proper
|
|
management of complex sets of schemas and subSchemas. There are
|
|
some preparations made for supporting `"$id"` and uris, but this
|
|
is still incomplete. `"definitions"` and `"$ref"` properties are recognized.
|
|
|
|
As almost anything is theoretically possible with JSON-Schema,
|
|
there are surely other things that are unsupported.
|
|
|
|
### All standard data types
|
|
|
|
* `"null"`
|
|
* `"boolean"`
|
|
* `"integer"`
|
|
* `"number"`
|
|
* `"boolean"`
|
|
* `"string"`
|
|
* `"array"`
|
|
* `"object"`
|
|
|
|
### Dynamic properties
|
|
|
|
* `"if"`
|
|
* `"not"`
|
|
* `"oneOf"`
|
|
* `"anyOf"`
|
|
* `"allOf"`
|
|
|
|
### Static Properties
|
|
|
|
#### Array
|
|
|
|
* `"maxItems"`
|
|
* `"minItems"`
|
|
* `"uniqueItems"`
|
|
* `"prefixItems"`
|
|
* `"contains"` (`"minContains"`, `"maxContains"`)
|
|
|
|
#### Object
|
|
|
|
* `"properties"` (`"minProperties"`, `"maxProperties"`)
|
|
* `"patternProperties"`
|
|
* `"additionalProperties"`
|
|
* `"required"`
|
|
|
|
#### String
|
|
|
|
* `"pattern"`
|
|
* `"minLength"`
|
|
* `"maxLength"`
|
|
|
|
#### Number, Integer
|
|
|
|
* `"minimum"`
|
|
* `"maximum"`
|
|
* `"exclusiveMinimum"`
|
|
* `"exclusiveMinimum"`
|
|
* `"multipleOf"` (only if object is an integer)
|
|
|
|
### `"$updateSemantics"`
|
|
|
|
* `"replace"` (fully replaces any old data)
|
|
* `"merge"` (for objects, keeps and/or updates existing values)
|
|
* `"suggest"` (adds value if not already present)
|
|
|
|
### Custom validation options
|
|
|
|
Using `gmconfig_schema_utils:validate(Json, Schema, Opts)`, a few options are supported
|
|
to further enhance the validation (`Opts` is of type `map()`):
|
|
|
|
`coerce => boolean()` converts strings to integers, null and booleans when needed.
|
|
`enums_to_atoms => boolean()` converts enum strings to atoms
|
|
`extensions => map()` supports mapping `x-...` properties to custom validators.
|
|
|
|
#### Validator extensions
|
|
|
|
See the following test case:
|
|
```erlang
|
|
t_nested_refs() ->
|
|
S = read("data/nested_refs_schema.json"),
|
|
F = fun(Str, #{<<"tags">> := Tags}) ->
|
|
true = lists:any(
|
|
fun(T) ->
|
|
nomatch =/= string:prefix(Str, T)
|
|
end, Tags)
|
|
end,
|
|
Opts = #{extensions => #{<<"x-serialization">> => F}},
|
|
Vs = #{<<"tx">> => #{<<"from">> => <<"ak_good">>}},
|
|
Vf = #{<<"tx">> => #{<<"from">> => <<"ac_bad">>}},
|
|
validate(Vs, S, Opts),
|
|
fails(Vf, S, Opts, #{e => failing_schemas}),
|
|
ok.
|
|
```
|
|
This simulates an encoding extension, where the example fun here simply checks
|
|
if tags specified under the `x-serialization` property are prefixes of the
|
|
given string value.
|
|
|
|
In the test schema, we can see the following definition:
|
|
```json
|
|
"Pubkey": {
|
|
"type": "string",
|
|
"x-serialization": {
|
|
"tags": ["ak", "ct"]
|
|
}
|
|
```
|
|
|
|
Whenever the validator encounters an `x-...` property mapped to a validator fun,
|
|
this fun is called with the value and the schema part of the property. The return
|
|
value of the fun is ignored, and any normal return is treated as a validation success.
|