Programmatically determine Service provider


#1

Hi,

I am looking to add some conditional logic to a recipe based on what Chef has determined to be the default provider for Chef::Resource::Service.

I’ve done a bit of introspection with pry and chef-shell but @provider always appears to be nil.

Is there a way to determine which provider Chef has selected as the default for the platform?

Rationale: I wanted to use some conditional logic (based on provider) that would determine which cookbook_file would be used. Example: If the platform were SysV, then deploy init scripts, but if the platform utilized systemd, then deploy unit files.

Cheers,


B.


#2

Hello @bwarsing

I think the provider will be nil unless it is passed in as part of the block at the time the resource is created, i.e.

service "tomcat" do
  provider Chef::Provider::Service::Init
  action :start
end

If the provider is not specified when the action of the resource is run the Provider resolver will perform a lookup and return the appropriate provider.

dir = directory 'c:\temp\'
dir_provider = dir.provider_for_action(:create) #=> Chef::Provider::Directory

However, I do not recommend that you write code like this as it requires internal / low level knowledge of the code behind the DSL which could be subject to change. The consumers of the Chef DSL ought to stay at the higher level, the internal and provider code works well.

What is your use case?


#3

Chris,

Thanks for the reply… I wanted to define a Chef service and at runtime, conditionally deploy either the systemd unit files OR the SysV init scripts appropriate to that service.

The thought being that if I could pre-determine what Chef had devised as the default provider for the platform, I could make an intelligent decision about which file to deploy (systemd unit file OR init script).

I have devised a workaround in the form a helper method:

    def systemd_running?
      Mixlib::ShellOut.new('/sbin/pidof systemd').run_command.exitstatus == 0
    end

Just wondering if there’s a better way…

Cheers,


B.


#4

You can use node['init_package'] to get the init service provider.

Here’s an example (you’d have another case for sysvinit, of course):

  case node['init_package']
  when 'systemd'
    template "/etc/systemd/system/#{service_name}.service" do
      cookbook 'consulite'
      source 'init/systemd.erb'
    end
    service service_name do
      action [:enable, :start]
    end
  end

#5

Ameir,

That’s precisely what I was aiming at! Thanks for the example code.

Cheers,


B.