TDD WITH CHEF
FUN WITH FLAGS TESTING
Created by /Simone Soldateschi @soldasimo
( )
WHO AM I?
Simone Soldateschi @soldasimo
- Snr DevOps Engineer based in Sydney
- Leading DevOps Engineering Team at
- 15 years of experience as:
    - SysAdmin
    - SoftwareEng
    - SysEng
- Been DevOps'in for the last 5-ish years
Rackspace AU
WHAT IS TDD?
Test Driven Development
Meaning... write tests
see them fail
write code to pass tests
  ...still waiting...
SOUNDS WEIRD? ;)
WHY?
no PowerPoint-like presentation
using the mouse is boring
    and I don't have one
coding is fun
 
IT'S LIVE-DEMO, WITH TDD!
HOW?
Use TDD
Write Chef Cookbook
Deploy node.js web-app
Leverage Vagrant, Docker, or Cloud Server
Run this very presentation
    
Kinda recursive, isn't it? ;)
WHAT DO YOU USE?
 
"THE USUAL" DEPLOY WORKFLOW
start coding
compile it
deploy artifacts
looks good?
  wait   ...still waiting... any issues?
REACTIVE APPROACH
CHEF OVERVIEW
 
IN SHORT
code
test it
OK? push it
KO? fix it!
?
and many others
Berkshelf
Test Kitchen
Foodcritic
Default Ruby interpreter
$ which ruby
/usr/bin/ruby
Save you from headaches ( )Chef Docs
$ chef exec which ruby
/opt/chefdk/embedded/bin/ruby
Permanent settings
$ chef shell-init bash
export PATH="/opt/chefdk/bin:/Users/siso/.chefdk/gem/ruby/2.1.0/bin:/opt/chef
export GEM_ROOT="/opt/chefdk/embedded/lib/ruby/gems/2.1.0"
export GEM_HOME="/Users/siso/.chefdk/gem/ruby/2.1.0"
export GEM_PATH="/Users/siso/.chefdk/gem/ruby/2.1.0:/opt/chefdk/embedded/lib/
PROJECT SPECS
GOAL
Deploy this Node.js presentation
TASKS
Node.js should be installed
Checkout Git repository
Let the Internet access the web-server
Web-server should not run as root
LET'S COOK
 
