November 29, 2015

Executing Ruby code in AWS Lambda

AWS Lambda supports only Java, JavaScript & Python at the time of writing this post. I was wondering whether I can exploit the Lambda to execute chef’s knife commands on it since Lambda runs on a Linux container. Using simple python function I have identified that the code of the Lambda function gets copied to /var/task and executed from there.

I decided to custom build ruby as embedded platform similar to how chef-client or chefdk are distributed. My requirement is to execute knife commands and its uses embedded ruby version 2.1.0, hence I downloaded the source archive that specific version.

Lambda have certain limitations on the package size that the total uncompressed size of code and its dependencies should not exceed 250MB. Due to this limitation I compiled ruby by configuring it with limited set of options as listed below.

./configure --prefix=/var/task/customruby --disable-werror --disable-largefile --disable-install-doc \
  --disable-install-rdoc --disable-install-capi --without-gmp --without-valgrind

Note: Remember to install zlib, zlib-devel, openssl & openssl-devel before compiling ruby for gem installation and ssl access.

Once the ruby has been compiled and installed, ruby binaries will be available under /var/task/customruby/bin/. Using the gem binary under this location, install all the required gem files.

In my case I installed all the gems which are part of the chef client from previously installed local gem cache with –no-ri & –no-rdoc to save space in the package. Created a directory containing knife.rb & validator key which are needed to connect to the chef server. I created a simple python program to validate it, which lists all the environments in the chef server.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import time
from subprocess import Popen, PIPE, STDOUT

def lambda_handler(event, context):
    cmd = '/var/task/customruby/bin/knife environment list -c /var/task/chef/knife.rb'
    p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
    output = p.stdout.read()
    print 'List of environments available in this chef server. n' + output
    return

if __name__ == '__main__':
    lambda_handler('event', 'handler')

Lambda function in action:
LambdaRuby_log

This opens up whole new opportunity and I don’t need to wait for AWS to provide support for ruby, at least for my requirement.

© Prakash P 2015 - 2019

Powered by Hugo & Kiss.