dropshell release 2025.0518.1355
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled

This commit is contained in:
Your Name 2025-05-18 13:55:39 +12:00
parent 314a5fe96a
commit 2b446f80a3
12 changed files with 205 additions and 133 deletions

View File

@ -73,6 +73,7 @@ function run_command() {
# update the main variables. # update the main variables.
CONFIG_PATH="${service_path}/config" CONFIG_PATH="${service_path}/config"
SERVICE="${SERVICE_NAME}" SERVICE="${SERVICE_NAME}"
DOCKER_CLI_HINTS=false
set +a set +a
@ -99,6 +100,10 @@ function command_exists() {
} }
if [ ! -d "${SERVICES_PATH}" ]; then
echo "Services path does not exist: ${SERVICES_PATH}"
exit 0
fi
# Get all service names # Get all service names
SERVICE_NAMES=$(ls "${SERVICES_PATH}") SERVICE_NAMES=$(ls "${SERVICES_PATH}")

View File

@ -281,36 +281,39 @@ bool recreate_tree(std::string destination_folder) {
"YXRofS9jb25maWcvc2VydmljZS5lbnYiCiAgICAgICAgbG9hZF9kb3RlbnYgIiR7c2VydmljZV9w"\ "YXRofS9jb25maWcvc2VydmljZS5lbnYiCiAgICAgICAgbG9hZF9kb3RlbnYgIiR7c2VydmljZV9w"\
"YXRofS9jb25maWcvLnRlbXBsYXRlX2luZm8uZW52IgoKICAgICAgICAjIHVwZGF0ZSB0aGUgbWFp"\ "YXRofS9jb25maWcvLnRlbXBsYXRlX2luZm8uZW52IgoKICAgICAgICAjIHVwZGF0ZSB0aGUgbWFp"\
"biB2YXJpYWJsZXMuCiAgICAgICAgQ09ORklHX1BBVEg9IiR7c2VydmljZV9wYXRofS9jb25maWci"\ "biB2YXJpYWJsZXMuCiAgICAgICAgQ09ORklHX1BBVEg9IiR7c2VydmljZV9wYXRofS9jb25maWci"\
"CiAgICAgICAgU0VSVklDRT0iJHtTRVJWSUNFX05BTUV9IgoKICAgICAgICBzZXQgK2EKCiAgICAg"\ "CiAgICAgICAgU0VSVklDRT0iJHtTRVJWSUNFX05BTUV9IgogICAgICAgIERPQ0tFUl9DTElfSElO"\
"ICAgX2NoZWNrX3JlcXVpcmVkX2Vudl92YXJzX2FsbHNlcnZpY2Vzc3RhdHVzICJDT05GSUdfUEFU"\ "VFM9ZmFsc2UKCiAgICAgICAgc2V0ICthCgogICAgICAgIF9jaGVja19yZXF1aXJlZF9lbnZfdmFy"\
"SCIgIlNFUlZFUiIgIlNFUlZJQ0UiICJBR0VOVF9QQVRIIiAiSE9TVF9OQU1FIiAiVEVNUExBVEUi"\ "c19hbGxzZXJ2aWNlc3N0YXR1cyAiQ09ORklHX1BBVEgiICJTRVJWRVIiICJTRVJWSUNFIiAiQUdF"\
"CgogICAgICAgIGlmIFsgIiRjYXB0dXJlX291dHB1dCIgPSAidHJ1ZSIgXTsgdGhlbgogICAgICAg"\ "TlRfUEFUSCIgIkhPU1RfTkFNRSIgIlRFTVBMQVRFIgoKICAgICAgICBpZiBbICIkY2FwdHVyZV9v"\
"ICAgICAjIENhcHR1cmUgYW5kIHJldHVybiBvdXRwdXQKICAgICAgICAgICAgYmFzaCAiJHtzZXJ2"\ "dXRwdXQiID0gInRydWUiIF07IHRoZW4KICAgICAgICAgICAgIyBDYXB0dXJlIGFuZCByZXR1cm4g"\
"aWNlX3BhdGh9L3RlbXBsYXRlLyR7Y29tbWFuZH0uc2giIDI+JjEKICAgICAgICBlbHNlCiAgICAg"\ "b3V0cHV0CiAgICAgICAgICAgIGJhc2ggIiR7c2VydmljZV9wYXRofS90ZW1wbGF0ZS8ke2NvbW1h"\
"ICAgICAgICMgUnVuIHNpbGVudGx5IGFuZCByZXR1cm4gZXhpdCBjb2RlCiAgICAgICAgICAgIGJh"\ "bmR9LnNoIiAyPiYxCiAgICAgICAgZWxzZQogICAgICAgICAgICAjIFJ1biBzaWxlbnRseSBhbmQg"\
"c2ggIiR7c2VydmljZV9wYXRofS90ZW1wbGF0ZS8ke2NvbW1hbmR9LnNoIiA+IC9kZXYvbnVsbCAy"\ "cmV0dXJuIGV4aXQgY29kZQogICAgICAgICAgICBiYXNoICIke3NlcnZpY2VfcGF0aH0vdGVtcGxh"\
"PiYxCiAgICAgICAgZmkKICAgICkKICAgIENVUlJFTlRfRVhJVF9DT0RFPSQ/Cn0KCmZ1bmN0aW9u"\ "dGUvJHtjb21tYW5kfS5zaCIgPiAvZGV2L251bGwgMj4mMQogICAgICAgIGZpCiAgICApCiAgICBD"\
"IGNvbW1hbmRfZXhpc3RzKCkgewogICAgbG9jYWwgc2VydmljZV9wYXRoPSQxCiAgICBsb2NhbCBj"\ "VVJSRU5UX0VYSVRfQ09ERT0kPwp9CgpmdW5jdGlvbiBjb21tYW5kX2V4aXN0cygpIHsKICAgIGxv"\
"b21tYW5kPSQyCiAgICBpZiBbICEgLWYgIiR7c2VydmljZV9wYXRofS90ZW1wbGF0ZS8ke2NvbW1h"\ "Y2FsIHNlcnZpY2VfcGF0aD0kMQogICAgbG9jYWwgY29tbWFuZD0kMgogICAgaWYgWyAhIC1mICIk"\
"bmR9LnNoIiBdOyB0aGVuCiAgICAgICAgcmV0dXJuIDEKICAgIGZpCiAgICByZXR1cm4gMAp9CgoK"\ "e3NlcnZpY2VfcGF0aH0vdGVtcGxhdGUvJHtjb21tYW5kfS5zaCIgXTsgdGhlbgogICAgICAgIHJl"\
"CiMgR2V0IGFsbCBzZXJ2aWNlIG5hbWVzClNFUlZJQ0VfTkFNRVM9JChscyAiJHtTRVJWSUNFU19Q"\ "dHVybiAxCiAgICBmaQogICAgcmV0dXJuIDAKfQoKCmlmIFsgISAtZCAiJHtTRVJWSUNFU19QQVRI"\
"QVRIfSIpCgojIEl0ZXJhdGUgb3ZlciBhbGwgc2VydmljZSBuYW1lcwpmb3IgU0VSVklDRV9OQU1F"\ "fSIgXTsgdGhlbgogICAgZWNobyAiU2VydmljZXMgcGF0aCBkb2VzIG5vdCBleGlzdDogJHtTRVJW"\
"IGluICR7U0VSVklDRV9OQU1FU307IGRvCgogICAgU0VSVklDRV9QQVRIPSQocmVhbHBhdGggIiR7"\ "SUNFU19QQVRIfSIKICAgIGV4aXQgMApmaQoKIyBHZXQgYWxsIHNlcnZpY2UgbmFtZXMKU0VSVklD"\
"U0VSVklDRVNfUEFUSH0vJHtTRVJWSUNFX05BTUV9IikKCiAgICAjLS0tLS0tLS0tLS0tLS0tLS0t"\ "RV9OQU1FUz0kKGxzICIke1NFUlZJQ0VTX1BBVEh9IikKCiMgSXRlcmF0ZSBvdmVyIGFsbCBzZXJ2"\
"LS0tLS0tLS0tLS0tLS0KICAgICMgR2V0IHRoZSBzZXJ2aWNlIGhlYWx0aAogICAgaWYgISBjb21t"\ "aWNlIG5hbWVzCmZvciBTRVJWSUNFX05BTUUgaW4gJHtTRVJWSUNFX05BTUVTfTsgZG8KCiAgICBT"\
"YW5kX2V4aXN0cyAiJHtTRVJWSUNFX1BBVEh9IiAic3RhdHVzIjsgdGhlbgogICAgICAgIFNFUlZJ"\ "RVJWSUNFX1BBVEg9JChyZWFscGF0aCAiJHtTRVJWSUNFU19QQVRIfS8ke1NFUlZJQ0VfTkFNRX0i"\
"Q0VfSEVBTFRIPSJ1bmtub3duIgogICAgZWxzZQogICAgICAgIHJ1bl9jb21tYW5kICIke1NFUlZJ"\ "KQoKICAgICMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICAgIyBHZXQgdGhlIHNl"\
"Q0VfUEFUSH0iICJzdGF0dXMiICJmYWxzZSIKICAgICAgICBpZiBbICIke0NVUlJFTlRfRVhJVF9D"\ "cnZpY2UgaGVhbHRoCiAgICBpZiAhIGNvbW1hbmRfZXhpc3RzICIke1NFUlZJQ0VfUEFUSH0iICJz"\
"T0RFfSIgLWVxIDAgXTsgdGhlbgogICAgICAgICAgICBTRVJWSUNFX0hFQUxUSD0iaGVhbHRoeSIK"\ "dGF0dXMiOyB0aGVuCiAgICAgICAgU0VSVklDRV9IRUFMVEg9InVua25vd24iCiAgICBlbHNlCiAg"\
"ICAgICAgICBlbHNlCiAgICAgICAgICAgIFNFUlZJQ0VfSEVBTFRIPSJ1bmhlYWx0aHkiCiAgICAg"\ "ICAgICAgcnVuX2NvbW1hbmQgIiR7U0VSVklDRV9QQVRIfSIgInN0YXR1cyIgImZhbHNlIgogICAg"\
"ICAgZmkKICAgIGZpCgogICAgIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgICAj"\ "ICAgIGlmIFsgIiR7Q1VSUkVOVF9FWElUX0NPREV9IiAtZXEgMCBdOyB0aGVuCiAgICAgICAgICAg"\
"IEdldCB0aGUgc2VydmljZSBwb3J0cwogICAgaWYgISBjb21tYW5kX2V4aXN0cyAiJHtTRVJWSUNF"\ "IFNFUlZJQ0VfSEVBTFRIPSJoZWFsdGh5IgogICAgICAgIGVsc2UKICAgICAgICAgICAgU0VSVklD"\
"X1BBVEh9IiAicG9ydHMiOyB0aGVuCiAgICAgICAgU0VSVklDRV9QT1JUUz0iIgogICAgZWxzZQog"\ "RV9IRUFMVEg9InVuaGVhbHRoeSIKICAgICAgICBmaQogICAgZmkKCiAgICAjLS0tLS0tLS0tLS0t"\
"ICAgICAgIHJ1bl9jb21tYW5kICIke1NFUlZJQ0VfUEFUSH0iICJwb3J0cyIgInRydWUiCiAgICAg"\ "LS0tLS0tLS0tLS0tLS0tLS0tLS0KICAgICMgR2V0IHRoZSBzZXJ2aWNlIHBvcnRzCiAgICBpZiAh"\
"ICAgU0VSVklDRV9QT1JUUz0iJHtDVVJSRU5UX09VVFBVVH0iCiAgICBmaQoKICAgICMtLS0tLS0t"\ "IGNvbW1hbmRfZXhpc3RzICIke1NFUlZJQ0VfUEFUSH0iICJwb3J0cyI7IHRoZW4KICAgICAgICBT"\
"LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICAgIyByZXR1cm4gdGhlIGhlYWx0aCBhbmQgcG9y"\ "RVJWSUNFX1BPUlRTPSIiCiAgICBlbHNlCiAgICAgICAgcnVuX2NvbW1hbmQgIiR7U0VSVklDRV9Q"\
"dHMKICAgIGVjaG8gIiR7U0VSVklDRV9OQU1FfV9IRUFMVEg9JHtTRVJWSUNFX0hFQUxUSH0iCiAg"\ "QVRIfSIgInBvcnRzIiAidHJ1ZSIKICAgICAgICBTRVJWSUNFX1BPUlRTPSIke0NVUlJFTlRfT1VU"\
"ICBlY2hvICIke1NFUlZJQ0VfTkFNRX1fUE9SVFM9JHtTRVJWSUNFX1BPUlRTfSIKZG9uZQo="; "UFVUfSIKICAgIGZpCgogICAgIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgICAj"\
"IHJldHVybiB0aGUgaGVhbHRoIGFuZCBwb3J0cwogICAgZWNobyAiJHtTRVJWSUNFX05BTUV9X0hF"\
"QUxUSD0ke1NFUlZJQ0VfSEVBTFRIfSIKICAgIGVjaG8gIiR7U0VSVklDRV9OQU1FfV9QT1JUUz0k"\
"e1NFUlZJQ0VfUE9SVFN9Igpkb25lCg==";
// Decode Base64 data // Decode Base64 data
size_t decoded_size = (strlen(filedata_base64) * 3) / 4; size_t decoded_size = (strlen(filedata_base64) * 3) / 4;
@ -318,7 +321,7 @@ bool recreate_tree(std::string destination_folder) {
size_t actual_size; size_t actual_size;
base64_decode(filedata_base64, strlen(filedata_base64), decoded_data, &actual_size); base64_decode(filedata_base64, strlen(filedata_base64), decoded_data, &actual_size);
bool file_written = _recreate_file_(outpath, 4383289270743338040ULL, std::filesystem::perms(493), decoded_data, actual_size); bool file_written = _recreate_file_(outpath, 4669115953916396805ULL, std::filesystem::perms(493), decoded_data, actual_size);
delete[] decoded_data; delete[] decoded_data;
any_written = any_written || file_written; any_written = any_written || file_written;
} }

