MXS-1220: Fix resource self links

The top level resource self links pointed to the collection instead of the
resource itself. The individual resoures now also have a links field that
contains the self link to the resource. This should make navigation of the
API easier as all objects have valid links in them.
This commit is contained in:
Markus Mäkelä 2017-05-09 09:32:21 +03:00
parent 9fee283a3f
commit 157b7f853b
10 changed files with 98 additions and 19 deletions

View File

@ -65,6 +65,19 @@ json_t* mxs_json_relationship(const char* host, const char* endpoint);
*/
void mxs_json_add_relation(json_t* rel, const char* id, const char* type);
/**
* @brief Create self link object
*
* The self link points to the object itself.
*
* @param host Hostname of this server
* @param path Base path to the resource collection
* @param id The identified of this resource
*
* @return New self link object
*/
json_t* mxs_json_self_link(const char* host, const char* path, const char* id);
/**
* @brief Return value at provided JSON Pointer
*

View File

@ -526,13 +526,16 @@ json_t* filter_json_data(const MXS_FILTER_DEF* filter, const char* host)
json_object_set_new(rval, CN_RELATIONSHIPS, rel);
json_object_set_new(rval, CN_ATTRIBUTES, attr);
json_object_set_new(rval, CN_LINKS, mxs_json_self_link(host, CN_FILTERS, filter->name));
return rval;
}
json_t* filter_to_json(const MXS_FILTER_DEF* filter, const char* host)
{
return mxs_json_resource(host, MXS_JSON_API_FILTERS, filter_json_data(filter, host));
string self = MXS_JSON_API_FILTERS;
self += filter->name;
return mxs_json_resource(host, self.c_str(), filter_json_data(filter, host));
}
json_t* filter_list_to_json(const char* host)

View File

@ -131,3 +131,17 @@ json_t* mxs_json_pointer(json_t* json, const char* json_ptr)
{
return mxs_json_pointer_internal(json, json_ptr);
}
json_t* mxs_json_self_link(const char* host, const char* path, const char* id)
{
json_t* links = json_object();
string self = host;
self += "/";
self += path;
self += "/";
self += id;
json_object_set_new(links, CN_SELF, json_string(self.c_str()));
return links;
}

View File

@ -453,6 +453,7 @@ static json_t* module_json_data(const LOADED_MODULE *mod, const char* host)
json_object_set_new(attr, CN_PARAMETERS, params);
json_object_set_new(obj, CN_ATTRIBUTES, attr);
json_object_set_new(obj, CN_LINKS, mxs_json_self_link(host, CN_MODULES, mod->module));
return obj;
}

View File

@ -1544,13 +1544,16 @@ json_t* monitor_json_data(const MXS_MONITOR* monitor, const char* host)
json_object_set_new(rval, CN_RELATIONSHIPS, rel);
json_object_set_new(rval, CN_ATTRIBUTES, attr);
json_object_set_new(rval, CN_LINKS, mxs_json_self_link(host, CN_MONITORS, monitor->name));
return rval;
}
json_t* monitor_to_json(const MXS_MONITOR* monitor, const char* host)
{
return mxs_json_resource(host, MXS_JSON_API_MONITORS, monitor_json_data(monitor, host));
string self = MXS_JSON_API_MONITORS;
self += monitor->name;
return mxs_json_resource(host, self.c_str(), monitor_json_data(monitor, host));
}
json_t* monitor_list_to_json(const char* host)

View File

@ -1361,16 +1361,6 @@ bool server_is_mxs_service(const SERVER *server)
return rval;
}
json_t* server_self_link(const char* host)
{
json_t* links = json_object();
string self = host;
self += "/servers/";
json_object_set_new(links, CN_SELF, json_string(self.c_str()));
return links;
}
static json_t* server_json_attributes(const SERVER* server)
{
/** Resource attributes */
@ -1468,16 +1458,18 @@ static json_t* server_to_json_data(const SERVER* server, const char* host)
json_object_set_new(rel, CN_SERVICES, service_relations_to_server(server, host));
json_object_set_new(rel, CN_MONITORS, monitor_relations_to_server(server, host));
json_object_set_new(rval, CN_RELATIONSHIPS, rel);
/** Attributes */
json_object_set_new(rval, CN_ATTRIBUTES, server_json_attributes(server));
json_object_set_new(rval, CN_LINKS, mxs_json_self_link(host, CN_SERVERS, server->unique_name));
return rval;
}
json_t* server_to_json(const SERVER* server, const char* host)
{
return mxs_json_resource(host, MXS_JSON_API_SERVERS, server_to_json_data(server, host));
string self = MXS_JSON_API_SERVERS;
self += server->unique_name;
return mxs_json_resource(host, self.c_str(), server_to_json_data(server, host));
}
json_t* server_list_to_json(const char* host)

