MXS-1220: Add creation of listeners via REST API
Listeners can now be created via the REST API by doing a POST request to the service listener resource.
This commit is contained in:
@ -46,14 +46,19 @@ MXS_BEGIN_DECLS
|
|||||||
#define MXS_JSON_PTR_RELATIONSHIPS_MONITORS "/data/relationships/monitors/data"
|
#define MXS_JSON_PTR_RELATIONSHIPS_MONITORS "/data/relationships/monitors/data"
|
||||||
#define MXS_JSON_PTR_RELATIONSHIPS_FILTERS "/data/relationships/filters/data"
|
#define MXS_JSON_PTR_RELATIONSHIPS_FILTERS "/data/relationships/filters/data"
|
||||||
|
|
||||||
/** Server JSON Pointers */
|
/** Parameter value JSON Pointers */
|
||||||
#define MXS_JSON_PTR_SRV_PORT MXS_JSON_PTR_PARAMETERS "/port"
|
#define MXS_JSON_PTR_PARAM_PORT MXS_JSON_PTR_PARAMETERS "/port"
|
||||||
#define MXS_JSON_PTR_SRV_ADDRESS MXS_JSON_PTR_PARAMETERS "/address"
|
#define MXS_JSON_PTR_PARAM_ADDRESS MXS_JSON_PTR_PARAMETERS "/address"
|
||||||
#define MXS_JSON_PTR_SRV_PROTOCOL MXS_JSON_PTR_PARAMETERS "/protocol"
|
#define MXS_JSON_PTR_PARAM_PROTOCOL MXS_JSON_PTR_PARAMETERS "/protocol"
|
||||||
#define MXS_JSON_PTR_SRV_AUTHENTICATOR MXS_JSON_PTR_PARAMETERS "/authenticator"
|
#define MXS_JSON_PTR_PARAM_AUTHENTICATOR MXS_JSON_PTR_PARAMETERS "/authenticator"
|
||||||
#define MXS_JSON_PTR_SRV_AUTHENTICATOR_OPTIONS MXS_JSON_PTR_PARAMETERS "/authenticator_options"
|
#define MXS_JSON_PTR_PARAM_AUTHENTICATOR_OPTIONS MXS_JSON_PTR_PARAMETERS "/authenticator_options"
|
||||||
|
#define MXS_JSON_PTR_PARAM_SSL_KEY MXS_JSON_PTR_PARAMETERS "/ssl_key"
|
||||||
|
#define MXS_JSON_PTR_PARAM_SSL_CERT MXS_JSON_PTR_PARAMETERS "/ssl_cert"
|
||||||
|
#define MXS_JSON_PTR_PARAM_SSL_CA_CERT MXS_JSON_PTR_PARAMETERS "/ssl_ca_cert"
|
||||||
|
#define MXS_JSON_PTR_PARAM_SSL_VERSION MXS_JSON_PTR_PARAMETERS "/ssl_version"
|
||||||
|
#define MXS_JSON_PTR_PARAM_SSL_CERT_VERIFY_DEPTH MXS_JSON_PTR_PARAMETERS "/ssl_cert_verify_depth"
|
||||||
|
|
||||||
#define PTR_MON_MODULE "/data/attributes/module"
|
#define MXS_JSON_PTR_MODULE "/data/attributes/module"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common configuration parameters names
|
* Common configuration parameters names
|
||||||
|
|||||||
@ -816,8 +816,8 @@ static inline const char* string_or_null(json_t* json, const char* path)
|
|||||||
static bool server_contains_required_fields(json_t* json)
|
static bool server_contains_required_fields(json_t* json)
|
||||||
{
|
{
|
||||||
json_t* id = mxs_json_pointer(json, MXS_JSON_PTR_ID);
|
json_t* id = mxs_json_pointer(json, MXS_JSON_PTR_ID);
|
||||||
json_t* port = mxs_json_pointer(json, MXS_JSON_PTR_SRV_PORT);
|
json_t* port = mxs_json_pointer(json, MXS_JSON_PTR_PARAM_PORT);
|
||||||
json_t* address = mxs_json_pointer(json, MXS_JSON_PTR_SRV_ADDRESS);
|
json_t* address = mxs_json_pointer(json, MXS_JSON_PTR_PARAM_ADDRESS);
|
||||||
|
|
||||||
return (id && json_is_string(id) &&
|
return (id && json_is_string(id) &&
|
||||||
address && json_is_string(address) &&
|
address && json_is_string(address) &&
|
||||||
@ -869,6 +869,14 @@ static bool link_server_to_objects(SERVER* server, set<string>& relations)
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static string json_int_to_string(json_t* json)
|
||||||
|
{
|
||||||
|
char str[25]; // Enough to store any 64-bit integer value
|
||||||
|
int64_t i = json_integer_value(json);
|
||||||
|
snprintf(str, sizeof(str), "%ld", i);
|
||||||
|
return string(str);
|
||||||
|
}
|
||||||
|
|
||||||
SERVER* runtime_create_server_from_json(json_t* json)
|
SERVER* runtime_create_server_from_json(json_t* json)
|
||||||
{
|
{
|
||||||
SERVER* rval = NULL;
|
SERVER* rval = NULL;
|
||||||
@ -876,22 +884,20 @@ SERVER* runtime_create_server_from_json(json_t* json)
|
|||||||
if (server_contains_required_fields(json))
|
if (server_contains_required_fields(json))
|
||||||
{
|
{
|
||||||
const char* name = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_ID));
|
const char* name = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_ID));
|
||||||
const char* address = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_SRV_ADDRESS));
|
const char* address = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_PARAM_ADDRESS));
|
||||||
|
|
||||||
/** The port needs to be in string format */
|
/** The port needs to be in string format */
|
||||||
char port[200]; // Enough to store any port value
|
string port = json_int_to_string(mxs_json_pointer(json, MXS_JSON_PTR_PARAM_PORT));
|
||||||
int i = json_integer_value(mxs_json_pointer(json, MXS_JSON_PTR_SRV_PORT));
|
|
||||||
snprintf(port, sizeof(port), "%d", i);
|
|
||||||
|
|
||||||
/** Optional parameters */
|
/** Optional parameters */
|
||||||
const char* protocol = string_or_null(json, MXS_JSON_PTR_SRV_PROTOCOL);
|
const char* protocol = string_or_null(json, MXS_JSON_PTR_PARAM_PROTOCOL);
|
||||||
const char* authenticator = string_or_null(json, MXS_JSON_PTR_SRV_AUTHENTICATOR);
|
const char* authenticator = string_or_null(json, MXS_JSON_PTR_PARAM_AUTHENTICATOR);
|
||||||
const char* authenticator_options = string_or_null(json, MXS_JSON_PTR_SRV_AUTHENTICATOR_OPTIONS);
|
const char* authenticator_options = string_or_null(json, MXS_JSON_PTR_PARAM_AUTHENTICATOR_OPTIONS);
|
||||||
|
|
||||||
set<string> relations;
|
set<string> relations;
|
||||||
|
|
||||||
if (extract_relations(json, relations, server_relation_types, server_relation_is_valid) &&
|
if (extract_relations(json, relations, server_relation_types, server_relation_is_valid) &&
|
||||||
runtime_create_server(name, address, port, protocol, authenticator, authenticator_options))
|
runtime_create_server(name, address, port.c_str(), protocol, authenticator, authenticator_options))
|
||||||
{
|
{
|
||||||
rval = server_find_by_unique_name(name);
|
rval = server_find_by_unique_name(name);
|
||||||
ss_dassert(rval);
|
ss_dassert(rval);
|
||||||
@ -1000,7 +1006,7 @@ static bool validate_monitor_json(json_t* json)
|
|||||||
json_t* value;
|
json_t* value;
|
||||||
|
|
||||||
if ((value = mxs_json_pointer(json, MXS_JSON_PTR_ID)) && json_is_string(value) &&
|
if ((value = mxs_json_pointer(json, MXS_JSON_PTR_ID)) && json_is_string(value) &&
|
||||||
(value = mxs_json_pointer(json, PTR_MON_MODULE)) && json_is_string(value))
|
(value = mxs_json_pointer(json, MXS_JSON_PTR_MODULE)) && json_is_string(value))
|
||||||
{
|
{
|
||||||
set<string> relations;
|
set<string> relations;
|
||||||
if (extract_relations(json, relations, object_relation_types, object_relation_is_valid))
|
if (extract_relations(json, relations, object_relation_types, object_relation_is_valid))
|
||||||
@ -1056,7 +1062,7 @@ MXS_MONITOR* runtime_create_monitor_from_json(json_t* json)
|
|||||||
if (validate_monitor_json(json))
|
if (validate_monitor_json(json))
|
||||||
{
|
{
|
||||||
const char* name = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_ID));
|
const char* name = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_ID));
|
||||||
const char* module = json_string_value(mxs_json_pointer(json, PTR_MON_MODULE));
|
const char* module = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_MODULE));
|
||||||
|
|
||||||
if (runtime_create_monitor(name, module))
|
if (runtime_create_monitor(name, module))
|
||||||
{
|
{
|
||||||
@ -1324,3 +1330,58 @@ bool runtime_alter_logs_from_json(json_t* json)
|
|||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool validate_listener_json(json_t* json)
|
||||||
|
{
|
||||||
|
bool rval = false;
|
||||||
|
json_t* param;
|
||||||
|
|
||||||
|
if ((param = mxs_json_pointer(json, MXS_JSON_PTR_ID)) && json_is_string(param) &&
|
||||||
|
(param = mxs_json_pointer(json, MXS_JSON_PTR_PARAMETERS)) && json_is_object(param))
|
||||||
|
{
|
||||||
|
json_t* value;
|
||||||
|
|
||||||
|
if ((value = mxs_json_pointer(param, CN_PORT)) && json_is_integer(value) &&
|
||||||
|
(!(value = mxs_json_pointer(param, CN_ADDRESS)) || json_is_string(value)) &&
|
||||||
|
(!(value = mxs_json_pointer(param, CN_AUTHENTICATOR)) || json_is_string(value)) &&
|
||||||
|
(!(value = mxs_json_pointer(param, CN_AUTHENTICATOR_OPTIONS)) || json_is_string(value)) &&
|
||||||
|
(!(value = mxs_json_pointer(param, CN_SSL_KEY)) || json_is_string(value)) &&
|
||||||
|
(!(value = mxs_json_pointer(param, CN_SSL_CERT)) || json_is_string(value)) &&
|
||||||
|
(!(value = mxs_json_pointer(param, CN_SSL_CA_CERT)) || json_is_string(value)) &&
|
||||||
|
(!(value = mxs_json_pointer(param, CN_SSL_VERSION)) || json_is_string(value)) &&
|
||||||
|
(!(value = mxs_json_pointer(param, CN_SSL_CERT_VERIFY_DEPTH)) || json_is_integer(value)))
|
||||||
|
{
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool runtime_create_listener_from_json(SERVICE* service, json_t* json)
|
||||||
|
{
|
||||||
|
bool rval = false;
|
||||||
|
|
||||||
|
if (validate_listener_json(json))
|
||||||
|
{
|
||||||
|
string port = json_int_to_string(mxs_json_pointer(json, MXS_JSON_PTR_PARAM_PORT));
|
||||||
|
|
||||||
|
const char* id = string_or_null(json, MXS_JSON_PTR_ID);
|
||||||
|
const char* address = string_or_null(json, MXS_JSON_PTR_PARAM_ADDRESS);
|
||||||
|
const char* protocol = string_or_null(json, MXS_JSON_PTR_PARAM_PROTOCOL);
|
||||||
|
const char* authenticator = string_or_null(json, MXS_JSON_PTR_PARAM_AUTHENTICATOR);
|
||||||
|
const char* authenticator_options = string_or_null(json, MXS_JSON_PTR_PARAM_AUTHENTICATOR_OPTIONS);
|
||||||
|
const char* ssl_key = string_or_null(json, MXS_JSON_PTR_PARAM_SSL_KEY);
|
||||||
|
const char* ssl_cert = string_or_null(json, MXS_JSON_PTR_PARAM_SSL_CERT);
|
||||||
|
const char* ssl_ca_cert = string_or_null(json, MXS_JSON_PTR_PARAM_SSL_CA_CERT);
|
||||||
|
const char* ssl_version = string_or_null(json, MXS_JSON_PTR_PARAM_SSL_VERSION);
|
||||||
|
const char* ssl_cert_verify_depth = string_or_null(json, MXS_JSON_PTR_PARAM_SSL_CERT_VERIFY_DEPTH);
|
||||||
|
|
||||||
|
rval = runtime_create_listener(service, id, address, port.c_str(), protocol,
|
||||||
|
authenticator, authenticator_options,
|
||||||
|
ssl_key, ssl_cert, ssl_ca_cert, ssl_version,
|
||||||
|
ssl_cert_verify_depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|||||||
@ -238,6 +238,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);
|
bool runtime_alter_service_from_json(SERVICE* service, json_t* new_json);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a listener from JSON
|
||||||
|
*
|
||||||
|
* @param service Service where the listener is created
|
||||||
|
* @param json JSON definition of the new listener
|
||||||
|
*
|
||||||
|
* @return True if the listener was successfully created and started
|
||||||
|
*/
|
||||||
|
bool runtime_create_listener_from_json(SERVICE* service, json_t* json);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Alter logging options using JSON
|
* @brief Alter logging options using JSON
|
||||||
*
|
*
|
||||||
|
|||||||
@ -190,6 +190,19 @@ HttpResponse cb_create_monitor(const HttpRequest& request)
|
|||||||
return HttpResponse(MHD_HTTP_FORBIDDEN);
|
return HttpResponse(MHD_HTTP_FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpResponse cb_create_service_listener(const HttpRequest& request)
|
||||||
|
{
|
||||||
|
json_t* json = request.get_json();
|
||||||
|
SERVICE* service = service_find(request.uri_part(1).c_str());
|
||||||
|
|
||||||
|
if (service && json && runtime_create_listener_from_json(service, json))
|
||||||
|
{
|
||||||
|
return HttpResponse(MHD_HTTP_NO_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return HttpResponse(MHD_HTTP_FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
HttpResponse cb_alter_monitor(const HttpRequest& request)
|
HttpResponse cb_alter_monitor(const HttpRequest& request)
|
||||||
{
|
{
|
||||||
json_t* json = request.get_json();
|
json_t* json = request.get_json();
|
||||||
@ -453,6 +466,8 @@ public:
|
|||||||
m_post.push_back(SResource(new Resource(cb_flush, 3, "maxscale", "logs", "flush")));
|
m_post.push_back(SResource(new Resource(cb_flush, 3, "maxscale", "logs", "flush")));
|
||||||
m_post.push_back(SResource(new Resource(cb_create_server, 1, "servers")));
|
m_post.push_back(SResource(new Resource(cb_create_server, 1, "servers")));
|
||||||
m_post.push_back(SResource(new Resource(cb_create_monitor, 1, "monitors")));
|
m_post.push_back(SResource(new Resource(cb_create_monitor, 1, "monitors")));
|
||||||
|
m_post.push_back(SResource(new Resource(cb_create_service_listener, 3,
|
||||||
|
"services", ":service", "listeners")));
|
||||||
|
|
||||||
/** Update resources */
|
/** Update resources */
|
||||||
m_put.push_back(SResource(new Resource(cb_alter_server, 2, "servers", ":server")));
|
m_put.push_back(SResource(new Resource(cb_alter_server, 2, "servers", ":server")));
|
||||||
|
|||||||
@ -62,5 +62,28 @@ describe("Service", function() {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("create a listener", function() {
|
||||||
|
var listener = {
|
||||||
|
"links": {
|
||||||
|
"self": "http://localhost:8989/v1/services/RW-Split-Router/listeners"
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"attributes": {
|
||||||
|
"parameters": {
|
||||||
|
"port": 4012,
|
||||||
|
"protocol": "MySQLClient",
|
||||||
|
"authenticator": "MySQLAuth",
|
||||||
|
"address": "127.0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": "RW-Split-Listener-2",
|
||||||
|
"type": "listeners"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return request.post(base_url + "/services/RW-Split-Router/listeners", {json: listener})
|
||||||
|
.should.be.fulfilled
|
||||||
|
});
|
||||||
|
|
||||||
after(stopMaxScale)
|
after(stopMaxScale)
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user