Skip to content
Snippets Groups Projects
Commit 0cb91010 authored by Alexander Turenko's avatar Alexander Turenko Committed by Alexander Turenko
Browse files

config: allow to call config:get() from app script

It is convenient to access configuration using `config:get()` from the
application script (`app.file` or `app.module`).

However, before this commit, it was not possible, because the
configuration was not considered as applied before the application
script is loaded.

Now, the script loading is moved into the post-apply phase.

The resulting sequence of steps on startup/reload is the following.

* collect configuration information (from all the sources)
* <if the previous step is failed, set `check_errors` status and break>
* apply the configuration (call all the appliers)
* <if the previous step is failed, set `check_errors` status and break>
* <set the new successful status: `ready` or `check_warnings`>
* call post-apply hooks (including application script loading)
* <if the previous step is failed, set `check_errors` status and break>
* <set the new successful status: `ready` or `check_warnings`>

I would like to briefly comment the changes in the tests.

* `app_test.lua`: added the check for the new behavior (call
  config:get() from the app script)
* `appliers_test.lua`: fixed the applier call (`.apply` ->
  `.post_apply`)
* `config_test.lua`: fixed status observed in the app script
  (`*_in_progress` -> `ready`)

Part of #8862

NO_DOC=reflected in https://github.com/tarantool/doc/issues/3544
parent 06ca83c9
No related branches found
No related tags found
No related merge requests found
## feature/config
* It is now possible to access configuration from the application script using
the `config:get()` method (gh-8862).
local log = require('internal.config.utils.log')
local function apply(config)
local function apply(_config)
log.verbose('app.apply: do nothing')
end
local function post_apply(config)
local configdata = config._configdata
local file = configdata:get('app.file', {use_default = true})
local module = configdata:get('app.module', {use_default = true})
if file ~= nil then
assert(module == nil)
local fn = assert(loadfile(file))
log.verbose('app.apply: loading '..file)
log.verbose('app.post_apply: loading '..file)
fn(file)
elseif module ~= nil then
log.verbose('app.apply: loading '..module)
log.verbose('app.post_apply: loading '..module)
require(module)
end
end
......@@ -18,4 +22,5 @@ end
return {
name = 'app',
apply = apply,
post_apply = post_apply,
}
......@@ -279,10 +279,6 @@ function methods._apply_on_startup(self, opts)
end
self._configdata_applied = self._configdata
if extras ~= nil then
extras.post_apply(self)
end
else
assert(false)
end
......@@ -294,12 +290,35 @@ function methods._apply(self)
end
self._configdata_applied = self._configdata
end
function methods._post_apply(self)
for _, applier in ipairs(self._appliers) do
if applier.post_apply ~= nil then
applier.post_apply(self)
end
end
if extras ~= nil then
extras.post_apply(self)
end
end
-- Set proper status depending on received alerts.
function methods._set_status_based_on_alerts(self)
local status = 'ready'
for _, alert in pairs(self._alerts) do
assert(alert.type == 'error' or alert.type == 'warn')
if alert.type == 'error' then
status = 'check_errors'
break
end
status = 'check_warnings'
end
self._status = status
broadcast(self)
end
function methods._startup(self, instance_name, config_file)
assert(self._status == 'uninitialized')
self._status = 'startup_in_progress'
......@@ -331,9 +350,10 @@ function methods._startup(self, instance_name, config_file)
else
self:_apply_on_startup({phase = 2})
end
self:_set_status_based_on_alerts()
self._status = 'ready'
broadcast(self)
self:_post_apply()
self:_set_status_based_on_alerts()
end
function methods.get(self, path)
......@@ -360,27 +380,21 @@ function methods._reload_noexc(self, opts)
self._alerts = {}
self._metadata = {}
local ok, err = pcall(self._collect, self, opts)
if ok then
ok, err = pcall(self._apply, self)
end
local ok, err = pcall(function(opts)
self:_collect(opts)
self:_apply()
self:_set_status_based_on_alerts()
self:_post_apply()
end, opts)
assert(not ok or err == nil)
if not ok then
self:_alert({type = 'error', message = err})
end
-- Set proper status depending on received alerts.
local status = 'ready'
for _, alert in pairs(self._alerts) do
assert(alert.type == 'error' or alert.type == 'warn')
if alert.type == 'error' then
status = 'check_errors'
break
end
status = 'check_warnings'
end
self._status = status
broadcast(self)
self:_set_status_based_on_alerts()
return ok, err
end
......
......@@ -5,13 +5,14 @@ local g = helpers.group()
-- Start a script that is pointed by app.file or app.module.
--
-- TODO: Verify that the script has access to config:get() values.
-- Verify that the script has access to config:get() values.
g.test_startup_success = function(g)
local script = [[
-- TODO: Verify that the script has access to config:get()
-- values.
-- local config = require('config')
-- assert(config:get('app.cfg.foo') == 42)
local config = require('config')
assert(config:get('app.cfg.foo') == 42)
local info = config:info()
assert(info.status == 'ready')
assert(#info.alerts == 0)
_G.foo = 42
]]
......
......@@ -52,7 +52,7 @@ local appliers_script = [[
local fiber = require('internal.config.applier.fiber')
fiber.apply(config)
local app = require('internal.config.applier.app')
local ok, err = pcall(app.apply, config)
local ok, err = pcall(app.post_apply, config)
%s
os.exit(0)
]]
......
......@@ -237,8 +237,7 @@ g.test_config_broadcast = function()
local fiber = require('fiber')
local status = ''
box.watch('config.info', function(_, v) status = v.status end)
while status ~= 'startup_in_progress' and
status ~= 'reload_in_progress' do
while status ~= 'ready' do
fiber.sleep(0.1)
end
print(status)
......@@ -249,7 +248,7 @@ g.test_config_broadcast = function()
local args = {'main.lua'}
local res = justrun.tarantool(dir, {}, args, opts)
t.assert_equals(res.exit_code, 0)
local exp = {'startup_in_progress', 'ready', 'reload_in_progress', 'ready'}
local exp = {'ready', 'ready', 'ready', 'ready'}
t.assert_equals(res.stdout, table.concat(exp, "\n"))
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment