chef初心者がTest Kitchenを使ってみる 

# 概要
Chefの`Test Kitchen`を利用した時の備忘録です。
Chefチュートリアルの`Manage Your Fleet with Chef Infra`を通して`Kitchen`とは何かを学びます。

https://learn.chef.io/courses/course-v1:chef+Infra101+perpetual/course/#block-v1:chef+Infra101+perpetual+type@chapter+block@49dd59ea8b1f4c50ae9a260db35452ad


## 01. Kitchenとは
テスト自動化ツールのことです。
chefはcookbookを作り、各ノード(物理サーバ等)にcookbookを適用してインフラ設定等を自動化します。
`Kitchen`はそのテストをサポートするCLIであり、簡単にテストを実施できます。

https://docs.chef.io/workstation/kitchen/

## 02. 事前準備
Kitchenを動かすには、`VirtualBox`と`Vagrant`をinstallしておく必要があります。
事前にinstall済みのため、インストール手順等は記載しません。
下記コマンドから、事前にインストール済みであることを確認します。

```Bash:Windows10端末
$ VBoxManage --version
6.1.32r149290

$ vagrant --version
Vagrant 2.2.19
```

また、`chefDK`も事前にinstallしておく必要があります。
下記コマンドから、事前にインストール済みであることを確認します。

```Bash:Windows10端末
$ chef -v
ChefDK version: 4.13.3
Chef Infra Client version: 15.14.0
Chef InSpec version: 4.24.8
Test Kitchen version: 2.8.0
Foodcritic version: 16.3.0
Cookstyle version: 5.23.0
```

## 03. 実践 - Test Kitchenの土台準備
Kitchenを使う事前準備として、cookbookの雛形を作成する。

```Bash:Windows10端末
$ chef generate cookbook cookbooks/learn_chef

$ ls -ltr cookbooks/learn_chef/
total 28
-rw-rw-r--. 1 vagrant vagrant  742 Jan 28 13:32 metadata.rb
-rw-rw-r--. 1 vagrant vagrant   58 Jan 28 13:32 README.md
-rw-rw-r--. 1 vagrant vagrant  158 Jan 28 13:32 CHANGELOG.md
-rw-rw-r--. 1 vagrant vagrant 1176 Jan 28 13:32 chefignore
-rw-rw-r--. 1 vagrant vagrant  519 Jan 28 13:32 Policyfile.rb
-rw-rw-r--. 1 vagrant vagrant   70 Jan 28 13:32 LICENSE
-rw-rw-r--. 1 vagrant vagrant  741 Jan 28 13:32 kitchen.yml
drwxrwxr-x. 3 vagrant vagrant   25 Jan 28 13:32 test
drwxrwxr-x. 3 vagrant vagrant   40 Jan 28 13:32 spec
drwxrwxr-x. 2 vagrant vagrant   24 Jan 28 13:32 recipes
```


色々作成されるファイルは一旦無視し、`kitchen.yml`の中身を確認する。
`kitchen.yml`には、テスト環境の設定が記述される。
下記場合だと、`vagrant`を使用して`Ubuntu`と`CentOS`の2インスタンスを作成し、Chef Infra(`chef_zero`)を使ってテストインスタンスをプロビジョニングといった具合でテストを実行できるということです。

```Bash:Windows10端末
$ cat cookbooks/learn_chef/kitchen.yml
---
driver:
  name: vagrant

## The forwarded_port port feature lets you connect to ports on the VM guest via
## localhost on the host.
## see also: https://www.vagrantup.com/docs/networking/forwarded_ports.html

#  network:
#    - ["forwarded_port", {guest: 80, host: 8080}]

provisioner:
  name: chef_zero

  ## product_name and product_version specifies a specific Chef product and version to install.
  ## see the Chef documentation for more details: https://docs.chef.io/config_yml_kitchen.html
  #  product_name: chef
  #  product_version: 15

verifier:
  name: inspec

platforms:
  - name: ubuntu-18.04
  - name: centos-7

suites:
  - name: default
    verifier:
      inspec_tests:
        - test/integration/default
    attributes:
```

`kitchen list`コマンドで、テスト環境の各インスタンス情報を確認できます。
先ほど確認した`ubuntu/18`と`centos/7`がインスタンスとしてあることが確認できますね。

```Bash:Windows10端末
$ kitchen list
Instance             Driver   Provisioner  Verifier  Transport  Last Action    Last Error
default-ubuntu-1804  Vagrant  ChefZero     Inspec    Ssh        <Not Created>  <None>
default-centos-7     Vagrant  ChefZero     Inspec    Ssh        <Not Created>  <None>
```

`kitchen create`コマンドでテスト用インスタンスを作成します。
このコマンドは、各OSイメージをdownloadし、テストインスタンスに対してデプロイするため完了まで数分~数十分ほど時間が掛かる場合があります。

```Bash:Windows10端末
$ kitchen create
```

▼ create失敗例①
create時にエラーになりました。
なぜか共有フォルダのtmp参照パスが誤って設定されました。。
GUIから直接修正し、再度`kitchen create`を実行で解決できました。

```Bash:エラー例1
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: 1 actions failed.
>>>>>>     Failed to complete #create action: [Expected process to exit with [0], but received '1'
...(省略)
    Vagrant is currently configured to create VirtualBox synced folders with
    the `SharedFoldersEnableSymlinksCreate` option enabled. If the Vagrant
    guest is not trusted, you may want to disable this option. For more
    information on this option, please refer to the VirtualBox manual:

    https://www.virtualbox.org/manual/ch04.html#sharedfolders
```


