概要
cookbookのversionを使って、安全に他のcookbookを使ったり、他のcookbookに影響を及ぼさずにcookbookに修正を入れることができるようにします。
また、cookbookのversioning policyについても紹介します。
cookbookの変更と後方互換性
複数のcookbookを組み合わせて一つのcookbookを書いていると、ある日突然、使用しているcookbookに仕様変更が入り、
作っているcookbookに動かなくなったり意図しない動作をするようになってしまうことがあります。
逆も同じで、cookbookに仕様変更を入れてしまうと、それを使っているcookbook全てに修正を入れなくてはいけなくなります。
つまり、cookbookに後方互換性の無い修正が入り、その影響を未然に防ぐことができなかったということです。
recipeを使うのに必須だったattributeの名前が変わったり、recipe名が変わったり、librariesで提供されている関数名が変わったり。。。
使っているcookbookは全て自社製で、変更は全て把握しているので互換性のない変更が入るときは全cookbookをチェックしているぜ!
というのであれば問題無いですが。OSSのcookbookを使っていたり、社内の別のチームが作ったcookbookを使っていたりすると、すぐこの問題にぶち当たります。てめえふざけんなよ、予告なしにこんなクソ変更入れやがって!
こういった問題をcookbookのversionを使って解決します。
cookbookのversion
cookbookにはversioningの仕組みがあります。
metadata.rbに
version '0.0.1'
のように書くことで、cookbookにversionをつけることができます。
また、他のcookbookを使うときにmetadata.rbに
depends 'other-cookbook'
と書いていると思いますが、下のように書くことで他のcookbookのversionを指定することができます。
depends 'other-cookbook', '~> 0.1.2'
上の例では、"'other-cookbook'というcookbookのバージョン0.1.2以上0.2.0未満"を指定しています。
Gemfileを使ったことがある人はわかると思いますが、gemのversionの指定の仕方と大体同じです。
詳しくはこちら。
http://docs.getchef.com/essentials_cookbook_versions.html
metadata.rbのdependsに使うcookbook versionの条件を指定しておくと、chef-clientやberks installなどを使った時に
このversion条件を満たすversionのcookbookをダウンロードしてくるようになります。
こうすることで、cookbookが突然version upしてもその変更を受けないようにすることができます。
cookbookのversioning policy
これで万事解決かというとそうではありません。
当初の問題は、後方互換性の無い変更が入ると困るのであって、裏を返せば後方互換性の無い変更が入るまでは別にどうでもいいです。
それに、依存するcookbookのversion up毎に後方互換性があるか無いかチェックするのは面倒臭すぎます。
そこで、cookbookのversionの付け方のガイドラインを決め、version番号から後方互換性のある変更なのか無い変更なのかを見分けられるようにします。
Cookbook Versioning Policy
http://chef-community.github.io/cvp/
上のページでは、cookbookのversionにSemantic Versioningの考え方を導入しています。
cookbook versionの各桁をそれぞれmajor, minor, patch versionとし、
recipeやattribute、librariesをAPIに見立て、その変更内容によってversionのどの桁を上げるかを決定します。
- 後方互換性の無い変更が入る時はmajor番号を上げる
- 例: recipe名の変更、必須なattributeの名前の変更、recipe/attributeの削除、libraries関数のシグニチャの変更
- 後方互換性のある機能追加が入る場合はminor番号を上げる
- 例: recipeの追加、libraries関数の追加、
- 後方互換性のあるバグ修正が入る場合はpatch番号を上げる
詳細な内容は上のページを見てください。
このポリシーに従っているcookbookを使うときは、
depends 'hoge', '~> 1.2'
のように指定しておくと、
バグ修正と機能追加は自動で取り込むが、後方互換性の無い変更は(metadata.rbを更新しない限り)取り込まないようにできます。
このポリシーをcookbookを書く人全員で共有しておけば、後方互換性の無い変更をしても他チームに影響を及ぼさずに済むし、
他チームが後方互換性の無い変更をしてきても、きちんと事前にテストしてからcookbookを更新することができるようになります。
CHANGELOGのすゝめ
cookbookの分散開発で起きそうな問題を、cookbookのversionを使うことで解決を図りましたが、もう一点
cookbookに変更を入れるときは、CHANGELOGを書いておくことをオススメします。
cookbookは普通のプログラミング言語のAPIと違い、シグニチャがわかりづらいです。
recipeの書き方が悪いと、どのようなattributeが必須なのかがすぐにわかりません。cookbook中をくまなく調べないとわからないこともあります。
なるべくシンプルにrecipeを構成するのも重要ですが、ドキュメント(README.md)を詳細に書くのも効果的です。
(recipeやresourceの中でattributeをassertしたりするとより効果的です。)
これはcookbookに変更が入った時も同様です。どのようにシグニチャが変わったのか、後方互換性はあるのかを
cookbookの変更の度にCHANGELOGに書いておくと、cookbookを使っている人たちが変更に追従しやすくなります。
CHANGELOGの書き方は、各version毎に
- Breaking changes
- Enhancements
- Bugfix
のような変更の種類毎に分けて書くとよいと思います。
まとめ
- cookbookに後方互換性の無い変更が入ると辛い
- cookbookのversionを付けよう
- 他のcookbookを使うときはversionを指定しよう
- 後方互換性に着目してcookbookのversioningをしよう
- READMEやCHANGELOGを書こう