Skip to content

Commit 0d1fae7

Browse files
committed
config: add --help-env-list CLI option
It lists the environment variables that are taken into account by the config module. TBD: Part of #xxxx NO_DOC=reflected in tarantool/doc#3544
1 parent 2ed954e commit 0d1fae7

File tree

8 files changed

+165
-2
lines changed

8 files changed

+165
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## feature/config
2+
3+
* Added `--help-env-list` CLI option (gh-8862).

src/box/lua/config/init.lua

+5
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,11 @@ function methods._startup(self, instance_name, config_file)
336336
broadcast(self)
337337
end
338338

339+
function methods._print_env_list(self)
340+
local env_source = require('internal.config.source.env').new()
341+
io.stdout:write(env_source:_env_list())
342+
end
343+
339344
function methods.get(self, path)
340345
selfcheck(self, 'get')
341346
if self._status == 'uninitialized' then

src/box/lua/config/source/env.lua

+57
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local schema = require('internal.config.utils.schema')
2+
local tabulate = require('internal.config.utils.tabulate')
23
local instance_config = require('internal.config.instance_config')
34

45
local methods = {}
@@ -14,6 +15,62 @@ function methods._env_var_name(self, path_in_schema)
1415
return env_var_name
1516
end
1617

18+
function methods._env_list(self)
19+
local rows = {}
20+
21+
local ce = 'Community Edition'
22+
local ee = 'Enterprise Edition'
23+
24+
-- A header of the table.
25+
table.insert(rows, {
26+
'ENVIRONMENT VARIABLE',
27+
'TYPE',
28+
'DEFAULT',
29+
'AVAILABILITY',
30+
})
31+
table.insert(rows, tabulate.SPACER)
32+
33+
-- Environment variables that duplicate CLI options.
34+
table.insert(rows, {
35+
'TT_INSTANCE_NAME',
36+
'string',
37+
'N/A',
38+
ce,
39+
})
40+
table.insert(rows, {
41+
'TT_CONFIG',
42+
'string',
43+
'nil',
44+
ce,
45+
})
46+
table.insert(rows, tabulate.SPACER)
47+
48+
-- Collect the options from the schema and sort them
49+
-- lexicographically.
50+
local options = instance_config:pairs():totable()
51+
table.sort(options, function(a, b)
52+
return table.concat(a.path, '_') < table.concat(b.path, '_')
53+
end)
54+
55+
-- Transform the schema nodes (options) into the environment
56+
-- variables description.
57+
for _, w in ipairs(options) do
58+
local default = w.schema.default
59+
if default == nil and type(default) == 'cdata' then
60+
default = 'box.NULL'
61+
end
62+
63+
table.insert(rows, {
64+
self._env_var_name(self, w.path),
65+
w.schema.type,
66+
tostring(default),
67+
w.annotations.enterprise_edition and ee or ce,
68+
})
69+
end
70+
71+
return tabulate.encode(rows)
72+
end
73+
1774
-- Gather most actual config values.
1875
function methods.sync(self, _config_module, _iconfig)
1976
local values = {}

src/lua/init.c

+18
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,7 @@ run_script_f(va_list ap)
10421042
bool interactive = opt_mask & O_INTERACTIVE;
10431043
bool bytecode = opt_mask & O_BYTECODE;
10441044
bool debugging = opt_mask & O_DEBUGGING;
1045+
bool help_env_list = opt_mask & O_HELP_ENV_LIST;
10451046
/*
10461047
* An error is returned via an external diag. A caller
10471048
* can't use fiber_join(), because the script can call
@@ -1108,6 +1109,23 @@ run_script_f(va_list ap)
11081109
}
11091110
}
11101111

1112+
/*
1113+
* Show a list of environment variables that are
1114+
* considered by tarantool and exit.
1115+
*/
1116+
if (help_env_list) {
1117+
/* require('config'):_print_env_list() */
1118+
if (lua_require_lib(L, "config") != 0)
1119+
goto error;
1120+
lua_pushstring(L, "_print_env_list");
1121+
lua_gettable(L, -2);
1122+
lua_pushvalue(L, -2);
1123+
if (luaT_call(L, 1, 0) != 0)
1124+
goto error;
1125+
lua_settop(L, 0);
1126+
goto end;
1127+
}
1128+
11111129
/*
11121130
* Start an instance using an externally provided
11131131
* configuration if the --name option is passed.

src/lua/init.h

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct instance_state {
5555
#define O_BYTECODE 0x2
5656
#define O_DEBUGGING 0x4
5757
#define O_EXECUTE 0x8
58+
#define O_HELP_ENV_LIST 0x10
5859

5960
/**
6061
* Create tarantool_L and initialize built-in Lua modules.

src/main.cc

+7-2
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,7 @@ print_help(FILE *stream, const char *program)
632632
" %s [OPTIONS] [SCRIPT [ARGS]]\n\n"
633633
"Options:\n\n"
634634
" -h, --help display this help and exit\n"
635+
" --help-env-list display env variables taken into account\n"
635636
" -v, --version print program version and exit\n"
636637
" -c, --config PATH set a path to yaml config file as 'PATH'\n"
637638
" -n, --name INSTANCE set an instance name as 'INSTANCE'\n"
@@ -677,6 +678,7 @@ main(int argc, char **argv)
677678
{"version", no_argument, 0, 'v'},
678679
{"config", required_argument, 0, 'c'},
679680
{"name", required_argument, 0, 'n'},
681+
{"help-env-list", no_argument, 0, 'E'},
680682
{NULL, 0, 0, 0},
681683
};
682684
static const char *opts = "+hVvb::ij:e:l:dc:n:";
@@ -706,6 +708,9 @@ main(int argc, char **argv)
706708
case 'h':
707709
print_help(stdout, basename(argv[0]));
708710
return 0;
711+
case 'E':
712+
opt_mask |= O_HELP_ENV_LIST;
713+
break;
709714
case 'i':
710715
/* Force interactive mode */
711716
opt_mask |= O_INTERACTIVE;
@@ -805,8 +810,8 @@ main(int argc, char **argv)
805810
if (strlen(tarantool_path) < strlen(tarantool_bin))
806811
panic("executable path is trimmed");
807812

