2014-05-20: ごがつはつか: Asakusa.rb #261

Asakusa.rb #261 だった。レアキャラゲストがきていたので例によって途中で移動が発生したのだけど、予算の関係で早期に撤退しました。

envchain というのをつくったはなし

https://github.com/sorah/envchain を作って公開しました。

export AWS_SECRET_ACCESS_KEY とかしてカジュアルに普通のシェル環境につねに credential とか token の類をつっこんでおくと、意図せずそのトークンが使われて事故ったり、悪意のあるコードとかで流出したら怖いよね (特に前者) ということで昔から専用の env コマンドの alias をつかって必要なコマンドにだけ AWS トークンな環境変数をセットしていた。

という事をいってたら「それみんなもそうした方がいいかもねー、あーほら OS X keychain とか」みたいな事を言われたので実装してしまった。

$ envchain --set aws-sorah AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
aws-sorah.AWS_ACCESS_KEY_ID: foo
aws-sorah.AWS_SECRET_ACCESS_KEY: bar
$ env | grep AWS_ || echo 'there is no aws env'
there is no aws env
$ envchain aws-sorah env | grep AWS_
AWS_ACCESS_KEY_ID=foo

自分にとっても気軽に同様のコマンド増やせるし、plain text で保存しなくてすむし、複数の credential 切り替えとかも楽だし便利になった。

どうぞご利用ください。

Published at 2014-05-20 23:00:00 +0900

2014-05-18: ごがつじゅうはちにち

ちょっと前から録画サーバーに logrotate を入れて (入れ忘れてた) 放置してたらサーバーがいきなり hang するようになって、rotate のタイミングぽいから無効化して放置していた。 やっぱりログが肥大なので適当に手で掃除してたら目の前で hang してくれて、まだ ssh セッションもいきている状態だったので調査できた。

具体的には munin の巨大なログを rotate するときに munin があやしいのかと思ったらそうではなかった。 手で log の掃除をしてた時に起きて、しかしmuninはそんなへんな感じになっていなかったのでファイル周りがあやしいのかなあと想像。その内 LA がみるみる上昇していく。でも CPU 使用率はそんな高くない。

というわけで ps してみると uninterruptable なプロセスがわんさかいらっしゃるの。そして /var/log ディレクトリを見に行った瞬間そのプロセスはそうなる。ssh とか sudo はログを吐きにいくから当然刺さる。tmux でひたすら :new-window su してしのぎました。

結論としては dmesg で ext4 サブシステムがなんか吐いてくれてた。 https://gist.github.com/sorah/d2927b576687bda99f6b#file-dmesg

/var/log がおかしいことになってるので当然再起動した後は書き込まれてなくてわからなかったので目の前で再現してくれて助かった。

linux.git: 89a4e48f8479f8145eca9698f39fe188c982212f で直っているみたいなのでひさびさにカーネル更新して終了、したい。ひさびさに更新しようとしたら udev とかいろいろ依存が絡んできてつらい目にあっています。まずは gcc を新しくビルドしないと udev がビルドできない。

Published at 2014-05-18 23:00:00 +0900

2014-05-17: ごがつじゅうなのか: Ruby 開発者会議

5 月の Ruby 開発者会議に参加してきた。会場をホストするとすぐ行けて便利。(当初予定より待機が遅れてしまって申し訳なかった)

https://bugs.ruby-lang.org/projects/ruby/wiki/DevelopersMeeting20140517Japan

大きい変更と言えば lib/test ディレクトリを消しました。minitest も消えると思う。 Ruby 本体のテストケースは test/unit と test/unit が依存している minitest 4 に依存していたのだけど、 hsbt さんが test/unit, minitest を lib から test にコピーして lib/ ディレクトリへの依存を無くしてくれたので一旦消した。ありがたや。

test/unit.rb は minitest 4 のラッパーになっていて、minitest 5 だと内部構造が変わりすぎていて追いかけるのがしんどいというのと、そもそもこんなラッパーならいらないよね、というのが元々の流れ。あとは gem install minitest で 5 系が入っちゃうと壊れるという問題もあった。

