kappa add nginx --features "ssl=on,gzip=off" --config "port=8080" adds/updates feature flags and config values in the system config. Comma-separated key=value pairs. Idempotent — only prints 'updated' when something actually changed.
This commit is contained in:
+74
-5
@@ -54,6 +54,8 @@ Subcommands:
|
||||
rollback Show available generations
|
||||
index <dir> Build an index.kap from .kap files in a directory
|
||||
add <pkg> [v] Add a package to system config (optional version)
|
||||
--features "key=on,key2=off" Set feature flags
|
||||
--config "key=val,key2=val2" Set config values
|
||||
remove <pkg> Remove a package from system config
|
||||
|
||||
Options:
|
||||
@@ -232,6 +234,8 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
const char* file_arg = nullptr;
|
||||
const char* version_arg = nullptr;
|
||||
const char* features_arg = nullptr;
|
||||
const char* config_arg = nullptr;
|
||||
bool dry_run = false;
|
||||
for (int i = arg_start + 1; i < argc; ++i) {
|
||||
if (std::string_view(argv[i]) == "-h"
|
||||
@@ -254,6 +258,14 @@ int main(int argc, char* argv[]) {
|
||||
paths::set_root(argv[++i]);
|
||||
continue;
|
||||
}
|
||||
if (std::string_view(argv[i]) == "--features" && i + 1 < argc) {
|
||||
features_arg = argv[++i];
|
||||
continue;
|
||||
}
|
||||
if (std::string_view(argv[i]) == "--config" && i + 1 < argc) {
|
||||
config_arg = argv[++i];
|
||||
continue;
|
||||
}
|
||||
if (std::string_view(argv[i]) == "--dry-run") {
|
||||
dry_run = true;
|
||||
continue;
|
||||
@@ -334,6 +346,52 @@ int main(int argc, char* argv[]) {
|
||||
std::cerr << "error: no package name specified\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Parse --features key=on,key2=off
|
||||
std::unordered_map<std::string, dsl::FeatureDef> features;
|
||||
if (features_arg != nullptr) {
|
||||
std::string_view fsv(features_arg);
|
||||
std::size_t pos = 0;
|
||||
while (pos < fsv.size()) {
|
||||
auto comma = fsv.find(',', pos);
|
||||
auto pair = fsv.substr(pos, comma == std::string_view::npos
|
||||
? std::string_view::npos
|
||||
: comma - pos);
|
||||
auto eq = pair.find('=');
|
||||
if (eq != std::string_view::npos) {
|
||||
auto key = std::string(pair.substr(0, eq));
|
||||
auto val = pair.substr(eq + 1);
|
||||
while (!key.empty() && key.back() == ' ') key.pop_back();
|
||||
while (!val.empty() && val.front() == ' ') val.remove_prefix(1);
|
||||
features[key] = {val == "on" || val == "true" || val == "1",
|
||||
false, ""};
|
||||
}
|
||||
pos = comma == std::string_view::npos ? fsv.size() : comma + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse --config key=val,key2=val2
|
||||
std::unordered_map<std::string, std::string> config;
|
||||
if (config_arg != nullptr) {
|
||||
std::string_view csv(config_arg);
|
||||
std::size_t pos = 0;
|
||||
while (pos < csv.size()) {
|
||||
auto comma = csv.find(',', pos);
|
||||
auto pair = csv.substr(pos, comma == std::string_view::npos
|
||||
? std::string_view::npos
|
||||
: comma - pos);
|
||||
auto eq = pair.find('=');
|
||||
if (eq != std::string_view::npos) {
|
||||
auto key = std::string(pair.substr(0, eq));
|
||||
auto val = std::string(pair.substr(eq + 1));
|
||||
while (!key.empty() && key.back() == ' ') key.pop_back();
|
||||
while (!val.empty() && val.front() == ' ') val.erase(0, 1);
|
||||
config[key] = val;
|
||||
}
|
||||
pos = comma == std::string_view::npos ? csv.size() : comma + 1;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
auto config_path = std::filesystem::path(paths::system_dir()) / "config.kap";
|
||||
dsl::SystemConfig cfg;
|
||||
@@ -347,10 +405,21 @@ int main(int argc, char* argv[]) {
|
||||
for (auto& p : cfg.packages) {
|
||||
if (p.name == file_arg) {
|
||||
found = true;
|
||||
bool changed = false;
|
||||
if (version_arg != nullptr) {
|
||||
p.version = version_arg;
|
||||
std::cout << "updated " << file_arg
|
||||
<< " → version " << version_arg << "\n";
|
||||
changed = true;
|
||||
}
|
||||
if (!features.empty()) {
|
||||
for (auto& [k, v] : features) { p.features[k] = v; changed = true; }
|
||||
}
|
||||
if (!config.empty()) {
|
||||
for (auto& [k, v] : config) { p.config[k] = v; changed = true; }
|
||||
}
|
||||
if (changed) {
|
||||
std::cout << "updated " << file_arg;
|
||||
if (version_arg != nullptr) std::cout << " → " << version_arg;
|
||||
std::cout << "\n";
|
||||
} else {
|
||||
std::cout << file_arg << " already in packages\n";
|
||||
}
|
||||
@@ -364,11 +433,11 @@ int main(int argc, char* argv[]) {
|
||||
if (version_arg != nullptr) {
|
||||
pref.version = version_arg;
|
||||
}
|
||||
pref.features = std::move(features);
|
||||
pref.config = std::move(config);
|
||||
cfg.packages.push_back(std::move(pref));
|
||||
std::cout << "added " << file_arg;
|
||||
if (version_arg != nullptr) {
|
||||
std::cout << " " << version_arg;
|
||||
}
|
||||
if (version_arg != nullptr) std::cout << " " << version_arg;
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user