Files
dropshell/source/src/utils/env_validator.cpp
j 729a20707a
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 50s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m18s
feat: Update 3 files
2025-10-12 11:51:32 +13:00

161 lines
5.2 KiB
C++

#include "env_validator.hpp"
#include "envmanager.hpp"
#include "ordered_env.hpp"
#include "utils.hpp"
#include "output.hpp"
#include <fstream>
#include <sstream>
#include <set>
#include <algorithm>
#include <filesystem>
namespace dropshell {
bool validate_and_fix_service_env(
const std::string& template_service_env_path,
const std::string& service_env_path,
std::vector<std::string>& missing_vars,
std::vector<std::string>& extra_vars,
const std::string& template_info_env_path
) {
missing_vars.clear();
extra_vars.clear();
// Load template service.env
envmanager template_env(template_service_env_path);
if (!template_env.load()) {
error << "Failed to load template service.env from: " << template_service_env_path << std::endl;
return false;
}
ordered_env_vars template_vars;
template_env.get_all_variables(template_vars);
// Create a set of template variable names for quick lookup
std::set<std::string> template_var_names;
for (const auto& [key, value] : template_vars) {
template_var_names.insert(key);
}
// Also load template_info.env if provided - these variables are allowed in service.env
std::set<std::string> template_info_var_names;
if (!template_info_env_path.empty() && std::filesystem::exists(template_info_env_path)) {
envmanager template_info_env(template_info_env_path);
if (template_info_env.load()) {
ordered_env_vars template_info_vars;
template_info_env.get_all_variables(template_info_vars);
for (const auto& [key, value] : template_info_vars) {
template_info_var_names.insert(key);
}
}
}
// Load service service.env
envmanager service_env(service_env_path);
if (!service_env.load()) {
error << "Failed to load service service.env from: " << service_env_path << std::endl;
return false;
}
ordered_env_vars service_vars;
service_env.get_all_variables(service_vars);
// Create a set of service variable names for quick lookup
std::set<std::string> service_var_names;
for (const auto& [key, value] : service_vars) {
service_var_names.insert(key);
}
// Find missing variables (in template but not in service)
for (const auto& template_var_name : template_var_names) {
if (service_var_names.find(template_var_name) == service_var_names.end()) {
missing_vars.push_back(template_var_name);
}
}
// Find extra variables (in service but not in template or template_info)
for (const auto& service_var_name : service_var_names) {
if (template_var_names.find(service_var_name) == template_var_names.end() &&
template_info_var_names.find(service_var_name) == template_info_var_names.end()) {
extra_vars.push_back(service_var_name);
}
}
// If there are no differences, validation passes
if (missing_vars.empty() && extra_vars.empty()) {
return true;
}
// There are differences - need to fix the service.env file
debug << "Fixing service.env file: " << service_env_path << std::endl;
// Read the original file line by line
std::ifstream infile(service_env_path);
if (!infile.is_open()) {
error << "Failed to open service.env for reading: " << service_env_path << std::endl;
return false;
}
std::vector<std::string> lines;
std::string line;
while (std::getline(infile, line)) {
lines.push_back(line);
}
infile.close();
// Process lines and comment out extra variables
std::set<std::string> extra_vars_set(extra_vars.begin(), extra_vars.end());
for (auto& line : lines) {
std::string trimmed = trim(line);
// Skip empty lines and comments
if (trimmed.empty() || trimmed[0] == '#') {
continue;
}
// Check if this line defines a variable
size_t pos = trimmed.find('=');
if (pos != std::string::npos) {
std::string key = trim(trimmed.substr(0, pos));
key = dequote(key);
// If this is an extra variable, comment it out
if (extra_vars_set.find(key) != extra_vars_set.end()) {
// Only comment out if not already commented
if (line[0] != '#') {
line = "# " + line;
}
}
}
}
// Add missing variables at the end
if (!missing_vars.empty()) {
lines.push_back("");
lines.push_back("# Variables added from template update:");
for (const auto& var_name : missing_vars) {
// Get the value from the template
std::string value = get_var(template_vars, var_name);
lines.push_back(var_name + "=" + quote(value));
}
}
// Write the modified file back
std::ofstream outfile(service_env_path);
if (!outfile.is_open()) {
error << "Failed to open service.env for writing: " << service_env_path << std::endl;
return false;
}
for (const auto& l : lines) {
outfile << l << std::endl;
}
outfile.close();
// Validation failed because we had to make changes
return false;
}
} // namespace dropshell