Test-Driven Infrastructure Development with Chef

Stoyan Stoyanov

WeltN24 GmbH

22 April 2015

whoami

  • Spreading the DevOps Cutlture @ Welt
  • Worked as OPs, now more DEV
  • Rubyist still doing a lot of  Java ..
  • @s_stoyanoff

Why Chef?

  • Containers are cool but Dockerfiles are a step back imho
  • Chef is perfect for the provisioning and the orchestration of the containers
  • Still almost everything runs on VMs or bare metal servers

Why TDD your infrastructure?

  • Removes the fear of changing code
  • Enables you to react very quick to new requirements
    • Saves money in the long run
  • Avoid design problems
  • Documentation
  • More fun and time for the important things

What is TDD?

  • Red
  • Green
  • Refactor
  • Do it over and over again

Choose your weapon

Choose your weapon cont.

Organizing Code

  • Follow the ruby conventions
  • Don't put too much logic in the templates
    • Also use partial templates
  • Move complex logic from the recipes in lightweight resources
  • Pack pure ruby code in gems and test them separately (with rspec or minitest)

test-kitchen

  • It's an orchestration tool
  • We don't write tests in test-kitchen ;)
  • It runs tests across multiple nodes
    • converges nodes
    • enables the use of different matchers
    • verifies the state of the nodes

test-kitchen (cont'd)

  • Drivers
  • Provisioners
  • Platforms
  • Suites

Use the proper driver for test-kitchen

  • Quick feedback is fundamental
  • The vagrant driver is slow for end-to-end runs
  • Use kitchen converge and kitchen verify wisely
  • Find the best for your case
    • kitchen-docker (with chef_container or baseimage-docker)
    • kitchen-ec2
---
driver:
  name: chef_container

provisioner:
  name: chef_zero
  client_rb:
    require: 'chef-init'

platforms:
  - name: ubuntu-14.04
    driver_config:
      socket: <%= ENV['DOCKER_HOST'] %>
      image: chef/ubuntu-14.04
      disable_upstart: false
      forward: 9300
      privileged: true
      use_sudo: false

suites:
  - name: java
    run_list:
      - recipe[es::java]
  - name: default
    run_list:
      - recipe[es::default]
    attributes: { es: { cluster_name: 'foo' } }
  - name: plugins
    run_list:
      - recipe[es::default]
      - recipe[es::plugins]

Demo

Challenges

  • TDD hurts really hard at the beginning
  • You must know what to test
  • Many of the tools are under heavy development
    • But most of them are now stable
  • Beware that Dockers are not VMs
  • Integration with Jenkins is always tricky

Must Reads

Some Links

TDD with Chef

By Stoyan Stoyanov

TDD with Chef

  • 1,411