More instructions

This commit is contained in:
Your Name 2025-04-25 23:29:50 +12:00
parent fb46dffdaf
commit 3c99ad1503
6 changed files with 103 additions and 25 deletions

View File

@ -29,6 +29,7 @@ void print_help() {
std::cout << std::endl; std::cout << std::endl;
std::cout << "Service commands: (if no service is specified, all services for the server are affected)" << std::endl; std::cout << "Service commands: (if no service is specified, all services for the server are affected)" << std::endl;
std::cout << " install SERVER [SERVICE] Install/reinstall/update service(s). Non-destructive." << std::endl; std::cout << " install SERVER [SERVICE] Install/reinstall/update service(s). Non-destructive." << std::endl;
std::cout << " edit SERVER [SERVICE] Edit the configuration of the server/service." << std::endl;
std::cout << " COMMAND SERVER [SERVICE] Run a command on service(s)." << std::endl; std::cout << " COMMAND SERVER [SERVICE] Run a command on service(s)." << std::endl;
std::cout << std::endl; std::cout << std::endl;
std::cout << "Standard commands: install, uninstall, backup, restore, start, stop" << std::endl; std::cout << "Standard commands: install, uninstall, backup, restore, start, stop" << std::endl;
@ -114,25 +115,26 @@ int main(int argc, char* argv[]) {
} }
// auto completion stuff. // auto completion stuff.
std::set<std::string> commands; std::set<std::string> template_shell_commands, full_command_set;
std::vector<dropshell::ServerInfo> servers = dropshell::get_configured_servers(); std::vector<dropshell::ServerInfo> servers = dropshell::get_configured_servers();
for (const auto& server : servers) for (const auto& server : servers)
{ {
std::vector<dropshell::ServiceInfo> services = dropshell::get_server_services_info(server.name); std::vector<dropshell::ServiceInfo> services = dropshell::get_server_services_info(server.name);
for (const auto& service : services) for (const auto& service : services)
commands.merge(dropshell::get_used_commands(server.name, service.service_name)); template_shell_commands.merge(dropshell::get_used_commands(server.name, service.service_name));
} }
if (cmd == "autocomplete_list_commands") { if (cmd == "autocomplete_list_commands") { // add in commands handled here, not by the template shell scripts.
commands.merge(std::set<std::string>{ std::set<std::string> full_command_set = template_shell_commands;
"help","init" full_command_set.merge(std::set<std::string>{
"help","init" // these are always available.
}); });
if (cfg->is_config_set()) if (cfg->is_config_set())
commands.merge(std::set<std::string>{ full_command_set.merge(std::set<std::string>{
"server","templates","create-service","create-template","create-server","ssh" "server","templates","create-service","create-template","create-server","edit","ssh" // only if we have a config.
}); });
for (const auto& command : commands) { for (const auto& command : full_command_set) {
std::cout << command << std::endl; std::cout << command << std::endl;
} }
return 0; return 0;
@ -233,7 +235,19 @@ int main(int argc, char* argv[]) {
return 0; return 0;
} }
if (cmd == "edit" && argc < 4) {
if (argc < 3)
{
std::cerr << "Error: edit requires a server name and optionally service name" << std::endl;
return 1;
}
dropshell::edit_server(argv[2]);
return 0;
}
// handle running a command. // handle running a command.
std::set<std::string> commands = template_shell_commands;
commands.merge(std::set<std::string>{"ssh","edit"}); // handled by service_runner, but not in template_shell_commands.
for (const auto& command : commands) { for (const auto& command : commands) {
if (cmd == command) { if (cmd == command) {
std::string server_name; std::string server_name;
@ -260,6 +274,12 @@ int main(int argc, char* argv[]) {
// Unknown command // Unknown command
std::cerr << "Error: Unknown command '" << cmd << "'" << std::endl; std::cerr << "Error: Unknown command '" << cmd << "'" << std::endl;
std::cerr << "Valid commands: ";
for (const auto& command : commands) {
std::cerr << command << " ";
}
std::cerr << std::endl;
// print help
dropshell::print_help(); dropshell::print_help();
return 1; return 1;

View File

@ -157,8 +157,8 @@ void create_server(const std::string &server_name)
} }
// 2. create a new directory in the user config directory // 2. create a new directory in the user config directory
std::string config_dir = get_local_config_path(0); std::string config_servers_dir = get_local_config_servers_path(0);
std::string server_dir = config_dir + "/" + server_name; std::string server_dir = config_servers_dir + "/" + server_name;
fs::create_directory(server_dir); fs::create_directory(server_dir);
// 3. create a template server.env file in the server directory // 3. create a template server.env file in the server directory
@ -169,21 +169,21 @@ void create_server(const std::string &server_name)
server_env_file << "SSH_USER=" << user << std::endl; server_env_file << "SSH_USER=" << user << std::endl;
server_env_file << "SSH_PORT=" << 22 << std::endl; server_env_file << "SSH_PORT=" << 22 << std::endl;
server_env_file << std::endl; server_env_file << std::endl;
server_env_file << "DROPSHELL_PATH=/home/"+user+"/.dropshell" << std::endl; server_env_file << "DROPSHELL_DIR=/home/"+user+"/.dropshell" << std::endl;
server_env_file.close(); server_env_file.close();
// 4. add dropshell-agent service to server // 4. add dropshell-agent service to server
std::string service_dir = server_dir + "/dropshell-agent"; std::string service_dir = server_dir + "/dropshell-agent";
fs::create_directory(service_dir); fs::create_directory(service_dir);
std::string service_env_path = service_dir + "/service.env"; std::string service_env_path = service_dir + "/service.env";
std::filesystem::copy(get_local_system_templates_path() + "/dropshell-agent/service.env", service_env_path); std::filesystem::copy(get_local_system_templates_path() + "/dropshell-agent/example/service.env", service_env_path);
std::cout << "Server created successfully: " << server_name << std::endl; std::cout << "Server created successfully: " << server_name << std::endl;
std::cout << "Please edit the server.env file to configure the server, it is located at: "<<std::endl; std::cout << "Please complete the installation:" <<std::endl;
std::cout << " " << server_env_path << std::endl; std::cout << "1) edit the server configuration: dropshell edit " << server_name << std::endl;
std::cout << "Then run 'dropshell install " << server_name << " dropshell-agent' to install the agent" << std::endl; std::cout << "2) test ssh is working: dropshell ssh " << server_name << std::endl;
std::cout << "3) install dropshell-agent: dropshell install " << server_name << " dropshell-agent" << std::endl;
std::cout << std::endl; std::cout << std::endl;
std::cout << "You can then start managing your server with DropShell" << std::endl;
} }
} // namespace dropshell } // namespace dropshell

View File

@ -230,6 +230,10 @@ bool service_runner::uninstall() {
return true; return true;
} }
// ------------------------------------------------------------------------------------------------
// Run a command on the service.
// ------------------------------------------------------------------------------------------------
bool service_runner::run_command(const std::string& command) { bool service_runner::run_command(const std::string& command) {
if (!m_server_env) { if (!m_server_env) {
std::cerr << "Error: Server service not initialized" << std::endl; std::cerr << "Error: Server service not initialized" << std::endl;
@ -240,6 +244,13 @@ bool service_runner::run_command(const std::string& command) {
std::cerr << "Error: Template '" << m_service_info.template_name << "' not found" << std::endl; std::cerr << "Error: Template '" << m_service_info.template_name << "' not found" << std::endl;
return false; return false;
} }
// don't need a script for edit!
if (command == "edit") {
edit_service_config();
return true;
}
if (!template_command_exists(m_service_info.template_name, command)) { if (!template_command_exists(m_service_info.template_name, command)) {
std::cout << "No command script for " << m_service_info.template_name << " : " << command << std::endl; std::cout << "No command script for " << m_service_info.template_name << " : " << command << std::endl;
return true; // nothing to run. return true; // nothing to run.
@ -280,6 +291,11 @@ bool service_runner::run_command(const std::string& command) {
return execute_ssh_command(run_cmd, "Command returned error code: " + script_path); return execute_ssh_command(run_cmd, "Command returned error code: " + script_path);
} }
// ------------------------------------------------------------------------------------------------
// Backup the service.
// ------------------------------------------------------------------------------------------------
bool service_runner::backup() { bool service_runner::backup() {
maketitle("Backing up " + m_service_info.service_name + " (" + m_service_info.template_name + ") on " + m_server_name); maketitle("Backing up " + m_service_info.service_name + " (" + m_service_info.template_name + ") on " + m_server_name);
@ -514,6 +530,33 @@ void interactive_ssh(const std::string & server_name, const std::string & comman
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
void edit_server(const std::string &server_name)
{
std::string serverpath = get_local_server_path(server_name);
if (serverpath.empty()) {
std::cerr << "Error: Server not found: " << server_name << std::endl;
return;
}
std::ostringstream aftertext;
aftertext << "If you have changed DROPSHELL_DIR, you should manually move the files to the new location NOW.\n"
<< "You can ssh in to the remote server with: dropshell ssh "<<server_name<<"\n"
<< "Once moved, reinstall all services with: dropshell install " << server_name;
std::string config_file = serverpath + "/server.env";
edit_file(config_file, aftertext.str());
}
void edit_file(const std::string &file_path, const std::string & aftertext)
{
std::string cmd = "nano -w "+file_path+" ; echo \""+aftertext+"\"";
execlp("bash","bash","-c",cmd.c_str(), nullptr);
// If exec returns, it means there was an error
perror("ssh execution failed");
exit(EXIT_FAILURE);
}
void service_runner::interactive_ssh_service() void service_runner::interactive_ssh_service()
{ {
std::set<std::string> used_commands = get_used_commands(m_server_name, m_service_info.service_name); std::set<std::string> used_commands = get_used_commands(m_server_name, m_service_info.service_name);
@ -526,6 +569,17 @@ void service_runner::interactive_ssh_service()
interactive_ssh(m_server_name, "/bin/bash -c '"+command+"'"); interactive_ssh(m_server_name, "/bin/bash -c '"+command+"'");
} }
void service_runner::edit_service_config()
{
std::string config_file = get_local_service_env_path(m_server_name, m_service_info.service_name);
if (!fs::exists(config_file)) {
std::cerr << "Error: Service config file not found: " << config_file << std::endl;
return;
}
std::string aftertext = "To apply your changes, run:\n dropshell install " + m_server_name + " " + m_service_info.service_name;
edit_file(config_file, aftertext);
}
} // namespace dropshell } // namespace dropshell

View File

@ -84,6 +84,9 @@ class service_runner {
// replaces the current dropshell process with the ssh process // replaces the current dropshell process with the ssh process
void interactive_ssh_service(); void interactive_ssh_service();
// edit the service configuration file
void edit_service_config();
private: private:
std::string m_server_name; std::string m_server_name;
ServiceInfo m_service_info; ServiceInfo m_service_info;
@ -108,7 +111,11 @@ class service_runner {
static bool execute_local_command_and_capture_output(const std::string& command, std::string & output); static bool execute_local_command_and_capture_output(const std::string& command, std::string & output);
}; };
// other utility routines (not specific to service_runner)
void interactive_ssh(const std::string & server_name, const std::string & command); void interactive_ssh(const std::string & server_name, const std::string & command);
void edit_server(const std::string & server_name);
void edit_file(const std::string & file_path, const std::string & aftertext);
} // namespace dropshell } // namespace dropshell

View File

@ -149,11 +149,11 @@ bool create_service(const std::string &server_name, const std::string &service_n
// copy the template example files to the service directory // copy the template example files to the service directory
recursive_copy(tinfo.path+"/example", service_dir); recursive_copy(tinfo.path+"/example", service_dir);
std::cout << "Service created successfully: " << service_name << std::endl; std::cout << "Service " << service_name <<" created successfully"<<std::endl;
std::cout << "Please edit the service.env file to configure the service, it is located at: "<<std::endl; std::cout << std::endl;
std::cout << " " << service_dir << "/service.env" << std::endl; std::cout << "To complete the installation, please:" << std::endl;
std::cout << "Then run 'dropshell install " << server_name << " " << service_name << "' to install the service" << std::endl; std::cout << "1. edit the service.env file: dropshell edit " << server_name << " " << service_name << std::endl;
std::cout << "2. install the remote service: dropshell install " << server_name << " " << service_name << std::endl;
return true; return true;
} }

View File

@ -19,9 +19,6 @@ namespace dropshell {
std::set<std::string> get_used_commands(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);
bool create_service(const std::string& server_name, const std::string& service_name); bool create_service(const std::string& server_name, const std::string& service_name);
void interactive_ssh(const std::string & server_name, const std::string & service_name, const std::string & command);
} // namespace dropshell } // namespace dropshell