experimental #2: now interpolates environment variables in config object file

master
phanes 2022-01-17 00:12:13 -05:00
parent 2871f8f8c1
commit ebdb9d643a
8 changed files with 121 additions and 44 deletions

5
.gitignore vendored
View File

@ -2,3 +2,8 @@
cmake-build-debug cmake-build-debug
.idea .idea
./.idea ./.idea
./cmake-build-release/
cmake-build-release
CMakeFiles
CMakeLists.txt
Makefile

View File

@ -4,4 +4,5 @@ set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++1z -O0 -DDEBUG=1") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++1z -O0 -DDEBUG=1")
set(SOURCE_FILES Rex.cpp src/loaders/abstract/loaders.cpp src/loaders/abstract/loaders.h src/json/jsoncpp.cpp src/loaders/low_level/JSON_Loader.cpp src/loaders/low_level/JSON_Loader.h src/loaders/misc/helpers.cpp src/loaders/misc/helpers.h src/loaders/abstract/Suite.cpp src/loaders/abstract/Suite.h src/loaders/abstract/Plan.cpp src/loaders/abstract/Plan.h src/loaders/abstract/Conf.cpp src/loaders/abstract/Conf.h src/loaders/abstract/Unit.cpp src/loaders/abstract/Unit.h src/loaders/abstract/Task.cpp src/loaders/abstract/Task.h src/Sproc/Sproc.cpp src/Sproc/Sproc.h src/Logger/Logger.cpp src/Logger/Logger.h) set(SOURCE_FILES Rex.cpp src/loaders/abstract/loaders.cpp src/loaders/abstract/loaders.h src/json/jsoncpp.cpp src/loaders/low_level/JSON_Loader.cpp src/loaders/low_level/JSON_Loader.h src/loaders/misc/helpers.cpp src/loaders/misc/helpers.h src/loaders/abstract/Suite.cpp src/loaders/abstract/Suite.h src/loaders/abstract/Plan.cpp src/loaders/abstract/Plan.h src/loaders/abstract/Conf.cpp src/loaders/abstract/Conf.h src/loaders/abstract/Unit.cpp src/loaders/abstract/Unit.h src/loaders/abstract/Task.cpp src/loaders/abstract/Task.h src/Sproc/Sproc.cpp src/Sproc/Sproc.h src/Logger/Logger.cpp src/Logger/Logger.h)
add_executable(rex ${SOURCE_FILES}) add_executable(rex ${SOURCE_FILES})

View File

