chefでのインストールの目的別逆引き

なんかパッケージ入れたいとかソースから入れたいとかの目的別の逆引きしやすいように。
自分で書く場合の話であって、サードパーティのcookbook使う話は書いてないです。

主にcentosしか使ってないですのでそのつもりでどうぞ。

主に使うリソースはpackageとかbashとかです。リソースのマニュアルは以下などを。
https://docs.chef.io/chef/resources.html
http://matome.naver.jp/odai/2136687268845478601

##### **・yumで入れたい**

packageリソース使えばいいです。

```
package "ntp" do
  action [ :install, :upgrade ]
end
```

複数入れたい場合はrubyのeachメソッドを用います。

```
%W{ openssl openssl-devel }.each do |pkg|
  package "#{pkg}" do
    action [ :install, :upgrade ]
  end
end
```

rubyのeachメソッドの説明をすると、
%W{}の中にスペース区切りで対象パッケージを入れます。
.eachの手前に配列変数をおいて食わせるかんじ。
だからまあ、.eachの手前に`node['base_setting']['ssl_packages']`とかのアトリビュートそのまま書いて呼び出しても動きます。
で、doとendの中身が一つのブロックで、
`|pkg|`に配列が入れられて、`#{pkg}`で変数を呼びだしてつかってるかんじです。
上記の例ではアクションを配列で複数指定しているので、入ってなければinstallされ古ければupgradeされます。

rubyのメソッドを簡単に解説してる以下あたりが分かりやすそうです。
http://dev.classmethod.jp/server-side/chef-vagrant-ruby/

##### **・独自yumリポジトリにパッケージを置いてるのを配って入れたい**

opstionsでbaseとかupdatesとかepel等から入らないように調整するなどができます。

```
package "bash" do
  action :upgrade
  options "--disablerepo=base,updates"
end
```

独自リポジトリからカスタマイズビルドしたパッケージを入れたい場合にこのようにします。


##### **・リモートからダウンロードしてからパッケージを明示してyumじゃなくてrpmでいれたい**

```
version = data_bag_item('pkg_versions','innotop')['version']
innotop="innotop-#{version}.noarch.rpm"
baseurl = data_bag_item('pkg_versions','innotop')['url']
remote_file "/usr/local/src/#{innotop}" do
  not_if "ls /usr/local/src/#{innotop}"
  source "#{baseurl}/#{innotop}"
end

package "innotop" do
  action :install
  source "/usr/local/src/#{innotop}"
  provider Chef::Provider::Package::Rpm
  not_if 'rpm -qa|grep innotop'
end
```

##### **・バージョンを指定したい、オプションでリポジトリを指定したり除外したい**
`rpm -qi`でパッケージ入ってる情報を調べます（すでに入ってるところで）

```
$ rpm -qi jdk
Name        : jdk                          Relocations: /usr/java 
Version     : 1.7.0_55                          Vendor: Oracle Corporation
Release     : fcs                           Build Date: 2014年03月18日 03時07分21秒
Install Date: 2014年05月02日 05時39分59秒      Build Host: sc11137388.us.oracle.com
Group       : Development/Tools             Source RPM: jdk-1.7.0_55-fcs.src.rpm
Size        : 202038066                        License: http://java.com/license
Signature   : (none)
Packager    : Java Software <jre-comments@java.sun.com>
URL         : URL_REF
Summary     : Java Platform Standard Edition Development Kit
Description :
～略～
```

上記のうちNameがパッケージ名、Versionがバージョンに相当する情報です。
もし、既に入ってるところはない入れて試せない場合には、yum install を打って
実際には入れずにパッケージとバージョンを以下のように確かめます。

```
# yum install openssl
===============================================================================================
 パッケージ              アーキテクチャ   バージョン                   リポジトリー       容量
===============================================================================================
更新:
 openssl                 x86_64           1.0.1e-30.el6.11             updates           1.5 M
依存性関連での更新をします。:
 openssl-devel           x86_64           1.0.1e-30.el6.11             updates           1.2 M

トランザクションの要約
===============================================================================================
アップグレード       2 パッケージ

総ダウンロード容量: 2.7 M
これでいいですか? [y/N]n
```

そもそもパッケージ名がわからなくてどこにも入ってないなら`yum search openssl`、
どっかに入ってるコマンドのパッケージが知りたいなら`rpm -qf /path_to_command`するとよいです。
バージョン指定とオプション指定は以下のようにします。

```
jdk_version = node['cassandra']['jdk_version']

package 'jdk' do
  version "#{jdk_version}"
  options "--disablerepo=epel,base,updates"
  action :install
end
```

##### **・ダウンロードして実行権限つけるだけパターン**

