chef from opscode and the power of ruby

Posted by Edmund Haselwanter on Wednesday, October 14, 2009

Recent releases of chef from opscode provide a new resource: ruby_block

This is really great news as this allows for interesting problem solving.

Consider you want to do a very special HTTP request. E.g. a GET to localhost but with custom “Host” header information.

Install a Ruby Http Client

First we have to install a Ruby http client library. I’ll use curb in this example. It builds on top of libcurl so lets install that first.

   1  curl_devel = package "curl-devel" do
   2    action :install
   3  end
   4  
   5  curl_devel.run_action(:install)

With this code we tell chef to immediately execute this code. Otherwise we would have to face the problem that we just fullfill the chefrun post-condition that we have curl-devel installed. Next we have to install the curb gem.

   1  curb_gem = gem_package "curb" do
   2    action :install
   3  end
   4  
   5  curb_gem.run_action(:install)

as you see this is done the same way. Next we want to use curb in THIS chef-run. So we have tell chef the update of Gem, followed by requiring curb

   1  Gem.clear_paths
   2  
   3  require 'curb'

Ruby Code in Action

Now we are ready to take action.

   1  ruby_block "do-http-request-with-cutom-header" do
   2    block do
   3      timeout = 600
   4      host = "localhost:8080"
   5      real_host = "my.realhost.com"
   6      Chef::Log.info "call get on #{host}, maximal request time: #{timeout} seconds"
   7      c = Curl::Easy.new("http://#{host}/maintenance/do_something") do |curl|
   8        curl.headers['Host'] = real_host
   9        curl.verbose = true
  10        curl.timeout = timeout
  11      end
  12      c.perform
  13      if c.response_code == 200
  14        Chef::Log.info "GET success! response was:#{c.body_str}"
  15      else
  16        Chef::Log.error "GET FAILED. request response was HTTP #{c.response_code}, body: #{c.body_str}"
  17      end
  18    end
  19    action :create
  20  end

Great. Isn’t it? :-)