// Copyright Epic Games, Inc. All Rights Reserved. #include "admin_cmd.h" #include #include #include #include ZEN_THIRD_PARTY_INCLUDES_START #include ZEN_THIRD_PARTY_INCLUDES_END using namespace std::literals; namespace zen { ScrubCommand::ScrubCommand() { m_Options.add_options()("h,help", "Print help"); m_Options.add_option("", "u", "hosturl", "Host URL", cxxopts::value(m_HostName)->default_value(""), ""); } ScrubCommand::~ScrubCommand() = default; int ScrubCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_UNUSED(GlobalOptions); if (!ParseOptions(argc, argv)) { return 0; } m_HostName = ResolveTargetHostSpec(m_HostName); if (m_HostName.empty()) { throw OptionParseException("unable to resolve server specification"); } zen::HttpClient Http(m_HostName); if (zen::HttpClient::Response Response = Http.Post("/admin/scrub"sv)) { ZEN_CONSOLE("OK: {}", Response.ToText()); return 0; } else if (int StatusCode = (int)Response.StatusCode) { ZEN_ERROR("scrub start failed: {}: {} ({})", (int)Response.StatusCode, ReasonStringForHttpResultCode((int)Response.StatusCode), Response.AsText()); } else { ZEN_ERROR("scrub start failed: {}", Response.AsText()); } return 1; } ////////////////////////////////////////////////////////////////////////// GcCommand::GcCommand() { m_Options.add_options()("h,help", "Print help"); m_Options.add_option("", "u", "hosturl", "Host URL", cxxopts::value(m_HostName)->default_value(""), ""); m_Options.add_option("", "s", "smallobjects", "Collect small objects", cxxopts::value(m_SmallObjects)->default_value("false"), ""); m_Options.add_option("", "m", "maxcacheduration", "Max cache lifetime (in seconds)", cxxopts::value(m_MaxCacheDuration)->default_value("0"), ""); m_Options.add_option("", "d", "disksizesoftlimit", "Max disk usage size (in bytes)", cxxopts::value(m_DiskSizeSoftLimit)->default_value("0"), ""); } GcCommand::~GcCommand() { } int GcCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_UNUSED(GlobalOptions); if (!ParseOptions(argc, argv)) { return 0; } m_HostName = ResolveTargetHostSpec(m_HostName); if (m_HostName.empty()) { throw OptionParseException("unable to resolve server specification"); } cpr::Parameters Params; if (m_SmallObjects) { Params.Add({"smallobjects", "true"}); } if (m_MaxCacheDuration != 0) { Params.Add({"maxcacheduration", fmt::format("{}", m_MaxCacheDuration)}); } if (m_DiskSizeSoftLimit != 0) { Params.Add({"disksizesoftlimit", fmt::format("{}", m_DiskSizeSoftLimit)}); } cpr::Session Session; Session.SetHeader(cpr::Header{{"Accept", "application/json"}}); Session.SetUrl({fmt::format("{}/admin/gc", m_HostName)}); Session.SetParameters(Params); cpr::Response Result = Session.Post(); if (zen::IsHttpSuccessCode(Result.status_code)) { ZEN_CONSOLE("OK: {}", Result.text); return 0; } if (Result.status_code) { ZEN_ERROR("GC start failed: {}: {} ({})", Result.status_code, Result.reason, Result.text); } else { ZEN_ERROR("GC start failed: {}", Result.error.message); } return 1; } GcStatusCommand::GcStatusCommand() { m_Options.add_options()("h,help", "Print help"); m_Options.add_option("", "u", "hosturl", "Host URL", cxxopts::value(m_HostName)->default_value(""), ""); } GcStatusCommand::~GcStatusCommand() { } int GcStatusCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_UNUSED(GlobalOptions); if (!ParseOptions(argc, argv)) { return 0; } m_HostName = ResolveTargetHostSpec(m_HostName); if (m_HostName.empty()) { throw OptionParseException("unable to resolve server specification"); } cpr::Session Session; Session.SetHeader(cpr::Header{{"Accept", "application/json"}}); Session.SetUrl({fmt::format("{}/admin/gc", m_HostName)}); cpr::Response Result = Session.Get(); if (zen::IsHttpSuccessCode(Result.status_code)) { ZEN_CONSOLE("OK: {}", Result.text); return 0; } if (Result.status_code) { ZEN_ERROR("GC status failed: {}: {} ({})", Result.status_code, Result.reason, Result.text); } else { ZEN_ERROR("GC status failed: {}", Result.error.message); } return 1; } //////////////////////////////////////////// JobCommand::JobCommand() { m_Options.add_options()("h,help", "Print help"); m_Options.add_option("", "u", "hosturl", "Host URL", cxxopts::value(m_HostName)->default_value(""), ""); m_Options.add_option("", "j", "jobid", "Job id", cxxopts::value(m_JobId), ""); m_Options.add_option("", "c", "cancel", "Cancel job id", cxxopts::value(m_Cancel), ""); } JobCommand::~JobCommand() = default; int JobCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_UNUSED(GlobalOptions); using namespace std::literals; if (!ParseOptions(argc, argv)) { return 0; } m_HostName = ResolveTargetHostSpec(m_HostName); if (m_HostName.empty()) { throw OptionParseException("unable to resolve server specification"); } HttpClient Http(m_HostName); if (m_Cancel) { if (m_JobId == 0) { ZEN_ERROR("Job id must be given"); return 1; } } std::string Url = m_JobId != 0 ? fmt::format("/admin/jobs/{}", m_JobId) : "/admin/jobs"; if (m_Cancel) { if (HttpClient::Response Result = Http.Delete(Url, HttpClient::Accept(ZenContentType::kJSON))) { ZEN_CONSOLE("{}", Result); } else { Result.ThrowError("failed cancelling job"sv); return 1; } } else if (HttpClient::Response Result = Http.Get(Url, HttpClient::Accept(ZenContentType::kJSON))) { ZEN_CONSOLE("{}", Result.AsText()); } else { Result.ThrowError("failed fetching job info"sv); return 1; } return 0; } //////////////////////////////////////////// LoggingCommand::LoggingCommand() { m_Options.add_options()("h,help", "Print help"); m_Options.add_option("", "u", "hosturl", "Host URL", cxxopts::value(m_HostName)->default_value(""), ""); m_Options.add_option("", "", "cache-write-log", "Enable cache write logging", cxxopts::value(m_CacheWriteLog), ""); m_Options.add_option("", "", "cache-access-log", "Enable cache access logging", cxxopts::value(m_CacheAccessLog), ""); m_Options .add_option("", "", "set-log-level", "Set zenserver log level", cxxopts::value(m_SetLogLevel), ""); } LoggingCommand::~LoggingCommand() = default; int LoggingCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_UNUSED(GlobalOptions); using namespace std::literals; if (!ParseOptions(argc, argv)) { return 0; } m_HostName = ResolveTargetHostSpec(m_HostName); if (m_HostName.empty()) { throw OptionParseException("unable to resolve server specification"); } HttpClient Http(m_HostName); HttpClient::KeyValueMap Parameters; if (!m_CacheWriteLog.empty()) { if (m_CacheWriteLog == "enable") { (*Parameters)["cacheenablewritelog"] = "true"; } else if (m_CacheWriteLog == "disable") { (*Parameters)["cacheenablewritelog"] = "false"; } else { ZEN_ERROR("Invalid value for parameter 'cache-write-log'. Use 'enable' or 'disable'"); return 1; } } if (!m_CacheAccessLog.empty()) { if (m_CacheAccessLog == "enable") { (*Parameters)["cacheenableaccesslog"] = "true"; } else if (m_CacheAccessLog == "disable") { (*Parameters)["cacheenableaccesslog"] = "false"; } else { ZEN_ERROR("Invalid value for parameter 'cache-access-log'. Use 'enable' or 'disable'"); return 1; } } if (!m_SetLogLevel.empty()) { (*Parameters)["loglevel"] = m_SetLogLevel; } if ((*Parameters).empty()) { if (HttpClient::Response Result = Http.Get("/admin/logs", HttpClient::Accept(ZenContentType::kJSON))) { ZEN_CONSOLE("{}", Result.AsText()); } else { Result.ThrowError("failed fetching log info"sv); return 1; } return 0; } if (HttpClient::Response Result = Http.Post("/admin/logs", HttpClient::KeyValueMap{}, Parameters)) { ZEN_CONSOLE("{}", Result.AsText()); } else { Result.ThrowError("failed setting log info"sv); return 1; } return 0; } } // namespace zen