Skip to content
This repository has been archived by the owner on Dec 31, 2024. It is now read-only.

Commit

Permalink
add redhat_instance service type provider
Browse files Browse the repository at this point in the history
This provider is a subclass of the core redhat service provider.  It is
of limited use and is intended for service scripts that support managing
multiple service instances via additional arguments to the init script.

This is needed to function with 389's sysvinit script.  It appears that
this type of kluedge will not be nessicary for the systemd service
files.
  • Loading branch information
Joshua Hoblitt committed Jan 31, 2014
1 parent b5f5e99 commit 5f97fe9
Show file tree
Hide file tree
Showing 2 changed files with 216 additions and 0 deletions.
82 changes: 82 additions & 0 deletions lib/puppet/provider/service/redhat_instance.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
Puppet::Type.type(:service).provide :redhat_instance, :parent => :redhat do
desc <<-EOS
Manage odd RedHat services (specifially, 389 Directory Server) that use a
single /etc/init.d script to manage multiple instances of a service.
Start/stop uses /sbin/service. Does not allow enable/disable as this would
globally control all instances of the service.
The service type's little used `control` parameter is abused to set the name of
the service script name while the namevar indidicates the service instance
name.
*Example:*
Given a init.d scritpt that behaves like:
/etc/init.d/<script> <command> <instance name>
Eg.:
$ sudo /etc/init.d/dirsrv status
dirsrv ldap1 is stopped
dirsrv ldap2 (pid 5604) is running...
$ sudo /etc/init.d/dirsrv status ldap1
dirsrv ldap1 is stopped
$ sudo /etc/init.d/dirsrv status ldap2
dirsrv ldap2 (pid 5604) is running...
One might desire a manifest as so:
notify { 'bogus': }
service { 'ldap1':
control => 'dirsrv',
ensure => 'stopped',
enable => true, # <= ignored
hasstatus => true,
hasrestart => true,
provider => redhat_instance,
subscribe => Notify['bogus'],
}
service { 'ldap2':
control => 'dirsrv',
ensure => 'running',
enable => true, # <= ignored
hasstatus => true,
hasrestart => true,
provider => redhat_instance,
subscribe => Notify['bogus'],
}
EOS

# disable this provider matching the service types's feature :enableable
undef_method :enable
undef_method :disable
undef_method :enabled?

# this provider should never be the default
# XXX unsure of the "proper" way to remove the defaultfor from the base class
# undef_method :defaultfor
# defaultfor :osfamily => :dne
# @defaults = {}
def self.default?
false
end

def statuscmd
((@resource.provider.get(:hasstatus) == true) || (@resource[:hasstatus] == :true)) && [command(:service), @resource[:control], "status", @resource[:name]]
end

def restartcmd
(@resource[:hasrestart] == :true) && [command(:service), @resource[:control], "restart", @resource[:name]]
end

def startcmd
[command(:service), @resource[:control], "start", @resource[:name]]
end

def stopcmd
[command(:service), @resource[:control], "stop", @resource[:name]]
end
end
134 changes: 134 additions & 0 deletions spec/unit/provider/service/redhat_instance_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#! /usr/bin/env ruby

# copied (and heavily hacked up) on 2014-01-31 from:
# https://raw2.github.com/puppetlabs/puppet/master/lib/puppet/provider/service/redhat.rb

#
# Unit testing for the RedHat service Provider
#
require 'spec_helper'

provider_class = Puppet::Type.type(:service).provider(:redhat_instance)

describe provider_class, :as_platform => :posix do

before :each do
@class = Puppet::Type.type(:service).provider(:redhat_instance)
@resource = stub 'resource'
@resource.stubs(:[]).returns(nil)
@resource.stubs(:[]).with(:name).returns "myinstance"
@resource.stubs(:[]).with(:control).returns "myservice"
@provider = provider_class.new
@resource.stubs(:provider).returns @provider
@provider.resource = @resource
@provider.stubs(:get).with(:hasstatus).returns false
FileTest.stubs(:file?).with('/sbin/service').returns true
FileTest.stubs(:executable?).with('/sbin/service').returns true
Facter.stubs(:value).with(:operatingsystem).returns('CentOS')
end

