1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #include "remote/variablequeryhandler.hpp"
4 #include "remote/httputility.hpp"
5 #include "remote/filterutility.hpp"
6 #include "base/configtype.hpp"
7 #include "base/scriptglobal.hpp"
8 #include "base/logger.hpp"
9 #include "base/serializer.hpp"
10 #include "base/namespace.hpp"
11 #include <set>
12
13 using namespace icinga;
14
15 REGISTER_URLHANDLER("/v1/variables", VariableQueryHandler);
16
17 class VariableTargetProvider final : public TargetProvider
18 {
19 public:
20 DECLARE_PTR_TYPEDEFS(VariableTargetProvider);
21
GetTargetForVar(const String & name,const Value & value)22 static Dictionary::Ptr GetTargetForVar(const String& name, const Value& value)
23 {
24 return new Dictionary({
25 { "name", name },
26 { "type", value.GetReflectionType()->GetName() },
27 { "value", value }
28 });
29 }
30
FindTargets(const String & type,const std::function<void (const Value &)> & addTarget) const31 void FindTargets(const String& type,
32 const std::function<void (const Value&)>& addTarget) const override
33 {
34 {
35 Namespace::Ptr globals = ScriptGlobal::GetGlobals();
36 ObjectLock olock(globals);
37 for (const Namespace::Pair& kv : globals) {
38 addTarget(GetTargetForVar(kv.first, kv.second->Get()));
39 }
40 }
41 }
42
GetTargetByName(const String & type,const String & name) const43 Value GetTargetByName(const String& type, const String& name) const override
44 {
45 return GetTargetForVar(name, ScriptGlobal::Get(name));
46 }
47
IsValidType(const String & type) const48 bool IsValidType(const String& type) const override
49 {
50 return type == "Variable";
51 }
52
GetPluralName(const String & type) const53 String GetPluralName(const String& type) const override
54 {
55 return "variables";
56 }
57 };
58
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)59 bool VariableQueryHandler::HandleRequest(
60 AsioTlsStream& stream,
61 const ApiUser::Ptr& user,
62 boost::beast::http::request<boost::beast::http::string_body>& request,
63 const Url::Ptr& url,
64 boost::beast::http::response<boost::beast::http::string_body>& response,
65 const Dictionary::Ptr& params,
66 boost::asio::yield_context& yc,
67 HttpServerConnection& server
68 )
69 {
70 namespace http = boost::beast::http;
71
72 if (url->GetPath().size() > 3)
73 return false;
74
75 if (request.method() != http::verb::get)
76 return false;
77
78 QueryDescription qd;
79 qd.Types.insert("Variable");
80 qd.Permission = "variables";
81 qd.Provider = new VariableTargetProvider();
82
83 params->Set("type", "Variable");
84
85 if (url->GetPath().size() >= 3)
86 params->Set("variable", url->GetPath()[2]);
87
88 std::vector<Value> objs;
89
90 try {
91 objs = FilterUtility::GetFilterTargets(qd, params, user, "variable");
92 } catch (const std::exception& ex) {
93 HttpUtility::SendJsonError(response, params, 404,
94 "No variables found.",
95 DiagnosticInformation(ex));
96 return true;
97 }
98
99 ArrayData results;
100
101 for (const Dictionary::Ptr& var : objs) {
102 results.emplace_back(new Dictionary({
103 { "name", var->Get("name") },
104 { "type", var->Get("type") },
105 { "value", Serialize(var->Get("value"), 0) }
106 }));
107 }
108
109 Dictionary::Ptr result = new Dictionary({
110 { "results", new Array(std::move(results)) }
111 });
112
113 response.result(http::status::ok);
114 HttpUtility::SendJsonBody(response, params, result);
115
116 return true;
117 }
118
119