Robert Shecter

Test Driven Devops

Illustration: 500 - Internal server error

A new take on TDD

I like to apply Test Driven Development (TDD) to my sysadmin and security work. Every time I add a new redirect to a web server, I want to ensure I didn’t break something else.

Test Driven Development

Further, I want my SSL configurations proactively checked daily for any possible error. I use Ruby RSpec and write tests like these:

describe 'My app' do
  context 'www.myapp.com' do
    it { should be_up }
    it { should have_a_valid_cert }
  end

  it 'serves the www.myapp.com page without redirecting' do
    expect('http://www.myapp.com/about').to be_status 200
  end

  it 'only serves via www' do
    expect('http://myapp.com').to redirect_permanently_to 'http://www.myapp.com/'
  end

  it 'forces visitors to use https' do
    expect('myapp.com').to enforce_https_everywhere
  end
end

I created these new functions to help write these tests : be_up, have_a_valid_cert, be_status, redirect_permanently_to, and enforce_https_everywhere.

Step 1: Write a failing test

When I want to make a configuration change, I first write a new test for the desired outcome. I literally think to myself, “How do I want my app to work?” The test should demonstrate that. Naturally, it fails while the old tests pass.

Step 2: Make the firewall/Linux/whatever configuration work

Then I work on the config change. I re-run all the tests as I go. I am finished when they all pass. (Extra benefit: I know when to stop working!) I also run these automatically from a cron job to get pro-active notification of new problems.

Step 3: Clean up and document

All the tests are passing. That means I have a nice “safety net.” It lets me clean up and reorganize my configurations if they need it.

The phrases like have_a_valid_cert are custom RSpec matchers; they’re added into the RSpec environment by my open source library on Github.

4 responses to “Test Driven Devops”

  1. John Cooper Avatar
    John Cooper

    I have been doing a similar thing using cucumber and some simple net/http tests. It works okay but I like the format of what you have done there. Looks a lot simpler. I’ll have a look at it in more detail at the next major change we are looking at.
    Any reason you are switching to python? Will this mean you are not updating this library?
    Thanks for sharing your code.

    1. Robb Avatar
      Robb

      I’ll definitely be keeping this up to date; Ruby excels when it comes to test frameworks and Domain Specific Languages. I’d like to see what’s possible with Python because I find code written with it more maintainable.

  2. Arnab Avatar
    Arnab

    Your post reminds of something very similar – http://babushka.me/. Babushka is a tool for automating test-driven system admin tasks, you can check it out and see, it also has pretty nice DSL as well. You can also see https://github.com/politburo/politburo which is a Ruby DSL written on top of Babushka.

  3. mestachs Avatar
    mestachs

    Looks like https://github.com/garethr/prodder/ is pushing a bit further the ssl/http headers/open ports.
    Another, more generic, framework is gauntlt : http://gauntlt.org/

Leave a reply to Arnab Cancel reply