Last post discussed launching LuaJIT from Python on AWS Lambda.
Suppose you want to receive events from the Lua code in the Python code that invoked it.
If you don’t have a Python-Lua API then you are left with either using sockets, files or even getting feedback by reading the realtime output from the process stdout object (which is not that trivial, see this implementation)
A more elegant way would be if there was a Python API for accessing the Lua code (and vice versa). This is what lupa does, and it works with both Lua and LuaJIT.
I’ll explain how to install lupa so it can be used with Python on the amazon linux docker container, and thereby on AWS Lambda.
So, Connect to your amazon linux docker container and
mkdir -p /root/lambdalua cd /root/lambdalua # Download the lupa source code # link for latest source: https://pypi.org/project/lupa/#files - look for tar.gz file wget https://files.pythonhosted.org/packages/f2/b2/8295ebabb417173eaae05adc63353e4da3eb8909e1b636b17ff9f8e1cdce/lupa-1.7.tar.gz # extract the source in /root/lambdalua tar xzfv lupa-1.7.tar.gz # enter the lupa source directory cd lupa-1.7 wget http://luajit.org/download/LuaJIT-2.0.5.zip # download latest source of LuaJIT unzip LuaJIT-2.0.5.zip # unzip it in /root/lambdalua/lupa-1.7 cd LuaJIT-2.0.5 # genter LuaJIT source directory make CFLAGS=-fPIC # Make LuaJIT with -fPIC compile flag cd .. # back to lupa source dir python setup.py install # Create lupa Python module cd /root/lambdalua mkdir lupa_package # create a directory for a lupa test aws package # copy the Lupa module that we previously compiled to the lupa_package directory # so that the "import lupa" will work from the python code on AWS lambda cp -r ./lupa-1.7/build/lib.linux-x86_64-3.6/lupa lupa_package/
Now create /root/lambdalua/lupa_package/lambdalua.py so that it makes use of Lupa:
import subprocess import sys import os import lupa # use the local lupa module from lupa import LuaRuntime def lambda_luajit_func(event, context): def readfile(filename): content = '' with open(filename, 'r') as myfile: return myfile.read() lua = LuaRuntime(unpack_returned_tuples=True) # define fhe Python function that will be called from LuaJIT def add_one(num): return num + 1 # Load the Lua code lua_func = lua.eval(readfile('./test.lua')) params = { "add_one_func":add_one, "num":42 } # call the Lua function defined in test.lua with the above parameters res = lua_func(params) return res if __name__ == "__main__": print(lambda_luajit_func(None, None))
and also create the /root/lambdalua/lupa_package/test.lua that the above python file will load:
function(params_table) -- get the number passed from python num = params_table.num -- get the python function to invoke py_func = params_table.add_one_func -- return the result of invoking the Python function on the number return "The result is:"..py_func(num) end
To see that this actually works in our amazon linux docker, just type:
python lambdalua.py # output is: The result is:43
To make this run on AWS lambda, we pack the contents of /root/lambdalua/lupa_package in a zip file.
zip -r package.zip .
If the AWS credentials and command line is in your OS shell, then from an OS terminal copy the zip file to your OS from the docker container, e.g (you can skip this step if you copied the aws credentials to ~/.aws in the docker container):
docker cp lucid_poincare:/root/lambdalua/lupa_package/package.zip .
Create a function (if we haven’t done so already) or update the function (if we want to update the function from the previous post) and invoke it.
The details of creating the lambda user, profile, function etc from the aws command line are detailed in a previous post, but a quick overview assuming you already have a lambda user names lambda_user:
Next, assuming you already have a lambda account and user (if you don’t, see a previous post) either create a new function
aws lambda create-function --region us-east-1 --function-name lambda_luajit_func --zip-file fileb://package.zip --role arn:aws:iam::123456789012:role/basic_lambda_role --handler lambdalua.lambda_luajit_func --runtime python3.6 --profile lambda_use
or, if you already created the function lambdalua.lambda_luajit_func from the previous post, you can update it:
# the following assumes myzippackage is a bucket you own aws s3 rm s3://myzippackage/package.zip # remove previous package if exists aws s3 cp package.zip s3://myzippackage/package.zip # copy new package # update lambda_luajit_func function with contents of new package aws lambda update-function-code --region us-east-1 --function-name lambda_luajit_func --s3-bucket myzippackage --s3-key package.zip --profile lambda_user
finally, invoke the Lupa test on AWS lambda
aws lambda invoke --invocation-type RequestResponse --function-name lambda_luajit_func --region us-east-1 --log-type Tail --profile lambda_user out.txt cat out.txt # output should be: "The result is:43"