-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c940f9a
commit 6546bb9
Showing
4 changed files
with
722 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,208 @@ | ||
local function validate() | ||
local urilib = require("uri") | ||
|
||
local M = {} | ||
|
||
local supported_formats = {"json", "prometheus"} | ||
|
||
local function is_array(tbl) | ||
assert(type(tbl) == "table", "a table expected") | ||
for k, _ in pairs(tbl) do | ||
local found = false | ||
for idx, _ in ipairs(tbl) do | ||
if type(k) == type(idx) and k == idx then | ||
found = true | ||
end | ||
end | ||
if not found then | ||
return false | ||
end | ||
end | ||
return true | ||
end | ||
|
||
local function parse_listen(listen) | ||
if listen == nil then | ||
return nil, nil, "must exist" | ||
end | ||
if type(listen) ~= "string" and type(listen) ~= "number" then | ||
return nil, nil, "must be a string or a number, got " .. type(listen) | ||
end | ||
|
||
local host | ||
local port | ||
if type(listen) == "string" then | ||
local uri, err = urilib.parse(listen) | ||
if err ~= nil then | ||
return nil, nil, "failed to parse URI: " .. err | ||
end | ||
|
||
if uri.scheme ~= nil then | ||
if uri.scheme == "unix" then | ||
uri.unix = uri.path | ||
else | ||
return nil, nil, "URI scheme is not supported" | ||
end | ||
end | ||
|
||
if uri.login ~= nil or uri.password then | ||
return nil, nil, "URI login and password are not supported" | ||
end | ||
|
||
if uri.query ~= nil then | ||
return nil, nil, "URI query component is not supported" | ||
end | ||
|
||
if uri.unix ~= nil then | ||
host = "unix/" | ||
port = uri.unix | ||
else | ||
if uri.service == nil then | ||
return nil, nil, "URI must contain a port" | ||
end | ||
|
||
local ok, ret = pcall(tonumber, uri.service) | ||
if not ok then | ||
return nil, nil, "URI port must be a number" | ||
end | ||
if uri.host ~= nil then | ||
host = uri.host | ||
elseif uri.ipv4 ~= nil then | ||
host = uri.ipv4 | ||
elseif uri.ipv6 ~= nil then | ||
host = uri.ipv6 | ||
else | ||
host = "0.0.0.0" | ||
end | ||
port = ret | ||
end | ||
elseif type(listen) == "number" then | ||
host = "0.0.0.0" | ||
port = listen | ||
end | ||
|
||
if type(port) == "number" and (port < 1 or port > 65535) then | ||
return nil, nil, "port must be in range [1, 65535]" | ||
end | ||
return host, port, nil | ||
end | ||
|
||
local function validate_http_endpoint(endpoint) | ||
if type(endpoint) ~= "table" then | ||
error("http endpoint must be a table, got " .. type(endpoint), 4) | ||
end | ||
if endpoint.path == nil then | ||
error("http endpoint 'path' must exist", 4) | ||
end | ||
if type(endpoint.path) ~= "string" then | ||
error("http endpoint 'path' must be a string, got " .. type(endpoint.path), 4) | ||
end | ||
if string.sub(endpoint.path, 1, 1) ~= '/' then | ||
error("http endpoint 'path' must start with '/', got " .. endpoint.path, 4) | ||
end | ||
|
||
if endpoint.format == nil then | ||
error("http endpoint 'format' must exist", 4) | ||
end | ||
if type(endpoint.format) ~= "string" then | ||
error("http endpoint 'format' must be a string, got " .. type(endpoint.format), 4) | ||
end | ||
local found = false | ||
for _, supported in pairs(supported_formats) do | ||
if endpoint.format == supported then | ||
found = true | ||
end | ||
end | ||
if not found then | ||
error("http endpoint 'format' must be one of: " .. | ||
table.concat(supported_formats, ", ") .. ", got " .. endpoint.format, 4) | ||
end | ||
end | ||
|
||
local function apply() | ||
local function validate_http_node(node) | ||
if type(node) ~= "table" then | ||
error("http configuration node must be a table, got " .. type(node), 3) | ||
end | ||
|
||
local _, _, err = parse_listen(node.listen) | ||
if err ~= nil then | ||
error("failed to parse http 'listen' param: " .. err, 3) | ||
end | ||
|
||
node.endpoints = node.endpoints or {} | ||
if type(node.endpoints) ~= "table" then | ||
error("http 'endpoints' must be a table, got " .. type(node.endpoints), 3) | ||
end | ||
if not is_array(node.endpoints) then | ||
error("http 'endpoints' must be an array, not a map", 3) | ||
end | ||
for _, endpoint in ipairs(node.endpoints) do | ||
validate_http_endpoint(endpoint) | ||
end | ||
|
||
for i, ei in ipairs(node.endpoints) do | ||
for j, ej in ipairs(node.endpoints) do | ||
if i ~= j and ei.path == ej.path then | ||
error("http 'endpoints' must have different paths", 3) | ||
end | ||
end | ||
end | ||
end | ||
|
||
local function stop() | ||
local function validate_http(opts) | ||
if opts ~= nil and type(opts) ~= "table" then | ||
error("http configuration must be a table, got " .. type(opts), 2) | ||
end | ||
opts = opts or {} | ||
|
||
if not is_array(opts) then | ||
error("http configuration must be an array, not a map", 2) | ||
end | ||
|
||
for _, http_node in ipairs(opts) do | ||
validate_http_node(http_node) | ||
end | ||
|
||
for i, nodei in ipairs(opts) do | ||
local hosti, porti, erri = parse_listen(nodei.listen) | ||
assert(erri == nil) -- We should already successfully parse the URI. | ||
for j, nodej in ipairs(opts) do | ||
if i ~= j then | ||
local hostj, portj, errj = parse_listen(nodej.listen) | ||
assert(errj == nil) -- The same. | ||
if hosti == hostj and porti == portj then | ||
error("http configuration nodes must have different listen targets", 2) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
return { | ||
validate = validate, | ||
apply = apply, | ||
stop = stop, | ||
local export_type_validators = { | ||
["http"] = validate_http, | ||
} | ||
|
||
M.validate = function(conf) | ||
if conf ~= nil and type(conf) ~= "table" then | ||
error("configuration must be a table, got " .. type(conf)) | ||
end | ||
|
||
for export_type, opts in pairs(conf or {}) do | ||
if type(export_type) ~= "string" then | ||
error("export type must be a string, got " .. type(export_type)) | ||
end | ||
if export_type_validators[export_type] == nil then | ||
error("unsupported export type '" .. tostring(export_type) .. "'") | ||
end | ||
export_type_validators[export_type](opts) | ||
end | ||
end | ||
|
||
M.apply = function() | ||
|
||
end | ||
|
||
M.stop = function() | ||
|
||
end | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,19 @@ | ||
local t = require('luatest') | ||
local helpers = require('test.helper') | ||
|
||
local g = t.group('metrics_export_unit_test') | ||
local g = t.group() | ||
|
||
g.before_all(function() | ||
t.skip_if(not helpers.tarantool_role_is_supported(), | ||
'Tarantool role is supported only for Tarantool starting from v3.0.0') | ||
g.default_cfg = { } | ||
helpers.skip_if_unsupported() | ||
end) | ||
|
||
g.before_each(function() | ||
g.role = require('roles.metrics-export') | ||
g.role = require("roles.metrics-export") | ||
end) | ||
|
||
g.after_each(function() | ||
g.role.stop() | ||
end) | ||
|
||
function g.test_dummy() | ||
t.assert_equals(g.role.validate(), nil) | ||
local expected_methods = {"apply", "validate", "stop"} | ||
for _, method in ipairs(expected_methods) do | ||
g["test_exist_method_" .. method] = function() | ||
t.assert_type(g.role[method], "function") | ||
end | ||
end |
Oops, something went wrong.