Chef

Table Of Contents

service

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 service resource is used to manage a service.

Syntax

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

service "name" do
  attribute "value" # see attributes section below
  ...
  action :action # see actions section below
end

where

  • service tells the chef-client to use one of the following providers during the chef-client run: Chef::Provider::Service::Init, Chef::Provider::Service::Init::Debian, Chef::Provider::Service::Upstart, Chef::Provider::Service::Init::Freebsd, Chef::Provider::Service::Init::Gentoo, Chef::Provider::Service::Init::Redhat, Chef::Provider::Service::Solaris, Chef::Provider::Service::Windows, or Chef::Provider::Service::Macosx. The chef-client will detect the platform at the start of the run based on data collected by Ohai. After the platform is identified, the chef-client will determine the correct provider
  • name is the name of the resource block; when the service_name attribute is not specified as part of a recipe, name is also the name of the service
  • attribute is zero (or more) of the attributes that are available for this resource
  • :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
:enable Use to enable a service at boot.
:disable Use to disable a service.
:nothing Default. Use to do nothing with a service.
:start Use to start a service (and keep it running until stopped or disabled).
:stop Use to stop a service.
:restart Use to restart a service.
:reload Use to reload the configuration for this service.

Attributes

This resource has the following attributes:

Attribute Description
init_command The path to the init script associated with the service. This is typically /etc/init.d/SERVICE_NAME. The init_command attribute can be used to prevent the need to specify overrides for the start_command, stop_command, and restart_command attributes. Default value: nil.
pattern The pattern to look for in the process table. Default value: service_name.
priority Debian platform only. The relative priority of the program for start and shutdown ordering. May be an integer or a hash. An integer is used to define the start run levels; stop run levels are then 100-integer. A hash is used to define values for specific run levels. For example, { 2 => [:start, 20], 3 => [:stop, 55] } will set a priority of twenty for run level two and a priority of fifty-five for run level three.
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.
reload_command The command used to tell a service to reload its configuration.
restart_command The command used to restart a service.
service_name The name of the service. Default value: the name of the resource block (see Syntax section above).
start_command The command used to start a service.
status_command The command used to check the run status for a service.
stop_command The command used to stop a service.
supports A list of attributes that controls how the chef-client will attempt to manage a service: :restart, :reload, :status. For :restart, the init script or other service provider can use a restart command; if :restart is not specified, the chef-client will attempt to stop and then start a service. For :reload, the init script or other service provider can use a reload command. For :status, the init script or other service provider can use a status command to determine if the service is running; if :status is not specified, the chef-client will attempt to match the service_name against the process table as a regular expression, unless a pattern is specified as a parameter attribute. Default value: { :restart => false, :reload => false, :status => false } for all platforms (except for the Red Hat platform family, which defaults to { :restart => false, :reload => false, :status => true }.)

Providers

The service resource does not have service-specific short names. This is because the chef-client identifies the platform at the start of every chef-client run based on data collected by Ohai. The chef-client looks up the platform in the provider_mapping.rb file, and then determines the correct provider for that platform. In certain situations, such as when more than one init system is available on a node, a specific provider may need to be identified by using the provider attribute and the long name for that provider.

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

Long name Short name Notes
Chef::Provider::Service::Init service When this short name is used, the chef-client will determine the correct provider during the chef-client run.
Chef::Provider::Service::Init::Debian service The provider that is used with the Debian and Ubuntu platforms.
Chef::Provider::Service::Upstart service The provider that is used when Upstart is available on the platform.
Chef::Provider::Service::Init::Freebsd service The provider that is used with the FreeBSD platform.
Chef::Provider::Service::Init::Gentoo service The provider that is used with the Gentoo platform.
Chef::Provider::Service::Init::Redhat service The provider that is used with the Red Hat and CentOS platforms.
Chef::Provider::Service::Solaris service The provider that is used with the Solaris platform.
Chef::Provider::Service::Windows service The provider that is used with the Microsoft Windows platform.
Chef::Provider::Service::Macosx service The provider that is used with the Mac OS X platform.

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.

Start a service

service "example_service" do
  action :start
end

Start a service, enable it

service "example_service" do
  supports :status => true, :restart => true, :reload => true
  action [ :enable, :start ]
end

Use a pattern

service "samba" do
  pattern "smbd"
  action [:enable, :start]
end

Use the :nothing common action

service "memcached" do
  action :nothing
  supports :status => true, :start => true, :stop => true, :restart => true
end

Use the supports common attribute

service "apache" do
  supports :restart => true, :reload => true
  action :enable
end

Use the supports and providers common attributes

service "some_service" do
  provider Chef::Provider::Service::Upstart
  supports :status => true, :restart => true, :reload => true
  action [ :enable, :start ]
end

Manage a service, depending on the node platform

service "example_service" do
  case node["platform"]
  when "centos","redhat","fedora"
    service_name "redhat_name"
  else
    service_name "other_name"
  end
  supports :restart => true
  action [ :enable, :start ]
end

Change a service provider, depending on the node platform

service "example_service" do
  case node["platform"]
  when "ubuntu"
    if node["platform_version"].to_f >= 9.10
      provider Chef::Provider::Service::Upstart
    end
  end
  action [:enable, :start]
end

Reload a service using a template

