diff --git a/include/maxscale/config.h b/include/maxscale/config.h index 06490ef64..9939da27d 100644 --- a/include/maxscale/config.h +++ b/include/maxscale/config.h @@ -76,6 +76,7 @@ MXS_BEGIN_DECLS #define MXS_JSON_PTR_PARAM_SSL_VERIFY_PEER_CERT MXS_JSON_PTR_PARAMETERS "/ssl_verify_peer_certificate" /** Non-parameter JSON pointers */ +#define MXS_JSON_PTR_ROUTER "/data/attributes/router" #define MXS_JSON_PTR_MODULE "/data/attributes/module" #define MXS_JSON_PTR_PASSWORD "/data/attributes/password" #define MXS_JSON_PTR_ACCOUNT "/data/attributes/account" diff --git a/server/core/config_runtime.cc b/server/core/config_runtime.cc index aacb7e563..8453d40b8 100644 --- a/server/core/config_runtime.cc +++ b/server/core/config_runtime.cc @@ -1078,6 +1078,53 @@ bool runtime_create_filter(const char *name, const char *module, MXS_CONFIG_PARA return rval; } +static bool runtime_create_service(const char *name, const char *router, MXS_CONFIG_PARAMETER* params) +{ + mxs::SpinLockGuard guard(crt_lock); + bool rval = false; + + if (service_find(name) == NULL) + { + SERVICE* service = NULL; + CONFIG_CONTEXT ctx{(char*)""}; + ctx.parameters = load_defaults(router, MODULE_FILTER, CN_FILTER); + + if (ctx.parameters) + { + for (MXS_CONFIG_PARAMETER* p = params; p; p = p->next) + { + config_replace_param(&ctx, p->name, p->value); + } + + if ((service = service_alloc(name, router, ctx.parameters)) == NULL) + { + runtime_error("Could not create service '%s' with module '%s'", name, router); + } + + config_parameter_free(ctx.parameters); + } + + if (service) + { + if (service_serialize(service)) + { + MXS_NOTICE("Created service '%s'", name); + rval = true; + } + else + { + runtime_error("Failed to serialize service '%s'", name); + } + } + } + else + { + runtime_error("Can't create service '%s', it already exists", name); + } + + return rval; +} + bool runtime_destroy_service(SERVICE* service) { bool rval = false; @@ -1815,6 +1862,28 @@ MXS_FILTER_DEF* runtime_create_filter_from_json(json_t* json) return rval; } +SERVICE* runtime_create_service_from_json(json_t* json) +{ + SERVICE* rval = NULL; + + if (validate_object_json(json, {MXS_JSON_PTR_ROUTER}, {service_to_filter, object_to_server})) + { + const char* name = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_ID)); + const char* router = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_ROUTER)); + MXS_CONFIG_PARAMETER* params = extract_parameters_from_json(json); + + if (runtime_create_service(name, router, params)) + { + rval = service_find(name); + ss_dassert(rval); + } + + config_parameter_free(params); + } + + return rval; +} + bool object_to_server_relations(const char* target, json_t* old_json, json_t* new_json) { if (mxs_json_pointer(new_json, MXS_JSON_PTR_RELATIONSHIPS) == NULL) diff --git a/server/core/internal/config_runtime.h b/server/core/internal/config_runtime.h index d4ab6fd62..6ac49885a 100644 --- a/server/core/internal/config_runtime.h +++ b/server/core/internal/config_runtime.h @@ -275,6 +275,15 @@ MXS_MONITOR* runtime_create_monitor_from_json(json_t* json); */ MXS_FILTER_DEF* runtime_create_filter_from_json(json_t* json); +/** + * @brief Create a new service from JSON + * + * @param json JSON defining the service + * + * @return Created service or NULL on error + */ +SERVICE* runtime_create_service_from_json(json_t* json); + /** * @brief Alter a monitor using JSON * diff --git a/server/core/resource.cc b/server/core/resource.cc index 135615ca7..bf79c1e69 100644 --- a/server/core/resource.cc +++ b/server/core/resource.cc @@ -337,6 +337,18 @@ HttpResponse cb_create_filter(const HttpRequest& request) return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error()); } +HttpResponse cb_create_service(const HttpRequest& request) +{ + ss_dassert(request.get_json()); + + if (runtime_create_service_from_json(request.get_json())) + { + return HttpResponse(MHD_HTTP_NO_CONTENT); + } + + return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error()); +} + HttpResponse cb_create_service_listener(const HttpRequest& request) { SERVICE* service = service_find(request.uri_part(1).c_str()); @@ -885,6 +897,7 @@ public: 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_filter, 1, "filters"))); + m_post.push_back(SResource(new Resource(cb_create_service, 1, "services"))); m_post.push_back(SResource(new Resource(cb_create_service_listener, 3, "services", ":service", "listeners"))); m_post.push_back(SResource(new Resource(cb_create_user, 2, "users", "inet")));