Running `service` resources in Kitchen-Docker
When writing cookbooks, you need to actually test that they work. This is often done using Test Kitchen, a tool that allows you to converge your cookbooks on a real machine. There are a number of drivers that can be used, such as kitchen-vagrant and kitchen-docker.
For instance, I run against Docker due to its incredible speed compared to running on a virtual machine, and also due to the fact that this means I can use Docker with GitLab CI.
Getting kitchen-docker set up
For instance, let's assume we have a
.kitchen.yml configured to use Vagrant as a driver:
driver: name: docker provisioner: name: chef_zero # You may wish to disable always updating cookbooks in CI or other testing environments. # For example: # always_update_cookbooks: <%= !ENV['CI'] %> always_update_cookbooks: true verifier: name: inspec platforms: - name: debian driver_config: image: debian:jessie suites: - name: default run_list: - recipe[cookbook::default] verifier: inspec_tests: - test/smoke/default attributes:
However, when running any of the kitchen commands, you may encounter the following error:
$ kitchen list >>>>>> ------Exception------- >>>>>> Class: Kitchen::UserError >>>>>> Message: You must first install the Docker CLI tool http://www.docker.io/gettingstarted/ >>>>>> ---------------------- >>>>>> Please see .kitchen/logs/kitchen.log for more details >>>>>> Also try running `kitchen diagnose --all` for configuration
This is due to the Docker driver not being able to correctly find the CLI tool. An easy fix is to add the following to our
driver section in the
driver: name: docker + # make kitchen detect the Docker CLI tool correctly, via + # https://github.com/test-kitchen/kitchen-docker/issues/54#issuecomment-203248997 + use_sudo: false
Running service commands
Next, we want to be able to interact with services via Chef's
service resources. Trying to interface with a service in a Docker container results in the following error:
$ sudo systemctl restart mysql Failed to get D-Bus connection: Operation not permitted
This is due to the whole point of docker containers running a single application. When trying to interface with a
service, this requires a full init system, with multiple processes running on top of it. This means that you're using Docker for something it's not built for (out of the box).
Therefore, you need to extend the Docker container to have its own init system, as well as giving it root access across the host system: that is, this new container that is meant to be separate, and have its own nicely sandboxed resources will have root access to your machine. Be aware of the security risks this can cause on your machine - I have no responsibility for issues caused.
Following the advice in Stack Overflow: Kitchen-Docker and Systemd:
driver: name: docker # make kitchen detect the Docker CLI tool correctly, via # https://github.com/test-kitchen/kitchen-docker/issues/54#issuecomment-203248997 use_sudo: false + run_command: /bin/systemd + cap_add: + - SYS_ADMIN + volume: + - /sys/fs/cgroup
run_command defines what command should be run by the container, which in this case would be systemd, the init system used by Debian Jessie.
As mentioned, we also need to give it the
SYS_ADMIN capability, which gives it root access across the machine.