]> granicus.if.org Git - icinga2/commitdiff
Improve filter support for /v1/templates
authorGunnar Beutner <gunnar.beutner@netways.de>
Thu, 16 Jun 2016 06:28:57 +0000 (08:28 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 16 Jun 2016 06:38:15 +0000 (08:38 +0200)
refs #11941

doc/9-icinga2-api.md
lib/remote/filterutility.cpp
lib/remote/filterutility.hpp
lib/remote/templatequeryhandler.cpp

index 7b12e34d687bb5b99cef247658640ac506014ba0..4869e94b6adb59ca8b77d0a261229d49ff0d4ed8 100644 (file)
@@ -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:
index c3f2049f093ce6392a0d538beb7339a1b7c4295e..6e4bb625d720b0d9a6cfc19a6e10d69bb0052cde 100644 (file)
@@ -133,9 +133,9 @@ bool FilterUtility::EvaluateFilter(ScriptFrame& frame, Expression *filter,
 }
 
 static void FilteredAddTarget(ScriptFrame& permissionFrame, Expression *permissionFilter,
-    ScriptFrame& frame, Expression *ufilter, std::vector<Value>& result, const Object::Ptr& target)
+    ScriptFrame& frame, Expression *ufilter, std::vector<Value>& 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<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, const ApiUser::Ptr& user)
+std::vector<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, const ApiUser::Ptr& user, const String& variableName)
 {
        std::vector<Value> result;
 
@@ -214,7 +214,7 @@ std::vector<Value> 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<Value> 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<Value> 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;
index a745728d41601c71a39f891c12de361ab913fb8f..f304e32dc7163e42ed9abfe44be2d154513bb953 100644 (file)
@@ -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<Value> GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, const ApiUser::Ptr& user);
+       static std::vector<Value> 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());
 };
index 5e59c29a5e9c3225f5c2a70fd5154852e5933418..0494b21bddc8cbe1a32d842e249b1d6400753d13 100644 (file)
@@ -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<void (const Value&)>& addTarget) const override
        {
-               std::vector<ConfigItem::Ptr> 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<Value> 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();