rex/src/loaders/abstract/Unit.cpp

229 lines
7.9 KiB
C++
Raw Normal View History

2017-12-04 05:46:34 +00:00
/*
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 "Unit.h"
2017-06-20 06:06:33 +00:00
#include <iostream>
#include <fstream>
#include <cstdlib>
2017-06-21 04:01:00 +00:00
#include <stdexcept>
#include <pwd.h>
#include <grp.h>
2017-06-21 04:01:00 +00:00
/// Unit_NotPopulated - Meant to be thrown when a Unit type is not populated before being used.
/// Signaled by use of the 'populated' boolean member of the Unit class.
2017-06-23 17:15:31 +00:00
class Unit_NotPopulated: public std::runtime_error { public:
2017-06-21 04:01:00 +00:00
Unit_NotPopulated(): std::runtime_error("Unit: Attempted to access a member before loading values.") {}
};
/// EnvironmentErrorFatal - Meant to be thrown when the environment is too broken for Examplar to do its job.
class EnvironmentErrorFatal: public std::runtime_error { public:
EnvironmentErrorFatal(): std::runtime_error("Unit: Environment is too broken to continue.") {}
};
2017-06-23 17:15:31 +00:00
/// Unit_DataStructureException - Meant to be thrown when a Unit type is accessing a member that does not exist.
class Unit_DataStructureException: public std::runtime_error { public:
// TODO rework this to accept the key name being fetched
Unit_DataStructureException(): std::runtime_error("Unit: Attempted to access a member not present in defined Unit.") {}
};
/// Unit::Unit - Constructor for Unit type. The Unit is a definition of an automation task. Each Unit has:
/// name, used for identification and retrieval.
/// target, which is the filepath of an executable to trigger.
/// output, which is the desired output of the execution of target to STDOUT in determinations of of success or failure
/// (in addition to 0|non-0 exit code). If the output is set to look for "0" then it uses the exit code.
///
/// There is also:
/// rectifier, which is the path to an executable in the event of a non-0 exit code or a failure to get the desired
/// output.
/// 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" )
2020-06-21 00:09:32 +00:00
{
this->LOG_LEVEL;
}
2017-06-23 17:15:31 +00:00
/// Unit::load_root - Takes a JSON::Value and assigns the members to the Unit being populated.
///
/// \param loader_root - The JSON::Value object to use to populate unit from. Usually supplied as the Suite's buffer
/// member.
/// \return - Boolean representation of success or failure.
int Unit::load_root(Json::Value loader_root)
{
2017-06-23 17:15:31 +00:00
// TODO this needs reworked to have errmsg actually end up as a null return from json::value.get()
std::string errmsg = "SOMETHING WENT TERRIBLY WRONG IN PARSING";
// TODO this pattern is 'working but broken'. need to use a datastructure for required members and iterate
// do NOT replace this with a switch case pattern
if ( loader_root.isMember("name") )
{ this->name = loader_root.get("name", errmsg).asString(); } else throw Unit_DataStructureException();
2017-06-21 02:53:47 +00:00
2017-06-23 17:15:31 +00:00
if ( loader_root.isMember("target") )
{ this->target = loader_root.get("target", errmsg).asString(); } else throw Unit_DataStructureException();
2017-06-21 02:53:47 +00:00
2017-06-23 17:15:31 +00:00
if ( loader_root.isMember("rectifier") )
{ this->rectifier = loader_root.get("rectifier", errmsg).asString(); } else throw Unit_DataStructureException();
2017-06-21 02:53:47 +00:00
2017-06-23 17:19:49 +00:00
if ( loader_root.isMember("active") )
{ this->active = loader_root.get("active", errmsg).asBool(); } else throw Unit_DataStructureException();
2017-06-21 02:53:47 +00:00
2017-06-23 17:15:31 +00:00
if ( loader_root.isMember("required") )
{ this->required = loader_root.get("required", errmsg).asBool(); } else throw Unit_DataStructureException();
2017-06-21 02:53:47 +00:00
2017-06-23 17:15:31 +00:00
if ( loader_root.isMember("rectify") )
{ this->rectify = loader_root.get("rectify", errmsg).asBool(); } else throw Unit_DataStructureException();
// TODO functionize this
char * lgn;
std::string errmsg_user;
// if no user field is specified then default to the currently executing user
if ( ( lgn = getlogin() ) == NULL )
{
throw EnvironmentErrorFatal();
} else {
errmsg_user = lgn;
}
// -TODO
if ( loader_root.isMember( "user" ) )
{ this->user = loader_root.get( "user", errmsg_user ).asString(); } else this->user = lgn;
// TODO functionalize this
// get the current context gid as a backup value
int gid = getgid();
// declare the grp object to pull the name from once populated
struct group * grp;
// storage for backup value once retrieved
std::string errmsg_group;
// get the backup value and store it to errmsg_group
if ( ( grp = getgrgid( gid ) ) == NULL )
{
throw EnvironmentErrorFatal();
} else {
errmsg_group = grp->gr_name;
}
if ( loader_root.isMember( "group" ) )
{ this->group = loader_root.get( "group", errmsg_group ).asString(); } else this->group = grp->gr_name;
2017-06-21 02:53:47 +00:00
this->populated = true;
return 0;
}
2017-06-20 06:06:33 +00:00
2017-06-23 17:15:31 +00:00
/// Unit::load_string - populates a Unit object from a supplies JSON-formatted string. It's stellar.
///
/// \param json_val - JSON-formatted string to populate from. See Unit::load_root() for details on required structure.
/// \return - The bool representation of success or failure.
2017-06-20 06:06:33 +00:00
int Unit::load_string(std::string json_val)
{
2017-06-21 02:53:47 +00:00
// serialize
2020-06-21 00:09:32 +00:00
this->load_json_string( json_val );
2017-06-21 02:53:47 +00:00
// deserialize
this->load_root( this->json_root );
return 0;
}
2017-06-20 06:06:33 +00:00
2017-06-23 17:15:31 +00:00
/// Unit::get_name - retrieves the name of the unit.
///
/// \return the name of the unit.
std::string Unit::get_name()
{
2017-06-21 04:01:00 +00:00
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->name;
}
2017-06-23 17:15:31 +00:00
/// Unit::get_target - retrieves the target of the unit.
///
/// \return the target of the unit.
std::string Unit::get_target()
{
2017-06-21 04:01:00 +00:00
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->target;
}
2017-06-23 17:15:31 +00:00
/// Unit::get_output - retrieves the output of the unit.
///
/// \return the output of the unit.
std::string Unit::get_output()
{
2017-06-21 04:01:00 +00:00
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->output;
}
2017-06-23 17:15:31 +00:00
/// Unit::get_rectifier - retrieves the rectifier of the unit.
///
/// \return the rectifier of the unit.
std::string Unit::get_rectifier()
{
2017-06-21 04:01:00 +00:00
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->rectifier;
}
2017-06-23 17:15:31 +00:00
/// Unit::get_active - retrieves the armed status of the unit.
///
/// \return the armed status of the unit.
bool Unit::get_active()
{
2017-06-21 04:01:00 +00:00
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->active;
}
2017-06-23 17:15:31 +00:00
/// Unit::get_required - retrieves the requirement status of the unit.
///
/// \return the requirement status of the unit.
bool Unit::get_required()
{
2017-06-21 04:01:00 +00:00
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->required;
}
2017-06-23 17:15:31 +00:00
/// Unit::get_rectify - retrieves the rectification status of the unit.
///
/// \return the rectification status of the unit.
bool Unit::get_rectify()
{
2017-06-21 04:01:00 +00:00
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->rectify;
}
/// Unit::get_user - retrieves the user context for the unit.
///
/// \return the string value of the user name.
std::string Unit::get_user()
{
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->user;
}
/// Unit::get_group - retrieves the group context for the unit.
///
/// \return the string value of the group name.
std::string Unit::get_group()
{
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->group;
}