dropshell release 2025.0518.1558
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled
This commit is contained in:
parent
e45afe460b
commit
263edd9b50
137
source/src/commands/restoredata.cpp
Normal file
137
source/src/commands/restoredata.cpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include "utils/output.hpp"
|
||||||
|
#include "utils/assert.hpp"
|
||||||
|
#include "utils/utils.hpp"
|
||||||
|
#include "command_registry.hpp"
|
||||||
|
#include "config.hpp"
|
||||||
|
#include "services.hpp"
|
||||||
|
#include "servers.hpp"
|
||||||
|
#include "server_env_manager.hpp"
|
||||||
|
#include "templates.hpp"
|
||||||
|
#include "utils/directories.hpp"
|
||||||
|
#include "shared_commands.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
|
int restoredata_handler(const CommandContext& ctx);
|
||||||
|
|
||||||
|
void restoredata_autocomplete(const CommandContext& ctx);
|
||||||
|
|
||||||
|
|
||||||
|
static std::vector<std::string> restoredata_name_list={"restoredata","rd","restore","rest"};
|
||||||
|
|
||||||
|
// Static registration
|
||||||
|
struct RestoreDataCommandRegister {
|
||||||
|
RestoreDataCommandRegister() {
|
||||||
|
CommandRegistry::instance().register_command({
|
||||||
|
restoredata_name_list,
|
||||||
|
restoredata_handler,
|
||||||
|
restoredata_autocomplete,
|
||||||
|
false, // hidden
|
||||||
|
true, // requires_config
|
||||||
|
true, // requires_install
|
||||||
|
3, // min_args (after command)
|
||||||
|
3, // max_args (after command)
|
||||||
|
"restoredata SERVER SERVICE BACKUP_FILE",
|
||||||
|
"Restore data for a service on a server, overwriting the existing data.",
|
||||||
|
// heredoc
|
||||||
|
R"(
|
||||||
|
restoredata SERVER SERVICE BACKUP_FILE Restore data to a service on a server. Destructive.
|
||||||
|
|
||||||
|
Note: This command will not create any service configuration, you need
|
||||||
|
to have a valid service installed first.
|
||||||
|
The backup file must be in the local backups directory.
|
||||||
|
|
||||||
|
WARNING: This will permanently overwrite the service's data on the remote server!
|
||||||
|
)"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} restoredata_command_register;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int restoredata_handler(const CommandContext& ctx)
|
||||||
|
{
|
||||||
|
ASSERT(ctx.args.size() == 2, "Invalid number of arguments");
|
||||||
|
std::string server = ctx.args[0];
|
||||||
|
std::string service = ctx.args[1];
|
||||||
|
std::string backup_file = ctx.args[2];
|
||||||
|
|
||||||
|
server_env_manager server_env(server);
|
||||||
|
if (!server_env.is_valid()) {
|
||||||
|
error << "Server " << server << " is not valid" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_commands::cBackupFileName backup_details(backup_file);
|
||||||
|
if (!backup_details.is_valid()) {
|
||||||
|
error << "Invalid backup file: " << backup_file << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void restoredata_autocomplete(const CommandContext& ctx)
|
||||||
|
{
|
||||||
|
shared_commands::std_autocomplete(ctx);
|
||||||
|
if (ctx.args.size() == 2) // next arg is the backup file
|
||||||
|
{
|
||||||
|
std::string server = ctx.args[0];
|
||||||
|
std::string service = ctx.args[1];
|
||||||
|
|
||||||
|
std::vector<shared_commands::cBackupFileName> backups;
|
||||||
|
|
||||||
|
LocalServiceInfo service_info = get_service_info(server, service);
|
||||||
|
if (!SIvalid(service_info)) {
|
||||||
|
error << "Service " << service << " is not valid" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string template_name = service_info.template_name;
|
||||||
|
|
||||||
|
std::string local_backups_dir = gConfig().get_local_backup_path();
|
||||||
|
if (local_backups_dir.empty() || !std::filesystem::exists(local_backups_dir)) {
|
||||||
|
error << "Error: Local backups directory not found: " << local_backups_dir << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto& entry : std::filesystem::directory_iterator(local_backups_dir)) {
|
||||||
|
if (!entry.is_regular_file()) continue;
|
||||||
|
std::string filename = entry.path().filename().string();
|
||||||
|
shared_commands::cBackupFileName backup_details(filename);
|
||||||
|
if (backup_details.is_valid()) {
|
||||||
|
if (backup_details.get_template_name() == template_name) {
|
||||||
|
backups.push_back(backup_details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort backups by datetime
|
||||||
|
std::sort(backups.begin(), backups.end(), [](const shared_commands::cBackupFileName& a, const shared_commands::cBackupFileName& b) {
|
||||||
|
return a.get_datetime() > b.get_datetime();
|
||||||
|
});
|
||||||
|
|
||||||
|
// print most recent backup for each {host,service} pair
|
||||||
|
std::map<std::string, std::string> unique_backups;
|
||||||
|
for (const auto& backup : backups) {
|
||||||
|
std::string key = backup.get_server() + "-" + backup.get_service();
|
||||||
|
if (unique_backups.find(key) == unique_backups.end()) {
|
||||||
|
unique_backups[key] = backup.get_filename();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto& [key, value] : unique_backups) {
|
||||||
|
rawout << value << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace dropshell
|
Loading…
x
Reference in New Issue
Block a user