pre-release
parent
4b3a9170bf
commit
89f734de84
|
@ -1,7 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
project(examplar)
|
||||
project(rex)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++1z -O0 -DDEBUG=1")
|
||||
set(SOURCE_FILES examplar.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(examplar ${SOURCE_FILES})
|
||||
add_executable(rex ${SOURCE_FILES})
|
||||
|
|
38
README.md
38
README.md
|
@ -1,19 +1,19 @@
|
|||
# Examplar
|
||||
# Rex
|
||||
|
||||
## What is Examplar?
|
||||
## What is Rex?
|
||||
|
||||
Examplar is an execution flow component designed for the generation of SURRO Linux but kept broad in design for other use cases.
|
||||
Rex is an execution flow component designed for the generation of SURRO Linux but kept broad in design for other use cases.
|
||||
|
||||
At a high level, it is a very simple thing: It executes scripts and other executables in a predetermined order, logs their output, and has basic error handling using exit codes of the executables it is running.
|
||||
|
||||
It relies on a library of Units which are files that define, in json format, what executables it can execute. It uses a Plan to define which of those units it will actually execute. This allows you to have many things defined by multiple teams, and, with sufficient abstraction, use the same library of automations for multiple purposes.
|
||||
|
||||
# Instructions
|
||||
These are instructions for using Examplar.
|
||||
These are instructions for using Rex.
|
||||
|
||||
## Build
|
||||
|
||||
Compiling Examplar is easy. There are zero external dependencies. Build does require *cmake*.
|
||||
Compiling Rex is easy. There are zero external dependencies. Build does require *cmake*.
|
||||
|
||||
~~~~
|
||||
$ cmake .
|
||||
|
@ -31,39 +31,39 @@ Then place the binary where you'd like. I'd recommend packaging it for your fav
|
|||
5. Turn on the rectify pattern in the unit definition.
|
||||
|
||||
## Definitions
|
||||
So you've got Examplar compiled and you're ready to start automating the world.
|
||||
So you've got Rex compiled and you're ready to start automating the world.
|
||||
|
||||
If you're thinking "how do I configure this thing", this article is for you.
|
||||
|
||||
### Units
|
||||
|
||||
A Unit is an automation definition, written in JSON in a UNIT FILE. Deeper into Examplar’s internals, Units and Tasks have slightly different functions, but for the purposes of users, the terms can be used interchangeably. A Task is a task to be performed in a Plan, and a Unit is its definition. A Unit is a JSON object that has:
|
||||
A Unit is an automation definition, written in JSON in a UNIT FILE. Deeper into Rex’s internals, Units and Tasks have slightly different functions, but for the purposes of users, the terms can be used interchangeably. A Task is a task to be performed in a Plan, and a Unit is its definition. A Unit is a JSON object that has:
|
||||
|
||||
* A `name`, which is an identifier for the Unit used by people.
|
||||
* A `target`, which is the path to the automation script performing the work. This provides a clean linear path for huge chains of scripts to be executed in order and tracked on return for additional logic in chaining.
|
||||
* A `rectifier`, which is the path to the automation script to be executed if the target call fails.
|
||||
* A `rectify` attribute, which tells Examplar whether or not to execute the rectifier in the case of failure when executing the target.
|
||||
* An `active` attribute,which tells Examplar whether or not the Unit can be used in a Plan. This gives Unit developers a way to tell Plan developers not to use the Unit.
|
||||
* A `required` attribute which tells Examplar whether or not the Plan can continue if the Unit fails. If the rectify attribute is set to true, this attribute is checked after a rectifier failure. If not, this is checked after target failure. In either case, if the rectifier or target do not return successfully, Examplar will halt the execution of the Plan if this is turned on for the unit being executed. Otherwise it simply moves to the next Unit being executed.
|
||||
* A `rectify` attribute, which tells Rex whether or not to execute the rectifier in the case of failure when executing the target.
|
||||
* An `active` attribute,which tells Rex whether or not the Unit can be used in a Plan. This gives Unit developers a way to tell Plan developers not to use the Unit.
|
||||
* A `required` attribute which tells Rex whether or not the Plan can continue if the Unit fails. If the rectify attribute is set to true, this attribute is checked after a rectifier failure. If not, this is checked after target failure. In either case, if the rectifier or target do not return successfully, Rex will halt the execution of the Plan if this is turned on for the unit being executed. Otherwise it simply moves to the next Unit being executed.
|
||||
|
||||
### Tasks
|
||||
|
||||
A Task is an action item in a Plan, just like in real life. In the context of Examplar, a Task is a Unit that has been loaded and incorporated into a Plan in an actionable state. Inactive Units can not be loaded into a Plan and thus can never be a Task. The primary difference between a Task and a Unit is that a Unit is not actionable — it’s just a definition — while a Task a consumable, actionable automation.
|
||||
A Task is an action item in a Plan, just like in real life. In the context of Rex, a Task is a Unit that has been loaded and incorporated into a Plan in an actionable state. Inactive Units can not be loaded into a Plan and thus can never be a Task. The primary difference between a Task and a Unit is that a Unit is not actionable — it’s just a definition — while a Task a consumable, actionable automation.
|
||||
Suite
|
||||
|
||||
A Suite is not visible to the user and this is only for informational purposes. A Suite is a collection of all available Unit definitions loaded from one or more UNIT FILES. Just as a Unit is the definition for a Task, a Suite is a collection of Units that define the Task components of a Plan.
|
||||
|
||||
A Suite is consumed by a Plan during the conversion of Units to Tasks, though this is not visible to the user — it just simply helps to understand the kind of abstraction taking place in the conceptual model of Examplar.
|
||||
A Suite is consumed by a Plan during the conversion of Units to Tasks, though this is not visible to the user — it just simply helps to understand the kind of abstraction taking place in the conceptual model of Rex.
|
||||
Plan
|
||||
|
||||
A Plan is the glue of all the components of Examplar and is deceptively simple. A Plan loads a Suite for its Task definitions (Units), but the Tasks to actually execute are specified in the PLAN FILE. The Tasks are executed in the order specified in the PLAN FILE.
|
||||
A Plan is the glue of all the components of Rex and is deceptively simple. A Plan loads a Suite for its Task definitions (Units), but the Tasks to actually execute are specified in the PLAN FILE. The Tasks are executed in the order specified in the PLAN FILE.
|
||||
|
||||
### FILES
|
||||
There are several files used by Examplar.
|
||||
There are several files used by Rex.
|
||||
|
||||
#### CONFIG FILE and Attributes
|
||||
|
||||
This is the one config file that Examplar uses. The default path it looks is /etc/Examplar/config.json.
|
||||
This is the one config file that Rex uses. The default path it looks is /etc/Rex/config.json.
|
||||
|
||||
A config file at the time of writing this specifies a single JSON object with 5 attributes:
|
||||
|
||||
|
@ -75,7 +75,7 @@ A config file at the time of writing this specifies a single JSON object with 5
|
|||
|
||||
#### Configuration VERSION
|
||||
|
||||
The configuration version is checked to ensure that the configuration is consumable by that version of Examplar. This will pave the way for reverse compatibility if the project moves in that direction.
|
||||
The configuration version is checked to ensure that the configuration is consumable by that version of Rex. This will pave the way for reverse compatibility if the project moves in that direction.
|
||||
|
||||
|
||||
#### UNIT FILE
|
||||
|
@ -123,10 +123,10 @@ Next, add the unit to the plan by name.
|
|||
### 5. Set up your config file.
|
||||
Point your config file at your plan file and your units directory.
|
||||
|
||||
### 6. Run Examplar pointing at that config file.
|
||||
Execute examplar:
|
||||
### 6. Run Rex pointing at that config file.
|
||||
Execute rex:
|
||||
|
||||
examplar --verbose --config path/to/your/config/file.json
|
||||
rex --verbose --config path/to/your/config/file.json
|
||||
|
||||
And you should see your 'hello world' script.
|
||||
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
Rex - A unit-based automation, workflow, and testing system.
|
||||
|
||||
© SILO GROUP and Chris Punches, 2017.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "src/loaders/abstract/loaders.h"
|
||||
#include "src/Logger/Logger.h"
|
||||
|
||||
void version_info()
|
||||
{
|
||||
std::cout << "pre-release alpha" << std::endl;
|
||||
}
|
||||
|
||||
void print_usage()
|
||||
{
|
||||
// commandline switches:
|
||||
// -h help OPTIONAL
|
||||
// -v verbose OPTIONAL
|
||||
// -c CONFIG_FILE REQUIRED
|
||||
// -p PLAN_FILE REQUIRED
|
||||
|
||||
fprintf( stderr, "\nUsage:\n\trex [ -h | --help ] [ -v | --verbose ] ( ( ( -c | --config ) CONFIG_PATH ) ( -p | plan ) PLAN_PATH ) )\n" );
|
||||
|
||||
fprintf( stderr, "\nOptional Arguments:\n");
|
||||
fprintf( stderr, "\t-h | --help\n\t\tThis usage screen. Mutually exclusive to all other options.\n");
|
||||
fprintf( stderr, "\t-v | --verbose\n\t\tSets verbose output. Generally more than you want to see.\n");
|
||||
fprintf( stderr, "\nRequired Arguments:\n");
|
||||
fprintf( stderr, "\t-c | --config\n\t\tSupply the directory path for the configuration file.\n");
|
||||
fprintf( stderr, "\t-p | --plan\n\t\tSupply the directory path for the plan file to execute.\n\n");
|
||||
}
|
||||
|
||||
int main( int argc, char * argv[] )
|
||||
{
|
||||
// default verbosity setting
|
||||
int verbose_flag = false;
|
||||
|
||||
// whether to show usage screen
|
||||
int help_flag = false;
|
||||
|
||||
// did the user supply an argument to config
|
||||
int config_flag = false;
|
||||
|
||||
// did the user supply an argument to plan
|
||||
int plan_flag = false;
|
||||
|
||||
// did the user ask for the version info
|
||||
int version_flag = false;
|
||||
|
||||
// default config path
|
||||
std::string config_path;
|
||||
|
||||
// default plan path
|
||||
std::string plan_path;
|
||||
|
||||
// initialise for commandline argument processing
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
if ( argc <= 1 )
|
||||
{
|
||||
help_flag = true;
|
||||
}
|
||||
|
||||
// process commandline arguments
|
||||
while ( 1 )
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
|
||||
// commandline argument structure
|
||||
static struct option long_options[] = {
|
||||
{"verbose_flag", no_argument, 0, 'v' },
|
||||
{"version_info", no_argument, 0, 'i' },
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"config", required_argument, 0, 'c' },
|
||||
{"plan", required_argument, 0, 'p' },
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "vihc:p:", long_options, &option_index );
|
||||
if ( c == -1 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( c )
|
||||
{
|
||||
case 'i':
|
||||
version_flag = true;
|
||||
case 'h':
|
||||
help_flag = true;
|
||||
break;
|
||||
case 'v':
|
||||
verbose_flag = true;
|
||||
break;
|
||||
case 'c':
|
||||
config_flag = true;
|
||||
config_path = std::string( optarg );
|
||||
break;
|
||||
case 'p':
|
||||
plan_flag = true;
|
||||
plan_path = std::string( optarg );
|
||||
break;
|
||||
case '?':
|
||||
help_flag = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} // end switch
|
||||
} // end opts while
|
||||
|
||||
if ( version_flag ) {
|
||||
version_info();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// if the user supplied no config file, there's nothing to do but teach the user how to use this tool
|
||||
if (! config_flag ) {
|
||||
std::cerr << "NOT SUPPLIED: CONFIG_PATH" << std::endl;
|
||||
help_flag = true;
|
||||
}
|
||||
|
||||
// if the user supplied no plan file, there's nothing to do but teach the user how to use this tool
|
||||
if (! plan_flag ) {
|
||||
std::cerr << "NOT SUPPLIED: PLAN_PATH" << std::endl;
|
||||
help_flag = true;
|
||||
}
|
||||
|
||||
// if the user wants the help screen, just show it and leave
|
||||
if ( (help_flag) | (! config_flag) | (! plan_flag) )
|
||||
{
|
||||
print_usage();
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
// default logging level
|
||||
int L_LEVEL = E_INFO;
|
||||
|
||||
// if set to verbose_flag mode, output with DEBUG level verbosity
|
||||
if ( verbose_flag )
|
||||
{
|
||||
std::cout << "Setting verbosity level to 'DBUG'..." << std::endl;
|
||||
L_LEVEL = E_DEBUG;
|
||||
}
|
||||
|
||||
// the main scope logger
|
||||
Logger slog = Logger( L_LEVEL, "_main_" );
|
||||
slog.log( E_INFO, "* Initialising Logging...");
|
||||
|
||||
// configuration object that reads from config_path
|
||||
Conf configuration = Conf( config_path, L_LEVEL );
|
||||
|
||||
// check if context override is set in the config file
|
||||
if ( configuration.has_context_override() )
|
||||
{
|
||||
// if so, set the CWD.
|
||||
chdir( configuration.get_execution_context().c_str() );
|
||||
slog.log( E_DEBUG, "* Setting execution context: " + get_working_path() );
|
||||
}
|
||||
|
||||
// The Rex Paradigm:
|
||||
// - A Suite is made up of Units.
|
||||
// - A Unit is a definition of an executable along with various options surrounding its context and behaviour.
|
||||
// - A Plan is made up of Tasks.
|
||||
// - A Unit becomes a Task when it is added to a Plan.
|
||||
|
||||
// A Plan contains what units are executed and a Suite contains the definitions of those units.
|
||||
std::string plan_file = plan_path;
|
||||
|
||||
// load the filepaths to definitions of a plan and definitions of units.
|
||||
std::string definitions_file = configuration.get_units_path();
|
||||
|
||||
// initialise an empty suite (unit definitions library)
|
||||
slog.log( E_DEBUG, "* Initialising Suite...");
|
||||
Suite available_definitions = Suite( L_LEVEL );
|
||||
|
||||
// load units into suite
|
||||
slog.log( E_INFO, "* Loading all actionable Units into Suite..." );
|
||||
available_definitions.load_units_file( definitions_file );
|
||||
|
||||
// initialise an empty plan
|
||||
slog.log( E_DEBUG, "* Initialising Plan..." );
|
||||
Plan plan = Plan( &configuration, L_LEVEL );
|
||||
|
||||
// load the plan the user supplied
|
||||
slog.log( E_INFO, "* Loading Plan...");
|
||||
plan.load_plan_file( plan_file );
|
||||
|
||||
// ingest the suitable Tasks from the Suite into the Plan
|
||||
slog.log( E_INFO, "* Loading planned Tasks from Suite to Plan." );
|
||||
plan.load_definitions( available_definitions );
|
||||
|
||||
slog.log( E_INFO, "* Ready to execute all actionable Tasks in Plan." );
|
||||
|
||||
try
|
||||
{
|
||||
plan.execute();
|
||||
}
|
||||
|
||||
catch ( std::exception& e)
|
||||
{
|
||||
slog.log( E_FATAL, "Caught exception.");
|
||||
slog.log( E_FATAL, e.what() );
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
# Logic Tree for Examplar Task Execution
|
||||
# Logic Tree for Rex Task Execution
|
||||
|
||||
Examplar - An automation and testing framework.
|
||||
Rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
|
170
examplar.cpp
170
examplar.cpp
|
@ -1,170 +0,0 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "src/json/json.h"
|
||||
#include "src/loaders/abstract/loaders.h"
|
||||
#include "src/Logger/Logger.h"
|
||||
#include "src/loaders/misc/helpers.h"
|
||||
|
||||
void print_usage()
|
||||
{
|
||||
printf("examplar [ -h | --help ] [ -v | --verbose ] [ -e | --execution-context EXECUTION_CONTEXT ][ -c | --config CONFIG_PATH ]\n\n");
|
||||
}
|
||||
|
||||
int main( int argc, char * argv[] )
|
||||
{
|
||||
int opt;
|
||||
bool verbose = false;
|
||||
bool show_help = false;
|
||||
|
||||
// indicator of whether examplar should use a commandline argument for overriding the context
|
||||
// instead of what's supplied in the test file
|
||||
bool cli_context_supplied = false;
|
||||
|
||||
std::string config_path = "/etc/Examplar/config.json";
|
||||
std::string execution_context;
|
||||
|
||||
// commandline switches:
|
||||
// -h help
|
||||
// -v verbose
|
||||
// -c CONFIG_FILE_PATH -- defaults to '/etc/Examplar/config.json'
|
||||
// -e EXECUTION_CONTEXT -- current working directory when executing unit targets
|
||||
|
||||
while (1)
|
||||
{
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"config", required_argument, 0, 'c'},
|
||||
{"execution-context", required_argument, 0, 'e'},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
int option_index = 0;
|
||||
|
||||
opt = getopt_long( argc, argv, "vhec:", long_options, &option_index );
|
||||
|
||||
if ( opt == -1 )
|
||||
break;
|
||||
|
||||
switch ( opt )
|
||||
{
|
||||
case 0:
|
||||
if ( long_options[option_index].flag !=0 )
|
||||
break;
|
||||
case 'h':
|
||||
show_help = true;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
case 'c':
|
||||
config_path = std::string( optarg );
|
||||
break;
|
||||
case '?':
|
||||
print_usage();
|
||||
exit( 1 );
|
||||
case 'e':
|
||||
cli_context_supplied = true;
|
||||
execution_context = std::string( optarg );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( show_help )
|
||||
{
|
||||
print_usage();
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
int L_LEVEL = E_INFO;
|
||||
if ( verbose )
|
||||
{
|
||||
L_LEVEL = E_DEBUG;
|
||||
std::cout << "Verbosity is DBUG." << std::endl;
|
||||
} else {
|
||||
L_LEVEL = E_INFO;
|
||||
std::cout << "Verbosity is INFO." << std::endl;
|
||||
}
|
||||
|
||||
Logger slog = Logger( L_LEVEL, "_main_" );
|
||||
|
||||
// A Plan is made up of Tasks, and a Suite is made up of Units.
|
||||
// A Plan declares what units are executed and a Suite declares the definitions of those units.
|
||||
Conf configuration = Conf(config_path, L_LEVEL );
|
||||
|
||||
// check if context override
|
||||
|
||||
if ( configuration.has_context_override() )
|
||||
{
|
||||
// if so, set the CWD.
|
||||
chdir( configuration.get_execution_context().c_str() );
|
||||
slog.log( E_DEBUG, "Set execution context: " + get_working_path() );
|
||||
}
|
||||
|
||||
// if the user set this option as a commandline argument
|
||||
if ( cli_context_supplied )
|
||||
{
|
||||
// override the test file's specified execution context
|
||||
configuration.set_execution_context( execution_context );
|
||||
slog.log( E_DEBUG, "Set execution context from commandline: " + execution_context );
|
||||
}
|
||||
|
||||
// load the filepaths to definitions of a plan and definitions of units.
|
||||
std::string definitions_file = configuration.get_units_path();
|
||||
std::string plan_file = configuration.get_plan_path();
|
||||
|
||||
slog.log( E_DEBUG, "* Initialising suite (definition library).");
|
||||
Suite available_definitions = Suite( L_LEVEL );
|
||||
|
||||
slog.log( E_INFO, "* Loading all actionable units into suite." );
|
||||
available_definitions.load_units_file( definitions_file );
|
||||
|
||||
slog.log( E_DEBUG, "* Initialising plan." );
|
||||
Plan plan = Plan( &configuration, L_LEVEL );
|
||||
|
||||
slog.log( E_INFO, "* Loading plan outline.");
|
||||
plan.load_plan_file( plan_file );
|
||||
|
||||
slog.log( E_INFO, "* Loading planned tasks from suite to plan." );
|
||||
plan.load_definitions( available_definitions );
|
||||
|
||||
slog.log( E_INFO, "* Ready to execute all actionable tasks in plan." );
|
||||
|
||||
try
|
||||
{
|
||||
plan.execute();
|
||||
}
|
||||
|
||||
catch ( std::exception& e)
|
||||
{
|
||||
slog.log( E_FATAL, "Caught exception.");
|
||||
slog.log( E_FATAL, e.what() );
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -10,7 +10,7 @@ Logger::Logger( int LOG_LEVEL, std::string mask )
|
|||
this->mask = mask;
|
||||
|
||||
setlogmask( LOG_UPTO( this->LOG_LEVEL ) );
|
||||
openlog( this->mask.c_str(), LOG_CONS | LOG_PID | LOG_NDELAY, LOG_PERROR | LOG_LOCAL1 );
|
||||
openlog( "rex", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_PERROR | LOG_LOCAL1 );
|
||||
|
||||
}
|
||||
|
||||
|
@ -33,19 +33,10 @@ void Logger::log( int LOG_LEVEL, std::string msg )
|
|||
|
||||
if ( LOG_LEVEL == E_FATAL | LOG_LEVEL == E_WARN )
|
||||
{
|
||||
std::cerr << "[" << this->get_8601() << "] [" << ERR << "] " << "[" << this->mask << "] " << msg.c_str() << std::endl;
|
||||
std::cerr << "[" << get_8601() << "] [" << ERR << "] " << "[" << this->mask << "] " << msg.c_str() << std::endl;
|
||||
} else {
|
||||
std::cout << "[" << this->get_8601() << "] [" << ERR << "] " << "[" << this->mask << "] " << msg.c_str() << std::endl;
|
||||
std::cout << "[" << get_8601() << "] [" << ERR << "] " << "[" << this->mask << "] " << msg.c_str() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string Logger::get_8601()
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto itt = std::chrono::system_clock::to_time_t(now);
|
||||
std::ostringstream ss;
|
||||
// ss << std::put_time(gmtime(&itt), "%FT%TZ");
|
||||
ss << std::put_time(localtime(&itt), "%Y-%m-%d_%H:%M:%S");
|
||||
return ss.str();
|
||||
}
|
|
@ -2,15 +2,15 @@
|
|||
// Created by bagira on 6/13/20.
|
||||
//
|
||||
|
||||
#ifndef EXAMPLAR_LOGGER_H
|
||||
#define EXAMPLAR_LOGGER_H
|
||||
#ifndef REX_LOGGER_H
|
||||
#define REX_LOGGER_H
|
||||
|
||||
#include <syslog.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include "../loaders/misc/helpers.h"
|
||||
|
||||
enum L_LVL {
|
||||
E_FATAL,
|
||||
|
@ -27,9 +27,8 @@ public:
|
|||
private:
|
||||
int LOG_LEVEL;
|
||||
std::string mask;
|
||||
std::string get_8601();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //EXAMPLAR_LOGGER_H
|
||||
#endif //REX_LOGGER_H
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include "Sproc.h"
|
||||
#include "../loaders/misc/helpers.h"
|
||||
#include "sys/stat.h"
|
||||
|
||||
#define PARENT default
|
||||
|
||||
|
@ -141,7 +143,7 @@ int set_identity_context( std::string task_name, std::string user_name, std::str
|
|||
///
|
||||
/// \param input - The commandline input to execute.
|
||||
/// \return - The return code of the execution of input in the calling shell.
|
||||
int Sproc::execute(std::string shell, std::string environment_file, std::string user_name, std::string group_name, std::string command, int LOG_LEVEL, std::string task_name )
|
||||
int Sproc::execute(std::string shell, std::string environment_file, std::string user_name, std::string group_name, std::string command, int LOG_LEVEL, std::string task_name, bool log_to_file, std::string logs_dir )
|
||||
{
|
||||
// the logger
|
||||
Logger slog = Logger( LOG_LEVEL, "_sproc" );
|
||||
|
@ -164,10 +166,25 @@ int Sproc::execute(std::string shell, std::string environment_file, std::string
|
|||
// potentially corrupting user interaction with TUIs in the processes. This should give us our log and our output
|
||||
// in as hands off a way as possible with as few assumptions as possible, while still doing this in a somewhat C++-y
|
||||
// way.
|
||||
if (! is_dir( logs_dir ) ) {
|
||||
int check = mkdir( logs_dir.c_str(), 0777 );
|
||||
if (! check ) {
|
||||
slog.log( E_FATAL, "Sprocket couldn't create the logs parent directory." );
|
||||
}
|
||||
}
|
||||
|
||||
std::string timestamp = get_8601();
|
||||
|
||||
std::string contained_dir = logs_dir + "/" + task_name;
|
||||
if (! is_dir( contained_dir ) ) {
|
||||
int check = mkdir( contained_dir.c_str(), 0777 );
|
||||
if (! check ) {
|
||||
slog.log( E_FATAL, "Sprocket couldn't create the instance log directory.");
|
||||
}
|
||||
}
|
||||
// set up the "Tee" with the parent
|
||||
std::string child_stdout_log_path = "./stdout.log";
|
||||
std::string child_stderr_log_path = "./stderr.log";
|
||||
std::string child_stdout_log_path = contained_dir + "/" + timestamp + ".stdout.log";
|
||||
std::string child_stderr_log_path = contained_dir + "/" + timestamp + ".stderr.log";
|
||||
|
||||
std::ofstream stdout_log;
|
||||
std::ofstream stderr_log;
|
||||
|
@ -316,9 +333,13 @@ int Sproc::execute(std::string shell, std::string environment_file, std::string
|
|||
set_stdout_break = true;
|
||||
break;
|
||||
default:
|
||||
tee_out.write( stdout_buf, stdout_count );
|
||||
tee_out.flush();
|
||||
|
||||
if ( log_to_file ) {
|
||||
tee_out.write( stdout_buf, stdout_count );
|
||||
tee_out.flush();
|
||||
} else {
|
||||
std::cout.write( stdout_buf, stdout_count );
|
||||
std::cout.flush();
|
||||
}
|
||||
// clear the buffer to prevent artifacts from previous loop
|
||||
memset( &stdout_buf[0], 0, sizeof( stdout_buf ) -1 );
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FTESTS_SPROC_H
|
||||
#define FTESTS_SPROC_H
|
||||
#ifndef REX_SPROCKET_H
|
||||
#define REX_SPROCKET_H
|
||||
|
||||
#include "../Logger/Logger.h"
|
||||
#include <iostream>
|
||||
|
@ -61,7 +61,9 @@ class Sproc {
|
|||
std::string group_name,
|
||||
std::string command,
|
||||
int LOG_LEVEL,
|
||||
std::string task_name
|
||||
std::string task_name,
|
||||
bool log_to_file,
|
||||
std::string logs_dir
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -88,4 +90,4 @@ class teestream : public std::ostream
|
|||
teebuf tbuf;
|
||||
};
|
||||
|
||||
#endif //FTESTS_SPROC_H
|
||||
#endif //REX_SPROCKET_H
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -66,7 +66,7 @@ protected:
|
|||
/// TODO Expand to detect when a directory path is supplied for units_path or plan_path and import all Tasks and Units.
|
||||
///
|
||||
/// \param filename - The filename to load the configuration from.
|
||||
Conf::Conf( std::string filename, int LOG_LEVEL ): JSON_Loader( LOG_LEVEL ), slog( LOG_LEVEL, "e_conf" )
|
||||
Conf::Conf(std::string filename, int LOG_LEVEL ): JSON_Loader(LOG_LEVEL ), slog(LOG_LEVEL, "_conf_" )
|
||||
{
|
||||
this->LOG_LEVEL = LOG_LEVEL;
|
||||
|
||||
|
@ -91,18 +91,18 @@ Conf::Conf( std::string filename, int LOG_LEVEL ): JSON_Loader( LOG_LEVEL ), slo
|
|||
throw ConfigLoadException("config_version string expected was " + std::string(VERSION_STRING) + " in: " + filename);
|
||||
}
|
||||
|
||||
// find the path to the plan file
|
||||
if ( this->get_serialized(this->plan_path, "plan_path" ) != 0 )
|
||||
{
|
||||
throw ConfigLoadException("plan_path string is not set in the config file supplied:" + filename);
|
||||
}
|
||||
|
||||
// find the path to the unit definitions file
|
||||
if (this->get_serialized(this->units_path, "units_path" ) != 0 )
|
||||
{
|
||||
throw ConfigLoadException("units_path string is not set in the config file supplied: " + filename);
|
||||
}
|
||||
|
||||
// find the path to logs directory
|
||||
if (this->get_serialized(this->logs_path, "logs_path" ) != 0 )
|
||||
{
|
||||
throw ConfigLoadException("logs_path string is not set in the config file supplied: " + filename);
|
||||
}
|
||||
|
||||
if ( this->get_serialized(this->override_execution_context, "execution_context_override" ) != 0 )
|
||||
{
|
||||
throw ConfigLoadException("execution_context_override boolean is not set in the config file supplied: " + filename);
|
||||
|
@ -114,11 +114,15 @@ Conf::Conf( std::string filename, int LOG_LEVEL ): JSON_Loader( LOG_LEVEL ), slo
|
|||
{
|
||||
throw ConfigLoadException("execution_context string is not set in the config file supplied: " + filename);
|
||||
} else {
|
||||
this->execution_context_literal = this->execution_context.asString();
|
||||
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.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// 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() {
|
||||
return this->override_execution_context.asBool();
|
||||
}
|
||||
|
@ -128,14 +132,14 @@ std::string Conf::get_execution_context() {
|
|||
return this->execution_context_literal;
|
||||
}
|
||||
|
||||
/// Conf::get_plan_path - Retrieves the path to the Plan definition file from the application configuration file.
|
||||
std::string Conf::get_plan_path() { return this->plan_path.asString(); }
|
||||
|
||||
/// 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(); }
|
||||
|
||||
/// 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(); }
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
|||
|
||||
*/
|
||||
|
||||
#ifndef FTESTS_CONF_H
|
||||
#define FTESTS_CONF_H
|
||||
#ifndef REX_CONF_H
|
||||
#define REX_CONF_H
|
||||
#include "../low_level/JSON_Loader.h"
|
||||
#include <exception>
|
||||
#include "../../Logger/Logger.h"
|
||||
|
@ -27,7 +27,7 @@
|
|||
|
||||
#define STRINGIZE2(s) #s
|
||||
#define STRINGIZE(s) STRINGIZE2(s)
|
||||
# define IMPL_CONFIG_VERSION 3
|
||||
# define IMPL_CONFIG_VERSION 4
|
||||
# define VERSION_STRING STRINGIZE(IMPL_CONFIG_VERSION)
|
||||
|
||||
class Conf: public JSON_Loader
|
||||
|
@ -37,23 +37,24 @@ private:
|
|||
Json::Value units_path;
|
||||
Json::Value execution_context;
|
||||
Json::Value config_version;
|
||||
Json::Value logs_path;
|
||||
|
||||
// flag to indicate if execution context should be overriden in config file
|
||||
// if set to true Examplar should use whats in the config file for current working directory
|
||||
// if set to false, Examplar should use the current working directory at time of execution
|
||||
// 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
|
||||
Json::Value override_execution_context;
|
||||
|
||||
bool override_context;
|
||||
std::string execution_context_literal;
|
||||
|
||||
public:
|
||||
Conf( std::string filename, int LOG_LEVEL );
|
||||
Conf(std::string filename, int LOG_LEVEL );
|
||||
|
||||
bool has_context_override();
|
||||
|
||||
std::string get_plan_path();
|
||||
std::string get_units_path();
|
||||
std::string get_execution_context();
|
||||
std::string get_logs_path();
|
||||
|
||||
void set_execution_context( std::string );
|
||||
|
||||
|
@ -63,4 +64,4 @@ private:
|
|||
|
||||
};
|
||||
|
||||
#endif //FTESTS_CONF_H
|
||||
#endif //REX_CONF_H
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -120,7 +120,7 @@ protected:
|
|||
/// Plan::Plan() - Constructor for Plan class. A Plan is a managed container for a Task vector. These tasks reference
|
||||
/// Units that are defined in the Units files (Suite). If Units are definitions, Tasks are selections of those
|
||||
/// definitions to execute, and if Units together form a Suite, Tasks together form a Plan.
|
||||
Plan::Plan( Conf * configuration, int LOG_LEVEL ): JSON_Loader( LOG_LEVEL ), slog( LOG_LEVEL, "e_plan" )
|
||||
Plan::Plan(Conf * configuration, int LOG_LEVEL ): JSON_Loader(LOG_LEVEL ), slog(LOG_LEVEL, "_plan_" )
|
||||
{
|
||||
this->configuration = configuration;
|
||||
this->LOG_LEVEL = LOG_LEVEL;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
|||
|
||||
*/
|
||||
|
||||
#ifndef FTESTS_PLAN_H
|
||||
#define FTESTS_PLAN_H
|
||||
#ifndef REX_PLAN_H
|
||||
#define REX_PLAN_H
|
||||
|
||||
#include <string>
|
||||
#include "../../json/json.h"
|
||||
|
@ -36,7 +36,7 @@ class Plan: public JSON_Loader
|
|||
Conf * configuration;
|
||||
|
||||
public:
|
||||
Plan( Conf * configuration, int LOG_LEVEL );
|
||||
Plan(Conf * configuration, int LOG_LEVEL );
|
||||
|
||||
// append this->tasks from JSON file
|
||||
void load_plan_file( std::string filename );
|
||||
|
@ -63,4 +63,4 @@ private:
|
|||
Logger slog;
|
||||
};
|
||||
|
||||
#endif //FTESTS_PLAN_H
|
||||
#endif //REX_PLAN_H
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
|||
|
||||
*/
|
||||
|
||||
#ifndef FTESTS_UNITS_H
|
||||
#define FTESTS_UNITS_H
|
||||
#ifndef REX_UNITS_H
|
||||
#define REX_UNITS_H
|
||||
|
||||
#include <vector>
|
||||
#include "../../json/json.h"
|
||||
|
@ -54,4 +54,4 @@ private:
|
|||
Logger slog;
|
||||
};
|
||||
|
||||
#endif //FTESTS_UNITS_H
|
||||
#endif //REX_UNITS_H
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -80,7 +80,7 @@ protected:
|
|||
/// Task::Task() - Constructor for the Task class. The Task is the building block of a Plan indicating of which Unit to
|
||||
/// execute, and its dependencies on other units to have already been completed successfully.
|
||||
Task::Task( int LOG_LEVEL ):
|
||||
slog( LOG_LEVEL, "e_task" ),
|
||||
slog( LOG_LEVEL, "_task_" ),
|
||||
definition( LOG_LEVEL )
|
||||
{
|
||||
// it hasn't executed yet.
|
||||
|
@ -165,9 +165,9 @@ bool Task::has_definition()
|
|||
/// Task::execute - execute a task's unit definition.
|
||||
/// See the design document for what flow control needs to look like here.
|
||||
/// \param verbose - Verbosity level - not implemented yet.
|
||||
void Task::execute( Conf * configuration )
|
||||
void Task::execute(Conf * configuration )
|
||||
{
|
||||
// DUFFING - If Examplar is broken it's probably going to be in this block.
|
||||
// DUFFING - If rex is broken it's probably going to be in this block.
|
||||
// Somebody come clean this up, eh?
|
||||
|
||||
// PREWORK
|
||||
|
@ -219,7 +219,9 @@ void Task::execute( Conf * configuration )
|
|||
this->definition.get_group(),
|
||||
target_command,
|
||||
this->LOG_LEVEL,
|
||||
task_name
|
||||
task_name,
|
||||
this->definition.get_stdout_log_flag(),
|
||||
configuration->get_logs_path()
|
||||
);
|
||||
|
||||
// **********************************************
|
||||
|
@ -286,7 +288,9 @@ void Task::execute( Conf * configuration )
|
|||
this->definition.get_group(),
|
||||
rectifier_command,
|
||||
this->LOG_LEVEL,
|
||||
task_name
|
||||
task_name,
|
||||
this->definition.get_stdout_log_flag(),
|
||||
configuration->get_logs_path()
|
||||
);
|
||||
|
||||
// **********************************************
|
||||
|
@ -335,7 +339,9 @@ void Task::execute( Conf * configuration )
|
|||
this->definition.get_group(),
|
||||
target_command,
|
||||
this->LOG_LEVEL,
|
||||
task_name
|
||||
task_name,
|
||||
this->definition.get_stdout_log_flag(),
|
||||
configuration->get_logs_path()
|
||||
);
|
||||
|
||||
// **********************************************
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
|||
|
||||
*/
|
||||
|
||||
#ifndef FTESTS_TASK_H
|
||||
#define FTESTS_TASK_H
|
||||
#ifndef REX_TASK_H
|
||||
#define REX_TASK_H
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include "../../json/json.h"
|
||||
|
@ -67,7 +67,7 @@ class Task
|
|||
std::string get_name();
|
||||
|
||||
// execute this task's definition
|
||||
void execute( Conf * configuration );
|
||||
void execute(Conf * configuration );
|
||||
|
||||
void mark_complete();
|
||||
|
||||
|
@ -79,4 +79,4 @@ private:
|
|||
int LOG_LEVEL;
|
||||
};
|
||||
|
||||
#endif //FTESTS_TASK_H
|
||||
#endif //REX_TASK_H
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
/// required, which is used as a flag to halt or continue if rectifier does not heal the system in such a way that
|
||||
/// target can run successfully.
|
||||
/// rectify, which is used as a flag to determine in the rectifier runs.
|
||||
Unit::Unit( int LOG_LEVEL ): JSON_Loader( LOG_LEVEL ), slog( LOG_LEVEL, "e_unit" )
|
||||
Unit::Unit( int LOG_LEVEL ): JSON_Loader( LOG_LEVEL ), slog( LOG_LEVEL, "_unit_" )
|
||||
{
|
||||
this->LOG_LEVEL;
|
||||
}
|
||||
|
@ -117,6 +117,10 @@ int Unit::load_root(Json::Value loader_root)
|
|||
{ this->required = loader_root.get("required", errmsg).asBool(); } else
|
||||
throw UnitException("No required attribute specified when loading a unit.");
|
||||
|
||||
if ( loader_root.isMember("log") )
|
||||
{ this->stdout_log_flag = loader_root.get("log", errmsg).asBool(); } else
|
||||
throw UnitException("No log attribute specified when loading a unit.");
|
||||
|
||||
if ( loader_root.isMember("rectify") )
|
||||
{ this->rectify = loader_root.get("rectify", errmsg).asBool(); } else
|
||||
throw UnitException("No rectify boolean attribute specified when loading a unit.");
|
||||
|
@ -286,3 +290,12 @@ std::string Unit::get_env_vars_file()
|
|||
return this->env_vars_file;
|
||||
}
|
||||
|
||||
/// Unit::get_stdout_log_flag() - retrieves the file path to use for the unit environment file. This is a file that is
|
||||
/// sourced by the chosen shell to populate any environment variables.
|
||||
/// \return the string value of the shell path.
|
||||
bool Unit::get_stdout_log_flag()
|
||||
{
|
||||
if ( ! this->populated ) { throw UnitException("Attempted to access an unpopulated unit."); }
|
||||
return this->stdout_log_flag;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -19,12 +19,12 @@
|
|||
*/
|
||||
|
||||
/* Unit.h
|
||||
* Unit is a type that represents a safely deserialized JSON object which defines what actions are taken as Examplar
|
||||
* Unit is a type that represents a safely deserialized JSON object which defines what actions are taken as rex
|
||||
* iterates through it's Tasks in it's given Plan. They only define the behaviour on execution, while the tasks define
|
||||
* which Units are executed and in what order (and which Units a given Task depends on.
|
||||
*/
|
||||
#ifndef FTESTS_UNIT_H
|
||||
#define FTESTS_UNIT_H
|
||||
#ifndef FTEST_UNIT_H
|
||||
#define FTEST_UNIT_H
|
||||
#include <string>
|
||||
#include "../../json/json.h"
|
||||
#include "../low_level/JSON_Loader.h"
|
||||
|
@ -59,6 +59,9 @@ private:
|
|||
// if rectifier exits on non-zero return code, it should be trigger the behaviour indicated by required
|
||||
bool rectify;
|
||||
|
||||
//indicator of whether stdout should log to file. used mainly to handle glitchy TUI systems when logs are being tailed.
|
||||
bool stdout_log_flag;
|
||||
|
||||
// user to run process as.
|
||||
// not intended for protected accounts, handle your own security
|
||||
std::string user;
|
||||
|
@ -91,6 +94,7 @@ public:
|
|||
bool get_active();
|
||||
bool get_required();
|
||||
bool get_rectify();
|
||||
bool get_stdout_log_flag();
|
||||
std::string get_user();
|
||||
std::string get_group();
|
||||
std::string get_shell();
|
||||
|
@ -100,4 +104,4 @@ private:
|
|||
Logger slog;
|
||||
};
|
||||
|
||||
#endif //FTESTS_UNIT_H
|
||||
#endif //FTEST_UNIT_H
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -17,12 +17,12 @@
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#ifndef FTESTS_LOADERS_H
|
||||
#define FTESTS_LOADERS_H
|
||||
#ifndef REX_LOADERS_H
|
||||
#define REX_LOADERS_H
|
||||
|
||||
#include "../low_level/JSON_Loader.h"
|
||||
#include "Suite.h"
|
||||
#include "Plan.h"
|
||||
#include "Conf.h"
|
||||
|
||||
#endif //FTESTS_LOADERS_H
|
||||
#endif //REX_LOADERS_H
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -38,7 +38,7 @@ class JSON_Loader_InvalidJSON: public std::runtime_error { public:
|
|||
/// JSON_Loader::JSON_Loader - Constructor for JSON_Loader base class. Simply inits to an unpopulated state.
|
||||
///
|
||||
/// The JSON_Loader type is a base type. It is meant to provide the functionalities shared between Suite and Plan.
|
||||
JSON_Loader::JSON_Loader( int LOG_LEVEL ): slog( LOG_LEVEL, "e_json" )
|
||||
JSON_Loader::JSON_Loader( int LOG_LEVEL ): slog( LOG_LEVEL, "_json_" )
|
||||
{
|
||||
this->populated = false;
|
||||
this->LOG_LEVEL = LOG_LEVEL;
|
||||
|
@ -91,7 +91,7 @@ void JSON_Loader::load_json_file( std::string filename )
|
|||
// first, check if the file exists
|
||||
if (! exists( filename ) )
|
||||
{
|
||||
this->slog.log( E_FATAL, "File '" + filename + "' does not exist." );
|
||||
this->slog.log( E_DEBUG, "File '" + filename + "' does not exist." );
|
||||
throw JSON_Loader_FileNotFound();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -17,8 +17,8 @@
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#ifndef FTESTS_JLOADER_H
|
||||
#define FTESTS_JLOADER_H
|
||||
#ifndef REX_JLOADER_H
|
||||
#define REX_JLOADER_H
|
||||
#include "../../json/json.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
@ -55,4 +55,4 @@ private:
|
|||
Logger slog;
|
||||
int LOG_LEVEL;
|
||||
};
|
||||
#endif //FTESTS_JLOADER_H
|
||||
#endif //REX_JLOADER_H
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -44,4 +44,14 @@ bool is_dir( std::string path )
|
|||
struct stat buf;
|
||||
stat( path.c_str(), &buf );
|
||||
return S_ISDIR(buf.st_mode);
|
||||
}
|
||||
|
||||
std::string get_8601()
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto itt = std::chrono::system_clock::to_time_t(now);
|
||||
std::ostringstream ss;
|
||||
// ss << std::put_time(gmtime(&itt), "%FT%TZ");
|
||||
ss << std::put_time(localtime(&itt), "%Y-%m-%d_%H:%M:%S");
|
||||
return ss.str();
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Examplar - An automation and testing framework.
|
||||
rex - An automation and testing framework.
|
||||
|
||||
© SURRO INDUSTRIES and Chris Punches, 2017.
|
||||
|
||||
|
@ -18,13 +18,18 @@
|
|||
|
||||
*/
|
||||
|
||||
#ifndef FTESTS_HELPERS_H
|
||||
#define FTESTS_HELPERS_H
|
||||
#ifndef REX_HELPERS_H
|
||||
#define REX_HELPERS_H
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
#include <syslog.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
bool exists (const std::string& name);
|
||||
|
||||
|
@ -32,4 +37,7 @@ std::string get_working_path();
|
|||
bool is_file( std::string );
|
||||
bool is_dir( std::string );
|
||||
|
||||
#endif //FTESTS_HELPERS_H
|
||||
std::string get_8601();
|
||||
|
||||
|
||||
#endif //REX_HELPERS_JH
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
echo CURSES DIALOG TEST
|
||||
echo "This is a test of how curses dialogs are handled. Expect freaky behaviour."
|
||||
|
||||
dialog --title "Dialog title" --inputbox "Enter your name:" 0 0
|
||||
echo test
|
||||
|
||||
#cat /dev/urandom
|
||||
exit $?
|
||||
|
||||
|
|
|
@ -1,2 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "dependent test"
|
||||
echo This test depends on another test having succeeded in order to execute.
|
||||
echo This tests dependencies.
|
||||
exit $?
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
echo "Failure handling test."
|
||||
echo "This test will fail on purpose."
|
||||
>&2 echo "This test is printing to stderr."
|
||||
exit 1
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
#!/bin/bash
|
||||
echo "This is an independent test. It does not depend on other tests."
|
||||
echo "Environment file check: TEST_VAR from environment file is set to: $TEST_VAR"
|
||||
|
||||
echo "TEST OUTPUT: Test var is: $TEST_VAR"
|
||||
|
||||
#dialog --stdout --title "Interact with me!" \
|
||||
# --backtitle "This is user interaction." \
|
||||
# --yesno "Yes: pass, No: fail" 7 60
|
||||
exit $?
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
{
|
||||
"execution_context_override": true,
|
||||
"execution_context": "/home/bagira/development/internal/Examplar/test",
|
||||
"execution_context": "/home/bagira/development/internal/rex/test",
|
||||
"units_path": "units/",
|
||||
"plan_path": "plans/test.plan",
|
||||
"config_version": "3",
|
||||
"env_vars_file": "examplar.variables",
|
||||
"shell": "/bin/bash"
|
||||
"logs_path": "logs/",
|
||||
"config_version": "3"
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
{ "name": "independent test 1", "dependencies": [ null ] },
|
||||
{ "name": "independent test 2", "dependencies": [ null ] },
|
||||
{ "name": "dependent test", "dependencies": [ "independent test 1" ] },
|
||||
{ "name": "curses dialog", "dependencies": [ "independent test 1" ] },
|
||||
{ "name": "fail", "dependencies": [ null ] }
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
|
||||
This test is printing to stderr.
|
||||
This test is printing to stderr.
|
||||
This test is printing to stderr.
|
||||
This test is printing to stderr.
|
||||
|
|
154
test/stdout.log
154
test/stdout.log
|
@ -1,46 +1,128 @@
|
|||
|
||||
[2021-04-03_20:20:26] [INFO] [_sproc] [ 'independent test 1' ] TEE Logging enabled.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 1' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 1' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 1' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 1' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 1' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 1' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 1' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-03_20:20:26] [INFO] [_sproc] [ 'independent test 1' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
[2021-04-04_19:08:56] [INFO] [_sproc] [ 'independent test 1' ] TEE Logging enabled.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 1' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 1' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 1' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 1' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 1' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 1' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 1' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-04_19:08:56] [INFO] [_sproc] [ 'independent test 1' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
TEST OUTPUT: Test var is: 999
|
||||
[2021-04-03_20:20:26] [INFO] [_sproc] [ 'independent test 2' ] TEE Logging enabled.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 2' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 2' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 2' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 2' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 2' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 2' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'independent test 2' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-03_20:20:26] [INFO] [_sproc] [ 'independent test 2' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
[2021-04-04_19:08:56] [INFO] [_sproc] [ 'independent test 2' ] TEE Logging enabled.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 2' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 2' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 2' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 2' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 2' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 2' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'independent test 2' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-04_19:08:56] [INFO] [_sproc] [ 'independent test 2' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
independent test 2 output
|
||||
independent test says TEST_VAR is 999
|
||||
[2021-04-03_20:20:26] [INFO] [_sproc] [ 'dependent test' ] TEE Logging enabled.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'dependent test' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'dependent test' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'dependent test' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'dependent test' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'dependent test' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'dependent test' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'dependent test' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-03_20:20:26] [INFO] [_sproc] [ 'dependent test' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
[2021-04-04_19:08:56] [INFO] [_sproc] [ 'dependent test' ] TEE Logging enabled.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'dependent test' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'dependent test' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'dependent test' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'dependent test' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'dependent test' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'dependent test' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'dependent test' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-04_19:08:56] [INFO] [_sproc] [ 'dependent test' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
dependent test
|
||||
[2021-04-03_20:20:26] [INFO] [_sproc] [ 'fail' ] TEE Logging enabled.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'fail' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'fail' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'fail' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'fail' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'fail' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'fail' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-03_20:20:26] [DBUG] [_sproc] [ 'fail' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-03_20:20:26] [INFO] [_sproc] [ 'fail' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
[2021-04-04_19:08:56] [INFO] [_sproc] [ 'fail' ] TEE Logging enabled.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'fail' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'fail' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'fail' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'fail' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'fail' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'fail' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-04_19:08:56] [DBUG] [_sproc] [ 'fail' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-04_19:08:56] [INFO] [_sproc] [ 'fail' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
This test will fail on purpose.
|
||||
[2021-04-04_19:15:50] [INFO] [_sproc] [ 'independent test 1' ] TEE Logging enabled.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-04_19:15:50] [INFO] [_sproc] [ 'independent test 1' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
TEST OUTPUT: Test var is: 999
|
||||
[2021-04-04_19:15:50] [INFO] [_sproc] [ 'independent test 1' ] TEE Logging enabled.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'independent test 1' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-04_19:15:50] [INFO] [_sproc] [ 'independent test 1' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
TEST OUTPUT: Test var is: 999
|
||||
[2021-04-04_19:15:50] [INFO] [_sproc] [ 'dependent test' ] TEE Logging enabled.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'dependent test' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'dependent test' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'dependent test' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'dependent test' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'dependent test' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'dependent test' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'dependent test' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-04_19:15:50] [INFO] [_sproc] [ 'dependent test' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
dependent test
|
||||
[2021-04-04_19:15:50] [INFO] [_sproc] [ 'fail' ] TEE Logging enabled.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'fail' ] DUP2: child_*_pipe[1]->STD*_FILENO
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'fail' ] Attempt: Running as user 'bagira'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'fail' ] Attempt: Running as group_name 'bagira'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'fail' ] UID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'fail' ] GID of 'bagira' is '1000'.
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'fail' ] Successfully set GID to '1000' (bagira).
|
||||
[2021-04-04_19:15:50] [DBUG] [_sproc] [ 'fail' ] Successfully set UID to '1000' (bagira).
|
||||
[2021-04-04_19:15:50] [INFO] [_sproc] [ 'fail' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
This test will fail on purpose.
|
||||
[2021-04-04_19:23:08] [INFO] [_sproc] [ 'independent test 1' ] TEE Logging enabled.
|
||||
[2021-04-04_19:23:08] [INFO] [_sproc] [ 'independent test 1' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
TEST OUTPUT: Test var is: 999
|
||||
[2021-04-04_19:23:08] [INFO] [_sproc] [ 'independent test 2' ] TEE Logging enabled.
|
||||
[2021-04-04_19:23:08] [INFO] [_sproc] [ 'independent test 2' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
independent test 2 output
|
||||
independent test says TEST_VAR is 999
|
||||
[2021-04-04_19:23:08] [INFO] [_sproc] [ 'dependent test' ] TEE Logging enabled.
|
||||
[2021-04-04_19:23:08] [INFO] [_sproc] [ 'dependent test' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
dependent test
|
||||
[2021-04-04_19:23:08] [INFO] [_sproc] [ 'fail' ] TEE Logging enabled.
|
||||
[2021-04-04_19:23:08] [INFO] [_sproc] [ 'fail' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
This test will fail on purpose.
|
||||
[2021-04-04_19:45:01] [INFO] [_sproc] [ 'independent test 1' ] TEE Logging enabled.
|
||||
[2021-04-04_19:45:01] [INFO] [_sproc] [ 'independent test 1' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
This is an independent test. It does not depend on other tests.
|
||||
Environment file check: TEST_VAR from environment file is set to: 999
|
||||
[2021-04-04_19:45:01] [INFO] [_sproc] [ 'independent test 2' ] TEE Logging enabled.
|
||||
[2021-04-04_19:45:01] [INFO] [_sproc] [ 'independent test 2' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
independent test 2 output
|
||||
independent test says TEST_VAR is 999
|
||||
[2021-04-04_19:45:01] [INFO] [_sproc] [ 'dependent test' ] TEE Logging enabled.
|
||||
[2021-04-04_19:45:01] [INFO] [_sproc] [ 'dependent test' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
dependent test
|
||||
This test depends on another test having succeeded in order to execute.
|
||||
This tests dependencies.
|
||||
[2021-04-04_19:45:01] [INFO] [_sproc] [ 'fail' ] TEE Logging enabled.
|
||||
[2021-04-04_19:45:01] [INFO] [_sproc] [ 'fail' ] Identity context set as user 'bagira' and group 'bagira'.
|
||||
variables file says hello and set a variable named TEST_VAR
|
||||
Failure handling test.
|
||||
This test will fail on purpose.
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
"rectifier": "",
|
||||
"active": true,
|
||||
"required": true,
|
||||
"log": true,
|
||||
"user": "bagira",
|
||||
"group": "bagira",
|
||||
"rectify": false,
|
||||
"shell": "/usr/bin/env bash",
|
||||
"environment": "environments/examplar.variables"
|
||||
"environment": "environments/rex.variables"
|
||||
},
|
||||
{
|
||||
"name": "independent test 2",
|
||||
|
@ -18,11 +19,12 @@
|
|||
"rectifier": "",
|
||||
"active": true,
|
||||
"required": true,
|
||||
"log": true,
|
||||
"user": "bagira",
|
||||
"group": "bagira",
|
||||
"rectify": false,
|
||||
"shell": "/usr/bin/env bash",
|
||||
"environment": "environments/examplar.variables"
|
||||
"environment": "environments/rex.variables"
|
||||
},
|
||||
{
|
||||
"name": "dependent test",
|
||||
|
@ -30,11 +32,12 @@
|
|||
"rectifier": "",
|
||||
"active": true,
|
||||
"required": true,
|
||||
"log": true,
|
||||
"user": "bagira",
|
||||
"group": "bagira",
|
||||
"rectify": false,
|
||||
"shell": "/usr/bin/env bash",
|
||||
"environment": "environments/examplar.variables"
|
||||
"environment": "environments/rex.variables"
|
||||
},
|
||||
{
|
||||
"name": "curses dialog",
|
||||
|
@ -42,11 +45,12 @@
|
|||
"rectifier": "",
|
||||
"active": true,
|
||||
"required": true,
|
||||
"log": false,
|
||||
"user": "bagira",
|
||||
"group": "bagira",
|
||||
"rectify": false,
|
||||
"shell": "/usr/bin/env bash",
|
||||
"environment": "environments/examplar.variables"
|
||||
"environment": "environments/rex.variables"
|
||||
},
|
||||
{
|
||||
"name": "fail",
|
||||
|
@ -54,11 +58,12 @@
|
|||
"rectifier": "",
|
||||
"active": true,
|
||||
"required": false,
|
||||
"log": true,
|
||||
"user": "bagira",
|
||||
"group": "bagira",
|
||||
"rectify": false,
|
||||
"shell": "/usr/bin/env bash",
|
||||
"environment": "environments/examplar.variables"
|
||||
"environment": "environments/rex.variables"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue