Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document the 'experimental.config.utils.schema' module #4469

Merged
merged 33 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b53adb0
Schema validation: update HTTP sample
andreyaksenov Aug 26, 2024
baddf54
Schema validation: samples
andreyaksenov Aug 26, 2024
f1261a6
Schema validation: samples - use endpoints instead of query params
andreyaksenov Aug 30, 2024
e4df6d8
Schema validation: samples - formatting/naming/cfg
andreyaksenov Aug 30, 2024
c180f39
Schema validation: samples - use ipairs
andreyaksenov Aug 30, 2024
5567165
Schema validation: samples - drop grpc/check nil
andreyaksenov Aug 30, 2024
8330c47
Schema validation: samples - update env sample
andreyaksenov Aug 30, 2024
d28c40a
Schema validation: samples - add local
andreyaksenov Aug 30, 2024
31f3df3
Schema validation
andreyaksenov Aug 26, 2024
ac1177b
Schema validation - review
andreyaksenov Sep 11, 2024
01cbe38
Schema validation - new sample
andreyaksenov Sep 12, 2024
81da573
Schema validation - rename samples
andreyaksenov Sep 12, 2024
e676fec
Schema validation 2
andreyaksenov Sep 12, 2024
f159ddd
Schema validation - add missing fields
andreyaksenov Sep 12, 2024
d18eb5f
Schema validation 3
andreyaksenov Sep 12, 2024
24adbba
Add text
p7nov Oct 9, 2024
d3b8d90
Add text
p7nov Oct 10, 2024
e45f78e
Add text
p7nov Oct 14, 2024
eefb3a4
Add text
p7nov Oct 14, 2024
b573e46
Add text
p7nov Oct 15, 2024
e71f41e
Add text
p7nov Oct 15, 2024
405e847
Fix
p7nov Oct 15, 2024
df97372
Fix
p7nov Oct 16, 2024
36cb3c3
Fix
p7nov Oct 16, 2024
cbc4bcd
Fix
p7nov Oct 16, 2024
f3e0c74
Fix
p7nov Oct 16, 2024
76125f6
Fix
p7nov Oct 17, 2024
d026a38
Add table structure to ref
p7nov Oct 17, 2024
f83e746
Fix
p7nov Oct 18, 2024
47c7f97
Fix
p7nov Oct 18, 2024
bee7bf5
Fix
p7nov Oct 18, 2024
0761e11
Apply suggestions from code review
p7nov Oct 22, 2024
5dbfc54
Review fixes
p7nov Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading