How to create services with the service resource?

Hi,
I naively assumed (and am not the only one:
http://lists.opscode.com/sympa/arc/chef/2012-05/msg00267.html) that
the service resource could be used to define, then run services:


service “atom-dataset-provider” do
start_command "/opt/atom-dataset-provider/current/provider.sh"
stop_command "/opt/atom-dataset-provider/current/kill_provider.sh"
action [:enable]
end

end
restart_command do
current_release = release_path
service “atom-dataset-provider” do
action [:restart]
end
end

But apparently it doesn’t. In that case:

  • what is the purpose of the “restart_command” etc parameters? How are
    they used, if not to write to a script in init.d/?
  • what’s the purpose of “supports” parameter - what does Chef do with it?
  • what’s the best way to create services? Foreman? A template as
    suggested in that thread?
  • any plans to make the service resource do this?
  • could the docs be made a bit more explicit? :slight_smile:

Thanks,
Steve

Hello,

You are correct in assuming that the service resource (when told to
use the Simple or Init Service Providers) can be used to define and
run services.

Please post the relevant debug output surrounding any problems you're
having with the service resource and provider.

Additionally, using bash scripts as your start/stop command is uh.. a
little suboptimal? Have you considered using a process supervision
system, e.g.; Runit, Upstart, Monit, s6, .. (...?)

To answer your other questions:

  • what is the purpose of the "restart_command" etc parameters? How are
    they used, if not to write to a script in init.d/?

If you specify a restart_command and the service supports :restart =>
true, then the restart_command will be issued when the :restart action
is run on the service.

  • what's the purpose of "supports" parameter - what does Chef do with it?

The supports parameter allows the user to supply hints to the provider
as to the state of the resources that Chef is managing, in this case:

:status (whether the service supports a status command)
:reload (supports reload?)
:restart (supports restart?)

I wrote this code years ago, so this is going off memory, essentially
the idea was:

If the service doesn't support status, inspect the process table (via
regex) to determine service status, alternately; when the service
supports status, issue the status command to determine service status.

restart and reload should be self-descriptive

I am not aware to any major modifications to this logic.

  • what's the best way to create services? Foreman? A template as
    suggested in that thread?

I'd suggest (as above) using a process supervision tool and/or
monitoring system (runit, monit, bluepill, daemontools, s6, ..?)

  • any plans to make the service resource do this?
  • could the docs be made a bit more explicit? :slight_smile:

Feel free to make edits (need an account) based on my comments here,
although I'd love to know what problems you were having or what
documentation in particular is lacking.

Cheers,

--AJ

On 16 August 2012 15:00, Steve Bennett stevage@gmail.com wrote:

Hi,
I naively assumed (and am not the only one:
chef - [chef] Re: Re: service resource not creating a file) that
the service resource could be used to define, then run services:

...
service "atom-dataset-provider" do
start_command "/opt/atom-dataset-provider/current/provider.sh"
stop_command "/opt/atom-dataset-provider/current/kill_provider.sh"
action [:enable]
end

end
restart_command do
current_release = release_path
service "atom-dataset-provider" do
action [:restart]
end
end

But apparently it doesn't. In that case:

Thanks,
Steve

On 16 August 2012 13:24, AJ Christensen aj@junglist.gen.nz wrote:

You are correct in assuming that the service resource (when told to
use the Simple or Init Service Providers)

Sorry, what do you mean "when told to..."? A comprehensive example in
the doco would be really helpful.

can be used to define and
run services.

Great!

Please post the relevant debug output surrounding any problems you're
having with the service resource and provider.

115.146.94.40 [2012-08-16T03:21:44+00:00] INFO: Processing
service[atom-dataset-provider] action enable
(/var/chef/cache/cookbooks/atom-dataset-provider/recipes/default.rb
line 94)
115.146.94.40 [2012-08-16T03:21:44+00:00] ERROR:
service[atom-dataset-provider]
(/var/chef/cache/cookbooks/atom-dataset-provider/recipes/default.rb
line 94) has had an error
115.146.94.40 [2012-08-16T03:21:44+00:00] ERROR:
service[atom-dataset-provider]
(/var/chef/cache/cookbooks/atom-dataset-provider/recipes/default.rb:94:in
`from_file') had an error:
115.146.94.40 service[atom-dataset-provider]
(/var/chef/cache/cookbooks/atom-dataset-provider/recipes/default.rb
line 94) had an error: Chef::Exceptions::Exec: /usr/sbin/update-rc.d
atom-dataset-provider defaults returned 1, expected 0

Additionally, using bash scripts as your start/stop command is uh.. a
little suboptimal? Have you considered using a process supervision
system, e.g.; Runit, Upstart, Monit, s6, .. (...?)

It's probably ok for my current dev/testing purposes - my learning
curve is steep enough already :slight_smile:

Feel free to make edits (need an account) based on my comments here,
although I'd love to know what problems you were having or what
documentation in particular is lacking.

Sure - like much of the Chef doco, it's just lacking explicitness, and
doesn't give any guidance on typical uses. Consider this description:


Service
Manage a service.

The reader has to read between the lines to work out what this
resource does and doesn't do. Here's a quick suggestion:

Service
A wrapper around the service subsystem (init.d, upstart etc as
appropriate), allowing you to start and stop existing system services,
or define new services.

And the Providers section assume that the reader knows (and cares)
what a Provider is, when they just came here to create a service. I
don't know enough about providers (see!) to really help, but an
improved text might look something like:

Providers
The Service resource uses a different subsystem Provider depending on
the platform. You can override this (for example, to use Upstart even
when it's not the default) as follows:...

I have edited some of the other doco already, but prefer to only make
changes when I'm confident what I'm talking about

Steve [former tech writer, perpetual critic...]

Cheers,

--AJ

On 16 August 2012 15:00, Steve Bennett stevage@gmail.com wrote:

Hi,
I naively assumed (and am not the only one:
chef - [chef] Re: Re: service resource not creating a file) that
the service resource could be used to define, then run services:

...
service "atom-dataset-provider" do
start_command "/opt/atom-dataset-provider/current/provider.sh"
stop_command "/opt/atom-dataset-provider/current/kill_provider.sh"
action [:enable]
end

end
restart_command do
current_release = release_path
service "atom-dataset-provider" do
action [:restart]
end
end

But apparently it doesn't. In that case:

Thanks,
Steve

On 16 August 2012 15:43, Steve Bennett stevage@gmail.com wrote:

On 16 August 2012 13:24, AJ Christensen aj@junglist.gen.nz wrote:

You are correct in assuming that the service resource (when told to
use the Simple or Init Service Providers)

Sorry, what do you mean "when told to..."? A comprehensive example in
the doco would be really helpful.

you can specify 'provider Chef::Provider::Service::Simple or ::Init'
in the resource declaration. I'm sure this is in the docs somewhere
(it's how you change the provider for any resource)

If you're using the Debian provider or whatever, that has additional
behaviour for enable/disable.

can be used to define and
run services.

Great!

Please post the relevant debug output surrounding any problems you're
having with the service resource and provider.

115.146.94.40 [2012-08-16T03:21:44+00:00] INFO: Processing
service[atom-dataset-provider] action enable
(/var/chef/cache/cookbooks/atom-dataset-provider/recipes/default.rb
line 94)
115.146.94.40 [2012-08-16T03:21:44+00:00] ERROR:
service[atom-dataset-provider]
(/var/chef/cache/cookbooks/atom-dataset-provider/recipes/default.rb
line 94) has had an error
115.146.94.40 [2012-08-16T03:21:44+00:00] ERROR:
service[atom-dataset-provider]
(/var/chef/cache/cookbooks/atom-dataset-provider/recipes/default.rb:94:in
`from_file') had an error:
115.146.94.40 service[atom-dataset-provider]
(/var/chef/cache/cookbooks/atom-dataset-provider/recipes/default.rb
line 94) had an error: Chef::Exceptions::Exec: /usr/sbin/update-rc.d
atom-dataset-provider defaults returned 1, expected 0

Looks like your init script isn't working correctly for action :enable
-- or... you haven't dropped an init script off? Perhaps?

You've only posted the INFO level output there. Re-run with -l debug.

What is the output of:

/usr/sbin/update-rc.d atom-dataset-provider defaults ?

--AJ

Additionally, using bash scripts as your start/stop command is uh.. a
little suboptimal? Have you considered using a process supervision
system, e.g.; Runit, Upstart, Monit, s6, .. (...?)

It's probably ok for my current dev/testing purposes - my learning
curve is steep enough already :slight_smile:

Feel free to make edits (need an account) based on my comments here,
although I'd love to know what problems you were having or what
documentation in particular is lacking.

Sure - like much of the Chef doco, it's just lacking explicitness, and
doesn't give any guidance on typical uses. Consider this description:


Service
Manage a service.

The reader has to read between the lines to work out what this
resource does and doesn't do. Here's a quick suggestion:

Service
A wrapper around the service subsystem (init.d, upstart etc as
appropriate), allowing you to start and stop existing system services,
or define new services.

And the Providers section assume that the reader knows (and cares)
what a Provider is, when they just came here to create a service. I
don't know enough about providers (see!) to really help, but an
improved text might look something like:

Providers
The Service resource uses a different subsystem Provider depending on
the platform. You can override this (for example, to use Upstart even
when it's not the default) as follows:...

I have edited some of the other doco already, but prefer to only make
changes when I'm confident what I'm talking about

Steve [former tech writer, perpetual critic...]

Cheers,

--AJ

On 16 August 2012 15:00, Steve Bennett stevage@gmail.com wrote:

Hi,
I naively assumed (and am not the only one:
chef - [chef] Re: Re: service resource not creating a file) that
the service resource could be used to define, then run services:

...
service "atom-dataset-provider" do
start_command "/opt/atom-dataset-provider/current/provider.sh"
stop_command "/opt/atom-dataset-provider/current/kill_provider.sh"
action [:enable]
end

end
restart_command do
current_release = release_path
service "atom-dataset-provider" do
action [:restart]
end
end

But apparently it doesn't. In that case:

Thanks,
Steve

On Thu, Aug 16, 2012 at 5:24 AM, AJ Christensen aj@junglist.gen.nz wrote:

Hello,

You are correct in assuming that the service resource (when told to
use the Simple or Init Service Providers) can be used to define and
run services.

Please post the relevant debug output surrounding any problems you're
having with the service resource and provider.

Additionally, using bash scripts as your start/stop command is uh.. a
little suboptimal? Have you considered using a process supervision
system, e.g.; Runit, Upstart, Monit, s6, .. (…?)

Well, if I understand Steve correctly, he's wondering why the service
resource doesn't take care of that too :slight_smile:

I'm not sure it would be a good idea to overload such an important
resource in this way, but I would love to see this functionality
added.
Right now many cookbooks have quite a bit of conditional logic (a
giant case..when) to do exactly this: create the necessary templates,
symlinks etc for Runit, Upstart and what have you.
Worse, most cookbooks don't even try to support all of them; they just
support one or two.
In the best case, this means you end up with a foreign system (e.g.
Runit on Ubuntu when Upstart would work perfectly well).
In the worst case, your platform is unsupported and you'll have to add
support yourself.

For most cookbooks, a simple resource that accepted the name of a
binary, arguments, and a few options (like whether the application
will demonize itself etc) would work great; some others may need to
override the templates.
Other than that, it would be reasonably easy to write, and it would
make life easier for cookbook writers while increasing support for the
different distros.

  • what's the purpose of "supports" parameter - what does Chef do with it?

The supports parameter allows the user to supply hints to the provider
as to the state of the resources that Chef is managing, in this case:

If the service doesn't support status, inspect the process table (via
regex) to determine service status, alternately; when the service
supports status, issue the status command to determine service status.

restart and reload should be self-descriptive

I am not aware to any major modifications to this logic.

That's still correct indeed.
It's pretty easy stuff, yet quite a few cookbooks don't get this
right. If you do a chef run in debug mode I bet you'll see a few.
That's one more argument to my thesis above.

Andrea

On Wed, Aug 15, 2012 at 11:00 PM, Steve Bennett stevage@gmail.com wrote:

But apparently it doesn't. In that case:

  • what is the purpose of the "restart_command" etc parameters? How are
    they used, if not to write to a script in init.d/?

It is important to understand that there is a one to many relationship
between resources and providers. Resources define something you want
to manage, and then providers take the action of managing that
resource on the system.

http://wiki.opscode.com/display/chef/Resources+and+Providers

There's a bit of presumption in wondering why something is not done in
init.d as that is part of a particular service management system,
albeit a historical one that is an ancestor of many newer
implementations.

Based on your platform and platform version, Chef makes default
guesses as to what provider you want for each resource based on what
it the default or most popular on that platform. For example, the
package resource on Debian uses apt and on Redhat it uses yum. You can
override these if you're using a different provider than the default
using the provider meta attribute. [1]

The init.d script is actually part of the init system. Other service
providers may have configuration files instead of scripts that you can
run by hand, such as upstart. The service resource has a number of
actions that are quite concrete in meaning, start, enable, etc, and we
try to avoid overloading those actions. If you imagine a
start_and_create_unless_exists action, then you've mixed two
resources; you're creating a file, and managing an service. Thus, Chef
operates at a level where if you need the file to be created, you use
a file resource or subclass such as remote_file or template. Then you
use the service resource to manage the service alone.

  • what's the purpose of "supports" parameter - what does Chef do with it?

This is most commonly needed with the traditional SysVinit system.
There's no requirement as to what actions this system can perform, but
start and stop are the defacto requirement. Some init scripts have a
restart or status function, but there's no concise way to tell if they
do so we depend on the user defining the service resource to be clear
about that functionality. If the script has a restart function, it's
likely the best way to restart the daemon. If it doesn't, we'll just
try to stop and start the daemon. If it has a status function, that's
likely to be much more accurate than chef having to run ps and trying
to find the daemon, which could result in something else being
inadvertently affected.

http://wiki.opscode.com/display/chef/Resources#Resources-Service

  • what's the best way to create services? Foreman? A template as
    suggested in that thread?

Usually a cookbook_file, unless you need to make any dynamic choices
in it like configuring where the configuration file is, in which case
a template [2].

  • any plans to make the service resource do this?

No, because that would overload the service resource by making it
manage both files and services.

Consider configuring an apt repository. You need to put a file in
there, run apt-get update, and then install the package. These are
three separate distinct actions. While we could modify the apt
provider to take a new repository as an attribute and do all this in a
single provider, it is a much cleaner (maintainable, understandable,
less magic) design to use another mechanism to do all three of these
together when needed. The example of this is the apt_repository LWRP.

https://github.com/opscode-cookbooks/apt/blob/master/providers/repository.rb

Parts of this concept of primitives are discussed in a recent video
Opscode put up talking about the history of Chef:

If you think about unix commands and the ability to chain small
commands that do one distinct thing well together to perform many more
complex tasks, you'll see the example we're following.

Another relevant and more humorous example is Zawinski's law: "Every
program attempts to expand until it can read mail. Those programs
which cannot so expand are replaced by ones which can."

  • could the docs be made a bit more explicit? :slight_smile:

Maybe. The devil is in the details of the actions; there is no create
action, just start, manage, etc. I suppose you could add a note along
the lines of "The service resource will not create a resource, it must
already exist to be managed." The trick is putting this note somewhere
everyone will see.

Bryan

[1] http://wiki.opscode.com/display/chef/Resources#Resources-CommonAttributes
[2] https://github.com/opscode-cookbooks/nagios/blob/master/templates/default/nagios-nrpe-server.erb#L33