Skip to content

Commit

Permalink
Document the 'experimental.config.utils.schema' module (#4469)
Browse files Browse the repository at this point in the history
Resolves #4279.

Co-authored-by: Pavel Semyonov <[email protected]>
Co-authored-by: Elena Shebunyaeva <[email protected]>
  • Loading branch information
3 people authored Oct 22, 2024
1 parent f0695d1 commit f7d76f6
Show file tree
Hide file tree
Showing 33 changed files with 1,831 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
-- greeter.lua --
local log = require('log').new("greeter")
local schema = require('experimental.config.utils.schema')

local greeter_schema = schema.new('greeter', schema.record({
greeting = schema.scalar({
type = 'string',
allowed_values = { 'Hi', 'Hello' }
})
}))

local function validate(cfg)
if cfg.greeting then
assert(type(cfg.greeting) == "string", "'greeting' should be a string")
assert(cfg.greeting == "Hi" or cfg.greeting == "Hello", "'greeting' should be 'Hi' or 'Hello'")
end
greeter_schema:validate(cfg)
end

local function apply(cfg)
log.info("%s from the 'greeter' role!", cfg.greeting)
log.info("%s from the 'greeter' role!", greeter_schema:get(cfg, 'greeting'))
end

local function stop()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
-- http-api.lua --
local httpd
local json = require('json')
local schema = require('experimental.config.utils.schema')

local function validate(cfg)
if cfg.host then
assert(type(cfg.host) == "string", "'host' should be a string containing a valid IP address")
local function validate_host(host, w)
local host_pattern = "^(%d+)%.(%d+)%.(%d+)%.(%d+)$"
if not host:match(host_pattern) then
w.error("'host' should be a string containing a valid IP address, got %q", host)
end
if cfg.port then
assert(type(cfg.port) == "number", "'port' should be a number")
assert(cfg.port >= 1 and cfg.port <= 65535, "'port' should be between 1 and 65535")
end

local function validate_port(port, w)
if port <= 1 or port >= 65535 then
w.error("'port' should be between 1 and 65535, got %d", port)
end
end

local listen_address_schema = schema.new('listen_address', schema.record({
host = schema.scalar({
type = 'string',
validate = validate_host,
default = '127.0.0.1',
}),
port = schema.scalar({
type = 'integer',
validate = validate_port,
default = 8080,
}),
}))

local function validate(cfg)
listen_address_schema:validate(cfg)
end

local function apply(cfg)
if httpd then
httpd:stop()
end
httpd = require('http.server').new(cfg.host, cfg.port)
local cfg_with_defaults = listen_address_schema:apply_default(cfg)
local host = listen_address_schema:get(cfg_with_defaults, 'host')
local port = listen_address_schema:get(cfg_with_defaults, 'port')
httpd = require('http.server').new(host, port)
local response_headers = { ['content-type'] = 'application/json' }
httpd:route({ path = '/band/:id', method = 'GET' }, function(req)
local id = req:stash('id')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
groups:
group001:
replicasets:
replicaset001:
instances:
instance001:
roles: [ http_api ]
roles_cfg:
http_api:
host: '127.0.0.1'
port: 8080
scheme: 'http'
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
-- http_api.lua --
local log = require('log').new("http_api")
local schema = require('experimental.config.utils.schema')

local function validate_host(host, w)
local host_pattern = "^(%d+)%.(%d+)%.(%d+)%.(%d+)$"
if not host:match(host_pattern) then
w.error("'host' should be a string containing a valid IP address, got %q", host)
end
end

local function validate_port(port, w)
if port <= 1 or port >= 65535 then
w.error("'port' should be between 1 and 65535, got %d", port)
end
end

local listen_address_schema = schema.new('listen_address', schema.record({
scheme = schema.scalar({
type = 'string',
allowed_values = { 'http', 'https' },
default = 'http',
}),
host = schema.scalar({
type = 'string',
validate = validate_host,
default = '127.0.0.1',
}),
port = schema.scalar({
type = 'integer',
validate = validate_port,
default = 8080,
}),
}))

local function validate(cfg)
listen_address_schema:validate(cfg)
end

local function apply(cfg)
local cfg_with_defaults = listen_address_schema:apply_default(cfg)
local scheme = listen_address_schema:get(cfg_with_defaults, 'scheme')
local host = listen_address_schema:get(cfg_with_defaults, 'host')
local port = listen_address_schema:get(cfg_with_defaults, 'port')
log.info("HTTP API endpoint: %s://%s:%d", scheme, host, port)
end

local function stop()
log.info("The 'http_api' role is stopped")
end

return {
validate = validate,
apply = apply,
stop = stop,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
instance001:
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-- api.lua --
local log = require('log').new("api")
local schema = require('experimental.config.utils.schema')

local listen_address = schema.record({
scheme = schema.enum({ 'http', 'https' }),
host = schema.scalar({ type = 'string' }),
port = schema.scalar({ type = 'integer' })
}, {
validate = function(data, w)
local protocol = w.schema.computed.annotations.protocol
if protocol == 'iproto' and data.scheme ~= nil then
w.error("iproto doesn't support 'scheme'")
end
end,
})

local http_listen_address_schema = schema.new('http_listen_address', schema.record({
name = schema.scalar({ type = 'string' }),
listen_address = listen_address,
}, {
protocol = 'http',
}))

local iproto_listen_address_schema = schema.new('iproto_listen_address', schema.record({
name = schema.scalar({ type = 'string' }),
listen_address = listen_address,
}, {
protocol = 'iproto',
}))

local function validate(cfg)
http_listen_address_schema:validate(cfg)
end

local function apply(cfg)
local scheme = http_listen_address_schema:get(cfg, 'listen_address.scheme')
local host = http_listen_address_schema:get(cfg, 'listen_address.host')
local port = http_listen_address_schema:get(cfg, 'listen_address.port')
log.info("API endpoint: %s://%s:%d", scheme, host, port)
end

local function stop()
log.info("The 'api' role is stopped")
end

return {
validate = validate,
apply = apply,
stop = stop,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
groups:
group001:
replicasets:
replicaset001:
instances:
instance001:
roles: [ api ]
roles_cfg:
api:
name: 'HTTP listen address'
listen_address:
host: '127.0.0.1'
port: 8080
scheme: 'http'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
instance001:
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
groups:
group001:
replicasets:
replicaset001:
instances:
instance001:
roles: [ http_api ]
roles_cfg:
http_api:
host: '127.0.0.1'
port: 8080
scheme: 'http'
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
-- http_api.lua --
local log = require('log').new("http_api")
local schema = require('experimental.config.utils.schema')

local listen_address_schema = schema.new('listen_address', schema.record({
scheme = schema.enum({ 'http', 'https' }, { env = 'HTTP_SCHEME' }),
host = schema.scalar({ type = 'string', env = 'HTTP_HOST' }),
port = schema.scalar({ type = 'integer', env = 'HTTP_PORT' })
}))

local function collect_env_cfg()
local res = {}
for _, w in listen_address_schema:pairs() do
local env_var = w.schema.env
if env_var ~= nil then
local value = schema.fromenv(env_var, os.getenv(env_var), w.schema)
listen_address_schema:set(res, w.path, value)
end
end
return res
end

local function validate(cfg)
local env_cfg = collect_env_cfg()
local result_cfg = listen_address_schema:merge(cfg, env_cfg)
listen_address_schema:validate(result_cfg)
end

local function apply(cfg)
local env_cfg = collect_env_cfg()
local result_cfg = listen_address_schema:merge(cfg, env_cfg)
log.info("HTTP API endpoint: %s://%s:%d", result_cfg.scheme, result_cfg.host, result_cfg.port)
end

local function stop()
log.info("The 'http_api' role is stopped")
end

return {
validate = validate,
apply = apply,
stop = stop,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
instance001:
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
groups:
group001:
replicasets:
replicaset001:
instances:
instance001:
roles: [ http_api ]
roles_cfg:
http_api:
host: '127.0.0.1'
port: 8080
scheme: 'http'
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
-- http_api.lua --
local log = require('log').new("http_api")
local schema = require('experimental.config.utils.schema')

local listen_address_schema = schema.new(
"listen_address",
schema.record(
{
scheme = schema.enum({ "http", "https" }),
host = schema.scalar({ type = "string" }),
port = schema.scalar({ type = "integer" })
}
),
{
methods = {
format = function(_self, url)
return string.format("%s://%s:%d", url.scheme, url.host, url.port)
end
}
}
)

local function validate(cfg)
listen_address_schema:validate(cfg)
end

local function apply(cfg)
local url_string = listen_address_schema:format(cfg)
log.info("HTTP API endpoint: %s", url_string)
end

local function stop()
log.info("The 'http_api' role is stopped")
end

return {
validate = validate,
apply = apply,
stop = stop,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
instance001:
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
groups:
group001:
replicasets:
replicaset001:
instances:
instance001:
roles: [ http-api ]
roles_cfg:
http-api:
- host: '127.0.0.1'
port: 8080
scheme: 'http'
- host: '127.0.0.1'
port: 8443
scheme: 'https'
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-- http_api.lua --
local log = require('log').new("http_api")
local schema = require('experimental.config.utils.schema')

local listen_address_schema = schema.new('listen_address', schema.array({
items = schema.record({
scheme = schema.enum({ 'http', 'https' }),
host = schema.scalar({ type = 'string' }),
port = schema.scalar({ type = 'integer' })
})
}))

local function validate(cfg)
listen_address_schema:validate(cfg)
end

local function apply(cfg)
for _, uri in ipairs(cfg) do
local scheme = uri.scheme
local host = uri.host
local port = uri.port
log.info("HTTP API endpoint: %s://%s:%d", scheme, host, port)
end
end

local function stop()
log.info("The 'http_api' role is stopped")
end

return {
validate = validate,
apply = apply,
stop = stop,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
instance001:
Loading

0 comments on commit f7d76f6

Please sign in to comment.