From aece8d61e27723e551848262b08fc9ae514b9635 Mon Sep 17 00:00:00 2001 From: Chris Boot Date: Tue, 24 Sep 2019 17:17:19 +0100 Subject: [PATCH] Introduce 'activate' parameter to config stage handling This functionality allows a stage to be uploaded and validated as normal, but not activated. This is useful to pre-flight an Icinga config package before it is applied to a monitoring cluster, for example in a CI pipeline. --- lib/remote/configpackageutility.cpp | 20 +++++++++++--------- lib/remote/configpackageutility.hpp | 4 ++-- lib/remote/configstageshandler.cpp | 10 +++++++++- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/remote/configpackageutility.cpp b/lib/remote/configpackageutility.cpp index ac877d16c..f143bfe7c 100644 --- a/lib/remote/configpackageutility.cpp +++ b/lib/remote/configpackageutility.cpp @@ -171,7 +171,7 @@ void ConfigPackageUtility::ActivateStage(const String& packageName, const String WritePackageConfig(packageName); } -void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName, bool reload) +void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName, bool activate, bool reload) { String logFile = GetPackageDir() + "/" + packageName + "/" + stageName + "/startup.log"; std::ofstream fpLog(logFile.CStr(), std::ofstream::out | std::ostream::binary | std::ostream::trunc); @@ -185,14 +185,16 @@ void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, con /* validation went fine, activate stage and reload */ if (pr.ExitStatus == 0) { - { - boost::mutex::scoped_lock lock(GetStaticPackageMutex()); + if (activate) { + { + boost::mutex::scoped_lock lock(GetStaticPackageMutex()); - ActivateStage(packageName, stageName); + ActivateStage(packageName, stageName); + } + + if (reload) + Application::RequestRestart(); } - - if (reload) - Application::RequestRestart(); } else { Log(LogCritical, "ConfigPackageUtility") << "Config validation failed for package '" @@ -200,7 +202,7 @@ void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, con } } -void ConfigPackageUtility::AsyncTryActivateStage(const String& packageName, const String& stageName, bool reload) +void ConfigPackageUtility::AsyncTryActivateStage(const String& packageName, const String& stageName, bool activate, bool reload) { VERIFY(Application::GetArgC() >= 1); @@ -226,7 +228,7 @@ void ConfigPackageUtility::AsyncTryActivateStage(const String& packageName, cons Process::Ptr process = new Process(Process::PrepareCommand(args)); process->SetTimeout(Application::GetReloadTimeout()); - process->Run(std::bind(&TryActivateStageCallback, _1, packageName, stageName, reload)); + process->Run(std::bind(&TryActivateStageCallback, _1, packageName, stageName, activate, reload)); } void ConfigPackageUtility::DeleteStage(const String& packageName, const String& stageName) diff --git a/lib/remote/configpackageutility.hpp b/lib/remote/configpackageutility.hpp index 9f105794c..5920b628a 100644 --- a/lib/remote/configpackageutility.hpp +++ b/lib/remote/configpackageutility.hpp @@ -37,7 +37,7 @@ public: static void SetActiveStage(const String& packageName, const String& stageName); static void SetActiveStageToFile(const String& packageName, const String& stageName); static void ActivateStage(const String& packageName, const String& stageName); - static void AsyncTryActivateStage(const String& packageName, const String& stageName, bool reload); + static void AsyncTryActivateStage(const String& packageName, const String& stageName, bool activate, bool reload); static std::vector > GetFiles(const String& packageName, const String& stageName); @@ -54,7 +54,7 @@ private: static void WritePackageConfig(const String& packageName); static void WriteStageConfig(const String& packageName, const String& stageName); - static void TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName, bool reload); + static void TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName, bool activate, bool reload); }; } diff --git a/lib/remote/configstageshandler.cpp b/lib/remote/configstageshandler.cpp index 2730ac37b..a34e35cbc 100644 --- a/lib/remote/configstageshandler.cpp +++ b/lib/remote/configstageshandler.cpp @@ -112,6 +112,11 @@ void ConfigStagesHandler::HandlePost( if (params->Contains("reload")) reload = HttpUtility::GetLastParameter(params, "reload"); + bool activate = true; + + if (params->Contains("activate")) + activate = HttpUtility::GetLastParameter(params, "activate"); + Dictionary::Ptr files = params->Get("files"); String stageName; @@ -120,12 +125,15 @@ void ConfigStagesHandler::HandlePost( if (!files) BOOST_THROW_EXCEPTION(std::invalid_argument("Parameter 'files' must be specified.")); + if (reload && !activate) + BOOST_THROW_EXCEPTION(std::invalid_argument("Parameter 'reload' must be false when 'activate' is false.")); + boost::mutex::scoped_lock lock(ConfigPackageUtility::GetStaticPackageMutex()); stageName = ConfigPackageUtility::CreateStage(packageName, files); /* validate the config. on success, activate stage and reload */ - ConfigPackageUtility::AsyncTryActivateStage(packageName, stageName, reload); + ConfigPackageUtility::AsyncTryActivateStage(packageName, stageName, activate, reload); } catch (const std::exception& ex) { return HttpUtility::SendJsonError(response, params, 500, "Stage creation failed.",