ruby_block resource
This page is generated from the Chef source code.To suggest a change, edit the ruby_block.rb file and submit a pull request to the Chef repository.
Use the ruby_block resource to execute Ruby code during a Chef
Infra 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
A ruby_block resource block executes a block of arbitrary Ruby code. For example, to reload the client.rb file during a Chef Infra Client run:
ruby_block 'reload_client_config' do
block do
Chef::Config.from_file("/etc/chef/client.rb")
end
action :run
end
The full syntax for all of the properties that are available to the ruby_block resource is:
ruby_block 'name' do
block Block
block_name String # defaults to 'name' if not specified
action Symbol # defaults to :run if not specified
end
where:
ruby_block
is the resource.name
is the name given to the resource block.block
is the block of Ruby code to be executed.action
identifies which steps Chef Infra Client will take to bring the node into the desired state.block
andblock_name
are properties of this resource, with the Ruby type shown. See “Properties” section below for more information about all of the properties that may be used with this resource.
Actions
The ruby_block resource has the following actions:
:create
- The same as
:run
. :nothing
- This resource block does not act unless notified by another resource to take action. Once notified, this resource block either runs immediately or is queued up to run at the end of a Chef Infra Client run.
:run
- Default. Run a Ruby block.
Properties
The ruby_block resource has the following properties:
block
- Ruby Type: Block
A block of Ruby code.
block_name
- Ruby Type: String | Default Value:
The resource block's name
The name of the Ruby block. Default value: the
name
of the resource block. See “Syntax” section above for more information.
ignore_failure
- Ruby Type: true, false | Default Value:
false
Continue running a recipe if a resource fails for any reason.
notifies
- Ruby Type: Symbol, Chef::Resource\[String\]
A resource may notify another resource to take action when its state changes. Specify a
'resource[name]'
, the:action
that resource should take, and then the:timer
for that action. A resource may notify more than one resource; use anotifies
statement for each resource to be notified.A timer specifies the point during a Chef Infra Client run at which a notification is run. The following timers are available:
:before
Specifies that the action on a notified resource should be run before processing the resource block in which the notification is located.
:delayed
Default. Specifies that a notification should be queued up, and then executed at the end of a Chef Infra Client run.
:immediate
,:immediately
Specifies that a notification should be run immediately, per resource notified.
The syntax for
notifies
is:notifies :action, 'resource[name]', :timer
retries
- Ruby Type: Integer | Default Value:
0
The number of attempts to catch exceptions and retry the resource.
retry_delay
- Ruby Type: Integer | Default Value:
2
The retry delay (in seconds).
subscribes
- Ruby Type: Symbol, Chef::Resource\[String\]
A resource may listen to another resource, and then take action if the state of the resource being listened to changes. Specify a
'resource[name]'
, the:action
to be taken, and then the:timer
for that action.Note that
subscribes
does not apply the specified action to the resource that it listens to - for example:file '/etc/nginx/ssl/example.crt' do mode '0600' owner 'root' end service 'nginx' do subscribes :reload, 'file[/etc/nginx/ssl/example.crt]', :immediately end
In this case the
subscribes
property reloads thenginx
service whenever its certificate file, located under/etc/nginx/ssl/example.crt
, is updated.subscribes
does not make any changes to the certificate file itself, it merely listens for a change to the file, and executes the:reload
action for its resource (in this examplenginx
) when a change is detected.A timer specifies the point during a Chef Infra Client run at which a notification is run. The following timers are available:
:before
Specifies that the action on a notified resource should be run before processing the resource block in which the notification is located.
:delayed
Default. Specifies that a notification should be queued up, and then executed at the end of a Chef Infra Client run.
:immediate
,:immediately
Specifies that a notification should be run immediately, per resource notified.
The syntax for
subscribes
is:subscribes :action, 'resource[name]', :timer
Examples
The following examples demonstrate various approaches for using the ruby_block resource in recipes:
Re-read configuration data
ruby_block 'reload_client_config' do
block do
Chef::Config.from_file('/etc/chef/client.rb')
end
action :run
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 Chef Infra 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 '0755'
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/chef-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']}]", :immediately
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/chef-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.override[:rbenv][:root] = rbenv_root
node.override[: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
Run specific blocks of Ruby code on specific platforms
The following example shows how the platform?
method and an if
statement can be used in a recipe along with the ruby_block
resource
to run certain blocks of Ruby code on certain platforms:
if platform_family?('debian', 'rhel', 'fedora', 'amazon')
ruby_block 'update-java-alternatives' do
block do
if platform?('ubuntu', 'debian') and version == 6
run_context = Chef::RunContext.new(node, {})
r = Chef::Resource::Execute.new('update-java-alternatives', run_context)
r.command 'update-java-alternatives -s java-6-openjdk'
r.returns [0,2]
r.run_action(:create)
else
require 'fileutils'
arch = node['kernel']['machine'] =~ /x86_64/ ? 'x86_64' : 'i386'
Chef::Log.debug("glob is #{java_home_parent}/java*#{version}*openjdk*")
jdk_home = Dir.glob("#{java_home_parent}/java*#{version}*openjdk{,[-\.]#{arch}}")[0]
Chef::Log.debug("jdk_home is #{jdk_home}")
if File.exist? java_home
FileUtils.rm_f java_home
end
FileUtils.ln_sf jdk_home, java_home
cmd = Chef::ShellOut.new(
%Q[ update-alternatives --install /usr/bin/java java #{java_home}/bin/java 1;
update-alternatives --set java #{java_home}/bin/java ]
).run_command
unless cmd.exitstatus == 0 or cmd.exitstatus == 2
Chef::Application.fatal!('Failed to update-alternatives for openjdk!')
end
end
end
action :nothing
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
property 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 :run, 'ruby_block[reload_config]', :immediately
end
end
end