Skip to content

Instantly share code, notes, and snippets.

@zachfi
Last active January 4, 2016 00:39
Show Gist options
  • Save zachfi/8543332 to your computer and use it in GitHub Desktop.
Save zachfi/8543332 to your computer and use it in GitHub Desktop.
OpenBSD service provider for Puppet
Puppet::Type.type(:service).provide :openbsd, :parent => :init do
desc "Provider for OpenBSD's rc.d daemon control scripts"
confine :operatingsystem => :openbsd
defaultfor :operatingsystem => :openbsd
has_feature :flaggable
def self.rcconf() '/etc/rc.conf' end
def self.rcconf_local() '/etc/rc.conf.local' end
def self.defpath
["/etc/rc.d"]
end
# Fetch the state of all service resources
def self.prefetch(resources)
services = instances
resources.keys.each do |name|
if provider = services.find { |svc| svc.name == name }
resources[name].provider = provider
end
end
end
# Return the list of rc scripts
def self.rclist
unless @rclist
Puppet.debug "Building list of rc scripts"
@rclist = []
defpath.each do |p|
Dir.glob(p + '/*').each do |item|
@rclist << item if File.executable?(item)
end
end
end
@rclist
end
# Return a hash where the keys are the rc script names with flags as values
def self.rcflags
unless @flag_hash
Puppet.debug "Retrieving flags for all discovered services"
@flag_hash = {}
Puppet.debug "Reading the contents of the rc conf files"
if File.exists?(rcconf_local())
rcconf_local_contents = File.open(rcconf_local()).read
else
rcconf_local_contents = []
end
if File.exists?(rcconf())
rcconf_contents = File.open(rcconf()).read
else
rcconf_contents = []
end
rclist().each do |rcitem|
rcname = rcitem.split('/').last
# Loop over each rc.conf file
[rcconf_local_contents, rcconf_contents].flatten.each do |rccontents|
if flagline = rccontents.each_line.find {|l| l =~ /#{rcname}_flags/ }
# Parse the line and figure out what the flags are
flag = flagline.split('=').last.split(/#/).first.strip.gsub(/"/, '')
@flag_hash[rcname.to_sym] ||= flag
end
end
@flag_hash[rcname.to_sym] ||= nil
end
end
@flag_hash
end
# Read the rc.conf* files and determine the value of the flags
def self.get_flags(rcname)
rcflags()
@flag_hash[rcname.to_sym]
end
def self.instances
instances = []
defpath.each do |path|
unless FileTest.directory?(path)
Puppet.debug "Service path #{path} does not exist"
next
end
rclist().each do |d|
instances << new(
:name => File.basename(d),
:path => path,
:flags => get_flags(File.basename(d)),
:hasstatus => true
)
end
end
instances
end
def startcmd
[self.initscript, "-f", :start]
end
def restartcmd
(@resource[:hasrestart] == :true) && [self.initscript, "-f", :restart]
end
def statuscmd
[self.initscript, :check]
end
def rcvar_name
self.name + '_flags'
end
def rcvar_value
[rcconf,rcconf_local].each do |file|
#
end
end
def set_flags(flags)
if flags.nil?
append = resource[:name] + '_flags=""'
else
append = resource[:name] + '_flags="' + flags + '"'
end
# Detect the existense of the tile
if File.exists?(self.class.rcconf_local())
s = File.read(self.class.rcconf_local())
else
s = ''
end
# We should detect the presence of the line and proceed accordingly
if s.lines.find {|l| /#{resource[:name]}_flags/ =~ l }.nil?
# line was not found
Puppet.debug "Appending service flags #{append}"
File.open(self.class.rcconf_local, File::WRONLY | File::APPEND | File::CREAT, 0644) { |f|
f << append + "\n"
}
else
if s.gsub!(/^#{resource[:name]}_flags="(.*)?"(.*)?$/, append)
Puppet.debug "Replacing service flags with #{append}"
File.open(self.class.rcconf_local(), 'w') { |f| f << s }
end
end
end
def remove_flags_line
# Detect the existense of the file
if File.exists?(self.class.rcconf_local())
s = File.read(self.class.rcconf_local())
if s.lines.find {|l| /#{resource[:name]}_flags/ =~ l }
Puppet.debug "Removing service flags for #{self.name}"
File.open(self.class.rcconf_local, 'w') { |f|
s.split('\n').each {|line|
f << line unless line =~ /#{resource[:name]}_flags/
}
}
end
else
Puppet.debug "The rc.conf.local file was not found"
end
end
# Determine if the rc script is included in base, or if it exists as a result
# of a package installation.
def in_base?
system("/usr/sbin/pkg_info -qE /etc/rc.d/#{self.name}> /dev/null")
$?.exitstatus == 1
end
def enabled?
if (@property_hash[:flags].nil? or @property_hash[:flags] == 'NO')
:false
#elsif @property_hash[:flags] != resource[:flags]
# # We set false here only so that flush is called to udpate the flags
# :false
else
:true
end
end
def enable
self.debug("Enabling #{self.name}")
end
# We should also check for default state
def disable
self.debug("Disabling #{self.name}")
end
def flags
@property_hash[:flags]
end
def flags=(value)
@property_hash[:flags] = value
end
def flush
debug "Flusing resource for #{self.name}"
if resource[:enable] == :true
set_flags(resource[:flags])
elsif resource[:enable] == :false
if not in_base?
remove_flags_line()
else
set_flags("NO")
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment