1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #include "remote/statushandler.hpp"
4 #include "remote/httputility.hpp"
5 #include "remote/filterutility.hpp"
6 #include "base/serializer.hpp"
7 #include "base/statsfunction.hpp"
8 #include "base/namespace.hpp"
9
10 using namespace icinga;
11
12 REGISTER_URLHANDLER("/v1/status", StatusHandler);
13
14 class StatusTargetProvider final : public TargetProvider
15 {
16 public:
17 DECLARE_PTR_TYPEDEFS(StatusTargetProvider);
18
FindTargets(const String & type,const std::function<void (const Value &)> & addTarget) const19 void FindTargets(const String& type,
20 const std::function<void (const Value&)>& addTarget) const override
21 {
22 Namespace::Ptr statsFunctions = ScriptGlobal::Get("StatsFunctions", &Empty);
23
24 if (statsFunctions) {
25 ObjectLock olock(statsFunctions);
26
27 for (const Namespace::Pair& kv : statsFunctions)
28 addTarget(GetTargetByName("Status", kv.first));
29 }
30 }
31
GetTargetByName(const String & type,const String & name) const32 Value GetTargetByName(const String& type, const String& name) const override
33 {
34 Namespace::Ptr statsFunctions = ScriptGlobal::Get("StatsFunctions", &Empty);
35
36 if (!statsFunctions)
37 BOOST_THROW_EXCEPTION(std::invalid_argument("No status functions are available."));
38
39 Value vfunc;
40
41 if (!statsFunctions->Get(name, &vfunc))
42 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid status function name."));
43
44 Function::Ptr func = vfunc;
45
46 if (!func)
47 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid status function name."));
48
49 Dictionary::Ptr status = new Dictionary();
50 Array::Ptr perfdata = new Array();
51 func->Invoke({ status, perfdata });
52
53 return new Dictionary({
54 { "name", name },
55 { "status", status },
56 { "perfdata", Serialize(perfdata, FAState) }
57 });
58 }
59
IsValidType(const String & type) const60 bool IsValidType(const String& type) const override
61 {
62 return type == "Status";
63 }
64
GetPluralName(const String & type) const65 String GetPluralName(const String& type) const override
66 {
67 return "statuses";
68 }
69 };
70
HandleRequest(AsioTlsStream & stream,const ApiUser::Ptr & user,boost::beast::http::request<boost::beast::http::string_body> & request,const Url::Ptr & url,boost::beast::http::response<boost::beast::http::string_body> & response,const Dictionary::Ptr & params,boost::asio::yield_context & yc,HttpServerConnection & server)71 bool StatusHandler::HandleRequest(
72 AsioTlsStream& stream,
73 const ApiUser::Ptr& user,
74 boost::beast::http::request<boost::beast::http::string_body>& request,
75 const Url::Ptr& url,
76 boost::beast::http::response<boost::beast::http::string_body>& response,
77 const Dictionary::Ptr& params,
78 boost::asio::yield_context& yc,
79 HttpServerConnection& server
80 )
81 {
82 namespace http = boost::beast::http;
83
84 if (url->GetPath().size() > 3)
85 return false;
86
87 if (request.method() != http::verb::get)
88 return false;
89
90 QueryDescription qd;
91 qd.Types.insert("Status");
92 qd.Provider = new StatusTargetProvider();
93 qd.Permission = "status/query";
94
95 params->Set("type", "Status");
96
97 if (url->GetPath().size() >= 3)
98 params->Set("status", url->GetPath()[2]);
99
100 std::vector<Value> objs;
101
102 try {
103 objs = FilterUtility::GetFilterTargets(qd, params, user);
104 } catch (const std::exception& ex) {
105 HttpUtility::SendJsonError(response, params, 404,
106 "No objects found.",
107 DiagnosticInformation(ex));
108 return true;
109 }
110
111 Dictionary::Ptr result = new Dictionary({
112 { "results", new Array(std::move(objs)) }
113 });
114
115 response.result(http::status::ok);
116 HttpUtility::SendJsonBody(response, params, result);
117
118 return true;
119 }
120
121