The quickest & easiest way to develop AWS Lambda functions that use Ruby gems

Although there are some nifty frameworks for building and managing AWS Lambda functions using Ruby, unless the project is quite complex I like a simple local-to-AWS development flow, without any framework magic obscuring what’s actually happening in my code.

This is probably the simplest way to get up and running developing locally for AWS Lamda functions that need to use common gems such as “rest-client”. It is modeled after: https://www.stevenringo.com/ruby-in-aws-lambda-with-postgresql-nokogiri/ but simplified.

You need an AWS account, and Docker, period. (Don’t even need the AWS CLI command line utility.)

In browser:

1. Create a default ‘hello world’ lambda function in your aws lambda console

It sets up intelligent default for roles etc.

I like to set concurrency to 1 while developing.

In the Mac terminal:

2. Create  a docker folder with a dockerfile that uses an aws lambda image

The folder is just to hold the docker file you use when you need to build or rebuilt the Docker image you use for local AWS Lambda development.
$ mkdir aws-lambda-docker
$ cd aws-lambda-docker

If using postgres (like the article above this was based on) it’ll need extra stuff, this example below is just the simplest  Dockerfile, to let you use ruby gems.

# be sure the ruby version is same as what aws lambda currently offers
# Dockerfile

FROM lambci/lambda:build-ruby2.7

RUN gem update bundler

CMD "/bin/bash"

3. Create tagged docker container, your own local “AWS Lambda in a Box” that you can re-use for all your Ruby-with-gems Lambda projects:

I’m building a container for aws lambda ruby v27 so I use that for the tag:

$ docker build -t awsruby27 .

4. Make a Project directory

$ mkdir awsstuff
$ cd awsstuff

5. Create your lambda_function.rb code

We’ll use two gems, one that needs to be compiled with native extensions (nokogiri) and one that does not (rest-client).

# lambda_function.rb
require 'json'
require 'rest-client'
require 'nokogiri'

def lambda_handler(event:, context:)
    url = "https://api.myip.com"
    puts "use rest-client ruby gem"
    html = "<html><title>The Title</title><body>The Body</body></html>"
    parsed_data = Nokogiri::HTML.parse(html)
    puts parsed_data.title
    rr = RestClient::Request.execute :method => :get, 
        :url => url, 
        :ssl_version => 'SSLv23'
    result = "Title check: #{parsed_data.title} and remote api returned #{rr.body}"

    { statusCode: rr.code, body: result }
end

6. Create your Gemfile

# Gemfile
source "https://rubygems.org"
gem "rest-client"
gem "nokogiri"

7. Inside the project folder, run the Lambda ruby container:

$ docker run --rm -it -v $PWD:/var/task -w /var/task awsruby27

Inside the docker container:

8. Bundle your project

Only needed when you create or  modify the Gemfile:

bash-4.2# bundle install --path vendor/bundle --clean

9. Test your handler code

Via Ruby’s -e option to execute a string containing the ruby code to require & invoke a function:

bash-4.2# ruby -e "require 'lambda_function'; puts lambda_handler(event: nil, context: nil)"
use rest-client ruby gem
The Title
{:statusCode=>200, :body=>"Title check: The Title and remote api returned {\"ip\":\"xxx.xxx.xxx.xxx\",\"country\":\"United States\",\"cc\":\"US\"}"}

Or interactively, via irb:

bash-4.2# irb
> require 'lambda_function'
> lambda_handler(event: nil, context: nil)
use rest-client ruby gem
The Title
{:statusCode=>200, :body=>"Title check: The Title and remote api returned {\"ip\":\"xxx.xxx.xxx.xxx\",\"country\":\"United States\",\"cc\":\"US\"}"}
> exit
bash-4.2# exit

10. Back in Terminal, package the zip file

$ rm -f deploy.zip ; zip -q -r deploy.zip .

In AWS console:

11. Upload your working zip file deployment to the lambda function

In aws console, on the existing lambda function, on CODE tab, use UPLOAD FROM button on right and upload zip fle

12. Test it on Lambda

Now you have an AWS Lambda function in Ruby, which can use arbitrary Ruby gems, even native-extensions gems like nokogiri (which works on AWS since you compiled your Ruby bundle inside a docker container based on the AWS ‘build’ image for Ruby).

A few notes about deployment size…

The bundle’s deployment size increases significantly if you add certain native-extension gems such as nokogiri, and if the deployment package exceeds some limit you will not be able to view the code on the AWS Lambda console and will see this message instead:

The deployment package of your Lambda function "test2" is too large to enable inline code editing. However, you can still invoke your function.

The code still runs on Lambda, only the code view/edit is disabled when the package is too large.

For your NEXT projects, simply start at step 4.

You’ve already created your Lambda-in-a-Box docker container so simply create a project folder, write your lambda_function.rb and Gemfile, then use your already-built docker container to run and text your code.

Why I’ll skip the J&J vaccine and wait for one of the “better” ones

Whenever my turns comes up, this is why I will decline the J&J vaccine if is the “first” one offered to me, despite the catchy (but IMO provably false) government PR slogan “the best vaccine is the one they offer you.”

I think there’s a lot of sloppy, quota-driven recommendations around which vaccine to get, hence this post. Uncle Sam wants as many vaccinated as soon as possible and IMO obfuscates or ignores some important information to that end.

