Skip to content
This repository has been archived by the owner on Jun 23, 2022. It is now read-only.

feat(http): add http interface for get_app_envs #321

Merged
merged 19 commits into from
Oct 9, 2019
50 changes: 50 additions & 0 deletions src/dist/replication/meta_server/meta_http_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,56 @@ void meta_http_service::get_cluster_info_handler(const http_request &req, http_r
resp.status_code = http_status_code::ok;
}

void meta_http_service::get_app_envs_handler(const http_request &req, http_response &resp)
{
// only primary process the request
if (!redirect_if_not_primary(req, resp))
return;

std::string app_name;
for (const auto &p : req.query_args) {
if ("name" == p.first) {
app_name = p.second;
break;
}
}

// app name must be set
if (app_name.empty()) {
resp.status_code = http_status_code::bad_request;
levy5307 marked this conversation as resolved.
Show resolved Hide resolved
resp.body = "app name cann't be empty";
levy5307 marked this conversation as resolved.
Show resolved Hide resolved
return;
}

// get all of the apps
configuration_list_apps_response response;
configuration_list_apps_request request;
request.status = dsn::app_status::AS_AVAILABLE;
_service->_state->list_apps(request, response);
if (response.err != dsn::ERR_OK) {
resp.body = response.err.to_string();
resp.status_code = http_status_code::internal_server_error;
return;
}

// using app envs to generate a table_printer
dsn::utils::table_printer tp;
for (auto &app : response.infos) {
if (app.app_name == app_name) {
for (auto env : app.envs) {
tp.add_row_name_and_data(env.first, env.second);
}
break;
}
}

// output as json format
std::ostringstream out;
tp.output(out, dsn::utils::table_printer::output_format::kJsonCompact);
resp.body = out.str();
resp.status_code = http_status_code::ok;
}

bool meta_http_service::redirect_if_not_primary(const http_request &req, http_response &resp)
{
#ifdef DSN_MOCK_TEST
Expand Down
7 changes: 7 additions & 0 deletions src/dist/replication/meta_server/meta_http_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ class meta_http_service : public http_service
this,
std::placeholders::_1,
std::placeholders::_2));
// GET ip:port/meta/app_envs?name=temp
register_handler("app_envs",
std::bind(&meta_http_service::get_app_envs_handler,
this,
std::placeholders::_1,
std::placeholders::_2));
}

std::string path() const override { return "meta"; }
Expand All @@ -49,6 +55,7 @@ class meta_http_service : public http_service
void list_app_handler(const http_request &req, http_response &resp);
void list_node_handler(const http_request &req, http_response &resp);
void get_cluster_info_handler(const http_request &req, http_response &resp);
void get_app_envs_handler(const http_request &req, http_response &resp);

private:
// set redirect location if current server is not primary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,6 @@ class meta_app_envs_test : public meta_test_base
create_app(app_name);
}

error_code update_app_envs(const std::vector<std::string> &env_keys,
const std::vector<std::string> &env_vals)
{
auto req = make_unique<configuration_update_app_env_request>();
req->__set_app_name(std::move(app_name));
req->__set_op(std::move(app_env_operation::type::APP_ENV_OP_SET));
req->__set_keys(env_keys);
req->__set_values(env_vals);

app_env_rpc rpc(std::move(req), RPC_CM_UPDATE_APP_ENV); // don't need reply
_ss->set_app_envs(rpc);
_ss->wait_all_task();
return rpc.response().err;
}

const std::string app_name = "test_app_env";
const std::string env_slow_query_threshold = "replica.slow_query_threshold";
};
Expand All @@ -75,7 +60,7 @@ TEST_F(meta_app_envs_test, set_slow_query_threshold)
{ERR_INVALID_PARAMETERS, "0", "20"}};

for (auto test : tests) {
error_code err = update_app_envs({env_slow_query_threshold}, {test.env_value});
error_code err = update_app_envs(app_name, {env_slow_query_threshold}, {test.env_value});

ASSERT_EQ(err, test.err);
ASSERT_EQ(app->envs.at(env_slow_query_threshold), test.expect_env_value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
#include <dsn/tool-api/http_server.h>

#include "dist/replication/meta_server/meta_http_service.h"
#include "dist/replication/meta_server/meta_server_failure_detector.h"
#include "dist/replication/test/meta_test/misc/misc.h"

#include "meta_service_test_app.h"
#include "meta_test_base.h"

namespace dsn {
Expand All @@ -23,19 +19,16 @@ class meta_http_service_test : public meta_test_base
{
meta_test_base::SetUp();
_mhs = dsn::make_unique<meta_http_service>(_ms.get());
create_app(test_app);
neverchanje marked this conversation as resolved.
Show resolved Hide resolved
}

std::unique_ptr<meta_http_service> _mhs;

/// === Tests ===

void test_get_app_from_primary()
{
std::string test_app = "test_app";
create_app(test_app);
http_request fake_req;
http_response fake_resp;
fake_req.query_args.emplace("name", "test_app");
fake_req.query_args.emplace("name", test_app);
_mhs->get_app_handler(fake_req, fake_resp);

ASSERT_EQ(fake_resp.status_code, http_status_code::ok)
Expand All @@ -44,9 +37,36 @@ class meta_http_service_test : public meta_test_base
R"(","partition_count":"8","max_replica_count":"3"}})" + "\n";
ASSERT_EQ(fake_resp.body, fake_json);
}

void test_get_app_envs()
{
// set app env
std::string env_key = "test_env";
std::string env_value = "test_value";
update_app_envs(test_app, {env_key}, {env_value});

// http get app envs
http_request fake_req;
http_response fake_resp;
fake_req.query_args.emplace("name", test_app);
_mhs->get_app_envs_handler(fake_req, fake_resp);

// env (value_version, 1) was set by create_app
std::string fake_json = R"({")" + env_key + R"(":)" +
R"(")" + env_value + R"(",)" +
R"("value_version":"1"})" + "\n";
ASSERT_EQ(fake_resp.status_code, http_status_code::ok)
<< http_status_code_to_string(fake_resp.status_code);
ASSERT_EQ(fake_resp.body, fake_json);
}

std::unique_ptr<meta_http_service> _mhs;
std::string test_app = "test_meta_http";
};

TEST_F(meta_http_service_test, get_app_from_primary) { test_get_app_from_primary(); }

TEST_F(meta_http_service_test, get_app_envs) { test_get_app_envs(); }

} // namespace replication
} // namespace dsn
16 changes: 16 additions & 0 deletions src/dist/replication/test/meta_test/unit_test/meta_test_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,22 @@ class meta_test_base : public testing::Test
ASSERT_TRUE(_ss->spin_wait_staging(30));
}

error_code update_app_envs(const std::string &app_name,
const std::vector<std::string> &env_keys,
const std::vector<std::string> &env_vals)
{
auto req = make_unique<configuration_update_app_env_request>();
req->__set_app_name(std::move(app_name));
req->__set_op(std::move(app_env_operation::type::APP_ENV_OP_SET));
req->__set_keys(env_keys);
req->__set_values(env_vals);

app_env_rpc rpc(std::move(req), RPC_CM_UPDATE_APP_ENV); // don't need reply
_ss->set_app_envs(rpc);
_ss->wait_all_task();
return rpc.response().err;
}

std::shared_ptr<app_state> find_app(const std::string &name) { return _ss->get_app(name); }

meta_duplication_service &dup_svc() { return *(_ms->_dup_svc); }
Expand Down