808-
if (script == NULL && (opt_mask & (O_INTERACTIVE | O_EXECUTE)) == 0 &&
809-
instance.name == NULL) {
813+
if (script == NULL && (opt_mask & (O_INTERACTIVE | O_EXECUTE |
814+
O_HELP_ENV_LIST)) == 0 && instance.name == NULL) {
810815
static const char misuse_msg[] = "Invalid usage: "
811816
"please either provide a Lua script name\n"
812817
"or specify an instance name to be started\n"

test/box-py/args.result

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Usage:
2424
Options:
2525

2626
-h, --help display this help and exit
27+
--help-env-list display env variables taken into account
2728
-v, --version print program version and exit
2829
-c, --config PATH set a path to yaml config file as 'PATH'
2930
-n, --name INSTANCE set an instance name as 'INSTANCE'
@@ -65,6 +66,7 @@ Usage:
6566
Options:
6667

6768
-h, --help display this help and exit
69+
--help-env-list display env variables taken into account
6870
-v, --version print program version and exit
6971
-c, --config PATH set a path to yaml config file as 'PATH'
7072
-n, --name INSTANCE set an instance name as 'INSTANCE'

test/config-luatest/cli_test.lua

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
local t = require('luatest')
2+
local justrun = require('test.justrun')
3+
4+
local g = t.group()
5+
6+
g.test_help_env_list = function()
7+
local res = justrun.tarantool('.', {}, {'--help-env-list'}, {nojson = true})
8+
t.assert_equals(res.exit_code, 0)
9+
10+
-- Pick up several well-known env variables to verify the idea
11+
-- of the listing, but at the same time, don't list all the
12+
-- options in the test case.
13+
local cases = {
14+
-- Verify that the env variables that duplicates CLI
15+
-- options are present.
16+
{
17+
name = 'TT_INSTANCE_NAME',
18+
type = 'string',
19+
default = 'N/A',
20+
availability = 'Community Edition',
21+
},
22+
{
23+
name = 'TT_CONFIG',
24+
type = 'string',
25+
default = 'nil',
26+
availability = 'Community Edition',
27+
},
28+
-- An env variable that accepts a numeric value and has
29+
-- explicit default value.
30+
{
31+
name = 'TT_MEMTX_MEMORY',
32+
type = 'integer',
33+
default = '268435456',
34+
availability = 'Community Edition',
35+
},
36+
-- An env variable that has box.NULL default.
37+
{
38+
name = 'TT_DATABASE_MODE',
39+
type = 'string',
40+
default = 'box.NULL',
41+
availability = 'Community Edition',
42+
},
43+
-- An option with a template default.
44+
{
45+
name = 'TT_CONSOLE_SOCKET',
46+
type = 'string',
47+
default = '{{ instance_name }}.control',
48+
availability = 'Community Edition',
49+
},
50+
-- An Enterprise Edition option and, at the same time,
51+
-- an option with non-string type.
52+
{
53+
name = 'TT_CONFIG_ETCD_ENDPOINTS',
54+
type = 'array',
55+
default = 'nil',
56+
availability = 'Enterprise Edition',
57+
},
58+
-- Yet another Enterprise Edition option.
59+
{
60+
name = 'TT_WAL_EXT_NEW',
61+
type = 'boolean',
62+
default = 'nil',
63+
availability = 'Enterprise Edition',
64+
},
65+
}
66+
67+
for _, case in ipairs(cases) do
68+
local needle = ('%s.*%s.*%s.*%s'):format(case.name, case.type,
69+
case.default, case.availability)
70+
t.assert(res.stdout:find(needle), case.name)
71+
end
72+
end

0 commit comments

Comments
 (0)