@ -70,6 +70,8 @@ protected:
Conf::Conf(std::string filename, int LOG_LEVEL ): JSON_Loader(LOG_LEVEL ), slog(LOG_LEVEL, "_conf_" ) Conf::Conf(std::string filename, int LOG_LEVEL ): JSON_Loader(LOG_LEVEL ), slog(LOG_LEVEL, "_conf_" )
{ {
this->LOG_LEVEL = LOG_LEVEL; this->LOG_LEVEL = LOG_LEVEL;
std::string jval_s;
bool jval_b;
// prepare context spaghetti // prepare context spaghetti
this->override_context = false; this->override_context = false;
@ -83,65 +85,59 @@ Conf::Conf(std::string filename, int LOG_LEVEL ): JSON_Loader(LOG_LEVEL ), slog(
throw ConfigLoadException("Config file not found."); throw ConfigLoadException("Config file not found.");
} }
if (this->get_serialized(this->config_version, "config_version" ) != 0)
{
throw ConfigLoadException("config_version string is not set in the config file supplied: " + filename);
}
if ( this->config_version.asString() != VERSION_STRING )
{
throw ConfigLoadException("config_version string expected was " + std::string(VERSION_STRING) + " in: " + filename);
}
// find the path to the unit definitions file // find the path to the unit definitions file
if (this->get_serialized(this->units_path, "units_path" ) != 0 ) if (this->get_string(jval_s, "units_path") != 0 )
{ { throw ConfigLoadException("units_path string is not set in the config file supplied: " + filename); } else {
throw ConfigLoadException("units_path string is not set in the config file supplied: " + filename); this->units_path = jval_s;
} }
jval_s = {0};
// find the path to logs directory // find the path to logs directory
if (this->get_serialized(this->logs_path, "logs_path" ) != 0 ) if (this->get_string(jval_s, "logs_path") != 0 )
{ { throw ConfigLoadException("logs_path string is not set in the config file supplied: " + filename); } else {
throw ConfigLoadException("logs_path string is not set in the config file supplied: " + filename); this->logs_path = jval_s;
} }
jval_s = {0};
if ( this->get_serialized(this->override_execution_context, "execution_context_override" ) != 0 ) if (this->get_bool(jval_b, "execution_context_override") != 0 )
{ { throw ConfigLoadException("execution_context_override boolean is not set in the config file supplied: " + filename); } else {
throw ConfigLoadException("execution_context_override boolean is not set in the config file supplied: " + filename); this->override_context = jval_b;
} else {
this->override_context = true;
} }
jval_b = {0};
if ( this->get_serialized(this->execution_context, "execution_context" ) != 0 ) if (this->get_string(jval_s, "execution_context") != 0 )
{ { throw ConfigLoadException("execution_context string is not set in the config file supplied: " + filename); } else {
throw ConfigLoadException("execution_context string is not set in the config file supplied: " + filename); if ( ! is_dir( jval_s ) ) { throw ConfigLoadException( "The execution context supplied is an invalid directory."); } else {
} else { this->execution_context = jval_s;
if ( is_dir( this->execution_context.asString() ) ) {
this->execution_context_literal = this->execution_context.asString();
} else {
throw ConfigLoadException( "The execution context supplied is an invalid directory.");
} }
} }
jval_s = {0};
interpolate( this->units_path );
interpolate( this->logs_path );
interpolate( this->execution_context );
}; };
/// Conf::has_context_override - Specifies whether or not the override context function is enabled in the Conf file. /// Conf::has_context_override - Specifies whether or not the override context function is enabled in the Conf file.
bool Conf::has_context_override() { bool Conf::has_context_override() {
return this->override_execution_context.asBool(); return this->override_execution_context;
} }
/// Conf::get_execution_context - Specifies the path to the current working directory to set for all unit executions. /// Conf::get_execution_context - Specifies the path to the current working directory to set for all unit executions.
std::string Conf::get_execution_context() { std::string Conf::get_execution_context() {
return this->execution_context_literal; return this->execution_context;
} }
/// Conf::get_units_path - Retrieves the path to the Unit definition file from the application configuration file. /// Conf::get_units_path - Retrieves the path to the Unit definition file from the application configuration file.
std::string Conf::get_units_path() { return this->units_path.asString(); } std::string Conf::get_units_path() { return this->units_path; }
/// Conf::get_units_path - Retrieves the path to the Unit definition file from the application configuration file. /// Conf::get_units_path - Retrieves the path to the Unit definition file from the application configuration file.
std::string Conf::get_logs_path() { return this->logs_path.asString(); } std::string Conf::get_logs_path() { return this->logs_path; }
/// Conf::set_execution_context- Sets the execution context. /// Conf::set_execution_context- Sets the execution context.
void Conf::set_execution_context(std::string execution_context ) void Conf::set_execution_context(std::string execution_context )
{ {
this->execution_context_literal = execution_context; this->execution_context = execution_context;
} }

View File