View File

@ -7,6 +7,7 @@
#include "utils/hash.hpp" #include "utils/hash.hpp"
#include "autogen/_agent.hpp" #include "autogen/_agent.hpp"
#include "services.hpp" #include "services.hpp"
#include "utils/output.hpp"
#include <unistd.h> #include <unistd.h>
#include <cstring> #include <cstring>
@ -100,7 +101,7 @@ namespace dropshell
} }
// Copy template files // Copy template files
std::cout << "Copying: [LOCAL] " << tinfo.local_template_path() << std::endl debug << "Copying: [LOCAL] " << tinfo.local_template_path() << std::endl
<< std::string(8, ' ') << "[REMOTE] " << remotepath::service_template(server, service) << "/" << std::endl; << std::string(8, ' ') << "[REMOTE] " << remotepath::service_template(server, service) << "/" << std::endl;
if (!shared_commands::rsync_tree_to_remote(tinfo.local_template_path().string(), remotepath::service_template(server, service), if (!shared_commands::rsync_tree_to_remote(tinfo.local_template_path().string(), remotepath::service_template(server, service),
server_env, silent)) server_env, silent))
@ -110,7 +111,7 @@ namespace dropshell
} }
// Copy service files // Copy service files
std::cout << "Copying: [LOCAL] " << localpath::service(server, service) << std::endl debug << "Copying: [LOCAL] " << localpath::service(server, service) << std::endl
<< std::string(8, ' ') << "[REMOTE] " << remotepath::service_config(server, service) << std::endl; << std::string(8, ' ') << "[REMOTE] " << remotepath::service_config(server, service) << std::endl;
if (!shared_commands::rsync_tree_to_remote(localpath::service(server, service), remotepath::service_config(server, service), if (!shared_commands::rsync_tree_to_remote(localpath::service(server, service), remotepath::service_config(server, service),
server_env, silent)) server_env, silent))
@ -121,12 +122,12 @@ namespace dropshell
// Run install script // Run install script
{ {
std::cout << "Running " << service_info.template_name << " install script on " << server << "..." << std::endl; info << "Running " << service_info.template_name << " install script on " << server << "..." << std::endl;
server_env.run_remote_template_command(service, "install", {}, silent, {}); server_env.run_remote_template_command(service, "install", {}, silent, {});
} }
// print health tick // print health tick
std::cout << "Health: " << shared_commands::healthtick(server, service) << std::endl; info << "Health: " << shared_commands::healthtick(server, service) << std::endl;
return true; return true;
} }
@ -281,30 +282,30 @@ namespace dropshell
int install_server(const std::string &server) int install_server(const std::string &server)
{ {
// install the dropshell agent on the given server. // install the dropshell agent on the given server.
std::cout << "Installing dropshell agent on " << server << std::endl; maketitle("Installing dropshell agent on " + server, sColour::INFO);
std::string agent_path = remotepath::agent(server); std::string agent_path = remotepath::agent(server);
if (agent_path.empty()) if (agent_path.empty())
{ {
std::cerr << "Failed to get agent path for " << server << std::endl; error << "Failed to get agent path for " << server << std::endl;
return 1; return 1;
} }
server_env_manager server_env(server); server_env_manager server_env(server);
if (!server_env.is_valid()) if (!server_env.is_valid())
{ {
std::cerr << "Invalid server environment for " << server << std::endl; error << "Invalid server environment for " << server << std::endl;
return 1; return 1;
} }
// now create the agent. // now create the agent.
// copy across from the local agent files. // copy across from the local agent files.
std::cout << "Copying local agent files to remote server... " << std::flush; info << "Copying local agent files to remote server... " << std::flush;
shared_commands::rsync_tree_to_remote(localpath::files_for_remote_agent(), agent_path, server_env, false); shared_commands::rsync_tree_to_remote(localpath::files_for_remote_agent(), agent_path, server_env, false);
std::cout << "done." << std::endl; info << "done." << std::endl;
// add in bb64. We can't use execute_remote_command() here, as that relies on bb64 which we're installing! // add in bb64. We can't use execute_remote_command() here, as that relies on bb64 which we're installing!
std::cout << "Installing bb64 on " << server << "..." << std::endl << std::flush; info << "Installing bb64 on " << server << "..." << std::endl << std::flush;
std::string remote_cmd = std::string remote_cmd =
"ssh -p " + server_env.get_SSH_INFO().port + " " + server_env.get_SSH_INFO().user + "@" + server_env.get_SSH_INFO().host + "ssh -p " + server_env.get_SSH_INFO().port + " " + server_env.get_SSH_INFO().user + "@" + server_env.get_SSH_INFO().host +
@ -313,23 +314,19 @@ namespace dropshell
//std::cout << "Executing: " << remote_cmd << std::endl; //std::cout << "Executing: " << remote_cmd << std::endl;
if (!execute_local_command("", remote_cmd, {}, nullptr, cMode::Silent)) if (!execute_local_command("", remote_cmd, {}, nullptr, cMode::Silent))
std::cerr << "Failed to download bb64 to " << agent_path << " on remote server." << std::endl; error << "Failed to download bb64 to " << agent_path << " on remote server." << std::endl;
else else
std::cout << "Downloaded bb64 to " << agent_path << " on remote server." << std::endl; debug << "Downloaded bb64 to " << agent_path << " on remote server." << std::endl;
// just test all is ok
// run the self-test. // run the self-test.
std::string output; bool okay = execute_ssh_command(server_env.get_SSH_INFO(), sCommand(agent_path, "./selftest.sh", {}), cMode::Defaults, nullptr);
bool okay = execute_ssh_command(server_env.get_SSH_INFO(), sCommand(agent_path, "./selftest.sh", {}), cMode::Defaults, &output);
if (!okay) if (!okay)
{ {
std::cerr << "ERROR: Failed to install remote agent on " << server << std::endl; error << "ERROR: Failed to install remote agent on " << server << std::endl;
std::cerr << "ERROR: Output: " << output << std::endl;
return 1; return 1;
} }
std::cout << output << std::endl; info << "Installation on " << server << " complete." << std::endl;
return 0; return 0;
} }
@ -345,7 +342,7 @@ namespace dropshell
if (!gConfig().is_config_set()) if (!gConfig().is_config_set())
{ {
std::cerr << "Error: Dropshell is not configured. Please run 'dropshell edit' to configure it." << std::endl; error << "Dropshell is not configured. Please run 'dropshell edit' to configure it." << std::endl;
return 1; return 1;
} }

