
The concept of
infrastructure as code allows us to apply to the infrastructure solutions from the world of development. Individual infrastructure components in projects are often repeated. When integrating such components, the most convenient option is general kukbuki. Code kukbukov constantly changing, fix bugs, there is a new functionality. With the help of testing, we monitor regressions, control backward compatibility and implement new features faster.
In this article we will get acquainted with the tools for testing, we will write a simple kukbook and a test for it.
')
What we test
First we need to decide on what we will test.
- Ruby Style Guide . In the Ruby world, there is no style guide from the language developers, but there is a style guide from the community . Since the code of the cookbooks is written in ruby, it is good to follow the practices that are already in the community;
- Cookbook linter. During the existence of the chef, a large number of patterns and anti-patterns have accumulated, they must be considered when writing the book;
- Integration testing . After making changes, it is necessary to check the performance of the kukbuk, boundary conditions and integration with other kukbuk.
Ruby Style Guide
To check ruby for compliance with the style guide, use the
Rubocop utility.
The utility is
installed by the
gem install rubocop command , you can check the code with the '
rubocop '
command. ', most errors can be fixed automatically, for this you need to use the
-a option.
If you need to disable some checks for some files, you need to create a
.rubocop.yml file and specify exceptions in it.
Example. For all subdirectories in the
test directory, disable the method length check for the
spec_helper.rb file
:MethodLength: Exclude: - 'test/**/spec_helper.rb'
Cookbook linter
Kukbuk style and identification of known errors is carried out using the utility
Foodcritic . The utility is
installed by the
gem install foodcritic command , run by the
foodcritic command
<path to the cookbook>Work example:
foodcritic . FC017: LWRP does not notify when updated: ./providers/default.rb:32
In case Foodcritic has found some problems, there are instructions for correcting them on the project site
http://acrmp.imtqy.com/foodcritic/ .
Integration testing
For integration testing, Chef has released the
Test Kitchen utility,
http://kitchen.ci . This utility prepares the test environment and runs your tests. In the simple case, Test Kitchen starts the virtual machine, starts the chef-client in it, and after passing the chef-run runs the tests.
Virtual machines are started via Vagrant. Anything that supports Vagrant can be used as a hypervisor. In addition to using virtual machines, Test Kitchen can work with public and private clouds.
Tests can be written using various frameworks. Out of the box, Bats, shUnit2, RSpec and Serverspec are supported. Test language Bash (Bats, shUnit2) or Ruby (RSpec, Serverspec). At the same time, the same kukbook can be tested under different operating systems and with different sets of tests.
Testing with Test Kitchen
In order to write tests and generally work with chef cookbooks in the modern world, the
Chef Development Kit is used . ChefDK installs its own installation of the ruby language and all the gems that are needed to work chef. Thus, the installation of chef will not depend on your system cuts, this will avoid many problems with cross-dependencies of gems and so on.
ChefDK itself includes chef and most of the necessary gems. If there is not enough of a heme, then it can be installed with the command:
chef gem install <heme name> .
Download ChefDK for your platform here:
https://downloads.chef.io/chef-dk/Test Kukbook
To teach testing, we will write a simple
deploy-user kukbook that will create a user
deployer and a home directory / home / deployer. In real life, to create users, you can (and should) use the already prepared
community kukbuks.
To generate the Kukbook skeleton, use the following command:
chef generate cookbook deploy-user . At the output we will get the deploy-user directory with a kukbook.
how to generate a skeleton?Historically, an empty kukbook could be created by a team.
knife cookbook create <name>
- This command creates a cookie in the directory that is specified in the settings of the knife, does not create a skeleton of tests, does not create a chefignore file, does not create a git repository, but creates many extra directories for all chef entities. Although, in the 2010th year, and it was very cool =)
berks cookbook <name>
- creates a skeleton using the berkshelf utility (this is like a bundler in the ruby world)
chef generate cookbook <name>
- creates a skeleton using the chef utility from ChefDK.
berks cookbook and chef generate do about the same thing. The difference in the details that we will not consider in this article. In any case, you can always add / remove what you need.
In the end, you can write a simple Thor / Rack task, which will take into account all your wishes.
Create the
attributes directory and the
default.rb file in it. In the file default.rb, we define variables with the name of the user and his shell.
attributes / default.rb :
default['deploy-user']['username'] = 'deployer' default['deploy-user']['shell'] = '/bin/bash'
In the
recipes / default.rb file,
let's call the standard user resource and pass it our parameters.
recipes / default.rb :
user node['deploy-user']['username'] do shell node['deploy-user']['shell'] supports manage_home: true end
For our example of such a simple kukbuk will be quite enough.
kitchen.yml
The entire configuration of Test Kitchen is described by a single .kitchen.yml file. We already have this file, it was generated by the
chef utility.
Let's go over the contents of .kitchen.yml.
The config is divided into sections, each section is responsible for different aspects of the testing process.
Default
.kitchen.yml :
--- driver: name: vagrant provisioner: name: chef_zero platforms: - name: ubuntu-12.04 - name: centos-6.5 suites: - name: default run_list: - recipe[deploy-user::default] attributes:
The
driver section describes the parameters of the virtual machine driver. In the simple case, we use Vagrant.
In the
provisioner section, we specify who will execute the code for the test book. In the case of Chef, there are two options, chef-solo and chef-zero. In the modern world, using chef-solo without much need is not required. You can also specify some additional options, for example, which version of Chef to install. If your Kukbook does not work with Chef 12, then you can explicitly specify the version of
require_chef_omnibus: 11.18.6 .
The
platforms section describes on which OS our kookbook will be tested. For example, you can add Ubuntu 14.04 as follows: '
- name: ubuntu-14.04 '.
IMPORTANT for each driver and platform, there are different default vagrant boxes. If you need to change the default settings, then the driver must pass the appropriate command.
Example: Parallels Desktop hypervisor and custom box.
platforms: - name: ubuntu-14.04 driver: provider: parallels box: express42/ubuntu-14.04
With such a record (
company / image ), the image is taken from
https://atlas.hashicorp.com , you can simply specify the url of the box via the
box_url option.
Finally, the
suites section describes a set of recipes that must be completed before running the tests. We have one suite named default. It describes the run-list with one recipe
deploy-user :: default . This is the recipe in which we described the creation of a user.
Work with Test Kitchen
Now let's see what we can do with our kitchen.
You can view the list of machines and their status using the
kitchen list command. Note that we have described only one suite, so only two machines will be created: default-ubuntu-1404 and default-centos-70. If we described another suite, the number of cars would double. The final number of machines is equal to: the number of
suites multiplied by the number of
platformsWith the
kitchen converge command, we will start creating virtual machines and launching all suites for all platforms. You can run one suite on one platform like this:
kitchen converge default-ubuntu-1404 . To remove all the machines and return everything as there was a
kitchen destroy command.
After running
kitchen converge, we’ll get running virtual machines with the
default.rb recipe from our
deploy-user kukbook.
If there are errors in the codebook code, the chef-run will be interrupted and the place in the code that caused the error will be shown. We believe that the chef-run was successful =). Next, let's check if the suite really worked properly and did what we expected from it. Use the
kitchen login default-ubuntu-1404 command to
log in to one of the machines.
Run the command
getent passwd deployer :
deployer:x:1001:1001::/home/deployer:/bin/bash
Indeed, user deployer is created, the correct home directory is used and the shell we need is used.
Now we’ll check that the user has created the home directory and has the correct owner, group and access rights:
ls -lah / home / deployer / .
drwxr-xr-x 2 deployer deployer 4096 Mar 15 23:12 . drwxr-xr-x 4 root root 4096 Mar 15 23:12 .. -rw-r--r-- 1 deployer deployer 220 Apr 8 2014 .bash_logout -rw-r--r-- 1 deployer deployer 3637 Apr 8 2014 .bashrc -rw-r--r-- 1 deployer deployer 675 Apr 8 2014 .profile
Indeed, the home directory exists and has the right owner, group and access rights.
Hooray, now you can test kukbuki!
Joke =)
Testing
To run the tests, there are two commands
kitchen verify and
kitchen test .
kitchen verify puts the framework for testing inside vm and runs your tests. You can edit your tests and re-run
verify .
kitchen test starts a full test cycle. First
, the kitchen destroy is executed , if the machine was previously created, then the suites are executed, tests are run and at the end sometimes the destroy is executed. By default, destroy is made if tests are successful. This behavior can be overridden using the
kitchen test command options.
Nowadays, kukbuki is usually tested by the Serverspec framework,
http://serverspec.org . Serverspec is an RSpec extension that provides convenient primitives for server testing. With the release of serverspec, people stopped writing tests on pure RSpec (as on bash).
If we start the
kitchen verify now , we will see that an empty test was written for us:
deploy-user::default does something (PENDING: Replace this with meaningful tests) Pending: (Failures listed here are expected and do not affect your suite's status) 1) deploy-user::default does something # Replace this with meaningful tests # /tmp/busser/suites/serverspec/default_spec.rb:8 Finished in 0.00185 seconds (files took 0.3851 seconds to load) 1 example, 0 failures, 1 pending Finished verifying <default-ubuntu-1404> (0m36.87s).
Open the file
test / integration / default / serverspec / default_spec.rb and write a test on our kukbook:
require 'spec_helper' describe 'deploy-user::default' do describe user('deployer') do it { should exist } it { should have_home_directory '/home/deployer' } it { should have_login_shell '/bin/bash' } end describe file('/home/deployer') do it { should be_directory } it { should be_mode 755 } it { should be_owned_by 'deployer' } it { should be_grouped_into 'deployer' } end end
The code describes the actions that we did on the machine manually.
The user
deployer must exist, have the home directory
/ home / deployer , and have shell
/ bin / bash .
/ home / deployer must be a directory, have 755 access rights, the owner of the
deployer, and the
deployer group.
If we are not mistaken anywhere, the result of
kitchen verify will be as follows:
deploy-user::default User "deployer" should exist should have home directory "/home/deployer" should have login shell "/bin/bash" File "/home/deployer" should be directory should be mode 755 should be owned by "deployer" should be grouped into "deployer" Finished in 0.10972 seconds (files took 0.306 seconds to load) 7 examples, 0 failures Finished verifying <default-ubuntu-1404> (0m1.92s).
Hooray, now you can test kukbuki!
Bonus Unit testing
In the world of ches, unit testing also exists. It uses the chefspec tool,
http://sethvargo.imtqy.com/chefspec/ . The main difference from testing through Test Kitchen is that the creation of virtual machines and the launch of the chef-run does not occur. Instead, a call to the resource with the required parameters is checked. This can be useful when some resources cannot be tested in the usual way. For example, if the performance of the resource depends on the external system or requires specific equipment. Well, such tests can be run in any CI system. Of the minuses worth noting that in this way is difficult to test LWRP.
An example of such a test can be found below.
spec / unit / recipes / default_spec.rb require 'spec_helper' describe 'deploy-user::default' do let(:chef_run) do runner = ChefSpec::ServerRunner.new runner.converge(described_recipe) end it 'converges successfully' do chef_run
If in the file
spec / spec_helper.rb add the line
at_exit {ChefSpec :: Coverage.report! } , after the end of the tests, the percentage of coverage will be displayed.
You can run these tests with the chef exec rspec -c command
.. Finished in 0.51553 seconds (files took 3.34 seconds to load) 2 examples, 0 failures ChefSpec Coverage report generated... Total Resources: 1 Touched Resources: 1 Touch Coverage: 100.0% You are awesome and so is your test coverage! Have a fantastic day!
Useful documentation