I'm currently a bit stuck in the "works-for-me-don't-need-any-tests"-state. 
But I hope I will find some time soon to write the tests ... ;-)

Anselm

On Monday 15 March 2010 22:37:38 James Turnbull wrote:
> 
> Anselm
> 
> Thanks for this.  Can you mail your code as a unified diff to the
> list for comment?  Did you make any progress on tests?
> 
> Thanks
> 
> James Turnbull
> 

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

diff --git a/lib/puppet/provider/service/bsd.rb b/lib/puppet/provider/service/bsd.rb
new file mode 100644
index 0000000..fed6559
--- /dev/null
+++ b/lib/puppet/provider/service/bsd.rb
@@ -0,0 +1,54 @@
+# Manage FreeBSD services.
+Puppet::Type.type(:service).provide :bsd, :parent => :init do
+    desc "FreeBSD's (and probably NetBSD?) form of ``init``-style service management.
+
+    Uses ``rc.conf.d`` for service enabling and disabling.
+
+"
+
+    confine :operatingsystem => [:freebsd, :netbsd, :openbsd]
+
+    @@rcconf_dir = '/etc/rc.conf.d'
+
+    def self.defpath
+        superclass.defpath
+    end
+
+    # remove service file from rc.conf.d to disable it
+    def disable
+        rcfile = File.join(@@rcconf_dir, @model[:name])
+        if File.exists?(rcfile)
+            File.delete(rcfile)
+        end
+    end
+
+    # if the service file exists in rc.conf.d then it's already enabled
+    def enabled?
+        rcfile = File.join(@@rcconf_dir, @model[:name])
+        if File.exists?(rcfile)
+            return :true
+        end
+
+        return :false
+    end
+
+    # enable service by creating a service file under rc.conf.d with the
+    # proper contents
+    def enable
+        if not File.exists?(@@rcconf_dir)
+            Dir.mkdir(@@rcconf_dir)
+        end
+        rcfile = File.join(@@rcconf_dir, @model[:name])
+        open(rcfile, 'w') { |f| f << "%s_enable=\"YES\"\n" % @model[:name] }
+    end
+
+    # Override stop/start commands to use one<cmd>'s and the avoid race condition
+    # where provider trys to stop/start the service before it is enabled
+    def startcmd
+        [self.initscript, :onestart]
+    end
+
+    def stopcmd
+        [self.initscript, :onestop]
+    end
+end
diff --git a/lib/puppet/provider/service/freebsd.rb b/lib/puppet/provider/service/freebsd.rb
index baf5e5a..27f3715 100644
--- a/lib/puppet/provider/service/freebsd.rb
+++ b/lib/puppet/provider/service/freebsd.rb
@@ -1,56 +1,139 @@
-# Manage FreeBSD services.
 Puppet::Type.type(:service).provide :freebsd, :parent => :init do
-    desc "FreeBSD's (and probably NetBSD?) form of ``init``-style service management.
 
-    Uses ``rc.conf.d`` for service enabling and disabling.
+  desc "Provider for FreeBSD. Makes use of rcvar argument of init scripts and parses/edits rc files."
 
-"
+  confine :operatingsystem => [:freebsd]
+  defaultfor :operatingsystem => [:freebsd]
 
-    confine :operatingsystem => [:freebsd, :netbsd, :openbsd]
+  @@rcconf = '/etc/rc.conf'
+  @@rcconf_local = '/etc/rc.conf.local'
+  @@rcconf_dir = '/etc/rc.conf.d'
 
-    defaultfor :operatingsystem => :freebsd
+  def self.defpath
+    superclass.defpath
+  end
 
-    @@rcconf_dir = '/etc/rc.conf.d'
+  # Executing an init script with the 'rcvar' argument returns
+  # the service name, rcvar name and whether it's enabled/disabled
+  def rcvar
+    rcvar = execute([self.initscript, :rcvar], :failonfail => true, :squelch => false)
+    rcvar = rcvar.split("\n")
+    return rcvar
+  end
 
