From ace6882b59f8a0dc4223a466ed2963ff03eb29d1 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 15 Jun 2016 07:37:03 +0200 Subject: [PATCH] Implement support for retrieving a list of templates from the API fixes #11941 --- doc/9-icinga2-api.md | 26 ++++++ lib/remote/CMakeLists.txt | 4 +- lib/remote/templatequeryhandler.cpp | 133 ++++++++++++++++++++++++++++ lib/remote/templatequeryhandler.hpp | 39 ++++++++ 4 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 lib/remote/templatequeryhandler.cpp create mode 100644 lib/remote/templatequeryhandler.hpp diff --git a/doc/9-icinga2-api.md b/doc/9-icinga2-api.md index 9ee4afea1..7b12e34d6 100644 --- a/doc/9-icinga2-api.md +++ b/doc/9-icinga2-api.md @@ -626,6 +626,32 @@ Example for deleting the host object `example.localdomain`: ] } +## Config Templates + +Provides methods to manage configuration templates: + +* [querying templates](9-icinga2-api.md#icinga2-api-config-templates-query) + +### Querying Templates + +You can request information about configuration templates by sending +a `GET` query to the `/v1/templates/` URL endpoint. ` Actions diff --git a/lib/remote/CMakeLists.txt b/lib/remote/CMakeLists.txt index 2afd437fc..521186c83 100644 --- a/lib/remote/CMakeLists.txt +++ b/lib/remote/CMakeLists.txt @@ -29,8 +29,8 @@ set(remote_SOURCES endpoint.cpp endpoint.thpp eventshandler.cpp eventqueue.cpp filterutility.cpp httpchunkedencoding.cpp httpclientconnection.cpp httpserverconnection.cpp httphandler.cpp httprequest.cpp httpresponse.cpp httputility.cpp infohandler.cpp jsonrpc.cpp jsonrpcconnection.cpp jsonrpcconnection-heartbeat.cpp - messageorigin.cpp modifyobjecthandler.cpp statushandler.cpp objectqueryhandler.cpp typequeryhandler.cpp - url.cpp zone.cpp zone.thpp + messageorigin.cpp modifyobjecthandler.cpp statushandler.cpp objectqueryhandler.cpp templatequeryhandler.cpp + typequeryhandler.cpp url.cpp zone.cpp zone.thpp ) if(ICINGA2_UNITY_BUILD) diff --git a/lib/remote/templatequeryhandler.cpp b/lib/remote/templatequeryhandler.cpp new file mode 100644 index 000000000..5e59c29a5 --- /dev/null +++ b/lib/remote/templatequeryhandler.cpp @@ -0,0 +1,133 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "remote/templatequeryhandler.hpp" +#include "remote/httputility.hpp" +#include "remote/filterutility.hpp" +#include "config/configitem.hpp" +#include "base/configtype.hpp" +#include "base/scriptglobal.hpp" +#include "base/logger.hpp" +#include +#include + +using namespace icinga; + +REGISTER_URLHANDLER("/v1/templates", TemplateQueryHandler); + +class TemplateTargetProvider : public TargetProvider +{ +public: + DECLARE_PTR_TYPEDEFS(TemplateTargetProvider); + + 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); + } + } + + virtual Value GetTargetByName(const String& type, const String& name) const override + { + ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(type, name); + + if (!item || !item->IsAbstract()) + BOOST_THROW_EXCEPTION(std::invalid_argument("Template does not exist.")); + + return item; + } + + virtual bool IsValidType(const String& type) const override + { + Type::Ptr ptype = Type::GetByName(type); + + if (!ptype) + return false; + + return ConfigObject::TypeInstance->IsAssignableFrom(ptype); + } + + virtual String GetPluralName(const String& type) const override + { + return Type::GetByName(type)->GetPluralName(); + } +}; + +bool TemplateQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response, const Dictionary::Ptr& params) +{ + if (request.RequestUrl->GetPath().size() < 3 || request.RequestUrl->GetPath().size() > 4) + return false; + + if (request.RequestMethod != "GET") + return false; + + Type::Ptr type = FilterUtility::TypeFromPluralName(request.RequestUrl->GetPath()[2]); + + if (!type) { + HttpUtility::SendJsonError(response, 400, "Invalid type specified."); + return true; + } + + QueryDescription qd; + qd.Types.insert(type->GetName()); + qd.Permission = "templates/query/" + type->GetName(); + qd.Provider = new TemplateTargetProvider(); + + params->Set("type", type->GetName()); + + if (request.RequestUrl->GetPath().size() >= 4) { + String attr = type->GetName(); + boost::algorithm::to_lower(attr); + params->Set(attr, request.RequestUrl->GetPath()[3]); + } + + std::vector objs; + + try { + objs = FilterUtility::GetFilterTargets(qd, params, user); + } catch (const std::exception& ex) { + HttpUtility::SendJsonError(response, 404, + "No templates found.", + HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); + return true; + } + + 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()); + } + + Dictionary::Ptr result = new Dictionary(); + result->Set("results", results); + + response.SetStatus(200, "OK"); + HttpUtility::SendJsonBody(response, result); + + return true; +} + diff --git a/lib/remote/templatequeryhandler.hpp b/lib/remote/templatequeryhandler.hpp new file mode 100644 index 000000000..d390e833d --- /dev/null +++ b/lib/remote/templatequeryhandler.hpp @@ -0,0 +1,39 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef TEMPLATEQUERYHANDLER_H +#define TEMPLATEQUERYHANDLER_H + +#include "remote/httphandler.hpp" + +namespace icinga +{ + +class I2_REMOTE_API TemplateQueryHandler : public HttpHandler +{ +public: + DECLARE_PTR_TYPEDEFS(TemplateQueryHandler); + + virtual bool HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, + HttpResponse& response, const Dictionary::Ptr& params) override; +}; + +} + +#endif /* TEMPLATEQUERYHANDLER_H */