Skip to content

Commit

Permalink
ITL: add CheckCommand icinga4win-api
Browse files Browse the repository at this point in the history
  • Loading branch information
Al2Klimov committed Nov 5, 2021
1 parent d892fc7 commit 8c6a837
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 0 deletions.
4 changes: 4 additions & 0 deletions itl/command-icinga.conf
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ object CheckCommand "exception" {
object CheckCommand "sleep" {
import "sleep-check-command"
}

object CheckCommand "icinga4win-api" {
import "icinga4win-api-check-command"
}
1 change: 1 addition & 0 deletions lib/methods/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ set(methods_SOURCES
dummychecktask.cpp dummychecktask.hpp
exceptionchecktask.cpp exceptionchecktask.hpp
icingachecktask.cpp icingachecktask.hpp
icinga4winapichecktask.cpp icinga4winapichecktask.hpp
nullchecktask.cpp nullchecktask.hpp
nulleventtask.cpp nulleventtask.hpp
pluginchecktask.cpp pluginchecktask.hpp
Expand Down
137 changes: 137 additions & 0 deletions lib/methods/icinga4winapichecktask.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/* Icinga 2 | (c) 2021 Icinga GmbH | GPLv2+ */

#ifndef _WIN32
# include <stdlib.h>
#endif /* _WIN32 */
#include "methods/icinga4winapichecktask.hpp"
#include "icinga/icingaapplication.hpp"
#include "icinga/pluginutility.hpp"
#include "base/utility.hpp"
#include "base/perfdatavalue.hpp"
#include "base/convert.hpp"
#include "base/function.hpp"
#include "base/io-engine.hpp"
#include "base/json.hpp"
#include "base/logger.hpp"
#include "base/tcpsocket.hpp"
#include "base/tlsstream.hpp"
#include <boost/asio.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>

using namespace icinga;

REGISTER_FUNCTION_NONCONST(Internal, Icinga4WinApiCheck, &Icinga4WinApiCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");

void Icinga4WinApiCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
using namespace boost::asio;
using namespace boost::beast;
using namespace boost::beast::http;

REQUIRE_NOT_NULL(checkable);
REQUIRE_NOT_NULL(cr);

CheckCommand::Ptr command = CheckCommand::ExecuteOverride ? CheckCommand::ExecuteOverride : checkable->GetCheckCommand();

Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);

MacroProcessor::ResolverList resolvers;

if (MacroResolver::OverrideMacros)
resolvers.emplace_back("override", MacroResolver::OverrideMacros);

if (service)
resolvers.emplace_back("service", service);
resolvers.emplace_back("host", host);
resolvers.emplace_back("command", command);
resolvers.emplace_back("icinga", IcingaApplication::GetInstance());

String psCommand = MacroProcessor::ResolveMacros("$icinga4win_api_command_name$", resolvers, checkable->GetLastCheckResult(),
nullptr, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros);

Dictionary::Ptr arguments = MacroProcessor::ResolveMacros("$icinga4win_api_arguments$", resolvers, checkable->GetLastCheckResult(),
nullptr, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros);

Dictionary::Ptr params = new Dictionary();

if (arguments) {
ObjectLock oLock (arguments);
Array::Ptr dummy = new Array();

for (auto& kv : arguments) {
Array::Ptr arg = MacroProcessor::ResolveArguments(
dummy, new Dictionary({{kv.first, kv.second}}), resolvers,
checkable->GetLastCheckResult(), resolvedMacros, useResolvedMacros
);

switch (arg ? arg->GetLength() : 0) {
case 0:
continue;
case 1:
params->Set(arg->Get(0), true);
break;
case 2:
params->Set(arg->Get(0), arg->Get(1));
break;
default: {
auto k (arg->Get(0));

arg->Remove(0);
params->Set(k, arg);
}
}
}
}

if (resolvedMacros && !useResolvedMacros)
return;

ssl::context ctx (ssl::context::tls);
AsioTlsStream conn (IoEngine::Get().GetIoContext(), ctx);
request<string_body> req;
flat_buffer buf;
response<string_body> resp;

req.method(verb::post);
req.target("/v1/checker?command=" + psCommand);
req.set(field::content_type, "application/json");
req.body() = JsonEncode(params);

Connect(conn.lowest_layer(), "127.0.0.1", "5668");
conn.next_layer().handshake(conn.next_layer().client);

double start = Utility::GetTime();

write(conn, req);
conn.flush();
read(conn, buf, resp);

double end = Utility::GetTime();

Dictionary::Ptr result = Dictionary::Ptr(JsonDecode(resp.body()))->Get(psCommand);

if (Checkable::ExecuteCommandProcessFinishedHandler) {
ProcessResult pr;
pr.PID = -1;
pr.Output = result->Get("checkresult") + " |" + Array::Ptr(result->Get("perfdata"))->Join("");
pr.ExecutionStart = start;
pr.ExecutionEnd = end;
pr.ExitStatus = result->Get("exitcode");

Checkable::ExecuteCommandProcessFinishedHandler(command->GetName(), pr);
} else {
cr->SetOutput(result->Get("checkresult"));
cr->SetPerformanceData(result->Get("perfdata"));
cr->SetState((ServiceState)(int)result->Get("exitcode"));
cr->SetExitStatus(result->Get("exitcode"));
cr->SetExecutionStart(start);
cr->SetExecutionEnd(end);
cr->SetCommand(command->GetName());

checkable->ProcessCheckResult(cr);
}
}
30 changes: 30 additions & 0 deletions lib/methods/icinga4winapichecktask.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* Icinga 2 | (c) 2021 Icinga GmbH | GPLv2+ */

#ifndef ICINGA4WINAPICHECKTASK_H
#define ICINGA4WINAPICHECKTASK_H

#include "methods/i2-methods.hpp"
#include "icinga/service.hpp"
#include "base/dictionary.hpp"

namespace icinga
{

/**
* Executes checks via local Icinga for Windows API.
*
* @ingroup methods
*/
class Icinga4WinApiCheckTask
{
public:
static void ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);

private:
Icinga4WinApiCheckTask();
};

}

#endif /* ICINGA4WINAPICHECKTASK_H */
5 changes: 5 additions & 0 deletions lib/methods/methods-itl.conf
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ System.assert(Internal.run_with_activation_context(function() {
execute = NullCheck
}

template CheckCommand "icinga4win-api-check-command" use (Icinga4WinApiCheck = Internal.Icinga4WinApiCheck) {
execute = Icinga4WinApiCheck
}

template EventCommand "null-event-command" use (NullEvent = Internal.NullEvent) {
execute = NullEvent
}
Expand All @@ -64,6 +68,7 @@ System.assert(Internal.run_with_activation_context(function() {

var methods = [
"IcingaCheck",
"Icinga4WinApiCheck",
"ClusterCheck",
"ClusterZoneCheck",
"PluginCheck",
Expand Down

0 comments on commit 8c6a837

Please sign in to comment.