Note – this post explicitly assumes one has a reasonable expectation of being able to get the Pfizer or Moderna within a week or two after declining the J&J. I believe the J&J is “better than nothing” if there is no other choice within a moderate timeframe… for example if I lived in a rural area without refrigeration.

Point 1: Data available today suggests to me that you are somewhat more likely to infect someone else  (with possibly disastrous results) if you get the J&J vaccine instead of Pfizer or Moderna.

Remember, your own chance of infection if you get J&J is roughly 5 times higher than if you get Pfizer or Moderna. (About 25% vs 5% given the relative efficacies of 75% vs 95%.)

The “argument” used by J&J apologists (and bureaucrats who want to hit a vaccination goal) is that:

  • J&J is admittedly not as effective at preventing infection,
  • but if you get COVID the J&J is just as good at keeping you from developing a serious or fatal case of COVID.

So, good for you.

But let’s not ignore the inconvenient fact that if you yourself happen to get infected experiencing a mild symptom, there is no CDC conclusion to suggest that anyone not-yet-vaccinated whom you happen to infect will have milder symptoms as a  result of your vaccination. And, unfortunately, no CDC conclusion as yet that you are less likely to infect someone else if you are infected-but-vaccinated.

So if you care about the unvaccinated people around you (nearly) as much as yourself, it seems to me you want to insist upon a vaccine where your chance of infection is about 1/5 as high as with the less-effective J&J.

Point 2: Misleading counter-claim: If you “wait for one of the good ones” to become available, you’re putting yourself at increased risk of catching COVID, so get J&J if thats what they offer you.

This lazy argument presumes “wait” means “wait a long time”.

The increased risk while waiting obviously DEPENDS upon how long the “wait” is… what if it’s an hour? or tomorrow? or one week? or six months?

Even without doing math you know that if “the wait” is 1 minute you have near-zero incremental risk during that minute, but if “the wait” is a year the risk of waiting is a lot higher, right?

But lets do some easy math… since Uncle Sam doesn’t publish the number let’s make a first-approximation guesstimate of someone’s “incremental per-day risk of infection” then double-check our first guesstimate against the CDC daily infection rate.

Estimates so far seem to be that about 30% of the USA have thus far been infected.  Let’s call the time period 365 days. So as a very rough first approximation the risk/day is on the order of 0.30 / 365 = 0.0008, now let’s arbitrarily triple that risk to 0.0025 to lean a little further into the risk. So by that (very simplistic) math each day one “waits” their added risk of infection is in the ballpark of 1/4 of 1%. (I expect it’s actually much smaller because if you have avoided infection so far you’re likely being pretty careful and hopefully will remain so, plus rates of community spread seem to be leveling or even dropping.)

In fact, as a second estimate and sanity check, we get a far smaller number for the average daily infection rate (.00015) if you divide current daily COVID cases by the US population, so for two weeks that comes out to 0.002, e.g. roughly 1/5 of 1% additional risk if you wait 2 extra weeks for a better vaccine.

My own conclusion:

Rather than accepting J&J today, waiting a week or 2 (possibly even 3) for Pfizer or Moderna to become available to me is safer for the still-unvaccinated people around me since it decreases the odds of my catching a mild case and then watching someone I infect experience a critical case.

A few other salient arguments re: J&J:

A – We don’t yet know which (if any) vaccines  do/don’t prevent transmission to others if you are infected, so it is theoretically possible J&J “might” do a better job of preventing infecting people around you if you have an active (but mild) infected.

We don’t know. So it seems foolish to me to ignore the major points 1 & 2 above on the mere speculation that a vaccine that allows a 5-times higher infection rate might somehow reduce transmission to others when you’re infected. Sure it might be true, but we have no reason (yet) to rely on that speculation.

B – People who are less likely to come back for the second shot should get J&J because it is better than a single dose of Pfizer or Moderna.

Sure, get J&J if you’re gonna skip shot#2 of Pfizer/Moderna. (Although J&J is perhaps not better by a huge amount… Pfizer or Moderna still seem to do pretty well (about 50%) after one shot.)

I don’t minimize the importance of wide-spread vaccination to try to reach some sort of herd immunity. But until we reach that herd immunity, it seems to me that the people around you could be at increased net risk if you allow yourself to be stampeded into getting the J&J vaccine if you could have waited a few days and gotten one of the better ones.

I’m neither a doctor nor an epidemiologist. But neither am I afraid to employ a little critical thinking to challenge far-too-glib slogans from bureaucrats who have a quota (and who all got the better vaccine), for whom you and the people around you are merely statistics.

Autonomous Vehicles as “Bad Actors”

As discussed in detail with my pal Dave in early-and-mid 2020, it seems like autonomous cars make a pretty good platform for spying… innocent-looking mobile platforms with video and audio capability, which can be re-routed without suspicion* “a little bit out of the way” into an area of interest with the tweak of an algorithm here and there.

Looks like China is now concerned about similar capabilities with Teslas.

Personally, I hope someone like the Electronic Freedom Foundation ensures laws are created to prohibit the following:

  1. domestic government agencies “rerouting” an AV for purposes of spying, and
  2. advertisers “rerouting” an AV to “happen” to drive by an event or location (such as that BBQ joint filling the air with delicious BBQ smells).

* when your outsource routing decisions to your AV car, you really won’t be aware of the “reason” the AV decided to drive past that suspected drug den or BBQ joint.