rapid chef development with berkshelf, test-kitchen and foodcritic
DESCRIPTION
An introduction to Chef Cookbook development tools: * Berkshelf * Test-Kitchen * FoodcriticTRANSCRIPT
CLOUD SAVVY
BROWN BAG:Rapid Chef
Development
Hart Hoover@hhoover
CLOUD SAVVY 2
CLOUD SAVVY 3
ENTERPRISE
CLOUD SAVVY 4
CHEF SOLO
CLOUD SAVVY 5OPEN SOURCE CHEF
CLOUD SAVVY
TOOLS!
6
CLOUD SAVVY
TOOLS!
6
• Git/GitHub
CLOUD SAVVY
TOOLS!
6
• Git/GitHub
• Berkshelf
CLOUD SAVVY
TOOLS!
6
• Git/GitHub
• Berkshelf
• Vagrant
CLOUD SAVVY
TOOLS!
6
• Git/GitHub
• Berkshelf
• Vagrant
• Vagrant Plugins
CLOUD SAVVY
TOOLS!
6
• Git/GitHub
• Berkshelf
• Vagrant
• Vagrant Plugins
• Test Kitchen
CLOUD SAVVY
TOOLS!
6
• Git/GitHub
• Berkshelf
• Vagrant
• Vagrant Plugins
• Test Kitchen
• Foodcritic
CLOUD SAVVY 7
CLOUD SAVVY 8
CLOUD SAVVY 8
CLOUD SAVVY 8
CLOUD SAVVY 8
• A CLI Tool
• A Source Code Management Tool
• A Package Manager
• Replaces parts of knife
• Specifically cookbook management
CLOUD SAVVY 8
• A CLI Tool
• A Source Code Management Tool
• A Package Manager
• Replaces parts of knife
• Specifically cookbook management
THE BERKSHELF WAY IS BETTER
CLOUD SAVVY 9
CLOUD SAVVY 10
CLOUD SAVVY 11
Why Vagrant?
• Repeatable• Customizable• “It works on my machine.”
Developers
CLOUD SAVVY 12
Why Vagrant?
• Disposable Machines• Test your provisioning• Local → Production
Operations
CLOUD SAVVY 13
Why Vagrant?
=
CLOUD SAVVY 14
TEST KITCHEN
Convergence Integration Testing
for Chef
CLOUD SAVVY 14
TEST KITCHEN
Convergence Integration Testing
for Chef
Does my cookbook work?
CLOUD SAVVY 14
TEST KITCHEN
Convergence Integration Testing
for Chef
Does my cookbook work?
NO
CLOUD SAVVY 15
FoodCritic
Lint testing!
Makes it easy to flagknown issues
Better Cookbooks!
CLOUD SAVVY
ChefWorkFlowS
CLOUD SAVVY
OLD CHEF DEV WORKFLOW
17
CLOUD SAVVY
OLD CHEF DEV WORKFLOW
17
EditCookbook
CLOUD SAVVY
OLD CHEF DEV WORKFLOW
17
EditCookbook
UploadCookbook
CLOUD SAVVY
OLD CHEF DEV WORKFLOW
17
EditCookbook
ProvisionMachine
UploadCookbook
CLOUD SAVVY
OLD CHEF DEV WORKFLOW
17
EditCookbook
ProvisionMachine
BootstrapMachine
UploadCookbook
CLOUD SAVVY
OLD CHEF DEV WORKFLOW
17
EditCookbook
ProvisionMachine
BootstrapMachine
UploadCookbook
RunChef Client
CLOUD SAVVY
OLD CHEF DEV WORKFLOW
17
EditCookbook
ProvisionMachine
BootstrapMachine
SSH & Validate
UploadCookbook
RunChef Client
CLOUD SAVVY
OLD CHEF DEV WORKFLOW
17
EditCookbook
ProvisionMachine
BootstrapMachine
SSH & Validate
UploadCookbook
RunChef Client
CLOUD SAVVY
NEW CHEF DEV WORKFLOW
18
EditCookbook
VagrantUp
TestKitchen
CLOUD SAVVY
Our Workflow
19
Berkshelf VagrantUp
TestKitchen GitHub Production Monitoring
CLOUD SAVVY
Our Workflow
19
Berkshelf VagrantUp
TestKitchen GitHub Production Monitoring
CLOUD SAVVY
Our Workflow
19
{DEV
Berkshelf VagrantUp
TestKitchen GitHub Production Monitoring
CLOUD SAVVY
Our Workflow
19
{DEV OPS{Berkshelf Vagrant
UpTest
Kitchen GitHub Production Monitoring
CLOUD SAVVY
DevelopmentWalkthroughPrerequisites
CLOUD SAVVY
What You need• VirtualBox • Vagrant• Opscode’s 12.04 Vagrant Box• Ruby (1.9.3 or higher!)
• Berkshelf• Test Kitchen• Foodcritic
21
CLOUD SAVVY
Virtualbox
22
https://www.virtualbox.org/wiki/Downloads
CLOUD SAVVY
Vagrant
23
http://downloads.vagrantup.com
CLOUD SAVVY
OPSCODE’S VAGRANT BOX
24
$ vagrant box add \opscode-‐ubuntu-‐12.04 \http://tinyurl.com/chef1204
CLOUD SAVVY
CREATE A PROJECT
25
$ mkdir -‐p ~/projects/chefnovaclient
$ cd ~/projects/chefnovaclient
CLOUD SAVVY
Berkshelf
26
$ gem install berkshelf
CLOUD SAVVY
Test Kitchen
27
$ gem install test-‐kitchen -‐-‐pre
CLOUD SAVVY
FoodCritic
28
$ gem install foodcritic
CLOUD SAVVY 29
CLOUD SAVVY
DevelopmentWalkthrough
rackspace-novaclient&
supernova
CLOUD SAVVY
GET STARTED
31
$ berks init
$ cd ~/projects/chefnovaclient
CLOUD SAVVY 32
$ berks initberks init create Berksfile create Thorfile create .gitignore run git init from "." create Gemfile create .kitchen.yml append Thorfile create test/integration/default append .gitignore append .gitignore append Gemfile append GemfileYou must run `bundle install' to fetch any new gems. create VagrantfileSuccessfully initialized
CLOUD SAVVY 33
$ berks initberks init create Berksfile create Thorfile create .gitignore run git init from "." create Gemfile create .kitchen.yml append Thorfile create test/integration/default append .gitignore append .gitignore append Gemfile append GemfileYou must run `bundle install' to fetch any new gems. create VagrantfileSuccessfully initialized
CLOUD SAVVY 34
$ berks initberks init create Berksfile create Thorfile create .gitignore run git init from "." create Gemfile create .kitchen.yml append Thorfile create test/integration/default append .gitignore append .gitignore append Gemfile append GemfileYou must run `bundle install' to fetch any new gems. create VagrantfileSuccessfully initialized
CLOUD SAVVY 35
$ berks initberks init create Berksfile create Thorfile create .gitignore run git init from "." create Gemfile create .kitchen.yml append Thorfile create test/integration/default append .gitignore append .gitignore append Gemfile append GemfileYou must run `bundle install' to fetch any new gems. create VagrantfileSuccessfully initialized
CLOUD SAVVY 36
$ berks initberks init create Berksfile create Thorfile create .gitignore run git init from "." create Gemfile create .kitchen.yml append Thorfile create test/integration/default append .gitignore append .gitignore append Gemfile append GemfileYou must run `bundle install' to fetch any new gems. create VagrantfileSuccessfully initialized
CLOUD SAVVY 37
$ berks initberks init create Berksfile create Thorfile create .gitignore run git init from "." create Gemfile create .kitchen.yml append Thorfile create test/integration/default append .gitignore append .gitignore append Gemfile append GemfileYou must run `bundle install' to fetch any new gems. create VagrantfileSuccessfully initialized
CLOUD SAVVY 38
$ berks initberks init create Berksfile create Thorfile create .gitignore run git init from "." create Gemfile create .kitchen.yml append Thorfile create test/integration/default append .gitignore append .gitignore append Gemfile append GemfileYou must run `bundle install' to fetch any new gems. create VagrantfileSuccessfully initialized
CLOUD SAVVY 39
CLOUD SAVVY
INSTALL Kitchen-Vagrant
40
$ gem install kitchen-‐vagrant
CLOUD SAVVY
SET UP TEST KITCHEN
41
Goodbye10.04!
CLOUD SAVVY
RUN Test KitchEN
42
Good Luck!
$ kitchen verify
CLOUD SAVVY 43
CLOUD SAVVY
WHAT FAILED?
44
FATAL: No cookbook found
CLOUD SAVVY
What are our requirements?
45
CLOUD SAVVY
What are our requirements?
45
Python
pippackage manager
make
setuptools
CLOUD SAVVY
COPY/PasTE
46
http://tinyurl.com/chefpart2
CLOUD SAVVY
BERKSFILE: DependencIES!
47
site :opscode
cookbook 'apt'cookbook 'build-‐essential'cookbook 'python'
CLOUD SAVVY
RUN Test KitchEN
48
Good Luck!
$ kitchen converge
CLOUD SAVVY 49
Congrats!
You installed something...
CLOUD SAVVY 49
Congrats!
You installed something...
but not what we need.
CLOUD SAVVY
BERKSFILE:THIS IS A COOKBOOK
50
site :opscode
cookbook 'apt'cookbook 'build-‐essential'cookbook 'python'metadata
CLOUD SAVVY
BERKSFILE:THIS IS A COOKBOOK
51
site :opscode
cookbook 'apt'cookbook 'build-‐essential'cookbook 'python'metadata
CLOUD SAVVY
RUN Test KitchEN
52
Good Luck!
$ kitchen converge
CLOUD SAVVY 53
CLOUD SAVVY
WHAT FAILED?
54
Failed to complete #converge action
CLOUD SAVVY
metadata.RB:What is this THING??
55
name "chefnovaclient"version "1.0.0"description "Installs the novaclient."maintainer "Hart Hoover"maintainer_email "[email protected]"
depends "python"depends "apt"
supports "ubuntu"
CLOUD SAVVY
RUN Test KitchEN
56
Good Luck!
$ kitchen converge
CLOUD SAVVY 57
Congrats!
You installed something...
CLOUD SAVVY 57
Congrats!
You installed something...
but STILL not what we need.
CLOUD SAVVY
TIME TO WRITE RECIPES
58
CLOUD SAVVY
TIME TO WRITE RECIPES
59
$ berks cookbook .
Don’t overwrite stuff
CLOUD SAVVY
Default RECIPE:recipes/default.rb
60
include_recipe "apt"include_recipe "python::pip"
%w{git python-‐dev build-‐essential}.each do |pkg| package pkg do action :install endend
python_pip "rackspace-‐novaclient" do action :installend
CLOUD SAVVY 61
include_recipe "apt"include_recipe "python::pip"
%w{git python-‐dev build-‐essential}.each do |pkg| package pkg do action :install endend
python_pip "rackspace-‐novaclient" do action :installend
Default RECIPE:recipes/default.rb
CLOUD SAVVY 62
include_recipe "apt"include_recipe "python::pip"
%w{git python-‐dev build-‐essential}.each do |pkg| package pkg do action :install endend
python_pip "rackspace-‐novaclient" do action :installend
Default RECIPE:recipes/default.rb
CLOUD SAVVY 63
include_recipe "apt"include_recipe "python::pip"
%w{git python-‐dev build-‐essential}.each do |pkg| package pkg do action :install endend
python_pip "rackspace-‐novaclient" do action :installend
Default RECIPE:recipes/default.rb
CLOUD SAVVY
EDIT YOUR RUN LIST
64
suites:-‐ name: default run_list: -‐ recipe[chefnovaclient::default] attributes: {}
.kitchen.yaml
CLOUD SAVVY
EDIT YOUR RUN LIST
65
suites:-‐ name: default run_list: -‐ recipe[chefnovaclient::default] attributes: {}
.kitchen.yaml
CLOUD SAVVY
RUN FOODCRITIC!
66
$ foodcritic .
Everything good?
CLOUD SAVVY 67
FIX IT!
If Not:
CLOUD SAVVY
RUN Test KitchEN
68
Good Luck!
$ kitchen converge
CLOUD SAVVY
Did it work?
69
$ kitchen login default$ nova help
CLOUD SAVVY 70
CLOUD SAVVY 71
CLOUD SAVVY 72
SUPERNOVA
CLOUD SAVVY
Let’s MAKE AUTOMATED TESTs
73
$ mkdir test/integration/default/bats
$ touch test/integration/default/bats/supernova.bats
CLOUD SAVVY
TESTING
74
test/integration/default/bats/supernova.bats
#!/usr/bin/env bats
@test "supernova is installed" { which supernova}
CLOUD SAVVY 75
@test "supernova config exists" { cat /home/vagrant/.supernova}
TESTINGtest/integration/default/bats/supernova.bats
CLOUD SAVVY 76
@test "run supernova" { supernova myaccount list}
TESTINGtest/integration/default/bats/supernova.bats
CLOUD SAVVY 77
@test "novaclient installed" { which nova}
TESTINGtest/integration/default/bats/supernova.bats
CLOUD SAVVY
SUPERNOVA
78
recipes/default.rb
python_pip "git+git://github.com/major/supernova.git" do action :installend
template "/home/vagrant/.supernova" do source "supernova.erb" mode 0600 owner "vagrant" group "vagrant"end
CLOUD SAVVY
SuperNova
79
templates/default/supernova.erb[myaccount]OS_AUTH_URL=https://identity.api.rackspacecloud.com/v2.0/OS_VERSION=2.0OS_AUTH_SYSTEM=rackspaceOS_REGION_NAME=DFWOS_SERVICE_NAME=cloudserversOpenStackOS_TENANT_NAME=<%= node['chefnovaclient']['username'] %>OS_USERNAME=<%= node['chefnovaclient']['username'] %>OS_PASSWORD=<%= node['chefnovaclient']['password'] %>OS_NO_CACHE=1NOVA_VOLUME_SERVICE_NAME=cloudBlockStorage
CLOUD SAVVY
SuperNova
80
templates/default/supernova.erb[myaccount]OS_AUTH_URL=https://identity.api.rackspacecloud.com/v2.0/OS_VERSION=2.0OS_AUTH_SYSTEM=rackspaceOS_REGION_NAME=DFWOS_SERVICE_NAME=cloudserversOpenStackOS_TENANT_NAME=<%= node['chefnovaclient']['username'] %>OS_USERNAME=<%= node['chefnovaclient']['username'] %>OS_PASSWORD=<%= node['chefnovaclient']['password'] %>OS_NO_CACHE=1NOVA_VOLUME_SERVICE_NAME=cloudBlockStorage
CLOUD SAVVY
SuperNova
81
attributes/default.rb
default['chefnovaclient']['username'] = "USERNAME"default['chefnovaclient']['password'] = "APIKEY"
CLOUD SAVVY
RUN FOODCRITIC!
82
$ foodcritic .
Everything good?
CLOUD SAVVY
RUN Test KitchEN
83
Good Luck!
$ kitchen converge
CLOUD SAVVY
RUN YOUR Tests
84
Good Luck!
$ kitchen verify
CLOUD SAVVY
“SAVE YOUR WORK”
85
CLOUD SAVVY
THANKYOU!