Servers
This commit is contained in:
parent
0eacb838ce
commit
a718f23375
@ -7,15 +7,15 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
# Find required packages
|
# Find required packages
|
||||||
find_package(Boost REQUIRED COMPONENTS program_options filesystem system)
|
find_package(Boost REQUIRED COMPONENTS program_options filesystem system)
|
||||||
|
|
||||||
|
# Auto-detect source files
|
||||||
|
file(GLOB_RECURSE SOURCES "src/*.cpp")
|
||||||
|
file(GLOB_RECURSE HEADERS "src/*.hpp")
|
||||||
|
|
||||||
# Add executable
|
# Add executable
|
||||||
add_executable(dropshell
|
add_executable(dropshell ${SOURCES})
|
||||||
src/main.cpp
|
|
||||||
src/version.cpp
|
# Set include directories
|
||||||
src/status.cpp
|
target_include_directories(dropshell PRIVATE src)
|
||||||
src/servers.cpp
|
|
||||||
src/help.cpp
|
|
||||||
src/config.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Link libraries
|
# Link libraries
|
||||||
target_link_libraries(dropshell PRIVATE
|
target_link_libraries(dropshell PRIVATE
|
||||||
|
@ -7,7 +7,7 @@ _dropshell_completions() {
|
|||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
|
|
||||||
# List of main commands
|
# List of main commands
|
||||||
opts="help version status servers"
|
opts="help version status servers templates"
|
||||||
|
|
||||||
# If we're completing the first argument, show all commands
|
# If we're completing the first argument, show all commands
|
||||||
if [[ ${COMP_CWORD} -eq 1 ]] ; then
|
if [[ ${COMP_CWORD} -eq 1 ]] ; then
|
||||||
@ -36,6 +36,10 @@ _dropshell_completions() {
|
|||||||
COMPREPLY=( $(compgen -W "${servers[@]}" -- ${cur}) )
|
COMPREPLY=( $(compgen -W "${servers[@]}" -- ${cur}) )
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
templates)
|
||||||
|
# No additional completions for templates
|
||||||
|
COMPREPLY=()
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
27
src/dropshell.cpp
Normal file
27
src/dropshell.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "dropshell.hpp"
|
||||||
|
#include "templates.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
void dropshell::list_templates() {
|
||||||
|
template_manager tm;
|
||||||
|
std::vector<template_info> templates;
|
||||||
|
|
||||||
|
if (!tm.get_templates(templates)) {
|
||||||
|
std::cerr << "Error: Failed to get templates" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (templates.empty()) {
|
||||||
|
std::cout << "No templates found." << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Available templates:" << std::endl;
|
||||||
|
std::cout << std::left << std::setw(20) << "Name" << "Path" << std::endl;
|
||||||
|
std::cout << std::string(60, '-') << std::endl;
|
||||||
|
|
||||||
|
for (const auto& t : templates) {
|
||||||
|
std::cout << std::left << std::setw(20) << t.name << t.path << std::endl;
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,8 @@ void print_help(const boost::program_options::options_description& desc);
|
|||||||
void print_version();
|
void print_version();
|
||||||
void check_status();
|
void check_status();
|
||||||
void list_servers();
|
void list_servers();
|
||||||
|
void list_templates();
|
||||||
|
void show_server_details(const std::string& server_name);
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
std::vector<ServerInfo> get_configured_servers();
|
std::vector<ServerInfo> get_configured_servers();
|
||||||
|
@ -15,10 +15,14 @@ void print_help(const boost::program_options::options_description& desc) {
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::cout << " status Check system status" << std::endl;
|
std::cout << " status Check system status" << std::endl;
|
||||||
std::cout << " servers List configured servers" << std::endl;
|
std::cout << " servers List configured servers" << std::endl;
|
||||||
|
std::cout << " servers NAME Show details for specific server" << std::endl;
|
||||||
|
std::cout << " templates List available templates" << std::endl;
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::cout << "Examples:" << std::endl;
|
std::cout << "Examples:" << std::endl;
|
||||||
std::cout << " dropshell servers" << std::endl;
|
std::cout << " dropshell servers" << std::endl;
|
||||||
|
std::cout << " dropshell servers myserver" << std::endl;
|
||||||
std::cout << " dropshell init /path/to/directory" << std::endl;
|
std::cout << " dropshell init /path/to/directory" << std::endl;
|
||||||
|
std::cout << " dropshell templates" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dropshell
|
} // namespace dropshell
|
@ -51,7 +51,16 @@ int main(int argc, char* argv[]) {
|
|||||||
dropshell::check_status();
|
dropshell::check_status();
|
||||||
return 0;
|
return 0;
|
||||||
} else if (cmd == "servers") {
|
} else if (cmd == "servers") {
|
||||||
|
if (argc > 2) {
|
||||||
|
// Show details for specific server
|
||||||
|
dropshell::show_server_details(argv[2]);
|
||||||
|
} else {
|
||||||
|
// List all servers
|
||||||
dropshell::list_servers();
|
dropshell::list_servers();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else if (cmd == "templates") {
|
||||||
|
dropshell::list_templates();
|
||||||
return 0;
|
return 0;
|
||||||
} else if (cmd == "init") {
|
} else if (cmd == "init") {
|
||||||
if (!vm.count("directory")) {
|
if (!vm.count("directory")) {
|
||||||
|
74
src/server_env.cpp
Normal file
74
src/server_env.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include "server_env.hpp"
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <boost/property_tree/ini_parser.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
|
server_env::server_env(const std::string& path) {
|
||||||
|
// Construct the full path to _server.env
|
||||||
|
boost::filesystem::path env_path = boost::filesystem::path(path) / "_server.env";
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
if (!boost::filesystem::exists(env_path)) {
|
||||||
|
throw std::runtime_error("Server environment file not found: " + env_path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Read the INI file
|
||||||
|
boost::property_tree::ptree pt;
|
||||||
|
boost::property_tree::ini_parser::read_ini(env_path.string(), pt);
|
||||||
|
|
||||||
|
// Store all variables
|
||||||
|
for (const auto& section : pt) {
|
||||||
|
for (const auto& key_value : section.second) {
|
||||||
|
variables[key_value.first] = key_value.second.get_value<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify required variables exist
|
||||||
|
if (variables.find("SSH_HOST") == variables.end() ||
|
||||||
|
variables.find("SSH_USER") == variables.end() ||
|
||||||
|
variables.find("SSH_PORT") == variables.end()) {
|
||||||
|
throw std::runtime_error("Missing required variables in server environment file");
|
||||||
|
}
|
||||||
|
} catch (const boost::property_tree::ini_parser_error& e) {
|
||||||
|
throw std::runtime_error("Failed to parse server environment file: " + std::string(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string server_env::get_variable(const std::string& name) {
|
||||||
|
auto it = variables.find(name);
|
||||||
|
if (it == variables.end()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value = it->second;
|
||||||
|
|
||||||
|
// Replace ${USER} with actual username
|
||||||
|
const char* username = std::getenv("USER");
|
||||||
|
if (username) {
|
||||||
|
std::string user_var = "${USER}";
|
||||||
|
size_t pos = value.find(user_var);
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
value.replace(pos, user_var.length(), username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string server_env::get_SSH_HOST() {
|
||||||
|
return get_variable("SSH_HOST");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string server_env::get_SSH_USER() {
|
||||||
|
return get_variable("SSH_USER");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string server_env::get_SSH_PORT() {
|
||||||
|
return get_variable("SSH_PORT");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dropshell
|
32
src/server_env.hpp
Normal file
32
src/server_env.hpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// server_env.hpp
|
||||||
|
//
|
||||||
|
// read the _server.env file and provide a class to access the variables
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
|
// reads path / _server.env and provides a class to access the variables.
|
||||||
|
// each env file is required to have the following variables:
|
||||||
|
// SSH_HOST
|
||||||
|
// SSH_USER
|
||||||
|
// SSH_PORT
|
||||||
|
// the following replacements are made in the values:
|
||||||
|
// ${USER} -> the username of the user running dropshell
|
||||||
|
class server_env {
|
||||||
|
public:
|
||||||
|
server_env(const std::string& path);
|
||||||
|
std::string get_variable(const std::string& name);
|
||||||
|
|
||||||
|
std::string get_SSH_HOST();
|
||||||
|
std::string get_SSH_USER();
|
||||||
|
std::string get_SSH_PORT();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::string> variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dropshell
|
||||||
|
|
@ -86,4 +86,67 @@ void list_servers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void show_server_details(const std::string& server_name) {
|
||||||
|
std::string user_dir;
|
||||||
|
if (!get_user_directory(user_dir)) {
|
||||||
|
std::cerr << "Error: User directory not set" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path server_dir = fs::path(user_dir) / "servers" / server_name;
|
||||||
|
if (!fs::exists(server_dir)) {
|
||||||
|
std::cerr << "Error: Server '" << server_name << "' not found" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path env_file = server_dir / "_server.env";
|
||||||
|
if (!fs::exists(env_file)) {
|
||||||
|
std::cerr << "Error: Server configuration file not found" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Server Details: " << server_name << std::endl;
|
||||||
|
std::cout << std::string(40, '-') << std::endl;
|
||||||
|
|
||||||
|
std::ifstream file(env_file.string());
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
if (!line.empty() && line[0] != '#') {
|
||||||
|
std::cout << line << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if server is reachable via SSH
|
||||||
|
std::string ssh_address;
|
||||||
|
file.clear();
|
||||||
|
file.seekg(0);
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
if (boost::starts_with(line, "SSH_ADDRESS=")) {
|
||||||
|
ssh_address = line.substr(12);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ssh_address.empty()) {
|
||||||
|
std::cout << std::endl << "Server Status:" << std::endl;
|
||||||
|
std::cout << std::string(40, '-') << std::endl;
|
||||||
|
|
||||||
|
// Try to connect to the server
|
||||||
|
std::string cmd = "ssh -o ConnectTimeout=5 " + ssh_address + " 'echo connected' 2>/dev/null";
|
||||||
|
int result = system(cmd.c_str());
|
||||||
|
if (result == 0) {
|
||||||
|
std::cout << "Status: Online" << std::endl;
|
||||||
|
|
||||||
|
// Get uptime if possible
|
||||||
|
cmd = "ssh " + ssh_address + " 'uptime' 2>/dev/null";
|
||||||
|
int rval = system(cmd.c_str());
|
||||||
|
if (rval != 0) {
|
||||||
|
std::cout << "Error: Failed to get uptime" << std::endl;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "Status: Offline" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dropshell
|
} // namespace dropshell
|
@ -5,6 +5,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
template_manager::template_manager() {
|
template_manager::template_manager() {
|
||||||
// Constructor implementation
|
// Constructor implementation
|
||||||
}
|
}
|
||||||
@ -74,3 +76,4 @@ bool template_manager::get_template_info(const std::string& name, template_info&
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dropshell
|
@ -1,4 +1,9 @@
|
|||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
class template_info {
|
class template_info {
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -20,3 +25,5 @@ class template_manager {
|
|||||||
bool get_templates(std::vector<template_info>& templates);
|
bool get_templates(std::vector<template_info>& templates);
|
||||||
bool get_template_info(const std::string& name, template_info& info);
|
bool get_template_info(const std::string& name, template_info& info);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace dropshell
|
||||||
|
Loading…
x
Reference in New Issue
Block a user