[ 'RedHat', 'Suse' ].each do |osfamily|
it "should not be the default provider on #{osfamily}" do
#Facter.expects(:value).with(:osfamily).returns(osfamily)
provider_class.default?.should be_false
end
end

# test self.instances
describe "when getting all service instances" do
before :each do
@services = ['one', 'two', 'three', 'four', 'kudzu', 'functions', 'halt', 'killall', 'single', 'linuxconf', 'boot', 'reboot']
@not_services = ['functions', 'halt', 'killall', 'single', 'linuxconf', 'reboot', 'boot']
Dir.stubs(:entries).returns @services
FileTest.stubs(:directory?).returns(true)
FileTest.stubs(:executable?).returns(true)
end
it "should return instances for all services" do
(@services-@not_services).each do |inst|
@class.expects(:new).with{|hash| hash[:name] == inst && hash[:path] == '/etc/init.d'}.returns("#{inst}_instance")
end
results = (@services-@not_services).collect {|x| "#{x}_instance"}
@class.instances.should == results
end
it "should call service status when initialized from provider" do
@resource.stubs(:[]).with(:status).returns nil
@provider.stubs(:get).with(:hasstatus).returns true
@provider.expects(:execute).with{|command, *args| command == ['/sbin/service', 'myservice', 'status', 'myinstance']}
@provider.send(:status)
end
end

it "should not have an enabled? method" do
@provider.should_not respond_to(:enabled?)
end

it "should not have an enable method" do
@provider.should_not respond_to(:enable)
end

it "should not have a disable method" do
@provider.should_not respond_to(:disable)
end

[:start, :stop, :status, :restart].each do |method|
it "should have a #{method} method" do
@provider.should respond_to(method)
end
describe "when running #{method}" do

it "should use any provided explicit command" do
@resource.stubs(:[]).with(method).returns "/user/specified/command"
@provider.expects(:execute).with { |command, *args| command == ["/user/specified/command"] }
@provider.send(method)
end

it "should execute the service script with #{method} when no explicit command is provided" do
@resource.stubs(:[]).with("has#{method}".intern).returns :true
@provider.expects(:execute).with { |command, *args| command == ['/sbin/service', 'myservice', method.to_s, 'myinstance']}
@provider.send(method)
end
end
end

describe "when checking status" do
describe "when hasstatus is :true" do
before :each do
@resource.stubs(:[]).with(:hasstatus).returns :true
end
it "should execute the service script with fail_on_failure false" do
@provider.expects(:texecute).with(:status, ['/sbin/service', 'myservice', 'status', 'myinstance'], false)
@provider.status
end
it "should consider the process running if the command returns 0" do
@provider.expects(:texecute).with(:status, ['/sbin/service', 'myservice', 'status', 'myinstance'], false)
$CHILD_STATUS.stubs(:exitstatus).returns(0)
@provider.status.should == :running
end
[-10,-1,1,10].each { |ec|
it "should consider the process stopped if the command returns something non-0" do
@provider.expects(:texecute).with(:status, ['/sbin/service', 'myservice', 'status', 'myinstance'], false)
$CHILD_STATUS.stubs(:exitstatus).returns(ec)
@provider.status.should == :stopped
end
}
end
describe "when hasstatus is not :true" do
it "should consider the service :running if it has a pid" do
@provider.expects(:getpid).returns "1234"
@provider.status.should == :running
end
it "should consider the service :stopped if it doesn't have a pid" do
@provider.expects(:getpid).returns nil
@provider.status.should == :stopped
end
end
end

describe "when restarting and hasrestart is not :true" do
it "should stop and restart the process with the server script" do
@provider.expects(:texecute).with(:stop, ['/sbin/service', 'myservice', 'stop', 'myinstance'], true)
@provider.expects(:texecute).with(:start, ['/sbin/service', 'myservice', 'start', 'myinstance'], true)
@provider.restart
end
end
end

0 comments on commit 5f97fe9

Please sign in to comment.