From: Gunnar Beutner Date: Thu, 16 Jun 2016 06:28:57 +0000 (+0200) Subject: Improve filter support for /v1/templates X-Git-Tag: v2.5.0~258 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=28dee2b79b4c5ebf8d1365f33b93385bbdef9caa;p=icinga2 Improve filter support for /v1/templates refs #11941 --- diff --git a/doc/9-icinga2-api.md b/doc/9-icinga2-api.md index 7b12e34d6..4869e94b6 100644 --- a/doc/9-icinga2-api.md +++ b/doc/9-icinga2-api.md @@ -644,7 +644,11 @@ in: A list of all available configuration types is available in the [object types](6-object-types.md#object-types) chapter. -A [filter](9-icinga2-api.md#icinga2-api-filters) may be provided for this query type. +A [filter](9-icinga2-api.md#icinga2-api-filters) may be provided for this query type. The +template object can be accessed in the filter using the `tmpl` variable: + + $ curl -u root:root -k 'https://localhost:5661/v1/templates/hosts' -H "Accept: application/json" -X PUT -H "X-HTTP-Method-Override: GET" \ + -d '{ "filter": "match(\"g*\", tmpl.name)" }' Instead of using a filter you can optionally specify the template name in the URL path when querying a single object: diff --git a/lib/remote/filterutility.cpp b/lib/remote/filterutility.cpp index c3f2049f0..6e4bb625d 100644 --- a/lib/remote/filterutility.cpp +++ b/lib/remote/filterutility.cpp @@ -133,9 +133,9 @@ bool FilterUtility::EvaluateFilter(ScriptFrame& frame, Expression *filter, } static void FilteredAddTarget(ScriptFrame& permissionFrame, Expression *permissionFilter, - ScriptFrame& frame, Expression *ufilter, std::vector& result, const Object::Ptr& target) + ScriptFrame& frame, Expression *ufilter, std::vector& result, const String& variableName, const Object::Ptr& target) { - if (FilterUtility::EvaluateFilter(permissionFrame, permissionFilter, target) && FilterUtility::EvaluateFilter(frame, ufilter, target)) + if (FilterUtility::EvaluateFilter(permissionFrame, permissionFilter, target, variableName) && FilterUtility::EvaluateFilter(frame, ufilter, target, variableName)) result.push_back(target); } @@ -187,7 +187,7 @@ void FilterUtility::CheckPermission(const ApiUser::Ptr& user, const String& perm BOOST_THROW_EXCEPTION(ScriptError("Missing permission: " + requiredPermission)); } -std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, const ApiUser::Ptr& user) +std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, const ApiUser::Ptr& user, const String& variableName) { std::vector result; @@ -214,7 +214,7 @@ std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, c String name = HttpUtility::GetLastParameter(query, attr); Object::Ptr target = provider->GetTargetByName(type, name); - if (!FilterUtility::EvaluateFilter(permissionFrame, permissionFilter, target)) + if (!FilterUtility::EvaluateFilter(permissionFrame, permissionFilter, target, variableName)) BOOST_THROW_EXCEPTION(ScriptError("Access denied to object '" + name + "' of type '" + type + "'")); result.push_back(target); @@ -230,7 +230,7 @@ std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, c BOOST_FOREACH(const String& name, names) { Object::Ptr target = provider->GetTargetByName(type, name); - if (!FilterUtility::EvaluateFilter(permissionFrame, permissionFilter, target)) + if (!FilterUtility::EvaluateFilter(permissionFrame, permissionFilter, target, variableName)) BOOST_THROW_EXCEPTION(ScriptError("Access denied to object '" + name + "' of type '" + type + "'")); result.push_back(target); @@ -275,7 +275,7 @@ std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, c try { provider->FindTargets(type, boost::bind(&FilteredAddTarget, boost::ref(permissionFrame), permissionFilter, - boost::ref(frame), ufilter, boost::ref(result), _1)); + boost::ref(frame), ufilter, boost::ref(result), variableName, _1)); } catch (const std::exception& ex) { delete ufilter; throw; diff --git a/lib/remote/filterutility.hpp b/lib/remote/filterutility.hpp index a745728d4..f304e32dc 100644 --- a/lib/remote/filterutility.hpp +++ b/lib/remote/filterutility.hpp @@ -69,7 +69,8 @@ class I2_REMOTE_API FilterUtility public: static Type::Ptr TypeFromPluralName(const String& pluralName); static void CheckPermission(const ApiUser::Ptr& user, const String& permission, Expression **filter = NULL); - static std::vector GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, const ApiUser::Ptr& user); + static std::vector GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, + const ApiUser::Ptr& user, const String& variableName = String()); static bool EvaluateFilter(ScriptFrame& frame, Expression *filter, const Object::Ptr& target, const String& variableName = String()); }; diff --git a/lib/remote/templatequeryhandler.cpp b/lib/remote/templatequeryhandler.cpp index 5e59c29a5..0494b21bd 100644 --- a/lib/remote/templatequeryhandler.cpp +++ b/lib/remote/templatequeryhandler.cpp @@ -36,14 +36,20 @@ class TemplateTargetProvider : public TargetProvider public: DECLARE_PTR_TYPEDEFS(TemplateTargetProvider); + static Dictionary::Ptr GetTargetForTemplate(const ConfigItem::Ptr& item) + { + Dictionary::Ptr target = new Dictionary(); + target->Set("name", item->GetName()); + target->Set("type", item->GetType()); + return target; + } + virtual void FindTargets(const String& type, const boost::function& addTarget) const override { - std::vector targets = ConfigItem::GetItems(type); - - BOOST_FOREACH(const ConfigItem::Ptr& target, targets) { - if (target->IsAbstract()) - addTarget(target); + BOOST_FOREACH(const ConfigItem::Ptr& item, ConfigItem::GetItems(type)) { + if (item->IsAbstract()) + addTarget(GetTargetForTemplate(item)); } } @@ -54,7 +60,7 @@ public: if (!item || !item->IsAbstract()) BOOST_THROW_EXCEPTION(std::invalid_argument("Template does not exist.")); - return item; + return GetTargetForTemplate(item); } virtual bool IsValidType(const String& type) const override @@ -104,7 +110,7 @@ bool TemplateQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& std::vector objs; try { - objs = FilterUtility::GetFilterTargets(qd, params, user); + objs = FilterUtility::GetFilterTargets(qd, params, user, "tmpl"); } catch (const std::exception& ex) { HttpUtility::SendJsonError(response, 404, "No templates found.", @@ -114,12 +120,8 @@ bool TemplateQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& Array::Ptr results = new Array(); - BOOST_FOREACH(const ConfigItem::Ptr& obj, objs) { - Dictionary::Ptr result1 = new Dictionary(); - results->Add(result1); - - result1->Set("type", obj->GetType()); - result1->Set("name", obj->GetName()); + BOOST_FOREACH(const Dictionary::Ptr& obj, objs) { + results->Add(obj); } Dictionary::Ptr result = new Dictionary();