diff --git a/Documentation/REST-API/Resources-Service.md b/Documentation/REST-API/Resources-Service.md index 7d3a08b23..ad23bd85e 100644 --- a/Documentation/REST-API/Resources-Service.md +++ b/Documentation/REST-API/Resources-Service.md @@ -302,6 +302,35 @@ object. |ssl_version | The SSL version to use [TLSv1.2|TLSv1.1|TLSv1.0] | |ssl_cert_verify_depth | Certificate verification depth | +### Destroy a listener + +``` +DELETE /v1/services/:service/listeners/:name +``` + +In the URI , the _:name_ must map to a listener and the _:service_ must map to a +service. Both names must have all whitespace replaced with hyphens. + +#### Response + +OK: + +``` +Status: 204 No Content +``` + +Listener not found: + +``` +Status: 404 Not Found +``` + +Listener cannot be deleted: + +``` +Status: 403 Forbidden +``` + ### Update a service The _:name_ in the URI must map to a service name and the request body must be a diff --git a/include/maxscale/service.h b/include/maxscale/service.h index 81464e1fa..d16a4d07e 100644 --- a/include/maxscale/service.h +++ b/include/maxscale/service.h @@ -258,6 +258,16 @@ bool serviceHasListener(SERVICE *service, const char *protocol, */ bool service_port_is_used(unsigned short port); +/** + * @brief Check if the service has a listener with a matching name + * + * @param service Service to check + * @param name Name to compare to + * + * @return True if the service has a listener with a matching name + */ +bool service_has_named_listener(SERVICE *service, const char *name); + int serviceGetUser(SERVICE *service, char **user, char **auth); int serviceSetUser(SERVICE *service, const char *user, const char *auth); bool serviceSetFilters(SERVICE *service, char *filters); diff --git a/server/core/config_runtime.cc b/server/core/config_runtime.cc index b8710df3b..f81c52827 100644 --- a/server/core/config_runtime.cc +++ b/server/core/config_runtime.cc @@ -806,6 +806,7 @@ bool runtime_destroy_listener(SERVICE *service, const char *name) else { MXS_ERROR("Failed to destroy listener '%s' for service '%s'", name, service->name); + runtime_error("Failed to destroy listener '%s' for service '%s'", name, service->name); } } diff --git a/server/core/resource.cc b/server/core/resource.cc index 8036e2611..a4d469405 100644 --- a/server/core/resource.cc +++ b/server/core/resource.cc @@ -353,6 +353,29 @@ HttpResponse cb_delete_monitor(const HttpRequest& request) return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error()); } +HttpResponse cb_delete_listener(const HttpRequest& request) +{ + + SERVICE* service = service_find(request.uri_part(1).c_str()); + ss_dassert(service); + + if (service) + { + std::string listener = request.uri_part(3); + + if (!service_has_named_listener(service, listener.c_str())) + { + return HttpResponse(MHD_HTTP_NOT_FOUND); + } + else if (runtime_destroy_listener(service, listener.c_str())) + { + return HttpResponse(MHD_HTTP_NO_CONTENT); + } + } + + return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error()); +} + HttpResponse cb_all_servers(const HttpRequest& request) { return HttpResponse(MHD_HTTP_OK, server_list_to_json(request.host())); @@ -754,6 +777,12 @@ public: m_delete.push_back(SResource(new Resource(cb_delete_monitor, 2, "monitors", ":monitor"))); m_delete.push_back(SResource(new Resource(cb_delete_user, 3, "users", "inet", ":inetuser"))); m_delete.push_back(SResource(new Resource(cb_delete_user, 3, "users", "unix", ":unixuser"))); + + /** The wildcard for listener name isn't a good solution as it adds + * a burden to the callback and requires it to do the checking but it'll + * do for the time being */ + m_delete.push_back(SResource(new Resource(cb_delete_listener, 4, + "services", ":service", "listeners", "?"))); } ~RootResource() diff --git a/server/core/service.cc b/server/core/service.cc index 72a21013a..e0dfa8ed9 100644 --- a/server/core/service.cc +++ b/server/core/service.cc @@ -796,6 +796,22 @@ bool serviceHasListener(SERVICE *service, const char *protocol, return false; } +bool service_has_named_listener(SERVICE *service, const char *name) +{ + LISTENER_ITERATOR iter; + + for (SERV_LISTENER *listener = listener_iterator_init(service, &iter); + listener; listener = listener_iterator_next(&iter)) + { + if (listener_is_active(listener) && strcmp(listener->name, name) == 0) + { + return true; + } + } + + return false; +} + /** * Allocate a new server reference *