Testing infrastructure with Test Kitchen for Chef and Beaker for Puppet

Test Kitchen is a central tool in the Chef ecosystem as it enables thorough testing of infrastructure code and plays very well with a lot of other tools we already use and know. It takes the strong testing culture from the development world and applies it to an infrastructure-as-code environment. Test Kitchen helps start an isolated system environment, apply Chef cookbooks to it, and then execute tests. Supported test frameworks include RSpec, ServerSpec, or Bats (and more), with a large choice of supported environments such as AWS, Vagrant, Digital Ocean, Docker, and OpenStack. Test Kitchen integrates very well with Berkshelf, so cookbook dependencies aren't an issue while testing complex infrastructures. The best part is, it's already included in the Chef DK, so we just have to use it.

In this section, we'll structure everything needed to properly test our Chef cookbooks code using Vagrant with CentOS 7.2

Note

The Test Kitchen version in use in the Chef DK at the time of writing is 1.13.2.

Getting ready

To step through this recipe, you will need the following:

  • A working Chef DK installation on the workstation
  • A working Vagrant installation on the workstation
  • The Chef code from Chapter 6, Fundamentals of Managing Servers with Chef and Puppet, or any custom Chef code

How to do it…

Test Kitchen is configured by a single .kitchen.yml file at the root of the cookbook. It contains a lot of information:

  • How to test the system (Vagrant, by default)
  • How to provision the system (chef-solo, chef-zero, or other modes)
  • Which platforms to test (Ubuntu 16.04, CentOS 7.2, or other distributions)
  • The test suites (what to apply, where to find information, in what context, and similar information)

Configuring Test Kitchen

Irrespective of whether we already have a .kitchen.yml file or not, let's open it and fill in the following details:

  • We want to run the tests with Vagrant to closely simulate a VM in production
  • We want to provision using Chef Zero (by simulating a Chef server locally)
  • We want to test only on CentOS 7.2 (our code isn't currently designed to run on something else)
  • We want a single suite of tests, with a run list of the mysite::default recipe, and a path to the Data Bags

This is how our .kitchen.yml file looks for the mysite cookbook:

---
driver:
  name: vagrant

provisioner:
  name: chef_zero

platforms:
  - name: centos-7.2

suites:
  - name: default
    data_bags_path: "../../data_bags"
    run_list:
      - recipe[mysite::default]
    attributes:

Testing with Test Kitchen

To simply launch Test Kitchen with the specified configuration, execute the following command:

$ kitchen test
-----> Testing <default-centos-72>
-----> Creating <default-centos-72>...
[...]
       Finished creating <default-centos-72> (1m1.51s).
-----> Converging <default-centos-72>...
[...]
-----> Installing Chef Omnibus (install only if missing)
[...]
       resolving cookbooks for run list: ["mysite::default"]
       Synchronizing Cookbooks:
         - apache (0.5.0)
         - php (0.2.0)
         - selinux (0.9.0)
         - yum-mysql-community (1.0.0)
         - mysite (0.3.1)
         - mysql (8.0.4)
         - yum (4.0.0)
[...]
       Chef Client finished, 41/56 resources updated in 02 minutes 47 seconds
       Finished converging <default-centos-72> (3m18.96s).
-----> Setting up <default-centos-72>...
       Finished setting up <default-centos-72> (0m0.00s).
-----> Verifying <default-centos-72>...
       Preparing files for transfer
       Transferring files to <default-centos-72>
       Finished verifying <default-centos-72> (0m0.00s).
-----> Destroying <default-centos-72>...
       ==> default: Stopping the VMware VM...
       ==> default: Deleting the VM...
       Vagrant instance <default-centos-72> destroyed.
       Finished destroying <default-centos-72> (0m28.38s).
       Finished testing <default-centos-72> (4m48.86s).
-----> Kitchen is finished. (4m50.01s)

What happened here is the following:

  • Test Kitchen read the .kitchen.yml file
  • Test Kitchen created the Vagrant VM with the specified image
  • Test Kitchen installed Chef, synchronized the cookbooks, solved dependencies with Berkshelf, and applied the run_list content
  • Test Kitchen launched tests (we don't have any for now)
  • Test Kitchen destroyed the VM as everything went smoothly

How it works…

When we execute the simple kitchen test command, we are in fact running through five steps:

  1. kitchen create: This creates the virtual testing environment (in our case, through Vagrant and an hypervisor), but does not provision it.
  2. kitchen converge: This provisions the instance with the suite information from the .kitchen.yml we created. As we're using Test Kitchen with Chef, it starts by installing Chef and then resolves cookbook dependencies for us. Then it applies run_list with the requested Chef mode (chef-zero in our case).
  3. kitchen setup: This installs any additional plugin we might need.
  4. kitchen verify: This first installs everything needed to run the tests—in our case, this will be ServerSpec.
  5. kitchen destroy: If all tests pass, this step destroys the testing environment.

We highly recommend that you use each command sequentially for debugging purposes.

For reference, as this will all be discussed in the next section, all tests are located in the test/integration/<suite_name>/<plugin_name> folder. In other words, the test/integration/default/serverspec/virtualhost_spec.rb file will match the Chef cookbook recipe named virtualhost, executed from the default Kitchen test suite, and tested with the serverspec plugin.

There's more…

The counterpart for Puppet is Beaker. The development of Beaker is very active, and the current version (6.x) needs at least Ruby 2.2.5. In order to use the Embedded Ruby provided by Puppet Collections, let's stay on the 5.x branch:

$ sudo puppet resource package beaker-rspec 
provider=puppet_gem ensure=5.6.0

Note

A C/C++ compiler is needed to install Beaker, so install gcc/g++ or clang before trying to install beaker-rspec. The Zlib library is also needed (binaries and headers).

We also need another gem containing helpers: beaker-puppet_install_helper. This gem is mainly used to install Puppet in boxes during tests:

$ sudo puppet resource package beaker-puppet_install_helper provider=puppet_gem

We first need to define a list of supported platforms for running test acceptances. Each platform must be defined in a YAML file in spec/acceptance/nodesets. Since our code only works on Ubuntu, let's define a single platform in spec/acceptance/nodesets/default.yml:

HOSTS:
  ubuntu-1604-x64:
    roles:
      - agent
      - default
    platform: ubuntu-16.04-amd64
    hypervisor: vagrant
    box: bento/ubuntu-16.04
CONFIG:
  type: foss

As you can see, we will use Vagrant as hypervisor, with an Ubuntu Xenial box.

Note

type: foss means that the open source edition of Puppet will be used.

Now we can run Beaker:

$ rake beaker
/opt/puppetlabs/puppet/bin/ruby -I/opt/puppetlabs/puppet/lib/ruby/gems/2.1.0/gems/rspec-support-3.6.0.beta1/lib:/opt/puppetlabs/puppet/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta1/lib /opt/puppetlabs/puppet/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta1/exe/rspec --pattern spec/acceptance --color
No examples found.
Finished in 0.00081 seconds (files took 0.14125 seconds to load)
0 examples, 0 failures

No acceptance test has been defined yet, but we will see how to write one in the next pages.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.12.3