To reload a service based on a template, use the template and service resources together in the same recipe, similar to the following:

template "/tmp/somefile" do
  mode "0644"
  source "somefile.erb"
end

service "apache" do
  supports :restart => true, :reload => true
  action :enable
  subscribes :reload, "template[/tmp/somefile]", :immediately
end

where the subscribes notification is used to reload the service using the template specified by the template resource.

Enable a service after a restart or reload

service "apache" do
  supports :restart => true, :reload => true
  action :enable
end

Set an IP address using variables and a template

The following example shows how the template resource can be used in a recipe to combine settings stored in an attributes file, variables within a recipe, and a template to set the IP addresses that are used by the Nginx service. The attributes file contains the following:

default['nginx']['dir'] = "/etc/nginx"

The recipe then does the following to:

  • Declare two variables at the beginning of the recipe, one for the remote IP address and the other for the authorized IP address
  • Use the service resource to restart and reload the Nginx service
  • Load a template named “authorized_ip.erb” from the /templates directory that is used to set the IP address values based on the variables specified in the recipe
node.default['nginx']['remote_ip_var'] = "remote_addr"
node.default['nginx']['authorized_ips'] = ["127.0.0.1/32"]

service "nginx" do
  supports :status => true, :restart => true, :reload => true
end

template "authorized_ip" do
  path "#{node['nginx']['dir']}/authorized_ip"
  source "modules/authorized_ip.erb"
  owner "root"
  group "root"
  mode 00644
  variables(
    :remote_ip_var => node['nginx']['remote_ip_var'],
    :authorized_ips => node['nginx']['authorized_ips']
  )

  notifies :reload, resources(:service => "nginx")
end

where the variables attribute tells the template to use the variables set at the beginning of the recipe and the source attribute is used to call a template file located in the cookbook’s /templates directory. The template file looks something like:

geo $<%= @remote_ip_var %> $authorized_ip {
  default no;
  <% @authorized_ips.each do |ip| %>
  <%= "#{ip} yes;" %>
  <% end %>
}

Use a cron timer to manage a service

The following example shows how to install the crond application using two resources and a variable:

#  the following code sample comes from the ``cron`` cookbook: https://github.com/opscode-cookbooks/cron

cron_package = case node['platform']
  when "redhat", "centos", "scientific", "fedora", "amazon"
    node['platform_version'].to_f >= 6.0 ? "cronie" : "vixie-cron"
  else
    "cron"
  end

package cron_package do
  action :install
end

service "crond" do
  case node['platform']
  when "redhat", "centos", "scientific", "fedora", "amazon"
    service_name "crond"
  when "debian", "ubuntu", "suse"
    service_name "cron"
  end
  action [:start, :enable]
end

where

  • cron_package is a variable that is used to identify which platforms apply to which install packages
  • the package resource uses the cron_package variable to determine how to install the crond application on various nodes (with various platforms)
  • the service resource enables the crond application on nodes that have Red Hat, CentOS, Red Hat Enterprise Linux, Fedora, or Amazon Web Services, and the cron service on nodes that run Debian, Ubuntu, or openSUSE.

Restart a service, and then notify a different service

The following example shows how start a service named “example_service” and immediately notify the Nginx service to restart.

service "example_service" do
  action :start
  provider Chef::Provider::Service::Init
  notifies :restart, "service[nginx]", :immediately
end

where by using the default provider for the service, the recipe is telling the chef-client to determine the specific provider to be used during the chef-client run based on the platform of the node on which the recipe will run.

Stop a service, do stuff, and then restart it

The following example shows how to use the execute, service, and mount resources together to ensure that a node running on Amazon EC2 is running MySQL. This example does the following:

  • Checks to see if the Amazon EC2 node has MySQL
  • If the node has MySQL, stops MySQL
  • Installs MySQL
  • Mounts the node
  • Restarts MySQL
#  the following code sample comes from the ``server_ec2`` recipe in the following cookbook: https://github.com/opscode-cookbooks/mysql

if (node.attribute?('ec2') && ! FileTest.directory?(node['mysql']['ec2_path']))

  service "mysql" do
    action :stop
  end

  execute "install-mysql" do
    command "mv #{node['mysql']['data_dir']} #{node['mysql']['ec2_path']}"
    not_if do FileTest.directory?(node['mysql']['ec2_path']) end
  end

  [node['mysql']['ec2_path'], node['mysql']['data_dir']].each do |dir|
    directory dir do
      owner "mysql"
      group "mysql"
    end
  end

  mount node['mysql']['data_dir'] do
    device node['mysql']['ec2_path']
    fstype "none"
    options "bind,rw"
    action [:mount, :enable]
  end

  service "mysql" do
    action :start
  end

end

where

  • the two service resources are used to stop, and then restart the MySQL service
  • the execute resource is used to install MySQL
  • the mount resource is used to mount the node and enable MySQL

Control a service using the execute resource

Warning

This is an example of something that should NOT be done. Use the service resource to control a service, not the execute resource.

Do something like this:

service "tomcat" do
  action :start
end

and NOT something like this:

execute "start-tomcat" do
  command "/etc/init.d/tomcat6 start"
  action :run
end

There is no reason to use the execute resource to control a service because the service resource exposes the start_command attribute directly, which gives a recipe full control over the command issued in a much cleaner, more direct manner.