Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
1Thursday, October 3, 13
Testing Your Chef Infrastructure CodeTDD Your Infrastructure With Chefspec, Test-Kitchen, & Serverspec
2Thursday, October 3, 13
Speaker Introduction
Charles JohnsonSolutions Engineer, [email protected]@chipadeedoodah
3Thursday, October 3, 13
Your Infrastructure Code Isn’t “Just Scripts”
4Thursday, October 3, 13
Cookbooks Are Source Code• Chef Cookbook source code is just like the source
code for other programs.
• Changes are tracked and versioned with source control software such as git
• Code is inert until it has been deployed
• Code can be used to re-create the desired system configuration from scratch
5Thursday, October 3, 13
Cookbooks Are Artifacts• Chef Cookbook artifacts are just like the artifacts for other
programs.• Cookbooks are packaged for distribution• Cookbooks are deployed• Cookbooks are released with versions• Cookbooks are immutable once deployed• Cookbooks can depend on one another
6Thursday, October 3, 13
Cookbooks Are Artifacts
Close Encounters of the Third Kind, copyright 1977, Columbia Pictures
“This means something! This is important!”
7Thursday, October 3, 13
Cookbooks Are Artifacts
• Depending entirely on context,your infrastructure code can be either source code OR artifact.
Close Encounters of the Third Kind, copyright 1977, Columbia Pictures
“This means something! This is important!”
7Thursday, October 3, 13
Cookbooks Are Artifacts• This sounds obvious, but it’s easy to overlook:
Treating infrastructure code only as source code or only as artifacts will lead to long-term problems when using code to manage infrastructure.
Source'Code' Ar+fact'
• A good infrastructure code workflow treats code appropriately depending on context
8Thursday, October 3, 13
Code Can (Help)9Thursday, October 3, 13
But wait... Isn’t Chef a declarative language?
10Thursday, October 3, 13
• Chef itself is a testing engine. Either the intent expressed is executed, or the Chef run fails!
Yes! Chef is Declarative!package "apache2" do action :installend
template "/etc/apache2/apache2.conf" do source "apache2.conf.erb" owner "root" group "root" mode "0644" variables(:allow_override => "All") notifies :reload, "service[apache2]"end
service "apache2" do action [:enable,:start] supports :reload => trueend
11Thursday, October 3, 13
• Code Linting:
• Is my code properly formed?
• Signal in: Unit test
• Did I send Chef the correct command?
• Signal Processing: Convergence
• Did Chef interpret my command correctly?
• Signal out: Acceptance test
• Did my expressed intent, executed by Chef, achieve the desired result?
What and When To Test
Flickr user: Rain Rabbit
12Thursday, October 3, 13
Chef Testing Tools
13Thursday, October 3, 13
Chef Testing Tools• Linting: Foodcritic, Rubocop
http://acrmp.github.io/foodcritic/https://github.com/bbatsov/rubocop
13Thursday, October 3, 13
Chef Testing Tools• Linting: Foodcritic, Rubocop
http://acrmp.github.io/foodcritic/https://github.com/bbatsov/rubocop
• Unit Testing: Chefspechttps://github.com/acrmp/chefspec
13Thursday, October 3, 13
Chef Testing Tools• Linting: Foodcritic, Rubocop
http://acrmp.github.io/foodcritic/https://github.com/bbatsov/rubocop
• Unit Testing: Chefspechttps://github.com/acrmp/chefspec
• Convergence Testing: Test-Kitchenhttps://github.com/opscode/test-kitchen
13Thursday, October 3, 13
Chef Testing Tools• Linting: Foodcritic, Rubocop
http://acrmp.github.io/foodcritic/https://github.com/bbatsov/rubocop
• Unit Testing: Chefspechttps://github.com/acrmp/chefspec
• Convergence Testing: Test-Kitchenhttps://github.com/opscode/test-kitchen
• Acceptance Testing: ServerSpechttp://serverspec.org
13Thursday, October 3, 13
Berkshelf• Cookbook manager
• No more maintaining copies ofunmodified community cookbooksin a personal repo!
• Automatically resolves all cookbook dependencies
• Artifact installer• If you’re familiar with bundler,
berks is easy• Integrates tightly with...
14Thursday, October 3, 13
Make a Test Recipe
15Thursday, October 3, 13
$ knife cookbook create -o . myface
Create New Cookbook
** Creating cookbook myface** Creating README for cookbook: myface** Creating CHANGELOG for cookbook: myface** Creating metadata for cookbook: myface
16Thursday, October 3, 13
OPEN IN EDITOR: myface/Gemfile
source 'https://rubygems.org'
gem 'berkshelf', '~> 2.0'gem 'chefspec', '~> 2.0'gem 'foodcritic', '~> 2.2'gem 'rubocop', '~> 0.12'
group :integration do gem 'test-kitchen', '~> 1.0.0.beta' gem 'kitchen-ec2', '~> 0.7.0'end
Set Up Gemfile
17Thursday, October 3, 13
OPEN IN EDITOR: myface/Berksfile
site :opscodemetadata
group :integration do cookbook 'apt', '~> 2.0'end
Set Up Berksfile
18Thursday, October 3, 13
OPEN IN EDITOR: myface/recipes/default.rb
## Cookbook Name:: myface# Recipe:: default## Copyright 2013, Charles Johnson## All rights reserved - Do Not Redistribute#
package "apache2" do action :installend
service "apache2" do action [:enable,:start] supports :reload => trueend
Edit default recipe
19Thursday, October 3, 13
Chefspec- Signal In / Unit Test
20Thursday, October 3, 13
How ChefSpec Works
Sysadmin / Developer
21Thursday, October 3, 13
How ChefSpec Works
$rspec
Sysadmin / Developer
$ mock node$ mock chef-client converge$ verify test assertions$ report results
in-memory test
21Thursday, October 3, 13
How ChefSpec Works
$rspec
Sysadmin / Developer
..
Finished in 0.0222 seconds2 examples, 0 failures
21Thursday, October 3, 13
$ cd myface myface $ bundle install
Install Test Suite Bundle
Fetching gem metadata from https://rubygems.org/......Resolving dependencies...Installing i18n (0.6.5)Installing multi_json (1.8.0)...Using bundler (1.3.5)Your bundle is complete!Use `bundle show [gemname]` to see where a bundled gem is installed.
22Thursday, October 3, 13
myface $ mkdir -p spec/unit/recipes
Create Unit Test Directories
(no output)
23Thursday, October 3, 13
OPEN IN EDITOR: spec/spec_helper.rb
require 'chefspec'require 'berkshelf'
Berkshelf.ui.mute do Berkshelf::Berksfile.from_file('Berksfile').install(path: 'vendor/cookbooks/')end
RSpec.configure do |c| c.after(:suite) do # Berks will infinitely nest vendor/cookbooks/ntp on each rspec run # https://github.com/RiotGames/berkshelf/issues/828 FileUtils.rm_rf('vendor/') endend
Create the Chefspec spec_helper.rb
24Thursday, October 3, 13
OPEN IN EDITOR: myface/recipes/default.rb
## Cookbook Name:: myface# Recipe:: default## Copyright 2013, Charles Johnson## All rights reserved - Do Not Redistribute#
package "apache2" do action :installend
service "apache2" do action [:enable,:start] supports :reload => trueend
One more time: The Default Recipe
25Thursday, October 3, 13
OPEN IN EDITOR: spec/unit/recipes/default_spec.rb
require 'spec_helper'
describe 'myface::default' do let (:chef_run) { ChefSpec::ChefRunner.new.converge 'myface::default' }
it "installs apache2" do expect(chef_run).to install_package 'apache2' end
it "starts and enables the apache2 service" do expect(chef_run).to start_service 'apache2' expect(chef_run).to set_service_to_start_on_boot 'apache2' endend
Create default_spec.rb
26Thursday, October 3, 13
OPEN IN EDITOR: spec/unit/recipes/default_spec.rb
require 'spec_helper'
describe 'myface::default' do let (:chef_run) { ChefSpec::ChefRunner.new.converge 'myface::default' }
it "installs apache2" do expect(chef_run).to install_package 'apache2' end
it "starts and enables the apache2 service" do expect(chef_run).to start_service 'apache2' expect(chef_run).to set_service_to_start_on_boot 'apache2' endend
Create default_spec.rb
26Thursday, October 3, 13
OPEN IN EDITOR: spec/unit/recipes/default_spec.rb
require 'spec_helper'
describe 'myface::default' do let (:chef_run) { ChefSpec::ChefRunner.new.converge 'myface::default' }
it "installs apache2" do expect(chef_run).to install_package 'apache2' end
it "starts and enables the apache2 service" do expect(chef_run).to start_service 'apache2' expect(chef_run).to set_service_to_start_on_boot 'apache2' endend
Create default_spec.rb
26Thursday, October 3, 13
myface $ rspec
Run Chefspec Test Suite
..
Finished in 0.02124 seconds2 examples, 0 failures
27Thursday, October 3, 13
Test Kitchen- Signal Processing / Convergence Test
28Thursday, October 3, 13
How Test-Kitchen Works
Cloud Provisioner(Amazon EC2)
Sysadmin / Developer
29Thursday, October 3, 13
How Test-Kitchen Works
$ kitchen test
Cloud Provisioner(Amazon EC2)
https
Instances
Sysadmin / Developer
29Thursday, October 3, 13
How Test-Kitchen Works
$ kitchen test
Cloud Provisioner(Amazon EC2)
https
Instances
ssh
$ install Chef$ configure Chef$ copy cookbook$ run Chef$ report results
Sysadmin / Developer
29Thursday, October 3, 13
How Test-Kitchen Works
$ kitchen test
Cloud Provisioner(Amazon EC2)
https
Sysadmin / Developer
Chef Client finished, 4 resources updated Finished converging <default-ubuntu-1004> (1m24.99s).-----> Kitchen is finished. (1m25.45s)
29Thursday, October 3, 13
OPEN IN EDITOR: .kitchen.yml
---driver_plugin: ec2driver_config: availability_zone: us-east-1a aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> aws_ssh_key_id: <%= ENV['EC2_SSH_KEY_NAME'] %> ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> flavor_id: m1.small require_chef_omnibus: true
platforms:- name: ubuntu-10.04suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}
Create Kitchen.yml
30Thursday, October 3, 13
OPEN IN EDITOR: .kitchen.yml
---driver_plugin: ec2driver_config: availability_zone: us-east-1a aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> aws_ssh_key_id: <%= ENV['EC2_SSH_KEY_NAME'] %> ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> flavor_id: m1.small require_chef_omnibus: true...
Create Kitchen.yml
31Thursday, October 3, 13
OPEN IN EDITOR: .kitchen.yml
...platforms:- name: ubuntu-10.04
suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}
Create Kitchen.yml
32Thursday, October 3, 13
OPEN IN EDITOR: .kitchen.yml
---driver_plugin: ec2driver_config: availability_zone: us-east-1a aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> aws_ssh_key_id: <%= ENV['EC2_SSH_KEY_NAME'] %> ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> flavor_id: m1.small require_chef_omnibus: true
platforms:- name: ubuntu-10.04
suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}
Create Kitchen.yml
33Thursday, October 3, 13
myface $ kitchen test
Test Myface
-----> Starting Kitchen (v1.0.0.beta.3)-----> Cleaning up any prior instances of <default-ubuntu-1004>...-----> Testing <default-ubuntu-1004>-----> Creating <default-ubuntu-1004> EC2 instance <i-e941558c> created.-----> Converging <default-ubuntu-1004>... (Lots of Chef happens here) Resolving cookbook dependencies with BerkshelfUsing myface (0.1.0)Using apt (2.1.1)... (Lots more Chef) Finished converging <default-ubuntu-1004> (1m24.99s).-----> Kitchen is finished. (1m25.45s)
34Thursday, October 3, 13
Bussers & ServerSpec- Signal Out / Acceptance Test
35Thursday, October 3, 13
Instance
$ install Chef$ configure Chef$ copy cookbook$ run Chef
How Kitchen Bussers Work
36Thursday, October 3, 13
Instance
$ install Chef$ configure Chef$ copy cookbook$ run Chef
If acceptance tests present:$ install acceptance test framework$ copy acceptance tests$ run acceptance suite
$ report results
How Kitchen Bussers Work
36Thursday, October 3, 13
Currently Supported Bussers• Minitest
• Not to be confused with chef-minitest-handler. Straight minitest, no fancy Chef-specific matchers or assertions.https://github.com/fnichol/busser-minitest
• BATS• Bash-based acceptance testing & host inspection.
https://github.com/sstephenson/bats
• ServerSpec
• Young project, aims to provide rspec-based testing & host inspection.http://serverspec.org
37Thursday, October 3, 13
myface $ mkdir -p test/integration/default/serverspec/localhost
Create Serverspec Test Directories
(no output)
38Thursday, October 3, 13
OPEN IN EDITOR: test/integration/default/serverspec/spec_helper.rb
require 'serverspec'require 'pathname'
include Serverspec::Helper::Execinclude Serverspec::Helper::DetectOS
RSpec.configure do |c| c.before :all do c.os = backend(Serverspec::Commands::Base).check_os endend
Create the ServerSpec spec_helper.rb
39Thursday, October 3, 13
OPEN IN EDITOR: test/integration/default/serverspec/localhost/default_spec.rb
require 'spec_helper'
describe 'myface::default recipe' do
it 'Enables & starts the apache2 service' do expect(service 'apache2').to be_running expect(service 'apache2').to be_enabled end
end
Create the ServerSpec spec_helper.rb
40Thursday, October 3, 13
OPEN IN EDITOR: test/integration/default/serverspec/localhost/default_spec.rb
require 'spec_helper'
describe 'myface::default recipe' do
it 'Enables & starts the apache2 service' do expect(service 'apache2').to be_running expect(service 'apache2').to be_enabled end
end
Create the ServerSpec spec_helper.rb
40Thursday, October 3, 13
myface $ kitchen verify
Test Myface
-----> Starting Kitchen (v1.0.0.beta.3)-----> Cleaning up any prior instances of <default-ubuntu-1004>... (all the same stuff from before)-----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/opt/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /opt/busser/suites/serverspec/localhost/default_spec.rb .
Finished in 0.12308 seconds 1 example, 0 failures Finished verifying <default-ubuntu-1004> (0m8.99s).-----> Kitchen is finished. (1m34.66s)
41Thursday, October 3, 13
Put It All Together
42Thursday, October 3, 13
Chef Testing Tools
43Thursday, October 3, 13
Chef Testing Tools
• Unit Testing: Chefspechttps://github.com/acrmp/chefspec
43Thursday, October 3, 13
Chef Testing Tools
• Unit Testing: Chefspechttps://github.com/acrmp/chefspec
• Convergence Testing: Test-Kitchenhttps://github.com/opscode/test-kitchen
43Thursday, October 3, 13
Chef Testing Tools
• Unit Testing: Chefspechttps://github.com/acrmp/chefspec
• Convergence Testing: Test-Kitchenhttps://github.com/opscode/test-kitchen
• Acceptance Testing: ServerSpechttp://serverspec.org
43Thursday, October 3, 13
• New initiative: Upgrade or replace all Ubuntu 10.04 instances with Ubuntu 12.04.
New Edict: Upgrade to Ubuntu 12.04
Flickr user: iheartubuntu
44Thursday, October 3, 13
• New initiative: Upgrade or replace all Ubuntu 10.04 instances with Ubuntu 12.04.
• Because we have a comprehensive automated test suite, we can easily test our infrastructure code and deploy with confidence.
New Edict: Upgrade to Ubuntu 12.04
Flickr user: iheartubuntu
44Thursday, October 3, 13
OPEN IN EDITOR: .kitchen.yml
...platforms:- name: ubuntu-10.04- name: ubuntu-12.04
suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}
Create Kitchen.yml
45Thursday, October 3, 13
OPEN IN EDITOR: .kitchen.yml
...platforms:- name: ubuntu-10.04- name: ubuntu-12.04
suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}
Create Kitchen.yml
45Thursday, October 3, 13
OPEN IN EDITOR: .kitchen.yml
---driver_plugin: ec2driver_config: availability_zone: us-east-1a aws_access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> aws_secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> aws_ssh_key_id: <%= ENV['EC2_SSH_KEY_NAME'] %> ssh_key: <%= ENV['EC2_SSH_KEY_PATH'] %> flavor_id: m1.small require_chef_omnibus: true
platforms:- name: ubuntu-10.04- name: ubuntu-12.04suites:- name: default run_list: - recipe[apt::default] - recipe[myface::default] attributes: {}
Create Kitchen.yml
46Thursday, October 3, 13
myface $ kitchen test --parallel
Test Myface
-----> Starting Kitchen (v1.0.0.beta.3)-----> Creating <default-ubuntu-1004>-----> Creating <default-ubuntu-1204> EC2 instance <i-f1f43688> created. EC2 instance <i-2557e15d> created.... (Chef converges)... (ServerSpec tests) EC2 instance <i-f1f43688> created. EC2 instance <i-2557e15d> created. Finished testing <default-ubuntu-1004> (3m21.22s). Finished testing <default-ubuntu-1204> (3m54.97s).-----> Kitchen is finished. (3m55.45s)
47Thursday, October 3, 13
So What’s the Catch?
48Thursday, October 3, 13
• Test-Kitchen is in beta & still has bugs
It’s All Bleeding Edge
fanex.com
49Thursday, October 3, 13
• Test-Kitchen is in beta & still has bugs
• Serverspec is a young language
It’s All Bleeding Edge
fanex.com
49Thursday, October 3, 13
• Test-Kitchen is in beta & still has bugs
• Serverspec is a young language
• Chefspec is under heavy development
It’s All Bleeding Edge
fanex.com
49Thursday, October 3, 13
• Test-Kitchen is in beta & still has bugs
• Serverspec is a young language
• Chefspec is under heavy development
• Cookbook generators don’t cover all the boilerplate files & folders just yet
It’s All Bleeding Edge
fanex.com
49Thursday, October 3, 13
• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers
But Wait! There’s More!
Chris Notarile
50Thursday, October 3, 13
• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers
• Fancy tricks:
But Wait! There’s More!
Chris Notarile
50Thursday, October 3, 13
• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers
• Fancy tricks:
• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!
But Wait! There’s More!
Chris Notarile
50Thursday, October 3, 13
• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers
• Fancy tricks:
• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!
• The Future:
But Wait! There’s More!
Chris Notarile
50Thursday, October 3, 13
• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers
• Fancy tricks:
• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!
• The Future:
• Support for other CM systems
But Wait! There’s More!
Chris Notarile
50Thursday, October 3, 13
• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers
• Fancy tricks:
• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!
• The Future:
• Support for other CM systems
• Support for other bussers
But Wait! There’s More!
Chris Notarile
50Thursday, October 3, 13
• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers
• Fancy tricks:
• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!
• The Future:
• Support for other CM systems
• Support for other bussers
• Support for even more cloud provisioners
But Wait! There’s More!
Chris Notarile
50Thursday, October 3, 13
• Test-Kitchen has drivers for Vagrant, Openstack, VMware, and other cloud providers
• Fancy tricks:
• Check out guard-kitchen in the Opscode zsh cookbook, and automatically test files when you save them!
• The Future:
• Support for other CM systems
• Support for other bussers
• Support for even more cloud provisioners
• Cookbook generators that write all these extra boilerplate files for you
But Wait! There’s More!
Chris Notarile
50Thursday, October 3, 13
Who’s this guy, again?
Charles JohnsonSolutions Engineer, [email protected]@chipadeedoodah
51Thursday, October 3, 13
Questions
• Question & Answer
52Thursday, October 3, 13