SlideShare uma empresa Scribd logo
1 de 415
Baixar para ler offline
v0.0.1
Testing Your
Automation Code
Mischa Taylor (@misheska)
misheska@getchef.com
Copyright (C) 2014 Chef Software, Inc.
1
Wednesday, April 30, 14
v2.0.0
Why Are You Here?
2
Wednesday, April 30, 14
3
You’ve used and want to
bulletproof
your so that
you are with
Spec
Wednesday, April 30, 14
In this class
• We’ll add tests to the apache cookbook from the
Fundamentals Course
• We’ll show you how to run cookbooks in a sandbox
environment mirroring production with Test
Kitchen
• We’ll show you how to detect suspicious cookbook
code with Foodcritic & RuboCop
• We’ll show you how to produce runnable
documentation with ChefSpec
4
Wednesday, April 30, 14
Using Chef is half the battle
5
“Chef is like....
tests for your infrastructure”
-Ezra Zygmuntowicz, Co-Founder EngineYard
http://www.akitaonrails.com/2008/6/5/railsconf-2008-brazil-rails-podcast-special-edition#.U0HfiF7Ed-8
Wednesday, April 30, 14
Chef makes things more testable
• Chef automates infrastructure in a repeatable
fashion
6
Wednesday, April 30, 14
What’s the other half of the battle?
7
“Have a plan”
-Adam Jacob, Co-Founder Chef
Wednesday, April 30, 14
There’s no more magic to testing
8
http://www.flickr.com/photos/dkeats/4128747046/sizes/s/in/photostream/
Wednesday, April 30, 14
You Are The Testing A-Team When...
9
Wednesday, April 30, 14
Recommended plan
• Build in quality and robustness up front
10
https://flic.kr/p/8W67ZC
Wednesday, April 30, 14
Otherwise you could...
• Verify and validate just before going to production
until time runs out. But time always runs out
11
http://mrg.bz/iEr1oj
Wednesday, April 30, 14
Waiting to test when it’s “done”
12
Intention:
Reality:
Build Test Deploy
Build
T
es
De
ploy
We’re late
no time
to test!
Wednesday, April 30, 14
13
Wednesday, April 30, 14
14
Wednesday, April 30, 14
Bake testing in earlier
15
Shorter cycles,
to start testing early as possible:
Build Test Deploy Build Test Deploy Build Test Deploy
Wednesday, April 30, 14
Penny saved with testing
16
Up Front Testing Saves Money
https://www.flickr.com/people/68751915@N05/
Wednesday, April 30, 14
Cost of change
17
Wednesday, April 30, 14
Test arrangement
• Arrange tests to get feedback fast - at the earliest
possible time
18
seconds
minutes
hours
Foodcritic/Rubocop
ChefSpec
Serverspec
Wednesday, April 30, 14
Reason for multiple tools
• Finding a bug in something that you can’t execute
is freaking hard!
• While fixing bugs before writing code is cheap,
finding them is expensive
19
Wednesday, April 30, 14
The Tools
• Each tool is specialized to give feedback as early
as possible during the cookbook authoring process
20
Wednesday, April 30, 14
What each tool does
• In your text editor when you type in cookbook code:
• Foodcritic analyzes your Chef style
• RuboCop analyzes your Ruby coding technique
• Before you deploy to a test node:
• ChefSpec helps you document and organize your
code
• After you deploy to a test node:
• Serverspec verifies a cookbook behaves as intended
21
Wednesday, April 30, 14
v2.0.0
Legend
22
Wednesday, April 30, 14
Legend: Do I run that command on my workstation?
$ whoami
i-am-a-workstation
This is an example of a command to run on your workstation
user@hostname:~$ whoami
i-am-a-chef-node
This is an example of a command to run on your target node via SSH.
23
Wednesday, April 30, 14
$ ifconfig
Legend: Example Terminal Command and Output
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
! options=3<RXCSUM,TXCSUM>
! inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
! inet 127.0.0.1 netmask 0xff000000
! inet6 ::1 prefixlen 128
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
! ether 28:cf:e9:1f:79:a3
! inet6 fe80::2acf:e9ff:fe1f:79a3%en0 prefixlen 64 scopeid 0x4
! inet 10.100.0.84 netmask 0xffffff00 broadcast 10.100.0.255
! media: autoselect
! status: active
p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
! ether 0a:cf:e9:1f:79:a3
! media: autoselect
! status: inactive
24
Wednesday, April 30, 14
OPEN IN EDITOR:
SAVE FILE!
~/hello_world
Hi!
I am a friendly file.
Legend: Example of editing a file on your workstation
25
Wednesday, April 30, 14
v2.0.0
Training Environment
(CloudShare)
26
Wednesday, April 30, 14
CloudShare Node
• Register and login to CloudShare (see invite)
• Start Using This Environment
27
Wednesday, April 30, 14
Two Virtual Machines
28
Wednesday, April 30, 14
Two Virtual Machines
29
We’ll just use the Ubuntu
w/Docker image
Wednesday, April 30, 14
30
The Ubuntu w/Docker
VM
will be your
Chef Development
Workstation
for this class
Wednesday, April 30, 14
CloudShare Development Workstation
31
Wednesday, April 30, 14
CloudShare Node
32
Wednesday, April 30, 14
$ ssh sysadmin@<EXTERNAL_ADDRESS>
Lab - Login
The authenticity of host 'uvo1qrwls0jdgs3blvt.vm.cld.sr
(69.195.232.110)' can't be established.
RSA key fingerprint is d9:95:a3:b9:02:27:e9:cd:
74:e4:a2:34:23:f5:a6:8b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'uvo1qrwls0jdgs3blvt.vm.cld.sr,
69.195.232.110' (RSA) to the list of known hosts.
chef@uvo1qrwls0jdgs3blvt.vm.cld.sr's password:
Last login: Mon Jan 6 16:26:24 2014 from
host86-145-117-53.range86-145.btcentralplus.com
[chef@CentOS63 ~]$
33
Wednesday, April 30, 14
Checkpoint
• At this point you should have
• One virtual machine (VM) or server that you’ll use
for the lab exercises
• The IP address or public hostname
• An application for establishing an ssh connection
• 'sudo' or 'root' permissions on the VM
34
Wednesday, April 30, 14
v2.0.0
Workstation Setup - Linux
(Docker)
Getting started
35
Wednesday, April 30, 14
Base OS Install
• Ubuntu and Enterprise Linux support the kernel
extensions needed for Docker (64-bit only).
• Ubuntu is recommended if you are using a VM. The
Enterprise Linux package uses the 3.14 kernel which
has issues working with the VMware and VirtualBox
guest tools.
36
Wednesday, April 30, 14
Base OS Install
• Recommended Packer templates for building the
base OS with Docker:
• Ubuntu Server:
https://github.com/misheska/basebox-packer/blob/
master/template/ubuntu/ubuntu1204-docker.json
• Vagrant Cloud:
vagrant	
  init	
  learningchef/ubuntu1204-­‐docker
37
Wednesday, April 30, 14
Install Chef
• Install Chef (if not already installed)
http://www.getchef.com/chef/install
38
Wednesday, April 30, 14
Install Chef Client
39
Wednesday, April 30, 14
Install on Linux
40
Wednesday, April 30, 14
$ curl -L http://www.getchef.com/chef/install.sh | sudo bash
Workstation Setup - Linux
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 14398 100 14398 0 0 56535 0 --:--:-- --:--:-- --:--:-- 78250
Downloading Chef for ubuntu...
Installing Chef
installing with dpkg...
Selecting previously unselected package chef.
(Reading database ... 78644 files and directories currently
installed.)
Unpacking chef (from .../chef_11.12.2-1_amd64.deb) ...
Setting up chef (11.12.2-1) ...
Thank you for installing Chef!
41
Wednesday, April 30, 14
What just happened?
• Chef and all of its dependencies installed via an
operating system-specific package ("omnibus installer")
• Installation includes
• The Ruby language - used by Chef
• knife - Command line tool for administrators
• chef-client - Client application
• ohai - System profiler
• ...and more
42
Wednesday, April 30, 14
OPEN IN EDITOR: $HOME/.bash_profile
export PATH="/opt/chef/embedded/bin:$PATH"
Add Chef Client to PATH
43
Wednesday, April 30, 14
$ source $HOME/.bash_profile
Make the profile active
44
Wednesday, April 30, 14
$ which ruby
Check the PATH setting
/opt/chef/embedded/bin/ruby
45
Wednesday, April 30, 14
$ chef-client --version
Verify Install
Chef: 11.12.2
46
Wednesday, April 30, 14
Install Developer Tools
• Install Developer Tools to build native extensions
47
http://patshaughnessy.net/2011/10/31/dont-be-terrified-of-building-native-extensions
Wednesday, April 30, 14
Install Developer Tools
• Use build-essential cookbook:
https://github.com/opscode-cookbooks/build-
essential
48
Wednesday, April 30, 14
$ mkdir /tmp/cookbooks
Temporary area for cookbook downloads
49
Wednesday, April 30, 14
$ cd /tmp/cookbooks
Easiest to go to cookbooks dir
50
Wednesday, April 30, 14
$ knife cookbook site download build-essential
$ tar xvf build-essential-*.tar.gz
Download build-essential cookbook
51
Wednesday, April 30, 14
$ cd /tmp
$ sudo chef-client -z -o build-essential
Use local mode to run cookbook
52
Wednesday, April 30, 14
$ gcc --version
Verify Install
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
53
Wednesday, April 30, 14
$ cd /tmp/cookbooks
Easiest to go to cookbooks dir
54
Wednesday, April 30, 14
$ knife cookbook site download git
$ knife cookbook site download dmg
$ knife cookbook site download windows
$ knife cookbook site download runit
$ knife cookbook site download yum
$ knife cookbook site download yum-epel
$ knife cookbook site download chef_handler
Download git cookbook + dependencies
55
Wednesday, April 30, 14
$ tar xvf git*.tar.gz
$ tar xvf dmg*.tar.gz
$ tar xvf windows*.tar.gz
$ tar xvf runit*.tar.gz
$ tar xvf yum-3*.tar.gz
$ tar xvf yum-epel*.tar.gz
$ tar xvf chef_handler*.tar.gz
Extract cookbook archives
56
Wednesday, April 30, 14
$ cd /tmp
$ sudo chef-client -z -o git
Use local mode to run cookbook
57
Wednesday, April 30, 14
$ git --version
Verify Install
git version 1.7.9.5
58
Wednesday, April 30, 14
$ rm -rf /tmp/cookbooks
Keep it neat
59
Wednesday, April 30, 14
v2.0.0
Our Source
60
Wednesday, April 30, 14
chef-fundamentals-repo
• We’re going to build on the chef-fundamentals-
repo created in the Chef Fundamentals training,
adding tests:
https://github.com/learnchef/chef-fundamentals-repo/
tree/master/cookbooks/apache
61
Wednesday, April 30, 14
$ cd $HOME
Home directory - great place for source
62
$ cd %USERPROFILE%
Wednesday, April 30, 14
$ git clone https://github.com/learnchef/chef-fundamentals-repo.git
Grab the chef-fundamentals repo from GitHub
Cloning into 'chef-fundamentals-repo'...
remote: Reusing existing pack: 247, done.
remote: Total 247 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (247/247), 149.52 KiB | 184.00 KiB/s,
done.
Resolving deltas: 100% (45/45), done.
Checking connectivity... done.
63
Wednesday, April 30, 14
$ cd chef-fundamentals-repo
chef-fundamentals-repo
64
!"" Berksfile
!"" cookbooks/
!"" data_bags/
!"" environments/
!"" .git/
!"" README.md
!"" roles/
#"" Vagrantfile
Wednesday, April 30, 14
v2.0.0
Reviewing Cookbooks with
Test Kitchen (Docker Version)
65
Wednesday, April 30, 14
Apache Clowns & Bears
• We’ll be focusing on the Apache Clowns and
Bears cookbook in:
chef-­‐fundamentals-­‐repo/cookbooks/apache
66
Wednesday, April 30, 14
Cookbook Review with Test Kitchen
• Test Kitchen is a great environment in which to
develop and review cookbooks
• Written by Fletcher Nichol
67
Wednesday, April 30, 14
Back in my day...
• Running a cookbook
involved a lot of setup:
• Configure workstation
• Configure Chef Server
• Bootstrap node
68
Wednesday, April 30, 14
No longer a chore
• Test Kitchen lets you set up sandbox environments
in which to run cookbooks right on your Chef
development workstation
69
Wednesday, April 30, 14
Supported Environments
• Test Kitchen supports:
• Virtual Machines
• Cloud Instances
• Metal - Physical Servers
• Containers (Docker, LXC, etc.)
70
Wednesday, April 30, 14
Sandbox Benefits
• A sandbox environment:
• Is a safe place to make mistakes
• Easily reset to a clean config
• Can simulate production
71
Wednesday, April 30, 14
Virtual Machines vs. Containers
72
Hypervisor/Host OS
Guest OS
Core OS
Guest OS Guest OS
App App App
App App App
Virtual Machines Containers
Wednesday, April 30, 14
73
Test Kitchen is
packaged as a
Ruby Gem
Wednesday, April 30, 14
Ruby Gem
• A gem is a application or supporting library
written in ruby, installable with:
74
gem	
  install
Wednesday, April 30, 14
$ sudo gem install test-kitchen --no-ri --no-rdoc
Install Test Kitchen
75
$ sudo env "PATH=$PATH"
gem install test-kitchen --no-ri --no-rdoc
Run As
Administrator
> gem install test-kitchen --no-ri --no-rdoc
Wednesday, April 30, 14
Install Test Kitchen
76
Fetching: net-scp-1.1.2.gem (100%)
Fetching: safe_yaml-1.0.2.gem (100%)
Fetching: thor-0.19.1.gem (100%)
Fetching: test-kitchen-1.2.1.gem (100%)
Successfully installed net-scp-1.1.2
Successfully installed safe_yaml-1.0.2
Successfully installed thor-0.19.1
Successfully installed test-kitchen-1.2.1
4 gems installed
Text
Output:
Wednesday, April 30, 14
OPEN IN EDITOR: $HOME/.gemrc
gem: --no-ri --no-rdoc
Automatically add --no-ri & --no-rdoc
77
Wednesday, April 30, 14
$ cd $HOME/chef-fundamentals-repo/cookbooks/apache
Go to Apache cookbook dir
78
Wednesday, April 30, 14
79
We’re going to
need a lot of gems
Wednesday, April 30, 14
Gemfile
• A Gemfile can be used to list all the gems you need
for cookbook testing
80
Wednesday, April 30, 14
Gemfile template
• Test Kitchen can generate a Gemfile template
(among other things)
81
Wednesday, April 30, 14
$ kitchen init --driver=kitchen-docker --create-gemfile
create .kitchen.yml
create test/integration/default
create Gemfile
append Gemfile
append Gemfile
You must run ‘bundle install’ to fetch any new gems.
Create Gemfile template
82
Wednesday, April 30, 14
chef-fundamentals-repo/cookbooks/apache/Gemfile
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-docker'
83
Wednesday, April 30, 14
$ kitchen init --driver=kitchen-docker --create-gemfile
create .kitchen.yml
create test/integration/default
create Gemfile
append Gemfile
append Gemfile
You must run ‘bundle install’ to fetch any new gems.
Create Gemfile template
84
Wednesday, April 30, 14
85
Wednesday, April 30, 14
86
Gemfile is read by:
bundle	
  install
to install gems
Wednesday, April 30, 14
87
No need to install bundler
• Chef install includes the bundler gem
• Outside the Chef install, bundler can be installed via:
•gem	
  install	
  bundler
Wednesday, April 30, 14
$ bundle install --path vendor/bundle
Do what Test Kitchen tells you
Fetching gem metadata from https://rubygems.org/..........
Fetching gem metadata from https://rubygems.org/..
Installing mixlib-shellout (1.3.0)
Installing net-ssh (2.8.0)
Installing net-scp (1.1.2)
Installing safe_yaml (1.0.2)
Installing thor (0.19.1)
Installing test-kitchen (1.2.1)
Installing kitchen-docker (1.0.0)
Using bundler (1.1.5)
Your bundle is complete! It was installed into ./vendor/bundle
88
Wednesday, April 30, 14
89
Vendor Everything
• Gems change frequently and sometimes conflict
• -­‐-­‐path option passed to bundle	
  install
overrides system gems by installing Gemfile gems
locally
• Bundler docs recommend using vendor/bundle
Wednesday, April 30, 14
90
If you vendor gems use:
bundle	
  exec
to read gems in
vendor/bunde
Wednesday, April 30, 14
91
Test Kitchen commands
• Let’s cover a few essential Test Kitchen commands
Wednesday, April 30, 14
92
kitchen list
• kitchen	
  list prints out a list of sandbox instances
defined in .kitchen.yml
Wednesday, April 30, 14
$ bundle exec kitchen list
kitchen list
Instance Driver Provisioner Last Action
default-ubuntu-1204 Docker ChefSolo <Not Created>
default-centos-64 Docker ChefSolo <Not Created>
93
Wednesday, April 30, 14
94
kitchen create
• kitchen	
  create	
  <instance_name> spins up a
sandbox instance
Wednesday, April 30, 14
$ bundle exec kitchen create default-centos-64
kitchen create
-----> Starting Kitchen (v1.2.1)
-----> Creating <default-centos-64>...
Step 0 : FROM centos:6.4
---> 539c0211cd76
Step 1 : RUN yum clean all
---> Using cache
---> 9a4da62cec5e
...
"Links": null,
"PublishAllPorts": false
}
}]
Finished creating <default-centos-64> (0m4.55s).
-----> Kitchen is finished. (0m4.66s)
95
Wednesday, April 30, 14
96
kitchen login
• kitchen	
  login	
  <instance_name> uses ssh to
login to the sandbox instance
Wednesday, April 30, 14
$ bundle exec kitchen login default-centos-64
kitchen login
kitchen@localhost's password:
[kitchen@fc9834984e9d ~]$ cat /etc/redhat-release
CentOS release 6.4 (Final)
[kitchen@fc9834984e9d ~]$ exit
logout
Connection to localhost closed.
97
Default password is kitchen
Wednesday, April 30, 14
98
kitchen destroy
• kitchen	
  destroy	
  <instance_name> shuts down a
sandbox instance and destroys and virtual resources
allocated
Wednesday, April 30, 14
$ bundle exec kitchen destroy default-centos-64
kitchen destroy
-----> Starting Kitchen (v1.2.1)
-----> Destroying <default-centos-64>...
3d71e7241e317d374f42ac0fc79c0752cb77eb86b4bfd76c068beebdb151dda3
3d71e7241e317d374f42ac0fc79c0752cb77eb86b4bfd76c068beebdb151dda3
Finished destroying <default-centos-64> (0m2.90s).
-----> Kitchen is finished. (0m3.07s)
99
Wednesday, April 30, 14
100
kitchen	
  converge
performs a Chef run
in the sandbox instance
Wednesday, April 30, 14
$ bundle exec kitchen converge default-centos-64
Perform Chef run
-----> Starting Kitchen (v1.2.1)
-----> Creating <default-centos-64>...
Step 0 : FROM centos:6.4
---> 539c0211cd76
Step 1 : RUN yum clean all
---> Using cache
---> 735ba0db794e
....
101
Wednesday, April 30, 14
$ bundle exec kitchen converge default-centos-64
Perform Chef run
-----> Starting Kitchen (v1.2.1)
-----> Creating <default-centos-64>...
Step 0 : FROM centos:6.4
---> 539c0211cd76
Step 1 : RUN yum clean all
---> Using cache
---> 735ba0db794e
....
[2014-04-07T02:32:50-04:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited
unsuccessfully (exit code 1)
>>>>>> Converge failed on instance <default-centos-64>.
>>>>>> Please see .kitchen/logs/default-centos-64.log for more details
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: SSH exited (1) for command: [sudo -E chef-solo --config /tmp/kitchen/solo.rb --json-
attributes /tmp/kitchen/dna.json --log_level info]
>>>>>> ----------------------
102
FAILWednesday, April 30, 14
103
Our first bit of feedback!
Wednesday, April 30, 14
104
Wednesday, April 30, 14
105
Undefined attribute
• When you see undefined	
  method	
  ‘[]’	
  for	
  
nil:NilClass it often means you have an
undefined attribute
• Let’s see if node["motd"]["company"] is being set
Wednesday, April 30, 14
cookbooks/apache/attributes/default.rb
106
default["apache"]["indexfile"] = "index1.html"
default["apache"]["sites"]["clowns"] = { "port"
=> 80 }
default["apache"]["sites"]["bears"] = { "port"
=> 81 }
NOPEWednesday, April 30, 14
107
Undefined attribute
• How is ["motd"]["company"] set in the motd
cookbook?
Wednesday, April 30, 14
cookbooks/motd/attributes/default.rb
108
default["motd"]["company"] = "Chef"
Wednesday, April 30, 14
Good cookbooks
• Good cookbooks can be used in isolation
• They set reasonable defaults for all attributes used
• Test Kitchen is designed to run a cookbook in
isolation to give you feedback on attribute use
109
Wednesday, April 30, 14
Test attributes
• We won’t fix the motd cookbook in this class
• Test Kitchen supports injection of test attributes
• We’ll supply the correct attribute in
the .kitchen.yml configuration file
110
Wednesday, April 30, 14
Default .kitchen.yml
111
---
driver:
name: docker
provisioner:
name: chef_solo
platforms:
- name: ubuntu-12.04
- name: centos-6.4
suites:
- name: default
run_list:
- recipe[apache::default]
attributes:
Wednesday, April 30, 14
.kitchen.yml is a tab-free zone
• Spacing matters in a .kitchen.yml file.
• .kitchen.yml is a tab-free zone - you will get errors
if you try to use tabs. Set your editor accordingly.
112
Wednesday, April 30, 14
---
driver:
name: docker
provisioner:
name: chef_solo
platforms:
- name: ubuntu-12.04
- name: centos-6.4
suites:
- name: default
run_list:
- recipe[apache::default]
attributes:
motd: {company: Chef}
cookbooks/apache/.kitchen.yml
Set node[“motd”][“company”] (docker)
113
OPEN IN EDITOR:
Wednesday, April 30, 14
$ bundle exec kitchen converge default-centos-64
Perform Chef run
-----> Starting Kitchen (v1.2.1)
-----> Converging <default-centos-64>...
Preparing files for transfer
Preparing current project directory as a cookbook
Removing non-cookbook files before transfer
Transfering files to <default-centos-64>
[2014-04-07T02:40:01-04:00] INFO: Forking chef instance to
converge...
Starting Chef Client, version 11.10.4
....
114
Wednesday, April 30, 14
$ bundle exec kitchen converge default-centos-64
Perform Chef run
-----> Starting Kitchen (v1.2.1)
-----> Converging <default-centos-64>...
Preparing files for transfer
Preparing current project directory as a cookbook
Removing non-cookbook files before transfer
Transfering files to <default-centos-64>
[2014-04-07T02:40:01-04:00] INFO: Forking chef instance to converge...
Starting Chef Client, version 11.10.4
....
[2014-04-07T02:40:03-04:00] INFO: Report handlers complete
Chef Client finished, 5/10 resources updated in 2.52587913 seconds
Finished converging <default-centos-64> (0m4.15s).
-----> Kitchen is finished. (0m4.22s)
115
WIN
Wednesday, April 30, 14
Where to go next
• Learning Chef book excerpt
was sent to you are part of
the class registration.
• Chapter 1 covers Test
Kitchen and .kitchen.yml
format in more detail.
• Appendix provides
sample .kitchen.yml configs
116
Wednesday, April 30, 14
Where to go next
• Vagrant boxes for training image:
• VirtualBox 4.3.10
https://s3-us-west-2.amazonaws.com/misheska/vagrant/virtualbox4.3.10/ubuntu1204-docker-
chef11.12.2.box
• VMware Fusion 6/Workstation 10
https://s3-us-west-2.amazonaws.com/misheska/vagrant/vmware9.6.1/ubuntu1204-docker-
chef11.12.2.box
• Packer Template
https://github.com/misheska/basebox-packer/blob/master/template/ubuntu/ubuntu1204-docker.json
117
Wednesday, April 30, 14
Gemfile
118
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-vagrant'
Wednesday, April 30, 14
VirtualBox - .kitchen.yml
119
---
driver:
name: vagrant
provisioner:
name: chef_solo
platforms:
- name: ubuntu1204-docker
driver:
box: ubuntu1204-docker
box_url: https://s3-us-west-2.amazonaws.com/misheska/vagrant/
vmware9.6.1/ubuntu1204-docker-chef11.12.2.box
customize:
memory: 1024
suites:
- name: default
Wednesday, April 30, 14
VMware Fusion 6 - .kitchen.yml
120
---
driver:
name: vagrant
provisioner:
name: chef_solo
platforms:
- name: ubuntu1204-docker
driver:
provider: vmware_fusion
box: ubuntu1204-docker
box_url: https://s3-us-west-2.amazonaws.com/misheska/vagrant/
vmware9.6.1/ubuntu1204-docker-chef11.12.2.box
customize:
memory: 1024
suites:
- name: default
Wednesday, April 30, 14
VMware Workstation 10 - .kitchen.yml
121
---
driver:
name: vagrant
provisioner:
name: chef_solo
platforms:
- name: ubuntu1204-docker
driver:
provider: vmware_workstation
box: ubuntu1204-docker
box_url: https://s3-us-west-2.amazonaws.com/misheska/vagrant/
vmware9.6.1/ubuntu1204-docker-chef11.12.2.box
customize:
memory: 1024
suites:
- name: default
Wednesday, April 30, 14
v2.0.0
Automated Verification in
Test Kitchen with Serverspec
(Docker Version)
122
Wednesday, April 30, 14
123
Let’s verify that the Apache cookbook
actually works by
configuring Test Kitchen to allow
web browser access by
the Chef Development workstation
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/.kitchen.yml
---
driver:
name: docker
provisioner:
name: chef_solo
platforms:
- name: centos-6.4
driver_config:
forward:
- 80:80
suites:
- name: default
run_list:
- recipe[apache::default]
attributes:
motd: {company: Chef}
Network config - clowns
124
Wednesday, April 30, 14
$ bundle exec kitchen destroy default-centos-64
Network reconfig requires destroy
-----> Starting Kitchen (v1.2.1)
-----> Destroying <default-centos-64>...
5b88b1806d613be02bfcd14f359c8d9bb1d77f06bbce7e423c0e3100fee73177
5b88b1806d613be02bfcd14f359c8d9bb1d77f06bbce7e423c0e3100fee73177
Finished destroying <default-centos-64> (0m0.47s).
-----> Kitchen is finished. (0m0.53s)
125
Wednesday, April 30, 14
$ bundle exec kitchen converge default-centos-64
Perform Chef run
-----> Starting Kitchen (v1.2.1)
-----> Creating <default-centos-64>...
Step 0 : FROM centos:6.4
---> 539c0211cd76
Step 1 : RUN yum clean all
---> Using cache
---> 735ba0db794e
Step 2 : RUN yum install -y sudo openssh-server openssh-
clients curl
---> Using cache
---> 37c081ac2580
....
126
Wednesday, April 30, 14
Port now forwarded
127
Wednesday, April 30, 14
$ curl localhost:80
Does it blend?
<html>
<body>
<h1>Welcome to Chef</h1>
<h2>We love clowns</h2>
172.17.0.2:80
</body>
</html>
128
Wednesday, April 30, 14
$ curl localhost:80
Does it blend?
<html>
<body>
<h1>Welcome to Chef</h1>
<h2>We love clowns</h2>
172.17.0.2:80
</body>
</html>
129
WIN
Wednesday, April 30, 14
Clowns in your web browser
130
•You can access the clowns web site
using the external address for your
CloudShare workstation
Wednesday, April 30, 14
CloudShare Node
131
Wednesday, April 30, 14
CloudShare Node
132
Wednesday, April 30, 14
http://<EXTERNAL_ADDRESS>
133
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/.kitchen.yml
---
driver:
name: docker
provisioner:
name: chef_solo
platforms:
- name: centos-6.4
driver_config:
forward:
- 80:80
- 81:81
suites:
- name: default
run_list:
- recipe[apache::default]
attributes:
motd: {company: Chef}
Network config - bears
134
Wednesday, April 30, 14
$ bundle exec kitchen destroy default-centos-64
Network reconfig requires destroy
-----> Starting Kitchen (v1.2.1)
-----> Destroying <default-centos-64>...
5b88b1806d613be02bfcd14f359c8d9bb1d77f06bbce7e423c0e3100fee73177
5b88b1806d613be02bfcd14f359c8d9bb1d77f06bbce7e423c0e3100fee73177
Finished destroying <default-centos-64> (0m0.47s).
-----> Kitchen is finished. (0m0.53s)
135
Wednesday, April 30, 14
$ bundle exec kitchen converge default-centos-64
Perform Chef run
-----> Starting Kitchen (v1.2.1)
-----> Creating <default-centos-64>...
Step 0 : FROM centos:6.4
---> 539c0211cd76
Step 1 : RUN yum clean all
---> Using cache
---> 735ba0db794e
Step 2 : RUN yum install -y sudo openssh-server openssh-clients curl
---> Using cache
---> 37c081ac2580
....
[2014-04-07T03:06:36-04:00] INFO: Report handlers complete
Chef Client finished, 11/11 resources updated in 24.32934282 seconds
Finished converging <default-centos-64> (0m38.09s).
-----> Kitchen is finished. (0m38.33s)
136
Wednesday, April 30, 14
Both ports forwarded
137
Wednesday, April 30, 14
$ curl localhost:81
Does it blend?
<html>
<body>
<h1>Welcome to Chef</h1>
<h2>We love bears</h2>
172.17.0.2:81
</body>
</html>
138
Wednesday, April 30, 14
Very nice!
139
Wednesday, April 30, 14
140
Wednesday, April 30, 14
141
Wednesday, April 30, 14
Serverspec author
• Written by Gosuke Miyashita
142
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Gemfile
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'serverspec', '~> 1.1'
Add serverspec to Gemfile
143
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Gemfile
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'serverspec', '~> 1.1'
Add serverspec to Gemfile
144
PessimisticVersion
Constraint
Wednesday, April 30, 14
Version Constraint
145
•If a gem properly follows semantic
versioning with its versioning scheme.
You can take advantage of this to
choose a version constraint to lock
down the gem in your application.
http://guides.rubygems.org/patterns/#declaring_dependencies
Wednesday, April 30, 14
Semantic Versioning
146
Given a version number MAJOR.MINOR.PATCH, increment
the:
1.MAJOR version when you make incompatible API
changes,
2.MINOR version when you add functionality in a backwards-
compatible manner, and
3.PATCH version when you make backwards-compatible bug
fixes.
Additional labels for pre-release and build metadata are
available as extensions to the MAJOR.MINOR.PATCH format.
http://guides.rubygems.org/patterns/#semantic_versioning
Wednesday, April 30, 14
Versioning Example
147
Let’s say the following releases of a gem exist:
■Version 2.1.0 — Baseline
■Version 2.2.0 — Introduced some new (backward
compatible) features.
■Version 2.2.1 — Removed some bugs
■Version 2.2.2 — Streamlined your code
■Version 2.3.0 — More new features (but still backwards
compatible).
■Version 3.0.0 — Reworked the interface. Code written to
version 2.x might not work.
http://guides.rubygems.org/patterns/#semantic_versioning
Wednesday, April 30, 14
Version Constraint
148
gem 'library', '= 2.2.0'
Only use version 2.2.0
Wednesday, April 30, 14
Optimistic Version Constraint
149
gem 'library', '>= 2.2.0'
Assume all changes from 2.x on will
work, including 3.0.0 and higher
Wednesday, April 30, 14
Pessimistic Version Constraint
150
gem 'library', '>= 2.2.0', ‘< 3.0’
Explicitly exclude any versions that might
break your code
Wednesday, April 30, 14
Pessimistic Version Constraint
151
gem 'library', '>= 2.2.0', ‘< 3.0’
Shorthand for:
Using the twiddle-wakka:
gem 'library', '~> 2.2'
Wednesday, April 30, 14
$ bundle install
Install Serverspec
152
$ CONFIGURE_ARGS="--with-ldflags=
'-Wno-error=unused-command-line-argument-hard-error-in-
future'" bundle install
clang 5.1 Workaround
Wednesday, April 30, 14
v2.0.0
RSpec Syntax
153
Wednesday, April 30, 14
Documentation form
154
describe	
  ‘<entity>’	
  do
	
  	
  <descriptions	
  here>
end
Wednesday, April 30, 14
Documentation example
155
describe	
  ‘clowns	
  site’	
  do
	
  	
  ...
end
Wednesday, April 30, 14
Description form
156
describe	
  ‘<entity>’	
  do
	
  	
  it	
  ‘<description>’	
  do
	
  	
  	
  	
  	
  ...
	
  	
  end
end
Wednesday, April 30, 14
Description example
157
describe	
  ‘clowns	
  site’	
  do
	
  	
  it	
  ‘responds	
  on	
  port	
  80’	
  do
	
  	
  	
  	
  ...
	
  	
  end
end
Wednesday, April 30, 14
Expectation form
158
describe	
  ‘<entity>’	
  do
	
  	
  it	
  ‘<description>’	
  do
	
  	
  	
  	
  expect(thing).to	
  eq	
  result
	
  	
  end
end
Wednesday, April 30, 14
Expectation form
159
describe	
  ‘<entity>’	
  do
	
  	
  it	
  ‘<description>’	
  do
	
  	
  	
  	
  expect(thing).to	
  eq	
  result
	
  	
  end
end
Matcher
Wednesday, April 30, 14
Expectation example
160
describe	
  ‘clowns	
  site’	
  do
	
  	
  it	
  ‘responds	
  on	
  port	
  80’	
  do
	
  	
  	
  	
  expect(port	
  80).to	
  be_listening	
  ‘tcp’
	
  	
  end
end
Wednesday, April 30, 14
Expectation form
161
describe	
  ‘<entity>’	
  do
	
  	
  it	
  ‘<description>’	
  do
	
  	
  	
  	
  expect(thing).to	
  eq	
  result
	
  	
  end
end
This is new syntax
Wednesday, April 30, 14
Should vs Expect
162
describe	
  ‘clowns	
  site’	
  do
	
  	
  it	
  ‘responds	
  on	
  port	
  80’	
  do
	
  	
  	
  	
  expect(port	
  80).to	
  be_listening	
  ‘tcp’
	
  	
  end
end
Expect Form
One-Liner Should Form
describe	
  ‘clowns	
  site’	
  do
	
  	
  describe	
  port(80)	
  do
	
  	
  	
  	
  it	
  {	
  should	
  be_listening.with(‘tcp’)	
  }
	
  	
  end
end
Wednesday, April 30, 14
Expect vs. Should
163
Debate on whether or not to use expect vs. should is
epic:
http://myronmars.to/n/dev-blog/2012/06/rspecs-new-
expectation-syntax
...and pointless. Use whatever makes the most sense
to you. There are some technical limitations to the
‘should’ form, but if you stick to the “one-liner should”
syntax, they are essentially interchangeable.
Wednesday, April 30, 14
We Use Expect Form
164
Because all the ChefSpec examples are in the expect
form
Wednesday, April 30, 14
165
Let’s write some serverspec
tests!
Wednesday, April 30, 14
166
Default location for tests
• By default, Test Kitchen will look in the test/
integration directory for test-related files
• For convenience, Test Kitchen creates this directory
when you run kitchen	
  init
Wednesday, April 30, 14
chef-fundamentals-repo
167
.
!"" attributes/
!"" .bundle/
!"" CHANGELOG.md
!"" files/
!"" Gemfile
!"" Gemfile.lock
!"" .kitchen/
!"" .kitchen.yml
!"" metadata.rb
!"" README.md
!"" recipes/
!"" templates/
!"" test/
$   #"" integration/
#"" vendor/
Wednesday, April 30, 14
168
Suite subdirectory
• Test Kitchen requires a few more directories underneath
test/integration
• First directory name underneath test/integration should
match the suite name:
└──	
  test/
	
  	
  	
  	
  └──	
  integration/
	
  	
  	
  	
  	
  	
  	
  	
  └──	
  <suite_name>/
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/.kitchen.yml
---
driver:
name: docker
provisioner:
name: chef_solo
platforms:
- name: centos-6.4
driver_config:
forward:
- 80:80
- 81:81
suites:
- name: default
run_list:
- recipe[apache::default]
attributes:
motd: {company: Chef}
Network configuration
169
Suite name
Wednesday, April 30, 14
170
Suite subdirectory
• Our suite name is default
└──	
  test/
	
  	
  	
  	
  └──	
  integration/
	
  	
  	
  	
  	
  	
  	
  	
  └──	
  default/
Wednesday, April 30, 14
171
Busser directory
• The next directory level denotes the test plugin, as
Test Kitchen many different kinds of test plugins. A test
plugin is called a busser. We’ll be using the busser
directory called serverspec.
└──	
  test/
	
  	
  	
  	
  └──	
  integration/
	
  	
  	
  	
  	
  	
  	
  	
  └──	
  default/
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  └──	
  serverspec/
Wednesday, April 30, 14
172
Hostname directory
• Serverspec supports testing via SSH, so it requires yet
another directory level to denote the hostname. We
won’t be using this capability, so it should be localhost
└──	
  test/
	
  	
  	
  	
  └──	
  integration/
	
  	
  	
  	
  	
  	
  	
  	
  └──	
  default/
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  └──	
  serverspec/
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  └──	
  localhost/
Wednesday, April 30, 14
173
Hostname directory
• NOTE: Use of the localhost directory is optional
Wednesday, April 30, 14
$ cd $HOME/chef-fundamentals-repos/cookbooks/apache
Make sure you are in the apache cookbook root
174
> cd %USERPROFILE%/chef-fundamentals-repos/cookbooks/apache
Wednesday, April 30, 14
$ mkdir -p test/integration/default/serverspec
Create test directory structure
175
> mkdir testintegrationdefaultserverspec
Wednesday, April 30, 14
176
*_spec.rb files
• By convention, Test Kitchen expects files with tests
to end in _spec.rb
Wednesday, April 30, 14
Serverspec expectation form
• Every specialized RSpec-based testing library like
serverspec has their own special twist on the basic
RSpec expectation form
177
Wednesday, April 30, 14
Generic Expectation Form
178
describe	
  ‘<entity>’	
  do
	
  	
  it	
  ‘<description>’	
  do
	
  	
  	
  	
  expect(thing).to	
  eq	
  result
	
  	
  end
end
Wednesday, April 30, 14
Serverspec Command
179
describe	
  ‘<entity>’	
  do
	
  	
  it	
  ‘<description>’	
  do
	
  	
  	
  	
  expect(command).to	
  eq	
  result
	
  	
  end
end
thing to expect
is called a command
in serverspec
Wednesday, April 30, 14
Serverspec commands & matchers
• Serverspec has provides a wide variety of matchers
for each command
• Serverspec commands are well-documented: http://
serverspec.org/resource_types.html
180
Wednesday, April 30, 14
Serverspec resources
181
Wednesday, April 30, 14
Port resource/be_listening matcher
182
Wednesday, April 30, 14
183
Writing your first test
• Let’s create a serverspec test checking to make sure
the clowns web site is active on port 80
• Let’s use the port resource and the be_listening
matcher
Wednesday, April 30, 14
Spec for clowns
184
require 'serverspec'
include Serverspec::Helper::Exec
describe 'clowns site' do
it 'responds on port 80' do
expect(port 80).to be_listening 'tcp'
end
end
OPEN IN EDITOR:
apache/test/integration/default/serverspec/clown_spec.rb
Wednesday, April 30, 14
185
kitchen setup
• Before running tests you need to run kitchen	
  
setup
• kitchen	
  setup loads and configures the file
necessary to run test plugins on the node
• The component that manages Test Kitchen plugins
is called Busser
Wednesday, April 30, 14
$ bundle exec kitchen setup default-centos-64
kitchen setup
-----> Starting Kitchen (v1.2.1)
-----> Setting up <default-centos-64>...
Fetching: thor-0.19.0.gem (100%)
Fetching: busser-0.6.2.gem (100%)
Successfully installed thor-0.19.0
Successfully installed busser-0.6.2
2 gems installed
-----> Setting up Busser
Creating BUSSER_ROOT in /tmp/busser
Creating busser binstub
Plugin serverspec installed (version 0.2.6)
-----> Running postinstall for serverspec plugin
Finished setting up <default-centos-64> (0m34.28s).
-----> Kitchen is finished. (0m34.37s)
186
Wednesday, April 30, 14
187
kitchen verify
• The kitchen	
  verify command will run the tests in
your *_spec.rb files in the test/integration tree
Wednesday, April 30, 14
$ bundle exec kitchen verify default-centos-64
kitchen verify
-----> Starting Kitchen (v1.2.1)
-----> Verifying <default-centos-64>...
Removing /tmp/busser/suites/serverspec
Uploading /tmp/busser/suites/serverspec/localhost/clown_spec.rb (mode=0664)
-----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/
rspec /tmp/busser/suites/serverspec/localhost/clown_spec.rb --color --format
documentation
clowns site
responds on port 80
Finished in 0.00713 seconds
1 example, 0 failures
Finished verifying <default-centos-64> (0m0.90s).
-----> Kitchen is finished. (0m0.97s)
188
Wednesday, April 30, 14
189
Verifying that the tests work
• Did the test actually do anything? Let’s verify this
by changing the port to a known incorrect value.
Wednesday, April 30, 14
Replace port 80 with 85
190
require 'serverspec'
include Serverspec::Helper::Exec
describe 'clowns site' do
it 'responds on port 85' do
expect(port 85).to be_listening 'tcp'
end
end
OPEN IN EDITOR:
apache/test/integration/default/serverspec/clown_spec.rb
Wednesday, April 30, 14
$ bundle exec kitchen verify default-centos-64
This should fail
-----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/
suites/serverspec/localhost/clown_spec.rb --color --format documentation
clowns site
responds on port 85 (FAILED - 1)
Failures:
1) clowns site responds on port 85
Failure/Error: expect(port 85).to be_listening 'tcp'
netstat -tunl | grep -- :85
expected Port "85" to be listening "tcp"
# /tmp/busser/suites/serverspec/localhost/clown_spec.rb:7:in `block (2 levels) in <top (required)>'
Finished in 0.00718 seconds
1 example, 1 failure
...
191
Wednesday, April 30, 14
$ bundle exec kitchen verify default-centos-64
This should fail
-----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/
suites/serverspec/localhost/clown_spec.rb --color --format documentation
clowns site
responds on port 85 (FAILED - 1)
Failures:
1) clowns site responds on port 85
Failure/Error: expect(port 85).to be_listening 'tcp'
netstat -tunl | grep -- :85
expected Port "85" to be listening "tcp"
# /tmp/busser/suites/serverspec/localhost/clown_spec.rb:7:in `block (2 levels) in <top (required)>'
Finished in 0.00718 seconds
1 example, 1 failure
...
192
WIN FAILWednesday, April 30, 14
193
Back to success
• Remember to reset the tests back to the original port
value so they succeed again!
Wednesday, April 30, 14
Reset back to port 80
194
require 'serverspec'
include Serverspec::Helper::Exec
describe 'clowns site' do
it 'responds on port 80' do
expect(port 80).to be_listening 'tcp'
end
end
OPEN IN EDITOR:
apache/test/integration/default/serverspec/clown_spec.rb
Wednesday, April 30, 14
$ bundle exec kitchen verify default-centos-64
kitchen verify
-----> Starting Kitchen (v1.2.1)
-----> Verifying <default-centos-64>...
Removing /tmp/busser/suites/serverspec
Uploading /tmp/busser/suites/serverspec/localhost/clown_spec.rb (mode=0664)
-----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/
rspec /tmp/busser/suites/serverspec/localhost/clown_spec.rb --color --format
documentation
clowns site
responds on port 80
Finished in 0.00713 seconds
1 example, 0 failures
Finished verifying <default-centos-64> (0m0.90s).
-----> Kitchen is finished. (0m0.97s)
195
Wednesday, April 30, 14
196
Testing bears
• Let’s add another test to do a similar check for the
bears port
Wednesday, April 30, 14
Spec for bears
197
require 'serverspec'
include Serverspec::Helper::Exec
describe 'bears site' do
it 'responds on port 81' do
expect(port 81).to be_listening 'tcp'
end
end
OPEN IN EDITOR:
apache/test/integration/default/serverspec/bear_spec.rb
Wednesday, April 30, 14
198
No need to run kitchen setup
• You only need to run kitchen	
  setup once per
node. (Though it doesn’t hurt to run it more than
once).
Wednesday, April 30, 14
$ bundle exec kitchen verify default-centos-64
Verifying clowns & bears
...
----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/
embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/bear_spec.rb /tmp/busser/
suites/serverspec/localhost/clown_spec.rb --color --format documentation
bears site
responds on port 81
clowns site
responds on port 80
Finished in 0.00889 seconds
2 examples, 0 failures
...
199
Wednesday, April 30, 14
200
Code cleanup
• Common code can be moved to a file called
spec_helper.rb in test/integration/default/
serverspec
• Test Kitchen automatically looks for
spec_helper.rb in test/integration/default/
serverspec
Wednesday, April 30, 14
201
Code cleanup
• Let’s move common code between clowns & bears
to spec_helper.rb
Wednesday, April 30, 14
spec_helper.rb
202
require 'serverspec'
include Serverspec::Helper::Exec
OPEN IN EDITOR:
apache/test/integration/default/serverspec/spec_helper.rb
Wednesday, April 30, 14
require spec_helper clowns
203
require 'spec_helper'
describe 'clowns site' do
it 'responds on port 80' do
expect(port 80).to be_listening 'tcp'
end
end
OPEN IN EDITOR:
apache/test/integration/default/serverspec/clown_spec.rb
Wednesday, April 30, 14
require spec_helper bears
204
require 'spec_helper'
describe 'bears site' do
it 'responds on port 81' do
expect(port 81).to be_listening 'tcp'
end
end
OPEN IN EDITOR:
apache/test/integration/default/serverspec/bear_spec.rb
Wednesday, April 30, 14
$ bundle exec kitchen verify default-centos-64
Testing clowns and bears w/spec_helper.rb
...
----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/
embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/bear_spec.rb /tmp/busser/
suites/serverspec/localhost/clown_spec.rb --color --format documentation
bears site
response on port 81
clowns site
responds on port 80
Finished in 0.00889 seconds
2 examples, 0 failures
...
205
Wednesday, April 30, 14
$ bundle exec kitchen verify default-centos-64
Testing clowns and bears w/spec_helper.rb
...
----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/
embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/bear_spec.rb /tmp/busser/
suites/serverspec/localhost/clown_spec.rb --color --format documentation
bears site
response on port 81
clowns site
responds on port 80
Finished in 0.00889 seconds
2 examples, 0 failures
...
206
WINWednesday, April 30, 14
207
Are the web sites really working?
• While we’ve added checks to verify that the test
node is listening on ports 80 and 81, we haven’t
verified that users see the right content when they
visit these sites.
• Let’s use the command resource with the
return_stdout matcher to do a simple check with
curl to verify that port 80 is clowns and port 81 is
bears.
Wednesday, April 30, 14
command resource/return_stdout matcher
208
Wednesday, April 30, 14
Check clown content
209
require 'spec_helper'
describe 'clowns site' do
it 'responds on port 80' do
expect(port 80).to be_listening 'tcp'
end
it 'returns clowns in the HTML body' do
expect(command 'curl localhost:80').to 
return_stdout(/clowns/)
end
end
OPEN IN EDITOR:
apache/test/integration/default/serverspec/clown_spec.rb
Wednesday, April 30, 14
210
Wednesday, April 30, 14
Check bear content
211
require 'spec_helper'
describe 'bears site' do
it 'responds on port 81' do
expect(port 81).to be_listening 'tcp'
end
it 'returns bears in the HTML body' do
expect(command 'curl localhost:81').to 
return_stdout(/bears/)
end
end
OPEN IN EDITOR:
apache/test/integration/default/serverspec/bear_spec.rb
Wednesday, April 30, 14
$ bundle exec kitchen verify default-centos-64
Testing for content
...
-----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/
suites/serverspec/localhost/bear_spec.rb /tmp/busser/suites/serverspec/localhost/clown_spec.rb --color --
format documentation
bears site
responds on port 81
returns bears in the HTML body
clowns site
responds on port 80
returns clowns in the HTML body
Finished in 0.0293 seconds
4 examples, 0 failures
Finished verifying <default-centos-64> (0m1.73s).
-----> Kitchen is finished. (0m1.79s)
...
212
WINWednesday, April 30, 14
213
Detecting the target OS
• Many of the resources require that Serverspec
detect the OS so it can run the correct command for
your platform
expect(package	
  'httpd').to	
  be_installed
