goss を使ったサーバ構築のテスト


はじめに

以前 InSpec でデプロイを自動テスト化する という記事で InSpec というテストフレームワークの紹介をしましたが、最近 goss という Go 言語製のテストフレームワークを使い始めたのでそのご紹介です。

goss とは

goss は YAML でテストケースを記述し、その内容に従ってテストを実行できるフレームワークです。

特徴

  • シングルバイナリなのでライブラリのインストールなどが不要
  • 記述が YAML なので覚えることが少ない
  • 速い

goss でできるテストの例

goss を使えば下記のようなことがテストできるようになります。

  • ファイルが存在するか
  • ファイル属性は正しいか
  • プロセスやサービスは起動しているか
  • パッケージはインストールされているか
  • HTTP レスポンスのヘッダやボディは正しいか

インストール

開発用途の環境に入れるのであれば下記でインストールできます。

$ curl -fsSL https://goss.rocks/install | sh

本番用途の環境であればこのインストール方法は推奨されてないので、代わりに下記のようにインストールします。

$ curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.9/goss-linux-amd64 -o /usr/local/bin/goss
$ chmod +x /usr/local/bin/goss

使い方

試しに Apache が正しく動いているかどうかをテストしてみたいと思います。 goss.yaml という名前で下記のようにファイルを作成します。

動作環境

  • CentOS 7
  • Apache 2.4.6
goss.yaml
package:
  httpd:
    title: httpd 2.4.6 がインストールされていること
    installed: true
    versions:
      - 2.4.6

file:
  /etc/httpd/conf/httpd.conf:
    title: 設定ファイルが存在すること
    exists: true

service:
  httpd:
    title: httpd がサービスに登録されていること
    enabled: true
    running: true

process:
  httpd:
    title: httpd が起動していること
    running: true

port:
  tcp:80:
    title: 80 ポートをリッスンしていること
    listening: true

http:
  http://localhost:
    title: 疎通できること
    status: 200

テストをするには goss.yaml を保存した場所で下記のコマンドを実行します。

$ goss validate

もしテストに失敗すれば下記のようなエラーメッセージが出力されます。

$ goss validate
F..F..F.

Failures/Skipped:

Title: 80 ポートをリッスンしていること
Port: tcp:80: listening:
Expected
    <bool>: false
to equal
    <bool>: true

Title: 疎通できること
HTTP: http://localhost: status:
Expected
    <int>: 403
to equal
    <int>: 200

Title: httpd がサービスに登録されていること
Service: httpd: enabled:
Expected
    <bool>: false
to equal
    <bool>: true

Total Duration: 0.045s
Count: 8, Failed: 3, Skipped: 0

テストレポートは JSON や JUnit 形式で出力することもできます。レポート形式を指定するには -f を使用します。

$ goss validate -f junit

goss を使ったヘルスチェック

Serverspec や InSpec にはない機能として、goss をサーバとして起動しておき、テストのレポートを HTTP で受け取る機能が便利でした。

下記コマンドを実行すると goss サーバがポート 8080 で起動します。

$ goss serve -f junit

curl やブラウザから http://<host>:8080/healthz にアクセスするとテストレポートを取得できます。

$ curl http://localhost:8080/healthz

テストレポートを JUnit 形式で取得できるようにしておき、これを CI で定期実行させると単体テストを CI で実行する感覚でヘルスチェックが行えるようになります。

注意点

Serverspec や InSpec はリモートサーバを対象にテストを実行できますが goss にはリモート実行の機能は実装されていません。これは goss の設計をシンプルに保つことと簡単なシェルを書けば goss ファイルの転送と実行はできるからという作者の意向によるものです。(参考:ssh and exec support

ちなみにコンテナを対象に goss を実行する場合は dgoss という goss ラッパが使用できますが、これは単にコンテナに goss ファイルを送るだけのシンプルなシェルスクリプトとして実装されています。

リモート実行をしたい場合は dgoss と同様のスクリプトを書いて運用するのが良いと思います。ただ個人的には HTTP でテスト結果を受け取れる機能が使いやすいので、テスト対象のサーバであらかじめ goss サーバを起動させて使用しています。

さいごに

Serverspec や InSpec と比べて実行速度が圧倒的に速いことと YAML でテストを記述できるという点が goss の魅力ではないかと思いますので是非お試しください。