diff --git a/doc/10-icinga-template-library.md b/doc/10-icinga-template-library.md
index 2e8120385..3fe35584c 100644
--- a/doc/10-icinga-template-library.md
+++ b/doc/10-icinga-template-library.md
@@ -74,9 +74,13 @@ plugin scripts.
### icinga
Check command for the built-in `icinga` check. This check returns performance
-data for the current Icinga instance.
+data for the current Icinga instance and optionally allows for minimum version checks.
-The `icinga` check command does not support any vars.
+Custom attributes passed as [command parameters](03-monitoring-basics.md#command-passing-parameters):
+
+Name | Description
+-----------------------|---------------
+icinga\_min\_version | **Optional.** Required minimum Icinga 2 version, e.g. `2.8.0`. If not satisfied, the state changes to `Critical`. Release packages only.
### cluster
diff --git a/lib/methods/icingachecktask.cpp b/lib/methods/icingachecktask.cpp
index 70a757a4f..da46ef206 100644
--- a/lib/methods/icingachecktask.cpp
+++ b/lib/methods/icingachecktask.cpp
@@ -32,9 +32,25 @@ using namespace icinga;
REGISTER_SCRIPTFUNCTION_NS(Internal, IcingaCheck, &IcingaCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
-void IcingaCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+void IcingaCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
+ CheckCommand::Ptr commandObj = checkable->GetCheckCommand();
+
+ Host::Ptr host;
+ Service::Ptr service;
+ tie(host, service) = GetHostService(checkable);
+
+ MacroProcessor::ResolverList resolvers;
+ if (service)
+ resolvers.emplace_back("service", service);
+ resolvers.emplace_back("host", host);
+ resolvers.emplace_back("command", commandObj);
+ resolvers.emplace_back("icinga", IcingaApplication::GetInstance());
+
+ String icingaMinVersion = MacroProcessor::ResolveMacros("$icinga_min_version$", resolvers, checkable->GetLastCheckResult(),
+ nullptr, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros);
+
if (resolvedMacros && !useResolvedMacros)
return;
@@ -130,17 +146,31 @@ void IcingaCheckTask::ScriptFunc(const Checkable::Ptr& service, const CheckResul
perfdata->Add(new PerfdataValue("sum_bytes_sent_per_second", bytesSentPerSecond));
perfdata->Add(new PerfdataValue("sum_bytes_received_per_second", bytesReceivedPerSecond));
- cr->SetOutput("Icinga 2 has been running for " + Utility::FormatDuration(uptime) +
- ". Version: " + Application::GetAppVersion());
cr->SetPerformanceData(perfdata);
+ cr->SetState(ServiceOK);
+ String appVersion = Application::GetAppVersion();
+
+ String output = "Icinga 2 has been running for " + Utility::FormatDuration(uptime) +
+ ". Version: " + appVersion;
+
+ /* Indicate a warning if the last reload failed. */
double lastReloadFailed = Application::GetLastReloadFailed();
if (lastReloadFailed > 0) {
- cr->SetOutput(cr->GetOutput() + "; Last reload attempt failed at " + Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", lastReloadFailed));
+ output += "; Last reload attempt failed at " + Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", lastReloadFailed);
cr->SetState(ServiceWarning);
- } else
- cr->SetState(ServiceOK);
+ }
- service->ProcessCheckResult(cr);
+ /* Return an error if the version is less than specified (optional). */
+ String parsedAppVersion = appVersion.SubStr(1,5);
+
+ if (!icingaMinVersion.IsEmpty() && Utility::CompareVersion(icingaMinVersion, parsedAppVersion) < 0) {
+ output += "; Minimum version " + icingaMinVersion + " is not installed.";
+ cr->SetState(ServiceCritical);
+ }
+
+ cr->SetOutput(output);
+
+ checkable->ProcessCheckResult(cr);
}
diff --git a/lib/methods/icingachecktask.hpp b/lib/methods/icingachecktask.hpp
index 2868f6840..24f9f232f 100644
--- a/lib/methods/icingachecktask.hpp
+++ b/lib/methods/icingachecktask.hpp
@@ -34,7 +34,7 @@ namespace icinga
class IcingaCheckTask
{
public:
- static void ScriptFunc(const Checkable::Ptr& service, const CheckResult::Ptr& cr,
+ static void ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private: