.
This commit is contained in:
parent
bbf2575718
commit
d028a4d8c6
@ -21,6 +21,7 @@ configure_file(
|
|||||||
# Find required packages
|
# Find required packages
|
||||||
find_package(Boost REQUIRED COMPONENTS program_options filesystem system)
|
find_package(Boost REQUIRED COMPONENTS program_options filesystem system)
|
||||||
find_package(Curses REQUIRED)
|
find_package(Curses REQUIRED)
|
||||||
|
find_package(TBB REQUIRED)
|
||||||
|
|
||||||
# Auto-detect source files
|
# Auto-detect source files
|
||||||
file(GLOB_RECURSE SOURCES "src/*.cpp")
|
file(GLOB_RECURSE SOURCES "src/*.cpp")
|
||||||
@ -42,6 +43,7 @@ target_link_libraries(dropshell PRIVATE
|
|||||||
Boost::filesystem
|
Boost::filesystem
|
||||||
Boost::system
|
Boost::system
|
||||||
${CURSES_LIBRARIES}
|
${CURSES_LIBRARIES}
|
||||||
|
TBB::tbb
|
||||||
)
|
)
|
||||||
|
|
||||||
# Install targets
|
# Install targets
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <execution>
|
||||||
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
@ -55,18 +56,20 @@ void list_servers() {
|
|||||||
|
|
||||||
tableprint tp("All DropShell Servers");
|
tableprint tp("All DropShell Servers");
|
||||||
tp.add_row({"Name", "Address", "Health", "Ports"});
|
tp.add_row({"Name", "Address", "Health", "Ports"});
|
||||||
for (const auto& server : servers) {
|
|
||||||
|
std::for_each(std::execution::par, servers.begin(), servers.end(), [&](const ServerInfo& server) {
|
||||||
std::vector<int> ports_used;
|
std::vector<int> ports_used;
|
||||||
std::string serviceticks = "";
|
std::string serviceticks = "";
|
||||||
std::vector<ServiceInfo> services = get_server_services_info(server.name);
|
std::vector<ServiceInfo> services = get_server_services_info(server.name);
|
||||||
for (const auto& service : services) {
|
|
||||||
|
std::for_each(std::execution::par, services.begin(), services.end(), [&](const ServiceInfo& service) {
|
||||||
service_runner ss;
|
service_runner ss;
|
||||||
if (ss.init(server.name, service.service_name))
|
if (ss.init(server.name, service.service_name))
|
||||||
serviceticks += ss.healthmark() + " ";
|
serviceticks += ss.healthmark() + " ";
|
||||||
else std::cout<<"Error: Failed to initialise service runner for server: ["<<server.name<<"] and service: ["<<service.service_name<<"]"<<std::endl;
|
else std::cout<<"Error: Failed to initialise service runner for server: ["<<server.name<<"] and service: ["<<service.service_name<<"]"<<std::endl;
|
||||||
std::vector<int> ports = ss.get_ports();
|
std::vector<int> ports = ss.get_ports();
|
||||||
ports_used.insert(ports_used.end(), ports.begin(), ports.end());
|
ports_used.insert(ports_used.end(), ports.begin(), ports.end());
|
||||||
}
|
});
|
||||||
// convert ports_used to string
|
// convert ports_used to string
|
||||||
std::string ports_used_str = "";
|
std::string ports_used_str = "";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
@ -78,7 +81,7 @@ void list_servers() {
|
|||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
tp.add_row({server.name, server.ssh_host, serviceticks, ports_used_str});
|
tp.add_row({server.name, server.ssh_host, serviceticks, ports_used_str});
|
||||||
}
|
});
|
||||||
tp.print();
|
tp.print();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "templates.hpp"
|
#include "templates.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "utils/directories.hpp"
|
#include "utils/directories.hpp"
|
||||||
|
#include "utils/utils.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -155,7 +156,10 @@ void create_template(const std::string& template_name) {
|
|||||||
std::string replacement_line = "TEMPLATE=" + template_name;
|
std::string replacement_line = "TEMPLATE=" + template_name;
|
||||||
// replace the line in the example/service.env file with the replacement line
|
// replace the line in the example/service.env file with the replacement line
|
||||||
std::string service_env_path = new_template_path + "/example/service.env";
|
std::string service_env_path = new_template_path + "/example/service.env";
|
||||||
|
if (!replace_line_in_file(service_env_path, search_string, replacement_line)) {
|
||||||
|
std::cerr << "Error: Failed to replace TEMPLATE= line in service.env file" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 3. Print out the README.txt file and the path
|
// 3. Print out the README.txt file and the path
|
||||||
std::string readme_path = new_template_path + "/README.txt";
|
std::string readme_path = new_template_path + "/README.txt";
|
||||||
|
@ -134,14 +134,24 @@ std::string get_local_service_env_path(const std::string &server_name, const std
|
|||||||
return env.get_DROPSHELL_DIR();
|
return env.get_DROPSHELL_DIR();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_remote_service_path(const std::string &server_name, const std::string &service_name)
|
std::string get_remote_services_path(const std::string &server_name)
|
||||||
{
|
{
|
||||||
if (server_name.empty() || service_name.empty())
|
if (server_name.empty())
|
||||||
return std::string();
|
return std::string();
|
||||||
std::string dropshell_path = get_remote_DROPSHELL_path(server_name);
|
std::string dropshell_path = get_remote_DROPSHELL_path(server_name);
|
||||||
if (dropshell_path.empty())
|
if (dropshell_path.empty())
|
||||||
return std::string();
|
return std::string();
|
||||||
return (fs::path(dropshell_path) / service_name).string();
|
return (fs::path(dropshell_path) / "services").string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_remote_service_path(const std::string &server_name, const std::string &service_name)
|
||||||
|
{
|
||||||
|
if (server_name.empty() || service_name.empty())
|
||||||
|
return std::string();
|
||||||
|
std::string services_path = get_remote_services_path(server_name);
|
||||||
|
if (services_path.empty())
|
||||||
|
return std::string();
|
||||||
|
return (fs::path(services_path) / service_name).string();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_remote_service_config_path(const std::string &server_name, const std::string &service_name)
|
std::string get_remote_service_config_path(const std::string &server_name, const std::string &service_name)
|
||||||
|
@ -23,14 +23,16 @@ namespace dropshell {
|
|||||||
|
|
||||||
// remote paths
|
// remote paths
|
||||||
// DROPSHELL_DIR
|
// DROPSHELL_DIR
|
||||||
|
// |-- backups
|
||||||
|
// |-- services
|
||||||
// |-- service name
|
// |-- service name
|
||||||
// |-- config
|
// |-- config <-- this is passed as argument to all scripts
|
||||||
// |-- service.env
|
// |-- service.env
|
||||||
// |-- (user config files)
|
// |-- (user config files)
|
||||||
// |-- template
|
// |-- template
|
||||||
// |-- (script files)
|
// |-- (script files)
|
||||||
// |-- backups
|
|
||||||
std::string get_remote_DROPSHELL_path(const std::string &server_name);
|
std::string get_remote_DROPSHELL_path(const std::string &server_name);
|
||||||
|
std::string get_remote_services_path(const std::string &server_name);
|
||||||
std::string get_remote_service_path(const std::string &server_name, const std::string &service_name);
|
std::string get_remote_service_path(const std::string &server_name, const std::string &service_name);
|
||||||
std::string get_remote_service_config_path(const std::string &server_name, const std::string &service_name);
|
std::string get_remote_service_config_path(const std::string &server_name, const std::string &service_name);
|
||||||
std::string get_remote_service_template_path(const std::string &server_name, const std::string &service_name);
|
std::string get_remote_service_template_path(const std::string &server_name, const std::string &service_name);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace dropshell {
|
namespace dropshell {
|
||||||
|
|
||||||
@ -10,4 +12,34 @@ void maketitle(const std::string& title) {
|
|||||||
std::cout << std::string(title.length() + 4, '-') << std::endl;
|
std::cout << 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) {
|
||||||
|
std::ifstream input_file(file_path);
|
||||||
|
std::vector<std::string> file_lines;
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
if (!input_file.is_open()) {
|
||||||
|
std::cerr << "Error: Unable to open file: " << file_path << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (std::getline(input_file, line)) {
|
||||||
|
if (line.find(search_string) != std::string::npos)
|
||||||
|
file_lines.push_back(replacement_line);
|
||||||
|
else
|
||||||
|
file_lines.push_back(line);
|
||||||
|
}
|
||||||
|
input_file.close();
|
||||||
|
|
||||||
|
std::ofstream output_file(file_path);
|
||||||
|
if (!output_file.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error: Unable to open file: " << file_path << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const auto& modified_line : file_lines)
|
||||||
|
output_file << modified_line << "\n";
|
||||||
|
output_file.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dropshell
|
} // namespace dropshell
|
@ -11,4 +11,6 @@ namespace dropshell {
|
|||||||
*/
|
*/
|
||||||
void maketitle(const std::string& title);
|
void maketitle(const std::string& title);
|
||||||
|
|
||||||
|
bool replace_line_in_file(const std::string& file_path, const std::string& search_string, const std::string& replacement_line);
|
||||||
|
|
||||||
} // namespace dropshell
|
} // namespace dropshell
|
23
templates/dropshell-agent/README.txt
Normal file
23
templates/dropshell-agent/README.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
DropShell Template Example
|
||||||
|
|
||||||
|
Shell scripts defined in this folder are run as DropShell commands on the remote server (not locally!).
|
||||||
|
All scripts are passed the directory containing the server-specific service environment (SSSE) as an argument
|
||||||
|
(the environment file, along with any other server and service-specific files, is then in $1/service.env)
|
||||||
|
|
||||||
|
The default SSSE file included when a new service is created is in example/service.env. This must exist,
|
||||||
|
and must at minimum contain the TEMPLATE=<template_name> variable.
|
||||||
|
|
||||||
|
The optional backups script gets a second argument, which is the backup file to create (a single tgz file).
|
||||||
|
|
||||||
|
Mandatory scripts are:
|
||||||
|
- install.sh
|
||||||
|
- uninstall.sh
|
||||||
|
- start.sh
|
||||||
|
- stop.sh
|
||||||
|
|
||||||
|
Optional standard scripts are:
|
||||||
|
- backup.sh
|
||||||
|
- status.sh
|
||||||
|
- ports.sh
|
||||||
|
- logs.sh
|
||||||
|
|
60
templates/dropshell-agent/_allservicesstatus.sh
Normal file
60
templates/dropshell-agent/_allservicesstatus.sh
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This script checks ALL services on the server and returns a status for each.
|
||||||
|
|
||||||
|
# Return format is simple ENV with the following format:
|
||||||
|
# SERVICE_NAME_HEALTH=healthy|unhealthy|unknown
|
||||||
|
# SERVICE_NAME_PORTS=port1,port2,port3
|
||||||
|
|
||||||
|
# Get all services on the server
|
||||||
|
SCRIPT_DIR="$(dirname "$0")"
|
||||||
|
|
||||||
|
# // DROPSHELL_DIR
|
||||||
|
# // |-- backups
|
||||||
|
# // |-- services
|
||||||
|
# // |-- service name
|
||||||
|
# // |-- config <-- this is passed as argument to all scripts
|
||||||
|
# // |-- service.env
|
||||||
|
# // |-- (user config files)
|
||||||
|
# // |-- template
|
||||||
|
# // |-- (script files)
|
||||||
|
|
||||||
|
# Get all services on the server
|
||||||
|
SERVICES_PATH="${SCRIPT_DIR}/../"
|
||||||
|
|
||||||
|
# Get all service names
|
||||||
|
SERVICE_NAMES=$(ls "${SERVICES_PATH}")
|
||||||
|
|
||||||
|
# Iterate over all service names
|
||||||
|
for SERVICE_NAME in ${SERVICE_NAMES}; do
|
||||||
|
# Get the service health
|
||||||
|
SERVICE_PATH="${SERVICES_PATH}/${SERVICE_NAME}"
|
||||||
|
STATUS_FILE="${SERVICE_PATH}/template/status.sh"
|
||||||
|
if [ -f "${STATUS_FILE}" ]; then
|
||||||
|
# suppress all output from the status script
|
||||||
|
if $(bash "${STATUS_FILE}" "${SERVICE_PATH}/config" > /dev/null 2>&1); then
|
||||||
|
SERVICE_HEALTH="healthy"
|
||||||
|
else
|
||||||
|
SERVICE_HEALTH="unhealthy"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
SERVICE_HEALTH="unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the service ports
|
||||||
|
PORTS_FILE="${SERVICE_PATH}/template/ports.sh"
|
||||||
|
if [ -f "${PORTS_FILE}" ]; then
|
||||||
|
# suppress all output from the ports script
|
||||||
|
SERVICE_PORTS=$(bash "${PORTS_FILE}" "${SERVICE_PATH}/config" > /dev/null 2>&1)
|
||||||
|
else
|
||||||
|
SERVICE_PORTS="unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# return the health and ports
|
||||||
|
echo "${SERVICE_NAME}_HEALTH=${SERVICE_HEALTH}"
|
||||||
|
echo "${SERVICE_NAME}_PORTS=${SERVICE_PORTS}"
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
4
templates/dropshell-agent/example/service.env
Normal file
4
templates/dropshell-agent/example/service.env
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Template to use - always required!
|
||||||
|
TEMPLATE=dropshell-agent
|
||||||
|
|
||||||
|
|
8
templates/dropshell-agent/install.sh
Normal file
8
templates/dropshell-agent/install.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# INSTALL SCRIPT
|
||||||
|
# The install script is required for all templates.
|
||||||
|
# It is used to install the service on the server.
|
||||||
|
# It is called with the path to the server specific env file as an argument.
|
||||||
|
|
||||||
|
echo "Installation of ${CONTAINER_NAME} complete"
|
8
templates/dropshell-agent/start.sh
Normal file
8
templates/dropshell-agent/start.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# START SCRIPT
|
||||||
|
# The start script is required for all templates.
|
||||||
|
# It is used to start the service on the server.
|
||||||
|
# It is called with the path to the server specific env file as an argument.
|
||||||
|
|
||||||
|
|
8
templates/dropshell-agent/status.sh
Normal file
8
templates/dropshell-agent/status.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# STATUS SCRIPT
|
||||||
|
# The status script is OPTIONAL.
|
||||||
|
# It is used to return the status of the service (0 is healthy, 1 is unhealthy).
|
||||||
|
# It is called with the path to the server specific env file as an argument.
|
||||||
|
|
||||||
|
return 0
|
7
templates/dropshell-agent/stop.sh
Normal file
7
templates/dropshell-agent/stop.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# STOP SCRIPT
|
||||||
|
# The stop script is required for all templates.
|
||||||
|
# It is used to stop the service on the server.
|
||||||
|
# It is called with the path to the server specific env file as an argument.
|
||||||
|
|
7
templates/dropshell-agent/uninstall.sh
Normal file
7
templates/dropshell-agent/uninstall.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# UNINSTALL SCRIPT
|
||||||
|
# The uninstall script is required for all templates.
|
||||||
|
# It is used to uninstall the service from the server.
|
||||||
|
# It is called with the path to the server specific env file as an argument.
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user