• You’ll need to add an extra Helper to spec_helper.rb
Wednesday, April 30, 14
spec_helper.rb
214
require 'serverspec'
include Serverspec::Helper::Exec
include Serverspec::Helper::DetectOS
OPEN IN EDITOR:
apache/test/integration/default/serverspec/spec_helper.rb
Wednesday, April 30, 14
Check httpd package
215
require 'spec_helper'
describe 'server' do
it 'has apache installed' do
expect(package 'httpd').to be_installed
end
end
OPEN IN EDITOR:
apache/test/integration/default/serverspec/default_spec.rb
Wednesday, April 30, 14
$ bundle exec kitchen verify default-centos-64
Testing for httpd
...
-----> Running serverspec test suite
/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/
suites/serverspec/localhost/bear_spec.rb /tmp/busser/suites/serverspec/localhost/clown_spec.rb --color --
format documentation
bears site
responds on port 81
returns bears in the HTML body
clowns site
responds on port 80
returns clowns in the HTML body
Finished in 0.0293 seconds
4 examples, 0 failures
Finished verifying <default-centos-64> (0m1.73s).
-----> Kitchen is finished. (0m1.79s)
...
216
WINWednesday, April 30, 14
217
kitchen test
• The kitchen	
  test command will automate all the
previous actions you’ve learned so far into one command.
It runs the following commands in sequence:
• kitchen	
  destroy (if necessary)
•kitchen	
  create
•kitchen	
  converge
•kitchen	
  setup
•kitchen	
  verify
•kitchen	
  destroy
Wednesday, April 30, 14
218
kitchen test
• The kitchen	
  test command is intended to be used
as a final check on a fresh image before committing
changes to source control and/or to be used in a
Continuous Integration environment like Jenkins.
Wednesday, April 30, 14
$ bundle exec kitchen test default-centos-64
kitchen test
-----> Starting Kitchen (v1.2.1)
-----> Cleaning up any prior instances of <default-centos-64>
-----> Destroying <default-centos-64>...
2c46b1a4609dc6a2beaf44e1134638b0a8ac47c9c5a02baee0bdb3df64e7bcdf
2c46b1a4609dc6a2beaf44e1134638b0a8ac47c9c5a02baee0bdb3df64e7bcdf
Finished destroying <default-centos-64> (0m0.60s).
-----> Testing <default-centos-64>
-----> Creating <default-centos-64>...
...
Finished in 0.0311 seconds
4 examples, 0 failures
Finished verifying <default-centos-64> (0m1.71s).
-----> Destroying <default-centos-64>...
d22a8c4db8505f89f7f7e65bca26492f58d5637f9a88763d5eb919d860dade4e
d22a8c4db8505f89f7f7e65bca26492f58d5637f9a88763d5eb919d860dade4e
Finished destroying <default-centos-64> (0m0.47s).
Finished testing <default-centos-64> (0m39.78s).
-----> Kitchen is finished. (0m39.84s)
219
Wednesday, April 30, 14
Where to go next
• Jenkins cookbook is chock full of advanced
Serverspec techniques:
https://github.com/opscode-cookbooks/jenkins
220
Wednesday, April 30, 14
Where to go next
• jenkins/test/shared/support contains
examples for implementing custom Serverspec
matchers used in jenkins/test/integration:
•describe	
  jenkins_job('my-­‐project')	
  do
	
  	
  it	
  {	
  should	
  be_a_jenkins_job	
  }
end
221
Wednesday, April 30, 14
Where to go next
• test/fixtures contains mini-cookbooks to
exercise resource providers
• Aliased in Berksfile:
•cookbook	
  'smoke',	
  path:	
  'test/fixtures/
cookbooks/smoke'
• Run via Rakefile
222
Wednesday, April 30, 14
Where to go next
• Uses data/path directive in .kitchen.yml to share
test data between serverspec suites
• Directory specified in data/path is copied to /tmp/
kitchen/data on guest
• Reason for weird require_relative directive in tests
that use custom Serverspec matchers:
require_relative	
  '../../../kitchen/data/
spec_helper'
223
Wednesday, April 30, 14
RECAP: Why Test?
• It’s important to find bugs fast
224
Wednesday, April 30, 14
Better, Faster, Stronger
• Test Kitchen is an invaluable tool for managing
sandbox environments and truly verifying that a
cookbook produces the intended results
• But it does require spinning up an instance and
performing a full Chef converge, which can take a
long time
• Use Test Kitchen judiciously. The other tools can
provide more limited forms of feedback faster.
225
Wednesday, April 30, 14
v2.0.0
Detect Suspicious Cookbook
Code with Foodcritic
226
Wednesday, April 30, 14
Feedback on Chef Coding Style
• Foodcritic provides feedback on your Chef coding
style
• It is designed to be used as you are writing Chef
code - how’s that for freaking fast!
• Written by Andrew Crump
http://acrmp.github.com/footcritic
227
Wednesday, April 30, 14
Feedback on Chef Coding Style
• Let’s install Foodcritic on your development
workstation so you can give it a spin
• Add Foodcritic to your Gemfile
• Install the app with bundle	
  install
228
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Gemfile
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'serverspec', '~> 1.1'
gem 'foodcritic', '~> 3.0'
Add foodcritic to Gemfile
229
Wednesday, April 30, 14
$ sudo yum install -y libxslt-devel libxml2-devel
Install Prerequisites
230
$ sudo apt-get install -y libxslt-dev libxml2-dev
Wednesday, April 30, 14
$ bundle install
Install Foodcritic
231
$ CONFIGURE_ARGS="--with-ldflags=
'-Wno-error=unused-command-line-argument-hard-error-in-
future'" bundle install
clang 5.1 Workaround
Wednesday, April 30, 14
$ bundle exec foodcritic --version
Verify install
foodcritic 3.0.3
232
Wednesday, April 30, 14
$ bundle exec foodcritic .
Run Foodcritic on your cookbook
233
FC003: Check whether you are running with chef
server before using server-specific features:
cookbooks/apache/recipes/ip-logger.rb:1
FC008: Generated cookbook metadata needs
updating: cookbooks/apache/metadata.rb:2
FC008: Generated cookbook metadata needs
updating: cookbooks/apache/metadata.rb:3
Wednesday, April 30, 14
234
More feedback!
Wednesday, April 30, 14
235
Fast feedback!
Wednesday, April 30, 14
Feedback on Chef Coding Style
• Foodcritic comes with a set of checks called rules
• Foodcritic rules are documented at http://
acrmp.github.io/foodcritic/
• The default rules are a good start, and you can add
new rules of your own easily
236
Wednesday, April 30, 14
Default Rules
237
Wednesday, April 30, 14
238
What about the
FC003 & FC008 issues
in the apache cookbook?
Wednesday, April 30, 14
FC008 - Generated cookbook metadata needs updating
239
Wednesday, April 30, 14
240
Let’s fix!
Wednesday, April 30, 14
cookbooks/apache/metadata.rb
241
name 'apache'
maintainer 'YOUR_COMPANY_NAME'
maintainer_email 'YOUR_EMAIL'
license 'All rights reserved'
description 'Installs/Configures apache'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.2.0'
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/metadata.rb
name 'apache'
maintainer 'Mischa Taylor'
maintainer_email 'misheska@getchef.com'
license 'All rights reserved'
description 'Installs/Configures apache'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.2.0'
242
Addressing FC008
Wednesday, April 30, 14
$ bundle exec foodcritic .
Rerun foodcritic
243
FC003: Check whether you are running
with chef server before using server-
specific features: ./recipes/ip-
logger.rb:1
Wednesday, April 30, 14
244
Two down,
one to go!
Wednesday, April 30, 14
FC003 - Check for chef server before using server-specific features
245
Wednesday, April 30, 14
246
Ignoring FC003
• Let’s say, for now, we don’t want to fix ip-­‐
logger.rb, and we’d like to squelch the FC003
check
Wednesday, April 30, 14
247
--tags parameter
• The -­‐-­‐tags	
  <TAGS> parameter can be used to
specify a list of rules for foodcritic to use
•foodcritic	
  -­‐-­‐tags	
  FC001,FC002,FC008
• The tilde (~) modifier can be used to ignore specific
rules
•foodcritic	
  -­‐-­‐tags	
  ~FC003
Wednesday, April 30, 14
$ bundle exec foodcritic --tags ~FC003 .
Ignore FC003
248
Wednesday, April 30, 14
$ bundle exec foodcritic --tags ~FC003 .
Ignore FC003
249
WINWednesday, April 30, 14
250
Custom rules
• Etsy created some custom Foodcritic rules to check
for issues that caused production outages/
performance degradation.
• Good example for how to create your own custom
rules
• Documented here:
https://github.com/etsy/foodcritic-rules
Wednesday, April 30, 14
Etsy Foodcritic Rules
• ETSY001 - Package or yum_package resource used
with :upgrade action
• ETSY002 - Execute resource used to run git commands
• ETSY003 - Execute resource used to run curl or wget commands
• ETSY004 - Execute resource defined without conditional or
action :nothing
• ETSY005 - Action :restart sent to a core service
• ETSY006 - Execute resource used to run chef-provided command
• ETSY007 - Package or yum_package resource used to install
core package without specific version number
251
Wednesday, April 30, 14
$ git clone https://github.com/etsy/
foodcritic-rules ../../foodcritic/etsy
$ rm -rf ../../foodcritic/etsy/.git
Installing new rules
252
Wednesday, April 30, 14
253
--include parameter
• The -­‐-­‐include	
  <PATH> parameter species
additional paths to load rules (shortened with -I)
Wednesday, April 30, 14
$ bundle exec foodcritic -t ~FC003 -I ../../
foodcritic .
Including Custom Rules
ETSY005: Action :restart sent to a core
service: ./recipes/default.rb:19
ETSY005: Action :restart sent to a core
service: ./recipes/default.rb:32
ETSY007: Package or yum_package resource used to
install core package without specific version
number: ./recipes/default.rb:10
254
Wednesday, April 30, 14
255
Editor support
• Many popular editors can be configured to run
Foodcritic inside the editor (including Vim, GNU
Emacs and Sublime Text). So you can get feedback
even faster.
Wednesday, April 30, 14
v2.0.0
Detect Suspicious Ruby Code
with RuboCop
256
Wednesday, April 30, 14
RuboCop - Feedback on Ruby Style
• Many people new to Ruby would like some guidance
on how to write idiomatic Ruby
• Get the same kind of feedback for Ruby using
RuboCop that you get for Chef Code using
Foodcritic (Chef code is Ruby)
257
Wednesday, April 30, 14
RuboCop Author
• Written by Bozhidar Batsov:
https://github.com/bbatsov/rubocop
258
Wednesday, April 30, 14
RuboCop - Feedback on Ruby Style
• Follows community-driven style guide:
https://github.com/bbatsov/ruby-style-guide
• Looks at cookbooks for Ruby best practices, not the
Chef DSL - that’s Foodcritic
259
Wednesday, April 30, 14
RuboCop - Feedback on Ruby Style
• Let’s install RuboCop on your development
workstation so you can give it a spin
• Add RuboCop to your Gemfile
• Install the app with bundle	
  install
260
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Gemfile
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'serverspec', '~> 1.1'
gem 'foodcritic', '~> 3.0'
gem 'rubocop', '~> 0.20'
Add rubocop to Gemfile
261
Wednesday, April 30, 14
$ bundle install
Install RuboCop
262
$ CONFIGURE_ARGS="--with-ldflags=
'-Wno-error=unused-command-line-argument-hard-error-in-
future'" bundle install
clang 5.1 Workaround
Wednesday, April 30, 14
$ bundle exec rubocop --version
Verify Install
0.20.1
263
Wednesday, April 30, 14
Running RuboCop
• Just run the rubocop command - it recursively
checks all the *.rb files in all subdirectories
underneath the current directory (excluding
vendor/)
264
Wednesday, April 30, 14
$ bundle exec rubocop
Run RuboCop on your cookbook
attributes/default.rb:3:19: C: Prefer single-quoted strings when you don't
need string interpolation or special symbols.
default["apache"]["sites"]["bears"] = { "port" => 81 }
^^^^^^^
attributes/default.rb:3:28: C: Prefer single-quoted strings when you don't
need string interpolation or special symbols.
default["apache"]["sites"]["bears"] = { "port" => 81 }
^^^^^^^
attributes/default.rb:3:41: C: Prefer single-quoted strings when you don't
need string interpolation or special symbols.
default["apache"]["sites"]["bears"] = { "port" => 81 }
^^^^^^
7 files inspected, 52 offenses detected
265
Wednesday, April 30, 14
rubocop-todo.yml via --auto-gen-config
• rubocop-todo.yml will help generate TODOs for each
item on the offense list
• It also shows you what config setting can be used to
mask each offense, which we’ll need to do for some
of these, because Chef code conventions vary
slightly from the Rubocop community standards
266
Wednesday, April 30, 14
$ bundle exec rubocop --auto-gen-config
Generate rubocop-todo.yml
attributes/default.rb:3:28: C: Prefer single-quoted strings when you
don't need string interpolation or special symbols.
default["apache"]["sites"]["bears"] = { "port" => 81 }
^^^^^^^
attributes/default.rb:3:41: C: Prefer single-quoted strings when you
don't need string interpolation or special symbols.
default["apache"]["sites"]["bears"] = { "port" => 81 }
^^^^^^
7 files inspected, 52 offenses detected
Created rubocop-todo.yml.
Run `rubocop --config rubocop-todo.yml`, or
add inherit_from: rubocop-todo.yml in a .rubocop.yml file.
267
Wednesday, April 30, 14
.rubocop.yml Configures RuboCop
• .rubocop.yml can be used to configure RuboCop
(similar to .kitchen.yml in Test Kitchen)
• We’ll add a settings to ignore things, similar to what
we did for Foodcritic, that don’t make as much sense
for Chef.
• Settings are documented in the RuboCop README:
https://github.com/bbatsov/rubocop/blob/master/
README.md
• Cop is the RuboCop equivalent of a rule
268
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/.rubocop.yml
inherit_from:	
  rubocop-­‐todo.yml
Include rubocop-todo.yml
269
Wednesday, April 30, 14
$ bundle exec rubocop
Run RuboCop on your cookbook
Inspecting 7 files
.......
7 files inspected, no offenses detected
270
Wednesday, April 30, 14
Easy peasy
• Wow, now more offenses...not really
271
Wednesday, April 30, 14
Match Chef community standards
• First, we’ll move some of the Cops from rubocop-
todo.yml to .rubocop.yml for things that match Chef
community standards (as opposed to the Ruby
community standards)
272
Wednesday, April 30, 14
Missing utf-8 encoding comment
273
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/.rubocop.yml
inherit_from:	
  rubocop-­‐todo.yml
Encoding:
	
  	
  Enabled:	
  false
Chef does not (yet) support encoding comment
274
Wednesday, April 30, 14
Line is too long
275
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/.rubocop.yml
inherit_from:	
  rubocop-­‐todo.yml
Encoding:
	
  	
  Enabled:	
  false
LineLength:
	
  	
  Max:	
  200
Relax line limit
276
Wednesday, April 30, 14
Use the new Ruby 1.9 hash syntax
277
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/.rubocop.yml
inherit_from:	
  rubocop-­‐todo.yml
Encoding:
	
  	
  Enabled:	
  false
LineLength:
	
  	
  Max:	
  200
HashSyntax:
	
  EnforcedStyle:	
  hash_rockets
Some cookbooks try to be Ruby 1.8 compatible
278
Wednesday, April 30, 14
Prefer single-quoted strings
279
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/.rubocop.yml
inherit_from:	
  rubocop-­‐todo.yml
Encoding:
	
  	
  Enabled:	
  false
LineLength:
	
  	
  Max:	
  200
HashSyntax:
	
  	
  EnforcedStyle:	
  hash_rockets
StringLiterals:
	
  	
  Enabled:	
  false
Conflicts w/decision to relax FC002
280
Wednesday, April 30, 14
$ bundle exec rubocop --auto-gen-config
Regenerate rubocop-todo.yml
metadata.rb:2:11: C: Put one space between the method name and the first argument.
maintainer 'Mischa Taylor'
^^^^^^^
metadata.rb:4:8: C: Put one space between the method name and the first argument.
license 'All rights reserved'
^^^^^^^^^^
metadata.rb:5:12: C: Put one space between the method name and the first argument.
description 'Installs/Configures apache'
^^^^^^
metadata.rb:7:8: C: Put one space between the method name and the first argument.
version '0.2.0'
^^^^^^^^^^
7 files inspected, 11 offenses detected
281
Wednesday, April 30, 14
Rubocop Workflow
• Uncomment lines in rubocop-todo.yml
• Fix offenses
• git commit
• Repeat
282
Wednesday, April 30, 14
Only really critical issue
283
Wednesday, April 30, 14
Trailing whitespace & Git
• Whitespace differences make diffs longer and
diverts focus from more important changes
• Even with Git, trailing whitespace can make merge
conflicts more difficult to resolve
284
Wednesday, April 30, 14
285
Editor support
• Many popular editors can be configured to run
RuboCop inside the editor (including Vim, GNU
Emacs and Sublime Text). So you can get feedback
even faster.
• RuboCop includes great docs on editor configuration
(which work for Foodcritic as well):
https://github.com/bbatsov/rubocop#editor-
integration
Wednesday, April 30, 14
v2.0.0
Runnable documentation with
ChefSpec
286
Wednesday, April 30, 14
RECAP: Why Not Begin With Testing?
• Finding a bug in something that you can’t execute
is freaking hard!
• While fixing bugs before writing code is cheap,
finding them is expensive
287
Wednesday, April 30, 14
What is ChefSpec?
• ChefSpec helps produce runnable documentation.
Its primary purpose is to help document and
organize your code.
• As a side effect, you’ll end up with a set of tests
which can also be used to uncover bugs when
changes are made.
• Plus, your cookbook code will be improved when it
is guided by tests.
288
Wednesday, April 30, 14
ChefSpec Authors
• Written by Andrew Crump and Seth Vargo
289
Wednesday, April 30, 14
ChefSpec - Runnable Documentation
• Let’s install ChefSpec on your development
workstation so you can give it a spin
• Add ChefSpec to your Gemfile
• Install the app with bundle	
  install
290
Wednesday, April 30, 14
OPEN IN EDITOR: chef-fundamentals-repo/Gemfile
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'serverspec', '~> 1.1'
gem 'foodcritic', '~> 3.0'
gem 'rubocop', '~> 0.20'
gem 'chefspec', '~> 3.4'
Gemfile
291
Wednesday, April 30, 14
$ bundle install
Install ChefSpec
292
$ CONFIGURE_ARGS="--with-ldflags=
'-Wno-error=unused-command-line-argument-hard-error-in-
future'" bundle install
clang 5.1 Workaround
Wednesday, April 30, 14
ChefSpec builds on RSpec
• ChefSpec uses the RSpec description form to create
runnable documentation (in a similar vein to
serverspec)
293
Wednesday, April 30, 14
Documentation form
294
describe	
  ‘<recipe_name>’	
  do
	
  	
  <perform	
  in-­‐memory	
  Chef	
  run>
	
  	
  <descriptions	
  here>
end
Wednesday, April 30, 14
Documentation example
295
describe	
  ‘apache::default’	
  do
	
  	
  ...
end
Wednesday, April 30, 14
In-Memory Chef Run Form
296
require	
  ‘chefspec’
describe	
  ‘<recipe_name>’	
  do
	
  	
  chef_run	
  =	
  ChefSpec::Runner.new.converge(<recipe_name>)
	
  	
  <descriptions	
  here>
end
Wednesday, April 30, 14
In-Memory Chef Run Example
297
require	
  ‘chefspec’
describe	
  'apache::default'	
  do
	
  	
  chef_run	
  =	
  ChefSpec::Runner.new.converge('apache::default')
	
  	
  <descriptions	
  here>
end
Wednesday, April 30, 14
Expectation form
298
describe	
  ‘<recipe_name>’	
  do
	
  	
  <perform	
  in-­‐memory	
  Chef	
  run>
	
  	
  it	
  ‘<description>’	
  do
	
  	
  	
  	
  expect(<chef_run>).to	
  eq	
  result
	
  	
  end
end
Wednesday, April 30, 14
Expectation form
299
describe	
  ‘<recipe_name>’	
  do
	
  	
  <perform	
  in-­‐memory	
  Chef	
  run>
	
  	
  it	
  ‘<description>’	
  do
	
  	
  	
  	
  expect(<chef_run>).to	
  eq	
  result
	
  	
  end
end
Matcher
Wednesday, April 30, 14
Expectation Example
300
require	
  ‘chefspec’
describe	
  'apache::default'	
  do
	
  	
  chef_run	
  =	
  ChefSpec::Runner.new.converge('apache::default')
	
  	
  it	
  ‘installs	
  apache2’	
  do
	
  	
  	
  	
  expect(chef_run).to	
  install_package(‘httpd’)
	
  	
  end
