]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw/lua: allow setting metadata via lua
authorYuval Lifshitz <ylifshit@redhat.com>
Tue, 13 Oct 2020 16:54:18 +0000 (19:54 +0300)
committerYuval Lifshitz <ylifshit@redhat.com>
Fri, 30 Oct 2020 08:40:06 +0000 (10:40 +0200)
Signed-off-by: Yuval Lifshitz <ylifshit@redhat.com>
doc/radosgw/lua-scripting.rst
src/rgw/rgw_lua_request.cc
src/rgw/rgw_lua_utils.h
src/test/rgw/test_rgw_lua.cc

index 6c79dce5c05729d90479863068a9419d05405b59..a5dbc8710e1656add1639e760d5a2c336032c075 100644 (file)
@@ -202,7 +202,7 @@ Request Fields
 +----------------------------------------------------+----------+--------------------------------------------------------------+----------+-----------+----------+
 | ``Request.HTTP.Resources``                         | table    | string to string resource map                                | yes      | no        | no       |
 +----------------------------------------------------+----------+--------------------------------------------------------------+----------+-----------+----------+
-| ``Request.HTTP.Metadata``                          | table    | string to string metadata map                                | yes      | no        | no       |
+| ``Request.HTTP.Metadata``                          | table    | string to string metadata map                                | yes      | yes       | no       |
 +----------------------------------------------------+----------+--------------------------------------------------------------+----------+-----------+----------+
 | ``Request.HTTP.Host``                              | string   | host name                                                    | no       | no        | no       |
 +----------------------------------------------------+----------+--------------------------------------------------------------+----------+-----------+----------+
@@ -290,7 +290,6 @@ Lua Code Samples
 - Use of operations log only in case of errors:
 
 .. code-block:: lua
-
   
   if Request.Response.HTTPStatusCode ~= 200 then
     RGWDebugLog("request is bad, use ops log")
@@ -306,3 +305,22 @@ Lua Code Samples
     Request.Response.Message = "<Message> something bad happened :-( </Message>"
   end
 
+- Add metadata to objects that was not originally sent by the client:
+
+In the `preRequest` context we should add:
+
+.. code-block:: lua
+
+  if Request.RGWOp == 'put_obj' then
+    Request.HTTP.Metadata["x-amz-meta-mydata"] = "my value"
+  end
+
+In the `postRequest` context we look at the metadata:
+
+.. code-block:: lua
+
+  RGWDebugLog("number of metadata entries is: " .. #Request.HTTP.Metadata)
+  for k, v in pairs(Request.HTTP.Metadata) do
+    RGWDebugLog("key=" .. k .. ", " .. "value=" .. v)
+  end
index 8a65426af33f709d7cc70d1b108c81f8cf080711..6e3b148df3aac404286b8f3e0b468594202fd6d9 100644 (file)
@@ -80,7 +80,7 @@ struct ResponseMetaTable : public EmptyMetaTable {
     } else {
       throw_unknown_field(index, TableName());
     }
-    return ONE_RETURNVAL;
+    return NO_RETURNVAL;
   }
 };
 
@@ -244,7 +244,22 @@ struct ObjectMetaTable : public EmptyMetaTable {
   }
 };
 
