2014年4月16日水曜日

Ohai 7でプラグインの仕様が変わった

先日リリースされたChef Client 11.12.0から密かに同梱されているOhaiが7.0系に差し替わったのだが、これが結構な仕様変更を含んでいて、Ohai Pluginなどを自作して使ってる人は気をつけないとハマる模様。

プラグインの仕様変更

いちおう互換性が保持されるようになっていてv6のプラグインもそのまま動くのだけれど、実行するとこんな感じのWARNINGが出る。

[2014-04-16T15:50:02+09:00] WARN: [DEPRECATION] Plugin at /tmp/example/plugins/foo.rb is a version 6 plugin. Version 6 plugins will not be supported in future releases of Ohai. Please upgrade your plugin to version 7 plugin syntax. For more information visit here: docs.opscode.com/ohai_custom.html

細かい点で色々仕様が変わってはいるのだけど、一番大きいのはプラグインの書き方が変わったことと、プラグイン名を指定していた部分がアトリビュート名を指定するように変わったこと。

新しいプラグインの書き方

従来のプラグインはこんな感じだった。

provides "foo"

require_plugin "baz"

foo Mash.new
foo[:data1] = "foo1"
foo[:data2] = "foo2"

Ohai 7からはこんな感じになる。

Ohai.plugin(:Foo) do
  provides "foo"
  depends  "bar/baz"

  collect_data do
    foo Mash.new
    foo[:data1] = "foo1"
    foo[:data2] = "foo2"
  end

  collect_data(:windows) do
    foo Mash.new
    foo[:data1] = "win_foo1"
    foo[:data2] = "win_foo2"
  end
end

v6ではベタ書きスクリプトっぽかったのが、v7ではオブジェクトっぽく内容を定義する形になった。
上の例には書いていないが、普通にメソッドを書いたり共通処理用のクラスを別途まとめたりもできるようになっているので、複雑な処理が必要な場合にだいぶ書きやすくなったと思う。

collect_dataがデータを収集する部分なんだけど、引数でプラットフォーム毎の内容に分けて書くことができるようになった。
該当するプラットフォームのcollect_dataがあるとそちらが呼ばれて、なければ:defaultが指定されているcollect_dataが呼ばれる(指定しない場合は:default)。

また、v6ではrequire_pluginで依存するプラグインを指定していたが、v7からはdependsで依存するアトリビュートを指定するようになった。
利用する側はプラグイン名を知る必要はなく、「どのアトリビュートが使いたい」というのを指定すれば、Ohaiの本体が自動的にそのアトリビュートを提供するプラグインを読み込んでくれる。ここ割りと重要。

Rubyプログラムから使用する場合の注意点

プラグインの仕様が変わったことで利用の仕方も少し変わった。

普通に全プラグインを使う場合は従来と同じでOhai::System#all_pluginsを呼び出せば全部実行してくれる。

require "ohai"

ohai = Ohai::System.new
ohai.all_plugins

p ohai.data

自作プラグインなど特定のプラグインだけを実行したい場合は少し変わったのだけど、これがv6用プラグインとv7用プラグインで若干違っていたりしてカオスな感じがする。

require_pluginを使うパターン

v6用とv7用が混在している場合はこのやり方しかないように思う。

require "ohai"

Ohai::Config[:plugin_path] << "/path/to/oreore/plugins"

ohai = Ohai::System.new
ohai.load_plugins
ohai.require_plugin("foo/bar")      # v7の場合はアトリビュート名
ohai.require_plugin("hoge_fuga")    # v6の場合はプラグイン名

p ohai.data

まずload_pluginsというのが事前に必要になった。これを呼ばないとプラグインがOhaiに認識されない。
ちなみにload_pluginsを呼んでもv6用プラグインは読み込まれない。なぜならv6用プラグインは「読み込まれる=実行される」なので、問答無用で実行されてしまうから。
ただしv6用のプラグインであることは認識される(ソースファイル内の文字列とかで判定してるんだろうか?)。

require_pluginにはv7用プラグインの場合はアトリビュート名を、v6用の場合はプラグイン名を指定する。
v7用プラグインはload_pluginsによってprovidesなどのメタ情報がロードされるので、それを使って解決しているのだろう。
v6は前述のとおり読み込んでしまったら実行されてしまうので、読み込んでない状態では中に書かれているprovidesとかも認識されない。よってプラグイン名を指定することになるようだ。
ちなみにv7用プラグインのプラグインを指定しても動かない。

このへんの仕組みはOhai::ProvidesMapとかOhai::Loaderがやってるようなので、興味のある人はソースを読んでみるといいかも。

all_pluginsに引数を渡すパターン

このやり方はv6用プラグインが混在している環境では使えない。
というのも、v6用プラグインは指定できず、無条件に実行されてしまうから(この挙動が仕様なのか現バージョンの不具合なのかは不明)。

require "ohai"

Ohai::Config[:plugin_path] << "/path/to/oreore/plugins"

ohai = Ohai::System.new
ohai.all_plugins([
  "foo/bar",
  "languages/ruby"
])

p ohai.data

all_pluginsの引数にアトリビュート名を指定すると、該当するアトリビュートを提供するプラグインのみが実行される。
ただし、(v6用の)プラグイン名は指定できない。そして指定してないにも関わらず、存在するv6プラグインは全て実行される。

ちなみにload_pluginsは不要。というかall_pluginsが内部で呼び出している。

0 件のコメント:

コメントを投稿