Add direct relationship updating to REST API
The JSON API specification states that all resources must support direct modification of resource relationships by providing only the definition for a particular relationship type to a /:type/:id/relationships/:type endpoint. The relevant part of the JSON API specification: http://jsonapi.org/format/#crud-updating-to-many-relationships
This commit is contained in:
parent
7111724851
commit
6918842585
@ -1415,11 +1415,46 @@ bool runtime_alter_server_from_json(SERVER* server, json_t* new_json)
|
||||
return rval;
|
||||
}
|
||||
|
||||
const char* object_relation_types[] =
|
||||
static bool is_valid_relationship_body(json_t* json)
|
||||
{
|
||||
MXS_JSON_PTR_RELATIONSHIPS_SERVERS,
|
||||
NULL
|
||||
};
|
||||
bool rval = true;
|
||||
|
||||
json_t* obj = mxs_json_pointer(json, MXS_JSON_PTR_DATA);
|
||||
|
||||
if (!obj)
|
||||
{
|
||||
runtime_error("Field '%s' is not defined", MXS_JSON_PTR_DATA);
|
||||
rval = false;
|
||||
}
|
||||
else if (!json_is_array(obj))
|
||||
{
|
||||
runtime_error("Field '%s' is not an array", MXS_JSON_PTR_DATA);
|
||||
rval = false;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool runtime_alter_server_relationships_from_json(SERVER* server, const char* type, json_t* json)
|
||||
{
|
||||
bool rval = false;
|
||||
mxs::Closer<json_t*> old_json(server_to_json(server, ""));
|
||||
ss_dassert(old_json.get());
|
||||
|
||||
if (is_valid_relationship_body(json))
|
||||
{
|
||||
mxs::Closer<json_t*> j(json_pack("{s: {s: {s: {s: O}}}}", "data",
|
||||
"relationships", type, "data",
|
||||
json_object_get(json, "data")));
|
||||
|
||||
if (server_to_object_relations(server, old_json.get(), j.get()))
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static bool object_relation_is_valid(const std::string& type, const std::string& value)
|
||||
{
|
||||
@ -1624,6 +1659,48 @@ bool runtime_alter_monitor_from_json(MXS_MONITOR* monitor, json_t* new_json)
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool runtime_alter_monitor_relationships_from_json(MXS_MONITOR* monitor, json_t* json)
|
||||
{
|
||||
bool rval = false;
|
||||
mxs::Closer<json_t*> old_json(monitor_to_json(monitor, ""));
|
||||
ss_dassert(old_json.get());
|
||||
|
||||
if (is_valid_relationship_body(json))
|
||||
{
|
||||
mxs::Closer<json_t*> j(json_pack("{s: {s: {s: {s: O}}}}", "data",
|
||||
"relationships", "servers", "data",
|
||||
json_object_get(json, "data")));
|
||||
|
||||
if (object_to_server_relations(monitor->name, old_json.get(), j.get()))
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool runtime_alter_service_relationships_from_json(SERVICE* service, json_t* json)
|
||||
{
|
||||
bool rval = false;
|
||||
mxs::Closer<json_t*> old_json(service_to_json(service, ""));
|
||||
ss_dassert(old_json.get());
|
||||
|
||||
if (is_valid_relationship_body(json))
|
||||
{
|
||||
mxs::Closer<json_t*> j(json_pack("{s: {s: {s: {s: O}}}}", "data",
|
||||
"relationships", "servers", "data",
|
||||
json_object_get(json, "data")));
|
||||
|
||||
if (object_to_server_relations(service->name, old_json.get(), j.get()))
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the service parameter can be altered at runtime
|
||||
*
|
||||
|
@ -220,6 +220,17 @@ SERVER* runtime_create_server_from_json(json_t* json);
|
||||
*/
|
||||
bool runtime_alter_server_from_json(SERVER* server, json_t* new_json);
|
||||
|
||||
/**
|
||||
* @brief Alter server relationships
|
||||
*
|
||||
* @param server Server to alter
|
||||
* @param type Type of the relation, either @c services or @c monitors
|
||||
* @param json JSON that defines the relationship data
|
||||
*
|
||||
* @return True if the relationships were successfully modified
|
||||
*/
|
||||
bool runtime_alter_server_relationships_from_json(SERVER* server, const char* type, json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Create a new monitor from JSON
|
||||
*
|
||||
@ -239,6 +250,16 @@ MXS_MONITOR* runtime_create_monitor_from_json(json_t* json);
|
||||
*/
|
||||
bool runtime_alter_monitor_from_json(MXS_MONITOR* monitor, json_t* new_json);
|
||||
|
||||
/**
|
||||
* @brief Alter monitor relationships
|
||||
*
|
||||
* @param monitor Monitor to alter
|
||||
* @param json JSON that defines the new relationships
|
||||
*
|
||||
* @return True if the relationships were successfully modified
|
||||
*/
|
||||
bool runtime_alter_monitor_relationships_from_json(MXS_MONITOR* monitor, json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Alter a service using JSON
|
||||
*
|
||||
@ -249,6 +270,16 @@ bool runtime_alter_monitor_from_json(MXS_MONITOR* monitor, json_t* new_json);
|
||||
*/
|
||||
bool runtime_alter_service_from_json(SERVICE* service, json_t* new_json);
|
||||
|
||||
/**
|
||||
* @brief Alter service relationships
|
||||
*
|
||||
* @param service Service to alter
|
||||
* @param json JSON that defines the new relationships
|
||||
*
|
||||
* @return True if the relationships were successfully modified
|
||||
*/
|
||||
bool runtime_alter_service_relationships_from_json(SERVICE* service, json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Create a listener from JSON
|
||||
*
|
||||
|
@ -285,6 +285,29 @@ HttpResponse cb_alter_server(const HttpRequest& request)
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
|
||||
}
|
||||
|
||||
HttpResponse do_alter_server_relationship(const HttpRequest& request, const char* type)
|
||||
{
|
||||
SERVER* server = server_find_by_unique_name(request.uri_part(1).c_str());
|
||||
ss_dassert(server && request.get_json());
|
||||
|
||||
if (runtime_alter_server_relationships_from_json(server, type, request.get_json()))
|
||||
{
|
||||
return HttpResponse(MHD_HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
|
||||
}
|
||||
|
||||
HttpResponse cb_alter_server_service_relationship(const HttpRequest& request)
|
||||
{
|
||||
return do_alter_server_relationship(request, "services");
|
||||
}
|
||||
|
||||
HttpResponse cb_alter_server_monitor_relationship(const HttpRequest& request)
|
||||
{
|
||||
return do_alter_server_relationship(request, "monitors");
|
||||
}
|
||||
|
||||
HttpResponse cb_create_monitor(const HttpRequest& request)
|
||||
{
|
||||
ss_dassert(request.get_json());
|
||||
@ -323,6 +346,19 @@ HttpResponse cb_alter_monitor(const HttpRequest& request)
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
|
||||
}
|
||||
|
||||
HttpResponse cb_alter_monitor_server_relationship(const HttpRequest& request)
|
||||
{
|
||||
MXS_MONITOR* monitor = monitor_find(request.uri_part(1).c_str());
|
||||
ss_dassert(monitor && request.get_json());
|
||||
|
||||
if (runtime_alter_monitor_relationships_from_json(monitor, request.get_json()))
|
||||
{
|
||||
return HttpResponse(MHD_HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
|
||||
}
|
||||
|
||||
HttpResponse cb_alter_service(const HttpRequest& request)
|
||||
{
|
||||
SERVICE* service = service_find(request.uri_part(1).c_str());
|
||||
@ -336,6 +372,19 @@ HttpResponse cb_alter_service(const HttpRequest& request)
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
|
||||
}
|
||||
|
||||
HttpResponse cb_alter_service_server_relationship(const HttpRequest& request)
|
||||
{
|
||||
SERVICE* service = service_find(request.uri_part(1).c_str());
|
||||
ss_dassert(service && request.get_json());
|
||||
|
||||
if (runtime_alter_service_relationships_from_json(service, request.get_json()))
|
||||
{
|
||||
return HttpResponse(MHD_HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
|
||||
}
|
||||
|
||||
HttpResponse cb_alter_logs(const HttpRequest& request)
|
||||
{
|
||||
ss_dassert(request.get_json());
|
||||
@ -792,6 +841,16 @@ public:
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_logs, 2, "maxscale", "logs")));
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_maxscale, 1, "maxscale")));
|
||||
|
||||
/** Update resource relationships directly */
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_server_service_relationship, 4,
|
||||
"servers", ":server", "relationships", "services")));
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_server_monitor_relationship, 4,
|
||||
"servers", ":server", "relationships", "monitors")));
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_monitor_server_relationship, 4,
|
||||
"monitors", ":monitor", "relationships", "servers")));
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_service_server_relationship, 4,
|
||||
"services", ":service", "relationships", "servers")));
|
||||
|
||||
/** All patch resources require a request body */
|
||||
for (ResourceList::iterator it = m_patch.begin(); it != m_patch.end(); it++)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user