Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

Chef | resources | execute と script と bashの違いを知るためにオープンソースのコードリーディングをする

概要

execute と script と bashの違いを知るためにオープンソースのコードリーディングをする

詳細

execute と script と bashの違いを知るためにオープンソースのコードリーディングをする
※他の言語系リソースもbash resourceと同様です(Csh, Ruby, Python, Perl)

About Resource

Resourceの継承関係

Bash extends Script extends Execute の継承関係になっている

pry(main)> Chef::Resource::Bash.ancestors
=> [Chef::Resource::Bash,
 Chef::Resource::Script,
 Chef::Resource::Execute,
 : 略
 Kernel,
 BasicObject]

pry(main)> Chef::Resource::Script.ancestors
=> [Chef::Resource::Script,
 Chef::Resource::Execute,
 Chef::Resource,
 : 略
 Kernel,
 BasicObject]

pry(main)> Chef::Resource::Execute.ancestors
=> [Chef::Resource::Execute,
 Chef::Resource,
 : 略
 Kernel,
 BasicObject]
Bash(Csh, Ruby, Python, Perl) Resource実装の詳細

Scriptを継承して、interpreter属性にbashを設定しているだけ。

Script Resource実装の詳細

Executeを継承して、code・interpreter・flags属性と設定用のメソッドを追加しただけ。

About Provider

Providerの継承関係

リソース同様Script extends Execute の継承関係になっている

pry(main)> Chef::Provider::Script.ancestors
=> [Chef::Provider::Script,
 Chef::Provider::Execute,
 Chef::Mixin::ShellOut,
 Chef::Provider,
 : 略
 Kernel,
 BasicObject]

 pry(main)> Chef::Provider::Execute.ancestors
 => [Chef::Provider::Execute,
  Chef::Mixin::ShellOut,
  Chef::Provider,
  : 略
  Kernel,
  BasicObject]
Execute Provider実装の詳細

Mixlib::ShellOutのインスタンスを取得してrun_commandメソッドを実行している。
Mixlib::ShellOutについては以下。
https://github.com/opscode/mixlib-shellout/blob/master/lib/mixlib/shellout.rb

Mixlib::ShellOut内ではプラットフォームに応じて

'mixlib/shellout/windowsをrequire
ShellOut::WindowsかShellOut::Unixをinclude

を選ぶか

'mixlib/shellout/unix'をrequire
ShellOut::Unixをinclude

を選ぶか決めている。

ShellOut::Windows、ShellOut::Unixについては以下。

https://github.com/opscode/mixlib-shellout/blob/master/lib/mixlib/shellout/unix.rb
https://github.com/opscode/mixlib-shellout/blob/master/lib/mixlib/shellout/windows.rb

unixなら最終的にRubyのexec経由でコマンドを実行している。

command.kind_of?(Array) ? exec(*command) : exec(command)

をしている。

windowsなら最終的に

cmd /c "command"

をしている。

Script Provider実装の詳細

コマンドを一時ファイルに保存。
一時ファイルを利用するコマンドを設定。
その後はexecuteの処理をそのまま呼び出し。

コードリーディングの流れ

・それっぽいキーワードでgrepして該当処理を書いてありそうなコードを探し当てる
・chef配下のソースを確認する流れで、resourceとprovider配下のexecute.rb, script.rb, bash.rbなどのファイルを発見しソースを確認
・executeのソースの中でChef::Mixin::ShellOutの呼び出しを確認。該当コードを開く。
こちらもモジュール構成とディレクトリ構成がわかりやすくすぐコードを発見。
・Chef::Mixin::ShellOutからMixlib::ShellOutを呼んでいるが内部にソースが見当たらない。
ググったらGitHubを発見。
・Mixlib::ShellOutからMixlib::ShellOut::Unix,Mixlib::ShellOut::Windowsを呼び出していることを確認。
さらにGitHub内でそれらのコードを参照する。

今回コードリーディングした関連クラス群

chef/resource/execute.rb
chef/resource/script.rb
chef/resource/bash.rb
chef/provider/script.rb
chef/provider/execute.rb
chef/mixin/shell_out.rb
https://github.com/opscode/mixlib-shellout/blob/master/lib/mixlib/shellout.rb
https://github.com/opscode/mixlib-shellout/blob/master/lib/mixlib/shellout/unix.rb
https://github.com/opscode/mixlib-shellout/blob/master/lib/mixlib/shellout/windows.rb