allow to read environment variables as config parameters

Environment variables must be prefixed with winix_ to be loaded by winix.
The winix_ prefix is then removed and the key value converted to lowercase.

Sample:
evn WINIX_MY_OPTION=TEST123test winix -c config_file

This will add my_option to the config with value TEST123test.
Environment variables are read last so they will overwrite the values
from the configuration files.
This commit is contained in:
Tomasz Sowa 2022-04-16 21:50:23 +02:00
parent 4f8b5e649a
commit 64e5114947
3 changed files with 82 additions and 9 deletions

View File

@ -95,8 +95,6 @@ bool Config::ReadConfig(const std::wstring & config_file)
if( status == pt::SpaceParser::ok )
{
AssignValues();
SetAdditionalVariables();
return true;
}
else
@ -107,6 +105,12 @@ bool Config::ReadConfig(const std::wstring & config_file)
}
void Config::AssignValuesFromSpace()
{
AssignValues();
SetAdditionalVariables();
}
void Config::AssignValues()

View File

@ -854,6 +854,8 @@ public:
Config();
bool ReadConfig(const std::wstring & config_file);
void AssignValuesFromSpace();
/*
*

View File

@ -47,6 +47,7 @@
namespace Winix
{
@ -67,11 +68,22 @@ void print_syntax()
std::cout << "Usage: winix [options]" << std::endl;
std::cout << " -c : a path to the config file" << std::endl;
std::cout << " --config : a path to the config file" << std::endl;
std::cout << " --use-env : allow to use environment variables" << std::endl;
std::cout << " --dump-config : dump all read config options to stdout and exit" << std::endl;
std::cout << " -h : print usage information" << std::endl;
std::cout << " --help : print usage information" << std::endl;
std::cout << " -? : print usage information" << std::endl;
std::cout << std::endl;
std::cout << "At least one -c or --config parameter is required, use -c or --config option" << std::endl;
std::cout << "multiple times to load more than one config." << std::endl;
std::cout << std::endl;
std::cout << "Environment variables must be prefixed with winix_ to be loaded by winix." << std::endl;
std::cout << "The winix_ prefix is then removed and the key value converted to lowercase." << std::endl;
std::cout << "Sample:" << std::endl;
std::cout << "evn WINIX_MY_OPTION=TEST123test winix -c config_file" << std::endl;
std::cout << "This will add my_option to the config with value TEST123test." << std::endl;
std::cout << "Environment variables are read last so they will overwrite the values" << std::endl;
std::cout << "from the configuration files." << std::endl;
}
@ -179,7 +191,42 @@ bool ReadConfigs(const pt::Space::TableType & table, size_t & config_read)
}
bool ReadConfigs(const pt::Space & options)
void ReadEnvOption(const char * option)
{
const char winix_prefix[] = "winix_";
size_t prefix_len = sizeof(winix_prefix) - 1; // null terminating table
std::wstring opt, val;
if( pt::is_substr_nc(winix_prefix, option) )
{
pt::utf8_to_wide(option + prefix_len, opt);
std::wstring::size_type sep = opt.find('=');
if( sep != std::wstring::npos )
{
val = opt.substr(sep + 1);
opt.erase(sep);
}
TemplatesFunctions::locale.ToSmall(opt);
app.config.space.add(opt, val);
}
}
void ReadConfigFromEnv(const char ** env)
{
for(size_t i = 0 ; env[i] ; ++i)
{
ReadEnvOption(env[i]);
}
}
bool ReadConfigs(const pt::Space & options, const char ** env)
{
size_t config_read = 0;
bool status = true;
@ -205,6 +252,13 @@ bool ReadConfigs(const pt::Space & options)
return false;
}
if( options.has_key(L"use-env") )
{
ReadConfigFromEnv(env);
}
app.config.AssignValuesFromSpace();
return status;
}
@ -212,7 +266,7 @@ bool ReadConfigs(const pt::Space & options)
int main(int argc, const char ** argv)
int main(int argc, const char ** argv, const char ** env)
{
using Winix::app;
@ -241,22 +295,35 @@ using Winix::app;
}
Winix::Log & log = app.GetMainLog();
pt::WTextStream * log_buffer = log.get_log_buffer();
Winix::LogInfo(log, Winix::log3, "UTC booting Winix", true, ""); // date will be printed as UTC because the time zones are not loaded yet
if( !Winix::ReadConfigs(options) )
if( !Winix::ReadConfigs(options, env) )
{
// we need to print the buffer by hand because the logger
// is not fully initialized yet
pt::WTextStream * buffer = log.get_log_buffer();
if( buffer && !buffer->empty() )
if( log_buffer && !log_buffer->empty() )
{
pt::wide_stream_to_utf8(*buffer, std::cout);
pt::wide_stream_to_utf8(*log_buffer, std::cout);
}
return 2;
}
if( options.has_key(L"dump-config") )
{
if( log_buffer )
{
log << "all read config options (some of the values could have been modified by winix"
<< " but the modified values are not printed here):" << Winix::logend;
app.config.space.serialize_to_space_stream(*log_buffer, true);
log << Winix::logend;
pt::wide_stream_to_utf8(*log_buffer, std::cout);
}
return 0;
}
app.InitLoggers();
if( app.stdout_is_closed || app.config.demonize )