[和訳] Chefによるテスト駆動インフラの概観 #getchef
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
本稿は Overview of Test Driven Infrastructure with Chef (2015/04/21) の和訳です。また、長文のため、独自に目次をつけました。
この記事はChefによるテスト駆動インフラに関するすべてです。現時点でのChef Cookbookのテストの概観となります。この記事ではChefDKに含まれるツールに焦点を当てています。その他のツールやプロジェクトは完全性と歴史的な理由から言及しています。この記事はChefによるテスト駆動インフラで現在使っている、またはかつて使っていた多くのコンポーネントやツールの一般的な概要を記しています。これについての完全な書籍としては、Stephen Nelson-Smithによる「Test Driven Infrastructure with Chef」を参照してください。トレーニングに関しては、learnchefのレポジトリを参照してください。この記事では各項目において何かと何故かを議論したいと思います。どのようにはありません。「どのように」が重要でないからというわけではありません。各ツールについて詳細な実装をここで書くのが大変だからです。この記事ではいくつかの理由で例を示します。個々のツールについて語る前に、Chefの開発におけるさまざまなフェイズが何であるか、テストの種類が何であるか、見ておきましょう。
■Chefによる開発フェイズ
ここでは「収束前」「収束」「収束後」という開発における3つのフェイズについて述べます。
●収束前
収束前とは、NodeがChefによって収束される前のフェイズで、NodeでのChefの実行が必要ないフェイズです。文法チェック、lintチェック、ユニットテストなどを収束前に行います。Travis CIと連携したGitHubレポジトリのように、CIでの自動テストはたいてい収束前テストを行います。
●収束
収束とは、Chefを実行してシステムをあるべき状態に「収束」させるフェイズです。Resourceの現在の状態をテストし、正しくなければ(Providerによって)修正します。
●収束後
収束後とは、NodeでChefの実行が終わった後のフェイズです。このフェイズにおけるテストは、Nodeがあるべき状態になっていることを検証します。あるポートが待ち受けているか、設定ファイルが正しい内容を含んでいるか、正しい設定でサービスが動作しているかといったチェックを含みます。
■テストの種類
さまざまな種類のテストについて詳細を見ていくのはこの記事の範囲を越えています。Chef Cookbookのテストに関係する、ユニットテストとインテグレーションテストという2つについての概要に留めたいと思います。テストの種類のさらなる調査については、宿題として残しておきます。始めるにあたってSeth Vargoによる記事がよい資料となるでしょう。
●ユニットテスト
ユニットテストのねらいは、特定の入力を与えたRecipeが意図した出力をすることの確認です。ユニットテストは素早く、Nodeを収束することなしに行えるものなので、収束前に行うことができます。Chef CookbookのユニットテストはChefSpecで行えます。とても重要なこととして、Chef自身が動作するというテストの罠に陥らないことです。例えば、与えられたRecipeが次のようなResourceを持っていたとします。
package "httpd" do
action :install
end
ユニットテストは次のように書きたくなるでしょう。
it "installs the httpd package" do
expect(chef_run).to install_package("httpd")
end
これは、Recipeが「httpd」パッケージをインストールすると知っているので、Chefがどのように動くか確かだということです! しかし、Nodeのプラットフォームに依存して、パッケージ名は違ってくるでしょう。与えられたプラットフォーム上で特定のパッケージ名がインストールされる(この例ではRHELファミリーなら「httpd」で、Debianファミリーなら「apache2」)ことの検証にユニットテストを使うことができます。ChefSpecにおける条件テストについてより詳しくはこの件に関する記事を参照してください。
●インテグレーションテスト
インテグレーションテストのねらいは、ChefがNodeを収束した後のシステムの最終状態が実際に望んだ通りであるかの検証です。そのため、コードが望み通りであるかを高い確度で知ることができます。Chef Cookbookのインテグレーションテストは、Serverspec、BATS、Minitestといったさまざまなフレームワークをサポートした「busser」を通してTest Kitchen上で行われます。特徴については次の個々の項目を参照してください。
■よく使われるChefのテストツール
この項ではChefの開発でよく使われているツールを紹介します。
●RuboCop
これは何? 何故使う?
Rubocopは、コミュニティが取り決めているRubyスタイルガイドに基いたlintチェックとスタイルチェックを実行する、Rubyコマンドラインツールです。Chef Recipe、Resource、Libraryヘルパーなどを含むあらゆるRubyコードの静的解析を行います。Rubocopは.rubocop.ymlを通してあるルールを除外設定したり、「-lint」オプションつきで実行することですべてのスタイルチェックを除外してlintチェックのみを行うことができます。Rubocopは、Cookbookをより一貫性を保ってより簡単に管理できるように、Chefコミュニティで用いられています。
Chef開発におけるフェイズ
Rubocopは収束前か、Cookbookの変更点が望ましいスタイルに保たれているかCIシステムで実行します。Rakefile内のrakeタスクとして使われています。
入手するには
RubocopはChefDKに同梱されています。コマンドラインツールであるrubocopから起動するか、RakefileにRuboCop::RakeTask.new(:ruby)を含めることもできます。
より詳しく
●Foodcritic
これは何? 何故使う?
FoodcriticはChef Cookbookのlinkチェックを行うRubyコマンドラインツールです。収束中にChefが例外を発生する原因となりうるCookbook中の問題をより簡単に見つけることができます。Cookbookの作者はFoodcriticを使うことで、よいパターンを励行し、品質の高いCookbookを作る助けとなります。Foodcriticはたくさんのルールを同梱していて、ユーザが独自のルールを書くこともできます。.foodcritic設定ファイル、インラインコメント、コマンドラインフラグを通して、あるルールを無視するように設定することもできます。
Chef開発におけるフェイズ
Foodcriticは収束前や、Travis CIのようなCIシステムで実行します。
入手するには
FoodcriticはChefDKに同梱されています。コマンドラインツールであるfoodcriticから起動できます。Rubocopのように、RakefileにFoodCritic::Rake::LintTask.newを含めることもできます。
より詳しく
●ChefSpec
これは何? 何故使う?
ChefSpecはChef Cookbookのユニットテストフレームワークです。システムに何も変更を加えることなくローカルにテストを実行します。ChefSpecはResourceを収束する通常のテストや修復の動作を行わないので高速に動作します。また、後述のFauxhaiのデータも使えるので、異なるプラットフォームに対する条件付きテストも簡単に行えます。レグレッションを防ぐ助けとして、ChefSpecをCookbook作者に強く推奨します。ChefSpecによる価値あるテストは次の通りです。
- マルチプラットフォーム
- 条件分岐
- AttributeやData Bagによる動作
- Search結果
- ヘルパーメソッド
- 独自のResourceとProvider
Chef開発におけるフェイズ
ChefSpecはCookbookのテストの収束前に使います。主に特定の入力、特にAttributeのような値を検証するために用いて、Chefは期待するResourceコレクションを出力します。
入手するには
ChefSpecはChefDKに同梱されています。rspecを使って起動するので、specファイルがchefspecを要求します。
より詳しく
●Serverspec
これは何? 何故使う?
Serverspecは「すみからすみまで」のインテグレーションテストフレームワークです。プラットフォームやツールに寛容で、システムが期待通りに設定されているか検証するために、他の構成管理システムにも使われています。ローカル、SSH経由、WinRM経由、その他遠隔操作によって対象のNodeの実際の状態を確認します。ServerspecはRSpecで実装されているので、RSpecの文法を使います。
Chef開発におけるフェイズ
Serverspecは収束後のフェイズで使います。ChefがNodeで実行した実際の結果が望ましい状態かテストします。
入手するには
Serverspecは、Chef 12.1.0以上がAudit Modeで依存しているので、ChefDKに同梱されています。Test Kitchenで使うときは、テストするNode上でBusserによってインストールされます。Test Kitchenで使うには、test/integration/SUITE/serverspecディレクトリを作成すると、busserがあとのことをやってくれます。
より詳しく
●Chef Audit Mode
これは何? 何故使う?
Chef Audit Mode (監査モード)はChefバージョン12.1.0で導入された機能です。chef-clientがRecipeに書かれたテスト(Audit Control)を実行できるようにするモードです。監査の結果はChef Serverに送信されて、Chef Analyticsがインストールされていればさらなる解析や処理に用いられます。Audit ModeはServerspecのサブセット、つまりRSpecとして実装されています。Audit Modeは、NodeでResourceを収束するchef-clientの実行の一部として実行されます。例えば、Recipeがあるべき状態へ設定するためのpackage、template、service Resourceを持っていたら、Audit Modeはすべてがあるべき状態でポリシーに従っていることを検証します。Audit ModeはResourceを収束することなしに実行できます。つまり、package、template、service Resourceを持っている同じRecipeがそれらの状態を変更しなくても、Audit Controlを実行するということです。Audit Modeの主な恩恵は、Chef Analyticsとの組み合わせ、実行の結果の解析、例えばメール経由での結果の通知です。使っている言語はとてもはっきりしていて、PCI、SOX、個々の組織のポリシーの目的に合致した監査に適合しています。出力されるレポートは全体像を見通せる監査ドキュメントとして有用で、RecipeにControlが記述でき、検証のためのControlという意図のドキュメントとその意図のために収束するResourceという修正手順の両方を備えています。Audit Modeの主目的と通常のServerspecが異なっているのは意図的です。Audit Modeでは、意図はNodeがポリシーに適合しているかどうかの検証が狙いです。Serverspecでは、Recipeを実行した後のNodeの状態が正しいかどうかの検証が狙いです。
Chef開発におけるフェイズ
Audit Modeは収束フェイズの一部として実行されます。enabledに設定したら、NodeがResource Collection中のすべてのResourceを収束した後に実行されます。audit_onlyに設定したら、「収束後」とみなして監査を実行します。
入手するには
Audit ModeはChef 12.1.0以上に同梱されています。それより低いバージョンではサポートしていません。
より詳しく
●Test Kitchen
これは何? 何故使う?
Test Kitchenは対象のプラットフォームに隔離してインフラコードやソフトウェアの開発やテストを行うためのインテグレーションツールです。テストマシンを作成し、収束し、状態を検証するための収束後テストを実行します。Test KitchenはRubyで書かれています。vagrant、EC2、dockerなどといった、さまざまな種類の仮想マシン技術を通してサポートするマシンを作成するためのプラグイン機構を備えています。Test KitchenはChef開発者がさまざまなプラットフォームでのCookbookのテストを容易にしてくれます。実際にテストを行うServerspecやBATSのようなインテグレーションテストツールを収束後にインストールするbusserを使っています。
Chef開発におけるフェイズ
Test Kitchenは実際にマシンを収束して自動的に収束後テストを行います。手動もしくはCIシステムを通して実行します。
入手するには
Test KitchenはChefDKに同梱されています。はじめにkitchen initコマンドでCookbookに.kitchen.ymlファイルを作り、kitchen test、kitchen converge、kitchen verifyといったkitchenコマンドを使って設定したマシンで動作を行います。
より詳しく
■サポートツールと、依存関係にあるソフトウェア
この項では、ツールがサポートする一般的なツールや、それらの依存関係を紹介します。これらは完全性のために言及しています。
●RakeとThor
これは何? 何故使う?
RakeとThorはmakeに似た、コマンドラインのタスク実行ツールです。タスクはそれぞれRakefileとThorfileに記述します。どちらもRubyで実装されていますが、内部動作は若干異なります。これらはほぼ互換性があるので同じ項目で取り上げます。すなわち、一方をもう一方より好む人がいるということです。RakeとThorは、個々のプロジェクト次第で、テストスイートの実行、Cookbookのビルドとリリースといったタスクを持っています。FoodcriticやChefSpecのような、これまで述べてきたツールとRakeとThorを組み合せが考えられます。
Chef開発におけるフェイズ
RakeとThorは、ChefSpecやRSpecのようなタスクや、RubocopやFoodcriticのようなlistチェックを実行する収束前で使います。RubyGemプロジェクトはたいていgemをrubygems.orgにリリースするタスクを持っています。CookbookプロジェクトはCookbookをSupermarketにリリースする、またはChef Serverにアップロードするタスクを持っていることがあります。多くのプロジェクトはコミットごとに、Travis CIを使ってユニットテスト、スペックテスト、lintチェック、スタイルチェックのようなタスクを自動的に実行しています。
入手するには
RakeとThorは両方ともChefDKに同梱されています。Rakeを使うにはRakefileが必要です。Thorを使うにはThorfileが必要です。「rake -T」または「thor -T」を実行すると、プロジェクトのタスクの一覧を取得できます。
より詳しく
- Cookbook内のRakefileの例
- Cookbook内のThorfileの例
- Travis CIでrakeを使う例
- http://docs.seattlerb.org/rake/
- http://whatisthor.com/
●Guard
これは何? 何故使う?
Guardはファイルシステムの変更イベントを取り扱うRubyのコマンドラインツールです。ここで記述してきた他のツールの「自動実行」を行います。より一般的に言えば、.rbファイルが変更されたらテストスイートを実行するということを意味します。Guardは、監視するディレクトリやファイルと変更があったら実行するコマンドを指定するGuardfileによって設定します。
Chef開発におけるフェイズ
Guardは、「knife cookbook test」による文法チェック、「rubocop」と「foodcritic」によるlintチェック、「rspec (ChefSpec)」によるユニットテストを行う収束前に使います。Recipeの変更があったとき、自動的にTest Kitchenを走らせる「kitchen converge」や「kitchen verify」を実行することもできます。
入手するには
GuardはChefDKに同梱されています。特にTest Kitchenと統合するなら、「guard-kitchen」gemを使ってください。
より詳しく
●RSpec
これは何? 何故使う?
RSpecはテスト駆動開発(Test Driven Development; TDD)または振る舞い駆動開発(Behavior Driven Development; BDD)フレームワークです。Rubyコミュニティでテストのために広く使われており、新しいテストフレームワークを作る拡張性もあります。例えば、ChefSpecとServerspec (すなわちChef Audit Mode)はRSpecに基いています。Chef社ではChefはもちろん、開発している他のRubyベースのツールやライブラリのテストにRSpecを使っています。RSpecは、Chef Server、Chef Analytics、Chef Deliveryといったサーバ製品の検証のための「pedant」テストフレームワークの基礎にもなっています。
Chef開発におけるフェイズ
RSpecは収束前のChefSpecで使われます。収束中のServerspecを通したAudit Modeでも使われます。さらに収束後もServerspecから使われます。
入手するには
RSpecはChefSpecとServerspecが依存しているので、ChefDKに同梱されています。その他の非CookbookのプロジェクトにRSpecを含めるには、bundlerでインストールするためのGemfileに追加します。Chefに関連するRubyベースのプロジェクトのほとんどは、ユニットテストのためにRSpecを使っています。
より詳しく
●Fauxhai
これは何? 何故使う?
Fauxhaiは、テスト用のNode Attributeを提供するための疑似Ohaiデータを生成するツールです。FauxhaiはChefSpecで使われています。ほとんどのCookbook開発者は、新しいプラットフォームのサポートを追加するのでもなけば、直接Fauxhaiを使っていません。
入手するには
FauxhaiはChefSpecが依存しているので、ChefDKに同梱されています。
より詳しく
●Busser
これは何? 何故使う?
プロジェクトのREADMEによると、Busserはシステムの依存関係を満たすことのできない遠隔ノードで動作するように設計された、テストのセットアップと実行フレームワークです。Busserは、収束後のテストを行うためにTest Kitchenで使われています。異なるテストフレームワークを使えるように、プラグインベースのアーキテクチャを備えています。
Chef開発におけるフェイズ
Busserは、kitchen verify動作中、Test Kitchenによる収束後の自動テストで使われます。
入手するには
BusserはTest Kitchenによって自動的にインストールされます。
より詳しく
■あまり使われないか、非推奨のツール
この項では、あまり使われないか、既に述べた新しいツールの登場で非推奨と考えられるツールを紹介します。
●Cucumber
これは何? 何故使う?
Cucumberは、Gherkinという言語で記述された仕様に対して実行するストーリーを記述する、「プレーンテキスト」ベースのDSL(domain specific language; ドメイン固有言語)です。Ruby on RailsプロジェクトでBDDのために一般的に使われており、Chef Cookbook開発にも使われていました。
Chef開発におけるフェイズ
CucumberはChef Cookbook開発にあまり使われていません。以前は収束後の受け入れテストやインテグレーションテストに使われていましたが、ほとんどの人はServerspecやBATSを使うようになっています。
入手するには
CucumberはChefDKに同梱されています。
より詳しく
●BATS
これは何? 何故使う?
BATSはBourne-again shell (bash) テストフレームワークです。ユーザが検証のためにシステムにログインした後に実行したいコマンドをそのまま実装できるので、簡単にテストを書くことができます。しかし、bashがインストールされているUnix/Linuxシステム専用なので、Windowsシステムでは動作しません。つまりクロスプラットフォームなCookbookをテストすることが難しいので、ほとんどのユーザはServerspecを好みます。ServerspecはChef Audit Modeの基礎でもあるのでより広く使われているし、収束後のテストにはBATSよりServerspecがお勧めです。
Chef開発におけるフェイズ
BATSは収束後のフェイズで使います。NodeでChefを実行した結果があるべき状態になっているか実際の状態をテストします。
入手するには
BATSはChefDKに同梱されていません。Test KitchenがBusserによってインストールします。Test Kitchenの外でどのように使うか詳しい情報はホームページを参照してください。
より詳しく
●minitest
これは何? 何故使う?
minitestはRuby標準ライブラリに含まれるRubyテストフレームワークです。早く簡単に使えるように設計されています。しかし、Chefコミュニティでは、Chef自身も含めて非CookbookのRubyプロジェクトではRSpecが一般的に使われています。古いCookbookではminitest-chefプロジェクトがまだ使われているので、ここで取り上げています。収束後のテストにTest Kitchenより好む人もいるようです。
Chef開発におけるフェイズ
minitestは収束後のフェイズで使われます。歴史的には、Chefのレポートハンドラであるminitest-chef-handlerの一部としてのみ使われていました。kitchen verifyでbusserとして使うこともできます。
入手するには
minitestはRuby標準ライブラリに同梱されているので、ChefDKのomnibusインストールによる組み込みRubyも含めて、Rubyがインストールされているシステムならインストールされています。minitest-chef-handlerを使う際、Chefのレポートハンドラを通して起動されます。Test Kitchenから使う場合、テストするNode上でBusserとインストールされます。その場合はtest/integration/SUITE/minitestディレクトリを作成すると、busserがあとのことをやってくれます。
より詳しく
●minitest-chef-handler
これは何? 何故使う?
minitest-chef-handlerは、初期のChefの収束後のテストフレームワークです。minitestを使ってシステムの状態を検証するために、Chefの実行が成功した後にレポートハンドラとして実行します。このハンドラはTest KitchenとBusserによるテストフレームワークによって非推奨と考えられます。
Chef開発におけるフェイズ
minitest-chef-handlerは収束後のフェイズで実行します。実際は、Chefの実行の一部であるレポートハンドラとして実行されます。
入手するには
minitest-handler Cookbookはminitest-chef-handlerによって自動的にインストールされ、レポートハンドラとして実行するように登録されます。