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);
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);
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);
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);
/* 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;
}
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);
}
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());
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;
}
}
for (const boost::exception_ptr& ex : upq.GetExceptions()) {
- errors->Add(DiagnosticInformation(ex));
+ errors->Add(DiagnosticInformation(ex, false));
+
+ if (diagnosticInformation)
+ diagnosticInformation->Add(DiagnosticInformation(ex));
}
}
}
if (errors)
- errors->Add(DiagnosticInformation(ex));
+ errors->Add(DiagnosticInformation(ex, false));
+
+ if (diagnosticInformation)
+ diagnosticInformation->Add(DiagnosticInformation(ex));
return false;
}
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;
}
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 */
} 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) {
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)
return false;
}
- return DeleteObjectHelper(object, cascade, errors);
+ return DeleteObjectHelper(object, cascade, errors, diagnosticInformation);
}
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);
};
}
Dictionary::Ptr result1 = new Dictionary();
String status;
Array::Ptr errors = new Array();
+ Array::Ptr diagnosticInformation = new Array();
bool ignoreOnError = false;
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);
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);
} 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;
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;
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({
Dictionary::Ptr attrs = attrsVal;
+ bool verbose = false;
+
+ if (params)
+ verbose = HttpUtility::GetLastParameter(params, "verbose");
+
ArrayData results;
for (const ConfigObject::Ptr& obj : objs) {
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));