AWS Lambdaのソースコードを覗いて動作原理を知る試み
この記事は、Serverless Advent Calendar 2016の14日目の記事です。
昨日は工藤さん(level69)による、「Serverless Meetup Sapporoで話てきた」でした。
工藤さんは元々北海道出身という縁もあることから、先日のServerless Meetup Sapporoに自腹で遠征してくれました。本当にありがとうございます。
本題
さて、本題ですが、最近はApache (元IBM) Openwiskを筆頭に、IronFunctionsなど、OSSなFaaS実装が増えてきていますが、ふと「Lambdaはどうなってんだろーなー。あ、ていうかLambdaもPythonなら、スクリプト言語だからある程度まではソースコード読めるんでは?」と思い立ったので、じゃあやってみましょうという試みです。
まずはFunctionの呼び出し元を知る
Functionの中でスタックトレースを出力すれば、Functionの呼び出し元が分かるはずです。Lambdaのソースコードの旅はここから始まる!ということで、出力してみましょう。
以下のようなFunctionをアップロードして実行します。
import traceback def lambda_handler(event, context): traceback.print_stack()
結果を見てみましょう。
$ lamvery invoke {} START RequestId: ed0dbfd9-c134-11e6-92b1-ab90b641e77e Version: $LATEST File "/var/runtime/awslambda/bootstrap.py", line 426, in <module> main() File "/var/runtime/awslambda/bootstrap.py", line 423, in main handle_event_request(request_handler, invokeid, event_body, context_objs, invoked_function_arn) File "/var/runtime/awslambda/bootstrap.py", line 243, in handle_event_request result = request_handler(json_input, context) File "/Users/marcy/project/lambda-source/lambda_function.py", line 4, in lambda_handler END RequestId: ed0dbfd9-c134-11e6-92b1-ab90b641e77e REPORT RequestId: ed0dbfd9-c134-11e6-92b1-ab90b641e77e Duration: 0.55 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 15 MB
/var/runtime/awslambda/bootstrap.py
がLambda Function実行時の真の起点となるソースのようです。
起点のスクリプトをダウンロードしてみる
では、起点のスクリプトが分かったので取得してみましょう。Lambda:invokeFunction
のAPIで得られる標準出力の内容は一定の長さを超えると切られてしまうので、S3に入れてみることにします。
以下のようなFunctionをアップロードして実行します。
import boto3 s3 = boto3.resource('s3') def lambda_handler(event, context): s3.Object('marcy-terui', 'bootstrap.py').put( Body=open('/var/runtime/awslambda/bootstrap.py', 'rb'))
起点のスクリプトを読んでみる
さて、S3に入ったファイルを落として読んでみましょう。すると、まず冒頭でPythonの標準モジュールではないものをimportしています。特にimport前にsys.path.append
等を行っている記述はないので、同じディレクトリ内にあるはず。
同じディレクトリ内のファイルを全て取得する
以下のようなFunctionをアップロードして実行します。
import boto3 import os s3 = boto3.resource('s3') def lambda_handler(event, context): for f in os.listdir('/var/runtime/awslambda/'): s3.Object('marcy-terui', f).put( Body=open('/var/runtime/awslambda/{}'.format(f), 'rb'))
これで全て取得できました。
え?ソースコードを見せろって?
はい。おっしゃる通りで、ソースコードを見ながらあーでもないこーでもないっていうのをやりたかったんですが、ソースコードに思いっきり Copyright (c) 2013 Amazon. All rights reserved.
って書いてあるので、勝手に公開したら怒られかねないなと思いとどまりました。。。
気になる方は是非上記方法を試して見てください。一部 so
化されていますが、大部分は普通のPythonコードです。まだ全てをちゃんと読み込んでないですが、起動されたLambdaプロセスが呼び出しを待ち受ける方法が1つではないことが分かったりして、中々面白い発見があると思いますよ。何か最適化のヒントとなる情報などが読み取れたりするかも?(これくらいは言っても怒られないはず?)
簡単ですが、以上です
本当は、以下のようなのをある程度完成させてお披露目したかったんですが、Serverless Meetup SapporoやYAPC::Hokkaidoの諸々やら仕事がわりと立て込んでたりで進捗ダメです・・・年内には目処を付けたい。。。
SAMとStep Functionsを良い感じにIntegrateしてLamveryの大型アップデートしたい(というか根本から作り直したい)ので一週間くらいそれだけやる時間ください
— Masashi Terui (@marcy_terui) December 5, 2016
とりあえず、こちらからは以上です。
Serverless Meetup Sapporo会場案内とお知らせ
こんばんは。もうすぐServerless Meetup Sapporoの開催ですが、皆様いかがお過ごしでしょうか。
つい今しがた会場の下見に行ってきたのですが、中々IT系のイベントでは味わえない良い雰囲気でした。 ただ、入り口の場所など少し分かりにくかったので、会場の情報や当日の諸注意等をお知らせしておきたいと思います。
ちなみに会場の雰囲気はこんな感じです(レイアウトは当日代わります)
お知らせ・諸注意
会場は言われずとも分かる方もいると思うので、まずはお知らせと諸注意の方から。
開場は12:00から、本編は13:00から
今回は開場が12:00からとなっています。12:00〜13:00までは Registration & Social
ということで、入場の受付と参加者間の交流の時間となります。
飲み物持ち込み禁止、食べ物持ち込み自由
会場では Cash on Delivery
(代金引換)にてお飲み物が飲めます(アルコールOK、ソフトドリンクも有り)その代わり、 お飲み物の持ち込みは不可 となっておりますのでご注意ください。
飲み物のメニューはこんな感じです。
また、お昼時だからというわけではありませんが、とある方のご厚意により軽食が出ます。ですが、あくまで軽食でありおつまみ程度になりますので、 昼食をしっかりと食べたい場合は先に済ませていただくか、ご自分で持ち込みをお願いいたします。(少し多めに持ってきて他の方にも振る舞うと喜ばれること請け合いです!w)
是非、お早めにお越しの上、お楽しみいただければと思います。
Wifiはありません
ありません。是非、Twitter等でも盛り上がっていきたい所ですが、Pocker Wifi等のご利用をお願いいたします。
会場案内
会場はこちらです。
大通駅36番出口(地下鉄東豊線方面)からほど近く、マクドナルド向かいのダイソーさんの地下になります。ダイソーさんが目立つので建物自体は分かりやすいかと思います。
入口が少し分かりにくいのでご紹介しておきます。
建物の入口
建物の入口はダイソーさんの大きい入口から向かって左側面です。向かいにパチンコのベガスベガスがあります。
建物の入口には会場のCINEMA CAFEさんの看板はありません。目印は大戸屋さんですかね。
ちなみに、入口脇には看板が置かれています。
お店の入口
入るとすぐ降り階段があるので下に降ります。降りると右手にTreasureというスープカレー屋さんがあり、その向かって左脇に入り口があります。
到着!
到着したらまず受付をお願いします。受付が終わったらMustではありませんが、お飲み物を頼んでお楽しみください。
最後に
今回はYAPC::Hokkaidoにあわせたことも相まって東京でも実現しなかったクラウドベンダー3社揃い踏み、スピーカー8名、LT4名とカンファレンス並の豪華布陣です!
しかも、クラウドベンダー以外はほとんどが道内在住の技術者、または北海道出身で今も北海道に縁のある方々です。最新の旬なテーマでも北海道でここまでやれるんだ!ということを全国に知らしめるため、是非盛り上がっていければと思います!
また会場も約50名が満員御礼で、YAPCのような大規模イベントを除けば大盛況と言えると思います。本当にスピーカーの皆様、参加者の皆様に感謝致します。ありがとうございます。
今後も継続的に開催していきたいですが、こんなに運営を頑張るのは初回だけなので是非楽しんでいただければと思います(えw
当日お会い出来るのを楽しみにしております!
Serverless FrameworkのPluginを2つリリースしました
Serverless FrameworkのPluginを2つリリースしました。
経緯など
以前からLamveryというデプロイツールを作って使い続けてきましたが、イベントを繋ぐGlue Codeを管理するには我ながら便利に使えていましたし、今も使っています。
ですが、複数のファンクションからなるシステムをServerlessで作るにはやはりFunction単位ではなくプロジェクトやサービス単位での管理をやりたくなる場面があって、Serverless Frameworkがv1.0で設定ファイルがYAML化して超シンプルになったのと、かなり作りが良くなって挙動をPluginで置き換えるのが比較的容易になったので、Serverless Frameworkの足りない機能や気に入らない部分をPluginで補うという方向でやってみることにしました。
LamveryのMulti Function対応も考えていたのですが、Function単位のデプロイ(下記参照)はあれはあれでとても満足していて崩したくなく、それを保ちながらMulti Functionにも対応するとなるとちょっと実装が厳しそうだなと感じたというのもあります。
Plugins
serverless-crypt
AWS KMSを使った機密情報の受け渡しをサポートするためのプラグイン。 Lamveryの同機能の移植&焼き直しです。
serverless-rollback-function
2016.11.07現在、周辺リソースや全ファンクションを対象とした deploy
コマンドのrollback機能はv1.1.0での導入が決まっていますが、Function単体をデプロイする deploy function
コマンドを使用した場合のロールバックのサポートはまだ未定です。片手落ち感が半端ないし、正直リソースも更新されて時間がかかる deploy
コマンドよりも実運用では deploy function
を多用することになるはずなので、これが巻き戻せないのはツラい。
ということで、こちらもLamveryのロールバック機能を踏襲しつつServerless Frameworkの仕様に合わせた形で実装しました。
Plugin開発で得た知見など
今週、2016.11.9(水)のServerless Meetupで発表します。
Lamveryはどうなるの?
Lamveryも最近は安定稼働していて特に新しい機能が欲しくなったりしてないので開発が滞り気味ですが、イベントを繋ぐGlue Codeを管理する用途では普通に使っています。そういう用途ではServerless Frameworkは重厚だし細かい所で色々気が利かないし、今後も開発は続けるつもりですので、フィードバックお待ちしてます :-)
参考までに私的な使い分けはこんな感じです。
- イベントを繋ぐGlue CodeをFunction単位で楽に良い感じで管理したい場合はLamvery
- Multi Functionでガッツリ開発する場合はServerless Framework(とPlugin達)
最後に
こんな感じで今後もServerless Frameworkの気に食わない部分は色々あるのでPluginを開発しつつ、Pluginが増えるとメンテが面倒なので某氏を見習って本家にねじ込めそうなものはねじ込む方向でやっていきたいと思います。よろしくお願いします(誰となく
ServerlessConf Tokyo 2016が最高だった
イベント参加後の感想書くの久しぶりな気がするw
9/30(金)〜10/1(土)に開催されたServerlessConf Tokyo 2016に1日目のワークショップは普通に一般参加者として、2日目はスピーカーとして参加してきました。
ワークショップ
思った以上に実践的でそこそこ長丁場だったのもあって、けっこう疲れました。 ゾンビが大量発生した世界で生き残った人々が連絡を取り合うためのチャットシステムを作るみたいな感じだったのだけど、そのストーリー性のあるテーマのおかげでTwitterで参加者がわいわいしながらやっててとても楽しかったです。
その様子はこちらでご覧いただけます↓
内容はAPI Gatewayはやっぱりマネジメントコンソールから手動でポチポチするのツラいな・・・とか、Amazon ESやっぱ微妙だな・・・とか思ったりもしたけど全体的にはとても満足度が高かった。
カンファレンス本編
会場の写真を撮り忘れたのが痛いけど、とてもおしゃれで一体感のある良い会場でした。また、飲食の提供がとても充実していて、これどう考えても参加費以上にかかってるよね・・・という感じですごい充実していました。朝・昼・夕食が出て、特に夕食が話してばっかりであまりゆっくり食べられなかったけど、とても美味しかったです。懇親会のお酒も十分な量提供されていて良かったです。
自分のセッション
www.slideshare.net
一応、海外発のカンファレンスで海外ゲストも多いということでスライドだけ英語にして日本語で解説するスタイルにしてみました。元々、自分のツールを宣伝する気はほとんどなくて、そういう話をしても一部の刺さる人以外には面白くないのは自明だったので、フレームワークやツールの話をする人が自分だけということも踏まえて、なるべく網羅的に解説するとともに何をどう使うべきで、これからどうして行きたいか、を考えてもらえるような構成を意識しました。あとで懇親会とかで感想をくれた人達の反応から、わりと伝わったようで良かった。え、最初のネタ?何の話ですかね??
追記:日本語による解説も書きました(勤務時間中なので会社ブログ)
ベンダーセッション
AWS,Azure,IBMのベンダーセッションについては内容的にはAWSとAzureは既に知っていることがほとんどで、AWSはEcho, Alexaのデモがあったのが良かった。Azureも知識レベルではそこそこ知ってるので特に得るものはなかったけど面白かったです。IBMはOpenWiskが思った以上にガチでServerlessに取り組んでるというのがまず意外で、一応これから動向くらいはチェックしていこうと思いました。あと、この場にGoogleが居ないのが本当に残念でした。Firebaseは素晴らしい(Firebaseについては同じくランチセッションで登壇したSection-9メンバーでフリーランスのきはるさんからの紹介が分かりやすかったです)し、Cloud Functionsも順調に正式公開に向けて開発されているようだし(MLを見る限り)、Serverlessの文脈に含むべきか微妙なAppEngineも、気にせずその凄さを語ってほしかった。
事例セッション
事例セッションはグノシーの松本さん、日経の猪飼さんのセッションが実体験に基づくノウハウ詰まった良セッションでした。あと、GS2の丹羽さんが情熱と共に高い技術力を持ってガチでServerlessに取り組んでいるのが、セッションもそうだしその後に個別にお話できた時からも感じられてとても応援したくなりました。
海外ゲストセッション
ServerlessConfの大本であるA Cloud GuruとCloud Academyの方々によるセッションで、どちらも英語ながら分かりやすい、的を得たセッションで良かったです。特にCloud AcademyのAlexさんのセッションがServerlessにする所・しない所やその他も含めて納得感のある構成や解説で最高でした。EngineYardの人のセッションも組織論的な話で気になってたけど、何をしてたか忘れたけどまともに聞けなかったのが残念。
www.slideshare.net
LT
お酒とこのあとのパネルのことに夢中であまりちゃんと聞けなかったけど、デジタルキューブ堀家さんの発表で紹介されたShifterはWordPressの運用を知っている立場からすると本当に最高です。世のWordPressユーザはみんな知っておいてほしい。
パネルディスカッション
伊藤直也さんをモデレータにお迎えして、スピーカーのグノシーの松本さん、日経の猪飼さんと共にパネルディスカッションに立たせてもらいました。ちゃんとした場でのパネルは初めてで、途中「伊藤直也先生とできない生徒(俺)」みたいな感じになって申し訳なさと悔しさがあったけど、それも含めてServerlessもそうだしそれ以外にも自分のこれからを考える上で得るものが大きかったです。改めて皆さんにお礼を言いたかったけど、気づいたら帰られてしまっていたので、この場を借りてお礼を言いたいと思います。ありがとうございました。
懇親会(Social)
懇親会では今までネット上(主にTwitterとGitHub)では絡ませてもらっていたけど、対面でお話したことがない方々とたくさん話すことができて本当に良かった。地方に住んでるとこういう時じゃないと会う機会がなくて、今回はServerlessが広いコンテキストで色んな人が集まるということでさらにそれを促進してたと思う。皆さん、これからもよろしくお願いします。
総括して
最高だった。会場wifi無いのにTwitter上で色んな議論や話題が出てて、自分も含めてみんなが色々考える良い刺激になっていたのが凄い良かったと思います。パネルでは「現実的な線」で落ち着いた感じはあったけど、自分としてはやはりもう少し先を目指してみたいので、これからも「やっていく気持ち」になりました。ということで、ちょうどまた東京出張のタイミングと合ったので来月のMeetupにも参戦します。あと、札幌でもやるぞ!!
最後に、主催の吉田さん、運営の皆さん、スポンサーの皆さん、ありがとうございました。
リモートマルチワーカーになりました
前置き
この記事は、同業で私のことを知っている方向けのご報告、及び私自身の節目に対する記録の意味で書かれたものです。
自分の新しい状況を適切に言葉で表現するのが難しい
とりあえず、今日から新しいスタートを切ったというのは間違いないんですが、転職しましたっていうのも違うし、かといってフリーランスになりましたっていうのもちょっと違う感じで、タイトル決めるのに小一時間悩みました。
色々調べていたら、マルチワーク(多業)という言葉があるらしく、微妙にニュアンスが違う感じもするのですが、わりとマッチしてる気がするのと、基本的にリモートワークになるので、合体させてみました。
http://www.mlit.go.jp/kisha/kisha06/02/020614_2/01.pdf
で、このなんとも怪しいタイトル*1のできあがりですw
状況など
とりあえず、状況を書き出してみます。
- 前の会社は退職しましたが、フリーランスとして一部業務を請け負っています
- 新しい会社はフルタイムではなく稼働日数を減らして契約社員という形でジョインしています
- 基本的にリモートワークになります
- 今は研修で東京にいて、数ヶ月の間は行ったり来たりします(ので、遊んでください)
ざっくり言うと、所属が変わってリモートワークになって「副業」だったフリーランスが「兼業」になったって感じですかね?
以前から副業として活動していたフリーランスとしての仕事に注力し、独立しようかと考え始めていた時に、とある会社の方々と元々は普通に業務委託で一緒に仕事をできればと思って相談させてもらっていたのですが、稼働を減らしてフリーランスの活動と両立する形での働き方を提案してもらい、提案されたポジションというか仕事内容が魅力的で、会社としても以前から良いイメージを持っていたので乗らせてもらうことにしました。待遇も基本的に正社員と同じでありがたいことです。(もちろん給与は稼働日数が少ない分は考慮されています)どの会社かはそのうち別の形でお知らせしたいと思うので、一応一旦ここでは書かないでおきます。 フリーとして外側から関わるとなかなかできないような仕事なども出てくるので、そういった意味でも中に入って関わる会社があっても良いのかなと思ったというのもあります。
一つ言っておきたいこと
前の会社を辞めたのは副業でフリーランスをやっていたからでは決してありません。
たまたま副業でやっていたからその道を志向しただけであり、それが無ければ単純に転職していただけの話です。それももう少し早い時期にしていたはずです。
じゃあなんで辞めたのかって話はここではしませんが、これだけは言っておきたい。
「副業は人材流出のリスクがある」は真逆(の場合もある)
これは前の会社が良い悪いではなく、普通に仕事をしていれば、つまらない仕事が回ってくることや上手くいかないことはあるものです。時にそれが耐え切れなくなってしまいそうになった時に1つの会社だけで仕事をしているとどうでしょう?
逃げ場がありません。苦痛のある仕事を続け無くてはならない。「逃れたければ転職するしかない」ということになります。
副業があれば「こっちの仕事はさっさと終わらせて別の仕事をしよう」と思えますし、気分転換になります。現実逃避に思われるかもしれませんが、会社側からしても低いモチベーションでダラダラ仕事されるよりよっぽど良いはずです。もちろん、それで本業に手を抜くようなことがあれば論外ですが、それはそもそも副業する時の大前提なのでまた別の話です。また、そうやって過ごしているうちにまたモチベーションが回復したならそれは両者にとってメリットにしかなりません。
そういうわけで、私は経験者として「副業は人材流出のリスクがある」は否定します。
これからについて
とりあえずは当面は家族との時間も大事にしたいので、新しい生活に慣れることを重視していきたいと思います。フリーの方のお仕事については、まだ活動のキャパはそれなりに残っているはずですが、既に契約済みのお仕事を除き、大変ありがたいことにいくつかいただいているお話についてこちらからアクションすることは少し様子を見ながらとさせていただきたいと思っています。 もちろん、アクションいただければちゃんと返しますので、優先で対応させたいなら今がチャンスかもしれませんw
というわけで
散文的になりましたがご報告でした。
|д゚)チラッ
SwaggerのAPI定義をRuby DSLで書いてAPI Gatewayにデプロイできる「rapis」というgemを作った
背景
API Gatewayはとにかく設定が面倒である。Serverlessの概念はシステムをシンプルに保てるとても素晴らしいものだが、それを実現するための設定が複雑になって、運用に支障が出たりするのは厳しい。*1
「柔軟なリソース定義を担保しようと思ったらまあ仕方ないよね」みたいな気持ちもあるが、やっぱり面倒なものは面倒だ。
便利だけど、1リソースでモックのレスポンス返すだけのAPI定義で50行超か・・・ / “AWS CloudFormation が Amazon API Gateway をサポートしたので使ってみた | Developers.IO” https://t.co/vgKAk7BVHY
— Masashi Terui (@marcy_terui) 2016年5月10日
Terraformですらこの記述量なのか。。。 / “TerraformでAPI Gatewway - @ijin” https://t.co/KPf9jV4wzl
— Masashi Terui (@marcy_terui) 2016年5月2日
Swaggerですら面倒くさい。1APIにつき3行くらいで記述したい。
— Masashi Terui (@marcy_terui) 2016年5月2日
俺達(俺)は書いたコードをサクッと上げてサクッとAPI公開したいだけなんだ!!1
書いたコードをサクッとLambdaで実行出来るようにするツールはすでにある。
問題はAPI Gatewayの方。現状でAPI定義をする上で一番マシだと思えるのがSwaggerのインポートによる方法だが、それでも、x-amazon-apigateway-integration
みたいなAPI Gatewayの独自要素*2に色々突っ込む必要があったりして、まだまだ十分とはいえないし、冗長な表現も多い。
先人の知恵を借りてみる
同じように、非常に生のJSONで扱うのがツラい某CloudFormation
というものがあるが、これをRuby DSL*3でかけるようにすることで劇的(当社比)に見通しが良くなり、冗長な表現を避けることができるようになるツールとして、kumogata
がある。ただ変換を行うだけではなく、実際にデプロイを行ったりするための運用に便利な機能も付いていて、最近もv2になってChange Sets(プレビュー的な機能)に対応したりプラグイン機構を導入したりして進化してる。本当にいつもお世話になってます。
じゃあ、Swagger定義も同じようにRuby DSL化すれば楽になるのでは?
というのが今回の趣旨。併せて、運用に便利なdiffを取る機能や定義のデプロイ等も含めてツール化してみた。
使い方
とりあえずインストールはgemなのでこれです。
gem install rapis
詳しくはREADMEを読んでいただければと思いますが、ざっくり主なコマンドの解説だけ。
API Gatewayの仕様上の注意事項としては、Swagger定義のインポートはAPIのベースとなる設定に対して行うが、実際にAPIとして公開されるステージにデプロイ(反映)する作業は別のステップとなっており、エクスポートについてはベースの定義を出力することはできず、デプロイ済みのステージから抜くことしかできないということ(デプロイはまあ良いとしても、大本の設定は抜けるようにしてほしい。。。)*4
- API作成
rapis create -n <API名>
- APIとそれらが持つステージを一覧表示
rapis list
- 既存API定義をエクスポート
rapis export -r <APIのID> -s <Stage名>
rapis diff -r <APIのID> -s <Stage名>
rapis apply -r <APIのID>
rapis deploy -r <APIのID> -s <Stage名>
記述について
今のところ、機械的にRuby DSLに置き換えるとシンタックスエラーになるような部分以外は特に特別な記述に置き換えるようなことはしていないが、これから使っていく中で汎用的に使えるような省略表現やメソッドなんかを入れていくことで、もっと楽にかけるようにしていきたい。目指せ1APIあたり3行!
ちなみ現状(2016-06-02)ではにこれが
{ "swagger": "2.0", "info": { "version": "2016-05-27T17:07:04Z", "title": "PetStore" }, "host": "p0dvujrb13.execute-api.ap-northeast-1.amazonaws.com", "basePath": "/test", "schemes": [ "https" ], "paths": { "/": { "get": { "consumes": [ "application/json" ], "produces": [ "text/html" ], "responses": { "200": { "description": "200 response", "headers": { "Content-Type": { "type": "string" } } } }, "x-amazon-apigateway-integration": { "responses": { "default": { "statusCode": "200", "responseParameters": { "method.response.header.Content-Type": "'text/html'" }, "responseTemplates": { "text/html": "<html></html>" } } }, "requestTemplates": { "application/json": "{\"statusCode\": 200}" }, "passthroughBehavior": "when_no_match", "type": "mock" } } } }, "definitions": { "Empty": { "type": "object" } } }
こんな感じになる
rest_api do swagger "2.0" info do version "2016-05-27T17:07:04Z" title "PetStore" end host "p0dvujrb13.execute-api.ap-northeast-1.amazonaws.com" basePath "/test" schemes ["https"] paths do path "/" do get do consumes ["application/json"] produces ["text/html"] responses do code 200 do description "200 response" headers( {"Content-Type"=>{"type"=>"string"}}) end end amazon_apigateway_integration do responses do default do statusCode 200 responseParameters( {"method.response.header.Content-Type"=>"'text/html'"}) responseTemplates( {"text/html"=> "<html></html>"}) end end requestTemplates( {"application/json"=>"{\"statusCode\": 200}"}) passthroughBehavior "when_no_match" type "mock" end end end end definitions do Empty do type "object" end end end
実装について
基本的にはAWS APIをゴニョゴニョしているという形なんですが、一番面倒そうなAPI Gateway上ではJSONとして扱われるSwagger定義をRuby DSLと相互変換するのは、kumogata
を含め、AWS等の設定をコード化するCodenize.toolsの作者であるid:winebarrelさんが公開しているdslh
というgemを使ってます。
ということで、偉大な先人へ感謝をしつつ締めたいと思います。よろしくお願いします。
*1:普段、こんなことを言ったりしてるけど、これはServerless自体を否定してるんじゃなくて「サーバのお守りをしたくないだけならPaaSで良いんじゃないの?Serverlessはそこがコアじゃないよね?」って意味である
*2:参考→ Swagger に対する API Gateway 拡張 - Amazon API Gateway
*3:他のフォーマットもサポートしてる
*4:そもそもAPI Gatewayのデプロイの概念がよく分からんという方はコチラを→Amazon API Gateway での API のデプロイ - Amazon API Gateway
LamveryにSwaggerベースのちょっとリッチな機能付きAPI Gateway integrationを追加しました
経緯
API Gatewayの"x-amazon-apigateway-integration"っていう独自要素に色々突っ込んでるSwagger記述サンプルを見て複雑な気持ちになってる
— Masashi Terui (@marcy_terui) April 11, 2016
書いたコードをサクッと上げてサクッとWebから叩ける用にしたいだけなのに何故こんなにJSONを書かないといけないのか
— Masashi Terui (@marcy_terui) April 11, 2016
ということでサクッとAPIが定義できるようにしました。
ここで説明しないインストール方法や使い方の詳しい情報はGitHubのREADMEやQiitaの記事でご確認ください。
使い方(コマンド)
lamvery api [-d] [-n] [-r] [-s <stage-name>] [-w]
-d
は恒例のDry run!!-n
が後述の自動オプション付加の無効化-r
で削除-s
はAPI Gatewayで言うステージ(dev,prod環境使い分けるとかに使う)-w
で新規作成時に設定ファイルにAPIを識別する番号を保存(更新する時に指定しなくて良いようにする)
設定
こんな感じで設定を書きます。
api_id: myipugal74 stage: dev cors: origin: '*' methods: - GET - OPTION headers: - Content-Type - X-Amz-Date - Authorization - X-Api-Key configuration: swagger: '2.0' info: title: Sample API schemes: - https paths: /: get: produces: - application/json parameters: - name: sample in: query required: false type: string responses: '200': description: 200 response schema: $ref: '#/definitions/Sample' definitions: Sample: type: object
ちなみにこれとほぼ同じ雛形は以下のコマンドで生成できます。
lamvery init
で、本来ならこれをAPI Gateway
でLambda
backendによって動かすためには x-amazon-apigateway-integration
っていう要素に色々突っ込まないといけないわけですが、その辺は同じくLamvery
でデプロイしたFunctionに向くように自動でよしなにやってくれるという感じです。
差分表示
こんな感じでDiffっぽくSwagger定義の差分が見れます。Dry runにすれば事前に確認だけすることが可能。
最後に
これぐらいサクッと書いてサクッとAPI公開できると「ああ、サーバレスっていいなあ」って思えそうな感じ。
ただ、認証の定義とかは未対応だし、自動オプション付加のやり方とかもうちょっとスマートに出来ないか悩み中で、もしアイデアあればいただけると嬉しいです。
-n
(x-amazon-apigateway-integration
の自動付加をしないオプション)をつければ単純に差分表示&Dry run対応のSwagger importerとしても使えるので、良かったら使ってみてご意見ください。
明日、ぺちかん北海道なのに俺、何やってんだ。。。