Better errors.
This commit is contained in:
parent
42e25b6353
commit
38cb23706d
22
src/main.cpp
22
src/main.cpp
@ -231,15 +231,19 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// run the command on each service.
|
||||
for (const auto& service_info : server_and_services.servicelist) {
|
||||
service_runner runner(server_and_services.server_name, service_info.service_name);
|
||||
if (!runner.isValid())
|
||||
return die("Error: Failed to initialize service");
|
||||
|
||||
std::vector<std::string> additional_args;
|
||||
for (int i=4; i<argc; i++)
|
||||
additional_args.push_back(argv[i]);
|
||||
if (!runner.run_command(cmd, additional_args))
|
||||
return die(cmd+" failed.");
|
||||
if (!SIvalid(service_info))
|
||||
std::cerr<<"Error: Unable to get service information."<<std::endl;
|
||||
else {
|
||||
service_runner runner(server_and_services.server_name, service_info.service_name);
|
||||
if (!runner.isValid())
|
||||
return die("Error: Failed to initialize service");
|
||||
|
||||
std::vector<std::string> additional_args;
|
||||
for (int i=4; i<argc; i++)
|
||||
additional_args.push_back(argv[i]);
|
||||
if (!runner.run_command(cmd, additional_args))
|
||||
return die(cmd+" failed on service "+service_info.service_name);
|
||||
}
|
||||
}
|
||||
|
||||
// success!
|
||||
|
@ -112,13 +112,19 @@ std::string server_env_manager::construct_ssh_cmd(bool allocateTTY) const {
|
||||
|
||||
sCommand server_env_manager::construct_standard_command_run_cmd(const std::string &service_name, const std::string &command, std::vector<std::string> args, bool silent) const
|
||||
{
|
||||
if (command.empty())
|
||||
return sCommand();
|
||||
|
||||
std::string remote_service_template_path = remotepath::service_template(mServerName,service_name);
|
||||
std::string remote_service_config_path = remotepath::service_config(mServerName,service_name);
|
||||
|
||||
std::string script_path = remote_service_template_path + "/" + command + ".sh";
|
||||
|
||||
std::map<std::string, std::string> env_vars;
|
||||
get_all_service_env_vars(mServerName, service_name, env_vars);
|
||||
if (!get_all_service_env_vars(mServerName, service_name, env_vars)) {
|
||||
std::cerr << "Error: Failed to get all service env vars for " << service_name << std::endl;
|
||||
return sCommand();
|
||||
}
|
||||
|
||||
std::string argstr = "";
|
||||
for (const auto& arg : args) {
|
||||
@ -126,6 +132,10 @@ sCommand server_env_manager::construct_standard_command_run_cmd(const std::strin
|
||||
}
|
||||
|
||||
sCommand scommand(remote_service_template_path, "bash " + quote(script_path) + argstr + (silent ? " > /dev/null 2>&1" : ""), env_vars);
|
||||
|
||||
if (scommand.empty())
|
||||
std::cerr << "Error: Failed to construct command for " << service_name << " " << command << std::endl;
|
||||
|
||||
return scommand;
|
||||
}
|
||||
|
||||
@ -187,6 +197,8 @@ bool server_env_manager::execute_ssh_command_and_capture_output(const sCommand&
|
||||
bool server_env_manager::run_remote_template_command(const std::string &service_name, const std::string &command, std::vector<std::string> args, bool silent) const
|
||||
{
|
||||
sCommand scommand = construct_standard_command_run_cmd(service_name, command, args, silent);
|
||||
if (scommand.get_command_to_run().empty())
|
||||
return false;
|
||||
bool allocateTTY = (command=="ssh");
|
||||
return execute_ssh_command(scommand, allocateTTY);
|
||||
}
|
||||
@ -194,17 +206,23 @@ bool server_env_manager::run_remote_template_command(const std::string &service_
|
||||
bool server_env_manager::run_remote_template_command_and_capture_output(const std::string &service_name, const std::string &command, std::vector<std::string> args, std::string &output, bool silent) const
|
||||
{
|
||||
sCommand scommand = construct_standard_command_run_cmd(service_name, command, args, silent);
|
||||
if (scommand.get_command_to_run().empty())
|
||||
return false;
|
||||
bool allocateTTY = (command=="ssh");
|
||||
return execute_ssh_command_and_capture_output(scommand, output, allocateTTY);
|
||||
}
|
||||
|
||||
bool server_env_manager::execute_local_command(const sCommand& command) {
|
||||
if (command.get_command_to_run().empty())
|
||||
return false;
|
||||
int ret = system(command.construct_safecmd().c_str());
|
||||
return EXITSTATUSCHECK(ret);
|
||||
}
|
||||
|
||||
bool server_env_manager::execute_local_command_interactive(const sCommand &command)
|
||||
{
|
||||
if (command.get_command_to_run().empty())
|
||||
return false;
|
||||
std::string full_command = command.construct_rawcmd(); // Get the command string
|
||||
|
||||
pid_t pid = fork();
|
||||
@ -237,6 +255,8 @@ bool server_env_manager::execute_local_command_interactive(const sCommand &comma
|
||||
|
||||
bool server_env_manager::execute_local_command_and_capture_output(const sCommand& command, std::string &output)
|
||||
{
|
||||
if (command.get_command_to_run().empty())
|
||||
return false;
|
||||
std::string full_cmd = command.construct_safecmd() + " 2>&1";
|
||||
FILE *pipe = popen(full_cmd.c_str(), "r");
|
||||
if (!pipe) {
|
||||
@ -253,6 +273,8 @@ bool server_env_manager::execute_local_command_and_capture_output(const sCommand
|
||||
|
||||
std::string sCommand::construct_safecmd() const
|
||||
{
|
||||
if (mCmd.empty())
|
||||
return "";
|
||||
std::string to_encode;
|
||||
|
||||
for (const auto& env_var : mVars) {
|
||||
@ -271,6 +293,9 @@ std::string sCommand::construct_safecmd() const
|
||||
|
||||
std::string sCommand::construct_rawcmd() const
|
||||
{
|
||||
if (mCmd.empty())
|
||||
return "";
|
||||
|
||||
std::string rawcmd;
|
||||
if (!mDir.empty())
|
||||
rawcmd = "cd " + quote(mDir) + " && ";
|
||||
@ -287,6 +312,8 @@ std::string sCommand::construct_rawcmd() const
|
||||
|
||||
std::string makesafecmd(const std::string &command)
|
||||
{
|
||||
if (command.empty())
|
||||
return "";
|
||||
std::string encoded = base64_encode(dequote(trim(command)));
|
||||
std::string commandstr = "echo " + encoded + " | base64 -d | bash";
|
||||
return commandstr;
|
||||
|
@ -18,7 +18,7 @@ class sCommand {
|
||||
mDir(directory_to_run_in), mCmd(command_to_run), mVars(env_vars) {}
|
||||
sCommand(std::string command_to_run) :
|
||||
mDir(""), mCmd(command_to_run), mVars({}) {}
|
||||
|
||||
sCommand() : mDir(""), mCmd(""), mVars({}) {}
|
||||
|
||||
std::string get_directory_to_run_in() const { return mDir; }
|
||||
std::string get_command_to_run() const { return mCmd; }
|
||||
@ -29,6 +29,8 @@ class sCommand {
|
||||
std::string construct_safecmd() const;
|
||||
std::string construct_rawcmd() const;
|
||||
|
||||
bool empty() const { return mCmd.empty(); }
|
||||
|
||||
private:
|
||||
std::string mDir;
|
||||
std::string mCmd;
|
||||
|
@ -31,6 +31,9 @@ service_runner::service_runner(const std::string& server_name, const std::string
|
||||
return;
|
||||
|
||||
mServiceInfo = get_service_info(server_name, service_name);
|
||||
if (mServiceInfo.service_name.empty())
|
||||
return;
|
||||
|
||||
mService = mServiceInfo.service_name;
|
||||
|
||||
mValid = !mServiceInfo.local_template_path.empty();
|
||||
@ -144,7 +147,7 @@ bool service_runner::uninstall() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool service_runner::nuke()
|
||||
bool service_runner::nuke(bool silent)
|
||||
{
|
||||
maketitle("Nuking " + mService + " (" + mServiceInfo.template_name + ") on " + mServer);
|
||||
|
||||
@ -180,16 +183,17 @@ bool service_runner::nuke()
|
||||
|
||||
std::cout << "Service " << mService << " successfully nuked from " << mServer << std::endl;
|
||||
|
||||
std::cout << "There's nothing left on the remote server." << std::endl;
|
||||
std::cout << "You can remove the local files with:" << std::endl;
|
||||
std::cout << " rm -rf " << localpath::service(mServer,mService) << std::endl;
|
||||
|
||||
if (!silent) {
|
||||
std::cout << "There's nothing left on the remote server." << std::endl;
|
||||
std::cout << "You can remove the local files with:" << std::endl;
|
||||
std::cout << " rm -rf " << localpath::service(mServer,mService) << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool service_runner::fullnuke()
|
||||
{
|
||||
if (!nuke())
|
||||
if (!nuke(true))
|
||||
{
|
||||
std::cerr << "Warning: Nuke script failed, aborting fullnuke!" << std::endl;
|
||||
return false;
|
||||
|
@ -78,7 +78,7 @@ class service_runner {
|
||||
bool restore(std::string backup_file, bool silent=false);
|
||||
|
||||
// nuke the service
|
||||
bool nuke(); // nukes all data for this service on the remote server
|
||||
bool nuke(bool silent=false); // nukes all data for this service on the remote server
|
||||
bool fullnuke(); // nuke all data for this service on the remote server, and then nukes all the local service definitionfiles
|
||||
|
||||
// launch an interactive ssh session on a server or service
|
||||
|
@ -14,6 +14,13 @@ namespace fs = std::filesystem;
|
||||
|
||||
namespace dropshell {
|
||||
|
||||
bool SIvalid(const LocalServiceInfo& service_info) {
|
||||
return !service_info.service_name.empty() &&
|
||||
!service_info.template_name.empty() &&
|
||||
!service_info.local_service_path.empty() &&
|
||||
!service_info.local_template_path.empty();
|
||||
}
|
||||
|
||||
std::vector<LocalServiceInfo> get_server_services_info(const std::string& server_name) {
|
||||
std::vector<LocalServiceInfo> services;
|
||||
|
||||
@ -64,7 +71,8 @@ LocalServiceInfo get_service_info(const std::string &server_name, const std::str
|
||||
|
||||
// now set the template name and path.
|
||||
std::map<std::string, std::string> variables;
|
||||
get_all_service_env_vars(server_name, service_name, variables);
|
||||
if (!get_all_service_env_vars(server_name, service_name, variables))
|
||||
return LocalServiceInfo();
|
||||
|
||||
// confirm TEMPLATE is defined.
|
||||
auto it = variables.find("TEMPLATE");
|
||||
@ -207,10 +215,16 @@ bool create_service(const std::string &server_name, const std::string &template_
|
||||
|
||||
|
||||
|
||||
void get_all_service_env_vars(const std::string &server_name, const std::string &service_name, std::map<std::string, std::string> & all_env_vars)
|
||||
bool get_all_service_env_vars(const std::string &server_name, const std::string &service_name, std::map<std::string, std::string> & all_env_vars)
|
||||
{
|
||||
all_env_vars.clear();
|
||||
|
||||
if (localpath::service(server_name, service_name).empty() || !fs::exists(localpath::service(server_name, service_name)))
|
||||
{
|
||||
std::cerr << "Error: Service not found: " << service_name << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// add in some handy variables.
|
||||
all_env_vars["CONFIG_PATH"] = remotepath::service_config(server_name,service_name);
|
||||
all_env_vars["SERVER"] = server_name;
|
||||
@ -247,13 +261,22 @@ void get_all_service_env_vars(const std::string &server_name, const std::string
|
||||
std::cerr << "The TEMPLATE variable is required to determine the template name." << std::endl;
|
||||
std::cerr << "Please check the service.env file and the .template_info.env file in:" << std::endl;
|
||||
std::cerr << " " << localpath::service(server_name, service_name) << std::endl << std::endl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
template_info tinfo = gTemplateManager().get_template_info(it->second);
|
||||
if (tinfo.is_set())
|
||||
load_env_file(tinfo.local_template_path()/"_default.env");
|
||||
else
|
||||
if (!tinfo.is_set()) {
|
||||
std::cerr << "Error: Template '" << it->second << "' not found" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string default_env_file = tinfo.local_template_path()/"_default.env";
|
||||
if (!fs::exists(default_env_file)) {
|
||||
std::cerr << "Error: Template default env file '" << default_env_file << "' not found" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
load_env_file(default_env_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dropshell
|
||||
|
@ -15,13 +15,15 @@ namespace dropshell {
|
||||
std::string local_template_path;
|
||||
};
|
||||
|
||||
bool SIvalid(const LocalServiceInfo& service_info);
|
||||
|
||||
std::vector<LocalServiceInfo> get_server_services_info(const std::string& server_name);
|
||||
|
||||
LocalServiceInfo get_service_info(const std::string& server_name, const std::string& service_name);
|
||||
std::set<std::string> get_used_commands(const std::string& server_name, const std::string& service_name);
|
||||
|
||||
// get all env vars for a given service
|
||||
void get_all_service_env_vars(const std::string& server_name, const std::string& service_name, std::map<std::string, std::string> & all_env_vars);
|
||||
bool get_all_service_env_vars(const std::string& server_name, const std::string& service_name, std::map<std::string, std::string> & all_env_vars);
|
||||
|
||||
// list all backups for a given service (across all servers)
|
||||
std::set<std::string> list_backups(const std::string& server_name, const std::string& service_name);
|
||||
|
Loading…
x
Reference in New Issue
Block a user