Ansible Playbook検証環境構築 (Windows10 + KitchenCI + Docker)

#目的
Windows + kitchenCI + docker環境でansible playbookのテストを行う場合の選択肢としては以下の2つがある。

- kitchen-ansibleを使用

対象にansibleを導入してローカル適用を行う
コントローラーノードのファイルをcopyするなどの操作ができない

- kitchen-ansiblepushを使用

コントローラーノードにansibleを導入してsshにて適用
ansibleとしては本来の使用方法となるが、windowsに直接ansibleを導入することが困難

ここでは、ansibleを導入したdockerコンテナ(D1)から、kitchen-ansiblepushを利用したtest-kitchenにより、別のdocker環境(D2)を起動してansible playbookを適用させるKitchenCI環境を構築する例を示します。
なお、docker.sockのマウントによりコンテナ内からdockerを呼び出しているので、セキュリティ的なリスクがありうることにはご注意下さい。

[MAC版はこちら](https://qiita.com/hiroyuki_onodera/items/e915c873340cf059dae0)


## 環境

- Windows10 Pro: 1909
- Docker Desktop on Windows: Docker version 19.03.5, build 633a0ea
- Chef Workstation: 0.11.21
- git for windows: git version 2.25.1.windows.1


## 前提

- 操作はgit bash環境で実行する
- Docker for windowsを設定済み
- Gitを設定済み


## test-kitchen, InSpec (Chef Workstation)の設定

```
$ echo "eval \"\$(/c/opscode/chef-workstation/bin/chef shell-init bash | sed -e 's|C:|/c|g' -e 's|\\|/|g' -e 's|;|:|g')\"" >> ~/.bash_profile
$ . ~/.bash_profile
```
パスなどの設定を行う


## kitchen-ansible, kitchen-dockerの導入


```
$ gem install kitchen-ansible
$ gem install kitchen-docker
```
docker controllerコンテナ環境D1を作成するためにkitchen-ansibleを使用する。


## サンプルをgit clone

```
$ git clone git@github.com:hiroyuki-onodera/ansible-testenv-windows.git
$ cd ansible-testenv-windows.git
```


## Docker環境D1(ansible controller)構成用ファイル

### kitchen.yml (ansible controller構成用)

```yaml:kitchen.yml
driver:
  name: docker
  run_options: >-
    -v //var/run/docker.sock:/var/run/docker.sock
    -v /usr/local/bin/docker:/bin/docker
    -v <%= ENV['PWD'] %>/repo:/home/kitchen/repo
  socket: npipe:////./pipe/docker_engine

provisioner:
  name: ansible_playbook
  chef_bootstrap_url: nil
  hosts: ansible-controller
  playbook: site.yml

platforms:
  - name: centos-7

suites:
  - name: ansible-controller
```

### site.yml (ansible controller構成用)

```yaml:site.yml
- hosts: all
  gather_facts: false
  become: true
  become_user: kitchen
  tasks:
  - name: install the chef-workstation rpm from a remote repo
    become_user: root
    yum:
      name: https://packages.chef.io/files/stable/chef-workstation/0.11.21/el/7/chef-workstation-0.11.21-1.el7.x86_64.rpm

  - name: add 'eval "$(chef shell-init bash)"' to ~/.bash_profile
    lineinfile:
      dest: ~/.bash_profile
      line: eval "$(chef shell-init bash)"

  - name: gem install
    shell: |
      set -e
      . ~/.bash_profile
      gem install kitchen-ansiblepush
      gem install kitchen-docker

```




## Docker環境D1(ansible controller)構成

```
$ kitchen test -d never
```
数分かかる。
ansible, test-kitchen, InSpec, kitchen-ansiblepush, kitchen-docker が導入され、./repo/sampleが共有されたcentos7のdockerコンテナが立ち上がる。

## ansible controller環境にログインし､サンプルの設定ファイルを確認

```
$ kitchen login
Last login: Fri Mar  6 11:46:15 2020 from 172.17.0.1



[kitchen@8b85d4a98c06 ~]$ cd repo/sample/



[kitchen@8b85d4a98c06 sample]$ ls
kitchen.yml  site.yml  test
```

ここで~kitchen/repoは、Windows上の./repoの共有デバイス



### repo/sample/kitchen.yml

kitchenCI設定ファイル
git cloneの対象



```yaml:repo/sample/kitchen.yml
---
driver:
  name: docker
  use_sudo: true
  use_internal_docker_network: true

provisioner:
  name: ansible_push
  chef_bootstrap_url: nil

platforms:
- name: centos-7

suites:
- name: ansiblepush
  provisioner:
    playbook: ./site.yml

verifier:
  name: inspec
  inspec_tests:
  - test/integration/default
```



### repo/sample/site.yml

ユーザーfooを追加するplaybook
git cloneの対象


```yaml:repo/sample/site.yml
---
- hosts: all
  gather_facts: false
  become: true
  tasks:
  -
    user:
      name: foo
```


### repo/sample/test/integration/default/default_test.rb
InSpec test
ここではユーザーfooの存在を確認
git cloneの対象


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

describe user('foo') do
  it { should exist }
end
```



## kitchenCIを回し、環境D2を構成し、Ansible playbookのsite.ymlを適用


なお、

- $ kitchen test にて、対象環境構成、ansible playbook適用、verify、対象環境削除 が一括で可能。
- $ kitchen test -d never にて、対象環境構成、ansible playbook適用、verify が一括で可能。


```
[kitchen@8b85d4a98c06 sample]$ kitchen converge
-----> Starting Test Kitchen (v2.3.4)
-----> Creating <ansiblepush-centos-7>...
       Sending build context to Docker daemon  15.87kB
       Step 1/17 : FROM centos:centos7
        ---> 5e35e350aded
...
       *************** AnsiblePush run ***************

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

TASK [user] **************************************************************************************************************************************************
changed: [centos-7]

PLAY RECAP ***************************************************************************************************************************************************
centos-7                   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

       *************** AnsiblePush end run *******************
       Downloading files from <ansiblepush-centos-7>
       Finished converging <ansiblepush-centos-7> (0m3.94s).
-----> Test Kitchen is finished. (0m7.26s)
```

changed=1 は、ユーザー追加によるシステム変更を示している。


## 作成された環境D2に対してInSpec Testを実行

```
[kitchen@8b85d4a98c06 sample]$ kitchen verify
-----> Starting Test Kitchen (v2.3.4)
-----> Setting up <ansiblepush-centos-7>...
       Finished setting up <ansiblepush-centos-7> (0m0.00s).
-----> Verifying <ansiblepush-centos-7>...
       Loaded tests from {:path=>".home.kitchen.repo.sample.test.integration.default"}

Profile: tests from {:path=>"/home/kitchen/repo/sample/test/integration/default"} (tests from {:path=>".home.kitchen.repo.sample.test.integration.default"})
Version: (not specified)
Target:  ssh://kitchen@172.17.0.3:22

  User foo
     ✔  should exist

Test Summary: 1 successful, 0 failures, 0 skipped
       Finished verifying <ansiblepush-centos-7> (0m0.96s).
-----> Test Kitchen is finished. (0m3.28s)


[kitchen@8b85d4a98c06 sample]$ kitchen list
Instance              Driver  Provisioner  Verifier  Transport  Last Action  Last Error
ansiblepush-centos-7  Docker  AnsiblePush  Inspec    Ssh        Verified     <None>
```

InSpec TestによりUser fooの存在が確認された

## 環境D2にログインして確認

```
[kitchen@8b85d4a98c06 sample]$ kitchen login
Last login: Fri Mar  6 11:50:30 2020 from 172.17.0.2


[kitchen@d99a512d8465 ~]$ grep foo /etc/passwd
foo:x:1001:1001::/home/foo:/bin/bash


[kitchen@d99a512d8465 ~]$ logout
Connection to 172.17.0.3 closed.
```

## 環境D2の削除

```
[kitchen@8b85d4a98c06 sample]$ kitchen destroy
-----> Starting Test Kitchen (v2.3.4)
-----> Destroying <ansiblepush-centos-7>...
       PID                 USER                TIME                COMMAND
       22231               root                0:00                /usr/sbin/sshd -D -o UseDNS=no -o UsePAM=no -o PasswordAuthentication=yes -o UsePrivilegeSeparation=no -o PidFile=/tmp/sshd.pid
       d99a512d84657b1dc5b1d1a0eff8298fadd26d3009fe32b6496a2cf25ff36592
       d99a512d84657b1dc5b1d1a0eff8298fadd26d3009fe32b6496a2cf25ff36592
       Finished destroying <ansiblepush-centos-7> (0m0.47s).
-----> Test Kitchen is finished. (0m2.81s)
```


## 環境D1の削除

```
[kitchen@8b85d4a98c06 sample]$ logout
Connection to localhost closed.


$ kitchen destroy
-----> Starting Test Kitchen (v2.3.4)
-----> Destroying <ansible-controller-centos-7>...
       PID                 USER                TIME                COMMAND
       21479               root                0:00                /usr/sbin/sshd -D -o UseDNS=no -o UsePAM=no -o PasswordAuthentication=yes -o UsePrivilegeSeparation=no -o PidFile=/tmp/sshd.pid
       8b85d4a98c067c99a20d2163d9e04cad63718c537d9506921004f8203fc61589
       8b85d4a98c067c99a20d2163d9e04cad63718c537d9506921004f8203fc61589
       Finished destroying <ansible-controller-centos-7> (0m2.21s).
-----> Test Kitchen is finished. (0m3.71s)
```