]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add list user admin OP API
authorsongshuangyang <songshuangyang@baidu.com>
Tue, 13 Nov 2018 09:32:41 +0000 (17:32 +0800)
committerNathan Cutler <ncutler@suse.com>
Fri, 14 Feb 2020 12:35:56 +0000 (13:35 +0100)
The radosgw-admin tool support the `user list` subcommand to list radosgw users, but there is no user listing function for the admin OP API. It needs to support this API.

Signed-off-by: Oshyn Song <dualyangsong@gmail.com>
(cherry picked from commit 97e1ff50e57a51744a6d864cef15f9afe0e84b66)

Conflicts:
src/rgw/rgw_user.h
- needed to adapt the list_user RGWOp name() override

src/rgw/rgw_common.cc
src/rgw/rgw_rest_user.cc
src/rgw/rgw_user.cc
src/rgw/rgw_user.h

index c30b6af20bcfd1de52533cf862ed1c02d96208cf..ac765f9cad8519aed5ceeeb7d4ebfb171208cc6e 100644 (file)
@@ -942,6 +942,7 @@ void RGWHTTPArgs::append(const string& name, const string& val)
               (name.compare("index") == 0) ||
               (name.compare("policy") == 0) ||
               (name.compare("quota") == 0) ||
+              (name.compare("list") == 0) ||
               (name.compare("object") == 0)) {
 
     if (!admin_subresource_added) {
index bd561d0c470cf6183b512398cb996051f5a34918..2eaeaeb66c41cd0d123a4419e6b6324136ddeaec 100644 (file)
 
 #define dout_subsys ceph_subsys_rgw
 
+class RGWOp_User_List : public RGWRESTOp {
+
+public:
+  RGWOp_User_List() {}
+
+  int check_caps(RGWUserCaps& caps) override {
+    return caps.check_cap("users", RGW_CAP_READ);
+  }
+
+  void execute() override;
+
+  const string name() override { return "list_user"; }
+};
+
+void RGWOp_User_List::execute()
+{
+  RGWUserAdminOpState op_state;
+
+  uint32_t max_entries;
+  std::string marker;
+  RESTArgs::get_uint32(s, "max-entries", 1000, &max_entries);
+  RESTArgs::get_string(s, "marker", marker, &marker);
+
+  op_state.max_entries = max_entries;
+  op_state.marker = marker;
+  http_ret = RGWUserAdminOp_User::list(store, op_state, flusher);
+}
+
 class RGWOp_User_Info : public RGWRESTOp {
 
 public:
@@ -895,6 +923,9 @@ RGWOp *RGWHandler_User::op_get()
   if (s->info.args.sub_resource_exists("quota"))
     return new RGWOp_Quota_Info;
 
+  if (s->info.args.sub_resource_exists("list"))
+    return new RGWOp_User_List;
+
   return new RGWOp_User_Info;
 }
 
index ca0be3582308018910328e2c8bb2132e0c826b05..39f0d7879c95bd82964914ecf3d205809189df7c 100644 (file)
@@ -2312,6 +2312,77 @@ int RGWUser::info(RGWUserInfo& fetched_info, std::string *err_msg)
   return 0;
 }
 
+int RGWUser::list(RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher)
+{
+  Formatter *formatter = flusher.get_formatter();
+  void *handle = nullptr;
+  std::string metadata_key = "user";
+  if (op_state.max_entries > 1000) {
+    op_state.max_entries = 1000;
+  }
+
+  int ret = store->meta_mgr->list_keys_init(metadata_key, op_state.marker, &handle);
+  if (ret < 0) {
+    return ret;
+  }
+
+  bool truncated = false;
+  uint64_t count = 0;
+  uint64_t left = 0;
+  flusher.start(0);
+
+  // open the result object section
+  formatter->open_object_section("result");
+
+  // open the user id list array section
+  formatter->open_array_section("keys");
+  do {
+    std::list<std::string> keys;
+    left = op_state.max_entries - count;
+    ret = store->meta_mgr->list_keys_next(handle, left, keys, &truncated);
+    if (ret < 0 && ret != -ENOENT) {
+      return ret;
+    } if (ret != -ENOENT) {
+      for (std::list<std::string>::iterator iter = keys.begin(); iter != keys.end(); ++iter) {
+      formatter->dump_string("key", *iter);
+        ++count;
+      }
+    }
+  } while (truncated && left > 0);
+  // close user id list section
+  formatter->close_section();
+
+  formatter->dump_bool("truncated", truncated);
+  formatter->dump_int("count", count);
+  if (truncated) {
+    formatter->dump_string("marker", store->meta_mgr->get_marker(handle));
+  }
+
+  // close result object section
+  formatter->close_section();
+
+  store->meta_mgr->list_keys_complete(handle);
+
+  flusher.flush();
+  return 0;
+}
+
+int RGWUserAdminOp_User::list(RGWRados *store, RGWUserAdminOpState& op_state,
+                  RGWFormatterFlusher& flusher)
+{
+  RGWUser user;
+
+  int ret = user.init_storage(store);
+  if (ret < 0)
+    return ret;
+
+  ret = user.list(op_state, flusher);
+  if (ret < 0)
+    return ret;
+
+  return 0;
+}
+
 int RGWUserAdminOp_User::info(RGWRados *store, RGWUserAdminOpState& op_state,
                   RGWFormatterFlusher& flusher)
 {
index c9bca868bd4e00f395bad85e0500af54857dc0a4..ae5816e010cda636dec82af605bc6a80ea20d470 100644 (file)
@@ -226,6 +226,10 @@ struct RGWUserAdminOpState {
   RGWQuotaInfo bucket_quota;
   RGWQuotaInfo user_quota;
 
+  // req parameters for listing user
+  std::string marker;
+  uint32_t max_entries;
+
   void set_access_key(std::string& access_key) {
     if (access_key.empty())
       return;
@@ -534,6 +538,8 @@ struct RGWUserAdminOpState {
     found_by_email = false;
     found_by_key = false;
     mfa_ids_specified = false;
+    max_entries = 1000;
+    marker = "";
   }
 };
 
@@ -699,6 +705,9 @@ public:
   /* info from an already populated RGWUser */
   int info (RGWUserInfo& fetched_info, std::string *err_msg = NULL);
 
+  /* list the existing users */
+  int list(RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
+
   friend class RGWAccessKeyPool;
   friend class RGWSubUserPool;
   friend class RGWUserCapPool;
@@ -709,6 +718,9 @@ public:
 class RGWUserAdminOp_User
 {
 public:
+  static int list(RGWRados *store,
+                  RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
+
   static int info(RGWRados *store,
                   RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);