From 3d78870339ab2e4ff437ae6a59480b8d3cceaad7 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 12 Aug 2015 14:15:01 +0200 Subject: [PATCH] Implement support for modified attributes in the API refs #9081 --- lib/base/scriptutils.cpp | 13 +++- lib/base/scriptutils.hpp | 2 +- lib/icinga/icingaapplication.cpp | 13 ++-- lib/remote/CMakeLists.txt | 2 +- lib/remote/modifyobjecthandler.cpp | 100 +++++++++++++++++++++++++++++ lib/remote/modifyobjecthandler.hpp | 38 +++++++++++ lib/remote/statusqueryhandler.cpp | 3 + 7 files changed, 160 insertions(+), 11 deletions(-) create mode 100644 lib/remote/modifyobjecthandler.cpp create mode 100644 lib/remote/modifyobjecthandler.hpp diff --git a/lib/base/scriptutils.cpp b/lib/base/scriptutils.cpp index 6028380a846..edd58c858ec 100644 --- a/lib/base/scriptutils.cpp +++ b/lib/base/scriptutils.cpp @@ -251,12 +251,19 @@ Array::Ptr ScriptUtils::Keys(const Dictionary::Ptr& dict) return result; } -DynamicObject::Ptr ScriptUtils::GetObject(const Type::Ptr& type, const String& name) +DynamicObject::Ptr ScriptUtils::GetObject(const Value& vtype, const String& name) { - DynamicType::Ptr dtype = DynamicType::GetByName(type->GetName()); + String typeName; + + if (vtype.IsObjectType()) + typeName = static_cast(vtype)->GetName(); + else + typeName = vtype; + + DynamicType::Ptr dtype = DynamicType::GetByName(typeName); if (!dtype) - BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type name")); + return DynamicObject::Ptr(); return dtype->GetObject(name); } diff --git a/lib/base/scriptutils.hpp b/lib/base/scriptutils.hpp index 9005d8bcb12..ff36327bc76 100644 --- a/lib/base/scriptutils.hpp +++ b/lib/base/scriptutils.hpp @@ -47,7 +47,7 @@ class I2_BASE_API ScriptUtils static Array::Ptr Range(const std::vector& arguments); static Type::Ptr TypeOf(const Value& value); static Array::Ptr Keys(const Dictionary::Ptr& dict); - static DynamicObject::Ptr GetObject(const Type::Ptr& type, const String& name); + static DynamicObject::Ptr GetObject(const Value& type, const String& name); static Array::Ptr GetObjects(const Type::Ptr& type); static void Assert(const Value& arg); static String MsiGetComponentPathShim(const String& component); diff --git a/lib/icinga/icingaapplication.cpp b/lib/icinga/icingaapplication.cpp index 1b811c60760..c4f6fee6fa5 100644 --- a/lib/icinga/icingaapplication.cpp +++ b/lib/icinga/icingaapplication.cpp @@ -140,13 +140,14 @@ static void PersistModAttrHelper(const ConfigWriter::Ptr& cw, DynamicObject::Ptr if (previousObject) cw->EmitRaw("}\n\n"); - cw->EmitRaw("var obj = get_object("); - cw->EmitIdentifier(object->GetReflectionType()->GetName(), 0); - cw->EmitRaw(", "); - cw->EmitString(object->GetName()); - cw->EmitRaw(")\n"); + cw->EmitRaw("var obj = "); - cw->EmitRaw("if (obj) {\n"); + Array::Ptr args1 = new Array(); + args1->Add(object->GetReflectionType()->GetName()); + args1->Add(object->GetName()); + cw->EmitFunctionCall("get_object", args1); + + cw->EmitRaw("\nif (obj) {\n"); } cw->EmitRaw("\tobj."); diff --git a/lib/remote/CMakeLists.txt b/lib/remote/CMakeLists.txt index 07a9953f264..68c82b18218 100644 --- a/lib/remote/CMakeLists.txt +++ b/lib/remote/CMakeLists.txt @@ -28,7 +28,7 @@ set(remote_SOURCES endpoint.cpp endpoint.thpp filterutility.cpp httpchunkedencoding.cpp httpconnection.cpp httphandler.cpp httprequest.cpp httpresponse.cpp httputility.cpp jsonrpc.cpp jsonrpcconnection.cpp jsonrpcconnection-heartbeat.cpp - messageorigin.cpp statusqueryhandler.cpp url.cpp zone.cpp zone.thpp + messageorigin.cpp modifyobjecthandler.cpp statusqueryhandler.cpp url.cpp zone.cpp zone.thpp ) if(ICINGA2_UNITY_BUILD) diff --git a/lib/remote/modifyobjecthandler.cpp b/lib/remote/modifyobjecthandler.cpp new file mode 100644 index 00000000000..6b66be3ad1b --- /dev/null +++ b/lib/remote/modifyobjecthandler.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2015 Icinga Development Team (http://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/modifyobjecthandler.hpp" +#include "remote/httputility.hpp" +#include "remote/filterutility.hpp" +#include "remote/apiaction.hpp" +#include "base/exception.hpp" +#include "base/serializer.hpp" +#include +#include + +using namespace icinga; + +REGISTER_URLHANDLER("/v1", ModifyObjectHandler); + +bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) +{ + if (request.RequestMethod != "POST") + return false; + + if (request.RequestUrl->GetPath().size() < 2) + return false; + + Type::Ptr type = FilterUtility::TypeFromPluralName(request.RequestUrl->GetPath()[1]); + + if (!type) + return false; + + QueryDescription qd; + qd.Types.insert(type); + + Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request); + + params->Set("type", type->GetName()); + + if (request.RequestUrl->GetPath().size() >= 3) { + String attr = type->GetName(); + boost::algorithm::to_lower(attr); + params->Set(attr, request.RequestUrl->GetPath()[2]); + } + + std::vector objs = FilterUtility::GetFilterTargets(qd, params); + + Dictionary::Ptr attrs = params->Get("attrs"); + + Array::Ptr results = new Array(); + + if (attrs) { + BOOST_FOREACH(const DynamicObject::Ptr& obj, objs) { + Dictionary::Ptr result1 = new Dictionary(); + + result1->Set("type", obj->GetReflectionType()->GetName()); + result1->Set("name", obj->GetName()); + + String key; + + try { + ObjectLock olock(attrs); + BOOST_FOREACH(const Dictionary::Pair& kv, attrs) { + key = kv.first; + obj->ModifyAttribute(kv.first, kv.second); + } + + result1->Set("code", 200); + result1->Set("status", "Attributes updated."); + } catch (const std::exception& ex) { + result1->Set("code", 500); + result1->Set("status", "Attribute '" + key + "' could not be set: " + DiagnosticInformation(ex)); + } + + results->Add(result1); + } + } + + Dictionary::Ptr result = new Dictionary(); + result->Set("results", results); + + response.SetStatus(200, "OK"); + HttpUtility::SendJsonBody(response, result); + + return true; +} + diff --git a/lib/remote/modifyobjecthandler.hpp b/lib/remote/modifyobjecthandler.hpp new file mode 100644 index 00000000000..da424b9ad17 --- /dev/null +++ b/lib/remote/modifyobjecthandler.hpp @@ -0,0 +1,38 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2015 Icinga Development Team (http://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 MODIFYOBJECTHANDLER_H +#define MODIFYOBJECTHANDLER_H + +#include "remote/httphandler.hpp" + +namespace icinga +{ + +class I2_REMOTE_API ModifyObjectHandler : public HttpHandler +{ +public: + DECLARE_PTR_TYPEDEFS(ModifyObjectHandler); + + virtual bool HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response); +}; + +} + +#endif /* MODIFYOBJECTHANDLER_H */ diff --git a/lib/remote/statusqueryhandler.cpp b/lib/remote/statusqueryhandler.cpp index d66d362401c..8e0773cdee2 100644 --- a/lib/remote/statusqueryhandler.cpp +++ b/lib/remote/statusqueryhandler.cpp @@ -30,6 +30,9 @@ REGISTER_URLHANDLER("/v1", StatusQueryHandler); bool StatusQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { + if (request.RequestMethod != "GET") + return false; + if (request.RequestUrl->GetPath().size() < 2) return false;