]> granicus.if.org Git - icinga2/commitdiff
Add diagnostic_information as verbose error to config object handlers
authorMichael Friedrich <michael.friedrich@icinga.com>
Fri, 6 Apr 2018 10:26:49 +0000 (12:26 +0200)
committerMichael Friedrich <michael.friedrich@icinga.com>
Fri, 6 Apr 2018 10:26:49 +0000 (12:26 +0200)
lib/icinga/comment.cpp
lib/icinga/downtime.cpp
lib/remote/apilistener-configsync.cpp
lib/remote/configobjectutility.cpp
lib/remote/configobjectutility.hpp
lib/remote/createobjecthandler.cpp
lib/remote/deleteobjecthandler.cpp
lib/remote/modifyobjecthandler.cpp

index c23e1461907b2547b34e0cd4f50210a391b5974d..9931b42bddcbd786c0b06b50e5a59798b350c849 100644 (file)
@@ -182,7 +182,7 @@ String Comment::AddComment(const Checkable::Ptr& checkable, CommentType entryTyp
 
        Array::Ptr errors = new Array();
 
-       if (!ConfigObjectUtility::CreateObject(Comment::TypeInstance, fullName, config, errors)) {
+       if (!ConfigObjectUtility::CreateObject(Comment::TypeInstance, fullName, config, errors, nullptr)) {
                ObjectLock olock(errors);
                for (const String& error : errors) {
                        Log(LogCritical, "Comment", error);
@@ -214,7 +214,7 @@ void Comment::RemoveComment(const String& id, const MessageOrigin::Ptr& origin)
 
        Array::Ptr errors = new Array();
 
-       if (!ConfigObjectUtility::DeleteObject(comment, false, errors)) {
+       if (!ConfigObjectUtility::DeleteObject(comment, false, errors, nullptr)) {
                ObjectLock olock(errors);
                for (const String& error : errors) {
                        Log(LogCritical, "Comment", error);
index a52358359128ce271cb652b4449f119e30f534f0..73e41c2a8ac2786909574d78ff979a18503a6066 100644 (file)
@@ -256,7 +256,7 @@ String Downtime::AddDowntime(const Checkable::Ptr& checkable, const String& auth
 
        Array::Ptr errors = new Array();
 
-       if (!ConfigObjectUtility::CreateObject(Downtime::TypeInstance, fullName, config, errors)) {
+       if (!ConfigObjectUtility::CreateObject(Downtime::TypeInstance, fullName, config, errors, nullptr)) {
                ObjectLock olock(errors);
                for (const String& error : errors) {
                        Log(LogCritical, "Downtime", error);
@@ -309,7 +309,7 @@ void Downtime::RemoveDowntime(const String& id, bool cancelled, bool expired, co
 
        Array::Ptr errors = new Array();
 
-       if (!ConfigObjectUtility::DeleteObject(downtime, false, errors)) {
+       if (!ConfigObjectUtility::DeleteObject(downtime, false, errors, nullptr)) {
                ObjectLock olock(errors);
                for (const String& error : errors) {
                        Log(LogCritical, "Downtime", error);
index 067e2819ceba466d97543f9ee60d35680ab581f4..12c91065ec8cbe71fbc75514e5c0a7959e35079c 100644 (file)
@@ -116,15 +116,14 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
                /* object does not exist, create it through the API */
                Array::Ptr errors = new Array();
 
-               if (!ConfigObjectUtility::CreateObject(ptype,
-                       objName, config, errors)) {
+               if (!ConfigObjectUtility::CreateObject(ptype, objName, config, errors, nullptr)) {
                        Log(LogCritical, "ApiListener")
                                << "Could not create object '" << objName << "':";
 
-                               ObjectLock olock(errors);
+                       ObjectLock olock(errors);
                        for (const String& error : errors) {
-                                       Log(LogCritical, "ApiListener", error);
-                               }
+                               Log(LogCritical, "ApiListener", error);
+                       }
 
                        return Empty;
                }
@@ -256,7 +255,7 @@ Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin
 
        Array::Ptr errors = new Array();
 
-       if (!ConfigObjectUtility::DeleteObject(object, true, errors)) {
+       if (!ConfigObjectUtility::DeleteObject(object, true, errors, nullptr)) {
                Log(LogCritical, "ApiListener", "Could not delete object:");
 
                ObjectLock olock(errors);
index 38fda3824f95b66c04cb4a0f31555e45e9828274..3ad88c675453ae279bc3f88f46b27b35b2c1c1c8 100644 (file)
@@ -98,7 +98,7 @@ String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const Stri
 }
 
 bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& fullName,
-       const String& config, const Array::Ptr& errors)
+       const String& config, const Array::Ptr& errors, const Array::Ptr& diagnosticInformation)
 {
        {
                boost::mutex::scoped_lock lock(ConfigPackageUtility::GetStaticMutex());
@@ -114,7 +114,7 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
        Utility::MkDirP(Utility::DirName(path), 0700);
 
        if (Utility::PathExists(path)) {
-               errors->Add("Configuration file '" + path + "' already exists.");
+               errors->Add("Cannot create object '" + fullName + "'. Configuration file '" + path + "' already exists.");
                return false;
        }
 
@@ -144,7 +144,10 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
                                }
 
                                for (const boost::exception_ptr& ex : upq.GetExceptions()) {
-                                       errors->Add(DiagnosticInformation(ex));
+                                       errors->Add(DiagnosticInformation(ex, false));
+
+                                       if (diagnosticInformation)
+                                               diagnosticInformation->Add(DiagnosticInformation(ex));
                                }
                        }
 
@@ -161,7 +164,10 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
                }
 
                if (errors)
-                       errors->Add(DiagnosticInformation(ex));
+                       errors->Add(DiagnosticInformation(ex, false));
+
+               if (diagnosticInformation)
+                       diagnosticInformation->Add(DiagnosticInformation(ex));
 
                return false;
        }
@@ -169,17 +175,21 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
        return true;
 }
 
-bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors)
+bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade,
+       const Array::Ptr& errors, const Array::Ptr& diagnosticInformation)
 {
        std::vector<Object::Ptr> parents = DependencyGraph::GetParents(object);
 
        Type::Ptr type = object->GetReflectionType();
 
+       String name = object->GetName();
+
        if (!parents.empty() && !cascade) {
-               if (errors)
-                       errors->Add("Object '" + object->GetName() + "' of type '" + type->GetName() +
+               if (errors) {
+                       errors->Add("Object '" + name + "' of type '" + type->GetName() +
                                "' cannot be deleted because other objects depend on it. "
                                "Use cascading delete to delete it anyway.");
+               }
 
                return false;
        }
@@ -190,10 +200,10 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
                if (!parentObj)
                        continue;
 
-               DeleteObjectHelper(parentObj, cascade, errors);
+               DeleteObjectHelper(parentObj, cascade, errors, diagnosticInformation);
        }
 
-       ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(type, object->GetName());
+       ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(type, name);
 
        try {
                /* mark this object for cluster delete event */
@@ -208,12 +218,15 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
 
        } catch (const std::exception& ex) {
                if (errors)
-                       errors->Add(DiagnosticInformation(ex));
+                       errors->Add(DiagnosticInformation(ex, false));
+
+               if (diagnosticInformation)
+                       diagnosticInformation->Add(DiagnosticInformation(ex));
 
                return false;
        }
 
-       String path = GetObjectConfigPath(object->GetReflectionType(), object->GetName());
+       String path = GetObjectConfigPath(object->GetReflectionType(), name);
 
        if (Utility::PathExists(path)) {
                if (unlink(path.CStr()) < 0 && errno != ENOENT) {
@@ -227,7 +240,7 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
        return true;
 }
 
-bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors)
+bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors, const Array::Ptr& diagnosticInformation)
 {
        if (object->GetPackage() != "_api") {
                if (errors)
@@ -236,5 +249,5 @@ bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, bool cas
                return false;
        }
 
-       return DeleteObjectHelper(object, cascade, errors);
+       return DeleteObjectHelper(object, cascade, errors, diagnosticInformation);
 }
index ea42ff3f29a4b2207c41ad90ddd1989b51ffaed4..472af3c83559896abfa3758abe0f2271353c53c9 100644 (file)
@@ -45,13 +45,15 @@ public:
                bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs);
 
        static bool CreateObject(const Type::Ptr& type, const String& fullName,
-               const String& config, const Array::Ptr& errors);
+               const String& config, const Array::Ptr& errors, const Array::Ptr& diagnosticInformation);
 
-       static bool DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors);
+       static bool DeleteObject(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors,
+               const Array::Ptr& diagnosticInformation);
 
 private:
        static String EscapeName(const String& name);
-       static bool DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors);
+       static bool DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors,
+               const Array::Ptr& diagnosticInformation);
 };
 
 }
index ff90317af6089b4ab7a6e62747ed17201de146d3..e3646b3f3df46b1342f70aacf9a317a2a3200064 100644 (file)
@@ -74,6 +74,7 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
        Dictionary::Ptr result1 = new Dictionary();
        String status;
        Array::Ptr errors = new Array();
+       Array::Ptr diagnosticInformation = new Array();
 
        bool ignoreOnError = false;
 
@@ -86,10 +87,22 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
 
        String config;
 
+       bool verbose = false;
+
+       if (params)
+               verbose = HttpUtility::GetLastParameter(params, "verbose");
+
+       /* Object creation can cause multiple errors and optionally diagnostic information.
+        * We can't use SendJsonError() here.
+        */
        try {
                config = ConfigObjectUtility::CreateObjectConfig(type, name, ignoreOnError, templates, attrs);
        } catch (const std::exception& ex) {
-               errors->Add(DiagnosticInformation(ex));
+               errors->Add(DiagnosticInformation(ex, false));
+               diagnosticInformation->Add(DiagnosticInformation(ex));
+
+               if (verbose)
+                       result1->Set("diagnostic_information", diagnosticInformation);
 
                result1->Set("errors", errors);
                result1->Set("code", 500);
@@ -101,11 +114,14 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
                return true;
        }
 
-       if (!ConfigObjectUtility::CreateObject(type, name, config, errors)) {
+       if (!ConfigObjectUtility::CreateObject(type, name, config, errors, diagnosticInformation)) {
                result1->Set("errors", errors);
                result1->Set("code", 500);
                result1->Set("status", "Object could not be created.");
 
+               if (verbose)
+                       result1->Set("diagnostic_information", diagnosticInformation);
+
                response.SetStatus(500, "Object could not be created");
                HttpUtility::SendJsonBody(response, params, result);
 
index 027f62fed77fcbe7dfbf2413bb7905138d217df5..0d4053df34c017e116770d5c95d84361f28f7236 100644 (file)
@@ -65,11 +65,12 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
        } catch (const std::exception& ex) {
                HttpUtility::SendJsonError(response, params, 404,
                        "No objects found.",
-                       HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : "");
+                       DiagnosticInformation(ex));
                return true;
        }
 
        bool cascade = HttpUtility::GetLastParameter(params, "cascade");
+       bool verbose = HttpUtility::GetLastParameter(params, "verbose");
 
        ArrayData results;
 
@@ -79,8 +80,9 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
                int code;
                String status;
                Array::Ptr errors = new Array();
+               Array::Ptr diagnosticInformation = new Array();
 
-               if (!ConfigObjectUtility::DeleteObject(obj, cascade, errors)) {
+               if (!ConfigObjectUtility::DeleteObject(obj, cascade, errors, diagnosticInformation)) {
                        code = 500;
                        status = "Object could not be deleted.";
                        success = false;
@@ -89,13 +91,18 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
                        status = "Object was deleted.";
                }
 
-               results.push_back(new Dictionary({
+               Dictionary::Ptr result = new Dictionary({
                        { "type", type->GetName() },
                        { "name", obj->GetName() },
                        { "code", code },
                        { "status", status },
                        { "errors", errors }
-               }));
+               });
+
+               if (verbose)
+                       result->Set("diagnostic_information", diagnosticInformation);
+
+               results.push_back(result);
        }
 
        Dictionary::Ptr result = new Dictionary({
index 8933606710b5c5deb17837d9fc9c46fd54636903..603207ebb80836c246b60beb58cdcdf544e6fe9c 100644 (file)
@@ -77,6 +77,11 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
 
        Dictionary::Ptr attrs = attrsVal;
 
+       bool verbose = false;
+
+       if (params)
+               verbose = HttpUtility::GetLastParameter(params, "verbose");
+
        ArrayData results;
 
        for (const ConfigObject::Ptr& obj : objs) {
@@ -100,7 +105,10 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
                        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));
+                       result1->Set("status", "Attribute '" + key + "' could not be set: " + DiagnosticInformation(ex, false));
+
+                       if (verbose)
+                               result1->Set("diagnostic_information", DiagnosticInformation(ex));
                }
 
                results.push_back(std::move(result1));