4 #include "common/dout.h"
5 #include "services/svc_zone.h"
6 #include "rgw_lua_utils.h"
8 #include "rgw_common.h"
10 #include "rgw_process.h"
13 #include "rgw_sal_rados.h"
15 #define dout_subsys ceph_subsys_rgw
17 namespace rgw::lua::request
{
19 // closure that perform ops log action
23 constexpr const char* RequestLogAction
{"Log"};
25 int RequestLog(lua_State
* L
)
27 const auto rest
= reinterpret_cast<RGWREST
*>(lua_touserdata(L
, lua_upvalueindex(1)));
28 const auto olog
= reinterpret_cast<OpsLogSink
*>(lua_touserdata(L
, lua_upvalueindex(2)));
29 const auto s
= reinterpret_cast<req_state
*>(lua_touserdata(L
, lua_upvalueindex(3)));
30 const std::string
op_name(reinterpret_cast<const char*>(lua_touserdata(L
, lua_upvalueindex(4))));
32 const auto rc
= rgw_log_op(rest
, s
, op_name
, olog
);
33 lua_pushinteger(L
, rc
);
35 ldpp_dout(s
, 1) << "Lua ERROR: missing request state, cannot use ops log" << dendl
;
36 lua_pushinteger(L
, -EINVAL
);
42 struct ResponseMetaTable
: public EmptyMetaTable
{
43 static std::string
TableName() {return "Response";}
44 static std::string
Name() {return TableName() + "Meta";}
46 static int IndexClosure(lua_State
* L
) {
47 const auto err
= reinterpret_cast<const rgw_err
*>(lua_touserdata(L
, lua_upvalueindex(1)));
49 const char* index
= luaL_checkstring(L
, 2);
51 if (strcasecmp(index
, "HTTPStatusCode") == 0) {
52 lua_pushinteger(L
, err
->http_ret
);
53 } else if (strcasecmp(index
, "RGWCode") == 0) {
54 lua_pushinteger(L
, err
->ret
);
55 } else if (strcasecmp(index
, "HTTPStatus") == 0) {
56 pushstring(L
, err
->err_code
);
57 } else if (strcasecmp(index
, "Message") == 0) {
58 pushstring(L
, err
->message
);
60 return error_unknown_field(L
, index
, TableName());
65 static int NewIndexClosure(lua_State
* L
) {
66 auto err
= reinterpret_cast<rgw_err
*>(lua_touserdata(L
, lua_upvalueindex(1)));
68 const char* index
= luaL_checkstring(L
, 2);
70 if (strcasecmp(index
, "HTTPStatusCode") == 0) {
71 err
->http_ret
= luaL_checkinteger(L
, 3);
72 } else if (strcasecmp(index
, "RGWCode") == 0) {
73 err
->ret
= luaL_checkinteger(L
, 3);
74 } else if (strcasecmp(index
, "HTTPStatus") == 0) {
75 err
->err_code
.assign(luaL_checkstring(L
, 3));
76 } else if (strcasecmp(index
, "Message") == 0) {
77 err
->message
.assign(luaL_checkstring(L
, 3));
79 return error_unknown_field(L
, index
, TableName());
85 struct QuotaMetaTable
: public EmptyMetaTable
{
86 static std::string
TableName() {return "Quota";}
87 static std::string
Name() {return TableName() + "Meta";}
89 static int IndexClosure(lua_State
* L
) {
90 const auto info
= reinterpret_cast<RGWQuotaInfo
*>(lua_touserdata(L
, lua_upvalueindex(1)));
92 const char* index
= luaL_checkstring(L
, 2);
94 if (strcasecmp(index
, "MaxSize") == 0) {
95 lua_pushinteger(L
, info
->max_size
);
96 } else if (strcasecmp(index
, "MaxObjects") == 0) {
97 lua_pushinteger(L
, info
->max_objects
);
98 } else if (strcasecmp(index
, "Enabled") == 0) {
99 lua_pushboolean(L
, info
->enabled
);
100 } else if (strcasecmp(index
, "Rounded") == 0) {
101 lua_pushboolean(L
, !info
->check_on_raw
);
103 return error_unknown_field(L
, index
, TableName());
105 return ONE_RETURNVAL
;
109 struct PlacementRuleMetaTable
: public EmptyMetaTable
{
110 static std::string
TableName() {return "PlacementRule";}
111 static std::string
Name() {return TableName() + "Meta";}
113 static int IndexClosure(lua_State
* L
) {
114 const auto rule
= reinterpret_cast<rgw_placement_rule
*>(lua_touserdata(L
, lua_upvalueindex(1)));
116 const char* index
= luaL_checkstring(L
, 2);
118 if (strcasecmp(index
, "Name") == 0) {
119 pushstring(L
, rule
->name
);
120 } else if (strcasecmp(index
, "StorageClass") == 0) {
121 pushstring(L
, rule
->storage_class
);
123 return error_unknown_field(L
, index
, TableName());
125 return ONE_RETURNVAL
;
129 struct UserMetaTable
: public EmptyMetaTable
{
130 static std::string
TableName() {return "User";}
131 static std::string
Name() {return TableName() + "Meta";}
133 static int IndexClosure(lua_State
* L
) {
134 const auto user
= reinterpret_cast<const rgw_user
*>(lua_touserdata(L
, lua_upvalueindex(1)));
136 const char* index
= luaL_checkstring(L
, 2);
138 if (strcasecmp(index
, "Tenant") == 0) {
139 pushstring(L
, user
->tenant
);
140 } else if (strcasecmp(index
, "Id") == 0) {
141 pushstring(L
, user
->id
);
143 return error_unknown_field(L
, index
, TableName());
145 return ONE_RETURNVAL
;
149 struct OwnerMetaTable
: public EmptyMetaTable
{
150 static std::string
TableName() {return "Owner";}
151 static std::string
Name() {return TableName() + "Meta";}
153 static int IndexClosure(lua_State
* L
) {
154 const auto owner
= reinterpret_cast<ACLOwner
*>(lua_touserdata(L
, lua_upvalueindex(1)));
156 const char* index
= luaL_checkstring(L
, 2);
158 if (strcasecmp(index
, "DisplayName") == 0) {
159 pushstring(L
, owner
->get_display_name());
160 } else if (strcasecmp(index
, "User") == 0) {
161 create_metatable
<UserMetaTable
>(L
, false, &(owner
->get_id()));
163 return error_unknown_field(L
, index
, TableName());
165 return ONE_RETURNVAL
;
169 struct BucketMetaTable
: public EmptyMetaTable
{
170 static std::string
TableName() {return "Bucket";}
171 static std::string
Name() {return TableName() + "Meta";}
173 using Type
= rgw::sal::Bucket
;
175 static int IndexClosure(lua_State
* L
) {
176 const auto bucket
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
178 const char* index
= luaL_checkstring(L
, 2);
180 if (strcasecmp(index
, "Tenant") == 0) {
181 pushstring(L
, bucket
->get_tenant());
182 } else if (strcasecmp(index
, "Name") == 0) {
183 pushstring(L
, bucket
->get_name());
184 } else if (strcasecmp(index
, "Marker") == 0) {
185 pushstring(L
, bucket
->get_marker());
186 } else if (strcasecmp(index
, "Id") == 0) {
187 pushstring(L
, bucket
->get_bucket_id());
188 } else if (strcasecmp(index
, "Count") == 0) {
189 lua_pushinteger(L
, bucket
->get_count());
190 } else if (strcasecmp(index
, "Size") == 0) {
191 lua_pushinteger(L
, bucket
->get_size());
192 } else if (strcasecmp(index
, "ZoneGroupId") == 0) {
193 pushstring(L
, bucket
->get_info().zonegroup
);
194 } else if (strcasecmp(index
, "CreationTime") == 0) {
195 pushtime(L
, bucket
->get_creation_time());
196 } else if (strcasecmp(index
, "MTime") == 0) {
197 pushtime(L
, bucket
->get_modification_time());
198 } else if (strcasecmp(index
, "Quota") == 0) {
199 create_metatable
<QuotaMetaTable
>(L
, false, &(bucket
->get_info().quota
));
200 } else if (strcasecmp(index
, "PlacementRule") == 0) {
201 create_metatable
<PlacementRuleMetaTable
>(L
, false, &(bucket
->get_info().placement_rule
));
202 } else if (strcasecmp(index
, "User") == 0) {
203 create_metatable
<UserMetaTable
>(L
, false, &(bucket
->get_info().owner
));
205 return error_unknown_field(L
, index
, TableName());
207 return ONE_RETURNVAL
;
211 struct ObjectMetaTable
: public EmptyMetaTable
{
212 static const std::string
TableName() {return "Object";}
213 static std::string
Name() {return TableName() + "Meta";}
215 using Type
= rgw::sal::Object
;
217 static int IndexClosure(lua_State
* L
) {
218 const auto obj
= reinterpret_cast<const Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
220 const char* index
= luaL_checkstring(L
, 2);
222 if (strcasecmp(index
, "Name") == 0) {
223 pushstring(L
, obj
->get_name());
224 } else if (strcasecmp(index
, "Instance") == 0) {
225 pushstring(L
, obj
->get_instance());
226 } else if (strcasecmp(index
, "Id") == 0) {
227 pushstring(L
, obj
->get_oid());
228 } else if (strcasecmp(index
, "Size") == 0) {
229 lua_pushinteger(L
, obj
->get_obj_size());
230 } else if (strcasecmp(index
, "MTime") == 0) {
231 pushtime(L
, obj
->get_mtime());
233 return error_unknown_field(L
, index
, TableName());
235 return ONE_RETURNVAL
;
239 typedef int MetaTableClosure(lua_State
* L
);
241 template<typename MapType
>
242 int StringMapWriteableNewIndex(lua_State
* L
) {
243 const auto map
= reinterpret_cast<MapType
*>(lua_touserdata(L
, lua_upvalueindex(1)));
245 const char* index
= luaL_checkstring(L
, 2);
246 const char* value
= luaL_checkstring(L
, 3);
247 map
->insert_or_assign(index
, value
);
251 template<typename MapType
=std::map
<std::string
, std::string
>,
252 MetaTableClosure NewIndex
=EmptyMetaTable::NewIndexClosure
>
253 struct StringMapMetaTable
: public EmptyMetaTable
{
255 static std::string
TableName() {return "StringMap";}
256 static std::string
Name() {return TableName() + "Meta";}
258 static int IndexClosure(lua_State
* L
) {
259 const auto map
= reinterpret_cast<MapType
*>(lua_touserdata(L
, lua_upvalueindex(1)));
261 const char* index
= luaL_checkstring(L
, 2);
263 const auto it
= map
->find(std::string(index
));
264 if (it
== map
->end()) {
267 pushstring(L
, it
->second
);
269 return ONE_RETURNVAL
;
272 static int NewIndexClosure(lua_State
* L
) {
276 static int PairsClosure(lua_State
* L
) {
277 auto map
= reinterpret_cast<MapType
*>(lua_touserdata(L
, lua_upvalueindex(1)));
279 lua_pushlightuserdata(L
, map
);
280 lua_pushcclosure(L
, stateless_iter
, ONE_UPVAL
); // push the stateless iterator function
281 lua_pushnil(L
); // indicate this is the first call
282 // return stateless_iter, nil
284 return TWO_RETURNVALS
;
287 static int stateless_iter(lua_State
* L
) {
288 // based on: http://lua-users.org/wiki/GeneralizedPairsAndIpairs
289 auto map
= reinterpret_cast<MapType
*>(lua_touserdata(L
, lua_upvalueindex(1)));
290 typename
MapType::const_iterator next_it
;
291 if (lua_isnil(L
, -1)) {
292 next_it
= map
->begin();
294 const char* index
= luaL_checkstring(L
, 2);
295 const auto it
= map
->find(std::string(index
));
296 ceph_assert(it
!= map
->end());
297 next_it
= std::next(it
);
300 if (next_it
== map
->end()) {
301 // index of the last element was provided
306 pushstring(L
, next_it
->first
);
307 pushstring(L
, next_it
->second
);
311 return TWO_RETURNVALS
;
314 static int LenClosure(lua_State
* L
) {
315 const auto map
= reinterpret_cast<MapType
*>(lua_touserdata(L
, lua_upvalueindex(1)));
317 lua_pushinteger(L
, map
->size());
319 return ONE_RETURNVAL
;
323 struct GrantMetaTable
: public EmptyMetaTable
{
324 static std::string
TableName() {return "Grant";}
325 static std::string
Name() {return TableName() + "Meta";}
327 static int IndexClosure(lua_State
* L
) {
328 const auto grant
= reinterpret_cast<ACLGrant
*>(lua_touserdata(L
, lua_upvalueindex(1)));
330 const char* index
= luaL_checkstring(L
, 2);
332 if (strcasecmp(index
, "Type") == 0) {
333 lua_pushinteger(L
, grant
->get_type().get_type());
334 } else if (strcasecmp(index
, "User") == 0) {
335 const auto id_ptr
= grant
->get_id();
337 create_metatable
<UserMetaTable
>(L
, false, const_cast<rgw_user
*>(id_ptr
));
341 } else if (strcasecmp(index
, "Permission") == 0) {
342 lua_pushinteger(L
, grant
->get_permission().get_permissions());
343 } else if (strcasecmp(index
, "GroupType") == 0) {
344 lua_pushinteger(L
, grant
->get_group());
345 } else if (strcasecmp(index
, "Referer") == 0) {
346 pushstring(L
, grant
->get_referer());
348 return error_unknown_field(L
, index
, TableName());
350 return ONE_RETURNVAL
;
354 struct GrantsMetaTable
: public EmptyMetaTable
{
355 static std::string
TableName() {return "Grants";}
356 static std::string
Name() {return TableName() + "Meta";}
358 static int IndexClosure(lua_State
* L
) {
359 const auto map
= reinterpret_cast<ACLGrantMap
*>(lua_touserdata(L
, lua_upvalueindex(1)));
361 const char* index
= luaL_checkstring(L
, 2);
363 const auto it
= map
->find(std::string(index
));
364 if (it
== map
->end()) {
367 create_metatable
<GrantMetaTable
>(L
, false, &(it
->second
));
369 return ONE_RETURNVAL
;
372 static int PairsClosure(lua_State
* L
) {
373 auto map
= reinterpret_cast<ACLGrantMap
*>(lua_touserdata(L
, lua_upvalueindex(1)));
375 lua_pushlightuserdata(L
, map
);
376 lua_pushcclosure(L
, stateless_iter
, ONE_UPVAL
); // push the stateless iterator function
377 lua_pushnil(L
); // indicate this is the first call
378 // return stateless_iter, nil
380 return TWO_RETURNVALS
;
383 static int stateless_iter(lua_State
* L
) {
384 // based on: http://lua-users.org/wiki/GeneralizedPairsAndIpairs
385 auto map
= reinterpret_cast<ACLGrantMap
*>(lua_touserdata(L
, lua_upvalueindex(1)));
386 ACLGrantMap::iterator next_it
;
387 if (lua_isnil(L
, -1)) {
388 next_it
= map
->begin();
390 const char* index
= luaL_checkstring(L
, 2);
391 const auto it
= map
->find(std::string(index
));
392 ceph_assert(it
!= map
->end());
393 next_it
= std::next(it
);
396 if (next_it
== map
->end()) {
397 // index of the last element was provided
400 return TWO_RETURNVALS
;
404 while (next_it
->first
.empty()) {
405 // this is a multimap and the next element does not have a unique key
407 if (next_it
== map
->end()) {
408 // index of the last element was provided
411 return TWO_RETURNVALS
;
416 pushstring(L
, next_it
->first
);
417 create_metatable
<GrantMetaTable
>(L
, false, &(next_it
->second
));
420 return TWO_RETURNVALS
;
423 static int LenClosure(lua_State
* L
) {
424 const auto map
= reinterpret_cast<ACLGrantMap
*>(lua_touserdata(L
, lua_upvalueindex(1)));
426 lua_pushinteger(L
, map
->size());
428 return ONE_RETURNVAL
;
432 struct ACLMetaTable
: public EmptyMetaTable
{
433 static std::string
TableName() {return "ACL";}
434 static std::string
Name() {return TableName() + "Meta";}
436 using Type
= RGWAccessControlPolicy
;
438 static int IndexClosure(lua_State
* L
) {
439 const auto acl
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
441 const char* index
= luaL_checkstring(L
, 2);
443 if (strcasecmp(index
, "Owner") == 0) {
444 create_metatable
<OwnerMetaTable
>(L
, false, &(acl
->get_owner()));
445 } else if (strcasecmp(index
, "Grants") == 0) {
446 create_metatable
<GrantsMetaTable
>(L
, false, &(acl
->get_acl().get_grant_map()));
448 return error_unknown_field(L
, index
, TableName());
450 return ONE_RETURNVAL
;
454 struct StatementsMetaTable
: public EmptyMetaTable
{
455 static std::string
TableName() {return "Statements";}
456 static std::string
Name() {return TableName() + "Meta";}
458 using Type
= std::vector
<rgw::IAM::Statement
>;
460 static std::string
statement_to_string(const rgw::IAM::Statement
& statement
) {
461 std::stringstream ss
;
466 static int IndexClosure(lua_State
* L
) {
467 const auto statements
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
469 const auto index
= luaL_checkinteger(L
, 2);
471 if (index
>= (int)statements
->size() || index
< 0) {
474 // TODO: policy language could be interpreted to lua and executed as such
475 pushstring(L
, statement_to_string((*statements
)[index
]));
477 return ONE_RETURNVAL
;
480 static int PairsClosure(lua_State
* L
) {
481 auto statements
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
482 ceph_assert(statements
);
483 lua_pushlightuserdata(L
, statements
);
484 lua_pushcclosure(L
, stateless_iter
, ONE_UPVAL
); // push the stateless iterator function
485 lua_pushnil(L
); // indicate this is the first call
486 // return stateless_iter, nil
488 return TWO_RETURNVALS
;
491 static int stateless_iter(lua_State
* L
) {
492 auto statements
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
494 if (lua_isnil(L
, -1)) {
497 const auto it
= luaL_checkinteger(L
, -1);
501 if (next_it
>= statements
->size()) {
502 // index of the last element was provided
507 lua_pushinteger(L
, next_it
);
508 pushstring(L
, statement_to_string((*statements
)[next_it
]));
512 return TWO_RETURNVALS
;
515 static int LenClosure(lua_State
* L
) {
516 const auto statements
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
518 lua_pushinteger(L
, statements
->size());
520 return ONE_RETURNVAL
;
524 struct PolicyMetaTable
: public EmptyMetaTable
{
525 static std::string
TableName() {return "Policy";}
526 static std::string
Name() {return TableName() + "Meta";}
528 static int IndexClosure(lua_State
* L
) {
529 const auto policy
= reinterpret_cast<rgw::IAM::Policy
*>(lua_touserdata(L
, lua_upvalueindex(1)));
531 const char* index
= luaL_checkstring(L
, 2);
533 if (strcasecmp(index
, "Text") == 0) {
534 pushstring(L
, policy
->text
);
535 } else if (strcasecmp(index
, "Id") == 0) {
536 // TODO create pushstring for std::unique_ptr
540 pushstring(L
, policy
->id
.get());
542 } else if (strcasecmp(index
, "Statements") == 0) {
543 create_metatable
<StatementsMetaTable
>(L
, &(policy
->statements
));
545 return error_unknown_field(L
, index
, TableName());
547 return ONE_RETURNVAL
;
551 struct PoliciesMetaTable
: public EmptyMetaTable
{
552 static std::string
TableName() {return "Policies";}
553 static std::string
Name() {return TableName() + "Meta";}
555 using Type
= std::vector
<rgw::IAM::Policy
>;
557 static int IndexClosure(lua_State
* L
) {
558 const auto policies
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
560 const auto index
= luaL_checkinteger(L
, 2);
562 if (index
>= (int)policies
->size() || index
< 0) {
565 create_metatable
<PolicyMetaTable
>(L
, false, &((*policies
)[index
]));
567 return ONE_RETURNVAL
;
570 static int PairsClosure(lua_State
* L
) {
571 auto policies
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
572 ceph_assert(policies
);
573 lua_pushlightuserdata(L
, policies
);
574 lua_pushcclosure(L
, stateless_iter
, ONE_UPVAL
); // push the stateless iterator function
575 lua_pushnil(L
); // indicate this is the first call
576 // return stateless_iter, nil
578 return TWO_RETURNVALS
;
581 static int stateless_iter(lua_State
* L
) {
582 auto policies
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
584 if (lua_isnil(L
, -1)) {
587 ceph_assert(lua_isinteger(L
, -1));
588 const auto it
= luaL_checkinteger(L
, -1);
592 if (next_it
>= policies
->size()) {
593 // index of the last element was provided
598 lua_pushinteger(L
, next_it
);
599 create_metatable
<PolicyMetaTable
>(L
, false, &((*policies
)[next_it
]));
603 return TWO_RETURNVALS
;
606 static int LenClosure(lua_State
* L
) {
607 const auto policies
= reinterpret_cast<Type
*>(lua_touserdata(L
, lua_upvalueindex(1)));
609 lua_pushinteger(L
, policies
->size());
611 return ONE_RETURNVAL
;
615 struct HTTPMetaTable
: public EmptyMetaTable
{
616 static std::string
TableName() {return "HTTP";}
617 static std::string
Name() {return TableName() + "Meta";}
619 static int IndexClosure(lua_State
* L
) {
620 const auto info
= reinterpret_cast<req_info
*>(lua_touserdata(L
, lua_upvalueindex(1)));
622 const char* index
= luaL_checkstring(L
, 2);
624 if (strcasecmp(index
, "Parameters") == 0) {
625 create_metatable
<StringMapMetaTable
<>>(L
, false, &(info
->args
.get_params()));
626 } else if (strcasecmp(index
, "Resources") == 0) {
627 // TODO: add non-const api to get resources
628 create_metatable
<StringMapMetaTable
<>>(L
, false,
629 const_cast<std::map
<std::string
, std::string
>*>(&(info
->args
.get_sub_resources())));
630 } else if (strcasecmp(index
, "Metadata") == 0) {
631 create_metatable
<StringMapMetaTable
<meta_map_t
, StringMapWriteableNewIndex
<meta_map_t
>>>(L
, false, &(info
->x_meta_map
));
632 } else if (strcasecmp(index
, "Host") == 0) {
633 pushstring(L
, info
->host
);
634 } else if (strcasecmp(index
, "Method") == 0) {
635 pushstring(L
, info
->method
);
636 } else if (strcasecmp(index
, "URI") == 0) {
637 pushstring(L
, info
->request_uri
);
638 } else if (strcasecmp(index
, "QueryString") == 0) {
639 pushstring(L
, info
->request_params
);
640 } else if (strcasecmp(index
, "Domain") == 0) {
641 pushstring(L
, info
->domain
);
642 } else if (strcasecmp(index
, "StorageClass") == 0) {
643 pushstring(L
, info
->storage_class
);
645 return error_unknown_field(L
, index
, TableName());
647 return ONE_RETURNVAL
;
650 static int NewIndexClosure(lua_State
* L
) {
651 auto info
= reinterpret_cast<req_info
*>(lua_touserdata(L
, lua_upvalueindex(1)));
653 const char* index
= luaL_checkstring(L
, 2);
655 if (strcasecmp(index
, "StorageClass") == 0) {
656 info
->storage_class
= luaL_checkstring(L
, 3);
658 return error_unknown_field(L
, index
, TableName());
664 struct CopyFromMetaTable
: public EmptyMetaTable
{
665 static std::string
TableName() {return "CopyFrom";}
666 static std::string
Name() {return TableName() + "Meta";}
668 static int IndexClosure(lua_State
* L
) {
669 const auto s
= reinterpret_cast<req_state
*>(lua_touserdata(L
, lua_upvalueindex(1)));
671 const char* index
= luaL_checkstring(L
, 2);
673 if (strcasecmp(index
, "Tenant") == 0) {
674 pushstring(L
, s
->src_tenant_name
);
675 } else if (strcasecmp(index
, "Bucket") == 0) {
676 pushstring(L
, s
->src_bucket_name
);
677 } else if (strcasecmp(index
, "Object") == 0) {
678 create_metatable
<ObjectMetaTable
>(L
, false, s
->src_object
);
680 return error_unknown_field(L
, index
, TableName());
682 return ONE_RETURNVAL
;
686 struct ZoneGroupMetaTable
: public EmptyMetaTable
{
687 static std::string
TableName() {return "ZoneGroup";}
688 static std::string
Name() {return TableName() + "Meta";}
690 static int IndexClosure(lua_State
* L
) {
691 const auto s
= reinterpret_cast<req_state
*>(lua_touserdata(L
, lua_upvalueindex(1)));
693 const char* index
= luaL_checkstring(L
, 2);
695 if (strcasecmp(index
, "Name") == 0) {
696 pushstring(L
, s
->zonegroup_name
);
697 } else if (strcasecmp(index
, "Endpoint") == 0) {
698 pushstring(L
, s
->zonegroup_endpoint
);
700 return error_unknown_field(L
, index
, TableName());
702 return ONE_RETURNVAL
;
706 struct RequestMetaTable
: public EmptyMetaTable
{
707 static std::string
TableName() {return "Request";}
708 static std::string
Name() {return TableName() + "Meta";}
710 // __index closure that expect req_state to be captured
711 static int IndexClosure(lua_State
* L
) {
712 const auto s
= reinterpret_cast<req_state
*>(lua_touserdata(L
, lua_upvalueindex(1)));
713 const auto op_name
= reinterpret_cast<const char*>(lua_touserdata(L
, lua_upvalueindex(2)));
715 const char* index
= luaL_checkstring(L
, 2);
717 if (strcasecmp(index
, "RGWOp") == 0) {
718 pushstring(L
, op_name
);
719 } else if (strcasecmp(index
, "DecodedURI") == 0) {
720 pushstring(L
, s
->decoded_uri
);
721 } else if (strcasecmp(index
, "ContentLength") == 0) {
722 lua_pushinteger(L
, s
->content_length
);
723 } else if (strcasecmp(index
, "GenericAttributes") == 0) {
724 create_metatable
<StringMapMetaTable
<>>(L
, false, &(s
->generic_attrs
));
725 } else if (strcasecmp(index
, "Response") == 0) {
726 create_metatable
<ResponseMetaTable
>(L
, false, &(s
->err
));
727 } else if (strcasecmp(index
, "SwiftAccountName") == 0) {
728 if (s
->dialect
== "swift") {
729 pushstring(L
, s
->account_name
);
733 } else if (strcasecmp(index
, "Bucket") == 0) {
734 create_metatable
<BucketMetaTable
>(L
, false, s
->bucket
);
735 } else if (strcasecmp(index
, "Object") == 0) {
736 create_metatable
<ObjectMetaTable
>(L
, false, s
->object
);
737 } else if (strcasecmp(index
, "CopyFrom") == 0) {
738 if (s
->op_type
== RGW_OP_COPY_OBJ
) {
739 create_metatable
<CopyFromMetaTable
>(L
, s
);
743 } else if (strcasecmp(index
, "ObjectOwner") == 0) {
744 create_metatable
<OwnerMetaTable
>(L
, false, &(s
->owner
));
745 } else if (strcasecmp(index
, "ZoneGroup") == 0) {
746 create_metatable
<ZoneGroupMetaTable
>(L
, false, s
);
747 } else if (strcasecmp(index
, "UserACL") == 0) {
748 create_metatable
<ACLMetaTable
>(L
, false, s
->user_acl
);
749 } else if (strcasecmp(index
, "BucketACL") == 0) {
750 create_metatable
<ACLMetaTable
>(L
, false, s
->bucket_acl
);
751 } else if (strcasecmp(index
, "ObjectACL") == 0) {
752 create_metatable
<ACLMetaTable
>(L
, false, s
->object_acl
);
753 } else if (strcasecmp(index
, "Environment") == 0) {
754 create_metatable
<StringMapMetaTable
<rgw::IAM::Environment
>>(L
, false, &(s
->env
));
755 } else if (strcasecmp(index
, "Policy") == 0) {
756 // TODO: create a wrapper to std::optional
757 if (!s
->iam_policy
) {
760 create_metatable
<PolicyMetaTable
>(L
, false, s
->iam_policy
.get_ptr());
762 } else if (strcasecmp(index
, "UserPolicies") == 0) {
763 create_metatable
<PoliciesMetaTable
>(L
, false, &(s
->iam_user_policies
));
764 } else if (strcasecmp(index
, "RGWId") == 0) {
765 pushstring(L
, s
->host_id
);
766 } else if (strcasecmp(index
, "HTTP") == 0) {
767 create_metatable
<HTTPMetaTable
>(L
, false, &(s
->info
));
768 } else if (strcasecmp(index
, "Time") == 0) {
769 pushtime(L
, s
->time
);
770 } else if (strcasecmp(index
, "Dialect") == 0) {
771 pushstring(L
, s
->dialect
);
772 } else if (strcasecmp(index
, "Id") == 0) {
773 pushstring(L
, s
->req_id
);
774 } else if (strcasecmp(index
, "TransactionId") == 0) {
775 pushstring(L
, s
->trans_id
);
776 } else if (strcasecmp(index
, "Tags") == 0) {
777 create_metatable
<StringMapMetaTable
<RGWObjTags::tag_map_t
>>(L
, false, &(s
->tagset
.get_tags()));
778 } else if (strcasecmp(index
, "User") == 0) {
782 create_metatable
<UserMetaTable
>(L
, false, const_cast<rgw_user
*>(&(s
->user
->get_id())));
785 return error_unknown_field(L
, index
, TableName());
787 return ONE_RETURNVAL
;
792 rgw::sal::Store
* store
,
797 const std::string
& script
)
800 auto L
= luaL_newstate();
801 lua_state_guard
lguard(L
);
803 open_standard_libs(L
);
804 set_package_path(L
, store
?
805 store
->get_luarocks_path() :
808 create_debug_action(L
, s
->cct
);
810 create_metatable
<RequestMetaTable
>(L
, true, s
, const_cast<char*>(op_name
));
812 // add the ops log action
813 lua_getglobal(L
, RequestMetaTable::TableName().c_str());
814 ceph_assert(lua_istable(L
, -1));
815 pushstring(L
, RequestLogAction
);
816 lua_pushlightuserdata(L
, rest
);
817 lua_pushlightuserdata(L
, olog
);
818 lua_pushlightuserdata(L
, s
);
819 lua_pushlightuserdata(L
, const_cast<char*>(op_name
));
820 lua_pushcclosure(L
, RequestLog
, FOUR_UPVALS
);
824 // execute the lua script
825 if (luaL_dostring(L
, script
.c_str()) != LUA_OK
) {
826 const std::string
err(lua_tostring(L
, -1));
827 ldpp_dout(s
, 1) << "Lua ERROR: " << err
<< dendl
;
830 } catch (const std::runtime_error
& e
) {
831 ldpp_dout(s
, 1) << "Lua ERROR: " << e
.what() << dendl
;