AWS Lambda が Ruby をサポート した (2018年11月) ので、既存のコード (gouf/shindan) と組み合わせて、動作するものを作る
作ったものはコレ: gouf/serverless_ruby_demo
前提
- AWS のアカウントがある
- AWS Lambda にアクセス可能な IAM を用意してある
- Node.js が手元の環境で動く
- Ruby 2.5 が手元の環境で動く
- Docker が手元の環境で動く
- RSpec でテストコードが書ける (任意)
プロジェクトの初期化
Serverless の公式ページ にあるように、まずは初期セットアップを済ませる
# Step 1. Install serverless globally $ npm install serverless -g # Step 2. Create a serverless function $ serverless create --template hello-world # Step 3. deploy to cloud provider $ serverless deploy
デプロイまで うまくいっていれば、 sls invoke -f hello
で実行結果が返ってくるはず
このテンプレート初期化状態をもとに、実装を進めていく
テストコードを書く
「診断メーカー に存在する任意のID を渡すとその結果を返す」という動作を実現するコードを書きたい
簡単だけれど、次のように成功パターン・失敗パターンのテストコードを記述する
# spec/handler_spec.rb describe 'AWS Lambda Ruby Shindan' do context 'Invoke shindan function' do it 'returns error response' do response = shindan(event: {}, context: {}) expect(response[:statusCode]).to eq 400 end it 'returns succeed response' do # NOTE: 任意の有効な shindan_id を指定する response = shindan(event: {'shindan_id' => 865_730}, context: {}) expect(response[:statusCode]).to eq 200 end end end
(handler.rb
は spec/spec_helper.rb
, .rspec
など適当なところで require
しておく)
実装コードを書く
# handler.rb require 'json' require 'bundler' Bundler.setup(:deployment) require 'shindan' def shindan(event:, context:) shindan_id = event['shindan_id'] name = [*('A'..'z'), *('0'..'9')].sample(10) # "診断" に使う適当な名前の生成 scraper = ::Shindan::Scraper.new(shindan_id, name) { statusCode: 200, body: JSON.generate(scraper.shindan.lines.first.chomp) } rescue => e # なにか問題があれば 問答無用で 400 エラーを返す { statusCode: 400, body: JSON.generate(e.message) } end
API Gateway を設定する
Web ブラウザから AWS のコンソールにアクセスしなくても、こちら側 (serverless.yml
) で必要な設定を記述できる
template
の設定を書くことで、 API Gateway のエンドポイント + ?shindan_id=99999
と QueryString を組み合わせたリクエストで Lambda function に任意の値を渡せるようになる
# serverless.yml functions: shindan: handler: handler.shindan # The following are a few example events you can configure # NOTE: Please make sure to change your handler code to work with those events # Check the event documentation for details events: - http: path: shindan/create method: get integration: lambda request: template: application/json: '{ "shindan_id" : "$input.params(''shindan_id'')" }'
plugin を追加・設定する
このままだと、 AWS Lambda 環境内では あとから bundle といったやり方ができないので、gem の実態ファイルもろとも向こうの環境にアップロードするプラグインとその設定を追加する
npm install --save serverless-hooks-plugin
# serverless.yml plugins: - serverless-hooks-plugin custom: hooks: package:initialize: - docker run -v `pwd`:`pwd` -w `pwd` lambci/lambda:build-ruby2.5 /bin/bash -c "bundle install --deployment --without development && bundle package" package:finalize: - rm -rf vendor - rm -rf .bundle
デプロイと実行
sls deploy
でデプロイ実行
デプロイが成功すると、API Gateway のエンドポイント URL を教えてくれるので、そこにリクエストを送信してみる
成功すれば、上の画像のような結果が得られる
Links
Serverless:
- serverless/serverless: Serverless Framework – Build web, mobile and IoT applications with serverless architectures using AWS Lambda, Azure Functions, Google CloudFunctions & more! – - GitHub
- Serverless - The Serverless Application Framework powered by AWS Lambda, API Gateway, and more
- Serverless Framework - AWS Lambda Guide - IAM
- Serverless Framework - AWS Lambda Guide - Credentials
- uswitch/serverless-hooks-plugin: A plugin to run arbitrary commands on any lifecycle event in serverless - GitHub
- Ruby packaging does not include gems · Issue #5567 · serverless/serverless
AWS:
- AWS Lambda が Ruby をサポート
- Amazon API Gateway(API を簡単に作成・管理) | AWS
- AWS Lambda (サーバーレスでコードを実行・自動管理) | AWS
- AWS Identity and Access Management (IAM - ユーザのアクセスを安全に制御)| AWS