```
bash "install jq" do
  not_if "ls /usr/bin/jq"
  code <<-EOC
  curl -o /usr/bin/jq http://stedolan.github.io/jq/download/linux64/jq
  chmod +x /usr/bin/jq
  EOC
end
```

##### **・tarアーカイブから展開して入れたい**

```
cookbook_file "/usr/local/src/#{tarfile}" do
  not_if "ls /usr/local/src/#{tarfile}"
  source "usr/local/src/#{tarfile}"
end

bash "tar-open" do
  not_if "ls /usr/local/src/#{server}"
  code <<-EOC
    cd /usr/local/src
    wget #{tarurl} -O #{tarfile}
    tar xf #{tarfile}
  EOC
end

package "MySQL-client" do
  action :install
  source "/usr/local/src/#{client}"
  provider Chef::Provider::Package::Rpm
  not_if 'rpm -qa|grep MySQL-client'
end
```

※tarアーカイブをcookbook内でない別の場所から持ってきたいならremote_fileリソースを使います。


##### **・make installしたい**

事前に開発ツール(yum groupinstall 'Development tools')入ってないとたぶん入らないです

```
bash "bash-install-git" do
  not_if "ls -d /usr/local/src/git-1.9.0"
  code <<-EOC
    wget https://git-core.googlecode.com/files/git-1.9.0.tar.gz -P /usr/local/src
    cd /usr/local/src/
    tar zxf git-1.9.0.tar.gz
    cd /usr/local/src/git-1.9.0
    ./configure --prefix=/usr/local/git
    make all
    make install
    ln -sf /usr/local/git/bin/git* /usr/local/bin/
  EOC
end

```

※bashやexecuteリソース内で呼び出した環境変数はリソース内に閉じて引き継ぐことはできません。
一回一回指定する必要があります。（global変数ではなくlocal変数ってかんじです。）
http://qiita.com/taiaraky/items/a3f747fc6528ed6d874e

##### **・gemを入れたい**

こんなかんじ、`not_if`は時間がかかるから入れてるだけで要らないかもしれない

```
passenger_version = node['apache']['passenger_version']
gem_package 'passenger' do
  not_if "/usr/local/rbenv/shims/gem list|grep passenger|grep #{passenger_version}"
  version "#{passenger_version}"
  gem_binary '/usr/local/rbenv/shims/gem'
  options "--no-rdoc --no-ri"
end
```

gemでいれるのはmakeとかしてるのでめちゃ時間かかる。出来ればパッケージ化するのが無難。
開発ツール(yum groupinstall 'Development tools')入ってないとたぶん入らないと思う

##### **・gitから入れたい**

gitで取得したruby-buildのインストーラを/tmpに置いてbashでインストーラを起動

```
git "/tmp/ruby-build" do
user node['user']['name']
repository "git://github.com/sstephenson/ruby-build.git"
reference "master"
action :checkout
end

bash "install-rubybuild" do
not_if 'which ruby-build'
code <<-EOC
cd /tmp/ruby-build
./install.sh
EOC
end
```

##### **・入れた直後に環境変数を途中で読み込んでからなんか入れたい**

実行順序の話があります。
http://memo-off.blogspot.jp/2013/06/chefrecipe.html

1.compiling
2.converging
最後にnotifiesに指定されたリソースが実行されるというような順序の実行のされかたをします。
rubyのメソッドは1のcompilingの段階で全部行われてしまうしohaiでとれる値も同じことです。
それゆえ途中で変わった値は2のconvergingの段階で使われないです。
したがってohaiをreloadしたりruby_block内で変数を指定しなおすようなことが必要になるケースがあります。
（notifiesに:immediatelyを指定すると2の書いた準に即時実行にはなります。）

要は、rubyのメソッドはレシピ適用の前に実行されるため、
レシピ適用処理結果を基にした処理をしたい場合はruby_block内に書かないとダメって話等。

```
ruby_block "initialize_rbenv" do
  block do
    ENV['RBENV_ROOT'] = node[:rbenv][:root]
    ENV['PATH'] = "#{node[:rbenv][:root]}/bin:#{node[:rbenv][:root]}/shims:#{node[:ruby_build][:bin_path]}:#{ENV['PATH']}"
  end
  action :run
end

rbenv_ruby_version = node[:rbenv][:ruby_version]
bash "set_global_version" do
  not_if "/usr/local/rbenv/shims/ruby -v|grep #{rbenv_ruby_version}"
  code <<-EOC
    rbenv rehash
    rbenv global "#{rbenv_ruby_version}"
  EOC
end
```

もし、ruby_blockの中でresouce呼びたい場合メソッドを生やす必要があるので以下リンクを参照ください。
http://qiita.com/sonots/items/8ac33ce011bbfb210edd