詳細は https://bugs.ruby-lang.org/issues/9660, https://bugs.ruby-lang.org/issues/9711 まで。 個人的に Ruby 2.0 に入ってた test/unit (wrapper of minitest) と minitest 4 を、test-unit.gem (すとうさんが作ってる奴) と minitest 5 にしちゃうのがいいと思うんだけど。互換性がある || アップグレードが簡単なのであれば。

ただ minitest / test/unit を実際同梱しておいてどれくらいの人が嬉しいかというと微妙なのは実情だと思う。だからといって rspec を bundle みたいな流れにするのも、そもそもテストフレームワークを一切同梱しないのもなんかへんだと思うんだよな。ご意見求ム!

夜は 目黒にあった fish house oyster bar に流れた。生牡蠣リスクなのとそこまで好きなわけじゃないので焼き牡蠣と、シーフード的なやつやパエリア的なやつを食べた。 Ruby コミッタ各位はまたいつも見ている Web 系 Rubyist 各位と違った話題がでてきて濃くておもしろい。勉強になる。

Published at 2014-05-17 23:00:00 +0900

2014-05-08: ごがつようか

なんか一週間たつのはやい、と思ったら今週の営業日は少なかったのだった。

mackerel.io

はてなから mackerel.io とかいうメトリクス収集サービスが出ていたので試した。

gentoo 向けの ebuild を書きました: https://github.com/sorah/sorah-overlay/tree/master/net-analyzer/mackerel-agent

いかんせん個人なので冗長化とかをしっかりしているわけじゃないからサービス・ロール毎に2台以上それぞれ登録して、みたいな事はできないから本領発揮はしていないのだろうけど、綺麗にグラフとかでているし今後の機能拡張が待たれる。期待!

なんか察するに agent が go 製なのだけど、LL で下手に書くと既に入ってる LL の環境との相性等があって Treasure Data の fluentd パッケージ td-agent のように LL のインタプリタを同梱してパッケージングをする、という形になってしまう。 かといって C/C++ で書くのも少しだるいのか、そこで LL ぽさがある go で書くと 1 つのバイナリに収められるし、気軽なツール配布に go は向いてるのかなぁ、とおもった。個人的には C/C++ とかでもいいんだけど、go でも便利だし目的は満たせるからね。

golang はなんか外部との依存がほとんどなくて、ssl 周りのレイヤも独自で実装していてすごい。善し悪しは置いておいて。

Published at 2014-05-08 23:00:00 +0900

2014-05-02: ごがつふつか

花金だ。

Tour of Golang

そろそろ golang 把握だけはしておかないと、という事で tour.golang.org をやった。

72,73、これでいいのか自信がない。もっといい手があったりして。

模範回答はたぶん https://code.google.com/p/go-tour/source/browse/#hg%2Fsolutions なんだろうけど、これを見るかぎりどうやら #72 は tree.New(1) はかならず同じ結果返すっぽい。順序いれかわったりするんだろうとか勝手にきめていた。ので模範が書いてある通り、両者を同じ順序で辿っていって違うのが一つでもあったら打ち切るという戦略で良いんだと思う。


(public gist も secret gist っぽい URL もつようになったぽい。)

iTunes Match

日本の iTunes Store でもついに iTunes Match がはじまった! とてもうれしい。

iTS 上にある曲とのマッチングとかはどうでもよくて、iTS になくても web 上に上げておいて他のデバイスからなかったら fetch してくるという事ができるので満足。あ、ただ昔に rip した音源とかは 128kbps MP3 だったりするのでそれが 256kbps AAC にできるというのは嬉しいかも。

しかし matching ほんとうに終わらない。サービス開始直後の過負荷なのかなんなのか知らないけど... 定期的に stop して start すると、前回より高速に stop したところまでじわじわと復帰してくれるので、それでちょっと伸びてまた止まったら同じように stop → start…を繰り返している。

あとはよく他のスマートプレイリストを条件に加えたスマートプレイリストをつくっているんだけど、そいつらはどうも対象外になるっぽくて中途半端にスマートプレイリストが同期された…… 惜しい。

本・雑誌

わーニュージェネ 3 人が表紙だわー

スタッフへのインタビューみる限り丁寧っぽいから期待が膨らむ。

ニセコイ 12 (ジャンプコミックス)
古味 直志
集英社 (2014-05-02)

