MXS-1220: Add endpoint for set/clear of server status
The server status can now be manipulated via the REST API. Added tests for the state manipulation. Fixed minor issues in related code.
This commit is contained in:
@ -501,29 +501,80 @@ Server is in use:
|
||||
Status: 403 Forbidden
|
||||
```
|
||||
|
||||
# **TODO:** Implement the following features
|
||||
|
||||
### Get all connections to a server
|
||||
|
||||
Get all connections that are connected to a server.
|
||||
### Set server status
|
||||
|
||||
```
|
||||
GET /v1/servers/:name/connections
|
||||
POST /v1/servers/:name/set
|
||||
```
|
||||
|
||||
The _:name_ in the URI must map to a server name with all whitespace replaced
|
||||
with hyphens. This endpoint requires that the `status` parameter is passed with
|
||||
the request. The value of `status` must be one of the following values.
|
||||
|
||||
|Value | Status Description |
|
||||
|-----------|--------------------------------|
|
||||
|master | Server is a Master |
|
||||
|slave | Server is a Slave |
|
||||
|maintenance| Server is put into maintenance |
|
||||
|running | Server is up and running |
|
||||
|synced | Server is a Galera node |
|
||||
|ndb | Server is a NDBCluster node |
|
||||
|stale | Server is a stale Master |
|
||||
|
||||
For example, to set the server _db-server-1_ into maintenance mode, a request to
|
||||
the following URL must be made:
|
||||
|
||||
```
|
||||
POST /v1/servers/db-server-1/set?status=maintenance
|
||||
```
|
||||
|
||||
#### Response
|
||||
|
||||
### Close all connections to a server
|
||||
|
||||
Close all connections to a particular server. This will forcefully close all
|
||||
backend connections.
|
||||
|
||||
```
|
||||
DELETE /v1/servers/:name/connections
|
||||
```
|
||||
|
||||
#### Response
|
||||
OK:
|
||||
|
||||
```
|
||||
Status: 204 No Content
|
||||
```
|
||||
|
||||
Server not found:
|
||||
|
||||
```
|
||||
Status: 404 Not Found
|
||||
```
|
||||
|
||||
Missing or invalid parameter:
|
||||
|
||||
```
|
||||
Status: 403 Forbidden
|
||||
```
|
||||
|
||||
### Clear server status
|
||||
|
||||
```
|
||||
POST /v1/servers/:name/clear
|
||||
```
|
||||
|
||||
The _:name_ in the URI must map to a server name with all whitespace replaced
|
||||
with hyphens. This endpoint requires that the `status` parameter is passed with
|
||||
the request. The value of `status` must be one of the values defined in the
|
||||
_set_ endpoint documentation.
|
||||
|
||||
#### Response
|
||||
|
||||
OK:
|
||||
|
||||
```
|
||||
Status: 204 No Content
|
||||
```
|
||||
|
||||
Server not found:
|
||||
|
||||
```
|
||||
Status: 404 Not Found
|
||||
```
|
||||
|
||||
Missing or invalid parameter:
|
||||
|
||||
```
|
||||
Status: 403 Forbidden
|
||||
```
|
||||
|
@ -86,8 +86,19 @@ json_t* mxs_json_self_link(const char* host, const char* path, const char* id);
|
||||
*
|
||||
* @param json JSON object
|
||||
* @param json_ptr JSON Pointer to object
|
||||
*
|
||||
* @return Pointed value or NULL if no value is found
|
||||
*/
|
||||
json_t* mxs_json_pointer(json_t* json, const char* json_ptr);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return a JSON formatted error
|
||||
*
|
||||
* @param err Error description
|
||||
*
|
||||
* @return The error as JSON
|
||||
*/
|
||||
json_t* mxs_json_error(const char* err);
|
||||
|
||||
MXS_END_DECLS
|
||||
|
@ -1622,14 +1622,7 @@ json_t* runtime_get_json_error()
|
||||
|
||||
if (errmsg.length())
|
||||
{
|
||||
json_t* err = json_object();
|
||||
json_object_set_new(err, "detail", json_string(errmsg.c_str()));
|
||||
|
||||
json_t* arr = json_array();
|
||||
json_array_append_new(arr, err);
|
||||
|
||||
obj = json_object();
|
||||
json_object_set_new(obj, "errors", arr);
|
||||
obj = mxs_json_error(errmsg.c_str());
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
@ -155,3 +155,17 @@ json_t* mxs_json_self_link(const char* host, const char* path, const char* id)
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
json_t* mxs_json_error(const char* message)
|
||||
{
|
||||
json_t* err = json_object();
|
||||
json_object_set_new(err, "detail", json_string(message));
|
||||
|
||||
json_t* arr = json_array();
|
||||
json_array_append_new(arr, err);
|
||||
|
||||
json_t* obj = json_object();
|
||||
json_object_set_new(obj, "errors", arr);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
@ -562,6 +562,34 @@ HttpResponse cb_delete_user(const HttpRequest& request)
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
|
||||
}
|
||||
|
||||
HttpResponse cb_set_server(const HttpRequest& request)
|
||||
{
|
||||
SERVER* server = server_find_by_unique_name(request.uri_part(1).c_str());
|
||||
int opt = server_map_status(request.get_option("status").c_str());
|
||||
|
||||
if (opt)
|
||||
{
|
||||
server_set_status(server, opt);
|
||||
return HttpResponse(MHD_HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, mxs_json_error("Invalid or missing value for the `status` parameter"));
|
||||
}
|
||||
|
||||
HttpResponse cb_clear_server(const HttpRequest& request)
|
||||
{
|
||||
SERVER* server = server_find_by_unique_name(request.uri_part(1).c_str());
|
||||
int opt = server_map_status(request.get_option("status").c_str());
|
||||
|
||||
if (opt)
|
||||
{
|
||||
server_clear_status(server, opt);
|
||||
return HttpResponse(MHD_HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, mxs_json_error("Invalid or missing value for the `status` parameter"));
|
||||
}
|
||||
|
||||
HttpResponse cb_modulecmd(const HttpRequest& request)
|
||||
{
|
||||
std::string module = request.uri_part(2);
|
||||
@ -699,6 +727,8 @@ public:
|
||||
"services", ":service", "listeners")));
|
||||
m_post.push_back(SResource(new Resource(cb_create_user, 2, "users", "inet")));
|
||||
m_post.push_back(SResource(new Resource(cb_create_user, 2, "users", "unix")));
|
||||
m_post.push_back(SResource(new Resource(cb_set_server, 3, "servers", ":server", "set")));
|
||||
m_post.push_back(SResource(new Resource(cb_clear_server, 3, "servers", ":server", "clear")));
|
||||
|
||||
/** For all module commands that modify state/data */
|
||||
m_post.push_back(SResource(new Resource(cb_modulecmd, 4, "maxscale", "modules", ":module", "?")));
|
||||
|
@ -5,7 +5,7 @@ describe("Errors", function()
|
||||
{
|
||||
before(startMaxScale)
|
||||
|
||||
it("error on invalid PUT request", function()
|
||||
it("error on invalid PATCH request", function()
|
||||
{
|
||||
return request.patch(base_url + "/servers/server1", { json: {this_is: "a test"}})
|
||||
.should.be.rejected
|
||||
|
@ -80,3 +80,51 @@ describe("Server Relationships", function() {
|
||||
|
||||
after(stopMaxScale)
|
||||
});
|
||||
|
||||
describe("Server Status", function() {
|
||||
before(startMaxScale)
|
||||
|
||||
it("create new server", function() {
|
||||
return request.post(base_url + "/servers/", {json: server })
|
||||
.should.be.fulfilled
|
||||
});
|
||||
|
||||
it("set server into maintenance", function() {
|
||||
return request.post(base_url + "/servers/" + server.data.id + "/set?status=maintenance")
|
||||
.then(function(resp) {
|
||||
return request.get(base_url + "/servers/" + server.data.id)
|
||||
})
|
||||
.then(function(resp) {
|
||||
var srv = JSON.parse(resp)
|
||||
srv.data.attributes.status.should.match(/Maintenance/)
|
||||
})
|
||||
});
|
||||
|
||||
it("clear maintenance", function() {
|
||||
return request.post(base_url + "/servers/" + server.data.id + "/clear?status=maintenance")
|
||||
.then(function(resp) {
|
||||
return request.get(base_url + "/servers/" + server.data.id)
|
||||
})
|
||||
.then(function(resp) {
|
||||
var srv = JSON.parse(resp)
|
||||
srv.data.attributes.status.should.not.match(/Maintenance/)
|
||||
})
|
||||
});
|
||||
|
||||
it("set invalid status value", function() {
|
||||
return request.post(base_url + "/servers/" + server.data.id + "/set?status=somethingstrange")
|
||||
.should.be.rejected
|
||||
});
|
||||
|
||||
it("clear invalid status value", function() {
|
||||
return request.post(base_url + "/servers/" + server.data.id + "/clear?status=somethingstrange")
|
||||
.should.be.rejected
|
||||
});
|
||||
|
||||
it("destroy server", function() {
|
||||
return request.delete(base_url + "/servers/" + server.data.id)
|
||||
.should.be.fulfilled
|
||||
});
|
||||
|
||||
after(stopMaxScale)
|
||||
});
|
||||
|
Reference in New Issue
Block a user