Looping through Attributes within Chef Recipes

In a quest to make it easier for myself and others to modify my Chef recipes, I thought it was about time I started to use attributes much more seriously than I had been doing previously.

Soon enough, I needed to loop through a hash of attributes in order to make my recipe’s code as clean and efficient as possible, and if you are relatively new to Chef then you might find yourself running into the same syntactical nightmare I did.

Here’s how I did it.

The following is an extract from my attributes/default.rb file:

default[:software] = {
  :repos => {
    :remove => [
      'CentOS-Base',
      'CentOS-Debuginfo',
      'CentOS-fasttrack',
      'CentOS-Media',
      'CentOS-Vault'
  ],

The aim here is to use the yum cookbook to remove each of the listed repositories from the base image.

The code below addresses the part of the hash we wish to work with, takes the value contained within and runs through each iteration, passing i which contains the name of the repository:

# Remove base image repo's
node[:software][:repos][:remove].each do |i|
  yum_repository i do
    action :delete
  end
end

Great! We have supplied a single piece of information stored in a relatively simple hash and provided it to the yum_repository statement within the recipe.

Though, we now want to configure yum to use some new repositories, and this requires multiple bits of information to be supplied for each repository we wish to add…

Take a look at the next part of my attributes/default.rb file:

:add => {
  :epel => {
    'name' => 'epel',
    'description' => 'Extra Packages for Enterprise Linux',
    'baseurl' => 'http://hostname/repo/epel/6/$basearch/',
    'gpgkey' => 'http://hostname/repo/epel/RPM-GPG-KEY-EPEL-6',
    'gpgcheck' => true
  },
  :centos => {
    'name' => 'centos',
    'description' => 'CentOS Base',
    'baseurl' => 'http://hostname/repo/centos/$releasever/os/$basearch/',
    'gpgkey' => nil,
    'gpgcheck' => false
  }
}

Here we can see each repository has a set of defined key’s and associated values, we need to supply these to the yum_repository statement a little more gracefully this time, rather than just looping through blindly.

# Add custom repo's
node[:software][:repos][:add].each do |k, v|
  yum_repository v['name'] do
    description v['description']
    baseurl v['baseurl']
    gpgkey v['gpgkey']
    gpgcheck v['gpgcheck']
    action :create
  end
end

To a ruby guru, this may be pretty obvious, though it took a while to figure out both the key and value need to passed into each iteration of the loop, and then each value needs to be requested by it’s key using the value[‘key’] method you see above.

If you know of a better way to do this then feel free to comment below as I’d be interested to see it.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.