他の Cookbook の Attribute を部分的に読み込ませたい (けど無理っぽい)

環境ごとに Attribute を定義したいのだけれども、Environment はバージョン管理できないっぽい*1し、Attribute を定義する Cookbook を環境の数だけ作るのも DRY ではないので、ひとつの Recipe で各環境用の Attribute File を用意し、他の Cookbook から参照させることはできないかなーと思ったのでいろいろ試してみた。


イメージ的にはこんな感じ。

本番環境用: attributes/production.rb
開発環境用: attributes/develop.rb


結論から言うと、これを実現するのはかなり難しいことが分かった。


まず、他の Receipe の Attribute を参照する方法として、

  1. metadata.rb の depends に追加する
  2. include_attribute を使用する
  3. run_list に追加する

の 3 通りの方法がある。


そして、Chef の仕様として、attributes 配下のすべての Attribute File が読み込まれるとのこと。

An attribute file is located in the attributes/ sub-directory for a cookbook. When a cookbook is run against a node, the attributes contained in all attribute files are evaluated in the context of the node object. Node methods (when present) are used to set attribute values on a node. For example, the apache2 cookbook contains an attribute file called default.rb, which contains the following attributes:

About Attribute Files ― Chef Docs


これらを踏まえて Attribute File の読み込みの有無を確認してみた結果が以下の通り。
(各 Cookbook に attirbutes/default.rb と attributes/default2.rb を用意して確認してみた)

default.rb default2.rb
0. 自 Cookbook の Attribute
1. medadata.rb に追加
2. include_attribute を使用*2
3. run_list に追加

○…読み込まれる ☓…読み込まれない


ご覧のようにほぼすべての場合で、全部の Attribute File が読み込まれた。
唯一、include_attribute を使用した場合だけ、特定の Attribute File を読みこませることができたが、include_attribute は Attribute File 内でしか使用できないため、include_attribute 先を切り替えるための Attribute をまた指定しないといけないという卵と鶏問題が発生する。



というわけで諦めて環境ごとの Cookbook を用意することにしたのであった。

*1:Chef Server での話。ただ、試したわけではないので、もしかしたらできるのかも

*2:include_attribute "other_cookbook::default2"