When you want to test the integration of your snowflake data into your environments you should consider KitchenCI.
You should understand Test Driven Development with RSpec and Chef to such a degree that you have exhausted it as a resource. In that post we created a set of acceptance criteria and tests that support a user generating a file at a specific location containing a specific string of text. We are at a state where we can rely on the mechanics of the recipe … we know we can pass a string and have it show up in the intended file.
These RSpec tests provide assertions against generic data that we don’t want in production. When it comes time to validate the data that you will be using in a production or staging environment you hit scenarios where the data is unique per environment. These are our data separation principles in action. We can build seemingly unique environments simply by replacing data into the consistent structure. Test Kitchen helps us tremendously with these tasks.
Create a Test
The integration tests get stored in a slightly different location than the tests we wrote previously. A good first step is creating a spec helper file at test/integration/slogan/serverspec/spec_helper.rb. Executing the command serverspec-init generates the content of the file for us.
require 'serverspec'
include SpecInfra::Helper::Exec
include SpecInfra::Helper::DetectOS
RSpec.configure do |c|
if ENV['ASK_SUDO_PASSWORD']
require 'highline/import'
c.sudo_password = ask("Enter sudo password: ") { |q| q.echo = false }
else
c.sudo_password = ENV['SUDO_PASSWORD']
end
end
With the helper file in place, we can now address the previous two assertions.
As a result, we want to ensure the new tests that we add are unique in focus. Most code will travel through multiple environments like development, qa, staging, production etc. Our next test will be the equivallent of “Writes the slogan file to my development location.” The test is saved as test/integration/slogan/serverspec/slogan_spec.rb.
require 'spec_helper'
describe file('/etc/development_slogan') do
it { should be_file }
end
Kitchen Testing Suites
KitchenCI contains testing suites, which are a collection of meta data specific to that test. It has several ways of exposing data to your tests that can include the use of roles, data bags that can tie into your production chef servers or directly through json in a .kitchen.yml file. This functionality helps distributed teams work intelligently by integrating tightly with “real” data.
The data integration is why we are here, but let’s start with the basics and get to a state where we can run our failing test. Add the following to .kitchen.yml.
require 'spec_helper'
suites:
- name: slogan
run_list:
- recipe[nmdbase::slogan]
attributes: {
"nmdbase": {
"slogan": {
"path": "/etc/development_slogan"
}
}
}
Executing kitchen list shows us that the slogan suite is now available:
$ bundle exec kitchen list
Instance Driver Provisioner Last Action
slogan-ubuntu-1204 Vagrant ChefSolo
default-ubuntu-1204 Vagrant ChefSolo
ldap-ubuntu-1204 Vagrant ChefSolo
yubico-ubuntu-1204 Vagrant ChefSolo
yubico-ldap-ubuntu-1204 Vagrant ChefSolo
Kitchen Converge
When Kitchen performs a converge, it gathers all of your latest code, cookbooks, data, etc and creates a vagrant instance for each suite specified that has this information available to chef. It tells chef to perform a client run and configure the VM accordingly. Executing kitchen commands directly will leave the instance running for you to access. Executing kitchen commands from Rake will destroy the instance making it a suitable approach for continuous integration efforts. If you are familiar with vagrant, this is the equivalent of a vagrant up followed by a vagrant provision.
$ bundle exec kitchen converge slogan-ubuntu-1204
-----> Starting Kitchen (v1.2.1)
-----> Converging ...
Preparing files for transfer
Resolving cookbook dependencies with Berkshelf 2.0.16...
Removing non-cookbook files before transfer
Transfering files to
[2014-05-12T16:50:43+00:00] INFO: Forking chef instance to converge...
Starting Chef Client, version 11.10.4
[2014-05-12T16:50:43+00:00] INFO: *** Chef 11.10.4 ***
[2014-05-12T16:50:43+00:00] INFO: Chef-client pid: 20426
[2014-05-12T16:50:43+00:00] INFO: Setting the run_list to ["recipe[nmdbase::slogan]"] from JSON
[2014-05-12T16:50:43+00:00] INFO: Run List is [recipe[nmdbase::slogan]]
[2014-05-12T16:50:43+00:00] INFO: Run List expands to [nmdbase::slogan]
[2014-05-12T16:50:43+00:00] INFO: Starting Chef Run for slogan-ubuntu-1204
[2014-05-12T16:50:43+00:00] INFO: Running start handlers
[2014-05-12T16:50:43+00:00] INFO: Start handlers complete.
Compiling Cookbooks...
Converging 1 resources
Recipe: nmdbase::slogan
* template[/etc/development_slogan] action create[2014-05-12T16:50:44+00:00] INFO: Processing template[/etc/development_slogan] action create (nmdbase::slogan line 21)
[2014-05-12T16:50:44+00:00] INFO: template[/etc/development_slogan] created file /etc/development_slogan
- create new file /etc/development_slogan[2014-05-12T16:50:44+00:00] INFO: template[/etc/development_slogan] updated file contents /etc/development_slogan
- update content in file /etc/development_slogan from none to 081034
--- /etc/development_slogan 2014-05-12 16:50:44.040987721 +0000
+++ /tmp/chef-rendered-template20140512-20426-16ghydx 2014-05-12 16:50:44.040987721 +0000
@@ -1 +1,4 @@
+# This file was generated by Chef for slogan-ubuntu-1204.vagrantup.com
+# Do NOT modify this file by hand!
+I am verifying variables are used properly.[2014-05-12T16:50:44+00:00] INFO: template[/etc/development_slogan] owner changed to 0
[2014-05-12T16:50:44+00:00] INFO: template[/etc/development_slogan] group changed to 0
[2014-05-12T16:50:44+00:00] INFO: template[/etc/development_slogan] mode changed to 644
- change mode from '' to '0644'
- change owner from '' to 'root'
- change group from '' to 'root'
[2014-05-12T16:50:44+00:00] INFO: Chef Run complete in 0.101614243 seconds
Running handlers:
[2014-05-12T16:50:44+00:00] INFO: Running report handlers
Running handlers complete
[2014-05-12T16:50:44+00:00] INFO: Report handlers complete
Chef Client finished, 1/1 resources updated in 0.465135306 seconds
Finished converging (0m5.16s).
-----> Kitchen is finished. (0m6.23s)
Looking at kitchen list reflects the new status of this instance.
bundle exec kitchen list
Instance Driver Provisioner Last Action
slogan-ubuntu-1204 Vagrant ChefSolo Converged
default-ubuntu-1204 Vagrant ChefSolo
ldap-ubuntu-1204 Vagrant ChefSolo
yubico-ubuntu-1204 Vagrant ChefSolo
yubico-ldap-ubuntu-1204 Vagrant ChefSolo
At this point we have full access to the instance, as it is configured. We can log in and poke around to our hearts content. Being able to do this is a total distraction from our TDD approach, but it’s good to know that you have the option if you need it.
bundle exec kitchen login slogan-ubuntu-1204
Welcome to Ubuntu 12.04.4 LTS (GNU/Linux 3.11.0-15-generic i686)
* Documentation: https://help.ubuntu.com/
Last login: Mon May 12 16:52:54 2014 from 192.168.26.1
root@slogan-ubuntu-1204:/home/vagrant# ls -l /etc/development_slogan
-rw-r--r-- 1 root root 150 May 12 16:52 /etc/development_slogan
Kitchen Verify
Once the server is converged we can verify that it is configured the way we expect.
$ bundle exec kitchen verify slogan-ubuntu-1204
-----> Starting Kitchen (v1.2.1)
-----> Verifying ...
Removing /tmp/busser/suites/serverspec
Uploading /tmp/busser/suites/serverspec/slogan_spec.rb (mode=0644)
Uploading /tmp/busser/suites/serverspec/spec_helper.rb (mode=0644)
-----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/serverspec/slogan_spec.rb --color --format documentation
File "/etc/development_slogan"
should be file
Finished in 0.0327 seconds
1 example, 0 failures
Finished verifying (0m1.34s).
-----> Kitchen is finished. (0m2.39s)
Conclusion
This shows you how to work with your infrastructure from an integration perspective. The next step will continue on these concepts by introducing data_bags.