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();
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);

View 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);

View 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);

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,
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);
}

View 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);
};
}

View 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);

View 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({

View 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));