mike-neckのブログ

Java or Groovy or Swift or Golang

Vim でも AWS lambda 関数

普段 vimh/j/k/l/d/x/0/$/:wq くらいしか使わないのですが、ひょんなことから Vim で Web サーバーがたてられると聞いたので、サーバーが建てられるなら、 http クライアントも動くのだろうと考えて、 ラムダで動くかどうか試してみることにしました。

f:id:mike_neck:20181208195209p:plain


使用する vim

おそらく lambda を動かしている vm には、必要がないから vim は入ってないだろうと考え、 vim をビルドします。なお、このビルドは Amazon Linux 2 で実行しています。

yum install -y git ncurses-devel 
yum groupinstall "Development Tools"
git clone https://github.com/vim/vim
cd vim
./configure --with-features=normal --prefix=$HOME/release

vim の設定はなるべく軽いものにしたかったので、 --with-features オプションは normal にしました。また、リリースするのが目的なので、 --prefix$HOME の下の release ディレクトリーにしました。

また、試しに実行したときに libtinfo.so.6 がないため起動できなかったので、これを release ディレクトリーの下の lib ディレクトリーにコピーします。

このビルドが終わると、 release ディレクトリーの下はこのような形になります。

release
├── bin
│   └── vim
├── bootstrap
└── lib
    └── libtinfo.so.6

vim スクリプト

最初 bootstrap は単なる bash スクリプトにしようかと思いましたが、極力 vim でやろうと思ったのと、 shebang をつけてうまく終わるようにスクリプトを書けば、 vim の画面を表示しないでも vim を実行できる見通しがたったので、 bootstrapvim スクリプトを書いています。ちなみに vim スクリプトを書くのはこれが初めてです。

#!bin/vim -u

:let header = system("mktemp")[:-2]
:let request = "http://" . $AWS_LAMBDA_RUNTIME_API . "/2018-06-01/runtime/invocation/next"

:while 1
:  let event = system("curl -L -D " . header . " " . request)
:  let payload = "{\"receive\":" . event . "}"

:  let headers = readfile(header)
:  let id = ""
:  for item in headers
:    if item =~ "Lambda-Runtime-Aws-Request-Id"
:      let id = substitute(item, "Lambda-Runtime-Aws-Request-Id", "", "g")
:      let id = substitute(id, ":", "", "g")
:      let id = substitute(id, " ", "", "g")
:    endif
:  endfor

:  echo "==request=="
:  echo event
:  echo "==id=="
:  echo id

:  let response = "http://" . $AWS_LAMBDA_RUNTIME_API . "/2018-06-01/runtime/invocation/" . id . "/response"
:  echo response
:  let result = system("curl " . response . " -d '" . payload . "'")
:endwhile

:exit

リリース/デプロイ

先程のディレクトリーの構造

release
├── bin
│   └── vim
├── bootstrap
└── lib
    └── libtinfo.so.6

これを維持したまま、 zip でアーカイブして、 lambda にリリースします。


実行

lambda のコンソールから実行してみました。

次のようなペイロードを投げると、 receive というプロパティに同じオブジェクトが入った json が返ってくるはずです。

テストイベント

{
  "editor": ["vim","emacs","nano"],
  "language": "vimrc"
}

期待するレスポンス

{
  "receive": {
    "editor": ["vim","emacs","nano"],
    "language": "vimrc"
  }
}

そして実行結果の画面キャプチャーはこちら

f:id:mike_neck:20181208195011p:plain
テスト実行


というわけで、 AWS Lambda のカスタムランタイムとして vim を走らせることができました。 Vim スクリプトは サーバーレスアプリケーションを記述する言語になりうるし、 Vim はサーバーレスアプリケーション用のフレームワークと言うことができる。