-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
roles: introduce role for http servers
This patch adds `roles.http_server`. This role allows to configurate one or more HTTP servers. Those servers could be reused by several other roles. Servers could be accessed by their names (from the config). `get_server(name)` method returns a server by its name. If `nil` is passed, default server is returned. The server is default, if it has `DEFAULT_SERVER_NAME` as a name. Closes #196
- Loading branch information
Showing
13 changed files
with
475 additions
and
12 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
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
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
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
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 |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Install | ||
install(FILES http_server.lua DESTINATION ${TARANTOOL_INSTALL_LUADIR}/roles) |
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 |
---|---|---|
@@ -0,0 +1,134 @@ | ||
local urilib = require("uri") | ||
local http_server = require('http.server') | ||
|
||
local M = { | ||
DEFAULT_SERVER_NAME = 'default', | ||
} | ||
local servers = {} | ||
|
||
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 | ||
|
||
port = tonumber(uri.service) | ||
if port == nil 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 | ||
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 the range [1, 65535]" | ||
end | ||
return host, port, nil | ||
end | ||
|
||
local function apply_http(name, node) | ||
local host, port, err = parse_listen(node.listen) | ||
if err ~= nil then | ||
error("failed to parse URI: " .. err) | ||
end | ||
|
||
if servers[name] == nil then | ||
local httpd = http_server.new(host, port) | ||
httpd:start() | ||
servers[name] = { | ||
httpd = httpd, | ||
routes = {}, | ||
} | ||
end | ||
end | ||
|
||
M.validate = function(conf) | ||
if conf ~= nil and type(conf) ~= "table" then | ||
error("configuration must be a table, got " .. type(conf)) | ||
end | ||
conf = conf or {} | ||
|
||
for name, node in pairs(conf) do | ||
if type(name) ~= 'string' then | ||
error("name of the server must be a string") | ||
end | ||
|
||
local _, _, err = parse_listen(node.listen) | ||
if err ~= nil then | ||
error("failed to parse http 'listen' param: " .. err) | ||
end | ||
end | ||
end | ||
|
||
M.apply = function(conf) | ||
-- This should be called on the role's lifecycle, but it's better to give | ||
-- a meaningful error if something goes wrong. | ||
M.validate(conf) | ||
|
||
for name, node in pairs(conf or {}) do | ||
apply_http(name, node) | ||
end | ||
end | ||
|
||
M.stop = function() | ||
for _, server in pairs(servers) do | ||
server.httpd:stop() | ||
end | ||
servers = {} | ||
end | ||
|
||
M.get_server = function(name) | ||
checks('?string') | ||
|
||
name = name or M.DEFAULT_SERVER_NAME | ||
if type(name) == 'string' then | ||
return servers[name] | ||
end | ||
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 |
---|---|---|
@@ -0,0 +1,71 @@ | ||
local t = require('luatest') | ||
local treegen = require('luatest.treegen') | ||
local server = require('luatest.server') | ||
local fun = require('fun') | ||
local yaml = require('yaml') | ||
|
||
local helpers = require('test.helpers') | ||
local http_server_role = require('roles.http_server') | ||
local mock_role = require('test.mocks.mock_role') | ||
|
||
local g = t.group() | ||
|
||
g.test_http_server_role_usage = function() | ||
helpers.skip_if_not_tarantool3() | ||
|
||
local config = { | ||
credentials = { | ||
users = { | ||
guest = { | ||
roles = {'super'}, | ||
}, | ||
}, | ||
}, | ||
iproto = { | ||
listen = {{uri = 'unix/:./{{ instance_name }}.iproto'}}, | ||
}, | ||
groups = { | ||
['group-001'] = { | ||
replicasets = { | ||
['replicaset-001'] = { | ||
instances = { | ||
['instance-001'] = {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
roles_cfg = { | ||
http_server = { | ||
default = { | ||
listen = 13000, | ||
}, | ||
additional = { | ||
listen = 13001, | ||
} | ||
}, | ||
mock_role = { | ||
{ | ||
id = 1, | ||
}, | ||
{ | ||
id = 2, | ||
name = 'additional', | ||
}, | ||
}, | ||
}, | ||
} | ||
local dir = treegen.prepare_directory({}, {}) | ||
|
||
local config_file = treegen.write_file(dir, 'config.yaml', | ||
yaml.encode(config)) | ||
local opts = {config_file = config_file, chdir = dir} | ||
g.server = server:new(fun.chain(opts, {alias = 'instance-001'}):tomap()) | ||
g.server:start() | ||
|
||
http_server_role.apply(config.roles_cfg.http_server) | ||
mock_role.apply(config.roles_cfg.mock_role, http_server_role) | ||
|
||
t.assert_equals(mock_role.get_server_port(1), 13000) | ||
t.assert_equals(mock_role.get_server_port(2), 13001) | ||
end |
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 |
---|---|---|
@@ -0,0 +1,15 @@ | ||
local M = {} | ||
|
||
local servers = {} | ||
|
||
M.apply = function(conf, http_server_role) | ||
for _, server in pairs(conf) do | ||
servers[server.id] = http_server_role.get_server(server.name) | ||
end | ||
end | ||
|
||
M.get_server_port = function(id) | ||
return servers[id].httpd.port | ||
end | ||
|
||
return M |
Oops, something went wrong.