Implement vitastor-cli ls-user, modify-user, remove-user commands
This commit is contained in:
@@ -15,7 +15,6 @@ add_custom_command(
|
|||||||
add_library(vitastor_cli STATIC
|
add_library(vitastor_cli STATIC
|
||||||
cli_common.cpp
|
cli_common.cpp
|
||||||
cli_alloc_osd.cpp
|
cli_alloc_osd.cpp
|
||||||
cli_status.cpp
|
|
||||||
cli_describe.cpp
|
cli_describe.cpp
|
||||||
cli_fix.cpp
|
cli_fix.cpp
|
||||||
cli_ls.cpp
|
cli_ls.cpp
|
||||||
@@ -23,6 +22,7 @@ add_library(vitastor_cli STATIC
|
|||||||
cli_dd.cpp
|
cli_dd.cpp
|
||||||
cli_modify.cpp
|
cli_modify.cpp
|
||||||
cli_modify_osd.cpp
|
cli_modify_osd.cpp
|
||||||
|
cli_modify_user.cpp
|
||||||
cli_osd_tree.cpp
|
cli_osd_tree.cpp
|
||||||
cli_pg_ls.cpp
|
cli_pg_ls.cpp
|
||||||
cli_flatten.cpp
|
cli_flatten.cpp
|
||||||
@@ -37,6 +37,8 @@ add_library(vitastor_cli STATIC
|
|||||||
cli_pool_modify.cpp
|
cli_pool_modify.cpp
|
||||||
cli_pool_rm.cpp
|
cli_pool_rm.cpp
|
||||||
cli_serve.cpp
|
cli_serve.cpp
|
||||||
|
cli_status.cpp
|
||||||
|
cli_user_ls.cpp
|
||||||
${OPENAPI_JSON_H}
|
${OPENAPI_JSON_H}
|
||||||
)
|
)
|
||||||
target_compile_options(vitastor_cli PUBLIC -fPIC)
|
target_compile_options(vitastor_cli PUBLIC -fPIC)
|
||||||
|
|||||||
@@ -244,6 +244,17 @@ static const char* help_text =
|
|||||||
" -r|--reverse Sort in descending order\n"
|
" -r|--reverse Sort in descending order\n"
|
||||||
" -n|--count N Only list first N items\n"
|
" -n|--count N Only list first N items\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"vitastor-cli ls-users|user-ls|ls-user|list-users [<name> ...]\n"
|
||||||
|
" List users (only with specified names if passed).\n"
|
||||||
|
"\n"
|
||||||
|
"vitastor-cli modify-user --type <type> --groups group1,group2,... <username>\n"
|
||||||
|
" Create or update user permissions. User names match CN of their certificates.\n"
|
||||||
|
" --type TYPE Set user type: client, admin, mon or osd. Default is client.\n"
|
||||||
|
" --groups GROUPS Set user's groups.\n"
|
||||||
|
"\n"
|
||||||
|
"vitastor-cli rm-user|remove-user|delete-user <username>\n"
|
||||||
|
" Remove a user.\n"
|
||||||
|
"\n"
|
||||||
"vitastor-cli serve\n"
|
"vitastor-cli serve\n"
|
||||||
" Start HTTP server able to handle CLI commands over a REST API. Options:\n"
|
" Start HTTP server able to handle CLI commands over a REST API. Options:\n"
|
||||||
" --bind_address ADDR Specify server IP address or addresses, separated by space. Default is 127.0.0.1.\n"
|
" --bind_address ADDR Specify server IP address or addresses, separated by space. Default is 127.0.0.1.\n"
|
||||||
@@ -574,6 +585,35 @@ std::function<bool(cli_result_t &)> cli_tool_t::start(json11::Json::object cfg,
|
|||||||
}
|
}
|
||||||
action_cb = start_pool_ls(cfg);
|
action_cb = start_pool_ls(cfg);
|
||||||
}
|
}
|
||||||
|
else if (cmd[0] == "user-ls" || cmd[0] == "ls-user" || cmd[0] == "ls-users" || cmd[0] == "list-users")
|
||||||
|
{
|
||||||
|
// List users
|
||||||
|
if (cmd.size() > 1)
|
||||||
|
{
|
||||||
|
cmd.erase(cmd.begin(), cmd.begin()+1);
|
||||||
|
cfg["names"] = cmd;
|
||||||
|
}
|
||||||
|
action_cb = start_user_ls(cfg);
|
||||||
|
}
|
||||||
|
else if (cmd[0] == "modify-user" || cmd[0] == "user-modify")
|
||||||
|
{
|
||||||
|
// Create/update user
|
||||||
|
if (cmd.size() > 1)
|
||||||
|
{
|
||||||
|
cfg["name"] = cmd[1];
|
||||||
|
}
|
||||||
|
action_cb = start_modify_user(cfg);
|
||||||
|
}
|
||||||
|
else if (cmd[0] == "rm-user" || cmd[0] == "remove-user" || cmd[0] == "delete-user")
|
||||||
|
{
|
||||||
|
// Remove user
|
||||||
|
if (cmd.size() > 1)
|
||||||
|
{
|
||||||
|
cfg["name"] = cmd[1];
|
||||||
|
}
|
||||||
|
cfg["remove"] = true;
|
||||||
|
action_cb = start_modify_user(cfg);
|
||||||
|
}
|
||||||
else if (cmd[0] == "serve")
|
else if (cmd[0] == "serve")
|
||||||
{
|
{
|
||||||
// Start HTTP server
|
// Start HTTP server
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ public:
|
|||||||
std::function<bool(cli_result_t &)> start_merge(json11::Json);
|
std::function<bool(cli_result_t &)> start_merge(json11::Json);
|
||||||
std::function<bool(cli_result_t &)> start_modify(json11::Json);
|
std::function<bool(cli_result_t &)> start_modify(json11::Json);
|
||||||
std::function<bool(cli_result_t &)> start_modify_osd(json11::Json);
|
std::function<bool(cli_result_t &)> start_modify_osd(json11::Json);
|
||||||
|
std::function<bool(cli_result_t &)> start_modify_user(json11::Json);
|
||||||
std::function<bool(cli_result_t &)> start_osd_tree(json11::Json);
|
std::function<bool(cli_result_t &)> start_osd_tree(json11::Json);
|
||||||
std::function<bool(cli_result_t &)> start_pg_list(json11::Json);
|
std::function<bool(cli_result_t &)> start_pg_list(json11::Json);
|
||||||
std::function<bool(cli_result_t &)> start_pool_create(json11::Json);
|
std::function<bool(cli_result_t &)> start_pool_create(json11::Json);
|
||||||
@@ -81,6 +82,7 @@ public:
|
|||||||
std::function<bool(cli_result_t &)> start_rm_wildcard(json11::Json);
|
std::function<bool(cli_result_t &)> start_rm_wildcard(json11::Json);
|
||||||
std::function<bool(cli_result_t &)> start_serve(json11::Json);
|
std::function<bool(cli_result_t &)> start_serve(json11::Json);
|
||||||
std::function<bool(cli_result_t &)> start_status(json11::Json);
|
std::function<bool(cli_result_t &)> start_status(json11::Json);
|
||||||
|
std::function<bool(cli_result_t &)> start_user_ls(json11::Json);
|
||||||
|
|
||||||
// Should be called like loop_and_wait(start_status(), <completion callback>)
|
// Should be called like loop_and_wait(start_status(), <completion callback>)
|
||||||
void loop_and_wait(std::function<bool(cli_result_t &)> loop_cb, std::function<void(const cli_result_t &)> complete_cb);
|
void loop_and_wait(std::function<bool(cli_result_t &)> loop_cb, std::function<void(const cli_result_t &)> complete_cb);
|
||||||
|
|||||||
@@ -0,0 +1,161 @@
|
|||||||
|
// Copyright (c) Vitaliy Filippov, 2019+
|
||||||
|
// License: VNPL-1.1 (see README.md for details)
|
||||||
|
|
||||||
|
#include "cli.h"
|
||||||
|
#include "cluster_client.h"
|
||||||
|
#include "str_util.h"
|
||||||
|
|
||||||
|
// Create/update/delete a user
|
||||||
|
struct cli_modify_user_t
|
||||||
|
{
|
||||||
|
cli_tool_t *parent;
|
||||||
|
|
||||||
|
std::string user_name;
|
||||||
|
std::string user_type;
|
||||||
|
json11::Json groups;
|
||||||
|
bool del = false;
|
||||||
|
|
||||||
|
int state = 0;
|
||||||
|
cli_result_t result;
|
||||||
|
etcd_kv_t kv;
|
||||||
|
json11::Json::object new_cfg;
|
||||||
|
|
||||||
|
bool is_done()
|
||||||
|
{
|
||||||
|
return state == 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if (state == 1)
|
||||||
|
goto resume_1;
|
||||||
|
else if (state == 2)
|
||||||
|
goto resume_2;
|
||||||
|
if (user_type != "client" && user_type != "admin" && user_type != "mon" && user_type != "osd")
|
||||||
|
{
|
||||||
|
result = (cli_result_t){ .err = EINVAL, .text = "Unknown user type: "+user_type };
|
||||||
|
state = 100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (groups.is_string())
|
||||||
|
{
|
||||||
|
groups = groups == "" ? std::vector<std::string>() : explode(",", groups.string_value(), true);
|
||||||
|
}
|
||||||
|
else if (groups.is_array())
|
||||||
|
{
|
||||||
|
for (auto & gr: groups.array_items())
|
||||||
|
{
|
||||||
|
if (!gr.is_string())
|
||||||
|
{
|
||||||
|
result = (cli_result_t){ .err = EINVAL, .text = "Group names must be strings" };
|
||||||
|
state = 100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!groups.is_null())
|
||||||
|
{
|
||||||
|
result = (cli_result_t){ .err = EINVAL, .text = "Group names must be strings" };
|
||||||
|
state = 100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (user_name == "")
|
||||||
|
{
|
||||||
|
result = (cli_result_t){ .err = EINVAL, .text = "User name must not be empty" };
|
||||||
|
state = 100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parent->etcd_txn(json11::Json::object {
|
||||||
|
{ "success", json11::Json::array { json11::Json::object {
|
||||||
|
{ "request_range", json11::Json::object {
|
||||||
|
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/config/user/"+user_name) },
|
||||||
|
} },
|
||||||
|
} } }
|
||||||
|
});
|
||||||
|
state = 1;
|
||||||
|
resume_1:
|
||||||
|
if (parent->waiting > 0)
|
||||||
|
return;
|
||||||
|
if (parent->etcd_err.err)
|
||||||
|
{
|
||||||
|
result = parent->etcd_err;
|
||||||
|
state = 100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
kv = parent->cli->st_cli.parse_etcd_kv(parent->etcd_result["responses"][0]["response_range"]["kvs"][0]);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
new_cfg = kv.value.object_items();
|
||||||
|
if (!kv.mod_revision && del)
|
||||||
|
{
|
||||||
|
result = (cli_result_t){ .err = ENOENT, .text = "User "+user_name+" does not exist" };
|
||||||
|
state = 100;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!groups.is_null())
|
||||||
|
new_cfg["groups"] = groups;
|
||||||
|
if (user_type != "")
|
||||||
|
new_cfg["type"] = user_type;
|
||||||
|
if (!new_cfg["type"].is_string())
|
||||||
|
new_cfg["type"] = "client";
|
||||||
|
parent->etcd_txn(json11::Json::object {
|
||||||
|
{ "compare", json11::Json::array { json11::Json::object {
|
||||||
|
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/config/user/"+user_name) },
|
||||||
|
{ "target", kv.mod_revision ? "MOD" : "VERSION" },
|
||||||
|
{ kv.mod_revision ? "mod_revision" : "version", kv.mod_revision },
|
||||||
|
} } },
|
||||||
|
{ "success", json11::Json::array {
|
||||||
|
del ? json11::Json::object { { "request_delete_range", json11::Json::object {
|
||||||
|
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/config/user/"+user_name) },
|
||||||
|
} } } : json11::Json::object { { "request_put", json11::Json::object {
|
||||||
|
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/config/user/"+user_name) },
|
||||||
|
{ "value", base64_encode(json11::Json(new_cfg).dump()) }
|
||||||
|
} } },
|
||||||
|
} },
|
||||||
|
{ "failure", json11::Json::array { json11::Json::object {
|
||||||
|
{ "request_range", json11::Json::object {
|
||||||
|
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/config/user/"+user_name) },
|
||||||
|
} },
|
||||||
|
} } },
|
||||||
|
});
|
||||||
|
state = 2;
|
||||||
|
resume_2:
|
||||||
|
if (parent->waiting > 0)
|
||||||
|
return;
|
||||||
|
if (parent->etcd_err.err)
|
||||||
|
{
|
||||||
|
result = parent->etcd_err;
|
||||||
|
state = 100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (parent->etcd_result["succeeded"].bool_value())
|
||||||
|
break;
|
||||||
|
kv = parent->cli->st_cli.parse_etcd_kv(parent->etcd_result["responses"][0]["response_range"]["kvs"][0]);
|
||||||
|
}
|
||||||
|
state = 100;
|
||||||
|
result.text = del ? "User "+user_name+" removed" : "User "+user_name+" modified";
|
||||||
|
new_cfg["name"] = user_name;
|
||||||
|
result.data = del ? json11::Json::object{ { "ok", true } } : new_cfg;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::function<bool(cli_result_t &)> cli_tool_t::start_modify_user(json11::Json cfg)
|
||||||
|
{
|
||||||
|
auto creator = new cli_modify_user_t();
|
||||||
|
creator->parent = this;
|
||||||
|
creator->user_name = cfg["name"].string_value();
|
||||||
|
creator->user_type = cfg["type"].string_value();
|
||||||
|
creator->groups = cfg["groups"];
|
||||||
|
creator->del = cfg["remove"].bool_value();
|
||||||
|
return [creator](cli_result_t & result)
|
||||||
|
{
|
||||||
|
creator->loop();
|
||||||
|
if (creator->is_done())
|
||||||
|
{
|
||||||
|
result = creator->result;
|
||||||
|
delete creator;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -59,6 +59,9 @@ struct cli_serve_t
|
|||||||
{"pool/delete", {"rm-pool", false}},
|
{"pool/delete", {"rm-pool", false}},
|
||||||
{"pool/list", {"pools", true}},
|
{"pool/list", {"pools", true}},
|
||||||
{"pool/modify", {"modify-pool", false}},
|
{"pool/modify", {"modify-pool", false}},
|
||||||
|
{"user/delete", {"remove-user", false}},
|
||||||
|
{"user/list", {"ls-user", false}},
|
||||||
|
{"user/modify", {"modify-user", false}},
|
||||||
{"status", {"status", true}},
|
{"status", {"status", true}},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
// Copyright (c) Vitaliy Filippov, 2019+
|
||||||
|
// License: VNPL-1.1 (see README.md for details)
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include "cli.h"
|
||||||
|
#include "cluster_client.h"
|
||||||
|
#include "str_util.h"
|
||||||
|
#include "json_util.h"
|
||||||
|
|
||||||
|
// List users
|
||||||
|
struct user_lister_t
|
||||||
|
{
|
||||||
|
cli_tool_t *parent;
|
||||||
|
std::vector<std::string> only_names;
|
||||||
|
|
||||||
|
int state = 0;
|
||||||
|
cli_result_t result;
|
||||||
|
json11::Json::array users;
|
||||||
|
|
||||||
|
bool is_done()
|
||||||
|
{
|
||||||
|
return state == 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if (state == 1)
|
||||||
|
goto resume_1;
|
||||||
|
if (state == 100)
|
||||||
|
return;
|
||||||
|
{
|
||||||
|
json11::Json::array select;
|
||||||
|
if (!only_names.size())
|
||||||
|
{
|
||||||
|
select.push_back(json11::Json::object {
|
||||||
|
{ "request_range", json11::Json::object {
|
||||||
|
{ "key", base64_encode(
|
||||||
|
parent->cli->st_cli.etcd_prefix+"/config/user/"
|
||||||
|
) },
|
||||||
|
{ "range_end", base64_encode(
|
||||||
|
parent->cli->st_cli.etcd_prefix+"/config/user0"
|
||||||
|
) },
|
||||||
|
} },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto & name: only_names)
|
||||||
|
{
|
||||||
|
select.push_back(json11::Json::object {
|
||||||
|
{ "request_range", json11::Json::object {
|
||||||
|
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/config/user/"+name) },
|
||||||
|
} }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent->etcd_txn(json11::Json::object {
|
||||||
|
{ "success", select },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
state = 1;
|
||||||
|
resume_1:
|
||||||
|
if (parent->waiting > 0)
|
||||||
|
return;
|
||||||
|
if (parent->etcd_err.err)
|
||||||
|
{
|
||||||
|
result = parent->etcd_err;
|
||||||
|
state = 100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (auto & response: parent->etcd_result["responses"].array_items())
|
||||||
|
{
|
||||||
|
for (auto & kv_item: response["response_range"]["kvs"].array_items())
|
||||||
|
{
|
||||||
|
auto kv = parent->cli->st_cli.parse_etcd_kv(kv_item);
|
||||||
|
auto user = kv.value.object_items();
|
||||||
|
user["name"] = kv.key.substr(parent->cli->st_cli.etcd_prefix.size()+13);
|
||||||
|
if (!parent->json_output)
|
||||||
|
user["groups_fmt"] = implode(",", user["groups"].array_items());
|
||||||
|
users.push_back(std::move(user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parent->json_output)
|
||||||
|
{
|
||||||
|
// JSON output
|
||||||
|
result.data = users;
|
||||||
|
state = 100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Table output: name, type, groups
|
||||||
|
json11::Json::array cols;
|
||||||
|
cols.push_back(json11::Json::object{
|
||||||
|
{ "key", "name" },
|
||||||
|
{ "title", "NAME" },
|
||||||
|
});
|
||||||
|
cols.push_back(json11::Json::object{
|
||||||
|
{ "key", "type" },
|
||||||
|
{ "title", "TYPE" },
|
||||||
|
});
|
||||||
|
cols.push_back(json11::Json::object{
|
||||||
|
{ "key", "groups_fmt" },
|
||||||
|
{ "title", "GROUPS" },
|
||||||
|
});
|
||||||
|
result.text = print_table(users, cols, parent->color);
|
||||||
|
state = 100;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::function<bool(cli_result_t &)> cli_tool_t::start_user_ls(json11::Json cfg)
|
||||||
|
{
|
||||||
|
auto lister = new user_lister_t();
|
||||||
|
lister->parent = this;
|
||||||
|
if (cfg["names"].is_string())
|
||||||
|
lister->only_names.push_back(cfg["names"].string_value());
|
||||||
|
for (auto & item: cfg["names"].array_items())
|
||||||
|
lister->only_names.push_back(item.string_value());
|
||||||
|
return [lister](cli_result_t & result)
|
||||||
|
{
|
||||||
|
lister->loop();
|
||||||
|
if (lister->is_done())
|
||||||
|
{
|
||||||
|
result = lister->result;
|
||||||
|
delete lister;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
+91
-1
@@ -117,6 +117,7 @@
|
|||||||
"responses": {
|
"responses": {
|
||||||
"200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Image" } } } },
|
"200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Image" } } } },
|
||||||
"400": { "$ref": "#/components/responses/Invalid" },
|
"400": { "$ref": "#/components/responses/Invalid" },
|
||||||
|
"403": { "$ref": "#/components/responses/Forbidden" },
|
||||||
"409": { "$ref": "#/components/responses/UpdateConflict" },
|
"409": { "$ref": "#/components/responses/UpdateConflict" },
|
||||||
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
||||||
}
|
}
|
||||||
@@ -159,6 +160,7 @@
|
|||||||
"responses": {
|
"responses": {
|
||||||
"200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Image" } } } },
|
"200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Image" } } } },
|
||||||
"400": { "$ref": "#/components/responses/Invalid" },
|
"400": { "$ref": "#/components/responses/Invalid" },
|
||||||
|
"403": { "$ref": "#/components/responses/Forbidden" },
|
||||||
"409": { "$ref": "#/components/responses/UpdateConflict" },
|
"409": { "$ref": "#/components/responses/UpdateConflict" },
|
||||||
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
||||||
}
|
}
|
||||||
@@ -208,6 +210,7 @@
|
|||||||
}
|
}
|
||||||
} } } },
|
} } } },
|
||||||
"400": { "$ref": "#/components/responses/Invalid" },
|
"400": { "$ref": "#/components/responses/Invalid" },
|
||||||
|
"403": { "$ref": "#/components/responses/Forbidden" },
|
||||||
"409": { "$ref": "#/components/responses/UpdateConflict" },
|
"409": { "$ref": "#/components/responses/UpdateConflict" },
|
||||||
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
||||||
}
|
}
|
||||||
@@ -227,6 +230,7 @@
|
|||||||
"responses": {
|
"responses": {
|
||||||
"200": { "content": { "text/plain": { "schema": { "type": "string", "description": "Empty response" } } } },
|
"200": { "content": { "text/plain": { "schema": { "type": "string", "description": "Empty response" } } } },
|
||||||
"400": { "$ref": "#/components/responses/Invalid" },
|
"400": { "$ref": "#/components/responses/Invalid" },
|
||||||
|
"403": { "$ref": "#/components/responses/Forbidden" },
|
||||||
"409": { "$ref": "#/components/responses/UpdateConflict" },
|
"409": { "$ref": "#/components/responses/UpdateConflict" },
|
||||||
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
||||||
}
|
}
|
||||||
@@ -419,7 +423,7 @@
|
|||||||
}
|
}
|
||||||
} },
|
} },
|
||||||
"/pool/delete": { "post": {
|
"/pool/delete": { "post": {
|
||||||
"summary": "Delete an pool",
|
"summary": "Delete a pool",
|
||||||
"operationId": "poolDelete",
|
"operationId": "poolDelete",
|
||||||
"consumes": [ "application/json" ],
|
"consumes": [ "application/json" ],
|
||||||
"produces": [ "application/json" ],
|
"produces": [ "application/json" ],
|
||||||
@@ -441,6 +445,66 @@
|
|||||||
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
||||||
}
|
}
|
||||||
} },
|
} },
|
||||||
|
"/user/list": { "get": {
|
||||||
|
"summary": "List users",
|
||||||
|
"operationId": "userListGet",
|
||||||
|
"produces": [ "application/json" ],
|
||||||
|
"parameters": [ {
|
||||||
|
"name": "params",
|
||||||
|
"in": "query",
|
||||||
|
"schema": { "$ref": "#/components/schemas/UserListParams" },
|
||||||
|
"style": "form",
|
||||||
|
"explode": true
|
||||||
|
} ],
|
||||||
|
"responses": {
|
||||||
|
"200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserList" } } } }
|
||||||
|
}
|
||||||
|
}, "post": {
|
||||||
|
"summary": "List users",
|
||||||
|
"operationId": "userListPost",
|
||||||
|
"consumes": [ "application/json" ],
|
||||||
|
"produces": [ "application/json" ],
|
||||||
|
"requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserListParams" } } } },
|
||||||
|
"responses": {
|
||||||
|
"200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserList" } } } }
|
||||||
|
}
|
||||||
|
} },
|
||||||
|
"/user/modify": { "post": {
|
||||||
|
"summary": "Modify a user",
|
||||||
|
"operationId": "userModify",
|
||||||
|
"consumes": [ "application/json" ],
|
||||||
|
"produces": [ "application/json" ],
|
||||||
|
"requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } } },
|
||||||
|
"responses": {
|
||||||
|
"200": { "content": { "application/json": { "schema": {
|
||||||
|
"$ref": "#/components/schemas/User"
|
||||||
|
} } } },
|
||||||
|
"400": { "$ref": "#/components/responses/Invalid" },
|
||||||
|
"409": { "$ref": "#/components/responses/UpdateConflict" },
|
||||||
|
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
||||||
|
}
|
||||||
|
} },
|
||||||
|
"/user/delete": { "post": {
|
||||||
|
"summary": "Delete a user",
|
||||||
|
"operationId": "userDelete",
|
||||||
|
"consumes": [ "application/json" ],
|
||||||
|
"produces": [ "application/json" ],
|
||||||
|
"requestBody": { "content": { "application/json": { "schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": { "type": "string", "description": "User name to delete" }
|
||||||
|
}
|
||||||
|
} } } },
|
||||||
|
"responses": {
|
||||||
|
"200": { "content": { "application/json": { "schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": { "ok": { "type": "boolean" } }
|
||||||
|
} } } },
|
||||||
|
"400": { "$ref": "#/components/responses/Invalid" },
|
||||||
|
"409": { "$ref": "#/components/responses/UpdateConflict" },
|
||||||
|
"412": { "$ref": "#/components/responses/PreconditionFailed" }
|
||||||
|
}
|
||||||
|
} },
|
||||||
"/pg/list": { "get": {
|
"/pg/list": { "get": {
|
||||||
"summary": "List PGs",
|
"summary": "List PGs",
|
||||||
"operationId": "pgListGet",
|
"operationId": "pgListGet",
|
||||||
@@ -611,6 +675,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Forbidden": {
|
||||||
|
"description": "Access Denied (EACCES)",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": { "type": "string", "description": "Error text" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"PreconditionFailed": {
|
"PreconditionFailed": {
|
||||||
"description": "Precondition Failed (ENOTEMPTY, EEXIST or ENOENT)",
|
"description": "Precondition Failed (ENOTEMPTY, EEXIST or ENOENT)",
|
||||||
"content": {
|
"content": {
|
||||||
@@ -860,6 +932,24 @@
|
|||||||
} } ]
|
} } ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"UserListParams": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"names": { "type": "array", "items": { "type": "string" }, "description": "User names to list" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"UserList": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "$ref": "#/components/schemas/User" }
|
||||||
|
},
|
||||||
|
"User": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": { "type": "string", "description": "User name" },
|
||||||
|
"type": { "type": "string", "enum": [ "osd", "mon", "admin", "client" ], "description": "User type" },
|
||||||
|
"groups": { "type": "array", "items": { "type": "string" }, "description": "User group names" }
|
||||||
|
}
|
||||||
|
},
|
||||||
"PgListParams": {
|
"PgListParams": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
Reference in New Issue
Block a user