From: Gunnar Beutner Date: Tue, 25 Aug 2015 14:43:48 +0000 (+0200) Subject: Use dependency graph when deleting objects X-Git-Tag: v2.4.0~377 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=de09a562f64bd549b705bc258fde5d9a4caa42c4;p=icinga2 Use dependency graph when deleting objects refs #9096 --- diff --git a/lib/remote/configobjectutility.cpp b/lib/remote/configobjectutility.cpp index 2968ccdb2..1304bef0e 100644 --- a/lib/remote/configobjectutility.cpp +++ b/lib/remote/configobjectutility.cpp @@ -24,6 +24,7 @@ #include "config/configwriter.hpp" #include "base/exception.hpp" #include "base/serializer.hpp" +#include "base/dependencygraph.hpp" #include #include #include @@ -144,18 +145,29 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full return true; } - -bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, const Array::Ptr& errors) + +bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors) { - if (object->GetModule() != "_api") { + std::vector parents = DependencyGraph::GetParents(object); + + if (!parents.empty() && !cascade) { if (errors) - errors->Add("Object cannot be deleted because it was not created using the API."); - + errors->Add("Object cannot be deleted because other objects depend on it. Use cascading delete to delete it anyway."); + return false; } + BOOST_FOREACH(const Object::Ptr& pobj, parents) { + ConfigObject::Ptr parentObj = dynamic_pointer_cast(pobj); + + if (!parentObj) + continue; + + DeleteObjectHelper(parentObj, cascade, errors); + } + Type::Ptr type = object->GetReflectionType(); - + ConfigItem::Ptr item = ConfigItem::GetObject(type->GetName(), object->GetName()); try { @@ -172,7 +184,7 @@ bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, const Ar return false; } - + String typeDir = type->GetPluralName(); boost::algorithm::to_lower(typeDir); @@ -190,4 +202,16 @@ bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, const Ar return true; } - \ No newline at end of file + +bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors) +{ + if (object->GetModule() != "_api") { + if (errors) + errors->Add("Object cannot be deleted because it was not created using the API."); + + return false; + } + + return DeleteObjectHelper(object, cascade, errors); +} + diff --git a/lib/remote/configobjectutility.hpp b/lib/remote/configobjectutility.hpp index 476054052..f52ec8f7d 100644 --- a/lib/remote/configobjectutility.hpp +++ b/lib/remote/configobjectutility.hpp @@ -44,10 +44,11 @@ public: const Array::Ptr& templates, const Dictionary::Ptr& attrs, const Array::Ptr& errors); - static bool DeleteObject(const ConfigObject::Ptr& object, const Array::Ptr& errors); + static bool DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors); private: static String EscapeName(const String& name); + static bool DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors); }; } diff --git a/lib/remote/deleteobjecthandler.cpp b/lib/remote/deleteobjecthandler.cpp index 232e0de8a..854224e28 100644 --- a/lib/remote/deleteobjecthandler.cpp +++ b/lib/remote/deleteobjecthandler.cpp @@ -60,6 +60,8 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r std::vector objs = FilterUtility::GetFilterTargets(qd, params); + bool cascade = HttpUtility::GetLastParameter(params, "cascade"); + Array::Ptr results = new Array(); BOOST_FOREACH(const ConfigObject::Ptr& obj, objs) { @@ -70,9 +72,10 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r Array::Ptr errors = new Array(); - if (!ConfigObjectUtility::DeleteObject(obj, errors)) { + if (!ConfigObjectUtility::DeleteObject(obj, cascade, errors)) { result1->Set("code", 500); result1->Set("status", "Object could not be deleted."); + result1->Set("errors", errors); } else { result1->Set("code", 200); result1->Set("status", "Object was deleted.");