[Chef]猿でもわかるExecute,Script,Bashリソースの違い
結論
シェルスクリプトをbashで書くのであれば、下記はどれも変わらない。- "execute" リソースで "command"
- "script" リソースで "command"
- "script" リソースで "code"
- "bash" リソースで "command"
- "bash "リソースで "code"
解説
ソースコードを見てみるとわりと一目瞭然
公式マニュアルを見ても全然わからないのですが、ソースコードを見れば意外と簡単に仕組みがわかります。https://github.com/opscode/chef/blob/master/lib/chef/resource/bash.rb
ちなみに私はrbenv経由でgem install chefしたので、下記のような場所にソースコードがありました。
~/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/chef-11.8.2/lib/chef/resource/execute.rb
リソースの実体は「クラス」
まず、Chefのリソースというのは実体はrubyのクラスです。それぞれ下記のようなクラスとして定義されています。
- Chef::Resource::Execute
- Chef::Resource::Script
- Chef::Resource::Bash
- Chef::Resource::Ruby
- Chef::Resource::Perl
継承関係
クラスの継承関係はこのようになっています。 親 子 孫
Chef::Resource::Execute - Chef::Resource::Script - Chef::Resource::Bash
- Chef::Resource::Ruby
- Chef::Resource::Perl
Executeの子クラスがScript, Scriptの子クラスがBash/Ruby/Perlです。
クラスのコードを読んでみる
実はたったこれだけ。Chef::Resource::Bash
class Chef
class Resource
class Bash < Chef::Resource::Script
def initialize(name, run_context=nil)
super
@resource_name = :bash
@interpreter = "bash"
end
end
end
end
Chef::Resource::Perl
class Chef
class Resource
class Perl < Chef::Resource::Script
def initialize(name, run_context=nil)
super
@resource_name = :perl
@interpreter = "perl"
end
end
end
end
Chef::Resource::Ruby
class Chef
class Resource
class Ruby < Chef::Resource::Script
def initialize(name, run_context=nil)
super
@resource_name = :ruby
@interpreter = "ruby"
end
end
end
end
あっけにとられたのではないでしょうか?bash/ruby/perl リソースは、単にインタープリタの名前が違うだけなのです。
Chef::Resource::Script
今度は親クラスの方を見てみましょう。class Chef
class Resource
class Script < Chef::Resource::Execute
identity_attr :command
def initialize(name, run_context=nil)
super
@resource_name = :script
@command = name
@code = nil
@interpreter = nil
@flags = nil
end
def code(arg=nil)
set_or_return(
:code,
arg,
:kind_of => [ String ]
)
end
def interpreter(arg=nil)
set_or_return(
:interpreter,
arg,
:kind_of => [ String ]
)
end
def flags(arg=nil)
set_or_return(
:flags,
arg,
:kind_of => [ String ]
)
end
end
end
end
Chef::Resource::Executeにちょろっと毛が生えた程度のものですね。最大の違いは、
Chef::Resource::Executeには"code"属性がない
Chef::Resource::Scriptには"code"属性がある
ということです。
codeとcommandの違い
def command(arg=nil)
set_or_return(
:command,
arg,
:kind_of => [ String, Array ]
)
end
def code(arg=nil)
set_or_return(
:code,
arg,
:kind_of => [ String ]
)
end
commandは複数渡せる、codeは複数渡せない、くらいの違いでしょうか。
まとめ
Chefを使っていてもやもやしたらソースコードを見てみましょう。意外な発見があります。