AWSのブログを参考に、Clojureを使って初めてのAWS Lambda functionを作ってみる。
下準備
まずIAM roleを作る。sandbox-lambda-exec-role
という新しいロールを作り、権限の問題でハマりたくないのでとりあえずAWSLambdaFullAccess
というポリシーを割り当てた。
IAM userがsandbox-lambda-exec-role
ロールでLambda functionを実行できるように、IAM userのインラインポリシーを編集してiam:PassRole
を許可する。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1446873599000",
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": [
"arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/*"
]
}
]
}
Jarを作成
新しいプロジェクトhello
を作る。
lein new hello
project.clj
にcom.amazonaws/aws-lambda-java-core
などを追加。
(defproject hello "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.7.0"]
[org.clojure/data.json "0.2.6"]
[com.amazonaws/aws-lambda-java-core "1.0.0"]]
:aot :all)
src/hello/core.clj
を編集してハンドラを追加。
(ns hello.core
(:gen-class
:methods [^:static [handler [String] String]]))
(defn -handler [s]
(str "Hello " s "!"))
jarを作成。
$ lein uberjar
Lambda functionを作成&実行
AWS-CLIを使ってLambda function hello
を作成する。
aws lambda create-function --function-name hello --handler hello.core::handler --runtime java8 --memory 512 --timeout 10 --role arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/sandbox-lambda-exec-role --zip-file fileb://./target/hello-0.1.0-SNAPSHOT-standalone.jar
実行。
aws lambda invoke --invocation-type RequestResponse --function-name hello --log-type Tail --payload '"Clojure"' output.txt
正常に実行されるとoutput.txt
に、
"Hello Clojure!"
と出力される。
RequestStreamHandlerを実装
このあとAPI Gatewayを使ってREST API化にしようとしたのだが、パスに入れたname
パラメータをLambda Functionに渡す方法がぱっと分からないので、冒頭に上げたAWSブログを参考にして、RequestStreamHandler
を実装し、POSTボディからJSONを読んでパラメータを取得するように変更してみた。
(ns hello_lambda.core
(:gen-class
:implements [com.amazonaws.services.lambda.runtime.RequestStreamHandler])
(:require [clojure.data.json :as json]
[clojure.string :as s]
[clojure.java.io :as io]))
(defn hello [params]
{:message (str "Hello " (:name params))})
(defn -handleRequest [this is os context]
(let [w (io/writer os)]
(-> (json/read (io/reader is) :key-fn keyword)
(hello)
(json/write w))
(.flush w)))
API Gatewayを使ってこのLambda FunctionをREST APIで呼び出せるようにした記録はこちらの記事にあります。