@ -28,25 +28,23 @@
#define STRINGIZE2(s) #s #define STRINGIZE2(s) #s
#define STRINGIZE(s) STRINGIZE2(s) #define STRINGIZE(s) STRINGIZE2(s)
# define IMPL_CONFIG_VERSION 4 # define IMPL_CONFIG_VERSION 5
# define VERSION_STRING STRINGIZE(IMPL_CONFIG_VERSION) # define VERSION_STRING STRINGIZE(IMPL_CONFIG_VERSION)
class Conf: public JSON_Loader class Conf: public JSON_Loader
{ {
private: private:
Json::Value plan_path; std::string plan_path;
Json::Value units_path; std::string units_path;
Json::Value execution_context; std::string execution_context;
Json::Value config_version; std::string logs_path;
Json::Value logs_path;
// flag to indicate if execution context should be overriden in config file // flag to indicate if execution context should be overriden in config file
// if set to true rex should use whats in the config file for current working directory // if set to true rex should use whats in the config file for current working directory
// if set to false, rex should use the current working directory at time of execution // if set to false, rex should use the current working directory at time of execution
Json::Value override_execution_context; bool override_execution_context;
bool override_context; bool override_context;
std::string execution_context_literal;
public: public:
Conf( std::string filename, int LOG_LEVEL ); Conf( std::string filename, int LOG_LEVEL );

View File

@ -150,3 +150,57 @@ int JSON_Loader::get_serialized(Json::Value &input, std::string key )
// exit code for failure // exit code for failure
return 1; return 1;
} }
/// JSON_Loader::get_string - assigns the serialized representation of the value of a key (json::value)
///
/// \param input - A reference to the json::value object to receive the new value.
/// \param key - The JSON key name to assign the value to (the root of the json::value object by name)
/// \param verbose - Whether or not to print verbose output to STDOUT.
/// \return - Boolean indicator of success or failure (0|1)
int JSON_Loader::get_string( std::string &input, std::string key )
{
// throw if the class is not ready to be used.
if ( ! this->populated ) { throw JSON_Loader_NotReady(); }
if ( this->json_root.isMember( key ) )
{
// key was found so return it to the passed input ref
input = this->json_root[ key ].asString();
return 0;
}
// key was not found
// verbose mode tells the user what key we were looking for.
this->slog.log( E_FATAL, "Failed to find key '" + key + "'." );
// exit code for failure
return 1;
}
/// JSON_Loader::get_bool - assigns the serialized representation of the value of a key (json::value)
///
/// \param input - A reference to the json::value object to receive the new value.
/// \param key - The JSON key name to assign the value to (the root of the json::value object by name)
/// \param verbose - Whether or not to print verbose output to STDOUT.
/// \return - Boolean indicator of success or failure (0|1)
int JSON_Loader::get_bool( bool & input, std::string key )
{
// throw if the class is not ready to be used.
if ( ! this->populated ) { throw JSON_Loader_NotReady(); }
if ( this->json_root.isMember( key ) )
{
// key was found so return it to the passed input ref
input = this->json_root[ key ].asBool();
return 0;
}
// key was not found
// verbose mode tells the user what key we were looking for.
this->slog.log( E_FATAL, "Failed to find key '" + key + "'." );
// exit code for failure
return 1;
}

View File

@ -51,6 +51,8 @@ class JSON_Loader
// safely handle deserialized type retrieval (if we want it to be safe) // safely handle deserialized type retrieval (if we want it to be safe)
int get_serialized( Json::Value & input, std::string key ); int get_serialized( Json::Value & input, std::string key );
int get_string(std::string & input, std::string key );
int get_bool(bool & input, std::string key );
private: private:
Logger slog; Logger slog;

View File

@ -57,3 +57,16 @@ std::string get_8601()
ss << std::put_time(localtime(&itt), "%Y-%m-%d_%H:%M:%S"); ss << std::put_time(localtime(&itt), "%Y-%m-%d_%H:%M:%S");
return ss.str(); return ss.str();
} }
void interpolate( std::string & text )
{
static std::regex env( "\\$\\{([^}]+)\\}" );
std::smatch match;
while ( std::regex_search( text, match, env ) )
{
const char * s = getenv( match[1].str().c_str() );
const std::string var( s == NULL ? "" : s );
text.replace( match[0].first, match[0].second, var );
}
}

View File

@ -32,14 +32,22 @@
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
#include <regex>
bool exists (const std::string& name); bool exists (const std::string& name);
std::string get_working_path(); std::string get_working_path();
bool is_file( std::string ); bool is_file( std::string );
bool is_dir( std::string ); bool is_dir( std::string );
// expand environment variables in string
void interpolate( std::string & text);
std::string get_8601(); std::string get_8601();
const char * command2args( std::string input_string ); const char * command2args( std::string input_string );
#endif //REX_HELPERS_JH #endif //REX_HELPERS_JH