Add diagnostic_information as verbose error to config object handlers

This commit is contained in:
Michael Friedrich 2018-04-06 12:26:49 +02:00
parent a00197e919
commit c4a6ab0211
8 changed files with 78 additions and 33 deletions

View File

@ -182,7 +182,7 @@ String Comment::AddComment(const Checkable::Ptr& checkable, CommentType entryTyp
Array::Ptr errors = new Array(); 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); ObjectLock olock(errors);
for (const String& error : errors) { for (const String& error : errors) {
Log(LogCritical, "Comment", error); Log(LogCritical, "Comment", error);
@ -214,7 +214,7 @@ void Comment::RemoveComment(const String& id, const MessageOrigin::Ptr& origin)
Array::Ptr errors = new Array(); Array::Ptr errors = new Array();
if (!ConfigObjectUtility::DeleteObject(comment, false, errors)) { if (!ConfigObjectUtility::DeleteObject(comment, false, errors, nullptr)) {
ObjectLock olock(errors); ObjectLock olock(errors);
for (const String& error : errors) { for (const String& error : errors) {
Log(LogCritical, "Comment", error); Log(LogCritical, "Comment", error);

View File

@ -256,7 +256,7 @@ String Downtime::AddDowntime(const Checkable::Ptr& checkable, const String& auth
Array::Ptr errors = new Array(); 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); ObjectLock olock(errors);
for (const String& error : errors) { for (const String& error : errors) {
Log(LogCritical, "Downtime", error); Log(LogCritical, "Downtime", error);
@ -309,7 +309,7 @@ void Downtime::RemoveDowntime(const String& id, bool cancelled, bool expired, co
Array::Ptr errors = new Array(); Array::Ptr errors = new Array();
if (!ConfigObjectUtility::DeleteObject(downtime, false, errors)) { if (!ConfigObjectUtility::DeleteObject(downtime, false, errors, nullptr)) {
ObjectLock olock(errors); ObjectLock olock(errors);
for (const String& error : errors) { for (const String& error : errors) {
Log(LogCritical, "Downtime", error); Log(LogCritical, "Downtime", error);

View File

@ -116,15 +116,14 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
/* object does not exist, create it through the API */ /* object does not exist, create it through the API */
Array::Ptr errors = new Array(); Array::Ptr errors = new Array();
if (!ConfigObjectUtility::CreateObject(ptype, if (!ConfigObjectUtility::CreateObject(ptype, objName, config, errors, nullptr)) {
objName, config, errors)) {
Log(LogCritical, "ApiListener") Log(LogCritical, "ApiListener")
<< "Could not create object '" << objName << "':"; << "Could not create object '" << objName << "':";
ObjectLock olock(errors); ObjectLock olock(errors);
for (const String& error : errors) { for (const String& error : errors) {
Log(LogCritical, "ApiListener", error); Log(LogCritical, "ApiListener", error);
} }
return Empty; return Empty;
} }
@ -256,7 +255,7 @@ Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin
Array::Ptr errors = new Array(); 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:"); Log(LogCritical, "ApiListener", "Could not delete object:");
ObjectLock olock(errors); ObjectLock olock(errors);

View File

@ -98,7 +98,7 @@ String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const Stri
} }
bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& fullName, 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()); 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); Utility::MkDirP(Utility::DirName(path), 0700);
if (Utility::PathExists(path)) { if (Utility::PathExists(path)) {
errors->Add("Configuration file '" + path + "' already exists."); errors->Add("Cannot create object '" + fullName + "'. Configuration file '" + path + "' already exists.");
return false; return false;
} }
@ -144,7 +144,10 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
} }
for (const boost::exception_ptr& ex : upq.GetExceptions()) { 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) if (errors)
errors->Add(DiagnosticInformation(ex)); errors->Add(DiagnosticInformation(ex, false));
if (diagnosticInformation)
diagnosticInformation->Add(DiagnosticInformation(ex));
return false; return false;
} }
@ -169,17 +175,21 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full
return true; 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); std::vector<Object::Ptr> parents = DependencyGraph::GetParents(object);
Type::Ptr type = object->GetReflectionType(); Type::Ptr type = object->GetReflectionType();
String name = object->GetName();
if (!parents.empty() && !cascade) { if (!parents.empty() && !cascade) {
if (errors) if (errors) {
errors->Add("Object '" + object->GetName() + "' of type '" + type->GetName() + errors->Add("Object '" + name + "' of type '" + type->GetName() +
"' cannot be deleted because other objects depend on it. " "' cannot be deleted because other objects depend on it. "
"Use cascading delete to delete it anyway."); "Use cascading delete to delete it anyway.");
}
return false; return false;
} }
@ -190,10 +200,10 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
if (!parentObj) if (!parentObj)
continue; 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 { try {
/* mark this object for cluster delete event */ /* mark this object for cluster delete event */
@ -208,12 +218,15 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
if (errors) if (errors)
errors->Add(DiagnosticInformation(ex)); errors->Add(DiagnosticInformation(ex, false));
if (diagnosticInformation)
diagnosticInformation->Add(DiagnosticInformation(ex));
return false; return false;
} }
String path = GetObjectConfigPath(object->GetReflectionType(), object->GetName()); String path = GetObjectConfigPath(object->GetReflectionType(), name);
if (Utility::PathExists(path)) { if (Utility::PathExists(path)) {
if (unlink(path.CStr()) < 0 && errno != ENOENT) { if (unlink(path.CStr()) < 0 && errno != ENOENT) {
@ -227,7 +240,7 @@ bool ConfigObjectUtility::DeleteObjectHelper(const ConfigObject::Ptr& object, bo
return true; 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 (object->GetPackage() != "_api") {
if (errors) if (errors)
@ -236,5 +249,5 @@ bool ConfigObjectUtility::DeleteObject(const ConfigObject::Ptr& object, bool cas
return false; return false;
} }
return DeleteObjectHelper(object, cascade, errors); return DeleteObjectHelper(object, cascade, errors, diagnosticInformation);
} }

View File

@ -45,13 +45,15 @@ public:
bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs); bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs);
static bool CreateObject(const Type::Ptr& type, const String& fullName, 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: private:
static String EscapeName(const String& name); 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);
}; };
} }

View File

@ -74,6 +74,7 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
Dictionary::Ptr result1 = new Dictionary(); Dictionary::Ptr result1 = new Dictionary();
String status; String status;
Array::Ptr errors = new Array(); Array::Ptr errors = new Array();
Array::Ptr diagnosticInformation = new Array();
bool ignoreOnError = false; bool ignoreOnError = false;
@ -86,10 +87,22 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
String config; 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 { try {
config = ConfigObjectUtility::CreateObjectConfig(type, name, ignoreOnError, templates, attrs); config = ConfigObjectUtility::CreateObjectConfig(type, name, ignoreOnError, templates, attrs);
} catch (const std::exception& ex) { } 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("errors", errors);
result1->Set("code", 500); result1->Set("code", 500);
@ -101,11 +114,14 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
return true; return true;
} }
if (!ConfigObjectUtility::CreateObject(type, name, config, errors)) { if (!ConfigObjectUtility::CreateObject(type, name, config, errors, diagnosticInformation)) {
result1->Set("errors", errors); result1->Set("errors", errors);
result1->Set("code", 500); result1->Set("code", 500);
result1->Set("status", "Object could not be created."); result1->Set("status", "Object could not be created.");
if (verbose)
result1->Set("diagnostic_information", diagnosticInformation);
response.SetStatus(500, "Object could not be created"); response.SetStatus(500, "Object could not be created");
HttpUtility::SendJsonBody(response, params, result); HttpUtility::SendJsonBody(response, params, result);

View File

@ -65,11 +65,12 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
HttpUtility::SendJsonError(response, params, 404, HttpUtility::SendJsonError(response, params, 404,
"No objects found.", "No objects found.",
HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); DiagnosticInformation(ex));
return true; return true;
} }
bool cascade = HttpUtility::GetLastParameter(params, "cascade"); bool cascade = HttpUtility::GetLastParameter(params, "cascade");
bool verbose = HttpUtility::GetLastParameter(params, "verbose");
ArrayData results; ArrayData results;
@ -79,8 +80,9 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
int code; int code;
String status; String status;
Array::Ptr errors = new Array(); 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; code = 500;
status = "Object could not be deleted."; status = "Object could not be deleted.";
success = false; success = false;
@ -89,13 +91,18 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
status = "Object was deleted."; status = "Object was deleted.";
} }
results.push_back(new Dictionary({ Dictionary::Ptr result = new Dictionary({
{ "type", type->GetName() }, { "type", type->GetName() },
{ "name", obj->GetName() }, { "name", obj->GetName() },
{ "code", code }, { "code", code },
{ "status", status }, { "status", status },
{ "errors", errors } { "errors", errors }
})); });
if (verbose)
result->Set("diagnostic_information", diagnosticInformation);
results.push_back(result);
} }
Dictionary::Ptr result = new Dictionary({ Dictionary::Ptr result = new Dictionary({

View File

@ -77,6 +77,11 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
Dictionary::Ptr attrs = attrsVal; Dictionary::Ptr attrs = attrsVal;
bool verbose = false;
if (params)
verbose = HttpUtility::GetLastParameter(params, "verbose");
ArrayData results; ArrayData results;
for (const ConfigObject::Ptr& obj : objs) { for (const ConfigObject::Ptr& obj : objs) {
@ -100,7 +105,10 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
result1->Set("status", "Attributes updated."); result1->Set("status", "Attributes updated.");
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
result1->Set("code", 500); 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)); results.push_back(std::move(result1));