-template<typename MapType=std::map<std::string, std::string>>
+typedef int MetaTableClosure(lua_State* L);
+
+template<typename MapType>
+int StringMapWriteableNewIndex(lua_State* L) {
+  const auto map = reinterpret_cast<MapType*>(lua_touserdata(L, lua_upvalueindex(1)));
+
+  ceph_assert(lua_isstring(L, -1));
+  ceph_assert(lua_isstring(L, -2));
+  const char* value = lua_tostring(L, -1);
+  const char* index = lua_tostring(L, -2);
+  map->insert_or_assign(index, value);
+  return NO_RETURNVAL;
+}
+
+template<typename MapType=std::map<std::string, std::string>,
+  MetaTableClosure NewIndex=EmptyMetaTable::NewIndexClosure>
 struct StringMapMetaTable : public EmptyMetaTable {
 
   static std::string TableName() {return "StringMap";}
@@ -265,6 +280,10 @@ struct StringMapMetaTable : public EmptyMetaTable {
     return ONE_RETURNVAL;
   }
 
+  static int NewIndexClosure(lua_State* L) {
+    return NewIndex(L);
+  }
+
   static int PairsClosure(lua_State* L) {
     auto map = reinterpret_cast<MapType*>(lua_touserdata(L, lua_upvalueindex(1)));
     ceph_assert(map);
@@ -628,7 +647,7 @@ struct HTTPMetaTable : public EmptyMetaTable {
       create_metatable<StringMapMetaTable<>>(L, false, 
           const_cast<std::map<std::string, std::string>*>(&(info->args.get_sub_resources())));
     } else if (strcasecmp(index, "Metadata") == 0) {
-      create_metatable<StringMapMetaTable<meta_map_t>>(L, false, &(info->x_meta_map));
+      create_metatable<StringMapMetaTable<meta_map_t, StringMapWriteableNewIndex<meta_map_t>>>(L, false, &(info->x_meta_map));
     } else if (strcasecmp(index, "Host") == 0) {
       pushstring(L, info->host);
     } else if (strcasecmp(index, "Method") == 0) {
index 2c4d724a6f25a8628bcbd491b55a081f3c220243..e3a7a132cb18e5206f1fca32457e1920a5525d87 100644 (file)
@@ -43,6 +43,7 @@ constexpr auto THREE_UPVALS = 3;
 constexpr auto FOUR_UPVALS  = 4;
 constexpr auto FIVE_UPVALS  = 5;
 
+constexpr auto NO_RETURNVAL    = 0;
 constexpr auto ONE_RETURNVAL    = 1;
 constexpr auto TWO_RETURNVALS   = 2;
 constexpr auto THREE_RETURNVALS = 3;
@@ -143,21 +144,21 @@ struct EmptyMetaTable {
   // to change, overload this function in the derived
   static int NewIndexClosure(lua_State* L) {
     throw std::runtime_error("trying to write to readonly field");
-    return 1;
+    return NO_RETURNVAL;
   }
   
   // by default nothing is iterable
   // to change, overload this function in the derived
   static int PairsClosure(lua_State* L) {
     throw std::runtime_error("trying to iterate over non-iterable field");
-    return 1;
+    return ONE_RETURNVAL;
   }
   
   // by default nothing is iterable
   // to change, overload this function in the derived
   static int LenClosure(lua_State* L) {
     throw std::runtime_error("trying to get length of non-iterable field");
-    return 1;
+    return ONE_RETURNVAL;
   }
 
   static void throw_unknown_field(const std::string& index, const std::string& table) {
index 2df08bd3c2812a1de9d3ef068772bee102d6bd62..6cae8ebf0182fde472bea51a730adf2ec04fc435 100644 (file)
@@ -323,6 +323,48 @@ TEST(TestRGWLua, Tags)
   ASSERT_EQ(rc, 0);
 }
 
+TEST(TestRGWLua, TagsNotWriteable)
+{
+  const std::string script = R"(
+    Request.Tags["hello"] = "goodbye"
+  )";
+
+  DEFINE_REQ_STATE;
+  s.tagset.add_tag("hello", "world");
+
+  const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
+  ASSERT_NE(rc, 0);
+}
+
+TEST(TestRGWLua, Metadata)
+{
+  const std::string script = R"(
+    print("number of metadata entries is: " .. #Request.HTTP.Metadata)
+    for k, v in pairs(Request.HTTP.Metadata) do
+      print("key=" .. k .. ", " .. "value=" .. v)
+    end
+    print("value of 'hello' is:")
+    print(Request.HTTP.Metadata["hello"])
+    print("value of 'kaboom' is:")
+    print(Request.HTTP.Metadata["kaboom"])
+    Request.HTTP.Metadata["hello"] = "goodbye"
+    Request.HTTP.Metadata["kaboom"] = "boom"
+    print("new number of metadata entries is: " .. #Request.HTTP.Metadata)
+    print("new value of 'hello' is:")
+    print(Request.HTTP.Metadata["hello"])
+    print("new value of 'kaboom' is:")
+    print(Request.HTTP.Metadata["kaboom"])
+  )";
+
+  DEFINE_REQ_STATE;
+  s.info.x_meta_map["hello"] = "world";
+  s.info.x_meta_map["foo"] = "bar";
+  s.info.x_meta_map["ka"] = "boom";
+
+  const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script);
+  ASSERT_EQ(rc, 0);
+}
+
 TEST(TestRGWLua, Acl)
 {
   const std::string script = R"(