▼ create失敗例②
なぜか`ubuntu/18`のvagrant秘密鍵ファイルの参照パスが誤ったパスに設定されました。
1度、`.kitchen`にある`ubuntu/18`に関するファイルを全削除し、再度`kitchen create`を実行で解決できました。

```Bash:エラー例2
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: 1 actions failed.
>>>>>>     Failed to complete #create action: [Expected process to exit with [0], but received '1'
...(省略)
    default: SSH auth method: private key
STDERR: Timed out while waiting for the machine to boot. This means that
Vagrant was unable to communicate with the guest machine within
the configured ("config.vm.boot_timeout" value) time period.
```

作成が正常に完了すると`Last Action`が`Created`、`Last Error`が`<None>`になります。
上手くいかない場合はぐぐって解決します・・！

```Bash:Windows10端末
$ kitchen list
Instance             Driver   Provisioner  Verifier  Transport  Last Action  Last Error
default-ubuntu-1804  Vagrant  ChefZero     Inspec    Ssh        Created      <None>
default-centos-7     Vagrant  ChefZero     Inspec    Ssh        Created      <None>
```

`kitchen login`コマンドでテストインスタンスにログインできます。
ログアウトする場合は`exit`です。

```Bash:Windows10端末
# kitchen login <INSTANCE>
$ kitchen login default-centos-7
```

以上で、`Test Kitchen`を使う準備が整いました！！

## 04. 実践 - Test Kitchenでファイルリソースをテストする
`Test Kitchen`を活用してテストをしていきます。
チュートリアルでは、以下を実施しています。

```Bash:チュートリアルのゴール
- /etc/motdファイルを作成
  -  ファイルに"Learning Chef is fun with YAML!"と書き込む
```

まず、ファイル作成のレシピファイルを新規作成する。
ファイルは`yml形式`と`ruby形式`のどちらでもOKらしいです。

```Bash:/learn_chef/recipes/learn-chef.yml
resources:
 - type: "file"
   name: "/etc/motd"
   content: "Learning Chef is fun with YAML!"
```

その後、作ったレシピを適応するために`./recipes/default.rb`に読み込む設定を追加します。
recipiesは`default.rb`を最初に読み込むので、こファイルを拡張していくようです。

```Bash:/learn_chef/recipes/default.rb
#
# Cookbook:: learn_chef
# Recipe:: default
#
# Copyright:: 2022, The Authors, All Rights Reserved.
include_recipe "learn_chef::learn-chef"
```

最後に`kitchen converge`を実行して、レシピをテストVMにデプロイします。
ログ的に、先ほど作成した`centos/7`と`ubuntu/18`にファイル作成レシピが適応されていそうです。

```Bash:実行結果
$ kitchen converge
-----> Starting Test Kitchen (v2.8.0)
-----> Converging <default-ubuntu-1804>...
...(省略)...
       Converging 1 resources
       Recipe: learn_chef::learn-chef
         * file[/etc/motd] action create (up to date)
...(省略)...
-----> Converging <default-centos-7>...
...(省略)...
       Converging 1 resources
       Recipe: learn_chef::learn-chef
         * file[/etc/motd] action create (up to date)
...(省略)...
-----> Test Kitchen is finished. (0m41.48s)
```

VMにログインし、レシピが適応されているかを確認する。
問題なくファイル作成されていますね！！

```Bash:実行結果
# ubuntu
$ kitchen login default-ubuntu-1804
$ hostname
default-ubuntu-1804
$ cat /etc/motd
Learning Chef is fun with YAML!

# centos
$ kitchen login default-centos-7
$ hostname
default-centos-7.vagrantup.com
$ cat /etc/motd
Learning Chef is fun with YAML!
```

最後に、Kitchenで作成したVMを削除します。
`kitchen destroy`コマンドを使えば、簡単に削除できます。

```Bash:実行結果
$ kitchen destroy
-----> Starting Test Kitchen (v2.8.0)
-----> Destroying <default-ubuntu-1804>...
       ==> default: Forcing shutdown of VM...
       ==> default: Destroying VM and associated drives...
       Vagrant instance <default-ubuntu-1804> destroyed.
       Finished destroying <default-ubuntu-1804> (0m8.50s).
-----> Destroying <default-centos-7>...
       ==> default: Forcing shutdown of VM...
       ==> default: Destroying VM and associated drives...
       Vagrant instance <default-centos-7> destroyed.
       Finished destroying <default-centos-7> (0m8.59s).
-----> Test Kitchen is finished. (0m20.92s)

# 削除されると、Last Actionが<Not Created>に
$ kitchen list
Instance             Driver   Provisioner  Verifier  Transport  Last Action    Last Error
default-ubuntu-1804  Vagrant  ChefZero     Inspec    Ssh        <Not Created>  <None>
default-centos-7     Vagrant  ChefZero     Inspec    Ssh        <Not Created>  <None>
```


## まとめ
`Test Kitchen`を利用することで、作成したレシピ単位で簡単に動作確認することができました。
本家チュートリアルはもう少し続きますが、Test Kitchenとは何か？の備忘録のため記事はココまでとします。

`kitchen create`の環境構築に手惑いましたが、ググれば何とか解決できるレベルです。
レシピの動作確認に積極的に利用していきたいと思います！

※ 本家チュートリアルでapache2をinstallするレシピがありますが、`converg`時にエラーに。その場合は更新先のサーバにsshし、ライブラリを更新しておくと正常にinstallできました！！
（chefをキャッチアップする際、こういうブービートラップが多いのが辛みですね笑）

```Bash:VM
sudo apt-get -y update && sudo apt-get -y upgrade
```