diff --git a/include/maxscale/modinfo.h b/include/maxscale/modinfo.h index aea093fcf..de0fb6c6a 100644 --- a/include/maxscale/modinfo.h +++ b/include/maxscale/modinfo.h @@ -20,6 +20,8 @@ #include +#include + MXS_BEGIN_DECLS /** @@ -217,4 +219,76 @@ typedef struct mxs_module /** Name of the symbol that MaxScale will load */ #define MXS_MODULE_SYMBOL_NAME "mxs_get_module_object" +static inline const char* mxs_module_param_type_to_string(enum mxs_module_param_type type) +{ + switch (type) + { + case MXS_MODULE_PARAM_COUNT: + return "count"; + case MXS_MODULE_PARAM_INT: + return "int"; + case MXS_MODULE_PARAM_SIZE: + return "size"; + case MXS_MODULE_PARAM_BOOL: + return "bool"; + case MXS_MODULE_PARAM_STRING: + return "string"; + case MXS_MODULE_PARAM_ENUM: + return "enum"; + case MXS_MODULE_PARAM_PATH: + return "path"; + case MXS_MODULE_PARAM_SERVICE: + return "service"; + case MXS_MODULE_PARAM_SERVER: + return "server"; + case MXS_MODULE_PARAM_SERVERLIST: + return "serverlist"; + default: + ss_dassert(!true); + return "unknown"; + } +} + +static inline const char* mxs_module_api_to_string(MXS_MODULE_API type) +{ + switch (type) + { + case MXS_MODULE_API_PROTOCOL: + return "protocol"; + case MXS_MODULE_API_ROUTER: + return "router"; + case MXS_MODULE_API_MONITOR: + return "monitor"; + case MXS_MODULE_API_FILTER: + return "filter"; + case MXS_MODULE_API_AUTHENTICATOR: + return "authenticator"; + case MXS_MODULE_API_QUERY_CLASSIFIER: + return "query_classifier"; + default: + ss_dassert(!true); + return "unknown"; + } +} + +static inline const char* mxs_module_status_to_string(MXS_MODULE_STATUS type) +{ + switch (type) + { + case MXS_MODULE_IN_DEVELOPMENT: + return "In development"; + case MXS_MODULE_ALPHA_RELEASE: + return "Alpha"; + case MXS_MODULE_BETA_RELEASE: + return "Beta"; + case MXS_MODULE_GA: + return "GA"; + case MXS_MODULE_EXPERIMENTAL: + return "Experimental"; + default: + ss_dassert(!true); + return "Unknown"; + } +} + MXS_END_DECLS diff --git a/server/core/load_utils.cc b/server/core/load_utils.cc index f254dc1fe..39d088b6b 100644 --- a/server/core/load_utils.cc +++ b/server/core/load_utils.cc @@ -28,12 +28,16 @@ * * @endverbatim */ + +#include "maxscale/modules.h" + #include #include #include #include #include #include + #include #include #include @@ -45,6 +49,7 @@ #include #include "maxscale/modules.h" +#include "maxscale/config.h" typedef struct loaded_module { @@ -401,6 +406,64 @@ void dprintAllModules(DCB *dcb) dcb_printf(dcb, "----------------+-----------------+---------+-------+-------------------------\n\n"); } +static json_t* module_to_json(const LOADED_MODULE *mod, const char* host) +{ + json_t* obj = json_object(); + + json_object_set_new(obj, "name", json_string(mod->module)); + json_object_set_new(obj, "type", json_string(mod->type)); + json_object_set_new(obj, "version", json_string(mod->info->version)); + json_object_set_new(obj, "description", json_string(mod->info->description)); + json_object_set_new(obj, "api", json_string(mxs_module_api_to_string(mod->info->modapi))); + json_object_set_new(obj, "status", json_string(mxs_module_status_to_string(mod->info->status))); + + json_t* params = json_array(); + + for (int i = 0; mod->info->parameters[i].name; i++) + { + json_t* p = json_object(); + + json_object_set_new(p, CN_NAME, json_string(mod->info->parameters[i].name)); + json_object_set_new(p, CN_TYPE, json_string(mxs_module_param_type_to_string(mod->info->parameters[i].type))); + + if (mod->info->parameters[i].default_value) + { + json_object_set(p, "default_value", json_string(mod->info->parameters[i].default_value)); + } + + if (mod->info->parameters[i].type == MXS_MODULE_PARAM_ENUM && + mod->info->parameters[i].accepted_values) + { + json_t* arr = json_array(); + + for (int x = 0; mod->info->parameters[i].accepted_values[x].name; x++) + { + json_array_append_new(arr, json_string(mod->info->parameters[i].accepted_values[x].name)); + } + + json_object_set_new(p, "enum_values", arr); + } + + json_array_append_new(params, p); + } + + json_object_set_new(obj, CN_PARAMETERS, params); + + return obj; +} + +json_t* module_list_to_json(const char* host) +{ + json_t* arr = json_array(); + + for (LOADED_MODULE *ptr = registered; ptr; ptr = ptr->next) + { + json_array_append_new(arr, module_to_json(ptr, host)); + } + + return arr; +} + void moduleShowFeedbackReport(DCB *dcb) { GWBUF *buffer; @@ -843,7 +906,7 @@ const MXS_MODULE *get_module(const char *name, const char *type) { LOADED_MODULE *mod = find_module(name); - if (mod == NULL && load_module(name, type)) + if (mod == NULL && type && load_module(name, type)) { mod = find_module(name); } diff --git a/server/core/maxscale/modules.h b/server/core/maxscale/modules.h index 95cfd8923..1eecff5fa 100644 --- a/server/core/maxscale/modules.h +++ b/server/core/maxscale/modules.h @@ -63,7 +63,7 @@ void *load_module(const char *module, const char *type); * @brief Get a module * * @param name Name of the module - * @param type The module type + * @param type The module type or NULL for any type * @return The loaded module or NULL if the module is not loaded */ const MXS_MODULE *get_module(const char *name, const char *type); @@ -161,4 +161,12 @@ bool mxs_module_iterator_has_next(const MXS_MODULE_ITERATOR* iterator); */ MXS_MODULE* mxs_module_iterator_get_next(MXS_MODULE_ITERATOR* iterator); +/** + * @brief Convert all modules to JSON + * + * @param host The hostname of this server + * @return Array of modules in JSON format + */ +json_t* module_list_to_json(const char* host); + MXS_END_DECLS diff --git a/server/core/resource.cc b/server/core/resource.cc index 5a774793d..013c95b77 100644 --- a/server/core/resource.cc +++ b/server/core/resource.cc @@ -26,6 +26,7 @@ #include "maxscale/monitor.h" #include "maxscale/service.h" #include "maxscale/config_runtime.h" +#include "maxscale/modules.h" using std::list; using std::string; @@ -340,10 +341,9 @@ HttpResponse cb_tasks(const HttpRequest& request) return HttpResponse(MHD_HTTP_OK); } -HttpResponse cb_modules(const HttpRequest& request) +HttpResponse cb_all_modules(const HttpRequest& request) { - // TODO: Show modules - return HttpResponse(MHD_HTTP_OK); + return HttpResponse(MHD_HTTP_OK, module_list_to_json(request.host())); } HttpResponse cb_send_ok(const HttpRequest& request) @@ -384,7 +384,7 @@ public: m_get.push_back(SResource(new Resource(cb_threads, 2, "maxscale", "threads"))); m_get.push_back(SResource(new Resource(cb_logs, 2, "maxscale", "logs"))); m_get.push_back(SResource(new Resource(cb_tasks, 2, "maxscale", "tasks"))); - m_get.push_back(SResource(new Resource(cb_modules, 2, "maxscale", "modules"))); + m_get.push_back(SResource(new Resource(cb_all_modules, 2, "maxscale", "modules"))); /** Create new resources */ m_post.push_back(SResource(new Resource(cb_flush, 3, "maxscale", "logs", "flush")));