[Puppet] Using ‘macports’ as a provider instead of ‘darwinport’

I ran into an issue recently testing puppet on my Mac. Trying to “ensure” the package (ipcalc) was installed on my test system resulted in the error:

`--> sudo puppet agent --no-daemonize --test
info: Retrieving plugin
err: /File[/var/lib/puppet/lib]: Could not evaluate: Could not retrieve information from source(s) puppet://<server-name>/plugins
info: Caching catalog for <fqdn>
info: Applying configuration version '1321291410'
err: /Stage[main]//Package[ipcalc]/ensure: change from absent to present failed: Execution of '/opt/local/bin/port upgrade ipcalc' returned 1: Error: ipcalc is not installed
To report a bug, see <http://guide.macports.org/#project.tickets>

notice: Finished catalog run in 61.49 seconds
Changes:
            Total: 1
Events:
          Failure: 1
            Total: 1
Resources:
          Changed: 1
           Failed: 1
      Out of sync: 1
            Total: 8
Time:
   Config retrieval: 0.38
       Filebucket: 0.00
          Package: 30.99
         Schedule: 0.00
60.51s user 2.53s system 99% cpu 1:03.12s total

The site manifest, ‘site.pp’, had the following definitions:

Package {
  provider => $operatingsystem ? {
    darwin => darwinport,
  }
}

package {'ipcalc':
  ensure => installed,
}

stating that the packaging system to use on a Mac (darwin) is the ‘darwinport’ port system. I use ‘Mac Ports’, but the only provider I could find close enough was ‘darwinport’ from the output of “puppet describe -s package“:

> puppet describe -s package
...edited...
Providers
---------
    aix, appdmg, apple, apt, aptitude, aptrpm, blastwave, darwinport, dpkg,
    fink, freebsd, gem, hpux, macports, nim, openbsd, pkg, pkgdmg, portage,
    ports, portupgrade, rpm, rug, sun, sunfreeware, up2date, urpmi, yum,
    zypper

Looking at the initial error,

‘/opt/local/bin/port upgrade ipcalc’ returned 1: Error: ipcalc is not installed…“,

lead me to the realization that on the command-line “port installed” and not “port upgrade” should have been executed by puppet. But, with ‘Mac Ports’ as the package management system using “port upgrade ” to install a non-existent port will indeed fail. Apparently this was not the case with the original darwinport packaging system. This was confirmed by inspecting the puppet provider source file: “/opt/local/lib/ruby/site_ruby/1.8/puppet/provider/package/darwinport.rb” on the local system. It can be found with the command:

--> port contents puppet | grep darwin                                  
 /opt/local/lib/ruby/site_ruby/1.8/puppet/provider/package/darwinport.rb

Looking at the file confirmed the “install” function definition was relying on “port upgrade” to ensure that even non-existent packages should be installed:

 
45 
46   def install
47     should = @resource.should(:ensure)
48 
49     # Seems like you can always say 'upgrade'
50     output = port "upgrade", @resource[:name]
51     if output =~ /^Error: No port/
52       raise Puppet::ExecutionFailure, "Could not find package #{@resource[:name]}"
53     end
54   end
55 

I changed the code on line number 50 to instead read “output = port “install”, @resource[:name]” and that fixed the problem. However, since my current system is using “Mac Ports” I would like to specify “macports” as a provider instead of ‘darwinport’ in my site manifest. To accomplish that I simply copied the provider file for “darwinport.rb to macports.rb”:

--> sudo cp /opt/local/lib/ruby/site_ruby/1.8/puppet/provider/package/darwinport.rb /opt/local/lib/ruby/site_ruby/1.8/puppet/provider/package/macports.rb

and made the below changes specified in the diff output below:

--- /opt/local/lib/ruby/site_ruby/1.8/puppet/provider/package/darwinport.rb	2011-10-31 11:12:17.000000000 -0400
+++ /opt/local/lib/ruby/site_ruby/1.8/puppet/provider/package/macports.rb	2011-11-14 12:00:02.000000000 -0500
@@ -1,7 +1,7 @@
 require 'puppet/provider/package'
 
-Puppet::Type.type(:package).provide :darwinport, :parent => Puppet::Provider::Package do
-  desc "Package management using DarwinPorts on OS X."
+Puppet::Type.type(:package).provide :macports, :parent => Puppet::Provider::Package do
+  desc "Package management using Mac Ports on OS X."
 
   confine :operatingsystem => :darwin
   commands :port => "/opt/local/bin/port"
@@ -47,6 +47,16 @@
     should = @resource.should(:ensure)
 
     # Seems like you can always say 'upgrade'
+    output = port "install", @resource[:name]
+    if output =~ /^Error: No port/
+      raise Puppet::ExecutionFailure, "Could not find package #{@resource[:name]}"
+    end
+  end
+
+  def upgrade
+    should = @resource.should(:ensure)
+
+    # Seems like you can always say 'upgrade'
     output = port "upgrade", @resource[:name]
     if output =~ /^Error: No port/
       raise Puppet::ExecutionFailure, "Could not find package #{@resource[:name]}"

Now I am able to change my site manifest, site.pp, to read:

Package {
  provider => $operatingsystem ? {
    darwin => macports,
  }
}

package {'ipcalc':
  ensure => installed,
}

and it executes without issues when installing a new port:

`--> sudo puppet agent --no-daemonize --test
Password:
info: Retrieving plugin
err: /File[/var/lib/puppet/lib]: Could not evaluate: Could not retrieve information from source(s) puppet://<server-name>/plugins
info: Caching catalog for <fqdn>
info: Applying configuration version '1321293994'
notice: /Stage[main]//Package[ipcalc]/ensure: created
notice: Finished catalog run in 63.30 seconds
Changes:
            Total: 1
Events:
          Success: 1
            Total: 1
Resources:
          Changed: 1
      Out of sync: 1
            Total: 8
Time:
   Config retrieval: 0.44
       Filebucket: 0.00
          Package: 32.58
         Schedule: 0.00
60.94s user 2.84s system 92% cpu 1:09.09s total

`--> port installed ipcalc
The following ports are currently installed:
  ipcalc @0.41_0 (active)
Advertisements
This entry was posted in *Nix. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s