Deployment and update dependencies solved with Chef

One of the biggest questions when I present the Chef platform is: “How can we ensure that the database server is deployed/updated before the middleware and application server?”

People see the concept of resources, recipes and cookbooks and tend to think in a per node view. In my past i´ve seen several solutions, like copy a file at the end
of the first installation, create a database entry or others. With Chef there is a simple way to ensure that deployments or updates that shall apply to a full stack of
VM´s are handled: attributes.

Attributes (link) are part of Chef and stored with a node. Most of them are created automatically using ohai (link) but you can also set custom attributes and this is
where it becomes interesting. I will explain this in a small example:

We have 2 target machines that, 1 database server, 1 application server. The database server should be updated first and secondly the webserver.

We can add a small action at the end of the update recipe of the database server (/db-server-cookbook/recipes/update.rb):

ruby_block 'Set status attribute' do
  block do
    node.normal["install_status"] = "completed"
  end
end

PRO-TIP: Please note that the “old” method node.set will go away (Chef 14) and we will use node.normal instead.

This will add a node attribute as soon as the chef-client run reaches the end of the recipe. Now we can use the application update recipe (/app-server-cookbook/recipes/update.rb) to check if the database server already set the value. If so we can start the update of the application server as well with this litte snippet:

ruby_block 'Check for attribute' do
  block do
    sleep_time = 30
      result = search(:node, "name:#{node['dbserver']['name']}")
      puts result
        unless result.nil?
          puts "#{result.first['install_status']}"
          if result.first['install_status'] == "completed"
           exit = true
          else
           sleep sleep_time
          end
        else
          puts "nothing so far"
        end
    end
end

PRO-TIP: Please note that the name of the database server is an attribute in the recipe to be more dynamic.

As you can see the ruby snippet searches for the database server. As soon as the server was found it checks for the attribute that was set at the database server deployment/update. That´s really cool as you can check for all attributes on the system what allows you to create rules like (“all db servers in AWS but not the ones on vSphere”).

chef attributes

As soon as the attribute is set to “completed” exit will be set to true. This is where you can kick off with your application server installation.

Easy, right?

Leave a Reply