[icinga-checkins] icinga.org: icinga2/master: Improve filter support for /v1/templates

git at icinga.org git at icinga.org
Thu Jun 16 08:38:17 CEST 2016


Module: icinga2
Branch: master
Commit: 28dee2b79b4c5ebf8d1365f33b93385bbdef9caa
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=28dee2b79b4c5ebf8d1365f33b93385bbdef9caa

Author: Gunnar Beutner <gunnar.beutner at netways.de>
Date:   Thu Jun 16 08:28:57 2016 +0200

Improve filter support for /v1/templates

refs #11941

---

 doc/9-icinga2-api.md                |    6 +++++-
 lib/remote/filterutility.cpp        |   12 ++++++------
 lib/remote/filterutility.hpp        |    3 ++-
 lib/remote/templatequeryhandler.cpp |   28 +++++++++++++++-------------
 4 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/doc/9-icinga2-api.md b/doc/9-icinga2-api.md
index 7b12e34..4869e94 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 c3f2049..6e4bb62 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<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;
diff --git a/lib/remote/filterutility.hpp b/lib/remote/filterutility.hpp
index a745728..f304e32 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<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());
 };
diff --git a/lib/remote/templatequeryhandler.cpp b/lib/remote/templatequeryhandler.cpp
index 5e59c29..0494b21 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<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();



More information about the icinga-checkins mailing list