/* * Copyright (c) 2016 MariaDB Corporation Ab * * Use of this software is governed by the Business Source License included * in the LICENSE.TXT file and at www.mariadb.com/bsl11. * * Change Date: 2023-11-12 * * On the date above, in accordance with the Business Source License, use * of this software will be governed by version 2 or later of the General * Public License. */ #include "maxrest.hh" using namespace std; MaxRest::Server::Server(const MaxRest& maxrest, json_t* pObject) : name (maxrest.get (pObject, "id", Presence::MANDATORY)) , address (maxrest.get (pObject, "attributes/parameters/address")) , port (maxrest.get(pObject, "attributes/parameters/port")) , connections(maxrest.get(pObject, "attributes/statistics/connections")) , state (maxrest.get (pObject, "attributes/state")) { } MaxRest::MaxRest(TestConnections* pTest) : m_test(*pTest) { } unique_ptr MaxRest::v1_servers(const string& id) const { string path("servers"); path += "/"; path += id; return curl_get(path); } unique_ptr MaxRest::v1_servers() const { return curl_get("servers"); } void MaxRest::v1_maxscale_modules(const string& module, const string& command, const string& instance, const std::vector& params) const { string path("maxscale/modules"); path += "/"; path += module; path += "/"; path += command; path += "?"; path += instance; if (!params.empty()) { for (const auto& param : params) { path += "\\&"; path += param; } } curl_post(path); } MaxRest::Server MaxRest::show_server(const std::string& id) const { unique_ptr sObject = v1_servers(id); json_t* pData = get_object(sObject.get(), "data", Presence::MANDATORY); return Server(*this, pData); } vector MaxRest::list_servers() const { return get_array(v1_servers().get(), "data", Presence::MANDATORY); } json_t* MaxRest::get_object(json_t* pObject, const string& key, Presence presence) const { json_t* pValue = json_object_get(pObject, key.c_str()); if (!pValue && (presence == Presence::MANDATORY)) { raise("Mandatory key '" + key + "' not present."); } return pValue; } json_t* MaxRest::get_leaf_object(json_t* pObject, const string& key, Presence presence) const { auto i = key.find("/"); if (i == string::npos) { pObject = get_object(pObject, key, presence); } else { string head = key.substr(0, i); string tail = key.substr(i + 1); pObject = get_object(pObject, head, Presence::MANDATORY); pObject = get_leaf_object(pObject, tail, presence); } return pObject; } unique_ptr MaxRest::parse(const string& json) const { json_error_t error; unique_ptr sRoot(json_loads(json.c_str(), 0, &error)); if (!sRoot) { raise("JSON parsing failed: " + string(error.text)); } return sRoot; } unique_ptr MaxRest::curl_get(const string& path) const { return curl(GET, path); } unique_ptr MaxRest::curl_post(const string& path) const { return curl(POST, path); } unique_ptr MaxRest::curl(Command command, const string& path) const { string url = "http://127.0.0.1:8989/v1/" + path; string curl_command = "curl -u admin:mariadb "; switch (command) { case GET: curl_command += "-X GET "; break; case POST: curl_command += "-X POST "; break; } curl_command += url; auto result = m_test.maxscales->ssh_output(curl_command.c_str(), 0, false); if (result.first != 0) { raise("Invocation of curl failed: " + to_string(result.first)); } unique_ptr sRv; if (!result.second.empty()) { sRv = parse(result.second); } return sRv; } void MaxRest::raise(const std::string& message) const { ++m_test.global_result; throw runtime_error(message); } template<> string MaxRest::get(json_t* pObject, const string& key, Presence presence) const { json_t* pValue = get_leaf_object(pObject, key, presence); if (pValue && !json_is_string(pValue)) { raise("Key '" + key + "' is present, but value is not a string."); } return pValue ? json_string_value(pValue) : ""; } template<> int64_t MaxRest::get(json_t* pObject, const string& key, Presence presence) const { json_t* pValue = get_leaf_object(pObject, key, presence); if (pValue && !json_is_integer(pValue)) { raise("Key '" + key + "' is present, but value is not an integer."); } return pValue ? json_integer_value(pValue) : 0; }