読んだ。

Published at 2014-05-02 23:00:00 +0900

2014-04-23: しがつにじゅうさんにち

12km 徒歩。 (ただしカロリーはオーバーコミット)

CD

創傷イノセンス (初回限定盤)
内田真礼
ポニーキャニオン (2014-04-23)
売り上げランキング: 123

悪魔のリドル OP。まややん 1st シングルがとどきました。

配信は以下:

conoha にある CI サーバが刺さる

最近 conoha においてある chkbuild とか CI 用につかっているサーバーがよく刺さる。 具体的には、

  • VNC コンソールはまあ生きている (Left-Super での端末切り替えができる)
  • ただし login: で enter を叩くと帰ってこなくなる
  • ping / ssh とかは当然ながらとおらない

みたいな状態。しぶしぶ force reboot してたけど、再発しまくるので調査しないとならない気がする… どうやら chkbuild 中になっているみたいなんだよなあ。

一度コンソールでログインしっぱなしにしておいて再現したときにそのシェルの様子を見ようとしたけど、キー入力を与えてもなにも反応してくれなくなっていた。

conoha で magic sysrq

JavaScript Console を開いて、

rfb.sendKey(XK_Alt_L, true); rfb.sendKey(XK_Sys_Req, true);
rfb.sendKey(XK_m);
rfb.sendKey(XK_Alt_L, false); rfb.sendKey(XK_Sys_Req, false);

とかすればよい。1行目で Alt, SysRq の keydown が飛んで、2行目で m の keydown → keyup が飛ぶ。最後に Alt, SysRq のKeyUp を飛ばしてやる。

他のキー飛ばしたりしたい場合は、XK_m とかを XK_p なり XK_9 なりにすればよい。keysym.js 参照。

公式で SysRq ボタン用意してくれないかな。AltとかCtrlのボタンあるんだし。

とりあえず自己責任でどうぞ。

デレラジ

外だった上に電波が弱いところで iPhone できいてたけど音質がしんどかった。立ち見だからっていうのもあるのかなぁ 途中から 50kbps → 3000kbps くらいになって途切れ途切れになってたりしたし、おまけコーナー必須な気がするのでアーカイブ明日聞きます。

マリエッティがデート申し込んでたのすごいよかった。 アイマスタジオでのノリといい、キャストが完全に Pa だと思う (日記 4/18)

後はぬー、もとい 765 勢がデレラジにいるの新鮮だった。絡み聴くの楽しいね。

きゃはっ (っ>ω<c)

Published at 2014-04-23 23:50:00 +0900

2014-04-16: しがつじゅうろくにち

gem リリースしたりなんなりとしてました。

Villein - control serf agents from ruby

https://github.com/sorah/villein というのを作りました。 serf agent を立ち上げたり、serf コマンドのラッパーとしてユーザーイベントを発火させたりいろいろできます。

agent = Villein::Agent.new
agent.start!
agent.auto_stop

agent.on_member_join do |event|
  p event.members
end

agent.event('my-event', 'the-payload')

イベントハンドラーを親プロセスで受け取るの、親プロセスが死んだ時にどうするんだろうとかいろいろあるだろうけど、これが不要な設計にするべきというのが serf なのかなぁと思いながら実装した。実際どうなんだろう?

NGしまむらさんフィギュア

ダプルピースしまむらさんのフィギュアの発売が1ヶ月延期とのことです。 ところでこれ職場で目の前に置いてたいんですが、さすがにやばそうなので家の机に置きます。

トラハモ

かわいい。最後の天ちゃんの「乗っとるから」が怖い…もよーもよー…

Published at 2014-04-16 23:00:00 +0900

2014-04-14: しがつじゅうよっか

生きてます。


iTunes - ミュージック - fhana「いつかの、いくつかのきみとのせかい - EP」

表題曲だけ買った。後でカップリングも買う。


舞浜以降、外でも家でも同じセットリストばかり聞いていて、いつになったら普段のプレイリストに戻るんだろうという感じ。


さいきん、

を見てから入れるべきかなーと思っていた rubocop つっこんでみたけど、めちゃくちゃきびしいのね。 ベースは ↑ に乗っている config で、追加で以下:

