Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Testing Your Automation Code (Docker Version)

Testing Your Automation Code (Docker Version)

A hands-on workshop presented at ChefChef 2014 covering the basics of test automation with Chef.

Avatar for Mischa Taylor

Mischa Taylor

April 15, 2014
Tweet

More Decks by Mischa Taylor

Other Decks in Technology

Transcript

  1. 3 You’ve used and want to bulletproof your so that

    you are with Spec Wednesday, April 30, 14
  2. 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
  3. Using Chef is half the battle 5 “Chef is like....

    tests for your infrastructure” -Ezra Zygmuntowicz, Co-Founder Engine Yard http://www.akitaonrails.com/2008/6/5/railsconf-2008-brazil-rails-podcast-special-edition#.U0HfiF7Ed-8 Wednesday, April 30, 14
  4. Chef makes things more testable • Chef automates infrastructure in

    a repeatable fashion 6 Wednesday, April 30, 14
  5. What’s the other half of the battle? 7 “Have a

    plan” -Adam Jacob, Co-Founder Chef Wednesday, April 30, 14
  6. Recommended plan • Build in quality and robustness up front

    10 https://flic.kr/p/8W67ZC Wednesday, April 30, 14
  7. 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
  8. 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
  9. 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
  10. Penny saved with testing 16 Up Front Testing Saves Money

    https://www.flickr.com/people/68751915@N05/ Wednesday, April 30, 14
  11. 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
  12. 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
  13. The Tools • Each tool is specialized to give feedback

    as early as possible during the cookbook authoring process 20 Wednesday, April 30, 14
  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
  15. 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
  16. $ 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
  17. 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
  18. CloudShare Node • Register and login to CloudShare (see invite)

    • Start Using This Environment 27 Wednesday, April 30, 14
  19. 30 The Ubuntu w/Docker VM will be your Chef Development

    Workstation for this class Wednesday, April 30, 14
  20. $ 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. [email protected]'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
  21. 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
  22. 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
  23. 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
  24. $ 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
  25. 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
  26. 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
  27. $ knife cookbook site download build-essential $ tar xvf build-essential-*.tar.gz

    Download build-essential cookbook 51 Wednesday, April 30, 14
  28. $ cd /tmp $ sudo chef-client -z -o build-essential Use

    local mode to run cookbook 52 Wednesday, April 30, 14
  29. $ 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
  30. $ 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
  31. $ cd /tmp $ sudo chef-client -z -o git Use

    local mode to run cookbook 57 Wednesday, April 30, 14
  32. 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
  33. $ cd $HOME Home directory - great place for source

    62 $ cd %USERPROFILE% Wednesday, April 30, 14
  34. $ 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
  35. $ cd chef-fundamentals-repo chef-fundamentals-repo 64 !"" Berksfile !"" cookbooks/ !""

    data_bags/ !"" environments/ !"" .git/ !"" README.md !"" roles/ #"" Vagrantfile Wednesday, April 30, 14
  36. 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
  37. 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
  38. Back in my day... • Running a cookbook involved a

    lot of setup: • Configure workstation • Configure Chef Server • Bootstrap node 68 Wednesday, April 30, 14
  39. 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
  40. Supported Environments • Test Kitchen supports: • Virtual Machines •

    Cloud Instances • Metal - Physical Servers • Containers (Docker, LXC, etc.) 70 Wednesday, April 30, 14
  41. 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
  42. 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
  43. Ruby Gem • A gem is a application or supporting

    library written in ruby, installable with: 74 gem  install Wednesday, April 30, 14
  44. $ 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
  45. 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
  46. Gemfile • A Gemfile can be used to list all

    the gems you need for cookbook testing 80 Wednesday, April 30, 14
  47. Gemfile template • Test Kitchen can generate a Gemfile template

    (among other things) 81 Wednesday, April 30, 14
  48. $ 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
  49. $ 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
  50. 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
  51. $ 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
  52. 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
  53. 90 If you vendor gems use: bundle  exec to read

    gems in vendor/bunde Wednesday, April 30, 14
  54. 91 Test Kitchen commands • Let’s cover a few essential

    Test Kitchen commands Wednesday, April 30, 14
  55. 92 kitchen list • kitchen  list prints out a list

    of sandbox instances defined in .kitchen.yml Wednesday, April 30, 14
  56. $ 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
  57. $ 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
  58. 96 kitchen login • kitchen  login  <instance_name> uses ssh to

    login to the sandbox instance Wednesday, April 30, 14
  59. $ 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
  60. 98 kitchen destroy • kitchen  destroy  <instance_name> shuts down a

    sandbox instance and destroys and virtual resources allocated Wednesday, April 30, 14
  61. $ 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
  62. $ 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
  63. $ 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 FAIL Wednesday, April 30, 14
  64. 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
  65. 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
  66. 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
  67. 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
  68. .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
  69. --- 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
  70. $ 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
  71. $ 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
  72. 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
  73. 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
  74. 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
  75. 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
  76. 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
  77. 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
  78. 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
  79. $ 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
  80. $ 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
  81. $ 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
  82. $ 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
  83. 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
  84. 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
  85. $ 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
  86. $ 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
  87. $ 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
  88. 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
  89. 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 Pessimistic Version Constraint Wednesday, April 30, 14
  90. 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
  91. 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
  92. 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
  93. 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
  94. Pessimistic Version Constraint 150 gem 'library', '>= 2.2.0', ‘< 3.0’

    Explicitly exclude any versions that might break your code Wednesday, April 30, 14
  95. 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
  96. Description example 157 describe  ‘clowns  site’  do    it  ‘responds

     on  port  80’  do        ...    end end Wednesday, April 30, 14
  97. Expectation form 158 describe  ‘<entity>’  do    it  ‘<description>’  do

           expect(thing).to  eq  result    end end Wednesday, April 30, 14
  98. Expectation form 159 describe  ‘<entity>’  do    it  ‘<description>’  do

           expect(thing).to  eq  result    end end Matcher Wednesday, April 30, 14
  99. 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
  100. Expectation form 161 describe  ‘<entity>’  do    it  ‘<description>’  do

           expect(thing).to  eq  result    end end This is new syntax Wednesday, April 30, 14
  101. 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
  102. 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
  103. We Use Expect Form 164 Because all the ChefSpec examples

    are in the expect form Wednesday, April 30, 14
  104. 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
  105. 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
  106. 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
  107. 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
  108. 170 Suite subdirectory • Our suite name is default └──

     test/        └──  integration/                └──  default/ Wednesday, April 30, 14
  109. 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
  110. 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
  111. $ 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
  112. $ mkdir -p test/integration/default/serverspec Create test directory structure 175 >

    mkdir test\integration\default\serverspec Wednesday, April 30, 14
  113. 176 *_spec.rb files • By convention, Test Kitchen expects files

    with tests to end in _spec.rb Wednesday, April 30, 14
  114. 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
  115. Generic Expectation Form 178 describe  ‘<entity>’  do    it  ‘<description>’

     do        expect(thing).to  eq  result    end end Wednesday, April 30, 14
  116. 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
  117. 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
  118. 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
  119. 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
  120. 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
  121. $ 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
  122. 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
  123. $ 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
  124. 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
  125. 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
  126. $ 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
  127. $ 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 FAIL Wednesday, April 30, 14
  128. 193 Back to success • Remember to reset the tests

    back to the original port value so they succeed again! Wednesday, April 30, 14
  129. 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
  130. $ 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
  131. 196 Testing bears • Let’s add another test to do

    a similar check for the bears port Wednesday, April 30, 14
  132. 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
  133. 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
  134. $ 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
  135. 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
  136. 201 Code cleanup • Let’s move common code between clowns

    & bears to spec_helper.rb Wednesday, April 30, 14
  137. 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
  138. 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
  139. $ 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
  140. $ 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 WIN Wednesday, April 30, 14
  141. 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
  142. 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
  143. 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
  144. $ 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 WIN Wednesday, April 30, 14
  145. 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
  146. 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
  147. 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
  148. $ 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 WIN Wednesday, April 30, 14
  149. 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
  150. 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
  151. $ 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
  152. Where to go next • Jenkins cookbook is chock full

    of advanced Serverspec techniques: https://github.com/opscode-cookbooks/jenkins 220 Wednesday, April 30, 14
  153. 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
  154. 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
  155. 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
  156. 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
  157. 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
  158. 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
  159. 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
  160. $ sudo yum install -y libxslt-devel libxml2-devel Install Prerequisites 230

    $ sudo apt-get install -y libxslt-dev libxml2-dev Wednesday, April 30, 14
  161. $ 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
  162. 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
  163. 238 What about the FC003 & FC008 issues in the

    apache cookbook? Wednesday, April 30, 14
  164. 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
  165. OPEN IN EDITOR: cookbooks/apache/metadata.rb name 'apache' maintainer 'Mischa Taylor' maintainer_email

    '[email protected]' 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
  166. $ 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
  167. 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
  168. 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
  169. 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
  170. 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
  171. 253 --include parameter • The -­‐-­‐include  <PATH> parameter species additional

    paths to load rules (shortened with -I) Wednesday, April 30, 14
  172. $ 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
  173. 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
  174. 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
  175. 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
  176. 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
  177. 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
  178. 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
  179. $ 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
  180. 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
  181. $ 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
  182. .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
  183. $ bundle exec rubocop Run RuboCop on your cookbook Inspecting

    7 files ....... 7 files inspected, no offenses detected 270 Wednesday, April 30, 14
  184. 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
  185. 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
  186. 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
  187. $ 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
  188. Rubocop Workflow • Uncomment lines in rubocop-todo.yml • Fix offenses

    • git commit • Repeat 282 Wednesday, April 30, 14
  189. 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
  190. 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
  191. 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
  192. 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
  193. 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
  194. 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
  195. 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
  196. Documentation form 294 describe  ‘<recipe_name>’  do    <perform  in-­‐memory  Chef

     run>    <descriptions  here> end Wednesday, April 30, 14
  197. 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
  198. 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
  199. 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
  200. 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
  201. 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
  202. 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
  203. 303 Default location for tests • By default, ChefSpec will

    look in the spec/directory for ChefSpec test-related files Wednesday, April 30, 14
  204. 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
  205. 306 *_spec.rb files • By convention, ChefSpec expects files with

    tests to end in _spec.rb Wednesday, April 30, 14
  206. 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
  207. 313 Rspec runs ChefSpec • There’s no separate chefspec command.

    • Just run rspec to run ChefSpec tests. Wednesday, April 30, 14
  208. $ bundle exec rspec --color Run ChefSpec on your cookbok

    . Finished in 0.0006 seconds 1 example, 0 failures 314 Wednesday, April 30, 14
  209. 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
  210. $ 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
  211. 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
  212. $ bundle exec rspec --color Run ChefSpec on your cookbok

    . Finished in 0.0006 seconds 1 example, 0 failures 318 Wednesday, April 30, 14
  213. 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
  214. 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
  215. 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
  216. $ bundle exec rspec --color Run ChefSpec on your cookbok

    . Finished in 0.0006 seconds 1 example, 0 failures 322 Wednesday, April 30, 14
  217. 323 ChefSpec Resource Report • ChefSpec Resource Report can help

    guide writing your tests Wednesday, April 30, 14
  218. 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
  219. $ 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
  220. 326 create_file matcher • Let’s verify that the clowns.conf file

    gets created with the create_file matcher Wednesday, April 30, 14
  221. 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
  222. $ 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
  223. $ 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 FAIL Wednesday, April 30, 14
  224. 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
  225. 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
  226. $ bundle exec rspec --color Run ChefSpec on your cookbok

    . Finished in 0.01955 seconds 2 examples, 0 failures 334 Wednesday, April 30, 14
  227. $ bundle exec rspec --color Run ChefSpec on your cookbok

    . Finished in 0.01955 seconds 2 examples, 0 failures 335 WIN Wednesday, April 30, 14
  228. 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
  229. 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
  230. 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
  231. $ bundle exec rspec --color Run ChefSpec on your cookbok

    . Finished in 0.01955 seconds 2 examples, 0 failures 341 Wednesday, April 30, 14
  232. $ bundle exec rspec --color Run ChefSpec on your cookbok

    . Finished in 0.01955 seconds 2 examples, 0 failures 342 WIN Wednesday, April 30, 14
  233. 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
  234. 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
  235. 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
  236. 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
  237. 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
  238. $ 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
  239. 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
  240. $ 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
  241. $ 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
  242. 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
  243. 359 Where to go next Michael Goetz blog posts: ChefSpec

    and Guard: https://micgo.net/continuous-chefspec-validation-with-guard/ Wednesday, April 30, 14
  244. 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
  245. 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
  246. 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
  247. Rake - Repeatable Tasks • Task - expresses command line

    actions to perform 366 Wednesday, April 30, 14
  248. Rake - Repeatable Tasks • Configuration file for rake is

    a Rakefile 368 Wednesday, April 30, 14
  249. Rake - Actions • Actions are expressed in Ruby syntax

    • sh  “<command>”  runs a shell command: sh “bundle  exec  rspec” 369 Wednesday, April 30, 14
  250. OPEN IN EDITOR: cookbooks/apache/Rakefile task :rubocop do sh 'bundle exec

    rubocop' end Rubocop Task 370 Wednesday, April 30, 14
  251. $ bundle exec rake rubocop Execute Rake Task Inspecting 9

    files ....... 9 files inspected, no offenses detected 371 Wednesday, April 30, 14
  252. 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
  253. 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
  254. $ bundle exec rake --tasks Execute Rake Task rake rubocop

    # Run Ruby style checks with Rubocop 374 Wednesday, April 30, 14
  255. 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
  256. $ 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
  257. $ 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
  258. 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
  259. 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
  260. 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
  261. 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
  262. $ bundle exec rake Execute Rake Task bundle exec rubocop

    Inspecting 9 files ....... 7 files inspected, no offenses detected 383 Wednesday, April 30, 14
  263. 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
  264. 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
  265. $ sudo yum install -y libxslt-devel libxml2-devel Install Prerequisites 388

    $ sudo apt-get install -y libxslt-dev libxml2-dev Wednesday, April 30, 14
  266. $ cd $HOME Home directory - great place for source

    389 $ cd %USERPROFILE% Wednesday, April 30, 14
  267. Library cookbook • Popularized by Bryan Berry’s blog post How

    to Write Resuable Chef Cookbooks, Gangnam Style 391 Wednesday, April 30, 14
  268. $ 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
  269. $ 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
  270. 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
  271. 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
  272. $ 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
  273. OPEN IN EDITOR: test-class-jenkins/recipes/default.rb include_recipe 'jenkins::java' include_recipe 'jenkins::master' # Install

    version 1.13 of the greenballs plugin jenkins_plugin 'greenballs' do version '1.13' end Install greenballs plugin 407 Wednesday, April 30, 14
  274. $ 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... ... 408 Wednesday, April 30, 14
  275. OPEN IN EDITOR: test-class-jenkins/recipes/default.rb ... jenkins_script  'configure-­‐mailer'  do    command

     <<-­‐GROOVY.gsub(/^  {4}/,  '')        jenkins  =  jenkins.model.Jenkins.getInstance()        mailer  =  jenkins.getDescriptorByType(hudson.tasks.Mailer.DescriptorImpl)        mailer.setSmtpHost("smtp.gmail.com")        mailer.setUseSsl(true)        mailer.setSmtpAuth("smtp",  "password")        mailer.setReplyToAddress("[email protected]")        mailer.save()    GROOVY end Configure E-mail Notification 411 Wednesday, April 30, 14
  276. $ 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... ... 413 Wednesday, April 30, 14