#include "command_registry.hpp" #include "config.hpp" #include "utils/utils.hpp" #include "utils/directories.hpp" #include "shared_commands.hpp" #include "servers.hpp" #include "services.hpp" #include "servers.hpp" #include "templates.hpp" #include "assert.hpp" namespace dropshell { int ssh_handler(const CommandContext &ctx); static std::vector ssh_name_list = {"ssh"}; // Static registration struct SSHCommandRegister { SSHCommandRegister() { CommandRegistry::instance().register_command({ssh_name_list, ssh_handler, shared_commands::std_autocomplete, false, // hidden true, // requires_config true, // requires_install 1, // min_args (after command) 2, // max_args (after command) "ssh SERVER", "SSH into a server, or into a docker container for a service.", R"( ssh SERVER SERVICE SSH into a docker container for a service. ssh SERVER SSH into a server. ssh USER@SERVER SSH into a server as a specific user. )"}); } } ssh_command_register; bool ssh_into_server(const std::string &server, std::string user) { server_config server_env(server); if (!server_env.is_valid()) { error << "Server " << server << " is not valid" << std::endl; return false; } execute_ssh_command(server_env.get_SSH_INFO(user), sCommand(remotepath(server, user).DROPSHELL_DIR(), "ls --color && bash", {}), cMode::Interactive); return true; } bool ssh_into_service(const std::string &server, const std::string &service) { server_config server_env(server); if (!server_env.is_valid()) { error << "Server " << server << " is not valid" << std::endl; return false; } LocalServiceInfo sinfo = get_service_info(server, service); if (!SIvalid(sinfo)) { error << "Service " << service << " is not valid" << std::endl; return false; } if (!gTemplateManager().has_template(sinfo.template_name)) { error << "Template " << sinfo.template_name << " is not valid" << std::endl; return false; } if (!gTemplateManager().template_command_exists(sinfo.template_name, "ssh")) { error << "Template " << sinfo.template_name << " does not have an ssh command" << std::endl; return false; } server_env.run_remote_template_command(service, "ssh", {}, false, {}); // explicitly supports interactive ssh! return true; } int ssh_handler(const CommandContext &ctx) { if (ctx.args.size() < 1) { error << "Server name is required" << std::endl; return 1; } // ssh into the server if (ctx.args.size() < 2) { std::string arg1 = safearg(ctx.args, 0); std::string server, user; // parse either user@server or server if (arg1.find("@") != std::string::npos) { user = arg1.substr(0, arg1.find("@")); server = arg1.substr(arg1.find("@") + 1); } else { server = arg1; // get the first user from the server.env file, and ssh in as that user. server_config server_env(server); if (!server_env.is_valid()) { error << "Server " << server << " is not valid" << std::endl; return 1; } ASSERT(server_env.get_users().size() > 0, "Server " + server + " has no users"); user = server_env.get_users()[0].user; } return ssh_into_server(server, user) ? 0 : 1; } else { // ssh into a service on the server. std::string server = safearg(ctx.args, 0); std::string service = safearg(ctx.args, 1); return ssh_into_service(server, service) ? 0 : 1; } } } // namespace dropshell