# `raise` の代わりに `fail` を使えと一部いってくる。理由がよくわからないので切ってる。
SignalException:
  Enabled: false

# self. 明記しなくていいところは省けといってくるが、 self.attr == other.attr みたいな時には
# self 書いたほうがわかりやすかったりするので切ってる
RedundantSelf:
  Enabled: false

# 1行だけのメソッド定義はやめろと言ってくるけど、まぁ !!@ivar くらいの定義であれば 1 行でも
# いーじゃんみたいな感じなので切った。切らなくてもいいかもしれない。
SingleLineMethods:
  Enabled: false

# 式展開とかしてないなら single quote つかおうと言ってくる。が、今から直してまわるのはしんどい
# ので severity を下げてる。
StringLiterals:
  Severity: warning

# Hash とかで最後に余計なカンマを置いてると怒られる。ただこれしておくと 1 行追加した時に
# diff が綺麗なんだよね。という事で切っている。
TrailingComma:
  Enabled: false

# ↑ でメソッドの 1 行定義を並べたりするときに、行の間に空白がない。
# というわけでこれにひっかかるので切る。
EmptyLineBetweenDefs:
  Enabled: false

# %記法は `[` `]` を使えと書いてくるけど、そんなんケースバイケースだろという事で切ってる。
PercentLiteralDelimiters:
  Enabled: false

# 複数行で lambda つくるときは -> じゃなくて lambda つかえと言ってくる。
# 理由が見当らないし納得もできそうにないので切る。
Lambda:
  Enabled: false

しちゃった。

Published at 2014-04-14 23:00:00 +0900

2014-03-22: さんがつにじゅうににち: kosenconf-080tokyo

高専カンファレンス in 東京 2014 行ってきた。写真はまだ。

なんか asonas がコード書いてたので後ろから突っ込みを入れたり(依頼を受けてました、) CTF やってみようと言われたのでバイナリもらってう〜んといじってたら解けたとかやっていた。

たいした事はしてなくて手元で動かして strace しつつ探っていただけですね。実行ファイル無しでも解きたかったなあ


昼はじぐそうくんと asonas、mactkg と一緒にハングリーバーガーへ。


Rails 4 のエラーページ

