The following document is intended to be a quick guide to getting you setup for doing local development with Chef. This guide was created on my MacBook, but should work fine with Linux, and Windows workstations as well.
- Workstation - A workstation is a computer that is configured to run various Chef command-line tools that synchronize with a chef-repo, author cookbooks, interact with the Chef server, interact with nodes, or applications like Chef Delivery
- Node - A node is any machine—physical, virtual, cloud, network device, etc.—that is under management by Chef.
- Chef Server- The Chef server acts as a hub for configuration data. The Chef server stores cookbooks, the policies that are applied to nodes, and metadata that describes each registered node that is being managed by the chef-client.
- Resources - The fundamental building block of chef describing something you want to configure like a
package
,template
, orservice
, and the state that it is in - Recipes - An ordered list of resources
- Cookbooks - A collection of resources and their supporting files. Typically map 1:1 to something you want to configure (i.e.
mysql_cookbook
,httpd_cookbook
,sensu_cookbook
) - Environments - Environments can be created to reflect each organization’s patterns and workflow. For example, creating
production
,staging
,testing
, anddevelopment
environments. - Roles - A role is a way to define certain patterns and processes that exist across nodes in an organization as belonging to a single job function. Each role consists of zero (or more) attributes and a run-list. Each node can have zero (or more) roles assigned to it. When a role is run against a node, the configuration details of that node are compared against the attributes of the role, and then the contents of that role’s run-list are applied to the node’s configuration details. When a chef-client runs, it merges its own attributes and run-lists with those contained within each assigned role.
- Data Bags - A data bag is a global variable that is stored as JSON data and is accessible from a Chef server. A data bag is indexed for searching and can be loaded by a recipe or accessed during a search.
In order to get going you are going to need to install the following software on your local workstation.
- Chef Development Kit (ChefDK)
- Vagrant
- VirtualBox
- Programmer's Text editor like Atom, Sublime Text 2, or Notepad++
Once installed validate your installation by running the following commands*
$ chef -v
Chef Development Kit Version: 0.15.16
chef-client version: 12.11.18
delivery version: master (444effdf9c81908795e88157f01cd667a6c43b5f)
berks version: 4.3.5
kitchen version: 1.10.0
$ vagrant -v
Vagrant 1.8.4
$ VBoxManage -v
5.0.24r108355
- Validation steps were tested on MacOS. Commands may not work on Windows and Linux.
If you are new to Chef or software development for that matter it is probably a good idea to create a working directory for all of your source code. I use a folder called src
in my home directory (i.e. /Users/scottford/src
).
Open up the command terminal on your workstation (Powershell, Cmd, Terminal, iTerm, Bash, etc), change directory into your source directory and run the following command:
$ chef generate cookbook <COMPANY_NAME>_httpd
NOTE: I created a chef_httpd
cookbook so my examples from here on out will reference that cookbook name
$ cd chef_httpd
Open your text editor and open the folder for the cookbook you created. Doing this will allow you to see the entire contents of the httpd cookbook.
Test Kitchen is a test harness tool to execute your configured code on one or more platforms in isolation. A driver plugin architecture is used which lets you run your code on various cloud providers and virtualization technologies such as Amazon EC2, Blue Box, CloudStack, Digital Ocean, Rackspace, OpenStack, Vagrant, Docker, LXC containers, and more. Many testing frameworks are already supported out of the box including Inspec, Bats, shUnit2, RSpec, Serverspec, with others being created weekly.
The .kitchen.yml
file found inside the cookbook folder we just created when we ran chef generate cookbook
is the configuration file for Test Kitchen. It is here where you can set the driver you want to use, what platforms you need to support, testing frameworks, as well as the Chef run_list
you want Test Kitchen to run.
The first thing you should note is that the file is .yml
, which can be a little finicky if you have not worked with it before. You must NOT USE TABS, spaces only!
Very briefly we can cover the 4 main sections you're likely to find in a .kitchen.yml file:
driver
: This is where we configure the behaviour of the Kitchen Driver - the component that is responsible for creating a machine that we'll use to test our cookbook. Here we set up basics like credentials, ssh usernames, sudo requirements, etc. Each Driver is responsible for requiring and using the configuration here. Under this section we havedriver.name
: This tells Test Kitchen that we want to use thekitchen-vagrant
driver by default unless otherwise specified.provisioner
: This tells Test Kitchen how to run Chef, to apply the code in our cookbook to the machine under test. The default provisioner ischef_zero
which creates a small in memory Chef Server.platforms
: This is a list of operation systems on which we want to run our code. Note that the operating system's version, architecture, cloud environment, etc. might be relevant to what Test Kitchen considers a Platform.suites
: This section defines what we want to test. It includes the Chefrun-list
and any node attribute setups that we want run on each Platform above. For example, we might want to test the MySQL client cookbook code separately from the server cookbook code for maximum isolation.
Copy/Paste the following into your .kitchen.yml
---
driver:
name: vagrant
## The private_network feature lets you setup a private network on the VM guest
## via localhost on the host.
## see also: https://www.vagrantup.com/docs/networking/private_network.html
network:
- ["private_network", {ip: "33.33.33.33"}]
provisioner:
name: chef_zero
## The verifier section determines which test platform you want to use.
verifier:
name: inspec
format: doc
platforms:
- name: centos-6.7
suites:
- name: default
run_list:
- recipe[chef_httpd::default]
attributes:
Running the command kitchen list
lists out your configuration. It also validates the file. If you get any errors you most likely have a formatting error. Try copying/pasting from the example above.
$ kitchen list
Instance Driver Provisioner Verifier Transport Last Action
default-centos-67 Vagrant ChefZero Inspec Ssh <Not Created>
The kitchen create
command launches a VM using the driver configured. In our example we are using Vagrant to launch a VM locally. The first time you launch a specified platform you will need to pull down the Vagrant box file locally which is stored in ~/.vagrant.d/boxes
. Each subsequent launch of that platform will use the locally stored file.
$ kitchen create
-----> Starting Kitchen (v1.10.0)
-----> Creating <default-centos-67>...
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'bento/centos-6.7'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'bento/centos-6.7' is up to date...
==> default: A newer version of the box 'bento/centos-6.7' is available! You currently
==> default: have version '2.2.5'. The latest is version '2.2.7'. Run
==> default: `vagrant box update` to update.
==> default: Setting the name of the VM: kitchen-chef_httpd-default-centos-67_default_1467922394968_13785
...
-----> Kitchen is finished. (0m37.77s)
Running kitchen list
now shows the Last Action
as Created
.
$ kitchen list
Instance Driver Provisioner Verifier Transport Last Action
default-centos-67 Vagrant ChefZero Inspec Ssh Created
You now can actually login to your running VM with the command kitchen login
and execute commands just as you would on any other RHEL/CentOS system.
$ kitchen login
Last login: Thu Jul 7 20:13:57 2016 from 10.0.2.2
[vagrant@default-centos-67 ~]$ cat /etc/redhat-release
CentOS release 6.7 (Final)
[vagrant@default-centos-67 ~]$ exit
logout
Connection to 127.0.0.1 closed.
Running kitchen converge
checks to see that the box has been created, installs Chef on the target platform, and then runs chef-client
runs the run_list
for the suite.
$ kitchen converge
-----> Starting Kitchen (v1.10.0)
-----> Converging <default-centos-67>...
Preparing files for transfer
Preparing dna.json
Resolving cookbook dependencies with Berkshelf 4.3.5...
Removing non-cookbook files before transfer
Preparing validation.pem
Preparing client.rb
-----> Installing Chef Omnibus (install only if missing)
Downloading https://omnitruck.chef.io/install.sh to file /tmp/install.sh
Trying wget...
Download complete.
el 6 x86_64
Getting information for chef stable for el...
downloading https://omnitruck.chef.io/stable/chef/metadata?v=&p=el&pv=6&m=x86_64
to file /tmp/install.sh.3080/metadata.txt
...
Installing chef
installing with rpm...
...
Thank you for installing Chef!
Transferring files to <default-centos-67>
Starting Chef Client, version 12.12.13
Creating a new client identity for default-centos-67 using the validator key.
resolving cookbooks for run list: ["chef_httpd::default"]
Synchronizing Cookbooks:
- chef_httpd (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 0 resources
Running handlers:
Running handlers complete
Chef Client finished, 0/0 resources updated in 02 seconds
Finished converging <default-centos-67> (0m22.80s).
-----> Kitchen is finished. (0m25.76s)
Running kitchen list
now shows the Last Action
as Converged
$ kitchen list
Instance Driver Provisioner Verifier Transport Last Action
default-centos-67 Vagrant ChefZero Inspec Ssh Converged
Open up recipes\default.rb
#
# Cookbook Name:: chef_httpd
# Recipe:: default
#
# Copyright (c) 2015 The Authors, All Rights Reserved.
package 'httpd' do
action :install
end
service 'httpd' do
action [:start, :enable]
end
$ kitchen converge
-----> Starting Kitchen (v1.4.2)
-----> Converging <default-centos-71>...
...
Synchronizing Cookbooks:
- chef_httpd (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 2 resources
Recipe: chef_httpd::default
* yum_package[httpd] action install
- install version 2.2.15-53.el6.centos of package httpd
* service[httpd] action enable
- enable service service[httpd]
* service[httpd] action start
- start service service[httpd]
Running handlers:
Running handlers complete
Chef Client finished, 3/3 resources updated in 10 seconds
Finished converging <default-centos-67> (0m21.02s).
Open up a browser and go to http://33.33.33.33 to see the default configuration page for the Apache Webserver.
While it is nice that we can validate our webserver manually, wouldn't it be better to do our validation in an automated fashion? We can!
We are going to use a testing framework called Inspec
(Infrastructure Specification) to test the configuration of our webserver.
$ chef gem install inspec
Successfully installed inspec-0.26.0
1 gem installed
Open up your terminal again and change directory into your cookbook. Create a directory to store your your Inspec tests.
$ mkdir -p test/integration/default/inspec
In your editor, create a new file test/integration/default/inspec/default_spec.rb
and add the following test
describe port(80) do
it { should be_listening }
end
$ kitchen verify
-----> Starting Kitchen (v1.10.0)
-----> Setting up <default-centos-67>...
Finished setting up <default-centos-67> (0m0.00s).
-----> Verifying <default-centos-67>...
Detected alternative framework tests for `inspec`
Detected alternative framework tests for `serverspec`
Use `/Users/scottford/src/chef_httpd/test/integration/default/inspec` for testing
Port 80
should be listening
Finished in 0.12748 seconds (files took 1.18 seconds to load)
1 example, 0 failures
Finished verifying <default-centos-67> (0m1.01s).
-----> Kitchen is finished. (0m3.00s)
$ kitchen destroy