This commit is contained in:
129
src/commands/install.cpp
Normal file
129
src/commands/install.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
#include "command_registry.hpp"
|
||||
#include "config.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
#include "service_runner.hpp"
|
||||
#include "utils/directories.hpp"
|
||||
#include "standard_autocomplete.hpp"
|
||||
#include "templates.hpp"
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
#include <libassert/assert.hpp>
|
||||
|
||||
namespace dropshell {
|
||||
|
||||
void install_autocomplete(const CommandContext& ctx);
|
||||
int install_handler(const CommandContext& ctx);
|
||||
|
||||
static std::vector<std::string> install_name_list={"install"};
|
||||
|
||||
// Static registration
|
||||
struct InstallCommandRegister {
|
||||
InstallCommandRegister() {
|
||||
CommandRegistry::instance().register_command({
|
||||
install_name_list,
|
||||
install_handler,
|
||||
install_autocomplete,
|
||||
false, // hidden
|
||||
false, // requires_config
|
||||
2, // min_args (after command)
|
||||
2, // max_args (after command)
|
||||
"install SERVER SERVICE",
|
||||
"Install/reinstall/update service(s). Safe/non-destructive.",
|
||||
// heredoc
|
||||
R"(
|
||||
Install a service on a server.
|
||||
install <server> <service> install the given service on the given server.
|
||||
|
||||
Note you need to create the service first with:
|
||||
dropshell create-service <server> <template> <service>
|
||||
)"
|
||||
});
|
||||
}
|
||||
} install_command_register;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// install service over ssh
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool install_service(const std::string& server, const std::string& service, bool silent) {
|
||||
maketitle("Installing " + mService + " (" + mServiceInfo.template_name + ") on " + mServer);
|
||||
|
||||
if (!mServerEnv.is_valid()) return false; // should never hit this.
|
||||
|
||||
// Check if template exists
|
||||
template_info tinfo = gTemplateManager().get_template_info(mServiceInfo.template_name);
|
||||
if (!tinfo.is_set())
|
||||
return false;
|
||||
|
||||
// Create service directory
|
||||
std::string remote_service_path = remotepath::service(mServer, mService);
|
||||
std::string mkdir_cmd = "mkdir -p " + quote(remote_service_path);
|
||||
if (!execute_ssh_command(mServerEnv.get_SSH_INFO(), sCommand(mkdir_cmd), cMode::Silent))
|
||||
{
|
||||
std::cerr << "Failed to create service directory " << remote_service_path << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if rsync is installed on remote host
|
||||
std::string check_rsync_cmd = "which rsync";
|
||||
if (!execute_ssh_command(mServerEnv.get_SSH_INFO(), sCommand(check_rsync_cmd), cMode::Silent))
|
||||
{
|
||||
std::cerr << "rsync is not installed on the remote host" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy template files
|
||||
std::cout << "Copying: [LOCAL] " << tinfo.local_template_path() << std::endl << std::string(8,' ')<<"[REMOTE] " << remotepath::service_template(mServer, mService) << "/" << std::endl;
|
||||
if (!rsync_tree_to_remote(tinfo.local_template_path().string(), remotepath::service_template(mServer, mService), silent))
|
||||
{
|
||||
std::cerr << "Failed to copy template files using rsync" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy service files
|
||||
std::cout << "Copying: [LOCAL] " << localpath::service(mServer,mService) << std::endl << std::string(8,' ')<<"[REMOTE] " << remotepath::service_config(mServer,mService) << std::endl;
|
||||
if (!rsync_tree_to_remote(localpath::service(mServer,mService), remotepath::service_config(mServer,mService), silent))
|
||||
{
|
||||
std::cerr << "Failed to copy service files using rsync" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Run install script
|
||||
{
|
||||
mServerEnv.run_remote_template_command(mService, "install", {}, silent, {});
|
||||
}
|
||||
|
||||
// print health tick
|
||||
std::cout << "Health: " << healthtick() << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// install command implementation
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int install_handler(const CommandContext& ctx) {
|
||||
if (ctx.args.size() < 2) {
|
||||
std::cerr << "Error: install requires a server and service" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string server = safearg(ctx.args,0);
|
||||
std::string service = safearg(ctx.args,1);
|
||||
|
||||
return install_service(server, service, false) ? 0 : 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// install command autocomplete
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void install_autocomplete(const CommandContext& ctx) {
|
||||
std_autocomplete(install_name_list, ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace dropshell
|
Reference in New Issue
Block a user