Multiple directories
This commit is contained in:
parent
4d3523a346
commit
72e757ebd6
@ -30,17 +30,14 @@ bool config::load_config() {
|
||||
|
||||
envmanager config_env(config_path);
|
||||
if (!config_env.load())
|
||||
{
|
||||
std::cerr << "Warning: Unable to read configuration file: " << config_path << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
mLocalConfigPath = config_env.get_variable_substituted("local.config.directory");
|
||||
if (mLocalConfigPath.empty())
|
||||
{
|
||||
std::cerr << "Warning: User directory not set in config" << std::endl;
|
||||
std::string mDirectories = config_env.get_variable_substituted("local.config.directories");
|
||||
if (mDirectories.empty())
|
||||
return false;
|
||||
}
|
||||
|
||||
// Split the directories string into a vector of strings
|
||||
mLocalConfigPaths = string2multi(mDirectories);
|
||||
|
||||
//std::cout << "Local config path: " << mLocalConfigPath << std::endl;
|
||||
return true;
|
||||
@ -48,7 +45,7 @@ bool config::load_config() {
|
||||
|
||||
void config::save_config()
|
||||
{
|
||||
if (mLocalConfigPath.empty())
|
||||
if (mLocalConfigPaths.empty())
|
||||
{
|
||||
std::cerr << "Warning: Unable to save configuration file, as DropShell has not been initialised."<< std::endl;
|
||||
std::cerr << "Please run 'dropshell init <path>' to initialise DropShell." << std::endl;
|
||||
@ -57,36 +54,46 @@ void config::save_config()
|
||||
|
||||
std::string config_path = get_local_dropshell_config_path();
|
||||
envmanager config_env(config_path);
|
||||
config_env.set_variable("local.config.directory", mLocalConfigPath);
|
||||
|
||||
config_env.set_variable("local.config.directories", multi2string(mLocalConfigPaths));
|
||||
config_env.save();
|
||||
}
|
||||
|
||||
bool config::is_config_set() const
|
||||
{
|
||||
return !mLocalConfigPath.empty();
|
||||
return !mLocalConfigPaths.empty();
|
||||
}
|
||||
|
||||
bool config::get_local_config_directory(std::string& path) const {
|
||||
path = mLocalConfigPath;
|
||||
return !path.empty();
|
||||
|
||||
const std::vector<std::string> & config::get_local_config_directories() const
|
||||
{
|
||||
return mLocalConfigPaths;
|
||||
}
|
||||
|
||||
void config::init_local_config_directory(const std::string& path) {
|
||||
bool config::add_local_config_directory(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
throw std::runtime_error("Warning: Unable to initialise local config directory, as the path is empty.");
|
||||
return false;
|
||||
|
||||
// Convert to canonical path
|
||||
fs::path abs_path = fs::canonical(path);
|
||||
|
||||
// The directory must exist
|
||||
if (!fs::exists(abs_path)) {
|
||||
throw std::runtime_error("The local config directory does not exist: " + abs_path.string());
|
||||
std::cerr << "Error: The local config directory does not exist: " << abs_path.string() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
mLocalConfigPath = abs_path.string();
|
||||
save_config();
|
||||
std::cout << "Local config directory initialized to: " << abs_path.string() << std::endl;
|
||||
// Add to config paths if not already there
|
||||
std::string path_str = abs_path.string();
|
||||
if (std::find(mLocalConfigPaths.begin(), mLocalConfigPaths.end(), path_str) == mLocalConfigPaths.end()) {
|
||||
mLocalConfigPaths.push_back(path_str);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::cerr << "Warning: The local config directory is already registered: " << path_str << std::endl;
|
||||
std::cerr << "No changes made to the DropShell configuration." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace dropshell
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace dropshell {
|
||||
|
||||
@ -13,11 +14,11 @@ class config {
|
||||
|
||||
bool is_config_set() const;
|
||||
|
||||
bool get_local_config_directory(std::string& path) const;
|
||||
void init_local_config_directory(const std::string& path);
|
||||
const std::vector<std::string> & get_local_config_directories() const;
|
||||
bool add_local_config_directory(const std::string& path);
|
||||
|
||||
private:
|
||||
std::string mLocalConfigPath;
|
||||
std::vector<std::string> mLocalConfigPaths;
|
||||
};
|
||||
|
||||
|
||||
|
65
src/main.cpp
65
src/main.cpp
@ -11,7 +11,7 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <iomanip>
|
||||
namespace dropshell {
|
||||
|
||||
void print_version() {
|
||||
@ -30,7 +30,7 @@ void print_help() {
|
||||
std::cout << std::endl;
|
||||
std::cout << " help Show this help message" << std::endl;
|
||||
std::cout << " version Show version information" << std::endl;
|
||||
std::cout << " init DIR Initialise the local dropshell directory (local config, backups, etc)" << std::endl;
|
||||
std::cout << " init DIR Add a local dropshell config directory (you can add several)" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "Server commands:" << std::endl;
|
||||
@ -44,6 +44,11 @@ void print_help() {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Standard commands: install, backup, uninstall, start, stop" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "Creation commands: (apply to the first local config directory)"<<std::endl;
|
||||
std::cout << " create-template TEMPLATE" << std::endl;
|
||||
std::cout << " create-server SERVER" << std::endl;
|
||||
std::cout << " create-service SERVER SERVICE" << std::endl;
|
||||
}
|
||||
|
||||
} // namespace dropshell
|
||||
@ -73,27 +78,38 @@ int main(int argc, char* argv[]) {
|
||||
try {
|
||||
dropshell::config *cfg = dropshell::get_global_config();
|
||||
|
||||
// Handle commands
|
||||
std::string cmd;
|
||||
if (argc > 1) {
|
||||
cmd = argv[1];
|
||||
if (argc == 1) {
|
||||
dropshell::print_help();
|
||||
return 0;
|
||||
}
|
||||
std::string cmd = argv[1];
|
||||
|
||||
// silently attempt to load the config file.
|
||||
cfg->load_config();
|
||||
|
||||
// don't load old config if we're initializing
|
||||
if (cmd == "init") {
|
||||
std::string lcd;
|
||||
if (boost::filesystem::exists(dropshell::get_local_dropshell_config_path())) {
|
||||
std::cerr << "DropShell is already initialised in " << dropshell::get_local_dropshell_config_path() << std::endl;
|
||||
std::cerr << "Please manually delete this old config file and re-run the init command." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc < 3) {
|
||||
std::cerr << "Error: init command requires a directory argument" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
cfg->init_local_config_directory(argv[2]);
|
||||
if (!cfg->add_local_config_directory(argv[2]))
|
||||
return 1; // error already reported
|
||||
cfg->save_config();
|
||||
std::cout << "Config directory added: " << cfg->get_local_config_directories().back() << std::endl;
|
||||
if (cfg->get_local_config_directories().size() ==1)
|
||||
std::cout << "DropShell is now initialised and you can add a server with 'dropshell create-server <server-name>'" << std::endl;
|
||||
else
|
||||
{
|
||||
std::cout << "DropShell will now use all of the following directories for configuration:" << std::endl;
|
||||
for (const auto& dir : cfg->get_local_config_directories()) {
|
||||
std::cout << " " << dir << std::endl;
|
||||
}
|
||||
std::cout << "You can edit the config file manually at: " << dropshell::get_local_dropshell_config_path() << std::endl;
|
||||
}
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error in init: " << e.what() << std::endl;
|
||||
@ -111,9 +127,6 @@ int main(int argc, char* argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// silently attempt to load the config file.
|
||||
cfg->load_config();
|
||||
|
||||
// auto completion stuff.
|
||||
std::set<std::string> commands;
|
||||
std::vector<dropshell::ServerInfo> servers = dropshell::get_configured_servers();
|
||||
@ -126,13 +139,11 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
if (cmd == "autocomplete_list_commands") {
|
||||
commands.merge(std::set<std::string>{
|
||||
"help","version"
|
||||
"help","version","init"
|
||||
});
|
||||
if (!boost::filesystem::exists(dropshell::get_local_dropshell_config_path()))
|
||||
commands.insert("init");
|
||||
if (cfg->is_config_set())
|
||||
commands.merge(std::set<std::string>{
|
||||
"servers","templates"
|
||||
"servers","templates","create-service","create-template","create-server"
|
||||
});
|
||||
|
||||
for (const auto& command : commands) {
|
||||
@ -172,9 +183,11 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
std::string lcd;
|
||||
cfg->get_local_config_directory(lcd);
|
||||
std::cout << "Local config path: " << lcd << std::endl;
|
||||
|
||||
const std::vector<std::string> & local_config_directories = cfg->get_local_config_directories();
|
||||
std::cout << "Config directories: ";
|
||||
for (auto & dir : local_config_directories)
|
||||
std::cout << "["<< dir << "] " << std::endl;
|
||||
std::cout << std::endl;;
|
||||
// No arguments provided
|
||||
if (argc < 2) {
|
||||
dropshell::print_help();
|
||||
@ -197,6 +210,14 @@ int main(int argc, char* argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cmd == "create-template") {
|
||||
if (argc < 3) {
|
||||
std::cerr << "Error: create-template requires a template name" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
dropshell::create_template(argv[2]);
|
||||
return 0;
|
||||
}
|
||||
// handle running a command.
|
||||
for (const auto& command : commands) {
|
||||
if (cmd == command) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "utils/envmanager.hpp"
|
||||
#include "utils/directories.hpp"
|
||||
#include "services.hpp"
|
||||
#include "config.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
@ -18,15 +19,13 @@ namespace dropshell {
|
||||
std::vector<ServerInfo> get_configured_servers() {
|
||||
std::vector<ServerInfo> servers;
|
||||
|
||||
std::string servers_dir = get_local_config_servers_path();
|
||||
if (servers_dir.empty()) {
|
||||
std::vector<std::string> local_config_directories = get_global_config()->get_local_config_directories();
|
||||
if (local_config_directories.empty())
|
||||
return servers;
|
||||
}
|
||||
|
||||
if (!fs::exists(servers_dir)) {
|
||||
std::cerr << "Error: Servers directory not found:" << servers_dir << std::endl;
|
||||
return servers;
|
||||
}
|
||||
for (int i = 0; i < local_config_directories.size(); i++) {
|
||||
std::string servers_dir = get_local_config_servers_path(i);
|
||||
if (!servers_dir.empty() && fs::exists(servers_dir)) {
|
||||
|
||||
for (const auto& entry : fs::directory_iterator(servers_dir)) {
|
||||
if (fs::is_directory(entry)) {
|
||||
@ -34,7 +33,7 @@ std::vector<ServerInfo> get_configured_servers() {
|
||||
|
||||
server_env env(server_name);
|
||||
if (!env.is_valid()) {
|
||||
std::cerr << "Error: Invalid server environment file: " << server_name << std::endl;
|
||||
std::cerr << "Error: Invalid server environment file: " << entry.path().string() << std::endl;
|
||||
continue;
|
||||
}
|
||||
servers.push_back({
|
||||
@ -45,12 +44,12 @@ std::vector<ServerInfo> get_configured_servers() {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return servers;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void list_servers() {
|
||||
auto servers = get_configured_servers();
|
||||
|
||||
|
@ -275,7 +275,11 @@ bool service_runner::backup() {
|
||||
}
|
||||
|
||||
// Create backups directory locally if it doesn't exist
|
||||
std::string local_backups_dir = get_local_config_backups_path();
|
||||
std::string local_backups_dir = get_local_config_backups_path(0);
|
||||
if (local_backups_dir.empty()) {
|
||||
std::cerr << "Error: Local backups directory not found - is DropShell initialised?" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (!fs::exists(local_backups_dir)) {
|
||||
fs::create_directories(local_backups_dir);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "utils/envmanager.hpp"
|
||||
#include "utils/directories.hpp"
|
||||
#include "templates.hpp"
|
||||
#include "config.hpp"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <iostream>
|
||||
|
||||
@ -15,25 +16,32 @@ std::vector<ServiceInfo> get_server_services_info(const std::string& server_name
|
||||
if (server_name.empty())
|
||||
return services;
|
||||
|
||||
std::string serverpath = get_local_config_servers_path();
|
||||
std::vector<std::string> local_config_directories = get_global_config()->get_local_config_directories();
|
||||
if (local_config_directories.empty()) {
|
||||
std::cerr << "Error: No local config directories found" << std::endl;
|
||||
std::cerr << "Run 'dropshell init' to initialise DropShell" << std::endl;
|
||||
return services;
|
||||
}
|
||||
|
||||
for (int i = 0; i < getNumConfigDirectories(); i++) {
|
||||
std::string serverpath = get_local_config_servers_path(i);
|
||||
if (serverpath.empty()) {
|
||||
std::cerr << "Error: Server directory not found: " << serverpath << std::endl;
|
||||
return services;
|
||||
}
|
||||
fs::path server_dir = fs::path(serverpath) / server_name;
|
||||
if (!fs::exists(server_dir)) {
|
||||
std::cerr << "Error: Server directory not found:" << server_dir.string() << std::endl;
|
||||
return services;
|
||||
}
|
||||
if (fs::exists(server_dir)) {
|
||||
for (const auto& entry : fs::directory_iterator(server_dir)) {
|
||||
if (fs::is_directory(entry)) {
|
||||
ServiceInfo service = get_service_info(server_name, entry.path().filename().string());
|
||||
if (!service.template_name.empty()) {
|
||||
// std::cout << "Service: " << service.service_name << " found in " << server_dir.string() << ", with template: " << service.template_name << std::endl;
|
||||
services.push_back(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end of for (int i = 0; i < getNumConfigDirectories(); i++)
|
||||
}
|
||||
|
||||
|
||||
return services;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "utils/directories.hpp"
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
@ -40,7 +41,17 @@ bool get_templates(std::vector<template_info>& templates) {
|
||||
}
|
||||
};
|
||||
|
||||
add_templates_from_dir(get_local_config_templates_path());
|
||||
// add templates from the local config directories
|
||||
for (int i = 0; i < getNumConfigDirectories(); i++) {
|
||||
std::string path = get_local_config_templates_path(i);
|
||||
if (path.empty()) {
|
||||
std::cerr << "Error: Templates directory not found: " << path << std::endl;
|
||||
return false;
|
||||
}
|
||||
add_templates_from_dir(path);
|
||||
}
|
||||
|
||||
// add templates from the system templates directory
|
||||
add_templates_from_dir(get_local_system_templates_path());
|
||||
|
||||
return true;
|
||||
@ -96,4 +107,77 @@ void list_templates() {
|
||||
}
|
||||
}
|
||||
|
||||
void create_template(const std::string& template_name) {
|
||||
// 1. Create a new directory in the user templates directory
|
||||
std::vector<std::string> local_config_directories = get_global_config()->get_local_config_directories();
|
||||
|
||||
if (local_config_directories.empty()) {
|
||||
std::cerr << "Error: No local config directories found" << std::endl;
|
||||
std::cerr << "Run 'dropshell init' to initialise DropShell" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
template_info info;
|
||||
if (get_template_info(template_name, info)) {
|
||||
std::cerr << "Error: Template '" << template_name << "' already exists at " << info.path << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string user_templates_dir = local_config_directories[0] + "/templates";
|
||||
std::string new_template_path = user_templates_dir + "/" + template_name;
|
||||
|
||||
// Create the new template directory
|
||||
std::filesystem::create_directories(new_template_path);
|
||||
|
||||
// 2. Copy the example template from the system templates directory
|
||||
std::string system_templates_dir = get_local_system_templates_path();
|
||||
std::string example_template_path = system_templates_dir + "/example";
|
||||
|
||||
if (!std::filesystem::exists(example_template_path)) {
|
||||
std::cerr << "Error: Example template not found at " << example_template_path << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy all files from example template to new template
|
||||
for (const auto& entry : std::filesystem::recursive_directory_iterator(example_template_path)) {
|
||||
std::string relative_path = entry.path().string().substr(example_template_path.length());
|
||||
std::string target_path = new_template_path + relative_path;
|
||||
|
||||
if (entry.is_directory()) {
|
||||
std::filesystem::create_directory(target_path);
|
||||
} else {
|
||||
std::filesystem::copy_file(entry.path(), target_path);
|
||||
}
|
||||
}
|
||||
|
||||
// modify the TEMPLATE=example line in the service.env file to TEMPLATE=<template_name>
|
||||
std::string search_string = "TEMPLATE=";
|
||||
std::string replacement_line = "TEMPLATE=" + template_name;
|
||||
// replace the line in the example/service.env file with the replacement line
|
||||
std::string service_env_path = new_template_path + "/example/service.env";
|
||||
|
||||
|
||||
// 3. Print out the README.txt file and the path
|
||||
std::string readme_path = new_template_path + "/README.txt";
|
||||
if (std::filesystem::exists(readme_path)) {
|
||||
std::cout << "\nREADME contents:" << std::endl;
|
||||
std::cout << std::string(60, '-') << std::endl;
|
||||
|
||||
std::ifstream readme_file(readme_path);
|
||||
if (readme_file.is_open()) {
|
||||
std::string line;
|
||||
while (std::getline(readme_file, line)) {
|
||||
std::cout << line << std::endl;
|
||||
}
|
||||
readme_file.close();
|
||||
}
|
||||
std::cout << std::string(60, '-') << std::endl;
|
||||
} else {
|
||||
std::cout << "No README.txt file found in the template." << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << "Template '" << template_name << "' created at " << new_template_path << std::endl;
|
||||
}
|
||||
|
||||
} // namespace dropshell
|
@ -24,4 +24,11 @@ bool get_template_info(const std::string& name, template_info& info);
|
||||
bool template_command_exists(const std::string& template_name,const std::string& command);
|
||||
void list_templates();
|
||||
|
||||
|
||||
// create a template
|
||||
// 1. create a new directory in the user templates directory
|
||||
// 2. copy the example template from the system templates directory into the new directory
|
||||
// 3. print out the README.txt file in the new template directory, and the path to the new template
|
||||
void create_template(const std::string& template_name);
|
||||
|
||||
} // namespace dropshell
|
||||
|
@ -28,35 +28,41 @@ std::string get_local_system_templates_path()
|
||||
return "/opt/dropshell/templates";
|
||||
}
|
||||
|
||||
std::string get_local_config_path()
|
||||
int getNumConfigDirectories()
|
||||
{
|
||||
config *cfg = get_global_config();
|
||||
std::string user_dir;
|
||||
if (!cfg->get_local_config_directory(user_dir)) {
|
||||
return std::string();
|
||||
}
|
||||
return user_dir;
|
||||
std::vector<std::string> local_config_directories = cfg->get_local_config_directories();
|
||||
return local_config_directories.size();
|
||||
}
|
||||
|
||||
std::string get_local_config_templates_path()
|
||||
std::string get_local_config_path(int index)
|
||||
{
|
||||
std::string config_path = get_local_config_path();
|
||||
config *cfg = get_global_config();
|
||||
std::vector<std::string> local_config_directories = cfg->get_local_config_directories();
|
||||
if (index < 0 || index >= local_config_directories.size())
|
||||
return std::string();
|
||||
return local_config_directories[index];
|
||||
}
|
||||
|
||||
std::string get_local_config_templates_path(int index)
|
||||
{
|
||||
std::string config_path = get_local_config_path(index);
|
||||
if (config_path.empty())
|
||||
return std::string();
|
||||
return config_path + "/templates";
|
||||
}
|
||||
|
||||
std::string get_local_config_servers_path()
|
||||
std::string get_local_config_servers_path(int index)
|
||||
{
|
||||
std::string config_path = get_local_config_path();
|
||||
std::string config_path = get_local_config_path(index);
|
||||
if (config_path.empty())
|
||||
return std::string();
|
||||
return config_path + "/servers";
|
||||
}
|
||||
|
||||
std::string get_local_config_backups_path()
|
||||
std::string get_local_config_backups_path(int index)
|
||||
{
|
||||
std::string config_path = get_local_config_path();
|
||||
std::string config_path = get_local_config_path(index);
|
||||
if (config_path.empty())
|
||||
return std::string();
|
||||
return config_path + "/backups";
|
||||
@ -64,12 +70,15 @@ std::string get_local_config_backups_path()
|
||||
|
||||
std::string get_local_server_path(const std::string &server_name)
|
||||
{
|
||||
if (server_name.empty())
|
||||
config *cfg = get_global_config();
|
||||
std::vector<std::string> local_config_directories = cfg->get_local_config_directories();
|
||||
for (auto &dir : local_config_directories) {
|
||||
std::string server_path = dir + "/servers/" + server_name;
|
||||
if (fs::exists(server_path)) {
|
||||
return server_path;
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
std::string config_path = get_local_config_path();
|
||||
if (config_path.empty())
|
||||
return std::string();
|
||||
return config_path + "/servers/" + server_name;
|
||||
}
|
||||
|
||||
std::string get_local_server_env_path(const std::string &server_name)
|
||||
|
@ -8,10 +8,12 @@ namespace dropshell {
|
||||
// local paths - return empty string on failure
|
||||
std::string get_local_dropshell_config_path();
|
||||
std::string get_local_system_templates_path();
|
||||
std::string get_local_config_path();
|
||||
std::string get_local_config_templates_path();
|
||||
std::string get_local_config_servers_path();
|
||||
std::string get_local_config_backups_path();
|
||||
|
||||
int getNumConfigDirectories();
|
||||
std::string get_local_config_path(int index);
|
||||
std::string get_local_config_templates_path(int index);
|
||||
std::string get_local_config_servers_path(int index);
|
||||
std::string get_local_config_backups_path(int index);
|
||||
|
||||
std::string get_local_server_path(const std::string &server_name);
|
||||
std::string get_local_server_env_path(const std::string &server_name);
|
||||
|
@ -97,7 +97,7 @@ void envmanager::clear_variables() {
|
||||
m_variables.clear();
|
||||
}
|
||||
|
||||
std::string envmanager::trim(std::string str) const {
|
||||
std::string trim(std::string str) {
|
||||
// Trim leading whitespace
|
||||
str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
@ -132,4 +132,62 @@ std::string envmanager::expand_patterns(std::string str) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string multi2string(std::vector<std::string> values)
|
||||
{
|
||||
std::string result;
|
||||
for (const auto& value : values) {
|
||||
// remove any " contained in the string value, if present
|
||||
std::string quoteless_value = value;
|
||||
quoteless_value.erase(std::remove(quoteless_value.begin(), quoteless_value.end(), '"'), quoteless_value.end());
|
||||
result += "\"" + trim(quoteless_value) + "\",";
|
||||
}
|
||||
if (!result.empty())
|
||||
result.pop_back(); // Remove the last comma
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> string2multi(std::string values)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
// Return values separated by commas, but ignore commas within quotes
|
||||
bool inside_quotes = false;
|
||||
std::string current_item;
|
||||
|
||||
for (char c : values) {
|
||||
if (c == '"') {
|
||||
inside_quotes = !inside_quotes;
|
||||
} else if (c == ',' && !inside_quotes) {
|
||||
if (!current_item.empty()) {
|
||||
// Remove quotes if present
|
||||
if (current_item.front() == '"' && current_item.back() == '"') {
|
||||
current_item = current_item.substr(1, current_item.length() - 2);
|
||||
}
|
||||
std::string final = trim(current_item);
|
||||
if (!final.empty()) {
|
||||
result.push_back(final);
|
||||
}
|
||||
current_item.clear();
|
||||
}
|
||||
} else {
|
||||
current_item += c;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the last item if not empty
|
||||
if (!current_item.empty()) {
|
||||
// Remove quotes if present
|
||||
if (current_item.front() == '"' && current_item.back() == '"') {
|
||||
current_item = current_item.substr(1, current_item.length() - 2);
|
||||
}
|
||||
std::string final = trim(current_item);
|
||||
if (!final.empty()) {
|
||||
result.push_back(final);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace dropshell
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
namespace dropshell {
|
||||
|
||||
// envmanager is a class that manages the environment files for the application.
|
||||
@ -36,7 +37,6 @@ class envmanager {
|
||||
void clear_variables();
|
||||
|
||||
private:
|
||||
std::string trim(std::string str) const;
|
||||
std::string expand_patterns(std::string str) const;
|
||||
|
||||
private:
|
||||
@ -44,6 +44,11 @@ class envmanager {
|
||||
std::map<std::string, std::string> m_variables;
|
||||
};
|
||||
|
||||
// utility functions
|
||||
std::string trim(std::string str);
|
||||
std::string multi2string(std::vector<std::string> values);
|
||||
std::vector<std::string> string2multi(std::string values);
|
||||
|
||||
} // namespace dropshell
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,22 @@
|
||||
DropShell Template Example
|
||||
|
||||
Shell scripts defined in this folder are run as DropShell commands on the remote server (not locally!).
|
||||
All scripts are passed the server-specific service environment (SSSE) file as an argument.
|
||||
|
||||
The default SSSE file used when a new service is created is in example/service.env. This must exist,
|
||||
and must at minimum contain the TEMPLATE=<template_name> variable.
|
||||
|
||||
The backups script gets a second argument, which is the backup file to create (a single tgz file).
|
||||
|
||||
Mandatory scripts are:
|
||||
- install.sh
|
||||
- uninstall.sh
|
||||
- start.sh
|
||||
- stop.sh
|
||||
|
||||
Optional standard scripts are:
|
||||
- backup.sh
|
||||
- status.sh
|
||||
- ports.sh
|
||||
- logs.sh
|
||||
|
@ -63,6 +63,10 @@ grey_end() {
|
||||
}
|
||||
|
||||
create_and_start_container() {
|
||||
if [ -z "$1" ] || [ -z "$2" ]; then
|
||||
die "Template error: create_and_start_container <run_cmd> <container_name>"
|
||||
fi
|
||||
|
||||
local run_cmd="$1"
|
||||
local container_name="$2"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user