Chef

Table Of Contents

ruby_block

A resource is a key part of a recipe that defines the actions that can be taken against a piece of the system. These actions are identified during each chef-client run as the resource collection is compiled. Once identified, each resource (in turn) is mapped to a provider, which then configures each piece of the system.

The ruby_block resource is used to execute Ruby code during a chef-client run. Ruby code in the ruby_block resource is evaluated with other resources during convergence, whereas Ruby code outside of a ruby_block resource is evaluated before other resources, as the recipe is compiled.

Syntax

The syntax for using the ruby_block resource in a recipe is as follows:

ruby_block "name" do
  block do
    # some Ruby code
  end
  action :action # see actions section below
end

where

  • ruby_block tells the chef-client to use the Chef::Provider::RubyBlock provider during the chef-client run
  • name is the name of the resource block; when the block_name attribute is not specified as part of a recipe, name is also the name of the Ruby block
  • block is the attribute that is used to define the Ruby block
  • :action is the step that the resource will ask the provider to take during the chef-client run

Actions

This resource has the following actions:

Action Description
:create Default. Use to create a Ruby block.

Attributes

This resource has the following attributes:

Attribute Description
block A block of Ruby code.
block_name The name of the Ruby block. Default value: the name of the resource block (see Syntax section above).
provider Optional. Use to specify a provider by using its long name. For example: provider Chef::Provider::Long::Name. See the Providers section below for the list of providers available to this resource.

Providers

The following providers are available. Use the short name to call the provider from a recipe:

Long name Short name Notes
Chef::Provider::RubyBlock ruby_block The default provider for all platforms.

Examples

The following examples demonstrate various approaches for using resources in recipes. If you want to see examples of how Chef uses resources in recipes, take a closer look at the cookbooks that Chef authors and maintains: https://github.com/opscode-cookbooks.

Re-read configuration data

ruby_block "reload_client_config" do
  block do
    Chef::Config.from_file("/etc/chef/client.rb")
  end
  action :create
end

Install repositories from a file, trigger a command, and force the internal cache to reload

The following example shows how to install new yum repositories from a file, where the installation of the repository triggers a creation of the yum cache that forces the internal cache for the chef-client to reload:

execute "create-yum-cache" do
 command "yum -q makecache"
 action :nothing
end

ruby_block "reload-internal-yum-cache" do
  block do
    Chef::Provider::Package::Yum::YumCache.instance.reload
  end
  action :nothing
end

cookbook_file "/etc/yum.repos.d/custom.repo" do
  source "custom"
  mode 00644
  notifies :run, "execute[create-yum-cache]", :immediately
  notifies :create, "ruby_block[reload-internal-yum-cache]", :immediately
end

Use an if statement with the platform recipe DSL method

The following example shows how an if statement can be used with the platform? method in the Recipe DSL to run code specific to Microsoft Windows. The code is defined using the ruby_block resource:

#  the following code sample comes from the ``client`` recipe in the following cookbook: https://github.com/opscode-cookbooks/mysql

if platform?("windows")
  ruby_block "copy libmysql.dll into ruby path" do
    block do
      require 'fileutils'
      FileUtils.cp "#{node['mysql']['client']['lib_dir']}\\libmysql.dll",
        node['mysql']['client']['ruby_dir']
    end
    not_if { File.exist?("#{node['mysql']['client']['ruby_dir']}\\libmysql.dll") }
  end
end

Stash a file in a data bag

The following example shows how to use the ruby_block resource to stash a BitTorrent file in a data bag so that it can be distributed to nodes in the organization.

#  the following code sample comes from the ``seed`` recipe in the following cookbook: https://github.com/mattray/bittorrent-cookbook

ruby_block "share the torrent file" do
  block do
    f = File.open(node['bittorrent']['torrent'],'rb')
    #read the .torrent file and base64 encode it
    enc = Base64.encode64(f.read)
    data = {
      'id'=>bittorrent_item_id(node['bittorrent']['file']),
      'seed'=>node.ipaddress,
      'torrent'=>enc
    }
    item = Chef::DataBagItem.new
    item.data_bag('bittorrent')
    item.raw_data = data
    item.save
  end
  action :nothing
  subscribes :create, "bittorrent_torrent[#{node['bittorrent']['torrent']}]"
end

Update the /etc/hosts file

The following example shows how the ruby_block resource can be used to update the /etc/hosts file:

#  the following code sample comes from the ``ec2`` recipe in the following cookbook: https://github.com/opscode-cookbooks/dynect

ruby_block "edit etc hosts" do
  block do
    rc = Chef::Util::FileEdit.new("/etc/hosts")
    rc.search_file_replace_line(/^127\.0\.0\.1 localhost$/,
       "127.0.0.1 #{new_fqdn} #{new_hostname} localhost")
    rc.write_file
  end
end

Set environment variables

The following example shows how to use variables within a Ruby block to set environment variables using rbenv.

node.set[:rbenv][:root] = rbenv_root
node.set[:ruby_build][:bin_path] = rbenv_binary_path

ruby_block "initialize" do
  block do
    ENV['RBENV_ROOT'] = node[:rbenv][:root]
    ENV['PATH'] = "#{node[:rbenv][:root]}/bin:#{node[:ruby_build][:bin_path]}:#{ENV['PATH']}"
  end
end

Set JAVA_HOME

The following example shows how to use a variable within a Ruby block to set the java_home environment variable:

ruby_block "set-env-java-home" do
  block do
    ENV["JAVA_HOME"] = java_home
  end
end

Reload the configuration

The following example shows how to reload the configuration of a chef-client using the remote_file resource to:

  • using an if statement to check whether the plugins on a node are the latest versions
  • identify the location from which Ohai plugins are stored
  • using the notifies attribute and a ruby_block resource to trigger an update (if required) and to then reload the client.rb file.
directory node[:ohai][:plugin_path] do
  owner "chef"
  recursive true
end

ruby_block "reload_config" do
  block do
    Chef::Config.from_file("/etc/chef/client.rb")
  end
  action :nothing
end

if node[:ohai].key?(:plugins)
  node[:ohai][:plugins].each do |plugin|
    remote_file node[:ohai][:plugin_path] +"/#{plugin}" do
      source plugin
      owner "chef"
      notifies :create, resources(:ruby_block => "reload_config")
    end
  end
end