Skip to content

Commit

Permalink
config: expand config:info()
Browse files Browse the repository at this point in the history
Closes tarantool#9780

@TarantoolBot document
Title: Expansion of `config:info()`

Before this patch, the `meta` field of the `config:info()` function
contained the meta data of the last load, even if it was unsuccessful
reload. This can be inconvenient because if the reload fails, we expect
that the last configuration that was successfully applied is used, but
its metadata was lost.

Now `config:info()` can take one argument — the version of the
information that should be returned by the function. If no arguments are
specified or the argument is the string `v1`, the return value has the
same structure as before. If the argument is the string `v2`, the `meta`
field in the return value has fields - `active` (meta for the last
successfully applied configuration) and `last` (meta of the last loaded
configuration). Currently only these values are accepted.
  • Loading branch information
ImeevMA committed Mar 7, 2024
1 parent f90f539 commit 14fddb8
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 6 deletions.
3 changes: 3 additions & 0 deletions changelogs/unreleased/gh-9780-show-active-meta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## feature/config

* The `config:info()` functionality has been expanded (gh-9780).
31 changes: 25 additions & 6 deletions src/box/lua/config/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,9 @@ function methods._startup(self, instance_name, config_file)
self:_apply_on_startup({phase = 2})
end
self:_set_status_based_on_alerts()
if self._status == 'ready' or self._status == 'check_warnings' then
self._active_metadata = self._metadata
end

self:_post_apply()
self:_set_status_based_on_alerts()
Expand Down Expand Up @@ -450,6 +453,9 @@ function methods._reload_noexc(self, opts)
self:_store(self:_collect(opts))
self:_apply()
self:_set_status_based_on_alerts()
if self._status == 'ready' or self._status == 'check_warnings' then
self._active_metadata = self._metadata
end
self:_post_apply()
end, opts)

Expand All @@ -474,13 +480,26 @@ function methods.reload(self)
end
end

function methods.info(self)
function methods.info(self, version)
selfcheck(self, 'info')
return {
alerts = self._aboard:alerts(),
meta = self._metadata,
status = self._status,
}
if version == nil or version == 'v1' then
return {
alerts = self._aboard:alerts(),
meta = self._metadata,
status = self._status,
}
end
if version == 'v2' then
return {
alerts = self._aboard:alerts(),
meta = {
active = self._active_metadata,
last = self._metadata,
},
status = self._status,
}
end
error(('Expected "v2" or nil as info version, got %q'):format(version), 0)
end

-- The object is a singleton. The constructor should be called
Expand Down
177 changes: 177 additions & 0 deletions test/config-luatest/config_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1393,3 +1393,180 @@ g.test_non_dynamic_alert = function(g)
end,
})
end

-- Check that config:info('v2') works properly.
g.test_info_new_version = function(g)
local dir = treegen.prepare_directory(g, {}, {})

local config = [[
credentials:
users:
guest:
roles:
- super
iproto:
listen:
- uri: unix/:./{{ instance_name }}.iproto
groups:
group-001:
replicasets:
replicaset-001:
instances:
instance-001: {}
]]
treegen.write_script(dir, 'config.yaml', config)

-- New source that sets meta.
local script = string.dump(function()
local yaml = require('yaml')
local file = require('internal.config.utils.file')

local methods = {}
local mt = {
__index = methods,
}

function methods.sync(self, config)
local data = file.universal_read('myconf.yaml', 'my config file')
local ok, res = pcall(yaml.decode, data)
if not ok then
error('Unable to parse my config file')
end
self._values = res
config:_meta('myconf', 'revision', self._revision)
self._revision = self._revision + 1
end

function methods.get(self)
return self._values
end

local function new()
return setmetatable({
name = 'myfile',
type = 'instance',
_values = {},
_revision = 1,
}, mt)
end

return {
new = new,
}
end)
treegen.write_script(dir, 'source.lua', script)

local myconf = [[
sql:
cache_size: 12345
]]
treegen.write_script(dir, 'myconf.yaml', myconf)

local opts = {
config_file = 'config.yaml',
alias = 'instance-001',
chdir = dir,
}
g.server = server:new(opts)
g.server:start()

-- Make sure the new source is loaded properly and the meta is set.
g.server:exec(function()
local config = require('config')
t.assert_equals(config:get('sql.cache_size'), 5242880)

config:_register_source(require('source').new())
config:reload()
t.assert_equals(config:get('sql.cache_size'), 12345)
local exp = {
myconf = {
revision = 1,
},
}
t.assert_equals(config:info().meta, exp)
t.assert_equals(config:info('v1').meta, exp)
exp = {
active = {
myconf = {
revision = 1,
},
},
last = {
myconf = {
revision = 1,
},
},
}
t.assert_equals(config:info('v2').meta, exp)
end)

-- Make sure the meta for config:info() is new and that config:info('v2')
-- contains both applied meta and unapplied new meta when reload failed.
myconf = [[
sql:
cache_size: true
]]
treegen.write_script(dir, 'myconf.yaml', myconf)
g.server:exec(function()
local config = require('config')
t.assert_equals(config:get('sql.cache_size'), 12345)
pcall(config.reload, config)
t.assert_equals(config:get('sql.cache_size'), 12345)
local exp = {
myconf = {
revision = 2,
},
}
t.assert_equals(config:info().meta, exp)
t.assert_equals(config:info('v1').meta, exp)
exp = {
active = {
myconf = {
revision = 1,
},
},
last = {
myconf = {
revision = 2,
},
},
}
t.assert_equals(config:info('v2').meta, exp)
end)

-- Make sure that in config:info('v2') both applied meta and unapplied new
-- meta are equal when reload is successful.
myconf = [[
sql:
cache_size: 100000
]]
treegen.write_script(dir, 'myconf.yaml', myconf)
g.server:exec(function()
local config = require('config')
t.assert_equals(config:get('sql.cache_size'), 12345)
config:reload()
t.assert_equals(config:get('sql.cache_size'), 100000)
local exp = {
myconf = {
revision = 3,
},
}
t.assert_equals(config:info().meta, exp)
t.assert_equals(config:info('v1').meta, exp)
exp = {
active = {
myconf = {
revision = 3,
},
},
last = {
myconf = {
revision = 3,
},
},
}
t.assert_equals(config:info('v2').meta, exp)
end)
end

0 comments on commit 14fddb8

Please sign in to comment.