end
Wednesday, April 30, 14
Runnable Documentation
• expect statement does not actually perform the
httpd package installation
• It just verifies the cookbook syntax that it instructs
Chef to install the package
• Good enough for well-tested primitives like the
package resource
301
Wednesday, April 30, 14
302
Let’s write some ChefSpec
tests!
Wednesday, April 30, 14
303
Default location for tests
• By default, ChefSpec will look in the spec/directory
for ChefSpec test-related files
Wednesday, April 30, 14
chef-fundamentals-repo
304
.
!"" .bundle/
!"" .kitchen/
!"" .kitchen.yml
!"" CHANGELOG.md
!"" Gemfile
!"" Gemfile.lock
!"" README.md
!"" attributes/
!"" files/
!"" metadata.rb
!"" recipes/
!"" spec/
!"" templates/
!"" test/
$   #"" integration/
#"" vendor/
#"" bundle/
Wednesday, April 30, 14
$ mkdir spec
Create spec directory in cookbooks/apache
305
> mkdir spec
Wednesday, April 30, 14
306
*_spec.rb files
• By convention, ChefSpec expects files with tests to
end in _spec.rb
Wednesday, April 30, 14
ChefSpec Matcher Documentation
307
http://rubydoc.info/github/acrmp/chefspec/frames
Wednesday, April 30, 14
ChefSpec > API
308
Wednesday, April 30, 14
Each API has an example
309
Wednesday, April 30, 14
Let’s use the install_package matcher
310
Wednesday, April 30, 14
install_package Example
311
Wednesday, April 30, 14
OPEN IN EDITOR: spec/default_spec.rb
require 'chefspec'
describe 'apache::default' do
chef_run = ChefSpec::Runner.new.converge('apache::default')
it 'installs apache2' do
expect(chef_run).to install_package('httpd')
end
end
Test apache::default recipe
312
Wednesday, April 30, 14
313
Rspec runs ChefSpec
• There’s no separate chefspec command.
• Just run rspec to run ChefSpec tests.
Wednesday, April 30, 14
$ bundle exec rspec --color
Run ChefSpec on your cookbok
.
Finished in 0.0006 seconds
1 example, 0 failures
314
Wednesday, April 30, 14
OPEN IN EDITOR: spec/default_spec.rb
require 'chefspec'
describe 'apache::default' do
chef_run = ChefSpec::Runner.new.converge('apache::default')
it 'installs apache2' do
expect(chef_run).to install_package('badhttpd')
end
end
Did it really check anything?
315
Wednesday, April 30, 14
$ bundle exec rspec
Run ChefSpec on your cookbok
F
Failures:
1) apache::default installs apache2
Failure/Error: expect(chef_run).to install_package('badhttpd')
expected "package[badhttpd]" with action :install to be in Chef run. Other
package resources:
package[httpd]
# ./spec/default_spec.rb:7:in `block (2 levels) in <top (required)>'
Finished in 0.00044 seconds
1 example, 1 failure
316
Wednesday, April 30, 14
OPEN IN EDITOR: spec/default_spec.rb
require 'chefspec'
describe 'apache::default' do
chef_run = ChefSpec::Runner.new.converge('apache::default')
it 'installs apache2' do
expect(chef_run).to install_package('httpd')
end
end
Restore back to working
317
Wednesday, April 30, 14
$ bundle exec rspec --color
Run ChefSpec on your cookbok
.
Finished in 0.0006 seconds
1 example, 0 failures
318
Wednesday, April 30, 14
Lazy evaluation with let
319
require 'chefspec'
describe 'apache::default' do
let(:chef_run) 
{ ChefSpec::Runner.new.converge(described_recipe) }
it 'installs apache2' do
expect(chef_run).to install_package('httpd')
end
end
Lazy evaluation
Wednesday, April 30, 14
320
described_recipe
• let blocks aren’t evaluated until the first time they
are called
• Also allows ChefSpec to run the described_recipe
macro to evaluate the recipe name
Wednesday, April 30, 14
OPEN IN EDITOR: spec/default_spec.rb
require 'chefspec'
describe 'apache::default' do
let(:chef_run) 
{ ChefSpec::Runner.new.converge(described_recipe) }
it 'installs apache2' do
expect(chef_run).to install_package('httpd')
end
end
Lazy evaluation
321
Wednesday, April 30, 14
$ bundle exec rspec --color
Run ChefSpec on your cookbok
.
Finished in 0.0006 seconds
1 example, 0 failures
322
Wednesday, April 30, 14
323
ChefSpec Resource Report
• ChefSpec Resource Report can help guide writing
your tests
Wednesday, April 30, 14
OPEN IN EDITOR: spec/default_spec.rb
require 'chefspec'
at_exit { ChefSpec::Coverage.report! }
describe 'apache::default' do
let (:chef_run) 
{ ChefSpec::Runner.new.converge(described_recipe) }
it 'installs apache2' do
expect(chef_run).to install_package('httpd')
end
end
Adding resource report
324
Wednesday, April 30, 14
$ bundle exec rspec --color
Run ChefSpec on your cookbok
.
Finished in 0.01106 seconds
1 example, 0 failures
ChefSpec Coverage report generated...
Total Resources: 9
Touched Resources: 1
Touch Coverage: 11.11%
Untouched Resources:
service[httpd] /recipes/default.rb:14
execute[mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.disabled] /recipes/default.rb:19
template[/etc/httpd/conf.d/clowns.conf] /recipes/default.rb:32
directory[/srv/apache/clowns] /recipes/default.rb:43
template[/srv/apache/clowns/index.html] /recipes/default.rb:49
template[/etc/httpd/conf.d/bears.conf] /recipes/default.rb:32
directory[/srv/apache/bears] /recipes/default.rb:43
template[/srv/apache/bears/index.html] /recipes/default.rb:49
325
Wednesday, April 30, 14
326
create_file matcher
• Let’s verify that the clowns.conf file gets created
with the create_file matcher
Wednesday, April 30, 14
327
create_file matcher
Wednesday, April 30, 14
OPEN IN EDITOR: spec/default_spec.rb
require 'chefspec'
at_exit { ChefSpec::Coverage.report! }
describe 'apache::default' do
let(:chef_run) 
{ ChefSpec::Runner.new.converge(described_recipe) }
...
it 'creates clowns.conf' do
expect(chef_run).to 
create_file('/etc/httpd/conf.d/clowns.conf')
end
end
Checking clowns.conf files
328
Wednesday, April 30, 14
$ bundle exec rspec --color
Run ChefSpec on your cookbok
F
Failures:
1) apache::default creates clowns.conf
Failure/Error: expect(chef_run).to create_file('/srv/apache/clowns')
expected "file[/srv/apache/clowns]" with action :create to be in Chef run. Other file resources:
# ./spec/default_spec.rb:13:in `block (2 levels) in <top (required)>'
Finished in 0.01903 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/default_spec.rb:12 # apache::default creates clowns.conf
329
Wednesday, April 30, 14
$ bundle exec rspec --color
Run ChefSpec on your cookbok
F
Failures:
1) apache::default creates clowns.conf
Failure/Error: expect(chef_run).to create_file('/srv/apache/clowns')
expected "file[/srv/apache/clowns]" with action :create to be in Chef run. Other file resources:
# ./spec/default_spec.rb:13:in `block (2 levels) in <top (required)>'
Finished in 0.01903 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/default_spec.rb:12 # apache::default creates clowns.conf
330
FAILWednesday, April 30, 14
331
ChefSpec == Runnable Documentation
• Remember: ChefSpec is just runnable
documentation
• It isn’t actually performing a Chef run to verify that
clowns.conf was created
• Instead it is just verifying that you told Chef to
create the clowns.conf via the file resource, which
you never did - you used the template resource
Wednesday, April 30, 14
332
template matcher
Wednesday, April 30, 14
OPEN IN EDITOR: spec/default_spec.rb
require 'chefspec'
at_exit { ChefSpec::Coverage.report! }
describe 'apache::default' do
let(:chef_run)
{ ChefSpec::Runner.new.converge(described_recipe) }
...
it 'creates clowns.conf' do
expect(chef_run).to 
create_template('/etc/httpd/conf.d/clowns.conf')
end
end
Checking clowns.conf file
333
Wednesday, April 30, 14
$ bundle exec rspec --color
Run ChefSpec on your cookbok
.
Finished in 0.01955 seconds
2 examples, 0 failures
334
Wednesday, April 30, 14
$ bundle exec rspec --color
Run ChefSpec on your cookbok
.
Finished in 0.01955 seconds
2 examples, 0 failures
335
WINWednesday, April 30, 14
336
spec_helper.rb
• Similar to Serverspec, common code can be moved
to a file called spec_helper.rb with ChefSpec
Wednesday, April 30, 14
OPEN IN EDITOR: spec/spec_helper.rb
require 'chefspec'
at_exit { ChefSpec::Coverage.report! }
Checking clowns.conf file
337
Wednesday, April 30, 14
338
RSpec recurses through spec/*
• RSpec recurses through the spec/ subtree, looking
for tests, so you can create any directory structure
you like underneath
• We’ll move default_spec.rb to spec/recipes
Wednesday, April 30, 14
$ mkdir spec/recipes
$ mv spec/default_spec.rb spec/recipes
Move default_spec.rb
339
Wednesday, April 30, 14
OPEN IN EDITOR: spec/recipes/default_spec.rb
require 'spec_helper'
describe 'apache::default' do
let (:chef_run) 
{ ChefSpec::Runner.new.converge(described_recipe) }
it 'installs apache2' do
expect(chef_run).to install_package('httpd')
end
it 'creates clowns.conf' do
expect(chef_run).to 
create_template('/etc/httpd/conf.d/clowns.conf')
end
end
Checking clowns.conf file
340
Wednesday, April 30, 14
$ bundle exec rspec --color
Run ChefSpec on your cookbok
.
Finished in 0.01955 seconds
2 examples, 0 failures
341
Wednesday, April 30, 14
$ bundle exec rspec --color
Run ChefSpec on your cookbok
.
Finished in 0.01955 seconds
2 examples, 0 failures
342
WINWednesday, April 30, 14
343
Where to go next
• There’s a lot of ChefSpec written for the community
cookbooks. Check out the spec/ directory your
favorites.
Wednesday, April 30, 14
v2.0.0
Continuous Validation with
Guard
344
Wednesday, April 30, 14
What is Guard?
• A tool that monitors for filesystem changes and
performs actions (like launching rake tasks)
• Written by Thibaud Guillaume-Gentil
345
Wednesday, April 30, 14
Guard install
• Let’s install Guard on your development
workstation so you can give it a spin
• Add guard to your Gemfile
• Install the app with bundle	
  install
346
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Gemfile
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'serverspec', '~> 1.1'
gem 'foodcritic', '~> 3.0'
gem 'rubocop', '~> 0.20'
gem 'chefspec', '~> 3.4'
gem 'guard', '~> 2.6'
Gemfile
347
Wednesday, April 30, 14
$ bundle install
Install Guard
348
$ CONFIGURE_ARGS="--with-ldflags=
'-Wno-error=unused-command-line-argument-hard-error-in-
future'" bundle install
clang 5.1 Workaround
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Gemfile
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'serverspec', '~> 1.1'
gem 'foodcritic', '~> 3.0'
gem 'rubocop', '~> 0.20'
gem 'chefspec', '~> 3.4'
gem 'guard', '~> 2.6'
gem 'guard-rubocop', '~> 1.1'
Gemfile
349
Wednesday, April 30, 14
$ bundle install
Install guard-rubocop
350
$ CONFIGURE_ARGS="--with-ldflags=
'-Wno-error=unused-command-line-argument-hard-error-in-
future'" bundle install
clang 5.1 Workaround
Wednesday, April 30, 14
$ bundle exec guard init
Create Guardfile
02:39:58 - INFO - Writing new Guardfile to /home/vagrant/
chef-fundamentals-repo/cookbooks/apache/Guardfile
02:45:32 - INFO - rubocop guard added to Guardfile, feel
free to edit it
351
Wednesday, April 30, 14
cookbooks/apache/Guardfile
352
# A sample Guardfile
# More info at https://github.com/guard/guard#readme
guard :rubocop do
watch(%r{.+.rb$})
watch(%r{(?:.+/)?.rubocop.yml$}) { |m| File.dirname(m[0]) }
end
Wednesday, April 30, 14
$ bundle exec guard
Run Guard
02:48:54 - INFO - Guard is now watching at '/home/vagrant/
chef-fundamentals-repo/cookbooks/apache'
[1] guard(main)>
353
Wednesday, April 30, 14
CloudShare Node
354
Wednesday, April 30, 14
CloudShare Node
355
Wednesday, April 30, 14
$ cd $HOME/chef-fundamentals-repo/cookbooks/apache
In another session
356
And edit some .rb file - upon save, rubocop is
launched!
Wednesday, April 30, 14
Stopping guard
[1] guard(main)> quit
19:23:42 - INFO - Bye bye...
357
Wednesday, April 30, 14
358
Where to go next
Michael Goetz blog posts:
https://micgo.net/check-yo-self-before-you-wreck-yo-self-with-
foodcritic-chefspec/
Foodcritic and Guard:
Serverspec and Guard:
https://micgo.net/serverspec-guard-and-test-kitchen-testing-
servers-like-a-boss/
Wednesday, April 30, 14
359
Where to go next
Michael Goetz blog posts:
ChefSpec and Guard:
https://micgo.net/continuous-chefspec-validation-with-guard/
Wednesday, April 30, 14
v2.0.0
Repeating Test Steps with
Rake
360
Wednesday, April 30, 14
What is Rake?
• Rake includes a language for expressing the
command line steps needed to create an app
• Perfect for capturing all the commands you’ve
learned in this class so others can run them easily,
or in your continuous integration system (Jenkins,
Bamboo, TeamCity, etc.)
361
Wednesday, April 30, 14
Rake Author
• Written by Jim Weirich:
http://rake.rubyforge.org/
362
Wednesday, April 30, 14
Rake - Repeatable Test Commands
• Let’s install Rake on your development workstation
so you can give it a spin
• Add rake to your Gemfile
• Install the app with bundle	
  install
363
Wednesday, April 30, 14
OPEN IN EDITOR: chef-fundamentals-repo/Gemfile
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'rake'
gem 'serverspec', '~> 1.1'
gem 'foodcritic', '~> 3.0'
gem 'rubocop', '~> 0.20'
gem 'chefspec', '~> 3.4'
gem 'guard', '~> 2.6'
gem 'guard-rubocop', '~> 1.1'
Gemfile
364
Wednesday, April 30, 14
$ bundle install
Install Rake
365
$ CONFIGURE_ARGS="--with-ldflags=
'-Wno-error=unused-command-line-argument-hard-error-in-
future'" bundle install
clang 5.1 Workaround
Wednesday, April 30, 14
Rake - Repeatable Tasks
• Task - expresses command line actions to perform
366
Wednesday, April 30, 14
Rake Task Form
367
task :<task_name> do
<action>
<action>
end
Wednesday, April 30, 14
Rake - Repeatable Tasks
• Configuration file for rake is a Rakefile
368
Wednesday, April 30, 14
Rake - Actions
• Actions are expressed in Ruby syntax
• sh	
  “<command>”	
  runs a shell command:
sh “bundle	
  exec	
  rspec”
369
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Rakefile
task :rubocop do
sh 'bundle exec rubocop'
end
Rubocop Task
370
Wednesday, April 30, 14
$ bundle exec rake rubocop
Execute Rake Task
Inspecting 9 files
.......
9 files inspected, no offenses detected
371
Wednesday, April 30, 14
Task Description
• Every task should have a description which
documents what the task does
• rake	
  -­‐-­‐tasks prints out tasks with descriptions
372
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Rakefile
desc 'Run Ruby style checks with Rubocop'
task :rubocop do
sh 'bundle exec rubocop'
end
Rubocop Task
373
Wednesday, April 30, 14
$ bundle exec rake --tasks
Execute Rake Task
rake rubocop # Run Ruby style checks with Rubocop
374
Wednesday, April 30, 14
Adding Foodcritic
• Let’s add a task for Foocritic next
375
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Rakefile
desc 'Run Ruby style checks with Rubocop'
task :rubocop do
sh 'bundle exec rubocop'
end
desc 'Run Chef style checks with Foodcritic'
task :foodcritic do
sh 'bundle exec foodcritic -t ~FC003 .'
end
Foodcritic Task
376
Wednesday, April 30, 14
$ bundle exec rake foodcritic
Execute Rake Task
bundle exec foodcritic -t ~FC003 .
FC011: Missing README in markdown format: spec/README.md:1
FC031: Cookbook without metadata file: spec/metadata.rb:1
FC045: Consider setting cookbook name in metadata: spec/
metadata.rb:1
377
Wednesday, April 30, 14
$ bundle exec rake foodcritic
Execute Rake Task
bundle exec foodcritic -t ~FC003 .
FC011: Missing README in markdown format: spec/README.md:1
FC031: Cookbook without metadata file: spec/metadata.rb:1
FC045: Consider setting cookbook name in metadata: spec/
metadata.rb:1
378
WAT?Wednesday, April 30, 14
Foodcritic 3.0.3 issue
• Foodcritic is checking spec/ subtree when it
shouldn’t
• Does not expose command line option to exclude
directories:
https://github.com/acrmp/foodcritic/issues/148
• When fixed, this should work:
bundle	
  exec	
  foodcritic	
  -­‐X	
  spec	
  -­‐t	
  ~FC003	
  .
379
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Rakefile
desc 'Run Ruby style checks with Rubocop'
task :rubocop do
sh 'bundle exec rubocop'
end
require 'foodcritic'
desc 'Run Chef style checks with Foodcritic'
FoodCritic::Rake::LintTask.new(:foodcritic) do |t|
t.options = {
tags: ['~FC003'],
excludes: ['test', 'spec', 'features']
}
end
Workaround - Use Ruby
380
Wednesday, April 30, 14
Default task
• Rake supports a special task name called default
• default runs when no parameters are supplied to
rake
• default (as well as any other task) can point to a
list of other task names to execute
task	
  :default	
  =>	
  [:foodcritic]
381
Wednesday, April 30, 14
OPEN IN EDITOR: cookbooks/apache/Rakefile
task :default => [:rubocop, :foodcritic]
desc 'Run Ruby style checks with Rubocop'
task :rubocop do
sh 'bundle exec rubocop'
end
require 'foodcritic'
desc 'Run Chef style checks with Foodcritic'
FoodCritic::Rake::LintTask.new(:foodcritic) do |t|
t.options = {
tags: ['~FC003'],
excludes: ['test', 'spec', 'features' ]
}
end
Foodcritic Task
382
Wednesday, April 30, 14
$ bundle exec rake
Execute Rake Task
bundle exec rubocop
Inspecting 9 files
.......
7 files inspected, no offenses detected
383
Wednesday, April 30, 14
384
Where to go next
Rake Boot Camp
http://cloud.github.com/downloads/jimweirich/RakePresentations/PowerRake.key.pdf
http://www.confreaks.com/videos/899-railsconf2012-basic-rake
Go to http://confreaks.com
Search for “Basic Rake”
Wednesday, April 30, 14
385
Where to go next
Rake Tasks can have tests
http://blog.jayfields.com/2006/11/ruby-testing-rake-tasks.html
Wednesday, April 30, 14
v2.0.0
Jenkins
386
Wednesday, April 30, 14
What is Jenkins?
• Jenkins is a commonly used, open source
continuous integration system used to build early
and often
• Written by Kohsuke Kawaguchi
387
Wednesday, April 30, 14
$ sudo yum install -y libxslt-devel libxml2-devel
Install Prerequisites
388
$ sudo apt-get install -y libxslt-dev libxml2-dev
Wednesday, April 30, 14
$ cd $HOME
Home directory - great place for source
389
$ cd %USERPROFILE%
Wednesday, April 30, 14
Jenkins cookbook
• Jenkins cookbook - https://github.com/opscode-
cookbooks/jenkins
• Jenkins cookbook is library cookbook
390
Wednesday, April 30, 14
Library cookbook
• Popularized by Bryan Berry’s blog post How to Write
Resuable Chef Cookbooks, Gangnam Style
391
Wednesday, April 30, 14
Jenkins wrapper cookbook
• Start of our wrapper cookbook:
https://github.com/misheska/test-class-jenkins
392
Wednesday, April 30, 14
$ git clone https://github.com/misheska/test-class-jenkins
Grab test-class-jenkins from Github
Cloning into 'test-class-jenkins'...
remote: Counting objects: 19, done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 19 (delta 0), reused 19 (delta 0)
Unpacking objects: 100% (19/19), done.
393
Wednesday, April 30, 14
$ cd test-class-jenkins
test-class-jenkins
394
Wednesday, April 30, 14
$ bundle install --path vendor/bundle
Install gems vendored
Fetching gem metadata from https://rubygems.org/.......
Fetching additional metadata from https://rubygems.org/..
Resolving dependencies...
Installing rake (10.2.2)
Installing addressable (2.3.6)
Installing ast (1.1.0)
...
Installing powerpack (0.0.9)
Installing rainbow (2.0.0)
Installing ruby-progressbar (1.4.2)
Installing rubocop (0.20.1)
Using bundler (1.5.3)
Your bundle is complete!
It was installed into ./vendor/bundle
395
Wednesday, April 30, 14
Jenkins PSA
396
Wednesday, April 30, 14
397
Wednesday, April 30, 14
test-class-jenkins/recipes/default.rb
398
include_recipe 'jenkins::java'
include_recipe 'jenkins::master'
Wednesday, April 30, 14
test-class-jenkins/attributes/default.rb
399
include_attribute 'jenkins::master'
Wednesday, April 30, 14
test-class-jenkins/Gemfile
400
source 'https://rubygems.org'
gem 'test-kitchen'
gem 'kitchen-docker'
gem 'rake'
gem 'berkshelf', '~> 3.0.0.rc'
gem 'rubocop', '~> 0.20'
gem 'foodcritic', '~> 3.0'
Wednesday, April 30, 14
test-class-jenkins/.kitchen.yml
401
---
driver:
name: docker
provisioner:
name: chef_solo
platforms:
- name: centos-6.4
driver_config:
forward:
- 8080:8080
suites:
- name: default
run_list:
- recipe[test-class-jenkins::default]
Wednesday, April 30, 14
$ bundle exec kitchen converge
Perform Chef run of Jenkins wrapper
-----> Starting Kitchen (v1.2.1)
-----> Creating <default-centos-64>...
Step 0 : FROM centos:6.4
...
----> Converging <default-centos-64>...
Preparing files for transfer
Resolving cookbook dependencies with Berkshelf
3.0.0.rc1...
...
402
Wednesday, April 30, 14
http://<EXTERNAL_ADDRESS>:8080
403
Wednesday, April 30, 14
Check plugins
404
Wednesday, April 30, 14
Just defaults
405
Wednesday, April 30, 14
jenkins_plugin resource
406
Wednesday, April 30, 14
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)

Mais conteúdo relacionado

Mais procurados

Investigation of testing with ansible
Investigation of testing with ansibleInvestigation of testing with ansible
Investigation of testing with ansible
Dennis Rowe
 

Mais procurados (20)

Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
 
Monitoring and tuning your chef server - chef conf talk
Monitoring and tuning your chef server - chef conf talk Monitoring and tuning your chef server - chef conf talk
Monitoring and tuning your chef server - chef conf talk
 
Steamlining your puppet development workflow
Steamlining your puppet development workflowSteamlining your puppet development workflow
Steamlining your puppet development workflow
 
Network Automation Tools
Network Automation ToolsNetwork Automation Tools
Network Automation Tools
 
Workshop: Know Before You Push 'Go': Using the Beaker Acceptance Test Framewo...
Workshop: Know Before You Push 'Go': Using the Beaker Acceptance Test Framewo...Workshop: Know Before You Push 'Go': Using the Beaker Acceptance Test Framewo...
Workshop: Know Before You Push 'Go': Using the Beaker Acceptance Test Framewo...
 
London Hashicorp Meetup #8 - Testing Programmable Infrastructure By Matt Long
London Hashicorp Meetup #8 -  Testing Programmable Infrastructure By Matt LongLondon Hashicorp Meetup #8 -  Testing Programmable Infrastructure By Matt Long
London Hashicorp Meetup #8 - Testing Programmable Infrastructure By Matt Long
 
Building a Cauldron for Chef to Cook In
Building a Cauldron for Chef to Cook InBuilding a Cauldron for Chef to Cook In
Building a Cauldron for Chef to Cook In
 
Using Nagios with Chef
Using Nagios with ChefUsing Nagios with Chef
Using Nagios with Chef
 
Verifying your Ansible Roles using Docker, Test Kitchen and Serverspec
Verifying your Ansible Roles using Docker, Test Kitchen and ServerspecVerifying your Ansible Roles using Docker, Test Kitchen and Serverspec
Verifying your Ansible Roles using Docker, Test Kitchen and Serverspec
 
Tp install anything
Tp install anythingTp install anything
Tp install anything
 
Investigation of testing with ansible
Investigation of testing with ansibleInvestigation of testing with ansible
Investigation of testing with ansible
 
Drone your Ansible
Drone your AnsibleDrone your Ansible
Drone your Ansible
 
Chef training - Day2
Chef training - Day2Chef training - Day2
Chef training - Day2
 
DevOps Hackathon - Session 1: Vagrant
DevOps Hackathon - Session 1: VagrantDevOps Hackathon - Session 1: Vagrant
DevOps Hackathon - Session 1: Vagrant
 
Introduction to Ansible (Pycon7 2016)
Introduction to Ansible (Pycon7 2016)Introduction to Ansible (Pycon7 2016)
Introduction to Ansible (Pycon7 2016)
 
How Puppet Enables the Use of Lightweight Virtualized Containers - PuppetConf...
How Puppet Enables the Use of Lightweight Virtualized Containers - PuppetConf...How Puppet Enables the Use of Lightweight Virtualized Containers - PuppetConf...
How Puppet Enables the Use of Lightweight Virtualized Containers - PuppetConf...
 
The Modern Developer Toolbox
The Modern Developer ToolboxThe Modern Developer Toolbox
The Modern Developer Toolbox
 
Orchestration? You Don't Need Orchestration. What You Want is Choreography.
Orchestration? You Don't Need Orchestration. What You Want is Choreography.Orchestration? You Don't Need Orchestration. What You Want is Choreography.
Orchestration? You Don't Need Orchestration. What You Want is Choreography.
 
Chef 11 Preview/Chef for OpenStack
Chef 11 Preview/Chef for OpenStackChef 11 Preview/Chef for OpenStack
Chef 11 Preview/Chef for OpenStack
 
Using Vagrant
Using VagrantUsing Vagrant
Using Vagrant
 

Semelhante a Testing Your Automation Code (Docker Version)

Environments - Fundamentals Webinar Series Week 5
Environments - Fundamentals Webinar Series Week 5Environments - Fundamentals Webinar Series Week 5
Environments - Fundamentals Webinar Series Week 5
Chef
 
Test kitchen 1.0 - Fletcher Nichol
Test kitchen 1.0 - Fletcher NicholTest kitchen 1.0 - Fletcher Nichol
Test kitchen 1.0 - Fletcher Nichol
Devopsdays
 

Semelhante a Testing Your Automation Code (Docker Version) (20)

OpenStack Austin Meetup January 2014: Chef + OpenStack
OpenStack Austin Meetup January 2014: Chef + OpenStackOpenStack Austin Meetup January 2014: Chef + OpenStack
OpenStack Austin Meetup January 2014: Chef + OpenStack
 
Puppet Camp London 2014: Keynote
Puppet Camp London 2014: KeynotePuppet Camp London 2014: Keynote
Puppet Camp London 2014: Keynote
 
openQA hands on with openSUSE Leap 42.1 - openSUSE.Asia Summit ID 2016
openQA hands on with openSUSE Leap 42.1 - openSUSE.Asia Summit ID 2016openQA hands on with openSUSE Leap 42.1 - openSUSE.Asia Summit ID 2016
openQA hands on with openSUSE Leap 42.1 - openSUSE.Asia Summit ID 2016
 
The MetaCPAN VM Part II (Using the VM)
The MetaCPAN VM Part II (Using the VM)The MetaCPAN VM Part II (Using the VM)
The MetaCPAN VM Part II (Using the VM)
 
JupyterHub tutorial at JupyterCon
JupyterHub tutorial at JupyterConJupyterHub tutorial at JupyterCon
JupyterHub tutorial at JupyterCon
 
Community Cookbooks & further resources - Fundamentals Webinar Series Part 6
Community Cookbooks & further resources - Fundamentals Webinar Series Part 6Community Cookbooks & further resources - Fundamentals Webinar Series Part 6
Community Cookbooks & further resources - Fundamentals Webinar Series Part 6
 
Puppet and AWS is Easy...?
Puppet and AWS is Easy...?Puppet and AWS is Easy...?
Puppet and AWS is Easy...?
 
Puppet Camp Sydney 2015: Puppet and AWS is easy right.....?
Puppet Camp Sydney 2015: Puppet and AWS is easy right.....? Puppet Camp Sydney 2015: Puppet and AWS is easy right.....?
Puppet Camp Sydney 2015: Puppet and AWS is easy right.....?
 
Chef - Configuration Management for the Cloud
Chef - Configuration Management for the CloudChef - Configuration Management for the Cloud
Chef - Configuration Management for the Cloud
 
Introduction to Chef - Techsuperwomen Summit
Introduction to Chef - Techsuperwomen SummitIntroduction to Chef - Techsuperwomen Summit
Introduction to Chef - Techsuperwomen Summit
 
Node setup, resource, and recipes - Fundamentals Webinar Series Part 2
Node setup, resource, and recipes - Fundamentals Webinar Series Part 2Node setup, resource, and recipes - Fundamentals Webinar Series Part 2
Node setup, resource, and recipes - Fundamentals Webinar Series Part 2
 
Chef Fundamentals Training Series Module 3: Setting up Nodes and Cookbook Aut...
Chef Fundamentals Training Series Module 3: Setting up Nodes and Cookbook Aut...Chef Fundamentals Training Series Module 3: Setting up Nodes and Cookbook Aut...
Chef Fundamentals Training Series Module 3: Setting up Nodes and Cookbook Aut...
 
Environments - Fundamentals Webinar Series Week 5
Environments - Fundamentals Webinar Series Week 5Environments - Fundamentals Webinar Series Week 5
Environments - Fundamentals Webinar Series Week 5
 
Test kitchen 1.0 - Fletcher Nichol
Test kitchen 1.0 - Fletcher NicholTest kitchen 1.0 - Fletcher Nichol
Test kitchen 1.0 - Fletcher Nichol
 
Getting started with Octopus Deploy
Getting started with Octopus DeployGetting started with Octopus Deploy
Getting started with Octopus Deploy
 
Testing with PostgreSQL
Testing with PostgreSQLTesting with PostgreSQL
Testing with PostgreSQL
 
Plone Testing Tools And Techniques
Plone Testing Tools And TechniquesPlone Testing Tools And Techniques
Plone Testing Tools And Techniques
 
Node object and roles - Fundamentals Webinar Series Part 3
Node object and roles - Fundamentals Webinar Series Part 3Node object and roles - Fundamentals Webinar Series Part 3
Node object and roles - Fundamentals Webinar Series Part 3
 
Continuous delivery with jenkins, docker and exoscale
Continuous delivery with jenkins, docker and exoscaleContinuous delivery with jenkins, docker and exoscale
Continuous delivery with jenkins, docker and exoscale
 
Chef - Administration for programmers
Chef - Administration for programmersChef - Administration for programmers
Chef - Administration for programmers
 

Último

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Último (20)

Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 

Testing Your Automation Code (Docker Version)

  • 1. v0.0.1 Testing Your Automation Code Mischa Taylor (@misheska) misheska@getchef.com Copyright (C) 2014 Chef Software, Inc. 1 Wednesday, April 30, 14
  • 2. v2.0.0 Why Are You Here? 2 Wednesday, April 30, 14
  • 3. 3 You’ve used and want to bulletproof your so that you are with Spec Wednesday, April 30, 14
  • 4. In this class • We’ll add tests to the apache cookbook from the Fundamentals Course • We’ll show you how to run cookbooks in a sandbox environment mirroring production with Test Kitchen • We’ll show you how to detect suspicious cookbook code with Foodcritic & RuboCop • We’ll show you how to produce runnable documentation with ChefSpec 4 Wednesday, April 30, 14
  • 5. Using Chef is half the battle 5 “Chef is like.... tests for your infrastructure” -Ezra Zygmuntowicz, Co-Founder EngineYard http://www.akitaonrails.com/2008/6/5/railsconf-2008-brazil-rails-podcast-special-edition#.U0HfiF7Ed-8 Wednesday, April 30, 14
  • 6. Chef makes things more testable • Chef automates infrastructure in a repeatable fashion 6 Wednesday, April 30, 14
  • 7. What’s the other half of the battle? 7 “Have a plan” -Adam Jacob, Co-Founder Chef Wednesday, April 30, 14
  • 8. There’s no more magic to testing 8 http://www.flickr.com/photos/dkeats/4128747046/sizes/s/in/photostream/ Wednesday, April 30, 14
  • 9. You Are The Testing A-Team When... 9 Wednesday, April 30, 14
  • 10. Recommended plan • Build in quality and robustness up front 10 https://flic.kr/p/8W67ZC Wednesday, April 30, 14
  • 11. Otherwise you could... • Verify and validate just before going to production until time runs out. But time always runs out 11 http://mrg.bz/iEr1oj Wednesday, April 30, 14
  • 12. Waiting to test when it’s “done” 12 Intention: Reality: Build Test Deploy Build T es De ploy We’re late no time to test! Wednesday, April 30, 14
  • 15. Bake testing in earlier 15 Shorter cycles, to start testing early as possible: Build Test Deploy Build Test Deploy Build Test Deploy Wednesday, April 30, 14
  • 16. Penny saved with testing 16 Up Front Testing Saves Money https://www.flickr.com/people/68751915@N05/ Wednesday, April 30, 14
  • 18. Test arrangement • Arrange tests to get feedback fast - at the earliest possible time 18 seconds minutes hours Foodcritic/Rubocop ChefSpec Serverspec Wednesday, April 30, 14
  • 19. Reason for multiple tools • Finding a bug in something that you can’t execute is freaking hard! • While fixing bugs before writing code is cheap, finding them is expensive 19 Wednesday, April 30, 14
  • 20. The Tools • Each tool is specialized to give feedback as early as possible during the cookbook authoring process 20 Wednesday, April 30, 14
  • 21. What each tool does • In your text editor when you type in cookbook code: • Foodcritic analyzes your Chef style • RuboCop analyzes your Ruby coding technique • Before you deploy to a test node: • ChefSpec helps you document and organize your code • After you deploy to a test node: • Serverspec verifies a cookbook behaves as intended 21 Wednesday, April 30, 14
  • 23. Legend: Do I run that command on my workstation? $ whoami i-am-a-workstation This is an example of a command to run on your workstation user@hostname:~$ whoami i-am-a-chef-node This is an example of a command to run on your target node via SSH. 23 Wednesday, April 30, 14
  • 24. $ ifconfig Legend: Example Terminal Command and Output lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 ! options=3<RXCSUM,TXCSUM> ! inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 ! inet 127.0.0.1 netmask 0xff000000 ! inet6 ::1 prefixlen 128 gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280 stf0: flags=0<> mtu 1280 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ! ether 28:cf:e9:1f:79:a3 ! inet6 fe80::2acf:e9ff:fe1f:79a3%en0 prefixlen 64 scopeid 0x4 ! inet 10.100.0.84 netmask 0xffffff00 broadcast 10.100.0.255 ! media: autoselect ! status: active p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304 ! ether 0a:cf:e9:1f:79:a3 ! media: autoselect ! status: inactive 24 Wednesday, April 30, 14
  • 25. OPEN IN EDITOR: SAVE FILE! ~/hello_world Hi! I am a friendly file. Legend: Example of editing a file on your workstation 25 Wednesday, April 30, 14
  • 27. CloudShare Node • Register and login to CloudShare (see invite) • Start Using This Environment 27 Wednesday, April 30, 14
  • 29. Two Virtual Machines 29 We’ll just use the Ubuntu w/Docker image Wednesday, April 30, 14
  • 30. 30 The Ubuntu w/Docker VM will be your Chef Development Workstation for this class Wednesday, April 30, 14
  • 33. $ ssh sysadmin@<EXTERNAL_ADDRESS> Lab - Login The authenticity of host 'uvo1qrwls0jdgs3blvt.vm.cld.sr (69.195.232.110)' can't be established. RSA key fingerprint is d9:95:a3:b9:02:27:e9:cd: 74:e4:a2:34:23:f5:a6:8b. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'uvo1qrwls0jdgs3blvt.vm.cld.sr, 69.195.232.110' (RSA) to the list of known hosts. chef@uvo1qrwls0jdgs3blvt.vm.cld.sr's password: Last login: Mon Jan 6 16:26:24 2014 from host86-145-117-53.range86-145.btcentralplus.com [chef@CentOS63 ~]$ 33 Wednesday, April 30, 14
  • 34. Checkpoint • At this point you should have • One virtual machine (VM) or server that you’ll use for the lab exercises • The IP address or public hostname • An application for establishing an ssh connection • 'sudo' or 'root' permissions on the VM 34 Wednesday, April 30, 14
  • 35. v2.0.0 Workstation Setup - Linux (Docker) Getting started 35 Wednesday, April 30, 14
  • 36. Base OS Install • Ubuntu and Enterprise Linux support the kernel extensions needed for Docker (64-bit only). • Ubuntu is recommended if you are using a VM. The Enterprise Linux package uses the 3.14 kernel which has issues working with the VMware and VirtualBox guest tools. 36 Wednesday, April 30, 14
  • 37. Base OS Install • Recommended Packer templates for building the base OS with Docker: • Ubuntu Server: https://github.com/misheska/basebox-packer/blob/ master/template/ubuntu/ubuntu1204-docker.json • Vagrant Cloud: vagrant  init  learningchef/ubuntu1204-­‐docker 37 Wednesday, April 30, 14
  • 38. Install Chef • Install Chef (if not already installed) http://www.getchef.com/chef/install 38 Wednesday, April 30, 14
  • 41. $ curl -L http://www.getchef.com/chef/install.sh | sudo bash Workstation Setup - Linux % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 14398 100 14398 0 0 56535 0 --:--:-- --:--:-- --:--:-- 78250 Downloading Chef for ubuntu... Installing Chef installing with dpkg... Selecting previously unselected package chef. (Reading database ... 78644 files and directories currently installed.) Unpacking chef (from .../chef_11.12.2-1_amd64.deb) ... Setting up chef (11.12.2-1) ... Thank you for installing Chef! 41 Wednesday, April 30, 14
  • 42. What just happened? • Chef and all of its dependencies installed via an operating system-specific package ("omnibus installer") • Installation includes • The Ruby language - used by Chef • knife - Command line tool for administrators • chef-client - Client application • ohai - System profiler • ...and more 42 Wednesday, April 30, 14
  • 43. OPEN IN EDITOR: $HOME/.bash_profile export PATH="/opt/chef/embedded/bin:$PATH" Add Chef Client to PATH 43 Wednesday, April 30, 14
  • 44. $ source $HOME/.bash_profile Make the profile active 44 Wednesday, April 30, 14
  • 45. $ which ruby Check the PATH setting /opt/chef/embedded/bin/ruby 45 Wednesday, April 30, 14
  • 46. $ chef-client --version Verify Install Chef: 11.12.2 46 Wednesday, April 30, 14
  • 47. Install Developer Tools • Install Developer Tools to build native extensions 47 http://patshaughnessy.net/2011/10/31/dont-be-terrified-of-building-native-extensions Wednesday, April 30, 14
  • 48. Install Developer Tools • Use build-essential cookbook: https://github.com/opscode-cookbooks/build- essential 48 Wednesday, April 30, 14
  • 49. $ mkdir /tmp/cookbooks Temporary area for cookbook downloads 49 Wednesday, April 30, 14
  • 50. $ cd /tmp/cookbooks Easiest to go to cookbooks dir 50 Wednesday, April 30, 14
  • 51. $ knife cookbook site download build-essential $ tar xvf build-essential-*.tar.gz Download build-essential cookbook 51 Wednesday, April 30, 14
  • 52. $ cd /tmp $ sudo chef-client -z -o build-essential Use local mode to run cookbook 52 Wednesday, April 30, 14
  • 53. $ gcc --version Verify Install gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 53 Wednesday, April 30, 14
  • 54. $ cd /tmp/cookbooks Easiest to go to cookbooks dir 54 Wednesday, April 30, 14
  • 55. $ knife cookbook site download git $ knife cookbook site download dmg $ knife cookbook site download windows $ knife cookbook site download runit $ knife cookbook site download yum $ knife cookbook site download yum-epel $ knife cookbook site download chef_handler Download git cookbook + dependencies 55 Wednesday, April 30, 14
  • 56. $ tar xvf git*.tar.gz $ tar xvf dmg*.tar.gz $ tar xvf windows*.tar.gz $ tar xvf runit*.tar.gz $ tar xvf yum-3*.tar.gz $ tar xvf yum-epel*.tar.gz $ tar xvf chef_handler*.tar.gz Extract cookbook archives 56 Wednesday, April 30, 14
  • 57. $ cd /tmp $ sudo chef-client -z -o git Use local mode to run cookbook 57 Wednesday, April 30, 14
  • 58. $ git --version Verify Install git version 1.7.9.5 58 Wednesday, April 30, 14
  • 59. $ rm -rf /tmp/cookbooks Keep it neat 59 Wednesday, April 30, 14
  • 61. chef-fundamentals-repo • We’re going to build on the chef-fundamentals- repo created in the Chef Fundamentals training, adding tests: https://github.com/learnchef/chef-fundamentals-repo/ tree/master/cookbooks/apache 61 Wednesday, April 30, 14
  • 62. $ cd $HOME Home directory - great place for source 62 $ cd %USERPROFILE% Wednesday, April 30, 14
  • 63. $ git clone https://github.com/learnchef/chef-fundamentals-repo.git Grab the chef-fundamentals repo from GitHub Cloning into 'chef-fundamentals-repo'... remote: Reusing existing pack: 247, done. remote: Total 247 (delta 0), reused 0 (delta 0) Receiving objects: 100% (247/247), 149.52 KiB | 184.00 KiB/s, done. Resolving deltas: 100% (45/45), done. Checking connectivity... done. 63 Wednesday, April 30, 14
  • 64. $ cd chef-fundamentals-repo chef-fundamentals-repo 64 !"" Berksfile !"" cookbooks/ !"" data_bags/ !"" environments/ !"" .git/ !"" README.md !"" roles/ #"" Vagrantfile Wednesday, April 30, 14
  • 65. v2.0.0 Reviewing Cookbooks with Test Kitchen (Docker Version) 65 Wednesday, April 30, 14
  • 66. Apache Clowns & Bears • We’ll be focusing on the Apache Clowns and Bears cookbook in: chef-­‐fundamentals-­‐repo/cookbooks/apache 66 Wednesday, April 30, 14
  • 67. Cookbook Review with Test Kitchen • Test Kitchen is a great environment in which to develop and review cookbooks • Written by Fletcher Nichol 67 Wednesday, April 30, 14
  • 68. Back in my day... • Running a cookbook involved a lot of setup: • Configure workstation • Configure Chef Server • Bootstrap node 68 Wednesday, April 30, 14
  • 69. No longer a chore • Test Kitchen lets you set up sandbox environments in which to run cookbooks right on your Chef development workstation 69 Wednesday, April 30, 14
  • 70. Supported Environments • Test Kitchen supports: • Virtual Machines • Cloud Instances • Metal - Physical Servers • Containers (Docker, LXC, etc.) 70 Wednesday, April 30, 14
  • 71. Sandbox Benefits • A sandbox environment: • Is a safe place to make mistakes • Easily reset to a clean config • Can simulate production 71 Wednesday, April 30, 14
  • 72. Virtual Machines vs. Containers 72 Hypervisor/Host OS Guest OS Core OS Guest OS Guest OS App App App App App App Virtual Machines Containers Wednesday, April 30, 14
  • 73. 73 Test Kitchen is packaged as a Ruby Gem Wednesday, April 30, 14
  • 74. Ruby Gem • A gem is a application or supporting library written in ruby, installable with: 74 gem  install Wednesday, April 30, 14
  • 75. $ sudo gem install test-kitchen --no-ri --no-rdoc Install Test Kitchen 75 $ sudo env "PATH=$PATH" gem install test-kitchen --no-ri --no-rdoc Run As Administrator > gem install test-kitchen --no-ri --no-rdoc Wednesday, April 30, 14
  • 76. Install Test Kitchen 76 Fetching: net-scp-1.1.2.gem (100%) Fetching: safe_yaml-1.0.2.gem (100%) Fetching: thor-0.19.1.gem (100%) Fetching: test-kitchen-1.2.1.gem (100%) Successfully installed net-scp-1.1.2 Successfully installed safe_yaml-1.0.2 Successfully installed thor-0.19.1 Successfully installed test-kitchen-1.2.1 4 gems installed Text Output: Wednesday, April 30, 14
  • 77. OPEN IN EDITOR: $HOME/.gemrc gem: --no-ri --no-rdoc Automatically add --no-ri & --no-rdoc 77 Wednesday, April 30, 14
  • 78. $ cd $HOME/chef-fundamentals-repo/cookbooks/apache Go to Apache cookbook dir 78 Wednesday, April 30, 14
  • 79. 79 We’re going to need a lot of gems Wednesday, April 30, 14
  • 80. Gemfile • A Gemfile can be used to list all the gems you need for cookbook testing 80 Wednesday, April 30, 14
  • 81. Gemfile template • Test Kitchen can generate a Gemfile template (among other things) 81 Wednesday, April 30, 14
  • 82. $ kitchen init --driver=kitchen-docker --create-gemfile create .kitchen.yml create test/integration/default create Gemfile append Gemfile append Gemfile You must run ‘bundle install’ to fetch any new gems. Create Gemfile template 82 Wednesday, April 30, 14
  • 84. $ kitchen init --driver=kitchen-docker --create-gemfile create .kitchen.yml create test/integration/default create Gemfile append Gemfile append Gemfile You must run ‘bundle install’ to fetch any new gems. Create Gemfile template 84 Wednesday, April 30, 14
  • 86. 86 Gemfile is read by: bundle  install to install gems Wednesday, April 30, 14
  • 87. 87 No need to install bundler • Chef install includes the bundler gem • Outside the Chef install, bundler can be installed via: •gem  install  bundler Wednesday, April 30, 14
  • 88. $ bundle install --path vendor/bundle Do what Test Kitchen tells you Fetching gem metadata from https://rubygems.org/.......... Fetching gem metadata from https://rubygems.org/.. Installing mixlib-shellout (1.3.0) Installing net-ssh (2.8.0) Installing net-scp (1.1.2) Installing safe_yaml (1.0.2) Installing thor (0.19.1) Installing test-kitchen (1.2.1) Installing kitchen-docker (1.0.0) Using bundler (1.1.5) Your bundle is complete! It was installed into ./vendor/bundle 88 Wednesday, April 30, 14
  • 89. 89 Vendor Everything • Gems change frequently and sometimes conflict • -­‐-­‐path option passed to bundle  install overrides system gems by installing Gemfile gems locally • Bundler docs recommend using vendor/bundle Wednesday, April 30, 14
  • 90. 90 If you vendor gems use: bundle  exec to read gems in vendor/bunde Wednesday, April 30, 14
  • 91. 91 Test Kitchen commands • Let’s cover a few essential Test Kitchen commands Wednesday, April 30, 14
  • 92. 92 kitchen list • kitchen  list prints out a list of sandbox instances defined in .kitchen.yml Wednesday, April 30, 14
  • 93. $ bundle exec kitchen list kitchen list Instance Driver Provisioner Last Action default-ubuntu-1204 Docker ChefSolo <Not Created> default-centos-64 Docker ChefSolo <Not Created> 93 Wednesday, April 30, 14
  • 94. 94 kitchen create • kitchen  create  <instance_name> spins up a sandbox instance Wednesday, April 30, 14
  • 95. $ bundle exec kitchen create default-centos-64 kitchen create -----> Starting Kitchen (v1.2.1) -----> Creating <default-centos-64>... Step 0 : FROM centos:6.4 ---> 539c0211cd76 Step 1 : RUN yum clean all ---> Using cache ---> 9a4da62cec5e ... "Links": null, "PublishAllPorts": false } }] Finished creating <default-centos-64> (0m4.55s). -----> Kitchen is finished. (0m4.66s) 95 Wednesday, April 30, 14
  • 96. 96 kitchen login • kitchen  login  <instance_name> uses ssh to login to the sandbox instance Wednesday, April 30, 14
  • 97. $ bundle exec kitchen login default-centos-64 kitchen login kitchen@localhost's password: [kitchen@fc9834984e9d ~]$ cat /etc/redhat-release CentOS release 6.4 (Final) [kitchen@fc9834984e9d ~]$ exit logout Connection to localhost closed. 97 Default password is kitchen Wednesday, April 30, 14
  • 98. 98 kitchen destroy • kitchen  destroy  <instance_name> shuts down a sandbox instance and destroys and virtual resources allocated Wednesday, April 30, 14
  • 99. $ bundle exec kitchen destroy default-centos-64 kitchen destroy -----> Starting Kitchen (v1.2.1) -----> Destroying <default-centos-64>... 3d71e7241e317d374f42ac0fc79c0752cb77eb86b4bfd76c068beebdb151dda3 3d71e7241e317d374f42ac0fc79c0752cb77eb86b4bfd76c068beebdb151dda3 Finished destroying <default-centos-64> (0m2.90s). -----> Kitchen is finished. (0m3.07s) 99 Wednesday, April 30, 14
  • 100. 100 kitchen  converge performs a Chef run in the sandbox instance Wednesday, April 30, 14
  • 101. $ bundle exec kitchen converge default-centos-64 Perform Chef run -----> Starting Kitchen (v1.2.1) -----> Creating <default-centos-64>... Step 0 : FROM centos:6.4 ---> 539c0211cd76 Step 1 : RUN yum clean all ---> Using cache ---> 735ba0db794e .... 101 Wednesday, April 30, 14
  • 102. $ bundle exec kitchen converge default-centos-64 Perform Chef run -----> Starting Kitchen (v1.2.1) -----> Creating <default-centos-64>... Step 0 : FROM centos:6.4 ---> 539c0211cd76 Step 1 : RUN yum clean all ---> Using cache ---> 735ba0db794e .... [2014-04-07T02:32:50-04:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1) >>>>>> Converge failed on instance <default-centos-64>. >>>>>> Please see .kitchen/logs/default-centos-64.log for more details >>>>>> ------Exception------- >>>>>> Class: Kitchen::ActionFailed >>>>>> Message: SSH exited (1) for command: [sudo -E chef-solo --config /tmp/kitchen/solo.rb --json- attributes /tmp/kitchen/dna.json --log_level info] >>>>>> ---------------------- 102 FAILWednesday, April 30, 14
  • 103. 103 Our first bit of feedback! Wednesday, April 30, 14
  • 105. 105 Undefined attribute • When you see undefined  method  ‘[]’  for   nil:NilClass it often means you have an undefined attribute • Let’s see if node["motd"]["company"] is being set Wednesday, April 30, 14
  • 106. cookbooks/apache/attributes/default.rb 106 default["apache"]["indexfile"] = "index1.html" default["apache"]["sites"]["clowns"] = { "port" => 80 } default["apache"]["sites"]["bears"] = { "port" => 81 } NOPEWednesday, April 30, 14
  • 107. 107 Undefined attribute • How is ["motd"]["company"] set in the motd cookbook? Wednesday, April 30, 14
  • 109. Good cookbooks • Good cookbooks can be used in isolation • They set reasonable defaults for all attributes used • Test Kitchen is designed to run a cookbook in isolation to give you feedback on attribute use 109 Wednesday, April 30, 14
  • 110. Test attributes • We won’t fix the motd cookbook in this class • Test Kitchen supports injection of test attributes • We’ll supply the correct attribute in the .kitchen.yml configuration file 110 Wednesday, April 30, 14
  • 111. Default .kitchen.yml 111 --- driver: name: docker provisioner: name: chef_solo platforms: - name: ubuntu-12.04 - name: centos-6.4 suites: - name: default run_list: - recipe[apache::default] attributes: Wednesday, April 30, 14
  • 112. .kitchen.yml is a tab-free zone • Spacing matters in a .kitchen.yml file. • .kitchen.yml is a tab-free zone - you will get errors if you try to use tabs. Set your editor accordingly. 112 Wednesday, April 30, 14
  • 113. --- driver: name: docker provisioner: name: chef_solo platforms: - name: ubuntu-12.04 - name: centos-6.4 suites: - name: default run_list: - recipe[apache::default] attributes: motd: {company: Chef} cookbooks/apache/.kitchen.yml Set node[“motd”][“company”] (docker) 113 OPEN IN EDITOR: Wednesday, April 30, 14
  • 114. $ bundle exec kitchen converge default-centos-64 Perform Chef run -----> Starting Kitchen (v1.2.1) -----> Converging <default-centos-64>... Preparing files for transfer Preparing current project directory as a cookbook Removing non-cookbook files before transfer Transfering files to <default-centos-64> [2014-04-07T02:40:01-04:00] INFO: Forking chef instance to converge... Starting Chef Client, version 11.10.4 .... 114 Wednesday, April 30, 14
  • 115. $ bundle exec kitchen converge default-centos-64 Perform Chef run -----> Starting Kitchen (v1.2.1) -----> Converging <default-centos-64>... Preparing files for transfer Preparing current project directory as a cookbook Removing non-cookbook files before transfer Transfering files to <default-centos-64> [2014-04-07T02:40:01-04:00] INFO: Forking chef instance to converge... Starting Chef Client, version 11.10.4 .... [2014-04-07T02:40:03-04:00] INFO: Report handlers complete Chef Client finished, 5/10 resources updated in 2.52587913 seconds Finished converging <default-centos-64> (0m4.15s). -----> Kitchen is finished. (0m4.22s) 115 WIN Wednesday, April 30, 14
  • 116. Where to go next • Learning Chef book excerpt was sent to you are part of the class registration. • Chapter 1 covers Test Kitchen and .kitchen.yml format in more detail. • Appendix provides sample .kitchen.yml configs 116 Wednesday, April 30, 14
  • 117. Where to go next • Vagrant boxes for training image: • VirtualBox 4.3.10 https://s3-us-west-2.amazonaws.com/misheska/vagrant/virtualbox4.3.10/ubuntu1204-docker- chef11.12.2.box • VMware Fusion 6/Workstation 10 https://s3-us-west-2.amazonaws.com/misheska/vagrant/vmware9.6.1/ubuntu1204-docker- chef11.12.2.box • Packer Template https://github.com/misheska/basebox-packer/blob/master/template/ubuntu/ubuntu1204-docker.json 117 Wednesday, April 30, 14
  • 118. Gemfile 118 source 'https://rubygems.org' gem 'test-kitchen' gem 'kitchen-vagrant' Wednesday, April 30, 14
  • 119. VirtualBox - .kitchen.yml 119 --- driver: name: vagrant provisioner: name: chef_solo platforms: - name: ubuntu1204-docker driver: box: ubuntu1204-docker box_url: https://s3-us-west-2.amazonaws.com/misheska/vagrant/ vmware9.6.1/ubuntu1204-docker-chef11.12.2.box customize: memory: 1024 suites: - name: default Wednesday, April 30, 14
  • 120. VMware Fusion 6 - .kitchen.yml 120 --- driver: name: vagrant provisioner: name: chef_solo platforms: - name: ubuntu1204-docker driver: provider: vmware_fusion box: ubuntu1204-docker box_url: https://s3-us-west-2.amazonaws.com/misheska/vagrant/ vmware9.6.1/ubuntu1204-docker-chef11.12.2.box customize: memory: 1024 suites: - name: default Wednesday, April 30, 14
  • 121. VMware Workstation 10 - .kitchen.yml 121 --- driver: name: vagrant provisioner: name: chef_solo platforms: - name: ubuntu1204-docker driver: provider: vmware_workstation box: ubuntu1204-docker box_url: https://s3-us-west-2.amazonaws.com/misheska/vagrant/ vmware9.6.1/ubuntu1204-docker-chef11.12.2.box customize: memory: 1024 suites: - name: default Wednesday, April 30, 14
  • 122. v2.0.0 Automated Verification in Test Kitchen with Serverspec (Docker Version) 122 Wednesday, April 30, 14
  • 123. 123 Let’s verify that the Apache cookbook actually works by configuring Test Kitchen to allow web browser access by the Chef Development workstation Wednesday, April 30, 14
  • 124. OPEN IN EDITOR: cookbooks/apache/.kitchen.yml --- driver: name: docker provisioner: name: chef_solo platforms: - name: centos-6.4 driver_config: forward: - 80:80 suites: - name: default run_list: - recipe[apache::default] attributes: motd: {company: Chef} Network config - clowns 124 Wednesday, April 30, 14
  • 125. $ bundle exec kitchen destroy default-centos-64 Network reconfig requires destroy -----> Starting Kitchen (v1.2.1) -----> Destroying <default-centos-64>... 5b88b1806d613be02bfcd14f359c8d9bb1d77f06bbce7e423c0e3100fee73177 5b88b1806d613be02bfcd14f359c8d9bb1d77f06bbce7e423c0e3100fee73177 Finished destroying <default-centos-64> (0m0.47s). -----> Kitchen is finished. (0m0.53s) 125 Wednesday, April 30, 14
  • 126. $ bundle exec kitchen converge default-centos-64 Perform Chef run -----> Starting Kitchen (v1.2.1) -----> Creating <default-centos-64>... Step 0 : FROM centos:6.4 ---> 539c0211cd76 Step 1 : RUN yum clean all ---> Using cache ---> 735ba0db794e Step 2 : RUN yum install -y sudo openssh-server openssh- clients curl ---> Using cache ---> 37c081ac2580 .... 126 Wednesday, April 30, 14
  • 128. $ curl localhost:80 Does it blend? <html> <body> <h1>Welcome to Chef</h1> <h2>We love clowns</h2> 172.17.0.2:80 </body> </html> 128 Wednesday, April 30, 14
  • 129. $ curl localhost:80 Does it blend? <html> <body> <h1>Welcome to Chef</h1> <h2>We love clowns</h2> 172.17.0.2:80 </body> </html> 129 WIN Wednesday, April 30, 14
  • 130. Clowns in your web browser 130 •You can access the clowns web site using the external address for your CloudShare workstation Wednesday, April 30, 14
  • 134. OPEN IN EDITOR: cookbooks/apache/.kitchen.yml --- driver: name: docker provisioner: name: chef_solo platforms: - name: centos-6.4 driver_config: forward: - 80:80 - 81:81 suites: - name: default run_list: - recipe[apache::default] attributes: motd: {company: Chef} Network config - bears 134 Wednesday, April 30, 14
  • 135. $ bundle exec kitchen destroy default-centos-64 Network reconfig requires destroy -----> Starting Kitchen (v1.2.1) -----> Destroying <default-centos-64>... 5b88b1806d613be02bfcd14f359c8d9bb1d77f06bbce7e423c0e3100fee73177 5b88b1806d613be02bfcd14f359c8d9bb1d77f06bbce7e423c0e3100fee73177 Finished destroying <default-centos-64> (0m0.47s). -----> Kitchen is finished. (0m0.53s) 135 Wednesday, April 30, 14
  • 136. $ bundle exec kitchen converge default-centos-64 Perform Chef run -----> Starting Kitchen (v1.2.1) -----> Creating <default-centos-64>... Step 0 : FROM centos:6.4 ---> 539c0211cd76 Step 1 : RUN yum clean all ---> Using cache ---> 735ba0db794e Step 2 : RUN yum install -y sudo openssh-server openssh-clients curl ---> Using cache ---> 37c081ac2580 .... [2014-04-07T03:06:36-04:00] INFO: Report handlers complete Chef Client finished, 11/11 resources updated in 24.32934282 seconds Finished converging <default-centos-64> (0m38.09s). -----> Kitchen is finished. (0m38.33s) 136 Wednesday, April 30, 14
  • 138. $ curl localhost:81 Does it blend? <html> <body> <h1>Welcome to Chef</h1> <h2>We love bears</h2> 172.17.0.2:81 </body> </html> 138 Wednesday, April 30, 14
  • 142. Serverspec author • Written by Gosuke Miyashita 142 Wednesday, April 30, 14
  • 143. OPEN IN EDITOR: cookbooks/apache/Gemfile source 'https://rubygems.org' gem 'test-kitchen' gem 'kitchen-vagrant' gem 'serverspec', '~> 1.1' Add serverspec to Gemfile 143 Wednesday, April 30, 14
  • 144. OPEN IN EDITOR: cookbooks/apache/Gemfile source 'https://rubygems.org' gem 'test-kitchen' gem 'kitchen-vagrant' gem 'serverspec', '~> 1.1' Add serverspec to Gemfile 144 PessimisticVersion Constraint Wednesday, April 30, 14
  • 145. Version Constraint 145 •If a gem properly follows semantic versioning with its versioning scheme. You can take advantage of this to choose a version constraint to lock down the gem in your application. http://guides.rubygems.org/patterns/#declaring_dependencies Wednesday, April 30, 14
  • 146. Semantic Versioning 146 Given a version number MAJOR.MINOR.PATCH, increment the: 1.MAJOR version when you make incompatible API changes, 2.MINOR version when you add functionality in a backwards- compatible manner, and 3.PATCH version when you make backwards-compatible bug fixes. Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format. http://guides.rubygems.org/patterns/#semantic_versioning Wednesday, April 30, 14
  • 147. Versioning Example 147 Let’s say the following releases of a gem exist: ■Version 2.1.0 — Baseline ■Version 2.2.0 — Introduced some new (backward compatible) features. ■Version 2.2.1 — Removed some bugs ■Version 2.2.2 — Streamlined your code ■Version 2.3.0 — More new features (but still backwards compatible). ■Version 3.0.0 — Reworked the interface. Code written to version 2.x might not work. http://guides.rubygems.org/patterns/#semantic_versioning Wednesday, April 30, 14
  • 148. Version Constraint 148 gem 'library', '= 2.2.0' Only use version 2.2.0 Wednesday, April 30, 14
  • 149. Optimistic Version Constraint 149 gem 'library', '>= 2.2.0' Assume all changes from 2.x on will work, including 3.0.0 and higher Wednesday, April 30, 14
  • 150. Pessimistic Version Constraint 150 gem 'library', '>= 2.2.0', ‘< 3.0’ Explicitly exclude any versions that might break your code Wednesday, April 30, 14
  • 151. Pessimistic Version Constraint 151 gem 'library', '>= 2.2.0', ‘< 3.0’ Shorthand for: Using the twiddle-wakka: gem 'library', '~> 2.2' Wednesday, April 30, 14
  • 152. $ bundle install Install Serverspec 152 $ CONFIGURE_ARGS="--with-ldflags= '-Wno-error=unused-command-line-argument-hard-error-in- future'" bundle install clang 5.1 Workaround Wednesday, April 30, 14
  • 154. Documentation form 154 describe  ‘<entity>’  do    <descriptions  here> end Wednesday, April 30, 14
  • 155. Documentation example 155 describe  ‘clowns  site’  do    ... end Wednesday, April 30, 14
  • 156. Description form 156 describe  ‘<entity>’  do    it  ‘<description>’  do          ...    end end Wednesday, April 30, 14
  • 157. Description example 157 describe  ‘clowns  site’  do    it  ‘responds  on  port  80’  do        ...    end end Wednesday, April 30, 14
  • 158. Expectation form 158 describe  ‘<entity>’  do    it  ‘<description>’  do        expect(thing).to  eq  result    end end Wednesday, April 30, 14
  • 159. Expectation form 159 describe  ‘<entity>’  do    it  ‘<description>’  do        expect(thing).to  eq  result    end end Matcher Wednesday, April 30, 14
  • 160. Expectation example 160 describe  ‘clowns  site’  do    it  ‘responds  on  port  80’  do        expect(port  80).to  be_listening  ‘tcp’    end end Wednesday, April 30, 14
  • 161. Expectation form 161 describe  ‘<entity>’  do    it  ‘<description>’  do        expect(thing).to  eq  result    end end This is new syntax Wednesday, April 30, 14
  • 162. Should vs Expect 162 describe  ‘clowns  site’  do    it  ‘responds  on  port  80’  do        expect(port  80).to  be_listening  ‘tcp’    end end Expect Form One-Liner Should Form describe  ‘clowns  site’  do    describe  port(80)  do        it  {  should  be_listening.with(‘tcp’)  }    end end Wednesday, April 30, 14
  • 163. Expect vs. Should 163 Debate on whether or not to use expect vs. should is epic: http://myronmars.to/n/dev-blog/2012/06/rspecs-new- expectation-syntax ...and pointless. Use whatever makes the most sense to you. There are some technical limitations to the ‘should’ form, but if you stick to the “one-liner should” syntax, they are essentially interchangeable. Wednesday, April 30, 14
  • 164. We Use Expect Form 164 Because all the ChefSpec examples are in the expect form Wednesday, April 30, 14
  • 165. 165 Let’s write some serverspec tests! Wednesday, April 30, 14
  • 166. 166 Default location for tests • By default, Test Kitchen will look in the test/ integration directory for test-related files • For convenience, Test Kitchen creates this directory when you run kitchen  init Wednesday, April 30, 14
  • 167. chef-fundamentals-repo 167 . !"" attributes/ !"" .bundle/ !"" CHANGELOG.md !"" files/ !"" Gemfile !"" Gemfile.lock !"" .kitchen/ !"" .kitchen.yml !"" metadata.rb !"" README.md !"" recipes/ !"" templates/ !"" test/ $   #"" integration/ #"" vendor/ Wednesday, April 30, 14
  • 168. 168 Suite subdirectory • Test Kitchen requires a few more directories underneath test/integration • First directory name underneath test/integration should match the suite name: └──  test/        └──  integration/                └──  <suite_name>/ Wednesday, April 30, 14
  • 169. OPEN IN EDITOR: cookbooks/apache/.kitchen.yml --- driver: name: docker provisioner: name: chef_solo platforms: - name: centos-6.4 driver_config: forward: - 80:80 - 81:81 suites: - name: default run_list: - recipe[apache::default] attributes: motd: {company: Chef} Network configuration 169 Suite name Wednesday, April 30, 14
  • 170. 170 Suite subdirectory • Our suite name is default └──  test/        └──  integration/                └──  default/ Wednesday, April 30, 14
  • 171. 171 Busser directory • The next directory level denotes the test plugin, as Test Kitchen many different kinds of test plugins. A test plugin is called a busser. We’ll be using the busser directory called serverspec. └──  test/        └──  integration/                └──  default/                        └──  serverspec/ Wednesday, April 30, 14
  • 172. 172 Hostname directory • Serverspec supports testing via SSH, so it requires yet another directory level to denote the hostname. We won’t be using this capability, so it should be localhost └──  test/        └──  integration/                └──  default/                        └──  serverspec/                                └──  localhost/ Wednesday, April 30, 14
  • 173. 173 Hostname directory • NOTE: Use of the localhost directory is optional Wednesday, April 30, 14
  • 174. $ cd $HOME/chef-fundamentals-repos/cookbooks/apache Make sure you are in the apache cookbook root 174 > cd %USERPROFILE%/chef-fundamentals-repos/cookbooks/apache Wednesday, April 30, 14
  • 175. $ mkdir -p test/integration/default/serverspec Create test directory structure 175 > mkdir testintegrationdefaultserverspec Wednesday, April 30, 14
  • 176. 176 *_spec.rb files • By convention, Test Kitchen expects files with tests to end in _spec.rb Wednesday, April 30, 14
  • 177. Serverspec expectation form • Every specialized RSpec-based testing library like serverspec has their own special twist on the basic RSpec expectation form 177 Wednesday, April 30, 14
  • 178. Generic Expectation Form 178 describe  ‘<entity>’  do    it  ‘<description>’  do        expect(thing).to  eq  result    end end Wednesday, April 30, 14
  • 179. Serverspec Command 179 describe  ‘<entity>’  do    it  ‘<description>’  do        expect(command).to  eq  result    end end thing to expect is called a command in serverspec Wednesday, April 30, 14
  • 180. Serverspec commands & matchers • Serverspec has provides a wide variety of matchers for each command • Serverspec commands are well-documented: http:// serverspec.org/resource_types.html 180 Wednesday, April 30, 14
  • 183. 183 Writing your first test • Let’s create a serverspec test checking to make sure the clowns web site is active on port 80 • Let’s use the port resource and the be_listening matcher Wednesday, April 30, 14
  • 184. Spec for clowns 184 require 'serverspec' include Serverspec::Helper::Exec describe 'clowns site' do it 'responds on port 80' do expect(port 80).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/clown_spec.rb Wednesday, April 30, 14
  • 185. 185 kitchen setup • Before running tests you need to run kitchen   setup • kitchen  setup loads and configures the file necessary to run test plugins on the node • The component that manages Test Kitchen plugins is called Busser Wednesday, April 30, 14
  • 186. $ bundle exec kitchen setup default-centos-64 kitchen setup -----> Starting Kitchen (v1.2.1) -----> Setting up <default-centos-64>... Fetching: thor-0.19.0.gem (100%) Fetching: busser-0.6.2.gem (100%) Successfully installed thor-0.19.0 Successfully installed busser-0.6.2 2 gems installed -----> Setting up Busser Creating BUSSER_ROOT in /tmp/busser Creating busser binstub Plugin serverspec installed (version 0.2.6) -----> Running postinstall for serverspec plugin Finished setting up <default-centos-64> (0m34.28s). -----> Kitchen is finished. (0m34.37s) 186 Wednesday, April 30, 14
  • 187. 187 kitchen verify • The kitchen  verify command will run the tests in your *_spec.rb files in the test/integration tree Wednesday, April 30, 14
  • 188. $ bundle exec kitchen verify default-centos-64 kitchen verify -----> Starting Kitchen (v1.2.1) -----> Verifying <default-centos-64>... Removing /tmp/busser/suites/serverspec Uploading /tmp/busser/suites/serverspec/localhost/clown_spec.rb (mode=0664) -----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/ rspec /tmp/busser/suites/serverspec/localhost/clown_spec.rb --color --format documentation clowns site responds on port 80 Finished in 0.00713 seconds 1 example, 0 failures Finished verifying <default-centos-64> (0m0.90s). -----> Kitchen is finished. (0m0.97s) 188 Wednesday, April 30, 14
  • 189. 189 Verifying that the tests work • Did the test actually do anything? Let’s verify this by changing the port to a known incorrect value. Wednesday, April 30, 14
  • 190. Replace port 80 with 85 190 require 'serverspec' include Serverspec::Helper::Exec describe 'clowns site' do it 'responds on port 85' do expect(port 85).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/clown_spec.rb Wednesday, April 30, 14
  • 191. $ bundle exec kitchen verify default-centos-64 This should fail -----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/ suites/serverspec/localhost/clown_spec.rb --color --format documentation clowns site responds on port 85 (FAILED - 1) Failures: 1) clowns site responds on port 85 Failure/Error: expect(port 85).to be_listening 'tcp' netstat -tunl | grep -- :85 expected Port "85" to be listening "tcp" # /tmp/busser/suites/serverspec/localhost/clown_spec.rb:7:in `block (2 levels) in <top (required)>' Finished in 0.00718 seconds 1 example, 1 failure ... 191 Wednesday, April 30, 14
  • 192. $ bundle exec kitchen verify default-centos-64 This should fail -----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/ suites/serverspec/localhost/clown_spec.rb --color --format documentation clowns site responds on port 85 (FAILED - 1) Failures: 1) clowns site responds on port 85 Failure/Error: expect(port 85).to be_listening 'tcp' netstat -tunl | grep -- :85 expected Port "85" to be listening "tcp" # /tmp/busser/suites/serverspec/localhost/clown_spec.rb:7:in `block (2 levels) in <top (required)>' Finished in 0.00718 seconds 1 example, 1 failure ... 192 WIN FAILWednesday, April 30, 14
  • 193. 193 Back to success • Remember to reset the tests back to the original port value so they succeed again! Wednesday, April 30, 14
  • 194. Reset back to port 80 194 require 'serverspec' include Serverspec::Helper::Exec describe 'clowns site' do it 'responds on port 80' do expect(port 80).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/clown_spec.rb Wednesday, April 30, 14
  • 195. $ bundle exec kitchen verify default-centos-64 kitchen verify -----> Starting Kitchen (v1.2.1) -----> Verifying <default-centos-64>... Removing /tmp/busser/suites/serverspec Uploading /tmp/busser/suites/serverspec/localhost/clown_spec.rb (mode=0664) -----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/ rspec /tmp/busser/suites/serverspec/localhost/clown_spec.rb --color --format documentation clowns site responds on port 80 Finished in 0.00713 seconds 1 example, 0 failures Finished verifying <default-centos-64> (0m0.90s). -----> Kitchen is finished. (0m0.97s) 195 Wednesday, April 30, 14
  • 196. 196 Testing bears • Let’s add another test to do a similar check for the bears port Wednesday, April 30, 14
  • 197. Spec for bears 197 require 'serverspec' include Serverspec::Helper::Exec describe 'bears site' do it 'responds on port 81' do expect(port 81).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/bear_spec.rb Wednesday, April 30, 14
  • 198. 198 No need to run kitchen setup • You only need to run kitchen  setup once per node. (Though it doesn’t hurt to run it more than once). Wednesday, April 30, 14
  • 199. $ bundle exec kitchen verify default-centos-64 Verifying clowns & bears ... ----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/ embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/bear_spec.rb /tmp/busser/ suites/serverspec/localhost/clown_spec.rb --color --format documentation bears site responds on port 81 clowns site responds on port 80 Finished in 0.00889 seconds 2 examples, 0 failures ... 199 Wednesday, April 30, 14
  • 200. 200 Code cleanup • Common code can be moved to a file called spec_helper.rb in test/integration/default/ serverspec • Test Kitchen automatically looks for spec_helper.rb in test/integration/default/ serverspec Wednesday, April 30, 14
  • 201. 201 Code cleanup • Let’s move common code between clowns & bears to spec_helper.rb Wednesday, April 30, 14
  • 202. spec_helper.rb 202 require 'serverspec' include Serverspec::Helper::Exec OPEN IN EDITOR: apache/test/integration/default/serverspec/spec_helper.rb Wednesday, April 30, 14
  • 203. require spec_helper clowns 203 require 'spec_helper' describe 'clowns site' do it 'responds on port 80' do expect(port 80).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/clown_spec.rb Wednesday, April 30, 14
  • 204. require spec_helper bears 204 require 'spec_helper' describe 'bears site' do it 'responds on port 81' do expect(port 81).to be_listening 'tcp' end end OPEN IN EDITOR: apache/test/integration/default/serverspec/bear_spec.rb Wednesday, April 30, 14
  • 205. $ bundle exec kitchen verify default-centos-64 Testing clowns and bears w/spec_helper.rb ... ----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/ embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/bear_spec.rb /tmp/busser/ suites/serverspec/localhost/clown_spec.rb --color --format documentation bears site response on port 81 clowns site responds on port 80 Finished in 0.00889 seconds 2 examples, 0 failures ... 205 Wednesday, April 30, 14
  • 206. $ bundle exec kitchen verify default-centos-64 Testing clowns and bears w/spec_helper.rb ... ----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/ embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/bear_spec.rb /tmp/busser/ suites/serverspec/localhost/clown_spec.rb --color --format documentation bears site response on port 81 clowns site responds on port 80 Finished in 0.00889 seconds 2 examples, 0 failures ... 206 WINWednesday, April 30, 14
  • 207. 207 Are the web sites really working? • While we’ve added checks to verify that the test node is listening on ports 80 and 81, we haven’t verified that users see the right content when they visit these sites. • Let’s use the command resource with the return_stdout matcher to do a simple check with curl to verify that port 80 is clowns and port 81 is bears. Wednesday, April 30, 14
  • 209. Check clown content 209 require 'spec_helper' describe 'clowns site' do it 'responds on port 80' do expect(port 80).to be_listening 'tcp' end it 'returns clowns in the HTML body' do expect(command 'curl localhost:80').to return_stdout(/clowns/) end end OPEN IN EDITOR: apache/test/integration/default/serverspec/clown_spec.rb Wednesday, April 30, 14
  • 211. Check bear content 211 require 'spec_helper' describe 'bears site' do it 'responds on port 81' do expect(port 81).to be_listening 'tcp' end it 'returns bears in the HTML body' do expect(command 'curl localhost:81').to return_stdout(/bears/) end end OPEN IN EDITOR: apache/test/integration/default/serverspec/bear_spec.rb Wednesday, April 30, 14
  • 212. $ bundle exec kitchen verify default-centos-64 Testing for content ... -----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/ suites/serverspec/localhost/bear_spec.rb /tmp/busser/suites/serverspec/localhost/clown_spec.rb --color -- format documentation bears site responds on port 81 returns bears in the HTML body clowns site responds on port 80 returns clowns in the HTML body Finished in 0.0293 seconds 4 examples, 0 failures Finished verifying <default-centos-64> (0m1.73s). -----> Kitchen is finished. (0m1.79s) ... 212 WINWednesday, April 30, 14
  • 213. 213 Detecting the target OS • Many of the resources require that Serverspec detect the OS so it can run the correct command for your platform expect(package  'httpd').to  be_installed • You’ll need to add an extra Helper to spec_helper.rb Wednesday, April 30, 14
  • 214. spec_helper.rb 214 require 'serverspec' include Serverspec::Helper::Exec include Serverspec::Helper::DetectOS OPEN IN EDITOR: apache/test/integration/default/serverspec/spec_helper.rb Wednesday, April 30, 14
  • 215. Check httpd package 215 require 'spec_helper' describe 'server' do it 'has apache installed' do expect(package 'httpd').to be_installed end end OPEN IN EDITOR: apache/test/integration/default/serverspec/default_spec.rb Wednesday, April 30, 14
  • 216. $ bundle exec kitchen verify default-centos-64 Testing for httpd ... -----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/ suites/serverspec/localhost/bear_spec.rb /tmp/busser/suites/serverspec/localhost/clown_spec.rb --color -- format documentation bears site responds on port 81 returns bears in the HTML body clowns site responds on port 80 returns clowns in the HTML body Finished in 0.0293 seconds 4 examples, 0 failures Finished verifying <default-centos-64> (0m1.73s). -----> Kitchen is finished. (0m1.79s) ... 216 WINWednesday, April 30, 14
  • 217. 217 kitchen test • The kitchen  test command will automate all the previous actions you’ve learned so far into one command. It runs the following commands in sequence: • kitchen  destroy (if necessary) •kitchen  create •kitchen  converge •kitchen  setup •kitchen  verify •kitchen  destroy Wednesday, April 30, 14
  • 218. 218 kitchen test • The kitchen  test command is intended to be used as a final check on a fresh image before committing changes to source control and/or to be used in a Continuous Integration environment like Jenkins. Wednesday, April 30, 14
  • 219. $ bundle exec kitchen test default-centos-64 kitchen test -----> Starting Kitchen (v1.2.1) -----> Cleaning up any prior instances of <default-centos-64> -----> Destroying <default-centos-64>... 2c46b1a4609dc6a2beaf44e1134638b0a8ac47c9c5a02baee0bdb3df64e7bcdf 2c46b1a4609dc6a2beaf44e1134638b0a8ac47c9c5a02baee0bdb3df64e7bcdf Finished destroying <default-centos-64> (0m0.60s). -----> Testing <default-centos-64> -----> Creating <default-centos-64>... ... Finished in 0.0311 seconds 4 examples, 0 failures Finished verifying <default-centos-64> (0m1.71s). -----> Destroying <default-centos-64>... d22a8c4db8505f89f7f7e65bca26492f58d5637f9a88763d5eb919d860dade4e d22a8c4db8505f89f7f7e65bca26492f58d5637f9a88763d5eb919d860dade4e Finished destroying <default-centos-64> (0m0.47s). Finished testing <default-centos-64> (0m39.78s). -----> Kitchen is finished. (0m39.84s) 219 Wednesday, April 30, 14
  • 220. Where to go next • Jenkins cookbook is chock full of advanced Serverspec techniques: https://github.com/opscode-cookbooks/jenkins 220 Wednesday, April 30, 14
  • 221. Where to go next • jenkins/test/shared/support contains examples for implementing custom Serverspec matchers used in jenkins/test/integration: •describe  jenkins_job('my-­‐project')  do    it  {  should  be_a_jenkins_job  } end 221 Wednesday, April 30, 14
  • 222. Where to go next • test/fixtures contains mini-cookbooks to exercise resource providers • Aliased in Berksfile: •cookbook  'smoke',  path:  'test/fixtures/ cookbooks/smoke' • Run via Rakefile 222 Wednesday, April 30, 14
  • 223. Where to go next • Uses data/path directive in .kitchen.yml to share test data between serverspec suites • Directory specified in data/path is copied to /tmp/ kitchen/data on guest • Reason for weird require_relative directive in tests that use custom Serverspec matchers: require_relative  '../../../kitchen/data/ spec_helper' 223 Wednesday, April 30, 14
  • 224. RECAP: Why Test? • It’s important to find bugs fast 224 Wednesday, April 30, 14
  • 225. Better, Faster, Stronger • Test Kitchen is an invaluable tool for managing sandbox environments and truly verifying that a cookbook produces the intended results • But it does require spinning up an instance and performing a full Chef converge, which can take a long time • Use Test Kitchen judiciously. The other tools can provide more limited forms of feedback faster. 225 Wednesday, April 30, 14
  • 226. v2.0.0 Detect Suspicious Cookbook Code with Foodcritic 226 Wednesday, April 30, 14
  • 227. Feedback on Chef Coding Style • Foodcritic provides feedback on your Chef coding style • It is designed to be used as you are writing Chef code - how’s that for freaking fast! • Written by Andrew Crump http://acrmp.github.com/footcritic 227 Wednesday, April 30, 14
  • 228. Feedback on Chef Coding Style • Let’s install Foodcritic on your development workstation so you can give it a spin • Add Foodcritic to your Gemfile • Install the app with bundle  install 228 Wednesday, April 30, 14
  • 229. OPEN IN EDITOR: cookbooks/apache/Gemfile source 'https://rubygems.org' gem 'test-kitchen' gem 'kitchen-vagrant' gem 'serverspec', '~> 1.1' gem 'foodcritic', '~> 3.0' Add foodcritic to Gemfile 229 Wednesday, April 30, 14
  • 230. $ sudo yum install -y libxslt-devel libxml2-devel Install Prerequisites 230 $ sudo apt-get install -y libxslt-dev libxml2-dev Wednesday, April 30, 14
  • 231. $ bundle install Install Foodcritic 231 $ CONFIGURE_ARGS="--with-ldflags= '-Wno-error=unused-command-line-argument-hard-error-in- future'" bundle install clang 5.1 Workaround Wednesday, April 30, 14
  • 232. $ bundle exec foodcritic --version Verify install foodcritic 3.0.3 232 Wednesday, April 30, 14
  • 233. $ bundle exec foodcritic . Run Foodcritic on your cookbook 233 FC003: Check whether you are running with chef server before using server-specific features: cookbooks/apache/recipes/ip-logger.rb:1 FC008: Generated cookbook metadata needs updating: cookbooks/apache/metadata.rb:2 FC008: Generated cookbook metadata needs updating: cookbooks/apache/metadata.rb:3 Wednesday, April 30, 14
  • 236. Feedback on Chef Coding Style • Foodcritic comes with a set of checks called rules • Foodcritic rules are documented at http:// acrmp.github.io/foodcritic/ • The default rules are a good start, and you can add new rules of your own easily 236 Wednesday, April 30, 14
  • 238. 238 What about the FC003 & FC008 issues in the apache cookbook? Wednesday, April 30, 14
  • 239. FC008 - Generated cookbook metadata needs updating 239 Wednesday, April 30, 14
  • 241. cookbooks/apache/metadata.rb 241 name 'apache' maintainer 'YOUR_COMPANY_NAME' maintainer_email 'YOUR_EMAIL' license 'All rights reserved' description 'Installs/Configures apache' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version '0.2.0' Wednesday, April 30, 14
  • 242. OPEN IN EDITOR: cookbooks/apache/metadata.rb name 'apache' maintainer 'Mischa Taylor' maintainer_email 'misheska@getchef.com' license 'All rights reserved' description 'Installs/Configures apache' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version '0.2.0' 242 Addressing FC008 Wednesday, April 30, 14
  • 243. $ bundle exec foodcritic . Rerun foodcritic 243 FC003: Check whether you are running with chef server before using server- specific features: ./recipes/ip- logger.rb:1 Wednesday, April 30, 14
  • 244. 244 Two down, one to go! Wednesday, April 30, 14
  • 245. FC003 - Check for chef server before using server-specific features 245 Wednesday, April 30, 14
  • 246. 246 Ignoring FC003 • Let’s say, for now, we don’t want to fix ip-­‐ logger.rb, and we’d like to squelch the FC003 check Wednesday, April 30, 14
  • 247. 247 --tags parameter • The -­‐-­‐tags  <TAGS> parameter can be used to specify a list of rules for foodcritic to use •foodcritic  -­‐-­‐tags  FC001,FC002,FC008 • The tilde (~) modifier can be used to ignore specific rules •foodcritic  -­‐-­‐tags  ~FC003 Wednesday, April 30, 14
  • 248. $ bundle exec foodcritic --tags ~FC003 . Ignore FC003 248 Wednesday, April 30, 14
  • 249. $ bundle exec foodcritic --tags ~FC003 . Ignore FC003 249 WINWednesday, April 30, 14
  • 250. 250 Custom rules • Etsy created some custom Foodcritic rules to check for issues that caused production outages/ performance degradation. • Good example for how to create your own custom rules • Documented here: https://github.com/etsy/foodcritic-rules Wednesday, April 30, 14
  • 251. Etsy Foodcritic Rules • ETSY001 - Package or yum_package resource used with :upgrade action • ETSY002 - Execute resource used to run git commands • ETSY003 - Execute resource used to run curl or wget commands • ETSY004 - Execute resource defined without conditional or action :nothing • ETSY005 - Action :restart sent to a core service • ETSY006 - Execute resource used to run chef-provided command • ETSY007 - Package or yum_package resource used to install core package without specific version number 251 Wednesday, April 30, 14
  • 252. $ git clone https://github.com/etsy/ foodcritic-rules ../../foodcritic/etsy $ rm -rf ../../foodcritic/etsy/.git Installing new rules 252 Wednesday, April 30, 14
  • 253. 253 --include parameter • The -­‐-­‐include  <PATH> parameter species additional paths to load rules (shortened with -I) Wednesday, April 30, 14
  • 254. $ bundle exec foodcritic -t ~FC003 -I ../../ foodcritic . Including Custom Rules ETSY005: Action :restart sent to a core service: ./recipes/default.rb:19 ETSY005: Action :restart sent to a core service: ./recipes/default.rb:32 ETSY007: Package or yum_package resource used to install core package without specific version number: ./recipes/default.rb:10 254 Wednesday, April 30, 14
  • 255. 255 Editor support • Many popular editors can be configured to run Foodcritic inside the editor (including Vim, GNU Emacs and Sublime Text). So you can get feedback even faster. Wednesday, April 30, 14
  • 256. v2.0.0 Detect Suspicious Ruby Code with RuboCop 256 Wednesday, April 30, 14
  • 257. RuboCop - Feedback on Ruby Style • Many people new to Ruby would like some guidance on how to write idiomatic Ruby • Get the same kind of feedback for Ruby using RuboCop that you get for Chef Code using Foodcritic (Chef code is Ruby) 257 Wednesday, April 30, 14
  • 258. RuboCop Author • Written by Bozhidar Batsov: https://github.com/bbatsov/rubocop 258 Wednesday, April 30, 14
  • 259. RuboCop - Feedback on Ruby Style • Follows community-driven style guide: https://github.com/bbatsov/ruby-style-guide • Looks at cookbooks for Ruby best practices, not the Chef DSL - that’s Foodcritic 259 Wednesday, April 30, 14
  • 260. RuboCop - Feedback on Ruby Style • Let’s install RuboCop on your development workstation so you can give it a spin • Add RuboCop to your Gemfile • Install the app with bundle  install 260 Wednesday, April 30, 14
  • 261. OPEN IN EDITOR: cookbooks/apache/Gemfile source 'https://rubygems.org' gem 'test-kitchen' gem 'kitchen-vagrant' gem 'serverspec', '~> 1.1' gem 'foodcritic', '~> 3.0' gem 'rubocop', '~> 0.20' Add rubocop to Gemfile 261 Wednesday, April 30, 14
  • 262. $ bundle install Install RuboCop 262 $ CONFIGURE_ARGS="--with-ldflags= '-Wno-error=unused-command-line-argument-hard-error-in- future'" bundle install clang 5.1 Workaround Wednesday, April 30, 14
  • 263. $ bundle exec rubocop --version Verify Install 0.20.1 263 Wednesday, April 30, 14
  • 264. Running RuboCop • Just run the rubocop command - it recursively checks all the *.rb files in all subdirectories underneath the current directory (excluding vendor/) 264 Wednesday, April 30, 14
  • 265. $ bundle exec rubocop Run RuboCop on your cookbook attributes/default.rb:3:19: C: Prefer single-quoted strings when you don't need string interpolation or special symbols. default["apache"]["sites"]["bears"] = { "port" => 81 } ^^^^^^^ attributes/default.rb:3:28: C: Prefer single-quoted strings when you don't need string interpolation or special symbols. default["apache"]["sites"]["bears"] = { "port" => 81 } ^^^^^^^ attributes/default.rb:3:41: C: Prefer single-quoted strings when you don't need string interpolation or special symbols. default["apache"]["sites"]["bears"] = { "port" => 81 } ^^^^^^ 7 files inspected, 52 offenses detected 265 Wednesday, April 30, 14
  • 266. rubocop-todo.yml via --auto-gen-config • rubocop-todo.yml will help generate TODOs for each item on the offense list • It also shows you what config setting can be used to mask each offense, which we’ll need to do for some of these, because Chef code conventions vary slightly from the Rubocop community standards 266 Wednesday, April 30, 14
  • 267. $ bundle exec rubocop --auto-gen-config Generate rubocop-todo.yml attributes/default.rb:3:28: C: Prefer single-quoted strings when you don't need string interpolation or special symbols. default["apache"]["sites"]["bears"] = { "port" => 81 } ^^^^^^^ attributes/default.rb:3:41: C: Prefer single-quoted strings when you don't need string interpolation or special symbols. default["apache"]["sites"]["bears"] = { "port" => 81 } ^^^^^^ 7 files inspected, 52 offenses detected Created rubocop-todo.yml. Run `rubocop --config rubocop-todo.yml`, or add inherit_from: rubocop-todo.yml in a .rubocop.yml file. 267 Wednesday, April 30, 14
  • 268. .rubocop.yml Configures RuboCop • .rubocop.yml can be used to configure RuboCop (similar to .kitchen.yml in Test Kitchen) • We’ll add a settings to ignore things, similar to what we did for Foodcritic, that don’t make as much sense for Chef. • Settings are documented in the RuboCop README: https://github.com/bbatsov/rubocop/blob/master/ README.md • Cop is the RuboCop equivalent of a rule 268 Wednesday, April 30, 14
  • 269. OPEN IN EDITOR: cookbooks/apache/.rubocop.yml inherit_from:  rubocop-­‐todo.yml Include rubocop-todo.yml 269 Wednesday, April 30, 14
  • 270. $ bundle exec rubocop Run RuboCop on your cookbook Inspecting 7 files ....... 7 files inspected, no offenses detected 270 Wednesday, April 30, 14
  • 271. Easy peasy • Wow, now more offenses...not really 271 Wednesday, April 30, 14
  • 272. Match Chef community standards • First, we’ll move some of the Cops from rubocop- todo.yml to .rubocop.yml for things that match Chef community standards (as opposed to the Ruby community standards) 272 Wednesday, April 30, 14
  • 273. Missing utf-8 encoding comment 273 Wednesday, April 30, 14
  • 274. OPEN IN EDITOR: cookbooks/apache/.rubocop.yml inherit_from:  rubocop-­‐todo.yml Encoding:    Enabled:  false Chef does not (yet) support encoding comment 274 Wednesday, April 30, 14
  • 275. Line is too long 275 Wednesday, April 30, 14
  • 276. OPEN IN EDITOR: cookbooks/apache/.rubocop.yml inherit_from:  rubocop-­‐todo.yml Encoding:    Enabled:  false LineLength:    Max:  200 Relax line limit 276 Wednesday, April 30, 14
  • 277. Use the new Ruby 1.9 hash syntax 277 Wednesday, April 30, 14
  • 278. OPEN IN EDITOR: cookbooks/apache/.rubocop.yml inherit_from:  rubocop-­‐todo.yml Encoding:    Enabled:  false LineLength:    Max:  200 HashSyntax:  EnforcedStyle:  hash_rockets Some cookbooks try to be Ruby 1.8 compatible 278 Wednesday, April 30, 14
  • 280. OPEN IN EDITOR: cookbooks/apache/.rubocop.yml inherit_from:  rubocop-­‐todo.yml Encoding:    Enabled:  false LineLength:    Max:  200 HashSyntax:    EnforcedStyle:  hash_rockets StringLiterals:    Enabled:  false Conflicts w/decision to relax FC002 280 Wednesday, April 30, 14
  • 281. $ bundle exec rubocop --auto-gen-config Regenerate rubocop-todo.yml metadata.rb:2:11: C: Put one space between the method name and the first argument. maintainer 'Mischa Taylor' ^^^^^^^ metadata.rb:4:8: C: Put one space between the method name and the first argument. license 'All rights reserved' ^^^^^^^^^^ metadata.rb:5:12: C: Put one space between the method name and the first argument. description 'Installs/Configures apache' ^^^^^^ metadata.rb:7:8: C: Put one space between the method name and the first argument. version '0.2.0' ^^^^^^^^^^ 7 files inspected, 11 offenses detected 281 Wednesday, April 30, 14
  • 282. Rubocop Workflow • Uncomment lines in rubocop-todo.yml • Fix offenses • git commit • Repeat 282 Wednesday, April 30, 14
  • 283. Only really critical issue 283 Wednesday, April 30, 14
  • 284. Trailing whitespace & Git • Whitespace differences make diffs longer and diverts focus from more important changes • Even with Git, trailing whitespace can make merge conflicts more difficult to resolve 284 Wednesday, April 30, 14
  • 285. 285 Editor support • Many popular editors can be configured to run RuboCop inside the editor (including Vim, GNU Emacs and Sublime Text). So you can get feedback even faster. • RuboCop includes great docs on editor configuration (which work for Foodcritic as well): https://github.com/bbatsov/rubocop#editor- integration Wednesday, April 30, 14
  • 287. RECAP: Why Not Begin With Testing? • Finding a bug in something that you can’t execute is freaking hard! • While fixing bugs before writing code is cheap, finding them is expensive 287 Wednesday, April 30, 14
  • 288. What is ChefSpec? • ChefSpec helps produce runnable documentation. Its primary purpose is to help document and organize your code. • As a side effect, you’ll end up with a set of tests which can also be used to uncover bugs when changes are made. • Plus, your cookbook code will be improved when it is guided by tests. 288 Wednesday, April 30, 14
  • 289. ChefSpec Authors • Written by Andrew Crump and Seth Vargo 289 Wednesday, April 30, 14
  • 290. ChefSpec - Runnable Documentation • Let’s install ChefSpec on your development workstation so you can give it a spin • Add ChefSpec to your Gemfile • Install the app with bundle  install 290 Wednesday, April 30, 14
  • 291. OPEN IN EDITOR: chef-fundamentals-repo/Gemfile source 'https://rubygems.org' gem 'test-kitchen' gem 'kitchen-vagrant' gem 'serverspec', '~> 1.1' gem 'foodcritic', '~> 3.0' gem 'rubocop', '~> 0.20' gem 'chefspec', '~> 3.4' Gemfile 291 Wednesday, April 30, 14
  • 292. $ bundle install Install ChefSpec 292 $ CONFIGURE_ARGS="--with-ldflags= '-Wno-error=unused-command-line-argument-hard-error-in- future'" bundle install clang 5.1 Workaround Wednesday, April 30, 14
  • 293. ChefSpec builds on RSpec • ChefSpec uses the RSpec description form to create runnable documentation (in a similar vein to serverspec) 293 Wednesday, April 30, 14
  • 294. Documentation form 294 describe  ‘<recipe_name>’  do    <perform  in-­‐memory  Chef  run>    <descriptions  here> end Wednesday, April 30, 14
  • 295. Documentation example 295 describe  ‘apache::default’  do    ... end Wednesday, April 30, 14
  • 296. In-Memory Chef Run Form 296 require  ‘chefspec’ describe  ‘<recipe_name>’  do    chef_run  =  ChefSpec::Runner.new.converge(<recipe_name>)    <descriptions  here> end Wednesday, April 30, 14
  • 297. In-Memory Chef Run Example 297 require  ‘chefspec’ describe  'apache::default'  do    chef_run  =  ChefSpec::Runner.new.converge('apache::default')    <descriptions  here> end Wednesday, April 30, 14
  • 298. Expectation form 298 describe  ‘<recipe_name>’  do    <perform  in-­‐memory  Chef  run>    it  ‘<description>’  do        expect(<chef_run>).to  eq  result    end end Wednesday, April 30, 14
  • 299. Expectation form 299 describe  ‘<recipe_name>’  do    <perform  in-­‐memory  Chef  run>    it  ‘<description>’  do        expect(<chef_run>).to  eq  result    end end Matcher Wednesday, April 30, 14
  • 300. Expectation Example 300 require  ‘chefspec’ describe  'apache::default'  do    chef_run  =  ChefSpec::Runner.new.converge('apache::default')    it  ‘installs  apache2’  do        expect(chef_run).to  install_package(‘httpd’)    end end Wednesday, April 30, 14
  • 301. Runnable Documentation • expect statement does not actually perform the httpd package installation • It just verifies the cookbook syntax that it instructs Chef to install the package • Good enough for well-tested primitives like the package resource 301 Wednesday, April 30, 14
  • 302. 302 Let’s write some ChefSpec tests! Wednesday, April 30, 14
  • 303. 303 Default location for tests • By default, ChefSpec will look in the spec/directory for ChefSpec test-related files Wednesday, April 30, 14
  • 304. chef-fundamentals-repo 304 . !"" .bundle/ !"" .kitchen/ !"" .kitchen.yml !"" CHANGELOG.md !"" Gemfile !"" Gemfile.lock !"" README.md !"" attributes/ !"" files/ !"" metadata.rb !"" recipes/ !"" spec/ !"" templates/ !"" test/ $   #"" integration/ #"" vendor/ #"" bundle/ Wednesday, April 30, 14
  • 305. $ mkdir spec Create spec directory in cookbooks/apache 305 > mkdir spec Wednesday, April 30, 14
  • 306. 306 *_spec.rb files • By convention, ChefSpec expects files with tests to end in _spec.rb Wednesday, April 30, 14
  • 309. Each API has an example 309 Wednesday, April 30, 14
  • 310. Let’s use the install_package matcher 310 Wednesday, April 30, 14
  • 312. OPEN IN EDITOR: spec/default_spec.rb require 'chefspec' describe 'apache::default' do chef_run = ChefSpec::Runner.new.converge('apache::default') it 'installs apache2' do expect(chef_run).to install_package('httpd') end end Test apache::default recipe 312 Wednesday, April 30, 14
  • 313. 313 Rspec runs ChefSpec • There’s no separate chefspec command. • Just run rspec to run ChefSpec tests. Wednesday, April 30, 14
  • 314. $ bundle exec rspec --color Run ChefSpec on your cookbok . Finished in 0.0006 seconds 1 example, 0 failures 314 Wednesday, April 30, 14
  • 315. OPEN IN EDITOR: spec/default_spec.rb require 'chefspec' describe 'apache::default' do chef_run = ChefSpec::Runner.new.converge('apache::default') it 'installs apache2' do expect(chef_run).to install_package('badhttpd') end end Did it really check anything? 315 Wednesday, April 30, 14
  • 316. $ bundle exec rspec Run ChefSpec on your cookbok F Failures: 1) apache::default installs apache2 Failure/Error: expect(chef_run).to install_package('badhttpd') expected "package[badhttpd]" with action :install to be in Chef run. Other package resources: package[httpd] # ./spec/default_spec.rb:7:in `block (2 levels) in <top (required)>' Finished in 0.00044 seconds 1 example, 1 failure 316 Wednesday, April 30, 14
  • 317. OPEN IN EDITOR: spec/default_spec.rb require 'chefspec' describe 'apache::default' do chef_run = ChefSpec::Runner.new.converge('apache::default') it 'installs apache2' do expect(chef_run).to install_package('httpd') end end Restore back to working 317 Wednesday, April 30, 14
  • 318. $ bundle exec rspec --color Run ChefSpec on your cookbok . Finished in 0.0006 seconds 1 example, 0 failures 318 Wednesday, April 30, 14
  • 319. Lazy evaluation with let 319 require 'chefspec' describe 'apache::default' do let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) } it 'installs apache2' do expect(chef_run).to install_package('httpd') end end Lazy evaluation Wednesday, April 30, 14
  • 320. 320 described_recipe • let blocks aren’t evaluated until the first time they are called • Also allows ChefSpec to run the described_recipe macro to evaluate the recipe name Wednesday, April 30, 14
  • 321. OPEN IN EDITOR: spec/default_spec.rb require 'chefspec' describe 'apache::default' do let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) } it 'installs apache2' do expect(chef_run).to install_package('httpd') end end Lazy evaluation 321 Wednesday, April 30, 14
  • 322. $ bundle exec rspec --color Run ChefSpec on your cookbok . Finished in 0.0006 seconds 1 example, 0 failures 322 Wednesday, April 30, 14
  • 323. 323 ChefSpec Resource Report • ChefSpec Resource Report can help guide writing your tests Wednesday, April 30, 14
  • 324. OPEN IN EDITOR: spec/default_spec.rb require 'chefspec' at_exit { ChefSpec::Coverage.report! } describe 'apache::default' do let (:chef_run) { ChefSpec::Runner.new.converge(described_recipe) } it 'installs apache2' do expect(chef_run).to install_package('httpd') end end Adding resource report 324 Wednesday, April 30, 14
  • 325. $ bundle exec rspec --color Run ChefSpec on your cookbok . Finished in 0.01106 seconds 1 example, 0 failures ChefSpec Coverage report generated... Total Resources: 9 Touched Resources: 1 Touch Coverage: 11.11% Untouched Resources: service[httpd] /recipes/default.rb:14 execute[mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.disabled] /recipes/default.rb:19 template[/etc/httpd/conf.d/clowns.conf] /recipes/default.rb:32 directory[/srv/apache/clowns] /recipes/default.rb:43 template[/srv/apache/clowns/index.html] /recipes/default.rb:49 template[/etc/httpd/conf.d/bears.conf] /recipes/default.rb:32 directory[/srv/apache/bears] /recipes/default.rb:43 template[/srv/apache/bears/index.html] /recipes/default.rb:49 325 Wednesday, April 30, 14
  • 326. 326 create_file matcher • Let’s verify that the clowns.conf file gets created with the create_file matcher Wednesday, April 30, 14
  • 328. OPEN IN EDITOR: spec/default_spec.rb require 'chefspec' at_exit { ChefSpec::Coverage.report! } describe 'apache::default' do let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) } ... it 'creates clowns.conf' do expect(chef_run).to create_file('/etc/httpd/conf.d/clowns.conf') end end Checking clowns.conf files 328 Wednesday, April 30, 14
  • 329. $ bundle exec rspec --color Run ChefSpec on your cookbok F Failures: 1) apache::default creates clowns.conf Failure/Error: expect(chef_run).to create_file('/srv/apache/clowns') expected "file[/srv/apache/clowns]" with action :create to be in Chef run. Other file resources: # ./spec/default_spec.rb:13:in `block (2 levels) in <top (required)>' Finished in 0.01903 seconds 2 examples, 1 failure Failed examples: rspec ./spec/default_spec.rb:12 # apache::default creates clowns.conf 329 Wednesday, April 30, 14
  • 330. $ bundle exec rspec --color Run ChefSpec on your cookbok F Failures: 1) apache::default creates clowns.conf Failure/Error: expect(chef_run).to create_file('/srv/apache/clowns') expected "file[/srv/apache/clowns]" with action :create to be in Chef run. Other file resources: # ./spec/default_spec.rb:13:in `block (2 levels) in <top (required)>' Finished in 0.01903 seconds 2 examples, 1 failure Failed examples: rspec ./spec/default_spec.rb:12 # apache::default creates clowns.conf 330 FAILWednesday, April 30, 14
  • 331. 331 ChefSpec == Runnable Documentation • Remember: ChefSpec is just runnable documentation • It isn’t actually performing a Chef run to verify that clowns.conf was created • Instead it is just verifying that you told Chef to create the clowns.conf via the file resource, which you never did - you used the template resource Wednesday, April 30, 14
  • 333. OPEN IN EDITOR: spec/default_spec.rb require 'chefspec' at_exit { ChefSpec::Coverage.report! } describe 'apache::default' do let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) } ... it 'creates clowns.conf' do expect(chef_run).to create_template('/etc/httpd/conf.d/clowns.conf') end end Checking clowns.conf file 333 Wednesday, April 30, 14
  • 334. $ bundle exec rspec --color Run ChefSpec on your cookbok . Finished in 0.01955 seconds 2 examples, 0 failures 334 Wednesday, April 30, 14
  • 335. $ bundle exec rspec --color Run ChefSpec on your cookbok . Finished in 0.01955 seconds 2 examples, 0 failures 335 WINWednesday, April 30, 14
  • 336. 336 spec_helper.rb • Similar to Serverspec, common code can be moved to a file called spec_helper.rb with ChefSpec Wednesday, April 30, 14
  • 337. OPEN IN EDITOR: spec/spec_helper.rb require 'chefspec' at_exit { ChefSpec::Coverage.report! } Checking clowns.conf file 337 Wednesday, April 30, 14
  • 338. 338 RSpec recurses through spec/* • RSpec recurses through the spec/ subtree, looking for tests, so you can create any directory structure you like underneath • We’ll move default_spec.rb to spec/recipes Wednesday, April 30, 14
  • 339. $ mkdir spec/recipes $ mv spec/default_spec.rb spec/recipes Move default_spec.rb 339 Wednesday, April 30, 14
  • 340. OPEN IN EDITOR: spec/recipes/default_spec.rb require 'spec_helper' describe 'apache::default' do let (:chef_run) { ChefSpec::Runner.new.converge(described_recipe) } it 'installs apache2' do expect(chef_run).to install_package('httpd') end it 'creates clowns.conf' do expect(chef_run).to create_template('/etc/httpd/conf.d/clowns.conf') end end Checking clowns.conf file 340 Wednesday, April 30, 14
  • 341. $ bundle exec rspec --color Run ChefSpec on your cookbok . Finished in 0.01955 seconds 2 examples, 0 failures 341 Wednesday, April 30, 14
  • 342. $ bundle exec rspec --color Run ChefSpec on your cookbok . Finished in 0.01955 seconds 2 examples, 0 failures 342 WINWednesday, April 30, 14
  • 343. 343 Where to go next • There’s a lot of ChefSpec written for the community cookbooks. Check out the spec/ directory your favorites. Wednesday, April 30, 14
  • 345. What is Guard? • A tool that monitors for filesystem changes and performs actions (like launching rake tasks) • Written by Thibaud Guillaume-Gentil 345 Wednesday, April 30, 14
  • 346. Guard install • Let’s install Guard on your development workstation so you can give it a spin • Add guard to your Gemfile • Install the app with bundle  install 346 Wednesday, April 30, 14
  • 347. OPEN IN EDITOR: cookbooks/apache/Gemfile source 'https://rubygems.org' gem 'test-kitchen' gem 'kitchen-vagrant' gem 'serverspec', '~> 1.1' gem 'foodcritic', '~> 3.0' gem 'rubocop', '~> 0.20' gem 'chefspec', '~> 3.4' gem 'guard', '~> 2.6' Gemfile 347 Wednesday, April 30, 14
  • 348. $ bundle install Install Guard 348 $ CONFIGURE_ARGS="--with-ldflags= '-Wno-error=unused-command-line-argument-hard-error-in- future'" bundle install clang 5.1 Workaround Wednesday, April 30, 14
  • 349. OPEN IN EDITOR: cookbooks/apache/Gemfile source 'https://rubygems.org' gem 'test-kitchen' gem 'kitchen-vagrant' gem 'serverspec', '~> 1.1' gem 'foodcritic', '~> 3.0' gem 'rubocop', '~> 0.20' gem 'chefspec', '~> 3.4' gem 'guard', '~> 2.6' gem 'guard-rubocop', '~> 1.1' Gemfile 349 Wednesday, April 30, 14
  • 350. $ bundle install Install guard-rubocop 350 $ CONFIGURE_ARGS="--with-ldflags= '-Wno-error=unused-command-line-argument-hard-error-in- future'" bundle install clang 5.1 Workaround Wednesday, April 30, 14
  • 351. $ bundle exec guard init Create Guardfile 02:39:58 - INFO - Writing new Guardfile to /home/vagrant/ chef-fundamentals-repo/cookbooks/apache/Guardfile 02:45:32 - INFO - rubocop guard added to Guardfile, feel free to edit it 351 Wednesday, April 30, 14
  • 352. cookbooks/apache/Guardfile 352 # A sample Guardfile # More info at https://github.com/guard/guard#readme guard :rubocop do watch(%r{.+.rb$}) watch(%r{(?:.+/)?.rubocop.yml$}) { |m| File.dirname(m[0]) } end Wednesday, April 30, 14
  • 353. $ bundle exec guard Run Guard 02:48:54 - INFO - Guard is now watching at '/home/vagrant/ chef-fundamentals-repo/cookbooks/apache' [1] guard(main)> 353 Wednesday, April 30, 14
  • 356. $ cd $HOME/chef-fundamentals-repo/cookbooks/apache In another session 356 And edit some .rb file - upon save, rubocop is launched! Wednesday, April 30, 14
  • 357. Stopping guard [1] guard(main)> quit 19:23:42 - INFO - Bye bye... 357 Wednesday, April 30, 14
  • 358. 358 Where to go next Michael Goetz blog posts: https://micgo.net/check-yo-self-before-you-wreck-yo-self-with- foodcritic-chefspec/ Foodcritic and Guard: Serverspec and Guard: https://micgo.net/serverspec-guard-and-test-kitchen-testing- servers-like-a-boss/ Wednesday, April 30, 14
  • 359. 359 Where to go next Michael Goetz blog posts: ChefSpec and Guard: https://micgo.net/continuous-chefspec-validation-with-guard/ Wednesday, April 30, 14
  • 360. v2.0.0 Repeating Test Steps with Rake 360 Wednesday, April 30, 14
  • 361. What is Rake? • Rake includes a language for expressing the command line steps needed to create an app • Perfect for capturing all the commands you’ve learned in this class so others can run them easily, or in your continuous integration system (Jenkins, Bamboo, TeamCity, etc.) 361 Wednesday, April 30, 14
  • 362. Rake Author • Written by Jim Weirich: http://rake.rubyforge.org/ 362 Wednesday, April 30, 14
  • 363. Rake - Repeatable Test Commands • Let’s install Rake on your development workstation so you can give it a spin • Add rake to your Gemfile • Install the app with bundle  install 363 Wednesday, April 30, 14
  • 364. OPEN IN EDITOR: chef-fundamentals-repo/Gemfile source 'https://rubygems.org' gem 'test-kitchen' gem 'kitchen-vagrant' gem 'rake' gem 'serverspec', '~> 1.1' gem 'foodcritic', '~> 3.0' gem 'rubocop', '~> 0.20' gem 'chefspec', '~> 3.4' gem 'guard', '~> 2.6' gem 'guard-rubocop', '~> 1.1' Gemfile 364 Wednesday, April 30, 14
  • 365. $ bundle install Install Rake 365 $ CONFIGURE_ARGS="--with-ldflags= '-Wno-error=unused-command-line-argument-hard-error-in- future'" bundle install clang 5.1 Workaround Wednesday, April 30, 14
  • 366. Rake - Repeatable Tasks • Task - expresses command line actions to perform 366 Wednesday, April 30, 14
  • 367. Rake Task Form 367 task :<task_name> do <action> <action> end Wednesday, April 30, 14
  • 368. Rake - Repeatable Tasks • Configuration file for rake is a Rakefile 368 Wednesday, April 30, 14
  • 369. Rake - Actions • Actions are expressed in Ruby syntax • sh  “<command>”  runs a shell command: sh “bundle  exec  rspec” 369 Wednesday, April 30, 14
  • 370. OPEN IN EDITOR: cookbooks/apache/Rakefile task :rubocop do sh 'bundle exec rubocop' end Rubocop Task 370 Wednesday, April 30, 14
  • 371. $ bundle exec rake rubocop Execute Rake Task Inspecting 9 files ....... 9 files inspected, no offenses detected 371 Wednesday, April 30, 14
  • 372. Task Description • Every task should have a description which documents what the task does • rake  -­‐-­‐tasks prints out tasks with descriptions 372 Wednesday, April 30, 14
  • 373. OPEN IN EDITOR: cookbooks/apache/Rakefile desc 'Run Ruby style checks with Rubocop' task :rubocop do sh 'bundle exec rubocop' end Rubocop Task 373 Wednesday, April 30, 14
  • 374. $ bundle exec rake --tasks Execute Rake Task rake rubocop # Run Ruby style checks with Rubocop 374 Wednesday, April 30, 14
  • 375. Adding Foodcritic • Let’s add a task for Foocritic next 375 Wednesday, April 30, 14
  • 376. OPEN IN EDITOR: cookbooks/apache/Rakefile desc 'Run Ruby style checks with Rubocop' task :rubocop do sh 'bundle exec rubocop' end desc 'Run Chef style checks with Foodcritic' task :foodcritic do sh 'bundle exec foodcritic -t ~FC003 .' end Foodcritic Task 376 Wednesday, April 30, 14
  • 377. $ bundle exec rake foodcritic Execute Rake Task bundle exec foodcritic -t ~FC003 . FC011: Missing README in markdown format: spec/README.md:1 FC031: Cookbook without metadata file: spec/metadata.rb:1 FC045: Consider setting cookbook name in metadata: spec/ metadata.rb:1 377 Wednesday, April 30, 14
  • 378. $ bundle exec rake foodcritic Execute Rake Task bundle exec foodcritic -t ~FC003 . FC011: Missing README in markdown format: spec/README.md:1 FC031: Cookbook without metadata file: spec/metadata.rb:1 FC045: Consider setting cookbook name in metadata: spec/ metadata.rb:1 378 WAT?Wednesday, April 30, 14
  • 379. Foodcritic 3.0.3 issue • Foodcritic is checking spec/ subtree when it shouldn’t • Does not expose command line option to exclude directories: https://github.com/acrmp/foodcritic/issues/148 • When fixed, this should work: bundle  exec  foodcritic  -­‐X  spec  -­‐t  ~FC003  . 379 Wednesday, April 30, 14
  • 380. OPEN IN EDITOR: cookbooks/apache/Rakefile desc 'Run Ruby style checks with Rubocop' task :rubocop do sh 'bundle exec rubocop' end require 'foodcritic' desc 'Run Chef style checks with Foodcritic' FoodCritic::Rake::LintTask.new(:foodcritic) do |t| t.options = { tags: ['~FC003'], excludes: ['test', 'spec', 'features'] } end Workaround - Use Ruby 380 Wednesday, April 30, 14
  • 381. Default task • Rake supports a special task name called default • default runs when no parameters are supplied to rake • default (as well as any other task) can point to a list of other task names to execute task  :default  =>  [:foodcritic] 381 Wednesday, April 30, 14
  • 382. OPEN IN EDITOR: cookbooks/apache/Rakefile task :default => [:rubocop, :foodcritic] desc 'Run Ruby style checks with Rubocop' task :rubocop do sh 'bundle exec rubocop' end require 'foodcritic' desc 'Run Chef style checks with Foodcritic' FoodCritic::Rake::LintTask.new(:foodcritic) do |t| t.options = { tags: ['~FC003'], excludes: ['test', 'spec', 'features' ] } end Foodcritic Task 382 Wednesday, April 30, 14
  • 383. $ bundle exec rake Execute Rake Task bundle exec rubocop Inspecting 9 files ....... 7 files inspected, no offenses detected 383 Wednesday, April 30, 14
  • 384. 384 Where to go next Rake Boot Camp http://cloud.github.com/downloads/jimweirich/RakePresentations/PowerRake.key.pdf http://www.confreaks.com/videos/899-railsconf2012-basic-rake Go to http://confreaks.com Search for “Basic Rake” Wednesday, April 30, 14
  • 385. 385 Where to go next Rake Tasks can have tests http://blog.jayfields.com/2006/11/ruby-testing-rake-tasks.html Wednesday, April 30, 14
  • 387. What is Jenkins? • Jenkins is a commonly used, open source continuous integration system used to build early and often • Written by Kohsuke Kawaguchi 387 Wednesday, April 30, 14
  • 388. $ sudo yum install -y libxslt-devel libxml2-devel Install Prerequisites 388 $ sudo apt-get install -y libxslt-dev libxml2-dev Wednesday, April 30, 14
  • 389. $ cd $HOME Home directory - great place for source 389 $ cd %USERPROFILE% Wednesday, April 30, 14
  • 390. Jenkins cookbook • Jenkins cookbook - https://github.com/opscode- cookbooks/jenkins • Jenkins cookbook is library cookbook 390 Wednesday, April 30, 14
  • 391. Library cookbook • Popularized by Bryan Berry’s blog post How to Write Resuable Chef Cookbooks, Gangnam Style 391 Wednesday, April 30, 14
  • 392. Jenkins wrapper cookbook • Start of our wrapper cookbook: https://github.com/misheska/test-class-jenkins 392 Wednesday, April 30, 14
  • 393. $ git clone https://github.com/misheska/test-class-jenkins Grab test-class-jenkins from Github Cloning into 'test-class-jenkins'... remote: Counting objects: 19, done. remote: Compressing objects: 100% (16/16), done. remote: Total 19 (delta 0), reused 19 (delta 0) Unpacking objects: 100% (19/19), done. 393 Wednesday, April 30, 14
  • 395. $ bundle install --path vendor/bundle Install gems vendored Fetching gem metadata from https://rubygems.org/....... Fetching additional metadata from https://rubygems.org/.. Resolving dependencies... Installing rake (10.2.2) Installing addressable (2.3.6) Installing ast (1.1.0) ... Installing powerpack (0.0.9) Installing rainbow (2.0.0) Installing ruby-progressbar (1.4.2) Installing rubocop (0.20.1) Using bundler (1.5.3) Your bundle is complete! It was installed into ./vendor/bundle 395 Wednesday, April 30, 14
  • 400. test-class-jenkins/Gemfile 400 source 'https://rubygems.org' gem 'test-kitchen' gem 'kitchen-docker' gem 'rake' gem 'berkshelf', '~> 3.0.0.rc' gem 'rubocop', '~> 0.20' gem 'foodcritic', '~> 3.0' Wednesday, April 30, 14
  • 401. test-class-jenkins/.kitchen.yml 401 --- driver: name: docker provisioner: name: chef_solo platforms: - name: centos-6.4 driver_config: forward: - 8080:8080 suites: - name: default run_list: - recipe[test-class-jenkins::default] Wednesday, April 30, 14
  • 402. $ bundle exec kitchen converge Perform Chef run of Jenkins wrapper -----> Starting Kitchen (v1.2.1) -----> Creating <default-centos-64>... Step 0 : FROM centos:6.4 ... ----> Converging <default-centos-64>... Preparing files for transfer Resolving cookbook dependencies with Berkshelf 3.0.0.rc1... ... 402 Wednesday, April 30, 14