Skip to content

Commit

Permalink
Simplify failover setup for tests (#1358)
Browse files Browse the repository at this point in the history
  • Loading branch information
Steap2448 authored Apr 16, 2021
1 parent c830f0d commit 1ab444e
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 7 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@ Added

- Update vshard to 0.1.17.
(`Changelog <https://github.com/tarantool/vshard/releases/tag/0.1.17>`_).

- Update graphql to 0.1.1 which allows to return data and errors together.

- New test helper: ``cartridge.test-helpers.stateboard``.

- New ``failover`` option in the cluster test helper for easier failover setup.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Fixed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- Fix unclear timeout errors in case of ``InitError`` and ``BootError`` states
- Fix unclear timeout errors in case of ``InitError`` and ``BootError`` states.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Enhanced in WebUI
Expand Down
4 changes: 4 additions & 0 deletions cartridge/test-helpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ helpers.Cluster = require('cartridge.test-helpers.cluster')
-- @see cartridge.test-helpers.etcd
helpers.Etcd = require('cartridge.test-helpers.etcd')

--- Class to run and manage stateboard.
-- @see cartridge.test-helpers.stateboard
helpers.Stateboard = require('cartridge.test-helpers.stateboard')

return helpers
61 changes: 61 additions & 0 deletions cartridge/test-helpers/cluster.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ local uuid = require('uuid')

local luatest = require('luatest')
local Server = require('cartridge.test-helpers.server')
local Stateboard = require('cartridge.test-helpers.stateboard')

-- Defaults.
local Cluster = {
Expand All @@ -19,6 +20,7 @@ local Cluster = {
cookie = 'test-cluster-cookie',
base_http_port = 8080,
base_advertise_port = 13300,
failover = 'disabled',
}

function Cluster:inherit(object)
Expand All @@ -35,6 +37,8 @@ end
-- @int[opt] object.base_advertise_port Value to calculate server's advertise_port.
-- @bool[opt] object.use_vshard bootstrap vshard after server is started.
-- @tab object.replicasets Replicasets configuration. List of @{replicaset_config}
-- @string[opt] object.failover Failover mode: disabled, eventual, or stateful.
-- @string[opt] object.stateboard_entrypoint Command to run stateboard
-- @return object
function Cluster:new(object)
checks('table', {
Expand All @@ -46,6 +50,8 @@ function Cluster:new(object)
use_vshard = '?boolean',
replicasets = 'table',
env = '?table',
failover = '?string',
stateboard_entrypoint = '?string',
})
--- Replicaset config.
-- @table @replicaset_config
Expand Down Expand Up @@ -74,6 +80,31 @@ end

function Cluster:initialize()
self.servers = {}

assert(
self.failover == 'disabled'
or self.failover == 'eventual'
or self.failover == 'stateful',
"failover must be 'disabled', 'eventual' or 'stateful'"
)

if self.failover == 'stateful' then
assert(self.stateboard_entrypoint ~= nil,
'stateboard_entrypoint required for stateful failover')
self.stateboard = Stateboard:new({
workdir = fio.pathjoin(self.datadir, 'stateboard'),
command = self.stateboard_entrypoint,
net_box_port = 14401,
net_box_credentials = {
user = 'client',
password = self.cookie,
},
env = {
TARANTOOL_PASSWORD = self.cookie,
}
})
end

for _, replicaset_config in ipairs(self.replicasets) do
replicaset_config.uuid = replicaset_config.uuid or uuid.str()
if type(replicaset_config.servers) == 'number' then
Expand All @@ -91,6 +122,24 @@ function Cluster:initialize()
end
end

function Cluster:configure_failover()
assert(self.main_server)

local failover_config = {mode = self.failover}
if failover_config.mode == 'stateful' then
failover_config.state_provider = 'tarantool'
failover_config.tarantool_params = {
uri = self.stateboard.net_box_uri,
password = self.stateboard.net_box_credentials.password
}
end

self.main_server.net_box:call(
'package.loaded.cartridge.failover_set_params',
{failover_config}
)
end

--- Find server by alias.
-- @string alias
-- @return @{cartridge.test-helpers.server}
Expand Down Expand Up @@ -159,6 +208,12 @@ function Cluster:start()
if self.running then
return
end
if self.failover == 'stateful' then
self.stateboard:start()
luatest.helpers.retrying({}, function()
self.stateboard:connect_net_box()
end)
end
for _, server in ipairs(self.servers) do
server:start()
end
Expand All @@ -170,6 +225,9 @@ function Cluster:start()
self:bootstrap()
self.bootstrapped = true
end
if self.failover ~= 'disabled' then
self:configure_failover()
end
self.running = true
end

Expand All @@ -178,6 +236,9 @@ function Cluster:stop()
for _, server in ipairs(self.servers) do
server:stop()
end
if self.stateboard then
self.stateboard:stop()
end
self.running = nil
end

Expand Down
2 changes: 1 addition & 1 deletion cartridge/test-helpers/server.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
--- Extended luatest.Server class to run tarantool instance.
--- Extended luatest.Server class to run a cartridge instance.
--
-- @classmod cartridge.test-helpers.server

Expand Down
41 changes: 41 additions & 0 deletions cartridge/test-helpers/stateboard.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
--- Class to run and manage stateboard.
--
-- @classmod cartridge.test-helpers.stateboard

local luatest = require('luatest')
local log = require('log')

--- Build stateboard object.
-- @function new
-- @param object
-- @string object.name Human-readable node name.
-- @string object.command Command to run stateboard.
-- @string object.workdir Path to the data directory.
-- @string object.net_box_port Value to be passed in `TARANTOOL_LISTEN` and used for net_box connection.
-- @tab[opt] object.net_box_credentials Override default net_box credentials.
-- @tab[opt] object.env Environment variables passed to the process.
-- @return object
local Stateboard = luatest.Server:inherit({})

-- Start stateboard
function Stateboard:start()
getmetatable(getmetatable(self)).start(self)
end

-- Stop stateboard
function Stateboard:stop()
local process = self.process
if process == nil then
return
end
getmetatable(getmetatable(self)).stop(self)
luatest.helpers.retrying({}, function()
luatest.assert_not(
process:is_alive(),
string.format('Process %s is still running', self.alias)
)
end)
log.warn('Process %s killed', self.alias)
end

return Stateboard
1 change: 1 addition & 0 deletions config.ld
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ file = {
"cartridge/test-helpers/cluster.lua",
"cartridge/test-helpers/server.lua",
"cartridge/test-helpers/etcd.lua",
"cartridge/test-helpers/stateboard.lua",
"cartridge/remote-control.lua",
"cartridge/service-registry.lua",
"cartridge/user-defined-role.lua",
Expand Down
Empty file modified stateboard.init.lua
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion test/integration/failover_stateful_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ g_stateboard.before_all(function()
g.datadir = fio.tempdir()

g.kvpassword = require('digest').urandom(6):hex()
g.state_provider = require('luatest.server'):new({
g.state_provider = helpers.Stateboard:new({
command = helpers.entrypoint('srv_stateboard'),
workdir = fio.pathjoin(g.datadir, 'stateboard'),
net_box_port = 14401,
Expand Down
2 changes: 1 addition & 1 deletion test/integration/fencing_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ g_stateboard.before_all(function()

fio.mktree(fio.pathjoin(g.datadir, 'stateboard'))
g.kvpassword = require('digest').urandom(6):hex()
g.state_provider = require('luatest.server'):new({
g.state_provider = helpers.Stateboard:new({
command = helpers.entrypoint('srv_stateboard'),
workdir = fio.pathjoin(g.datadir, 'stateboard'),
net_box_port = 14401,
Expand Down
2 changes: 1 addition & 1 deletion test/integration/stateboard_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ g.before_each(function()
local password = require('digest').urandom(6):hex()

fio.mktree(fio.pathjoin(g.datadir, 'stateboard'))
g.stateboard = require('luatest.server'):new({
g.stateboard = helpers.Stateboard:new({
command = helpers.entrypoint('srv_stateboard'),
workdir = fio.pathjoin(g.datadir),
net_box_port = 13301,
Expand Down
3 changes: 2 additions & 1 deletion test/integration/switchover_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ g_stateboard.before_all(function()

fio.mktree(fio.pathjoin(g.datadir, 'stateboard'))
g.kvpassword = require('digest').urandom(6):hex()
g.state_provider = require('luatest.server'):new({
g.state_provider = helpers.Stateboard:new({
command = helpers.entrypoint('srv_stateboard'),
workdir = fio.pathjoin(g.datadir, 'stateboard'),
net_box_port = 14401,
Expand All @@ -65,6 +65,7 @@ g_stateboard.before_all(function()
),
},
})

g.state_provider:start()
helpers.retrying({}, function()
g.state_provider:connect_net_box()
Expand Down
40 changes: 39 additions & 1 deletion test/unit/helpers_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ g.before_all = function()
datadir = fio.tempdir(),
use_vshard = true,
server_command = helpers.entrypoint('srv_basic'),
failover = 'stateful',
stateboard_entrypoint = helpers.entrypoint('srv_stateboard'),
cookie = require('digest').urandom(6):hex(),
base_http_port = 8080,
base_advertise_port = 13300,
replicasets = {
{
alias = 'vshard',
roles = {'vshard-router', 'vshard-storage'},
roles = {'vshard-router', 'vshard-storage', 'failover-coordinator'},
servers = 1,
},
{
Expand Down Expand Up @@ -89,6 +91,42 @@ function g.test_replicaset_uuid_generation()
end
end

local function get_failover(cluster)
return cluster.main_server.net_box:call(
'package.loaded.cartridge.failover_get_params')
end

function g.test_failover()
t.assert_equals(get_failover(g.cluster).mode, 'stateful')
t.assert(g.cluster.stateboard)

local coordinator = g.cluster:server('vshard-1')
t.assert_equals(g.cluster.stateboard.net_box:call('get_coordinator'),
{uri = coordinator.advertise_uri, uuid = coordinator.instance_uuid})

t.assert_error_msg_contains(
"failover must be 'disabled', 'eventual' or 'stateful'",
build_cluster, {
replicasets = {{roles = {}, servers = 1, alias = ''}},
failover = 'thebest'
})

t.assert_error_msg_contains(
"stateboard_entrypoint required for stateful failover",
build_cluster, {
replicasets = {{roles = {}, servers = 1, alias = ''}},
failover = 'stateful',
})

-- t.assert_error_msg_contains(
-- "fake: no such stateboard_entrypoint",
-- build_cluster, {
-- replicasets = {{roles = {}, servers = 1, alias = ''}},
-- failover = 'stateful',
-- stateboard_entrypoint = 'fake'
-- })
end

function g.test_new_with_servers_count()
local cluster = build_cluster({replicasets = {
{roles = {}, servers = 2, alias = 'router'},
Expand Down

0 comments on commit 1ab444e

Please sign in to comment.