-    def self.defpath
-        superclass.defpath
-    end
+  # Extract service name
+  def service_name
+    name = self.rcvar[0]
+    self.error("No service name found in rcvar") if name.nil?
+    name = name.gsub!(/# (.*)/, '\1')
+    self.error("Service name is empty") if name.nil?
+    self.debug("Service name is #{name}")
+    return name
+  end
 
-    # remove service file from rc.conf.d to disable it
-    def disable
-        rcfile = File.join(@@rcconf_dir, @model[:name])
-        if File.exists?(rcfile)
-            File.delete(rcfile)
-        end
-    end
+  # Extract rcvar name
+  def rcvar_name
+    name = self.rcvar[1]
+    self.error("No rcvar name found in rcvar") if name.nil?
+    name = name.gsub!(/(.*)_enable=(.*)/, '\1')
+    self.error("rcvar name is empty") if name.nil?
+    self.debug("rcvar name is #{name}")
+    return name
+  end
 
-    # if the service file exists in rc.conf.d then it's already enabled
-    def enabled?
-        rcfile = File.join(@@rcconf_dir, @model[:name])
-        if File.exists?(rcfile)
-            return :true
-        end
+  # Extract rcvar value
+  def rcvar_value
+    value = self.rcvar[1]
+    self.error("No rcvar value found in rcvar") if value.nil?
+    value = value.gsub!(/(.*)_enable=\"?(.*)\"?/, '\2')
+    self.error("rcvar value is empty") if value.nil?
+    self.debug("rcvar value is #{value}")
+    return value
+  end
 
-        return :false
+  # Edit rc files and set the service to yes/no
+  def rc_edit(yesno)
+    service = self.service_name
+    rcvar = self.rcvar_name
+    self.debug("Editing rc files: setting #{rcvar} to #{yesno} for #{service}")
+    if not self.rc_replace(service, rcvar, yesno)
+      self.rc_add(service, rcvar, yesno)
     end
+  end
 
-    # enable service by creating a service file under rc.conf.d with the
-    # proper contents
-    def enable
-        if not File.exists?(@@rcconf_dir)
-            Dir.mkdir(@@rcconf_dir)
+  # Try to find an existing setting in the rc files 
+  # and replace the value
+  def rc_replace(service, rcvar, yesno)
+    success = false
+    # Replace in all files, not just in the first found with a match
+    [@@rcconf, @@rcconf_local, @@rcconf_dir + "/#{service}"].each do |filename|
+      if File.exists?(filename)
+        s = File.read(filename)
+        if s.gsub!(/(#{rcvar}_enable)=\"?(YES|NO)\"?/, "\\1=\"#{yesno}\"")
+          File.open(filename, File::WRONLY) { |f| f << s }
+          self.debug("Replaced in #{filename}")
+          success = true
         end
-        rcfile = File.join(@@rcconf_dir, @model[:name])
-        open(rcfile, 'w') { |f| f << "%s_enable=\"YES\"\n" % @model[:name] }
+      end
     end
+    return success
+  end
 
-    # Override stop/start commands to use one<cmd>'s and the avoid race condition
-    # where provider trys to stop/start the service before it is enabled
-    def startcmd
-        [self.initscript, :onestart]
+  # Add a new setting to the rc files
+  def rc_add(service, rcvar, yesno)
+    append = "\n\# Added by Puppet\n#{rcvar}_enable=\"#{yesno}\""
+    # First, try the one-file-per-service style
+    if File.exists?(@@rcconf_dir)
+      File.open(@@rcconf_dir + "/#{service}", File::WRONLY | File::APPEND | File::CREAT, 0644) {
+        |f| f << append
+        self.debug("Appended to #{f.path}")
+      }
+    else
+      # Else, check the local rc file first, but don't create it
+      if File.exists?(@@rcconf_local)
+        File.open(@@rcconf_local, File::WRONLY | File::APPEND) {
+          |f| f << append
+          self.debug("Appended to #{f.path}")
+        }
+      else
+        # At last use the standard rc.conf file
+        File.open(@@rcconf, File::WRONLY | File::APPEND | File::CREAT, 0644) {
+          |f| f << append
+          self.debug("Appended to #{f.path}")
+        }
+      end
     end
+  end
 
-    def stopcmd
-        [self.initscript, :onestop]
+  def enabled?
+    if /YES$/ =~ self.rcvar_value then
+      self.debug("Is enabled")
+      return :true
     end
+    self.debug("Is disabled")
+    return :false
+  end
+
+  def enable
+    self.debug("Enabling")
+    self.rc_edit("YES")
+  end
+
+  def disable
+    self.debug("Disabling")
+    self.rc_edit("NO")
+  end
+
+  def startcmd
+    [self.initscript, :onestart]
+  end
+
+  def stopcmd
+    [self.initscript, :onestop]
+  end
+
+  def statuscmd
+    [self.initscript, :onestatus]
+  end
+
 end

Reply via email to