Rails 4 において開発時の例外内容つきエラーページと production での素朴なエラーページ、さらに ActiveRecord::RecordNotFound だったら 404 とかデフォルトでどこでやってるんだろうみたいなのを追っていた。

  • ActionDispatch::ExceptionWrapper が例外を保持して @@resque_responses を見て exception のクラス名をキーに何かが取れたらそれをステータスコードとして返したりしている (#status_code, .status_code_for_exception)
  • 例外の表示は ActionDispatch::DebugExceptions ミドルウェアが担当。 config.action_dispatch.show_exceptions が true で config.action_dispatch.show_detailed_exceptions が true であればビューを render して返し、wrapper の返してきたステータスコードを採用
    • ActiveRecord::RecordNotFound であれば 404 で返しつつ例外ページが render される
    • config.action_dispatch.show_detailed_exceptionsconfig.consider_all_requests_local の値が採用されている事がある
  • エラーページの表示は ActionDispatch::ShowExceptions ミドルウェアが担当。 config.action_dispatch.show_exceptions が true であれば exceptions_app を呼び出し、そのレスポンスをエラーページとして採用する。
  • exceptions_app はデフォルトで ActionDispatch::PublicExceptions が利用される
    • Rails::Application#default_middleware_stackRails::Application#show_exceptions_app が呼ばれていて、そこでは config.exceptions_app がなければ PublicExceptions を作成して返している
    • exceptions_app は rack env で例外オブジェクト、また PATH_INFO で ExceptionWrapper の返してきたステータスコードが渡される (例: /404, /200)

こんがらがったのは下記。

  • config.action_dispatch.show_exceptions は例外ページを表示するのではなく Rails が例外のハンドリングをするかのフラグである
    • これが標準では test environment で無効になっているので、controller テストとかでは、例えば RecordNotFound エラーはテストコードまで届く
  • config.consider_all_requests_local が例外ページを表示するかを指示する

(つか Configuring Rails Applications — Ruby on Rails Guides に書いてあるんだから読めという話ではあった… middleware の話も書いてあったとは…)

Published at 2014-03-22 23:00:00 +0900

2014-03-15: JAWS DAYS 2014 #jawsdays

JAWS DAYS 2014 に参加してきました。

午前中のセッションは寝坊したのもあって逃した。といっても午後から参加しても支障がないタイムテーブルだったので (Kinesis の話とかはちょっと聞きたかったけど) 問題なし。

イベント自体の雰囲気としては、若干スーツや年齢高めの人達も散見されて、発表中に携帯のカメラでスライドを撮影する音がめっちゃ聞こえてくる感じで渋かった。異文化交流みたいな感じある。 内容自体はすごい良かったと思っています。

"Building Moneytree’s data aggregation system with SWF"

https://moneytree.jp/ の方が Amazon Simple WorkFlow について話していた。 "Our goal: sleep at night" …!

API throttling に気をつけようだとか、各 activity は何度実行しても冪等であるとカジュアルにリトライできて便利、みたいな話がされていた気がする。

しかし話は外れるけどデビットカードのアグリゲーションにどこも対応してなくてこういうサービス使いにくいんだよね… (即時引き落しなので銀行をトラックしとけばいいんだけど、銀行口座の明細には「デビットゴリヨウ」としか残らないのであった)

"AWSクラウドデザインパターン for Enterprise"

エンタープライズ方面の人間じゃないけれど CDP 面白いので聞いてきた。 あえてサブネットを切りまくってよりセキュアにするとか、pci-dss 準拠してないサービスもあるから PCI-DSS 守らないといけない人は気をつけようだとか、Direct Connect 便利〜みたいな事が話されていた。

(High Availability IAM Design Patterns - AWS Security Blog というのが気になったので後で読む)

(VPC 間接続、公式であると便利そうだなぁ…)

"マルチキャストがないならユニキャストすればいいじゃない/ほしいプロトコルはカプセルすればいいじゃない"

前半は SA 安川さんからのユニキャストでマルチキャストっぽい動作をさせてみました、というのと、後半は荒木さんからネットワークのトンネルやカプセル技術の一般的な話をしつつ、AWS で 6rd つかってみたよ的な話。

前半のマルチキャストについては、multicast packet を拾ったら、指定された MAC アドレス分宛先 MAC を書き換えたパケットを複製してついでに送信してやれば動くよね (動いた) という話。まず PoC として packetfu.gem を利用したコード が上がって、でもこれはこのプロセスが死んだらマルチキャスト動かなくて崩落するよねー、という事で Linux kernel の tc (traffic control) を利用したバージョン も紹介されてた。原理を見るのは ruby の PoC の方がわかりやすいかな。

実際に UPnP とか keepalived で使えるデモをしていた。UPnP の方は XBMC かな? をコントロールしようとしていて、XBMC の画面を手元に持ってくるのに (言及してなかったけど) App Stream を使っているっぽくて「おおーー動いてるし割と綺麗にかつ止まらずに映像降ってくる!」と感動してた。

後半は一般的な話で、TUN/TAP とか IP on IP とか IPsec とかの説明など。AWS で 6rd 使ってみたみたいな事も言及してた。HE が提供する 6rd endpoint でやってみたけど東京←→バージニアのレイテンシなら(幸いにして he の endpoint が両方ともその近辺にあるので)トンネル通さない場合と対して変わらなかった的な話も。ただ IPv6 をそのままインスタンスが受けるので iptables とかしないとヤバいよ〜みたいな話もあった。

"これで最強のAWSに"

Miles の前であえて AWS のダメなところを突っ込んでいくというもの。予想してたよりずっと濃くて一番面白かった。

DeNA はオンプレで動いてるサーバと AWS 上のサーバで社内のユーティリティコマンドを共通で使えるようにしているみたいだった。効率化などなど含めてハイブリッドに使う場合、ある程度操作を統一しとくのは重要そうで便利な気がした。

リクルートの 70 個くらいの VPC 管理 + さらに会計都合などなどによる AWS アカウント分断、すごいつらそうだった。ルーティング考えるだけで絶対に頭が溶ける。やばい。ネットワーク構成図みたいなのうつしてたけど複雑すぎヤバいみたいな感じ。

DeNA のわかものやスケールアウトのはるかさんはサポートサービスや management console にまで突っ込んでいた。 はるかさんの提案してた management console に対する操作を awscli 等のコマンドとして記録できるようにすると便利なんじゃないかみたいなのは Miles さんがすごい食い付いていたのと、聞いていて便利そう欲しい〜ってなった。

(cli の操作の便利なところは便利なんだけど、SG の指定とか subnet の指定とか AMI の指定がつらいからね…)

また一個収穫としては Eucalyptus は AWS とライセンスむずんだりしてある程度 API の互換性をとっているから、AWS 上で大きいインスタンスの上で Eucalyptus を動かせば API のテストとかに使えるんじゃないかな、という Miles さんからの情報。

あとは最後、観客からもなにかあればって聞いた時に何もなかったからって @kenjiskywalker おじさんが出てきて Cacti 捨てて全部 Zabbix でやればいいのにみたいな事をリクルートの宮崎さんにツッコんでたのは面白かった。出てくるところまでは予想の範疇でした。

まとめ

AWS おもしろい。プログラマブル度が高いのがやっぱ良いなぁ。

Published at 2014-03-15 23:00:00 +0900

2014-03-14: AWS Game Day Japan 2014 Spring

AWS Game Day Japan 2014 Spring に参加してきた。

問題は 2013 開催のやつと一緒。Image processor とか SQS とか使うやつでした。

チームメイトは @suzryo さんととささん。 (ref: suzryoさんのレポート )

あらかじめ断わっておくと強く批判しているつもりも dis っているつもりもないけれど、運営側が対戦相手のマッチングでミスをして、こっちが攻撃しているアカウントは他のチームも同時に攻撃していて、一方自分のチームのアカウントは攻撃を受けていないという状態になった。

つまり攻撃フェーズ中は意図しない変更がされてこちら側の攻撃が無効化されたりするし、自分のチームのアカウントは攻撃されちゃいないから復旧フェーズとは何だという状態でした。運営側を強く攻められないし攻めるつもりもないけど、正直に言うとわりと残念でテンションが下がった。

復旧フェーズで何も力試せなかったというのもそうだけれど、攻撃フェーズもこっちの意図した攻撃になってないとかそういうよくわからん感じになって… 途中で同じチームを攻撃しているチームの影響で作業止まったりしたし… (それに関しては運営のミスなので同じチームを攻撃していた他チームに対しては全く何も思ってないです。)

やった防御

あまり防御策は思いつかなかった。us-east-1 への構築を主に自分が担当して、suzryo さんは別リージョンでのバックアップみたいな事をやってくれていた。

防御としてやってみたのは、コマンドインジェクションで ec2-user の権限が奪えてしまうので、まず ssh アクセスはされないように crontab で毎分 authorize_keys を書き戻すという処理を入れてみたりしていた。

やった・やろうとした攻撃

  • SQS input queue の visibility timeout = 0 sec や delay timeout を最大にしたり、dead letter にすぐ飛ばしてしまうように
  • S3 の requester pay を有効化
  • Auto Scaling Policy で存在した scale out ポリシの cloudwatch alarm を若干いじっておく (不等号入れ替え、statistics を min にして分かりにくく無意味なものに)。ついでに cooldown 1800 sec とか。
  • ↑のカモフラージュ用に常に ALARM 状態、remove 1 instance するような Auto Scaling Policy を入れる
  • S3 bucket policy で getobject を deny
  • 後はやろうとしたけど出来なかった攻撃:
    • EC2 instance に結びつける IAM role でワーカーインスタンスの権限管理をしていたため、Auto Scaling 用の Launch Configuration では IAM role を指定する。ただし、攻撃用で利用する Power User には IAM に関する権限が与えられていないため、IAM role を指定して Launch Configuration を作る事ができなかった... (もしかして API 経由なら出来たのかなぁ)
    • Launch Configuration つくりなおせれば UserData で細工したりいろいろ面白い事ができたなあ…
  • これは時間がないのと他攻撃チームとの作業衝突でうまくできなかったのだけれど:
    • CLI tools 用の instance があったので、同じ user data で key pair だけ入れ替えて作成しなおし。そこに iptables を突っ込み、VPC Route Table をいじって S3/SQS へのリクエストが稀にうまくいかないみたいな状態にしようとしていた

2 チームがばらばらで同じチームに攻撃しているもんだから、途中でよくわからんインスタンスがでてきたり、SG いじられて疎通しなくなったり、default route 消されて疎通しなくなったり、auto scaling policy ががらっと入れ替わったりしてそれはそれでカオスで面白かった。

復旧

攻撃されてないので出来ず。

まとめ

Miles さんの "Hack Day must be fun, nothing to scare" っていう言葉はよかった。あと Miles さん「チョ〜スゴイ (日本語)」とか言ってたりおもしろかった。まあでも "(my) Nihongo is terrible..." とかいって基本英語だったけど。

途中からマッチングミスという事実が発覚してテンション落としつつもいろいろ弄れて楽しかった。次回開催で同様の事故がおこらない事を祈ります… 次回は復旧フェーズもやりたい…

あと、要望としてはマニュアル読んでみんなで同じもの構築とか無駄なので、構築は CloudFormation でサクッとやって防御に 100% 時間を振りたい感じかなー。

運営の皆様方お疲れさまでした。

Published at 2014-03-14 23:00:00 +0900

2014-02-28: Ruby 2.1.1 で Hash#reject のデグレ

Ruby 2.1.0 まで、Hash を継承したクラスの reject メソッドの挙動は継承クラスのオブジェクトを返す挙動をしてました。 しかし、 Ruby 2.1.1 で意図せずその挙動が変更され、必ず Hash クラスのオブジェクトが返されるようになりました。

class SubHash < Hash; end
p SubHash.new.reject{}.class #=> 2.1.0: SubHash 2.1.1: Hash
p Hash.new.reject{}.class #=> 2.1.0: Hash 2.1.1: Hash

(厳密には ivar 等その他の属性もコピーされなくなっています。 また、Ruby 2.1 からはバージョニングポリシーの変更により、2.0.0 までのパッチリリースにあたるリリース時で TEENY が増えます。詳細は今月の WEB+DB で!)

この挙動変更で具体的に影響を受けるのは、Rails の HashWithIndifferentAccess, OrderedHash です。壊れます (reject メソッドが必ず Hash オブジェクトを返してくるようになった)。 https://github.com/rails/rails/issues/14188

何故起きたか

そもそもこの挙動の変更は Ruby 2.1.1 では意図的ではないと思っています。事故です…。 これは bugs.r-l.o#9223 で昨年末 (2.1 リリース前に) 議論されていた変更ですが、この時期からの仕様変更はできないと Ruby 2.1.0 では見送られています。 そのため Ruby 2.1.0 では deprecated warning に留められました。 (それも --verbose, -v がついてないと表示されない物って…というのは今は置いておく。)

この変更の周辺コミットは https://gist.github.com/sorah/9265008 の通りです。詳細は←の gist を読んでください。 Ruby 2.1.0 の段階で、#ifdef により定数で警告+従来の挙動、あるいは警告せず新しい挙動 (必ず Hash オブジェクトを返す) という 2つ の挙動を切り替えられるようになっていました。尚、0 で新挙動、1 で従来の挙動になっています。

Ruby 2.1.0 リリースブランチが切られた後、trunk では r44358 で定数名が変更され、2.1.1 ブランチにバックポートされています。が、このコミットで一箇所 #ifdef 側の名前に変更漏れがあり、r44370 で修正されています。この r44370 がバックポートされず、必ず #ifdef が 0 と評価されて 2.1.1 では新挙動になってしまったという訳です。

事故ですね。

つきましては、r44370 をバックポートした Ruby 2.1.1p77 をビルドするか (たぶん大丈夫)、HashWithIndifferentAccess, OrderedHash にモンキーパッチで対処 する事をオススメします。

尚 r44370 のバックポートはされたので、2.1.2 では元の挙動に戻るでしょう。 https://bugs.ruby-lang.org/issues/9576

しかし、 2.2.0 では 2.1.1、つまり Hash クラスのオブジェクトが帰ってくる挙動に変更される ので、将来の事を考えたら 2.1.0 以前の挙動を期待するのはやめたほうが無難です。

Published at 2014-02-28 21:00:00 +0900