RubyなしでItamaeレシピを実行できる「itamae-go」を作った

Goとmrubyを使ってitamae-goを作った

github.com

Pokemon Goが流行っていたので流行に乗じてItamae Goを作った。

というのは冗談で、手元の開発環境のセットアップにitamaeを使っているのだけど、まっさらな環境でitamaeを実行したい時にRubyやitamaeをどういれるかについて考えるのが面倒なので、Rubyなしで実行できるitamaeを作った。Goで実装し、mrubyでレシピを読むことによりRubyなしでの実行を実現した。

インストール方法

Releasesバイナリを置いてあるのでこれをダウンロードする。基本的には環境セットアップ用のシェルスクリプトからこれをcurlなりwgetなりでダウンロードして使うことを想定している。

なんか動かなかったらgit cloneしてmakeすればその環境用のバイナリが作れるはず。 *1

使い方

普通にitamaeレシピを書いて、

# recipe.rb
package 'vim' do
  action :install
end

service 'sshd' do
  action [:start, :enable]
end

itamae-go localを実行する。

$ sudo ./itamae-go local recipe.rb
 INFO : Starting itamae...
 INFO : Recipe: recipe.rb
 INFO : package[vim] executed will change from 'false' to 'true'
 INFO : service[sshd] executed will change from 'false' to 'true'
 INFO : service[sshd] executed will change from 'false' to 'true'

CLIは大体本家itamaeと同じになるように作っていて、Thorじゃなくてmitchellh/cliを使ってる都合でitamae helpitamae-go --helpになってるところだけ違う。itamae-go sshはなくて、itamae-go localのみ。

実装ステータス

開発環境によく使われそうなOSXUbuntu(Debian)と、僕が使うArch Linuxをサポートしている。

実装している機能のリストはREADMEに書いてあって、_exampleに入ってるような機能は動く。 けど、一見実装されてそうな機能をいろいろサボってたり、まだ僕もそんな使ってない状況なので、自分で直しながら使うつもりの人以外は使わない方が良さそうなステータス。

Goからmrubyを使った感想

これを実装するために一昨日あたりに初めてmrubyを触った。あとプログラムに別の言語を組み込むのも初めてだったので、その辺の感想を書いておく。

良かった点

両方の言語の良いとこ取りができる

Goの豊富な標準ライブラリや高い性能を生かしつつ、RubyDSLやmrbgemsを活用した機能を持つことができ、両方の言語の良いところがそなわり最強に見える。

mrubyが思ったよりいろいろできる

mrubyはIOがないとかrequireがないとか、あんまり普通にプログラミングできるイメージではなかったけど、mrbgemsを追加してmrubyをビルドすれば割と目欲しい機能は揃う。やんちゃコードのミルフィーユみたいな奴も動いた。

悪かった点

Goとmrubyを行ったり来たりするコードを書くのが面倒

少なくともmitchellh/go-mrubyにあるAPIでは、Rubyで作ったデータ構造をいい感じにそのままGoの世界に持ってくる手段がない。具体的にはGoでJSONを読み込む時みたいにstructにtagを書いておくとRubyのstructがそのまま読めるみたいなのをやりたい気がするが、まあなかったのでRuby側にHashをとっておくコードを書いてkey一つごとにメソッド呼び出しをすることで取得していた。*2

あとは、そもそもRubyのコードをGoの文字列として持つしかないのでその時点で汚ないコードだし、それをどこに配置するかみたいな設計も難しくなる。

ロスコンパイルが大変

というか僕がcgo有効なGoのクロスコンパイルに慣れてなくてまだできてない*3。Goとmrubyそれぞれではクロスコンパイルができるので多分できるんだろうけど、普通のGoやmrubyのクロスコンパイルに比べるとちょっと面倒そう。

気持ち

mruby-cliでもワンバイナリにできるし、mrubyになくて困ったのは__FILE__くらい*4だったので、mrubyだけで作っても良かったんじゃないかと思ったけど、組み込み言語に関する知見は結構あったので良かった。

追記:

http://k0kubun.hatenablog.com/entry/itamae-mruby

k0kubun.hatenablog.com

*1:Makefileが雑なのでgoのディレクトリ規則に従った場所にgit cloneしないと通らない

*2:流石にもう少しマシな方法はあると思う

*3:なので、Releasesに置いてある奴はマシンを2台使ってあたたかみのあるビルドをしている

*4:なかったので、itamae-goでは読んでるRubyのコードのファイル名のスタックを持つようにしてるけど、それはmrubyでもできるので実装の障壁にはならない