View File

@ -2575,6 +2575,7 @@ json_t* service_json_data(const SERVICE* service, const char* host)
json_object_set_new(rval, CN_TYPE, json_string(CN_SERVICES));
json_object_set_new(rval, CN_ATTRIBUTES, service_attributes(service));
json_object_set_new(rval, CN_RELATIONSHIPS, service_relationships(service, host));
json_object_set_new(rval, CN_LINKS, mxs_json_self_link(host, CN_SERVICES, service->name));
spinlock_release(&service->spin);
@ -2583,7 +2584,9 @@ json_t* service_json_data(const SERVICE* service, const char* host)
json_t* service_to_json(const SERVICE* service, const char* host)
{
return mxs_json_resource(host, MXS_JSON_API_SERVICES, service_json_data(service, host));
string self = MXS_JSON_API_SERVICES;
self += service->name;
return mxs_json_resource(host, self.c_str(), service_json_data(service, host));
}
json_t* service_listeners_to_json(const SERVICE* service, const char* host)

View File

@ -1118,7 +1118,7 @@ json_t* session_json_data(const MXS_SESSION *session, const char *host)
if (session->client_dcb->user)
{
json_object_set_new(attr, "user", json_string(session->client_dcb->user));
json_object_set_new(attr, CN_USER, json_string(session->client_dcb->user));
}
if (session->client_dcb->remote)
@ -1141,14 +1141,17 @@ json_t* session_json_data(const MXS_SESSION *session, const char *host)
json_object_set_new(attr, "idle", json_real(idle));
}
json_object_set_new(data, "attributes", attr);
json_object_set_new(data, CN_ATTRIBUTES, attr);
json_object_set_new(data, CN_LINKS, mxs_json_self_link(host, CN_SESSIONS, ss.str().c_str()));
return data;
}
json_t* session_to_json(const MXS_SESSION *session, const char *host)
{
return mxs_json_resource(host, MXS_JSON_API_SESSIONS, session_json_data(session, host));
stringstream ss;
ss << MXS_JSON_API_SESSIONS << session->ses_id;
return mxs_json_resource(host, ss.str().c_str(), session_json_data(session, host));
}
struct SessionListData

View File

@ -62,3 +62,47 @@ describe("Individual Resources", function() {
after(stopMaxScale)
});
describe("Resource Self Links", function() {
before(startMaxScale)
var tests = [
"/servers",
"/sessions",
"/services",
"/monitors",
"/filters",
"/maxscale/threads",
"/maxscale/modules",
"/maxscale/tasks",
"/servers/server1",
"/servers/server2",
"/services/RW-Split-Router",
"/services/RW-Split-Router/listeners",
"/monitors/MySQL-Monitor",
"/filters/Hint",
"/sessions/1",
"/maxscale/",
"/maxscale/threads/0",
"/maxscale/logs",
"/maxscale/modules/readwritesplit",
]
tests.forEach(function(endpoint) {
it(endpoint + ': correct self link', function() {
var obj = null;
return request.get(base_url + endpoint)
.then(function(resp) {
obj = JSON.parse(resp)
return request.get(obj.links.self)
})
.then(function(resp) {
var obj_self = JSON.parse(resp)
obj_self.links.self.should.be.equal(obj.links.self)
})
.should.be.fulfilled
});
})
after(stopMaxScale)
});

View File

@ -814,6 +814,7 @@ public:
json_object_set_new(json, CN_ID, json_string(ss.str().c_str()));
json_object_set_new(json, CN_TYPE, json_string(CN_THREADS));
json_object_set_new(json, CN_ATTRIBUTES, attr);
json_object_set_new(json, CN_LINKS, mxs_json_self_link(m_host, CN_THREADS, ss.str().c_str()));
ss_dassert((size_t)idx < m_data.size());
m_data[idx] = json;
@ -833,7 +834,9 @@ public:
json_t* resource(int id)
{
return mxs_json_resource(m_host, MXS_JSON_API_THREADS, m_data[id]);
stringstream self;
self << MXS_JSON_API_THREADS << id;
return mxs_json_resource(m_host, self.str().c_str(), m_data[id]);
}
private: