From fa21117dfe06a3d0446cfb4b441bd4a957cd79cf Mon Sep 17 00:00:00 2001 From: Gleb Kashkin <g.kashkin@tarantool.org> Date: Mon, 1 Apr 2024 12:47:53 +0000 Subject: [PATCH] config: verify replicaset to contain an instance It is very easy to misplace a config option to a different level, for example create an empty replicaset `sharding` with storage role, instead of configuring sharding option to `storage`: ``` groups: g-001: replicasets: sharding: roles: - storage r-001: instances: i-001: {} ``` This patch adds validation that forbids creating an empty group or replicaset. Note that a group or a replicaset could still be defined in multiple config sources and may appear empty in one of them, the check is performed on the merged cluster config. Closes #9895 NO_DOC=bugfix --- ...h-9895-forbid-empty-group-or-replicaset.md | 5 ++++ src/box/lua/config/configdata.lua | 20 +++++++++++++ test/config-luatest/cluster_config_test.lua | 30 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 changelogs/unreleased/gh-9895-forbid-empty-group-or-replicaset.md diff --git a/changelogs/unreleased/gh-9895-forbid-empty-group-or-replicaset.md b/changelogs/unreleased/gh-9895-forbid-empty-group-or-replicaset.md new file mode 100644 index 0000000000..5b47bf8e32 --- /dev/null +++ b/changelogs/unreleased/gh-9895-forbid-empty-group-or-replicaset.md @@ -0,0 +1,5 @@ +## bugfix/config + +* Added additional validation to a cluster's configuration. + Now it is forbidden to create an empty group or + replicaset (gh-9895). diff --git a/src/box/lua/config/configdata.lua b/src/box/lua/config/configdata.lua index 81321b9d4e..d83fb18d2b 100644 --- a/src/box/lua/config/configdata.lua +++ b/src/box/lua/config/configdata.lua @@ -731,12 +731,32 @@ local function validate_anon(found, peers, failover, leader) end end +local function validate_misplacing(cconfig) + for group_name, group_cfg in pairs(cconfig.groups) do + if group_cfg.replicasets == nil or + next(group_cfg.replicasets) == nil then + error(('group %q should include at ' .. + 'least one replicaset.'):format(group_name), 0) + end + + for replicaset_name, replicaset_cfg in pairs(group_cfg.replicasets) do + if replicaset_cfg.instances == nil or + next(replicaset_cfg.instances) == nil then + error(('replicaset %q should include at ' .. + 'least one instance.'):format(replicaset_name), 0) + end + end + end +end + local function new(iconfig, cconfig, instance_name) -- Find myself in a cluster config, determine peers in the same -- replicaset. local found = cluster_config:find_instance(cconfig, instance_name) assert(found ~= nil) + validate_misplacing(cconfig) + -- Precalculate configuration with applied defaults. local iconfig_def = instance_config:apply_default(iconfig) diff --git a/test/config-luatest/cluster_config_test.lua b/test/config-luatest/cluster_config_test.lua index 075263962a..26d41bb922 100644 --- a/test/config-luatest/cluster_config_test.lua +++ b/test/config-luatest/cluster_config_test.lua @@ -281,3 +281,33 @@ g.test_instance_uri_errors = function(g) end) end) end + +-- Attempt to pass an empty group and an empty replicaset. +g.test_misplace_option = function(g) + local config = cbuilder.new() + :use_group('g-001') + + :use_replicaset('r-001') + :add_instance('i-001', {}) + + :use_group('sharding') + :set_group_option('roles', {'storage'}) + :config() + + cluster.startup_error(g, config, "group \"sharding\" should " .. + "include at least one replicaset.") + + local config = cbuilder.new() + :use_group('g-001') + + :use_replicaset('r-001') + :add_instance('i-001', {}) + + :use_replicaset('sharding') + :set_replicaset_option('roles', {'storage'}) + + :config() + + cluster.startup_error(g, config, "replicaset \"sharding\" should " .. + "include at least one instance.") +end -- GitLab