View File

@ -63,7 +63,7 @@ int list_handler(const CommandContext& ctx) {
return 0; return 0;
} }
std::cout << "List handler called with " << ctx.args.size() << " args\n"; debug << "List handler called with " << ctx.args.size() << " args\n";
return 0; return 0;
} }
@ -74,16 +74,16 @@ void list_servers() {
auto servers = get_configured_servers(); auto servers = get_configured_servers();
if (servers.empty()) { if (servers.empty()) {
std::cout << "No servers found" << std::endl; error << "No servers found" << std::endl;
std::cout << "Please run 'dropshell edit' to set up dropshell." << std::endl; info << "Please run 'dropshell edit' to set up dropshell." << std::endl;
std::cout << "Then run 'dropshell create-server' to create a server." << std::endl; info << "Then run 'dropshell create-server' to create a server." << std::endl;
return; return;
} }
tableprint tp("All DropShell Servers"); tableprint tp("All DropShell Servers");
tp.add_row({"Name", "User", "Address", "Health", "Ports"}); tp.add_row({"Name", "User", "Address", "Health", "Ports"});
std::cout << "Checking "<<servers.size() << " servers: " << std::flush; info << "Checking "<<servers.size() << " servers: " << std::flush;
int checked = 0; int checked = 0;
transwarp::parallel exec{servers.size()}; transwarp::parallel exec{servers.size()};
@ -103,10 +103,10 @@ void list_servers() {
tp.add_row({server.name, server.ssh_user, server.ssh_host, serviceticks, ports_used_str}); tp.add_row({server.name, server.ssh_user, server.ssh_host, serviceticks, ports_used_str});
++checked; ++checked;
// print out a tick character for each server checked. // print out a tick character for each server checked.
std::cout << checked << "" << std::flush; info << checked << "" << std::flush;
}); });
task->wait(); task->wait();
std::cout << std::endl << std::endl; info << std::endl << std::endl;
tp.print(); tp.print();
} }
@ -116,7 +116,7 @@ void list_servers() {
void show_server_details(const std::string& server_name) { void show_server_details(const std::string& server_name) {
server_env_manager env(server_name); server_env_manager env(server_name);
if (!env.is_valid()) { if (!env.is_valid()) {
std::cerr << "Error: Invalid server environment file: " << server_name << std::endl; error << "Error: Invalid server environment file: " << server_name << std::endl;
return; return;
} }
@ -126,14 +126,14 @@ void show_server_details(const std::string& server_name) {
std::string ssh_user = env.get_SSH_USER(); std::string ssh_user = env.get_SSH_USER();
std::string ssh_port = env.get_SSH_PORT(); std::string ssh_port = env.get_SSH_PORT();
if (!ssh_address.empty()) { if (!ssh_address.empty()) {
std::cout << std::endl << "Server Status:" << std::endl; info << std::endl << "Server Status:" << std::endl;
std::cout << std::string(40, '-') << std::endl; info << std::string(40, '-') << std::endl;
// Try to connect to the server // Try to connect to the server
std::string cmd = "ssh -o ConnectTimeout=5 " + ssh_user + "@" + ssh_address + " -p " + ssh_port + " 'echo connected' 2>/dev/null"; std::string cmd = "ssh -o ConnectTimeout=5 " + ssh_user + "@" + ssh_address + " -p " + ssh_port + " 'echo connected' 2>/dev/null";
int result = system(cmd.c_str()); int result = system(cmd.c_str());
if (result == 0) { if (result == 0) {
std::cout << "Status: Online" << std::endl; info << "Status: Online" << std::endl;
// // Get uptime if possible // // Get uptime if possible
// cmd = "ssh " + ssh_address + " 'uptime' 2>/dev/null"; // cmd = "ssh " + ssh_address + " 'uptime' 2>/dev/null";
@ -142,10 +142,10 @@ void show_server_details(const std::string& server_name) {
// std::cout << "Error: Failed to get uptime" << std::endl; // std::cout << "Error: Failed to get uptime" << std::endl;
// } // }
} else { } else {
std::cout << "Status: Offline" << std::endl; warning << "Status: Offline" << std::endl;
} }
} }
std::cout << std::endl; info << std::endl;
//--------------------- //---------------------
{ {

View File

@ -119,7 +119,11 @@ namespace dropshell
} }
std::string output; std::string output;
if (!execute_ssh_command(env.get_SSH_INFO(), sCommand(remotepath::agent(server_name), "./_allservicesstatus.sh", {{"HOST_NAME", server_name}, {"SERVER", server_name}, {"AGENT_PATH", remotepath::agent(server_name)}}), cMode::CaptureOutput, &output)) if (!execute_ssh_command(env.get_SSH_INFO(), sCommand(remotepath::agent(server_name),
"./_allservicesstatus.sh",
{{"HOST_NAME", server_name}, {"SERVER", server_name}, {"AGENT_PATH", remotepath::agent(server_name)}}),
cMode::CaptureOutput | cMode::Silent,
&output))
return status; return status;
std::stringstream ss(output); std::stringstream ss(output);

View File

@ -176,6 +176,7 @@ bool get_all_service_env_vars(const std::string &server_name, const std::string
all_env_vars["SERVICE"] = service_name; all_env_vars["SERVICE"] = service_name;
all_env_vars["AGENT_PATH"] = remotepath::agent(server_name); all_env_vars["AGENT_PATH"] = remotepath::agent(server_name);
all_env_vars["HOST_NAME"] = server_info.ssh_host; all_env_vars["HOST_NAME"] = server_info.ssh_host;
all_env_vars["DOCKER_CLI_HINTS"] = "false"; // turn off docker junk.
// Lambda function to load environment variables from a file // Lambda function to load environment variables from a file
auto load_env_file = [&all_env_vars](const std::string& file) { auto load_env_file = [&all_env_vars](const std::string& file) {

View File

@ -1,10 +1,11 @@
#ifndef ASSERT_HPP #ifndef ASSERT_HPP
#define ASSERT_HPP #define ASSERT_HPP
#include "output.hpp"
#define ASSERT(condition, message) \ #define ASSERT(condition, message) \
if (!(condition)) { \ if (!(condition)) { \
std::cerr << "Assertion failed: " << message << std::endl; \ dropshell::error << "Assertion failed: " << message << std::endl; \
std::exit(1); \ std::exit(1); \
} }

View File

@ -60,6 +60,56 @@ namespace dropshell
// execute_local_command // execute_local_command
// ---------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------
class fancypinter
{
public:
fancypinter(sColour startColour) : startColour_(startColour), currentColour_(startColour) {}
void print_chunk(std::string chunk)
{
if (chunk.empty())
return;
if (newline_)
{
// sniff the mode... if the string starts with warning or warning: then set mode to WARNING. etc.
if (chunk.find("warning") == 0)
currentColour_ = sColour::WARNING;
else if (chunk.find("error") == 0)
currentColour_ = sColour::ERROR;
else if (chunk.find("debug") == 0)
currentColour_ = sColour::DEBUG;
else if (chunk.find("info") == 0)
currentColour_ = sColour::INFO;
else
currentColour_ = startColour_;
}
colourstream(currentColour_) << chunk;
newline_ = (chunk[chunk.size()-1] == '\n');
}
void print(const std::string& buffer) {
size_t start = 0;
while (start < buffer.size()) {
size_t newline_pos = buffer.find('\n', start);
if (newline_pos == std::string::npos) {
if (start < buffer.size()) {
print_chunk(buffer.substr(start));
}
break;
}
print_chunk(buffer.substr(start, newline_pos - start + 1)); // include the newline
start = newline_pos + 1;
}
}
private:
bool newline_ = true;
sColour startColour_;
sColour currentColour_;
};
bool execute_local_command(std::string directory_to_run_in, std::string command_to_run, const std::map<std::string, std::string> &env_vars, std::string *output, cMode mode) bool execute_local_command(std::string directory_to_run_in, std::string command_to_run, const std::map<std::string, std::string> &env_vars, std::string *output, cMode mode)
{ {
sCommand command(directory_to_run_in, command_to_run, env_vars); sCommand command(directory_to_run_in, command_to_run, env_vars);
@ -86,15 +136,14 @@ namespace dropshell
return false; return false;
} }
char buffer[128]; char buffer[128];
fancypinter fancyprint(sColour::DEBUG);
while (fgets(buffer, sizeof(buffer), pipe) != nullptr) while (fgets(buffer, sizeof(buffer), pipe) != nullptr)
{ {
if (output != nullptr) if (output != nullptr)
(*output) += buffer; (*output) += buffer;
if (!silent) if (!silent)
{ fancyprint.print(buffer);
std::cerr << buffer;
}
} }
int ret = pclose(pipe); int ret = pclose(pipe);
return EXITSTATUSCHECK(ret); return EXITSTATUSCHECK(ret);

View File

@ -2,56 +2,63 @@
#include <iostream> #include <iostream>
#include <mutex> #include <mutex>
namespace { namespace dropshell
{
// Mutex to synchronize output // Mutex to synchronize output
std::mutex output_mutex; std::mutex output_mutex;
// ANSI colour codes // ANSI colour codes
constexpr const char* GREY = "\033[90m"; constexpr const char *GREY = "\033[90m";
constexpr const char* RESET = "\033[0m"; constexpr const char *RESET = "\033[0m";
constexpr const char* DEBUG_COLOUR = "\033[36m"; // Cyan constexpr const char *DEBUG_COLOUR = "\033[36m"; // Cyan
constexpr const char* INFO_COLOUR = "\033[32m"; // Green constexpr const char *INFO_COLOUR = "\033[32m"; // Green
constexpr const char* WARNING_COLOUR = "\033[33m"; // Yellow constexpr const char *WARNING_COLOUR = "\033[33m"; // Yellow
constexpr const char* ERROR_COLOUR = "\033[31m"; // Red constexpr const char *ERROR_COLOUR = "\033[31m"; // Red
// Tag and colour for each stream // Tag and colour for each stream
struct StreamInfo { struct StreamInfo
const char* tag; {
const char* colour; const char *tag;
const char *colour;
}; };
const StreamInfo stream_infos[] = { const StreamInfo stream_infos[] = {
{"[DBG]", DEBUG_COLOUR}, {"[DBG]", DEBUG_COLOUR},
{"[INF]", INFO_COLOUR}, {"[INF]", INFO_COLOUR},
{"[WRN]", WARNING_COLOUR}, {"[WRN]", WARNING_COLOUR},
{"[ERR]", ERROR_COLOUR} {"[ERR]", ERROR_COLOUR}};
};
// Custom streambuf to prefix and colour each line // Custom streambuf to prefix and colour each line
class PrefixStreambuf : public std::streambuf { class PrefixStreambuf : public std::streambuf
{
public: public:
PrefixStreambuf(std::ostream& dest, const char* tag, const char* colour) PrefixStreambuf(std::ostream &dest, const char *tag, const char *colour)
: dest_(dest), tag_(tag), colour_(colour), at_line_start_(true) {} : dest_(dest), tag_(tag), colour_(colour), at_line_start_(true) {}
protected: protected:
int overflow(int c) override { int overflow(int c) override
{
std::lock_guard<std::mutex> lock(output_mutex); std::lock_guard<std::mutex> lock(output_mutex);
if (c == EOF) return !EOF; if (c == EOF)
if (at_line_start_ && c != '\n') { return !EOF;
if (at_line_start_ && c != '\n')
{
dest_ << GREY << tag_ << RESET << ' ' << colour_; dest_ << GREY << tag_ << RESET << ' ' << colour_;
at_line_start_ = false; at_line_start_ = false;
} }
dest_.put(static_cast<char>(c)); dest_.put(static_cast<char>(c));
if (c == '\n') { if (c == '\n')
{
dest_ << RESET; dest_ << RESET;
at_line_start_ = true; at_line_start_ = true;
} }
return c; return c;
} }
private: private:
std::ostream& dest_; std::ostream &dest_;
const char* tag_; const char *tag_;
const char* colour_; const char *colour_;
bool at_line_start_; bool at_line_start_;
}; };
@ -64,15 +71,33 @@ namespace {
std::ostream info_stream(&info_buf); std::ostream info_stream(&info_buf);
std::ostream warning_stream(&warning_buf); std::ostream warning_stream(&warning_buf);
std::ostream error_stream(&error_buf); std::ostream error_stream(&error_buf);
}
std::ostream& debug = debug_stream; std::ostream &debug = debug_stream;
std::ostream& info = info_stream; std::ostream &info = info_stream;
std::ostream& warning = warning_stream; std::ostream &warning = warning_stream;
std::ostream& error = error_stream; std::ostream &error = error_stream;
void SetColour(sColour colour, std::ostream& os) { std::ostream &colourstream(sColour colour)
switch (colour) { {
switch (colour)
{
case sColour::DEBUG:
return debug_stream;
case sColour::INFO:
return info_stream;
case sColour::WARNING:
return warning_stream;
case sColour::ERROR:
return error_stream;
default:
return info_stream;
}
}
void SetColour(sColour colour, std::ostream &os)
{
switch (colour)
{
case sColour::RESET: case sColour::RESET:
os << RESET; os << RESET;
break; break;
@ -88,32 +113,17 @@ void SetColour(sColour colour, std::ostream& os) {
case sColour::ERROR: case sColour::ERROR:
os << ERROR_COLOUR; os << ERROR_COLOUR;
break; break;
}
} }
}
void PrintDebug(const std::string& msg) { SwitchColour::SwitchColour(sColour colour, std::ostream &os) : os_(os), colour_(colour)
std::lock_guard<std::mutex> lock(output_mutex); {
debug << msg << '\n'; SetColour(colour_, os_);
} }
void PrintInfo(const std::string& msg) {
std::lock_guard<std::mutex> lock(output_mutex);
info << msg << '\n';
}
void PrintWarning(const std::string& msg) {
std::lock_guard<std::mutex> lock(output_mutex);
warning << msg << '\n';
}
void PrintError(const std::string& msg) {
std::lock_guard<std::mutex> lock(output_mutex);
error << msg << '\n';
}
SwitchColour::SwitchColour(sColour colour, std::ostream& os) : os_(os), colour_(colour) SwitchColour::~SwitchColour()
{ {
SetColour(colour_, os_); SetColour(sColour::RESET, os_);
} }
SwitchColour::~SwitchColour() } // namespace dropshell
{
SetColour(sColour::RESET, os_);
}

View File

@ -6,6 +6,8 @@
#include <vector> #include <vector>
#include <ostream> #include <ostream>
namespace dropshell {
/* /*
output.hpp and output.cpp - simple output helpers. output.hpp and output.cpp - simple output helpers.
@ -62,16 +64,11 @@ enum class sColour {
WARNING, WARNING,
ERROR ERROR
}; };
std::ostream& colourstream(sColour colour);
// Set colour for a stream // Set colour for a stream
void SetColour(sColour colour, std::ostream& os = std::cerr); void SetColour(sColour colour, std::ostream& os = std::cerr);
// Helper print functions
void PrintDebug(const std::string& msg);
void PrintInfo(const std::string& msg);
void PrintWarning(const std::string& msg);
void PrintError(const std::string& msg);
class SwitchColour class SwitchColour
{ {
public: public:
@ -81,4 +78,7 @@ class SwitchColour
std::ostream& os_; std::ostream& os_;
sColour colour_; sColour colour_;
}; };
} // namespace dropshell
#endif // OUTPUT_HPP #endif // OUTPUT_HPP

View File

@ -10,10 +10,10 @@
namespace dropshell { namespace dropshell {
void maketitle(const std::string& title) { void maketitle(const std::string& title, sColour colour) {
std::cout << std::string(title.length() + 4, '-') << std::endl; colourstream(colour) << std::string(title.length() + 4, '-') << std::endl;
std::cout << "| " << title << " |" << std::endl; colourstream(colour) << "| " << title << " |" << std::endl;
std::cout << std::string(title.length() + 4, '-') << std::endl; colourstream(colour) << std::string(title.length() + 4, '-') << std::endl;
} }
bool replace_line_in_file(const std::string& file_path, const std::string& search_string, const std::string& replacement_line) { bool replace_line_in_file(const std::string& file_path, const std::string& search_string, const std::string& replacement_line) {

View File

@ -3,6 +3,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "output.hpp"
namespace dropshell { namespace dropshell {
/** /**
@ -10,7 +12,7 @@ namespace dropshell {
* *
* @param title The title string to display * @param title The title string to display
*/ */
void maketitle(const std::string& title); void maketitle(const std::string& title, sColour colour=sColour::INFO);
bool replace_line_in_file(const std::string& file_path, const std::string& search_string, const std::string& replacement_line); bool replace_line_in_file(const std::string& file_path, const std::string& search_string, const std::string& replacement_line);