Manually
$ cd cookbooks
$ mkdir -p foo/attributes foo/recipes
$ cat > foo/metadata.rb << EOF
> name 'foo'
> maintainer 'YOUR_COMPANY_NAME'
> maintainer_email 'YOUR_EMAIL'
> license 'All rights reserved'
> description 'Installs/Configures foo'
> long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
> version '0.1.0'
> EOF
...are you kidding me?!
knife
$ knife cookbook create foo
** Creating cookbook foo in /Users/siso/.chef/cookbooks
** Creating README for cookbook: foo
** Creating CHANGELOG for cookbook: foo
** Creating metadata for cookbook: foo
$ ls /Users/siso/.chef/cookbooks/foo/
CHANGELOG.md README.md attributes definitions files
libraries metadata.rb providers recipes resources
templates
Berkshelf
$ berks cookbook cheftdd
Get off on the right foot!
Berkshelf
$ berks cookbook cheftdd
...
create cheftdd/attributes
...
create cheftdd/recipes
...
create cheftdd/metadata.rb
...
create cheftdd/Berksfile
...
create .kitchen.yml
...
create test/integration/default
...
You must run `bundle install' to fetch any new gems.
create cheftdd/Vagrantfile
Berkshelf (full output)
$ berks cookbook cheftdd
create cheftdd/files/default
create cheftdd/templates/default
create cheftdd/attributes
create cheftdd/libraries
create cheftdd/providers
create cheftdd/recipes
create cheftdd/resources
create cheftdd/recipes/default.rb
create cheftdd/metadata.rb
create cheftdd/LICENSE
create cheftdd/README.md
create cheftdd/CHANGELOG.md
create cheftdd/Berksfile
create cheftdd/Thorfile
create cheftdd/chefignore
create cheftdd/.gitignore
GRAB RUBY GEMS
 
Bundler
$ bundle
Fetching gem metadata from https://rubygems.org/.......
Fetching additional metadata from https://rubygems.org/..
Resolving dependencies...
Using rake 10.4.2
Installing CFPropertyList 2.3.1
...
Using vagrant-wrapper 2.0.2
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
RUBOCOP
A Ruby static code analyzer, based on the community Ruby
style guide.
$ rubocop
warning: parser/current is loading parser/ruby21, which recognizes
warning: 2.1.5-compliant syntax, but you are running 2.1.4.
Inspecting 2 files
..
2 files inspected, no offenses detected
All good!
is a lint tool for your Opscode Chef cookbooks.
FOODCRITIC
Foodcritic
is a simple ruby build program with capabilities similar
to make.
RAKE
Rake
CHECK STYLE
Use Rake
to run andRubocop Foodcritic
in the right environment
with Bundler
$ bundle exec rake style
RACK005: Cookbook metadata must have maintainer='Rackspace' maintainer_email=
RACK005: Cookbook metadata must have maintainer='Rackspace' maintainer_email=
RACK008: Files expected by Support must exist: Berksfile.lock:0
RACK009: Berksfile.lock must not be in .gitignore: .gitignore:11
warning: parser/current is loading parser/ruby21, which recognizes
warning: 2.1.5-compliant syntax, but you are running 2.1.4.
Running RuboCop...
Inspecting 2 files
..
2 files inspected, no offenses detected
Need to fix something
Change Maintainer and email, and try again:
$ bundle exec rake style
RACK008: Files expected by Support must exist: Berksfile.lock:0
RACK009: Berksfile.lock must not be in .gitignore: .gitignore:11
warning: parser/current is loading parser/ruby21, which recognizes
warning: 2.1.5-compliant syntax, but you are running 2.1.4.
Running RuboCop...
Inspecting 2 files
..
2 files inspected, no offenses detected
It's better
Generate Berkshelf.lock:
$ berks install
Resolving cookbook dependencies...
Fetching 'cheftdd' from source at .
Fetching cookbook index from https://supermarket.chef.io...
Using cheftdd (0.1.0) from source at .
and let Git handle it
Try again:
$ bundle exec rake style
warning: parser/current is loading parser/ruby21, which recognizes
warning: 2.1.5-compliant syntax, but you are running 2.1.4.
Running RuboCop...
Inspecting 2 files
..
2 files inspected, no offenses detected
OK!
write RSpec tests
check servers are configured correctly
RSpec
Behaviour Driven Development for Ruby
Making TDD Productive and Fun
Default recipe should
update the package-manager database
upgrade packages
Which is
# apt-get update
# apt-get upgrade
Then write a test
$ cat test/unit/spec/default_spec.rb
...
it 'executes apt-get update' do
expect(chef_run).to run_execute('apt-get update')
end
...
it fails
$ bundle exec rake spec
/opt/chefdk/embedded/bin/ruby -I/Users/siso/.chefdk/gem/ruby/2.1.0/gems/rspec
F
Failures:
1) cheftdd::default executes apt-get update
Failure/Error: expect(chef_run).to run_execute('apt-get update')
expected "execute[apt-get update]" with action :run to be in Chef run.
# ./test/unit/spec/default_spec.rb:23:in `block (2 levels) in <top (requ
Finished in 0.15203 seconds (files took 2.39 seconds to load)
1 example, 1 failure
Write code to pass the test
#
# Cookbook Name:: cheftdd
# Recipe:: default
#
# Copyright (C) 2015 YOUR_NAME
#
# All rights reserved - Do Not Redistribute
#
execute "apt-get update/upgrade" do
command "apt-get update"
action :run
end
Run the test again
$ bundle exec rake spec
/opt/chefdk/embedded/bin/ruby -I/Users/siso/.chefdk/gem/ruby/2.1.0/gems/rspec
.
Finished in 0.16453 seconds (files took 2.52 seconds to load)
1 example, 0 failures
ChefSpec Coverage report generated...
Total Resources: 1
Touched Resources: 1
Touch Coverage: 100.0%
You are awesome and so is your test coverage! Have a fantastic day!
it's OK!
'NODEJS' RECIPE
Install Node.js
+
deploy web-app
Deploy :reveal.js
install and
clone reveal.js
resolve dependencies
serve the slide-deck
Node.js Grunt
$ git clone https://github.com/hakimel/reveal.js.git
$ npm install
$ grunt serve --port 80
FILE-NAMING SCHEMA
recipes/nodejs.rb
⥥
test/unit/spec/nodejs_spec.rb
test/unit/spec/nodejs_spec.rb
it 'include nodejs recipe' do
expect(chef_run).to include_recipe('nodejs')
end
# Follow instructions to install reveal.js on https://github.com/hakimel/reve
it 'install grunt-cli' do
expect(chef_run).to run_execute('npm install -g grunt-cli')
end
it 'install git' do
expect(chef_run).to install_apt_package('git')
end
it 'clone reveal.js GitHub repository' do
expect(chef_run).to run_execute('git clone https://github.com/hakimel/revea
end
recipes/nodejs.rbtests fail:
$ bundle exec rake spec
/opt/chefdk/embedded/bin/ruby -I/Users/siso/.chefdk/gem/ruby/2.1.0/gems/rspec
.FFFFF
Failures:
1) cheftdd::nodejs include nodejs recipe
Failure/Error: expect(chef_run).to include_recipe('nodejs')
expected ["cheftdd::nodejs"] to include "nodejs::default"
# ./test/unit/spec/nodejs_spec.rb:23:in `block (2 levels) in <top (requi
2) cheftdd::nodejs install grunt-cli
Failure/Error: expect(chef_run).to run_execute('npm install -g grunt-cli
expected "execute[npm install -g grunt-cli]" with action :run to be in
Install Node.js
#
# Cookbook Name:: cheftdd-demo
# Recipe:: nodejs
#
# Copyright (C) 2015 YOUR_NAME
#
# All rights reserved - Do Not Redistribute
#
#
# Install reveal.js - https://github.com/hakimel/reveal.js/
#
# install nodejs, from package by default
include_recipe 'nodejs'
execute 'install grunt-cli' do
Install reveal.js
package 'git' do
action :install
end
execute 'clone reveal.js GitHub repository' do
command 'git clone https://github.com/hakimel/reveal.js.git'
action :run
cwd '/opt'
not_if { File.exist?('/opt/reveal.js') }
end
Resolve dependencies
execute 'install npm packages' do
command 'npm install'
action :run
cwd '/opt/reveal.js'
end
execute 'start serving node.js app' do
command 'grunt serve &'
action :run
cwd '/opt/reveal.js'
end
Test nodejsrecipe:
$ bundle exec rake spec
/opt/chefdk/embedded/bin/ruby -I/Users/siso/.chefdk/gem/ruby/2.1.0/gems/rspec
......
Finished in 1.06 seconds (files took 2.51 seconds to load)
6 examples, 0 failures
Great, it's OK!
INTEGRATION TESTING
TEST KITCHEN
- run Integration Tests
- awesome documentation
have a read!
.KITCHEN.YML
---
driver:
name: vagrant
customize:
memory: 1024
provisioner:
name: chef_zero
nodes_path: "test/integration/nodes"
require_chef_omnibus: 11.16.4
client_rb:
environment: _default
attributes:
testkitchen: true
openssh:
server:
password_authentication: 'yes'
permit_root_login: 'yes'
authorization:
sudo:
users: ['vagrant']
passwordless: true
platforms:
- name: ubuntu-14.04
suites:
- name: default
run_list:
attributes:
- name: nodejs
run_list:
- recipe[cheftdd::default]
- recipe[cheftdd::nodejs]
NODE LIFECYCLE
Current status of nodes:
$ kitchen list
Instance Driver Provisioner Last Action
nodejs-ubuntu-1404 Rackspace ChefZero Not Created
Create node
# kitchen create
Node status
$ kitchen list
Instance Driver Provisioner Last Action
nodejs-ubuntu-1404 Rackspace ChefZero Created
Converge node
# kitchen converge
CONVERGE NODE
run chef-client on node
apply recipes
Node status
$ kitchen list
Instance Driver Provisioner Last Action
nodejs-ubuntu-1404 Rackspace ChefZero Converged
INTEGRATION TESTS
FILE-NAMING SCHEMA
test/integration/SUITE/rspec/WHATEVER_spec.rb
⥥
KitchenCI SUITE: nodejs
⥥
test/integration/nodejs/rspec/nodejs_spec.rb
RECIPE
# install nodejs, from package by default
include_recipe 'nodejs'
TEST
describe command('nodejs --version') do
its(:stdout) { should match(/v0.10.37/) }
end
RECIPE
package 'git' do
action :install
end
TEST
describe package('git') do
it { should be_installed }
end
RECIPE
execute 'clone reveal.js GitHub repository' do
command 'git clone https://github.com/hakimel/reveal.js.git'
action :run
cwd '/opt'
not_if { File.exist?('/opt/reveal.js') }
end
TEST
describe file('/opt/reveal.js') do
it { should be_directory }
end
RECIPE
execute 'start serving node.js app' do
command 'grunt serve --port 80 &'
action :run
cwd '/opt/reveal.js'
end
TEST
describe port('80') do
it { should be_listening }
end
RECIPE
add_iptables_rule('INPUT', '-p tcp -m state --state NEW --dport 80 -
s 0.0.0.0/0 -j ACCEPT', 50, 'Allow the Internet access the web-serve
r')
TEST
describe iptables do
it { should have_rule('-A INPUT -p tcp -m state --state NEW -m tcp
--dport 80 -m comment --comment "Allow the Internet access the web-
server" -j ACCEPT').with_chain('INPUT') }
end
KITCHENCI - INTEGRATION TESTS
Eventually, run integration tests
# kitchen verify
$ kitchen verify
-----> Starting Kitchen (v1.3.1)
-----> Setting up <nodejs-ubuntu-1404>...
-----> Setting up Busser
...
-----> Verifying <nodejs-ubuntu-1404>...
...
-----> Running rspec test suite
...
Finished in 0.09244 seconds
4 examples, 0 failures
Finished verifying <nodejs-ubuntu-1404> (0m2.94s).
-----> Kitchen is finished. (0m11.06s)
Full output:
$ kitchen verify
-----> Starting Kitchen (v1.3.1)
-----> Setting up <nodejs-ubuntu-1404>...
-----> Setting up Busser
Creating BUSSER_ROOT in /tmp/busser
Creating busser binstub
Plugin rspec already installed
Finished setting up <nodejs-ubuntu-1404> (0m3.09s).
-----> Verifying <nodejs-ubuntu-1404>...
Removing /tmp/busser/suites/rspec
Uploading /tmp/busser/suites/rspec/Gemfile (mode=0644)
Uploading /tmp/busser/suites/rspec/nodejs_spec.rb (mode=0644)
Uploading /tmp/busser/suites/rspec/spec_helper.rb (mode=0644)
-----> Running rspec test suite
run PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/
Don't run Bundler as root. Bundler can ask for sudo if it is needed, a
installing your bundle as root will break this application for all non
ALL IN ONE GO
$ kitchen test
«ha ah»
$ kitchen test
⥥
$ kitchen destroy
⥥
$ kitchen create
⥥
$ kitchen converge
⥥
$ kitchen verify
⥥
$ kitchen destroy
RECAP
write unit-tests
⥥
implement features
run unit-tests
⥥
$ bundle exec rake style
⥥
$ bundle exec rake spec
KO? fix it!
OK? move on
write integration-tests
⥥
run integration-tests
$ kitchen create
⥥
$ kitchen converge
⥥
$ kitchen verify
⥥
KO? fix it!
⥥
OK? done
LINKS
- click links on this slide-deck
-
-
-
-
-
-
-
An Overview of Chef
Install Chef DK
TDD with Chef, by Nathen Harvey
reveal.js
TDD with Chef, by Nathen Harvey
DevOps Reactions on Tumblr
The Phoenix Project
Source Quantity
The Big Bang Theory 1
Breaking Bad 1
How I Met Your Mother 2
Matrix 1

Test Driven Development with Chef

  • 1.
    TDD WITH CHEF FUNWITH FLAGS TESTING Created by /Simone Soldateschi @soldasimo
  • 2.
    ( ) WHO AMI? Simone Soldateschi @soldasimo - Snr DevOps Engineer based in Sydney - Leading DevOps Engineering Team at - 15 years of experience as:     - SysAdmin     - SoftwareEng     - SysEng - Been DevOps'in for the last 5-ish years Rackspace AU
  • 3.
    WHAT IS TDD? TestDriven Development Meaning... write tests see them fail write code to pass tests   ...still waiting... SOUNDS WEIRD? ;)
  • 4.
    WHY? no PowerPoint-like presentation usingthe mouse is boring     and I don't have one coding is fun   IT'S LIVE-DEMO, WITH TDD!
  • 5.
    HOW? Use TDD Write ChefCookbook Deploy node.js web-app Leverage Vagrant, Docker, or Cloud Server Run this very presentation      Kinda recursive, isn't it? ;)
  • 6.
    WHAT DO YOUUSE?  
  • 7.
    "THE USUAL" DEPLOYWORKFLOW start coding compile it deploy artifacts looks good?   wait   ...still waiting... any issues? REACTIVE APPROACH
  • 8.
  • 12.
    IN SHORT code test it OK?push it KO? fix it!
  • 13.
  • 15.
  • 16.
    Default Ruby interpreter $which ruby /usr/bin/ruby
  • 17.
    Save you fromheadaches ( )Chef Docs $ chef exec which ruby /opt/chefdk/embedded/bin/ruby
  • 18.
    Permanent settings $ chefshell-init bash export PATH="/opt/chefdk/bin:/Users/siso/.chefdk/gem/ruby/2.1.0/bin:/opt/chef export GEM_ROOT="/opt/chefdk/embedded/lib/ruby/gems/2.1.0" export GEM_HOME="/Users/siso/.chefdk/gem/ruby/2.1.0" export GEM_PATH="/Users/siso/.chefdk/gem/ruby/2.1.0:/opt/chefdk/embedded/lib/
  • 19.
    PROJECT SPECS GOAL Deploy thisNode.js presentation TASKS Node.js should be installed Checkout Git repository Let the Internet access the web-server Web-server should not run as root
  • 24.
  • 25.
    Manually $ cd cookbooks $mkdir -p foo/attributes foo/recipes $ cat > foo/metadata.rb << EOF > name 'foo' > maintainer 'YOUR_COMPANY_NAME' > maintainer_email 'YOUR_EMAIL' > license 'All rights reserved' > description 'Installs/Configures foo' > long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) > version '0.1.0' > EOF
  • 26.
  • 27.
    knife $ knife cookbookcreate foo ** Creating cookbook foo in /Users/siso/.chef/cookbooks ** Creating README for cookbook: foo ** Creating CHANGELOG for cookbook: foo ** Creating metadata for cookbook: foo $ ls /Users/siso/.chef/cookbooks/foo/ CHANGELOG.md README.md attributes definitions files libraries metadata.rb providers recipes resources templates
  • 28.
  • 29.
    Get off onthe right foot!
  • 30.
    Berkshelf $ berks cookbookcheftdd ... create cheftdd/attributes ... create cheftdd/recipes ... create cheftdd/metadata.rb ... create cheftdd/Berksfile ... create .kitchen.yml ... create test/integration/default ... You must run `bundle install' to fetch any new gems. create cheftdd/Vagrantfile
  • 31.
    Berkshelf (full output) $berks cookbook cheftdd create cheftdd/files/default create cheftdd/templates/default create cheftdd/attributes create cheftdd/libraries create cheftdd/providers create cheftdd/recipes create cheftdd/resources create cheftdd/recipes/default.rb create cheftdd/metadata.rb create cheftdd/LICENSE create cheftdd/README.md create cheftdd/CHANGELOG.md create cheftdd/Berksfile create cheftdd/Thorfile create cheftdd/chefignore create cheftdd/.gitignore
  • 32.
  • 33.
    Bundler $ bundle Fetching gemmetadata from https://rubygems.org/....... Fetching additional metadata from https://rubygems.org/.. Resolving dependencies... Using rake 10.4.2 Installing CFPropertyList 2.3.1 ... Using vagrant-wrapper 2.0.2 Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
  • 34.
    RUBOCOP A Ruby staticcode analyzer, based on the community Ruby style guide.
  • 35.
    $ rubocop warning: parser/currentis loading parser/ruby21, which recognizes warning: 2.1.5-compliant syntax, but you are running 2.1.4. Inspecting 2 files .. 2 files inspected, no offenses detected All good!
  • 36.
    is a linttool for your Opscode Chef cookbooks. FOODCRITIC Foodcritic
  • 37.
    is a simpleruby build program with capabilities similar to make. RAKE Rake
  • 38.
    CHECK STYLE Use Rake torun andRubocop Foodcritic in the right environment with Bundler
  • 39.
    $ bundle execrake style RACK005: Cookbook metadata must have maintainer='Rackspace' maintainer_email= RACK005: Cookbook metadata must have maintainer='Rackspace' maintainer_email= RACK008: Files expected by Support must exist: Berksfile.lock:0 RACK009: Berksfile.lock must not be in .gitignore: .gitignore:11 warning: parser/current is loading parser/ruby21, which recognizes warning: 2.1.5-compliant syntax, but you are running 2.1.4. Running RuboCop... Inspecting 2 files .. 2 files inspected, no offenses detected Need to fix something
  • 40.
    Change Maintainer andemail, and try again: $ bundle exec rake style RACK008: Files expected by Support must exist: Berksfile.lock:0 RACK009: Berksfile.lock must not be in .gitignore: .gitignore:11 warning: parser/current is loading parser/ruby21, which recognizes warning: 2.1.5-compliant syntax, but you are running 2.1.4. Running RuboCop... Inspecting 2 files .. 2 files inspected, no offenses detected It's better
  • 41.
    Generate Berkshelf.lock: $ berksinstall Resolving cookbook dependencies... Fetching 'cheftdd' from source at . Fetching cookbook index from https://supermarket.chef.io... Using cheftdd (0.1.0) from source at . and let Git handle it
  • 42.
    Try again: $ bundleexec rake style warning: parser/current is loading parser/ruby21, which recognizes warning: 2.1.5-compliant syntax, but you are running 2.1.4. Running RuboCop... Inspecting 2 files .. 2 files inspected, no offenses detected OK!
  • 44.
    write RSpec tests checkservers are configured correctly
  • 45.
    RSpec Behaviour Driven Developmentfor Ruby Making TDD Productive and Fun
  • 46.
    Default recipe should updatethe package-manager database upgrade packages
  • 47.
    Which is # apt-getupdate # apt-get upgrade
  • 48.
    Then write atest $ cat test/unit/spec/default_spec.rb ... it 'executes apt-get update' do expect(chef_run).to run_execute('apt-get update') end ...
  • 49.
    it fails $ bundleexec rake spec /opt/chefdk/embedded/bin/ruby -I/Users/siso/.chefdk/gem/ruby/2.1.0/gems/rspec F Failures: 1) cheftdd::default executes apt-get update Failure/Error: expect(chef_run).to run_execute('apt-get update') expected "execute[apt-get update]" with action :run to be in Chef run. # ./test/unit/spec/default_spec.rb:23:in `block (2 levels) in <top (requ Finished in 0.15203 seconds (files took 2.39 seconds to load) 1 example, 1 failure
  • 50.
    Write code topass the test # # Cookbook Name:: cheftdd # Recipe:: default # # Copyright (C) 2015 YOUR_NAME # # All rights reserved - Do Not Redistribute # execute "apt-get update/upgrade" do command "apt-get update" action :run end
  • 51.
    Run the testagain $ bundle exec rake spec /opt/chefdk/embedded/bin/ruby -I/Users/siso/.chefdk/gem/ruby/2.1.0/gems/rspec . Finished in 0.16453 seconds (files took 2.52 seconds to load) 1 example, 0 failures ChefSpec Coverage report generated... Total Resources: 1 Touched Resources: 1 Touch Coverage: 100.0% You are awesome and so is your test coverage! Have a fantastic day! it's OK!
  • 52.
  • 54.
    Deploy :reveal.js install and clonereveal.js resolve dependencies serve the slide-deck Node.js Grunt $ git clone https://github.com/hakimel/reveal.js.git $ npm install $ grunt serve --port 80
  • 55.
  • 56.
    test/unit/spec/nodejs_spec.rb it 'include nodejsrecipe' do expect(chef_run).to include_recipe('nodejs') end # Follow instructions to install reveal.js on https://github.com/hakimel/reve it 'install grunt-cli' do expect(chef_run).to run_execute('npm install -g grunt-cli') end it 'install git' do expect(chef_run).to install_apt_package('git') end it 'clone reveal.js GitHub repository' do expect(chef_run).to run_execute('git clone https://github.com/hakimel/revea end
  • 57.
    recipes/nodejs.rbtests fail: $ bundleexec rake spec /opt/chefdk/embedded/bin/ruby -I/Users/siso/.chefdk/gem/ruby/2.1.0/gems/rspec .FFFFF Failures: 1) cheftdd::nodejs include nodejs recipe Failure/Error: expect(chef_run).to include_recipe('nodejs') expected ["cheftdd::nodejs"] to include "nodejs::default" # ./test/unit/spec/nodejs_spec.rb:23:in `block (2 levels) in <top (requi 2) cheftdd::nodejs install grunt-cli Failure/Error: expect(chef_run).to run_execute('npm install -g grunt-cli expected "execute[npm install -g grunt-cli]" with action :run to be in
  • 58.
    Install Node.js # # CookbookName:: cheftdd-demo # Recipe:: nodejs # # Copyright (C) 2015 YOUR_NAME # # All rights reserved - Do Not Redistribute # # # Install reveal.js - https://github.com/hakimel/reveal.js/ # # install nodejs, from package by default include_recipe 'nodejs' execute 'install grunt-cli' do
  • 59.
    Install reveal.js package 'git'do action :install end execute 'clone reveal.js GitHub repository' do command 'git clone https://github.com/hakimel/reveal.js.git' action :run cwd '/opt' not_if { File.exist?('/opt/reveal.js') } end
  • 60.
    Resolve dependencies execute 'installnpm packages' do command 'npm install' action :run cwd '/opt/reveal.js' end execute 'start serving node.js app' do command 'grunt serve &' action :run cwd '/opt/reveal.js' end
  • 61.
    Test nodejsrecipe: $ bundleexec rake spec /opt/chefdk/embedded/bin/ruby -I/Users/siso/.chefdk/gem/ruby/2.1.0/gems/rspec ...... Finished in 1.06 seconds (files took 2.51 seconds to load) 6 examples, 0 failures Great, it's OK!
  • 62.
  • 63.
  • 65.
    - run IntegrationTests - awesome documentation have a read!
  • 66.
  • 67.
    provisioner: name: chef_zero nodes_path: "test/integration/nodes" require_chef_omnibus:11.16.4 client_rb: environment: _default attributes: testkitchen: true openssh: server: password_authentication: 'yes' permit_root_login: 'yes' authorization: sudo: users: ['vagrant'] passwordless: true
  • 68.
  • 69.
    suites: - name: default run_list: attributes: -name: nodejs run_list: - recipe[cheftdd::default] - recipe[cheftdd::nodejs]
  • 70.
    NODE LIFECYCLE Current statusof nodes: $ kitchen list Instance Driver Provisioner Last Action nodejs-ubuntu-1404 Rackspace ChefZero Not Created
  • 71.
  • 72.
    Node status $ kitchenlist Instance Driver Provisioner Last Action nodejs-ubuntu-1404 Rackspace ChefZero Created
  • 73.
  • 74.
    CONVERGE NODE run chef-clienton node apply recipes
  • 75.
    Node status $ kitchenlist Instance Driver Provisioner Last Action nodejs-ubuntu-1404 Rackspace ChefZero Converged
  • 76.
  • 77.
    RECIPE # install nodejs,from package by default include_recipe 'nodejs' TEST describe command('nodejs --version') do its(:stdout) { should match(/v0.10.37/) } end
  • 78.
    RECIPE package 'git' do action:install end TEST describe package('git') do it { should be_installed } end
  • 79.
    RECIPE execute 'clone reveal.jsGitHub repository' do command 'git clone https://github.com/hakimel/reveal.js.git' action :run cwd '/opt' not_if { File.exist?('/opt/reveal.js') } end TEST describe file('/opt/reveal.js') do it { should be_directory } end
  • 80.
    RECIPE execute 'start servingnode.js app' do command 'grunt serve --port 80 &' action :run cwd '/opt/reveal.js' end TEST describe port('80') do it { should be_listening } end
  • 81.
    RECIPE add_iptables_rule('INPUT', '-p tcp-m state --state NEW --dport 80 - s 0.0.0.0/0 -j ACCEPT', 50, 'Allow the Internet access the web-serve r') TEST describe iptables do it { should have_rule('-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -m comment --comment "Allow the Internet access the web- server" -j ACCEPT').with_chain('INPUT') } end
  • 82.
    KITCHENCI - INTEGRATIONTESTS Eventually, run integration tests # kitchen verify
  • 83.
    $ kitchen verify ----->Starting Kitchen (v1.3.1) -----> Setting up <nodejs-ubuntu-1404>... -----> Setting up Busser ... -----> Verifying <nodejs-ubuntu-1404>... ... -----> Running rspec test suite ... Finished in 0.09244 seconds 4 examples, 0 failures Finished verifying <nodejs-ubuntu-1404> (0m2.94s). -----> Kitchen is finished. (0m11.06s)
  • 85.
    Full output: $ kitchenverify -----> Starting Kitchen (v1.3.1) -----> Setting up <nodejs-ubuntu-1404>... -----> Setting up Busser Creating BUSSER_ROOT in /tmp/busser Creating busser binstub Plugin rspec already installed Finished setting up <nodejs-ubuntu-1404> (0m3.09s). -----> Verifying <nodejs-ubuntu-1404>... Removing /tmp/busser/suites/rspec Uploading /tmp/busser/suites/rspec/Gemfile (mode=0644) Uploading /tmp/busser/suites/rspec/nodejs_spec.rb (mode=0644) Uploading /tmp/busser/suites/rspec/spec_helper.rb (mode=0644) -----> Running rspec test suite run PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/ Don't run Bundler as root. Bundler can ask for sudo if it is needed, a installing your bundle as root will break this application for all non
  • 86.
    ALL IN ONEGO $ kitchen test «ha ah»
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
    LINKS - click linkson this slide-deck - - - - - - - An Overview of Chef Install Chef DK TDD with Chef, by Nathen Harvey reveal.js TDD with Chef, by Nathen Harvey DevOps Reactions on Tumblr The Phoenix Project
  • 95.
    Source Quantity The BigBang Theory 1 Breaking Bad 1 How I Met Your Mother 2 Matrix 1