##### **・直後にただちにサービスを起動したい**

対象リソースの中に以下のようにnotifiesを書く。

```
  notifies :reload, "ohai[reload]", :immediately
  notifies :restart, "service[rsyslog]", :immediately
```

:immediatelyを指定しないとデフォルトでは全てのレシピが適用されたあとにnotifiesに指定した処理が実行される
主に、設定ファイルをtemplateリソースで配って再読み込みしたい時や、
インストール直後に起動したい時なんかにserviceリソースを呼ぶ感じ。

クラスタ組んでて更新でサービスが自動で再起動されてしまうと主系が落ちて待機系にリソースが移ってしまうようなケースではnotifiesかかずに手動がよさそうです。

##### **・設定ファイルやパッケージファイルなどを配りたい**

そのまま配布したいなら前述のcookbook_fileを使います
変数を埋め込んでファイルを配りたい場合はtemplateリソースを使います。

以下はdata_bagsからロードして変数に埋め込んだデータをtemplateリソースのvariablesで差し替えてる例。

```
slappasswd = Chef::EncryptedDataBagItem.load("ldap","slappasswd")
ldappw2 = slappasswd["bindpw"]

template '/etc/phpldapadmin/config.php' do
  source   'config.php.erb'
  owner    'root'
  group    'apache'
  mode     0640
  variables ({
	:bindpw => ldappw2
  })
end
```

ちなみにレシピ上でvariablesで差し替える場合はsourceに指定されてるファイルに以下のように@つけて変数埋め込んでおきます。
`$servers->setValue('login','bind_pass','<%= @bindpw %>');`

どっかのattributeから差し替える場合は、以下のような感じに<%= %>内にattributeを埋め込んでおきます。
`<%= node['ldap']['basedndc1'] %>`

##### **・attributeの使い分け等、データをどこから持ってくるかの話**

そのリポジトリで共通の一意なデータと暗号化したいデータ、たとえばユーザデータや証明書なんかはdata_bagsで管理するといい。
環境毎に異なる変数はenvironmentsで、webやdb等の役割毎に異なる変数はrolesで、
node毎に異なる変数はnodesで管理するといい。デフォルト値があって複数のenvironmentやroleで共通であって
cookbookに含まれてしまっても問題のないとくに固有じゃないパラメータとかであれば、cookbooks/attributes/default.rbに書いとくといい。
全部jsonで書ける。jsonデータのシンタックスチェックにはjsonlintが便利である。
あとはホスト名とかIPとかcpuコア数とかメモリ搭載量とかohaiというchef同梱の仕組みでとれるホストデータを埋め込むことが可能。

ohaiのデータを呼び出したいならtemplateファイル内で
`<%= node['ipaddress'] %>`
とかするだけでOKでレシピや他のattribute書くとこになんかかいたりしなくても大丈夫。

cookbook内のattributes/default.rbとかに書くなら、
`default['apache']['version'] = '2.xxx'`
とか書いたりする

配列もいけます。

```
default['fluentd']['plugins'] = %w(
  fluent-plugin-file-alternative
  fluent-plugin-forest
  fluent-plugin-rewrite-tag-filter
  fluent-plugin-tail-ex
  fluent-mixin-config-placeholders
  fluent-plugin-parser
  fluent-plugin-record-reformer
  fluent-plugin-statsd
  fluent-plugin-datacounter
  fluent-plugin-mackerel
  statsd-ruby
  jsonpath
)
```

environments、roles、nodesの下はjson置く感じで、
以下のような感じに。"default_attributes"と"override_attributes"があって優先順位があり
同じ値は同じとこに書くと配列ならマージされたりする。
http://dev.classmethod.jp/server-side/chef/attribute-overrides-pattern/

```
"base_setting": {
                "swappiness": "30",
                "tcp_tw_reuse": "0",
                "tcp_tw_recycle": "0",
                "tcp_fin_timeout": "10",
                "tcp_max_syn_backlog": "8192",
                "somaxconn": "8192",
                "ntp_role": "server",
                "logrotate_types": ["ldap"],
                "rsyslog_type": "ldap"
        },
```

配列なら[]で囲んでカンマ区切りで書く。

```
"nic_devices":[
      "eth0","eth1"
    ],
```

data_bagsはディレクトリ一個しか掘れないので注意。
ディレクトリがバッグというか入れ物にあたる。
暗号化したいデータとかはこのへんに入れます。くわしいことは以下URLらへんで。
http://devlab.isao.co.jp/data_bags_exsample/
http://qiita.com/smallpalace/items/2ada68c2dbbc9065dcc1

とりあえずこのへんで。[Ansible版はこちら](https://qiita.com/smallpalace/private/113c2a35c7e550bb9045)。