Lua Scripting
New in version Pacific.
Contents
This feature allows users to upload Lua scripts to different context in the radosgw. The two supported context are “preRequest” that will execute a script before the operation was taken, and “postRequest” that will execute after each operation is taken. Script may be uploaded to address requests for users of a specific tenant. The script can access fields in the request and modify some fields. All Lua language features can be used in the script.
Script Management via CLI
To upload a script:
# radosgw-admin script put --infile={lua-file} --context={preRequest|postRequest} [--tenant={tenant-name}]
To print the content of the script to standard output:
# radosgw-admin script get --context={preRequest|postRequest} [--tenant={tenant-name}]
To remove the script:
# radosgw-admin script rm --context={preRequest|postRequest} [--tenant={tenant-name}]
Context Free Functions
Debug Log
The RGWDebugLog()
function accepts a string and prints it to the debug log with priority 20. Each log message is prefixed Lua INFO:
. This function has no return value.
Request Fields
Warning
This feature is experimental. Fields may be removed or renamed in the future.
Note
Although Lua is a case-sensitive language, field names provided by the radosgw are case-insensitive. Function names remain case-sensitive.
Fields marked “optional” can have a nil value.
Fields marked as “iterable” can be used by the pairs() function and with the # length operator.
All table fields can be used with the bracket operator
[]
.time
fields are strings with the following format:%Y-%m-%d %H:%M:%S
.
Field | Type | Description | Iterable | Writeable | Optional |
---|---|---|---|---|---|
| string | radosgw operation | no | no | no |
| string | decoded URI | no | no | no |
| integer | size of the request | no | no | no |
| table | string to string generic attributes map | yes | no | no |
| table | response to the request | no | no | no |
| integer | HTTP status code | no | yes | no |
| string | HTTP status text | no | yes | no |
| integer | radosgw error code | no | yes | no |
| string | response message | no | yes | no |
| string | swift account name | no | no | yes |
| table | info on the bucket | no | no | yes |
| string | tenant of the bucket | no | no | no |
| string | bucket name | no | no | no |
| string | bucket marker (initial id) | no | no | no |
| string | bucket id | no | no | no |
| integer | number of objects in the bucket | no | no | no |
| integer | total size of objects in the bucket | no | no | no |
| string | zone group of the bucket | no | no | no |
| time | creation time of the bucket | no | no | no |
| time | modification time of the bucket | no | no | no |
| table | bucket quota | no | no | no |
| integer | bucket quota max size | no | no | no |
| integer | bucket quota max number of objects | no | no | no |
| boolean | bucket quota is enabled | no | no | no |
| boolean | bucket quota is rounded to 4K | no | no | no |
| table | bucket placement rule | no | no | no |
| string | bucket placement rule name | no | no | no |
| string | bucket placement rule storage class | no | no | no |
| table | bucket owner | no | no | no |
| string | bucket owner tenant | no | no | no |
| string | bucket owner id | no | no | no |
| table | info on the object | no | no | yes |
| string | object name | no | no | no |
| string | object version | no | no | no |
| string | object id | no | no | no |
| integer | object size | no | no | no |
| time | object mtime | no | no | no |
| table | information on copy operation | no | no | yes |
| string | tenant of the object copied from | no | no | no |
| string | bucket of the object copied from | no | no | no |
| table | object copied from. See: | no | no | yes |
| table | object owner | no | no | no |
| string | object owner display name | no | no | no |
| table | object user. See: | no | no | no |
| string | name of zone group | no | no | no |
| string | endpoint of zone group | no | no | no |
| table | user ACL | no | no | no |
| table | user ACL owner. See: | no | no | no |
| table | user ACL map of string to grant note: grants without an Id are not presented when iterated and only one of them can be accessed via brackets | yes | no | no |
| table | user ACL grant | no | no | no |
| integer | user ACL grant type | no | no | no |
| table | user ACL grant user | no | no | no |
| table | user ACL grant user tenant | no | no | no |
| table | user ACL grant user id | no | no | no |
| integer | user ACL grant group type | no | no | no |
| string | user ACL grant referer | no | no | no |
| table | bucket ACL. See: | no | no | no |
| table | object ACL. See: | no | no | no |
| table | string to string environment map | yes | no | no |
| table | policy | no | no | yes |
| string | policy text | no | no | no |
| string | policy Id | no | no | yes |
| table | list of string statements | yes | no | no |
| table | list of user policies | yes | no | no |
| table | user policy. See: | no | no | no |
| string | radosgw host id: | no | no | no |
| table | HTTP header | no | no | no |
| table | string to string parameter map | yes | no | no |
| table | string to string resource map | yes | no | no |
| table | string to string metadata map | yes | yes | no |
| string | host name | no | no | no |
| string | HTTP method | no | no | no |
| string | URI | no | no | no |
| string | HTTP query string | no | no | no |
| string | domain name | no | no | no |
| time | request time | no | no | no |
| string | “S3” or “Swift” | no | no | no |
| string | request Id | no | no | no |
| string | transaction Id | no | no | no |
| table | object tags map | yes | no | no |
Request Functions
Operations Log
The Request.Log()
function prints the requests into the operations log. This function has no parameters. It returns 0 for success and an error code if it fails.
Lua Code Samples
- Print information on source and destination objects in case of copy:
function print_object(object)
RGWDebugLog(" Name: " .. object.Name)
RGWDebugLog(" Instance: " .. object.Instance)
RGWDebugLog(" Id: " .. object.Id)
RGWDebugLog(" Size: " .. object.Size)
RGWDebugLog(" MTime: " .. object.MTime)
end
if Request.CopyFrom and Request.Object and Request.CopyFrom.Object then
RGWDebugLog("copy from object:")
print_object(Request.CopyFrom.Object)
RGWDebugLog("to object:")
print_object(Request.Object)
end
- Print ACLs via a “generic function”:
function print_owner(owner)
RGWDebugLog("Owner:")
RGWDebugLog(" Dispaly Name: " .. owner.DisplayName)
RGWDebugLog(" Id: " .. owner.User.Id)
RGWDebugLog(" Tenanet: " .. owner.User.Tenant)
end
function print_acl(acl_type)
index = acl_type .. "ACL"
acl = Request[index]
if acl then
RGWDebugLog(acl_type .. "ACL Owner")
print_owner(acl.Owner)
RGWDebugLog(" there are " .. #acl.Grants .. " grant for owner")
for k,v in pairs(acl.Grants) do
RGWDebugLog(" Grant Key: " .. k)
RGWDebugLog(" Grant Type: " .. v.Type)
RGWDebugLog(" Grant Group Type: " .. v.GroupType)
RGWDebugLog(" Grant Referer: " .. v.Referer)
RGWDebugLog(" Grant User Tenant: " .. v.User.Tenant)
RGWDebugLog(" Grant User Id: " .. v.User.Id)
end
else
RGWDebugLog("no " .. acl_type .. " ACL in request: " .. Request.Id)
end
end
print_acl("User")
print_acl("Bucket")
print_acl("Object")
- Use of operations log only in case of errors:
if Request.Response.HTTPStatusCode ~= 200 then
RGWDebugLog("request is bad, use ops log")
rc = Request.Log()
RGWDebugLog("ops log return code: " .. rc)
end
- Set values into the error message:
if Request.Response.HTTPStatusCode == 500 then
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:
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:
RGWDebugLog("number of metadata entries is: " .. #Request.HTTP.Metadata)
for k, v in pairs(Request.HTTP.Metadata) do
RGWDebugLog("key=" .. k .. ", " .. "value=" .. v)
end