2011-09-30(金) [長年日記]
■ Amazon-Auth-ProxyをSinatraに移植してHerokuで動かす
先日発表になったGoogle App Engineの値上げはGAE上で無償サービスを運用していた人たちをパニックに陥れたが、tDiaryとて無関係ではない。amazon.rbが使っているProduct Advertising API用リバースプロキシがGAE上で稼動しているからだ。
GAEの値上げ自体は11月まで猶予されたが、それでもやはり、ああいうロックインされやすい環境に依存するのは危険だ。で、同じサービスをまちゅさんがheroku + Sinatraに移植してくれたので、そちらに引っ越すことに。たぶん10月末に予定されているtDiaryの次のリリースからはこちらを使うことになると思う。
さて、リバースプロキシだけでなく、認証プロキシの方もいつまでもCGIじゃねーだろというかもっと移植性の高い環境で動かさないとね、ということで。Sinatra移植に挑戦してみた。仕事でRuby使ってるつっても主にデータ処理なのでWebアプリの新作はもう何年も作ってないわけで、新しい技術のキャッチアップはぜんぜんしていないのだ。もちろんRailsでもいいわけだけど、そんなデカいものを作る予定もないのでまずはSinatraから。
というわけでGithubの方にいろいろ追加→amazon-auth-proxy。元のCGIをそのままライブラリとして使っているのでかなりひどいアーキテクチャだが、RSpecで不完全ながらテストも書いたし、Rack上で動くようにしたし、Bundler対応もした(というか対応しないとHerokuで動かせないみたい……なのかな?)。なんかモダンじゃーん。
で、これをHerokuで動かす。この手順を簡潔にしておけば、誰もがプロキシを運用できるはず。まずはgemでherokuをインストールし、「heroku create」でアプリケーションを作成する:
% gem install heroku ... % heroku create amazon-auth-proxy-tdtds Enter your Heroku credentials. Email: t@tdtds.jp Password: Found the following SSH public keys: 1) id_dsa.pub 2) tdtds.pub Which would you like to use with your Heroku account? 1 Uploading ssh public key /home/sho/.ssh/id_dsa.pub Creating amazon-auth-proxy-tdtds... done, stack is bamboo-mri-1.9.2 http://amazon-auth-proxy-tdtds.heroku.com/ | git@heroku.com:amazon-auth-proxy-tdtds.git Git remote heroku added %
これでamazon-auth-proxy-tdtds.heroku.comというサイトができた。ここにプログラムをgit pushすればデプロイできるのだけど、さて、ここで問題が。設定ファイルには秘密にしておかなければならないAmazonのキーが含まれるので、これをGitHub上に公開するわけにはいかない。たぶん良いプラクティスがあるのだと思うが、とりあえずローカルにreleaseというブランチを切って、そこに設定ファイルを含めてHerokuにpushすることにした。
% git checkout -b release % cp amazon-auth-proxy.sinatra.yaml amazon-auth-proxy.yaml % vi amazon-auth-proxy.yaml ...KEYなどを書き換え... % git add amazon-auth-proxy.yaml % git commit -m 'added yaml file for release.' ... % git push heroku release:master Counting objects: 90, done. Compressing objects: 100% (86/86), done. Writing objects: 100% (90/90), 12.94 KiB, done. Total 90 (delta 44), reused 3 (delta 0) -----> Heroku receiving push -----> Ruby/Sinatra app detected -----> Gemfile detected, running Bundler version 1.0.7 Unresolved dependencies detected; Installing... Using --without development:test Fetching source index for http://rubygems.org/ Installing diff-lcs (1.1.3) Installing rack (1.3.2) Installing rspec-core (2.6.4) Installing rspec-expectations (2.6.0) Installing rspec-mocks (2.6.0) Installing rspec (2.6.0) Installing tilt (1.3.3) Installing sinatra (1.2.6) Using bundler (1.0.7) Your bundle is complete! It was installed into ./.bundle/gems/ -----> Compiled slug size is 680K -----> Launching... done, v4 http://amazon-auth-proxy-tdtds.heroku.com deployed to Heroku To git@heroku.com:amazon-auth-proxy-tdtds.git * [new branch] release -> master
ありゃー、いりもしないRSpecまでインストールされちゃってるな。これはGemfileで開発用のgemだけ分離するような書き方があるのだろう(と、tDiaryのGemfileを見ながら学習)。まぁいいや。なんにせよ、本当に簡単で拍子抜けするくらいだなぁ。これが現代のPaaSか!(今ごろなに言ってんだ)
というわけでいちおう動くようになったけど(プロクシなのでブラウザからアクセスしてもなにもないよ)、まだ異常系もロクにできていないのでもうちょっといじってから本番投入するとしよう。
Amazonのキーは環境変数に入れるというのはどうでしょう?
http://devcenter.heroku.com/articles/config-vars
pitを使うとか
http://subtech.g.hatena.ne.jp/cho45/20080102/1199257680
今回、(ロックインを避けるために)環境に依存しないようにするのが主眼なんだけど、その環境変数技はHeroku以外にも応用が聞くんでしょうか? いやまぁ、環境変数くらいどこでも設定できるだろうとは思うけど。
Pitは普段から使っているけど、この場合の解決になるのかどうかよくわからない……。
dotCloundの場合は、設定ファイル(dotcloud.yml)に環境変数を書くやり方みたいですね。
http://docs.dotcloud.com/guides/environment/
まぁたしかに、ソースツリーに設定ファイル含めちゃったら、サーバ増やせないもんなぁ。しかし環境変数を使うとサーバはスケールするけど、PaaSごとに使い方を説明しなくちゃいけなくなるから人がスケールしない……。
group :test を除外するには BUNDLE_WITHOUT を使います(これはHeroku特有の設定)
heroku config:add BUNDLE_WITHOUT=development:test
Amazonのキーも環境変数を使うのがベターでしょうねえ。基本は yaml から読み出して無いなら環境変数という感じと思います。
あー、次善の策として環境変数を使うというのはいいね。そうしよう。
:testの除外については、ログに「Using --without development:test」とあるので、指定さえしておけば向こうで除外してくれるという認識なんだけど……。
Gemfile に group :test do ... end を作らないとダメです!
ああ、それはもちろん。