ローカルAnsibleからDockerに対して収束させるtest-Kitchen環境例


#概要
- mac環境におけるtest-kitchenによるDockerノードへのAnsibleによる収束と、その設定に使用した値を連携してのinspecによるテストを行う環境の構築手順をまとめる

- ansibleによる収束は、ローカルのmac環境上のansibleから行う。
    - その為、test-kitchenにおいてansible provisionerでは無く、ansible_push provisionerを使用する。
    - 参考：[kitchen-ansiblepushを利用したAnsible roleのテスト環境構築](https://dev.classmethod.jp/server-side/ansible/kitchen-ansiblepush/)


- test-kitchenやinspecの為、Chef Workstationを使用する。


#環境
macOS 10.13.6

##前提
以下が導入済み
Vagrant 2.1.2
Docker 2.0.0.2
Chef Workstation: 0.2.48

```bash
$ echo 'eval "$(chef shell-init bash)"' >> ~/.bash_profile
$ . ~/.bash_profile
```

#MacへのAnsible導入
Homebrewを導入
[Mac の開発を便利にするパッケージ管理ソフト Homebrew のインストール手順](https://weblabo.oscasierra.net/homebrew-1/)

その後

```bash
$ brew install ansible

...
```

#kitchen-ansiblepush, kitchen-dockerの導入

```bash

$ gem install kitchen-ansiblepush
Fetching: kitchen-ansiblepush-0.9.1.gem (100%)
Successfully installed kitchen-ansiblepush-0.9.1
1 gem installed

同様に
$ gem install kitchen-docker
...
```



#環境の雛形としてcookbookを作成

```bash
$ chef generate cookbook ansible2inspec
...
$ cd ansible2inspec
$ vi .kitchen.yml                              # test-kitchen設定ファイル
...
$ mkdir tasks
$ vi tasks/site.yml                            # playbook本体
...
$ vi test/integration/default/default_test.rb  # inspecテスト
...
```

##test-kitchen設定ファイル

デフォルトで作成される.kitchen.ymlから変更

```yaml:.kitchen.yml
---
driver:
  name: docker

provisioner:
  name: ansible_push
  chef_bootstrap_url: nil
  become: true

verifier:
  name: inspec

platforms:
  #- name: ubuntu-16.04
  - name: centos-7

suites:
  - name: ansiblepush
    provisioner:
      playbook: tasks/site.yml      # ここではtasksの下にsite.ymlをおいている
    verifier:
      inspec_tests:
        - test/integration/default
```

##playbook本体
最初のtaskは変数ファイルで設定するpackagesの内容をyumでインストール
最後のtaskは対象ノードの/tmp/node.jsonに変数情報を保存

```yaml:task/site.yml
---
- hosts: all
  become: yes
  vars:
    packages:
      - name: "tree"
  tasks:

    - name: "packagesのyumインストール"
      yum:
        name: "{{ item.name }}"
      with_items: "{{ packages }}"

    - name: "dump_variables hostvars to json on remote node"
      copy:
        content: "{{ vars | to_nice_json }}"
        dest: "/tmp/vars.json"
```



参照：[ServerspecをAnsibleのhostvars変数の値を使ってansible-playbook から実行する方法](https://qiita.com/tbuchi888/items/c415613d4763e9851b36)

##InSpecテスト
テンプレートとして作成されているinspecテストを編集。
対象ノード上の/tmp/vars.jsonを読み込んで変数を連携し、テストを行う


```ruby:test/integration/default/default_test.rb
# # encoding: utf-8

# Inspec test for recipe ansiblepush::default

# The Inspec reference, with examples and extensive documentation, can be
# found at http://inspec.io/docs/reference/resources/

# リモートのJSONをロード
vars = json('/tmp/vars.json').params

# テスト本体
vars['packages'].each do |p|
  describe package(p['name']) do
    it { should be_installed }
  end
end
```

#起動、収束、テストの実施
Docker起動、ansibleによる反映、変数を引き継いでのinspecでのテストを通しで行う。

```
$ kitchen test -d never
-----> Starting Kitchen (v1.24.0)
-----> Cleaning up any prior instances of <ansiblepush-centos-7>
-----> Destroying <ansiblepush-centos-7>...
       Finished destroying <ansiblepush-centos-7> (0m0.00s).
-----> Testing <ansiblepush-centos-7>
-----> Creating <ansiblepush-centos-7>...
       Sending build context to Docker daemon  115.2kB
       Step 1/17 : FROM centos:centos7
        ---> 1e1148e4cc2c
       Step 2/17 : ENV container docker
        ---> Using cache
        ---> 5f9edaa70656
       Step 3/17 : RUN yum clean all
        ---> Using cache
        ---> 987d0879683b
       Step 4/17 : RUN yum install -y sudo openssh-server openssh-clients which curl
        ---> Using cache
        ---> e35a73c53d1d
       Step 5/17 : RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
        ---> Using cache
        ---> adc8c9a47624
       Step 6/17 : RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ''
        ---> Using cache
        ---> fe00d7df7bfc
       Step 7/17 : RUN if ! getent passwd kitchen; then                 useradd -d /home/kitchen -m -s /bin/bash -p '*' kitchen;               fi
        ---> Using cache
        ---> 529ea1de9e4d
       Step 8/17 : RUN echo "kitchen ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
        ---> Using cache
        ---> 5ccd73b8f3eb
       Step 9/17 : RUN echo "Defaults !requiretty" >> /etc/sudoers
        ---> Using cache
        ---> 428bc6cc1d3a
       Step 10/17 : RUN mkdir -p /home/kitchen/.ssh
        ---> Using cache
        ---> 36d79e5b5650
       Step 11/17 : RUN chown -R kitchen /home/kitchen/.ssh
        ---> Using cache
        ---> 3dfb758ab5ef
       Step 12/17 : RUN chmod 0700 /home/kitchen/.ssh
        ---> Using cache
        ---> b4e63056f970
       Step 13/17 : RUN touch /home/kitchen/.ssh/authorized_keys
        ---> Using cache
        ---> f9d269f28c59
       Step 14/17 : RUN chown kitchen /home/kitchen/.ssh/authorized_keys
        ---> Using cache
        ---> a35ffa65d241
       Step 15/17 : RUN chmod 0600 /home/kitchen/.ssh/authorized_keys
        ---> Using cache
        ---> fecea6d3501f
       Step 16/17 : RUN mkdir -p /run/sshd
        ---> Using cache
        ---> 256240e4ee8c
       Step 17/17 : RUN echo ssh-rsa\ AAAAB3NzaC1yc2EAAAADAQABAAABAQC/EbMwOrfL4oDfP5DtrtHA7SdhmvWnIRCBn3rbtKqnjJ6ZqIgqdr8zrTPzWRjrRlY9mNKOleyicXXgjEmRWtzkrp0D\+ABA4cChdcsTWJH1BvqDZ0IwJAYf8PJoa09E2l9MvqH/8uXAzcBv\+OFGL5Yz9jnKYyzHv4RQACq5ibTSdHj5XEt/5fLCnjukB6uEXaiKjOA5jFljqD1pykrXqhRc\+dMY1WjFwu2kt445f22VFcbv0bOZggtfZR0NHFR/OA\+P/DPpfKU30OINSAB4\+iBgshInXxQw4e\+kXmJM0xikoeTb616H4MwXR1eHWA\+g4GaD\+8owWawPIaL3etgIdQ\+v\ kitchen_docker_key >> /home/kitchen/.ssh/authorized_keys
        ---> Using cache
        ---> 446f0fa10911
       Successfully built 446f0fa10911
       2b02c1b116aa9ef54304a3be169623f2a6d63448e6207522763616fc7c6111df
       0.0.0.0:32774
       [SSH] Established
       Finished creating <ansiblepush-centos-7> (0m1.58s).
-----> Converging <ansiblepush-centos-7>...
       Preparing files for transfer
       *************** AnsiblePush install_command ***************
       Ansible push config validated
       Transferring files to <ansiblepush-centos-7>
       *************** AnsiblePush run ***************

PLAY [all] *********************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************
ok: [centos-7]

TASK [packagesのyumインストール] ******************************************************************************************************
changed: [centos-7] => (item={u'name': u'tree'})

TASK [dump_variables hostvars to json on remote node] **************************************************************************
changed: [centos-7]

PLAY RECAP *********************************************************************************************************************
centos-7                   : ok=3    changed=2    unreachable=0    failed=0   

       *************** AnsiblePush end run *******************
       Downloading files from <ansiblepush-centos-7>
       Finished converging <ansiblepush-centos-7> (0m13.31s).
-----> Setting up <ansiblepush-centos-7>...
       Finished setting up <ansiblepush-centos-7> (0m0.00s).
-----> Verifying <ansiblepush-centos-7>...
       Loaded tests from {:path=>".Users.aa220269.repo.repo-test.cookbooks.ansible2inspec.test.integration.default"} 

Profile: tests from {:path=>"/Users/aa220269/repo/repo-test/cookbooks/ansible2inspec/test/integration/default"} (tests from {:path=>".Users.aa220269.repo.repo-test.cookbooks.ansible2inspec.test.integration.default"})
Version: (not specified)
Target:  ssh://kitchen@localhost:32774

  System Package tree
     ✔  should be installed

Test Summary: 1 successful, 0 failures, 0 skipped
       Finished verifying <ansiblepush-centos-7> (0m0.53s).
       Finished testing <ansiblepush-centos-7> (0m15.44s).
-----> Kitchen is finished. (0m18.52s)


$ kitchen list 
Instance              Driver  Provisioner  Verifier  Transport  Last Action  Last Error
ansiblepush-centos-7  Docker  AnsiblePush  Inspec    Ssh        Verified     <None>


$ kitchen exec -c 'sudo rpm -q tree'
-----> Execute command on ansiblepush-centos-7.
       tree-1.6.0-10.el7.x86_64
```

##補足

対象ノードを変更するには、.kitchen.ymlのdriver:を変更する。
proxy driverを使用すると稼働中の既存serverを対象とすることが可能。
- 参考 : [Chef ServerやKinfe-Zeroを必要としない、ChefDKよるリモートノードへのChef適用
](https://qiita.com/hiroyuki_onodera/items/18d450b0c568af3d1e2e)