1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
#include "remote/createobjecthandler.hpp"
#include "remote/configobjectutility.hpp"
#include "remote/httputility.hpp"
#include "remote/jsonrpcconnection.hpp"
#include "remote/filterutility.hpp"
#include "remote/apiaction.hpp"
#include "remote/zone.hpp"
#include "base/configtype.hpp"
#include <set>
using namespace icinga;
REGISTER_URLHANDLER("/v1/objects", CreateObjectHandler);
bool CreateObjectHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
HttpServerConnection& server
)
{
namespace http = boost::beast::http;
if (url->GetPath().size() != 4)
return false;
if (request.method() != http::verb::put)
return false;
Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]);
if (!type) {
HttpUtility::SendJsonError(response, params, 400, "Invalid type specified.");
return true;
}
FilterUtility::CheckPermission(user, "objects/create/" + type->GetName());
String name = url->GetPath()[3];
Array::Ptr templates = params->Get("templates");
Dictionary::Ptr attrs = params->Get("attrs");
/* Put created objects into the local zone if not explicitly defined.
* This allows additional zone members to sync the
* configuration at some later point.
*/
Zone::Ptr localZone = Zone::GetLocalZone();
String localZoneName;
if (localZone) {
localZoneName = localZone->GetName();
if (!attrs) {
attrs = new Dictionary({
{ "zone", localZoneName }
});
} else if (!attrs->Contains("zone")) {
attrs->Set("zone", localZoneName);
}
}
/* Sanity checks for unique groups array. */
if (attrs->Contains("groups")) {
Array::Ptr groups = attrs->Get("groups");
if (groups)
attrs->Set("groups", groups->Unique());
}
Dictionary::Ptr result1 = new Dictionary();
String status;
Array::Ptr errors = new Array();
Array::Ptr diagnosticInformation = new Array();
bool ignoreOnError = false;
if (params->Contains("ignore_on_error"))
ignoreOnError = HttpUtility::GetLastParameter(params, "ignore_on_error");
Dictionary::Ptr result = new Dictionary({
{ "results", new Array({ result1 }) }
});
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, false));
diagnosticInformation->Add(DiagnosticInformation(ex));
if (verbose)
result1->Set("diagnostic_information", diagnosticInformation);
result1->Set("errors", errors);
result1->Set("code", 500);
result1->Set("status", "Object could not be created.");
response.result(http::status::internal_server_error);
HttpUtility::SendJsonBody(response, params, result);
return true;
}
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.result(http::status::internal_server_error);
HttpUtility::SendJsonBody(response, params, result);
return true;
}
auto *ctype = dynamic_cast<ConfigType *>(type.get());
ConfigObject::Ptr obj = ctype->GetObject(name);
result1->Set("code", 200);
if (obj)
result1->Set("status", "Object was created");
else if (!obj && ignoreOnError)
result1->Set("status", "Object was not created but 'ignore_on_error' was set to true");
response.result(http::status::ok);
HttpUtility::SendJsonBody(response, params, result);
return true;
}
|