From: ryanohnemus Date: Sun, 3 Sep 2017 14:15:40 +0000 (-0500) Subject: API: Add optional reload parameter to config stage upload X-Git-Tag: v2.8.0~76^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1cb39994a565c59df0ebffd424e80e5f898a4181;p=icinga2 API: Add optional reload parameter to config stage upload You can now specify a boolean `reload` attribute that will allow you to skip the icinga2 reload after config validation. By default this is set to true. The response text has been updated to show if icinga2 will reload or if it was requested to be skipped. fixes #4769 --- diff --git a/doc/12-icinga2-api.md b/doc/12-icinga2-api.md index 89ec60e7e..7133ba4f6 100644 --- a/doc/12-icinga2-api.md +++ b/doc/12-icinga2-api.md @@ -1381,7 +1381,8 @@ Stages provide a way to maintain multiple configuration versions for a package. Send a `POST` request to the URL endpoint `/v1/config/stages` and add the name of an existing configuration package to the URL path (e.g. `example-cmdb`). The request body must contain the `files` attribute with the value being -a dictionary of file targets and their content. +a dictionary of file targets and their content. You can also specify an optional `reload` attribute +that will tell icinga2 to reload after stage config validation. By default this is set to `true`. The file path requires one of these two directories inside its path: @@ -1412,7 +1413,7 @@ intentional. "code": 200.0, "package": "example-cmdb", "stage": "example.localdomain-1441625839-0", - "status": "Created stage." + "status": "Created stage. Icinga2 will reload." } ] } @@ -1420,9 +1421,10 @@ intentional. The Icinga 2 API returns the `package` name this stage was created for, and also generates a unique name for the `stage` attribute you'll need for later requests. -Icinga 2 automatically restarts the daemon in order to activate the new config stage. -If the validation for the new config stage failed, the old stage and its configuration objects -will remain active. +Icinga 2 automatically restarts the daemon in order to activate the new config stage. This +can be disabled by setting `reload` to `false` in the request. +If the validation for the new config stage failed, the old stage +and its configuration objects will remain active. > **Note** > diff --git a/lib/remote/configpackageutility.cpp b/lib/remote/configpackageutility.cpp index 9c0d1bbf3..024b01a2c 100644 --- a/lib/remote/configpackageutility.cpp +++ b/lib/remote/configpackageutility.cpp @@ -176,7 +176,7 @@ void ConfigPackageUtility::ActivateStage(const String& packageName, const String WritePackageConfig(packageName); } -void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName) +void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName, bool reload) { String logFile = GetPackageDir() + "/" + packageName + "/" + stageName + "/startup.log"; std::ofstream fpLog(logFile.CStr(), std::ofstream::out | std::ostream::binary | std::ostream::trunc); @@ -191,7 +191,9 @@ void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, con /* validation went fine, activate stage and reload */ if (pr.ExitStatus == 0) { ActivateStage(packageName, stageName); - Application::RequestRestart(); + + if (reload) + Application::RequestRestart(); } else { Log(LogCritical, "ConfigPackageUtility") << "Config validation failed for package '" @@ -199,7 +201,7 @@ void ConfigPackageUtility::TryActivateStageCallback(const ProcessResult& pr, con } } -void ConfigPackageUtility::AsyncTryActivateStage(const String& packageName, const String& stageName) +void ConfigPackageUtility::AsyncTryActivateStage(const String& packageName, const String& stageName, bool reload) { VERIFY(Application::GetArgC() >= 1); @@ -213,7 +215,7 @@ void ConfigPackageUtility::AsyncTryActivateStage(const String& packageName, cons Process::Ptr process = new Process(Process::PrepareCommand(args)); process->SetTimeout(300); - process->Run(boost::bind(&TryActivateStageCallback, _1, packageName, stageName)); + process->Run(boost::bind(&TryActivateStageCallback, _1, packageName, stageName, reload)); } void ConfigPackageUtility::DeleteStage(const String& packageName, const String& stageName) diff --git a/lib/remote/configpackageutility.hpp b/lib/remote/configpackageutility.hpp index f6f8c4cb2..80813879d 100644 --- a/lib/remote/configpackageutility.hpp +++ b/lib/remote/configpackageutility.hpp @@ -51,7 +51,7 @@ public: static std::vector GetStages(const String& packageName); static String GetActiveStage(const String& packageName); static void ActivateStage(const String& packageName, const String& stageName); - static void AsyncTryActivateStage(const String& packageName, const String& stageName); + static void AsyncTryActivateStage(const String& packageName, const String& stageName, bool reload); static std::vector > GetFiles(const String& packageName, const String& stageName); @@ -65,7 +65,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); + static void TryActivateStageCallback(const ProcessResult& pr, const String& packageName, const String& stageName, bool reload); }; } diff --git a/lib/remote/configstageshandler.cpp b/lib/remote/configstageshandler.cpp index ee2fc2374..fa1e3309f 100644 --- a/lib/remote/configstageshandler.cpp +++ b/lib/remote/configstageshandler.cpp @@ -98,6 +98,10 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ if (!ConfigPackageUtility::ValidateName(packageName)) return HttpUtility::SendJsonError(response, 400, "Invalid package name."); + bool reload = true; + if (params->Contains("reload")) + reload = HttpUtility::GetLastParameter(params, "reload"); + Dictionary::Ptr files = params->Get("files"); String stageName; @@ -109,7 +113,7 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ stageName = ConfigPackageUtility::CreateStage(packageName, files); /* validate the config. on success, activate stage and reload */ - ConfigPackageUtility::AsyncTryActivateStage(packageName, stageName); + ConfigPackageUtility::AsyncTryActivateStage(packageName, stageName, reload); } catch (const std::exception& ex) { return HttpUtility::SendJsonError(response, 500, "Stage creation failed.", @@ -118,10 +122,13 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ Dictionary::Ptr result1 = new Dictionary(); + String responseStatus = "Created stage. "; + responseStatus += (reload ? " Icinga2 will reload." : " Icinga2 reload skipped."); + result1->Set("package", packageName); result1->Set("stage", stageName); result1->Set("code", 200); - result1->Set("status", "Created stage."); + result1->Set("status", responseStatus); Array::Ptr results = new Array(); results->Add(result1);