<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-998418780028044861</id><updated>2010-01-28T21:45:37.983+01:00</updated><title type='text'>On the brink</title><subtitle type='html'>Technical blog (Gunnar Wrobel)</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://log.onthebrink.de/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/-/kolab2gentoo'/><link rel='alternate' type='text/html' href='http://log.onthebrink.de/search/label/kolab2gentoo'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Gunnar Wrobel</name><uri>http://www.blogger.com/profile/05751776969338923853</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-998418780028044861.post-2948144297857229399</id><published>2008-05-18T07:28:00.006+02:00</published><updated>2008-05-18T10:26:07.822+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system administration'/><category scheme='http://www.blogger.com/atom/ns#' term='gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='masking'/><category scheme='http://www.blogger.com/atom/ns#' term='modules'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab2gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='puppet'/><category scheme='http://www.blogger.com/atom/ns#' term='keywords'/><category scheme='http://www.blogger.com/atom/ns#' term='use flags'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='sysadmin'/><category scheme='http://www.blogger.com/atom/ns#' term='portage'/><category scheme='http://www.blogger.com/atom/ns#' term='pardalys'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab'/><title type='text'>Using puppet on Gentoo</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.flickr.com/photos/wrobel/2493776447/"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://farm4.static.flickr.com/3208/2493776447_6e6f234e00_m_d.jpg" border="0" alt="" /&gt;&lt;/a&gt;
&lt;p&gt;
&lt;a href="http://puppet.reductivelabs.com/"&gt;Puppet&lt;/a&gt; is a tool for managing your system configuration. It provides a complete language for expressing and realizing system settings. After some introductory words this post will focus on a Gentoo specific puppet module for managing package installations.
&lt;/p&gt;
&lt;p&gt;
If you have no clue about puppet you might wish to read the introduction if you are interested in managing the configurations of your system in an efficient way. The discussion about the gentoo specific module will only be of interest to you if you already know the basics of writing puppet modules.
&lt;/p&gt;
&lt;h5&gt;Introduction&lt;/h5&gt;
&lt;p&gt;
What are the advantages of using puppet rather than editing all files in &lt;em&gt;/etc&lt;/em&gt; by hand?
&lt;ul&gt;
&lt;li&gt;Using puppet means you create a repository of your configuration knowledge&lt;/li&gt;
&lt;li&gt;You can replicate all of or part of the settings to another host&lt;/li&gt;
&lt;li&gt;In addition you can version control and share your knowledge in a repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
Mind you: If you are only managing a single host you might not find much value in the items listed above. Indeed puppet only becomes useful if you really wish to apply a complex configuration over many hosts.
&lt;/p&gt;
&lt;p&gt;
But of course this is true for any groupware server and in particular the &lt;a href="http://www.kolab.org"&gt;Kolab Server&lt;/a&gt;. Porting &lt;a href="http://www.gentoo.org/proj/en/kolab"&gt;Kolab to Gentoo&lt;/a&gt; is a project I have been working on for more than three years now.
&lt;/p&gt;
&lt;p&gt;
The initial version (Kolab2/Gentoo-2.1) failed to make me really happy. One central reason for that has been the configuration tool provided by Kolab. While it works fine for the original version of the Kolab Server it simply fails to cope with the amount of options users have on Gentoo.
&lt;/p&gt;
&lt;p&gt;
I always wanted to &lt;a href="http://log.onthebrink.de/2007/12/polymeraze-time-for-merging.html"&gt;merge my own crappy tool for configuration management&lt;/a&gt; with the code from the Kolab Server. But a kind anonymous voice answered to the blog post linked in the previous setence, telling me that this is a stupid idea and I should use puppet. He was right.
&lt;/p&gt;
&lt;p&gt;
So I'm establishing the &lt;a href="http://github.com/wrobel/pardalys/tree/master"&gt;Kolab2/Gentoo groupware server configuration&lt;/a&gt; based on puppet at the moment. As this includes generating some Gentoo specific modules for puppet it is now time to stop the introductory words and get down to some puppet code.
&lt;/p&gt;
&lt;h5&gt;Installing packages for generic distributions&lt;/h5&gt;
&lt;p&gt;
In order to tell puppet that you wish to have a single package installed you would use a construct like this:
&lt;/p&gt;
&lt;pre&gt;
package { openldap:
  ensure   =&gt; 'latest',
}
&lt;/pre&gt;
&lt;p&gt;
This works fine on most distributions but on Gentoo you might ask about support for use flags, keywords and masking.
&lt;/p&gt;
&lt;h5&gt;Installing packages on Gentoo&lt;/h5&gt;
&lt;p&gt;
My solution is &lt;a href="http://github.com/wrobel/pardalys/tree/master/pardalys/modules/os_gentoo"&gt;the puppet module  &lt;span style="font-weight:bold;"&gt;os_gentoo&lt;/span&gt;&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
This module is mainly concerned with management of the files/directories you find at &lt;em&gt;/etc/portage/package.*&lt;/em&gt; in your Gentoo system. In order for puppet to manage these paths it makes sense to convert these into directories.
&lt;/p&gt;
&lt;p&gt;
The module provides four central parts:
&lt;ol&gt;
&lt;li&gt;Backup of the original contents of &lt;em&gt;/etc/portage/package.*&lt;/em&gt; if these were files.&lt;/li&gt;
&lt;li&gt;Converting the paths into directories.&lt;/li&gt;
&lt;li&gt;Restoring the original file contents as &lt;em&gt;/etc/portage/package.*/package.*.original&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Providing functions to easily manage use flags, keywords and masking for other packages.&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;
&lt;h5&gt;Backup of &lt;em&gt;/etc/portage/package.*&lt;/em&gt;&lt;/h5&gt;
&lt;p&gt;
If the user managed &lt;em&gt;/etc/portage/package.*&lt;/em&gt; as files we need to grab the content and store it. Puppet provides the &lt;b&gt;file()&lt;/b&gt; function for that but that function will fail if it sees a directory. So we need to determine if the path already is a directory. We need to write some ruby code at this point and create a new &lt;b&gt;fact&lt;/b&gt;:
&lt;/p&gt;
&lt;pre&gt;
# Determine if these are regular files
 
package_use = '/etc/portage/package.use'
 
Facter.add('use_isfile') do
  setcode do
    if FileTest.file?(package_use)
      true
    else
      false
    end
  end
end

...
&lt;/pre&gt;
&lt;p&gt;
&lt;b&gt;Facts&lt;/b&gt; are little pieces of system information that puppet determines automatically using the tool &lt;em&gt;dev-ruby/facter&lt;/em&gt;. The code given above checks if &lt;em&gt;/etc/portage/package.use&lt;/em&gt; is a file and places that information in the variable &lt;b&gt;use_isfile&lt;/b&gt;. We will shortly meet that variable again.
&lt;/p&gt;
&lt;p&gt;
This &lt;b&gt;fact&lt;/b&gt; is something we &lt;a href="http://github.com/wrobel/pardalys/tree/master/pardalys/modules/os_gentoo/plugins/facter/portage_dirs.rb"&gt;store as a plugin at &lt;em&gt;os_gentoo/plugins/facter/portage_dirs.rb&lt;/em&gt; within the module&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
The code actually performing the backup is packaged in a &lt;a href="http://github.com/wrobel/pardalys/tree/master/pardalys/modules/os_gentoo/manifests/init.pp"&gt;puppet class&lt;/a&gt;:
&lt;/p&gt;
&lt;pre&gt;
# Class gentoo::etc::portage::backup
#
# Stores user settings in the /etc/portage/package.* files.
#
# @author Gunnar Wrobel &lt;p@rdus.de&gt;
# @version 1.0
# @package os_gentoo
#
class gentoo::etc::portage::backup
{
  if $use_isfile {
    $use = file('/etc/portage/package.use')
  } else {
    $use = false
  }
  if $keywords_isfile {
    $keywords = file('/etc/portage/package.keywords')
  } else {
    $keywords = false
  }
  if $mask_isfile {
    $mask = file('/etc/portage/package.mask')
  } else {
    $mask = false
  }
  if $unmask_isfile {
    $unmask = file('/etc/portage/package.unmask')
  } else {
    $unmask = false
  }
}
&lt;/pre&gt;
&lt;p&gt;
Here we meet the variables again. In case &lt;b&gt;$use_isfile&lt;/b&gt; is &lt;b&gt;true&lt;/b&gt; the file contents will be parsed into &lt;b&gt;$use&lt;/b&gt;. Otherwise the variable is set to &lt;b&gt;false&lt;/b&gt;. We return to our backup two sections further down.
&lt;/p&gt;
&lt;h5&gt;Converting &lt;em&gt;/etc/portage/package.*&lt;/em&gt; into directories&lt;/h5&gt;
&lt;p&gt;
Now that we have saved the file contents we can safely convert the files into directories. Puppet would not destroy the original files but instead store them in an archive. But recovering them from there would be cumbersome for the user. Automating the conversion seems to be a better solution.
&lt;/p&gt;
&lt;p&gt;
Requiring a path to be a directory is easy in puppet:
&lt;/p&gt;
&lt;pre&gt;
# Class gentoo::etc::portage
#
# Ensure that all /etc/portage/package.* locations are actually
# handled as directories. This allows to easily manage the package
# specific settings for Gentoo.
#
# @author Gunnar Wrobel &lt;p@rdus.de&gt;
# @version 1.0
# @package os_gentoo
#
class gentoo::etc::portage
{
  # Check that we are able to handle /etc/portage/package.* as
  # directories
 
  file { 'package.use::directory':
    path =&gt; '/etc/portage/package.use',
    ensure =&gt; 'directory',
    tag =&gt; 'buildhost'
  }
 
  file { 'package.keywords::directory':
    path =&gt; '/etc/portage/package.keywords',
    ensure =&gt; 'directory',
    tag =&gt; 'buildhost'
  }
 
  file { 'package.mask::directory':
    path =&gt; '/etc/portage/package.mask',
    ensure =&gt; 'directory',
    tag =&gt; 'buildhost'
  }
 
  file { 'package.unmask::directory':
    path =&gt; '/etc/portage/package.unmask',
    ensure =&gt; 'directory',
    tag =&gt; 'buildhost'
  }
}
&lt;/pre&gt;
&lt;p&gt;
Again the four actions have been packaged into a single puppet class. The different actions all have a &lt;b&gt;buildhost&lt;/b&gt; tag. This is only required if you really use a build host structure with your servers and plays no role otherwise.
&lt;/p&gt;
&lt;h5&gt;Restoring the original &lt;em&gt;/etc/portage/package.*&lt;/em&gt;&lt;/h5&gt;
&lt;p&gt;
Now that puppet converted &lt;em&gt;/etc/portage/package.*&lt;/em&gt; to directories we lost the original file contents. Another class will rescue them:
&lt;/p&gt;
&lt;pre&gt;
# Class gentoo::etc::portage::restore
#
# Restores user settings from the /etc/portage/package.* files.
#
# @author Gunnar Wrobel &lt;p@rdus.de&gt;
# @version 1.0
# @package os_gentoo
#
class gentoo::etc::portage::restore
{
  if $gentoo::etc::portage::backup::use {
    file { '/etc/portage/package.use/package.use.original':
      content =&gt; $gentoo::etc::portage::backup::use,
      tag =&gt; 'buildhost'
    }
  }
  if $gentoo::etc::portage::backup::keywords {
    file { '/etc/portage/package.keywords/package.keywords.original':
      content =&gt; $gentoo::etc::portage::backup::keywords,
      tag =&gt; 'buildhost'
    }
  }
  if $gentoo::etc::portage::backup::mask {
    file { '/etc/portage/package.mask/package.mask.original':
      content =&gt; $gentoo::etc::portage::backup::mask,
      tag =&gt; 'buildhost'
    }
  }
  if $gentoo::etc::portage::backup::unmask {
    file { '/etc/portage/package.unmask/package.unmask.original':
      content =&gt; $gentoo::etc::portage::backup::unmask,
      tag =&gt; 'buildhost'
    }
  }
}
&lt;/pre&gt;
&lt;p&gt;
For each of the four paths the original backup variable (e.g. &lt;b&gt;$gentoo::etc::portage::backup::use&lt;/b&gt;) is checked for content. We need to use the full class path here to access the variable content. If it contains content  it will be written to the corresponding new path (e.g. &lt;em&gt;/etc/portage/package.use/package.use.original&lt;/em&gt;).
&lt;/p&gt;
&lt;h5&gt;Handling &lt;em&gt;/etc/portage/package.*&lt;/em&gt; with puppet&lt;/h5&gt;
&lt;p&gt;
Now the management of &lt;em&gt;/etc/portage/package.*&lt;/em&gt; becomes easy as puppet can place new files for every package or set of packages that requires special use flags, keywords or masking.
&lt;/p&gt;
&lt;p&gt;
This is an example for the use flags:
&lt;/p&gt;
&lt;pre&gt;
# Function gentoo_use_flags
#
# Specify use flags for a package.
#
# @param context A unique context for the package
# @param package The package atom
# @param use The use flags to apply
#
define gentoo_use_flags ($context = '',
                         $package = '',
                         $use = '')
{
 
  file { "/etc/portage/package.use/${context}":
    content =&gt; "$package $use",
    require =&gt; File['package.use::directory'],
    tag =&gt; 'buildhost'
  }
 
}
&lt;/pre&gt;
&lt;p&gt;
The function takes a context which must be unique and will be used as path component. In addition the package atom needs to be specified including the use flags to be set. Puppet will then create a new file within &lt;em&gt;/etc/portage/package.use&lt;/em&gt; using the &lt;b&gt;file&lt;/b&gt; type (This is something different than the &lt;b&gt;file&lt;/b&gt; function mentioned above).
&lt;/p&gt;
&lt;p&gt;
The only new thing here is the &lt;b&gt;require&lt;/b&gt; argument that specifies that puppet must ensure that the file operation with the name &lt;b&gt;package.use::directory&lt;/b&gt; has been executed before creating this new file. In other words we ensure that &lt;em&gt;/etc/portage/package.use&lt;/em&gt; is indeed a directory.
&lt;p&gt;
&lt;h5&gt;Managing package installations on Gentoo&lt;/h5&gt;
&lt;p&gt;
Taking &lt;a href="http://github.com/wrobel/pardalys/tree/master/pardalys/modules/os_gentoo/manifests/init.pp"&gt;all these definitions&lt;/a&gt; together we can now express a package installation in the following way:
&lt;/p&gt;
&lt;pre&gt;
# Package installation
  case $operatingsystem {
    gentoo:
    {
      gentoo_unmask { openldap:
        context =&gt; 'service_openldap',
        package =&gt; '=net-nds/openldap-2.4.7',
        tag =&gt; 'buildhost'
      }
      gentoo_keywords { openldap:
        context =&gt; 'service_openldap',
        package =&gt; '=net-nds/openldap-2.4.7',
        keywords =&gt; "~$keyword",
        tag =&gt; 'buildhost'
      }
      gentoo_use_flags { openldap:
        context =&gt; 'service_openldap',
        package =&gt; 'net-nds/openldap',
        use =&gt; 'berkdb crypt overlays perl ssl syslog -sasl',
        tag =&gt; 'buildhost'
      }
      package { openldap:
        category =&gt; 'net-nds',
        ensure =&gt; 'latest',
        require =&gt; [ Gentoo_unmask['openldap'],
                       Gentoo_keywords['openldap'],
                       Gentoo_use_flags['openldap'] ],
        tag =&gt; 'buildhost'
      }
    }
    default:
    {
      package { openldap:
        ensure =&gt; 'installed',
      }
    }
  }
}
&lt;/pre&gt;
&lt;p&gt;
The example installs the experimental &lt;b&gt;net-nds/openldap-2.4.7&lt;/b&gt; package. We differentiate between Gentoo and other distributions using the &lt;b&gt;$operatingsystem&lt;/b&gt; variable automatically provided by puppet.
&lt;/p&gt;
&lt;p&gt;
Of course the Gentoo installation looks much more complex than the standard installation on other systems but we have a lot more flexibility on Gentoo. And the idea of the module is to allow us to use this flexibility within puppet.
&lt;/p&gt;
&lt;p&gt;
The first three sections (&lt;b&gt;gentoo_unmask&lt;/b&gt;,&lt;b&gt;gentoo_keywords&lt;/b&gt;, and &lt;b&gt;gentoo_use_flags&lt;/b&gt;) handle the settings in &lt;em&gt;/etc/portage/package.*&lt;/em&gt; and the actual installation happens in the fourth section. We use the standard &lt;b&gt;package&lt;/b&gt; type here but require that all the settings in &lt;em&gt;/etc/portage/package.*&lt;/em&gt; have been executed before puppet runs &lt;b&gt;emerge&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
A final note on the variable &lt;b&gt;$keyword&lt;/b&gt; that is being used in the section above. This is another &lt;a href="http://github.com/wrobel/pardalys/tree/master/pardalys/modules/os_gentoo/plugins/facter/keyword.rb"&gt;&lt;b&gt;fact&lt;/b&gt; &lt;/a&gt; that prevents us from specifying keywords like &lt;b&gt;~x86&lt;/b&gt; while we actually want &lt;b&gt;~amd64&lt;/b&gt;. It simply reads &lt;b&gt;ACCEPT_KEYWORDS&lt;/b&gt; and assumes that the user has the stable keyword selected there. This probably still needs fixing.
&lt;/p&gt;
&lt;h5&gt;Conclusion&lt;/h5&gt;
&lt;p&gt;
It is not too difficult to map the full power of package installations on Gentoo into the puppet way of installing packages. I'm pretty certain that some of the methods I implemented in &lt;b&gt;os_gentoo&lt;/b&gt; are still bound to evolve and do not yet represent the best way of handling installations on Gentoo. The module does for example not solve any of the issues mentioned on the &lt;a href="http://reductivelabs.com/trac/puppet/wiki/PuppetGentoo"&gt;Gentoo page in the puppet wiki&lt;/a&gt;. So there is still work to be done.
&lt;/p&gt;
&lt;p&gt;
But for now I'm happy to have the central aspects of use flags, keywords and masking available within puppet.
&lt;/p&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/998418780028044861-2948144297857229399?l=log.onthebrink.de' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.onthebrink.de/feeds/2948144297857229399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.onthebrink.de/2008/05/using-puppet-on-gentoo.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/2948144297857229399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/2948144297857229399'/><link rel='alternate' type='text/html' href='http://log.onthebrink.de/2008/05/using-puppet-on-gentoo.html' title='Using puppet on Gentoo'/><author><name>Gunnar Wrobel</name><uri>http://www.blogger.com/profile/05751776969338923853</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11408879373635975321'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-998418780028044861.post-1189031877663654589</id><published>2008-05-15T11:14:00.003+02:00</published><updated>2008-05-15T12:17:48.777+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='system administration'/><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='configuration'/><category scheme='http://www.blogger.com/atom/ns#' term='puppet'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab2gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='ldap'/><category scheme='http://www.blogger.com/atom/ns#' term='patch'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab'/><title type='text'>A first positive experience with ruby: Patching puppet</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.flickr.com/photos/wrobel/2493776447/"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://farm4.static.flickr.com/3208/2493776447_6e6f234e00_m_d.jpg" border="0" alt="" /&gt;&lt;/a&gt;
&lt;p&gt;
So far I didn't have much experience with ruby. The few lines of code I've written in that language reminded me too much of perl. And I'm not really a fan of the perl syntax. But today ruby managed to convince me in the area of unit testing.
&lt;/p&gt;
&lt;h5&gt;The problem&lt;/h5&gt;
&lt;p&gt;
I'm bound to stick to ruby as I decided that ruby-based &lt;a href="http://reductivelabs.com/projects/puppet/"&gt;puppet&lt;/a&gt; will provide a central element of the next &lt;a href="http://www.gentoo.org/proj/en/kolab"&gt;Kolab2/Gentoo&lt;/a&gt; version. While it provides some nice LDAP integration features these are not quite sufficient for Kolab. Puppet can grab some host parameters from LDAP and integrate these into the host configuration. The problem for Kolab2/Gentoo is the limitation to &lt;span style="font-weight:bold;"&gt;some&lt;/span&gt; LDAP parameters. Actually these have to be real LDAP attributes that have been defined in a schema. 
&lt;/p&gt;
&lt;p&gt;
As I have already &lt;a href="http://kolab.org/pipermail/kolab-devel/2008-April/008934.html"&gt;argued on the Kolab mailing list&lt;/a&gt; it does not make much sense to define attributes in a schema if you want to use such parameters for configuration of a large set of possible applications (postfic, openldap, cyrus, ...). In this case it makes more sense to use the approach also used by the Horde LDAP schema: specifying a single attribute that uses a string value to specify parameters with arbitrary names. E.g. ldapAttribute:"one=two" in order to define parameter "one". Only the "ldapAttribute" will have to be defined in a schema while the code using this parameter handles converting the string into the final paramter.
&lt;/p&gt;
&lt;p&gt;
I wrote a &lt;a href="http://reductivelabs.com/trac/puppet/ticket/1179"&gt;short patch&lt;/a&gt; for puppet to implement this. After a short while I got a positive response but the patch was considered insufficient as it lacked any tests.
&lt;/p&gt;
&lt;h5&gt;A simple solution&lt;/h5&gt;
&lt;p&gt;
I admit I was slightly worried because learning to handle just another test framework in a language I have nearly no clue about was something I did not fancy at all. And that was the first really positive surprise about ruby: Using the test framework and successfully writing unit tests in it was a matter of half an hour. Even though it required mocking the LDAP connection. 
&lt;/p&gt;
&lt;p&gt;
The testing allowed me to reconsider my expectations concerning the patch and to fix a problem of my initial version. I submitted the new version shortly afterwards and hope it will find its way into the repository now. 
&lt;/p&gt;
&lt;p&gt;
Well done, ruby. Let me see what else you can do in order to convince me that you are indeed a good thing...
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/998418780028044861-1189031877663654589?l=log.onthebrink.de' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.onthebrink.de/feeds/1189031877663654589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.onthebrink.de/2008/05/first-positive-experience-with-ruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/1189031877663654589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/1189031877663654589'/><link rel='alternate' type='text/html' href='http://log.onthebrink.de/2008/05/first-positive-experience-with-ruby.html' title='A first positive experience with ruby: Patching puppet'/><author><name>Gunnar Wrobel</name><uri>http://www.blogger.com/profile/05751776969338923853</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11408879373635975321'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-998418780028044861.post-2133762188928856038</id><published>2008-05-14T22:03:00.005+02:00</published><updated>2008-05-15T11:16:45.661+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='puppet'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab2gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='pardalys'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab2gentoonews'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab'/><title type='text'>app-admin/pardalys was created in the Kolab overlay</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://flickr.com/photos/wrobel/264813687/"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://farm1.static.flickr.com/103/264813687_5ebd3b95b7_m_d.jpg" border="0" alt="" /&gt;&lt;/a&gt;

&lt;P&gt;
If you look at the current ebuild you might wonder what the fuss might be about... It is a pretty empty package.
&lt;/p&gt;
&lt;P&gt;
But the &lt;a href="http://pardalys.sourceforge.net/"&gt;p@rdalys project&lt;/a&gt; will form the core for Kolab2/Gentoo-2.2. It will certainly replace net-mail/kolabd and might include some other packages, too.
&lt;/p&gt;
&lt;P&gt;
The idea is to allow you to install Kolab2/Gentoo-2.2 with two simple steps:
&lt;/p&gt;
&lt;Pre&gt;
emerge app-admin/pardalys
pardalys
&lt;/pre&gt;
&lt;P&gt;
Of course there is still a certain way to go until it will actually work that way. And this easy setup is actually just meant as a nice side effect and is not the main point of starting the project. I'll start explaining this package in greater detail once I push more code into it.
&lt;/p&gt;
&lt;P&gt;
For now the link to &lt;a href="http://pardalys.sourceforge.net/"&gt;the project page&lt;/a&gt; will be all I can provide.
&lt;/p&gt;
&lt;P&gt;
Currently it might not be clear what the package will actually be about but if people wish to contribute to the project at a later time point you should go visit the &lt;a href="http://github.com/wrobel/pardalys"&gt;git repository on GitHub&lt;/a&gt;. This git repository should serve as a scratch repository used for easy sharing and patching of the code. &lt;a href="http://pardalys.svn.sourceforge.net/viewvc/pardalys/"&gt;The reference repository&lt;/a&gt; on the other hand will be kept in subversion on SourceForge and will be used for packaging. 
&lt;/p&gt;
&lt;P&gt;
More on the whole story once there is more code.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/998418780028044861-2133762188928856038?l=log.onthebrink.de' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.onthebrink.de/feeds/2133762188928856038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.onthebrink.de/2008/05/app-adminpardalys-was-created-in-kolab.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/2133762188928856038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/2133762188928856038'/><link rel='alternate' type='text/html' href='http://log.onthebrink.de/2008/05/app-adminpardalys-was-created-in-kolab.html' title='app-admin/pardalys was created in the Kolab overlay'/><author><name>Gunnar Wrobel</name><uri>http://www.blogger.com/profile/05751776969338923853</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11408879373635975321'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-998418780028044861.post-1758429239832563689</id><published>2008-04-25T10:01:00.007+02:00</published><updated>2008-04-25T11:20:34.646+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pardus'/><category scheme='http://www.blogger.com/atom/ns#' term='gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='buch'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab2gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='opensourcepress'/><category scheme='http://www.blogger.com/atom/ns#' term='horde'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><category scheme='http://www.blogger.com/atom/ns#' term='groupware'/><category scheme='http://www.blogger.com/atom/ns#' term='sysadmin'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab2gentoonews'/><category scheme='http://www.blogger.com/atom/ns#' term='opensourcescool'/><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>The OpenSourceSchool opens its doors</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.opensourceschool.de/"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 79px;" src="http://www.opensourceschool.de/fileadmin/images/logo.gif" border="0" alt="" /&gt;&lt;/a&gt;
&lt;p&gt;
My &lt;a href="http://www.opensourcepress.de"&gt;publisher&lt;/a&gt; started with his next endeavor in bringing knowledge to the masses: The &lt;a href="http://www.opensourceschool.de"&gt;OpenSourceSchool&lt;/a&gt;. This time it is about spoken words - or courses - rather than written pages bound as books. Many &lt;a href="http://www.opensourcepress.de"&gt;OpenSourcePress&lt;/a&gt; authors are offering seminars there.
&lt;/p&gt;
&lt;p&gt;
I would definitely have liked to offer a course about &lt;a href="http://www.gentoo.org"&gt;Gentoo&lt;/a&gt; there. But I had to agree with them that this would probably not raise enough interest from paying customers. Or am I wrong about that?
&lt;/p&gt;
&lt;p&gt;
But of course there was room for the second topic dear to my heart: &lt;a href="http://www.gentoo.org/proj/en/kolab/"&gt;Kolab&lt;/a&gt;. &lt;a href="http://www.opensourceschool.de/index.php?id=15&amp;tx_ttproducts_pi1[backPID]=13&amp;tx_ttproducts_pi1[product]=33&amp;cHash=0e8d3864a9"&gt;The course&lt;/a&gt; will take five days and touch all major topics of the Kolab Server. Central components such as postfix, openldap, cyrus imap will provide the core components but I'll certainly also include a chapter about getting &lt;a href="http://www.horde.org"&gt;the Horde web client&lt;/a&gt; successfully installed. So we will hopefully have a new batch of Kolab experts in October.
&lt;/p&gt;
&lt;p&gt;
And hopefully the preparations for the course will also help in laying the groundwork for a book about Kolab. This is the only book I still want to write after going through the pain of writing &lt;a href="http://www.amazon.de/gp/product/3937514341?ie=UTF8&amp;tag=aufkant-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=3937514341"&gt;the Gentoo book&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/998418780028044861-1758429239832563689?l=log.onthebrink.de' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.onthebrink.de/feeds/1758429239832563689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.onthebrink.de/2008/04/opensourceschool-opens-its-doors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/1758429239832563689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/1758429239832563689'/><link rel='alternate' type='text/html' href='http://log.onthebrink.de/2008/04/opensourceschool-opens-its-doors.html' title='The OpenSourceSchool opens its doors'/><author><name>Gunnar Wrobel</name><uri>http://www.blogger.com/profile/05751776969338923853</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11408879373635975321'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-998418780028044861.post-5791359057531845134</id><published>2007-12-19T18:00:00.001+01:00</published><updated>2008-02-29T08:22:21.524+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab2gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='sourceforge'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='project'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab'/><category scheme='http://www.blogger.com/atom/ns#' term='polymeraze'/><title type='text'>Polymeraze: Time for merging</title><content type='html'>&lt;p&gt;
&lt;a href="http://polymeraze.sourceforge.net"&gt;Polymeraze&lt;/a&gt; is a tool that I wrote about two years ago. This package allowed me to cope with more than ten Gentoo servers at the same time. One of the main problems with many machines is to keep up with the configuration of the machines.
&lt;/p&gt;
&lt;p&gt;
Polymeraze allows you to create kind of knowledge base for configurations that can be applied to multiple hosts. It basically uses some template configurations which are being converted into the final configuration files by combining them with the specific host profile.
&lt;/p&gt;
&lt;p&gt;
While this tool was extremely handy it was also a bad hack since I wired it directly into the Gentoo package management system. This basically never really worked but since I knew how to handle it I just didn't mind too much.
&lt;/p&gt;
&lt;p&gt;
A while ago I realized that this tool has a few common properties with the good old "&lt;tt&gt;kolabconf&lt;/tt&gt;" from the &lt;a href="http://www.kolab.org"&gt;Kolab project&lt;/a&gt;. And since then I have dreamed of replacing &lt;tt&gt;kolabconf&lt;/tt&gt; with a rewritten &lt;tt&gt;polymeraze&lt;/tt&gt;.
&lt;/p&gt;
&lt;p&gt;
I hope that this merge will finally lead to a tool that will allow to get a really solid Kolab server natively integrated into the Gentoo system.
&lt;/p&gt;
&lt;p&gt;
Well, there is still plenty of work ahead. All I did so far is getting &lt;a href="http://polymeraze.sourceforge.net"&gt;the project page&lt;/a&gt; up. And now it is time for coding...
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/998418780028044861-5791359057531845134?l=log.onthebrink.de' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.onthebrink.de/feeds/5791359057531845134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.onthebrink.de/2007/12/polymeraze-time-for-merging.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/5791359057531845134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/5791359057531845134'/><link rel='alternate' type='text/html' href='http://log.onthebrink.de/2007/12/polymeraze-time-for-merging.html' title='Polymeraze: Time for merging'/><author><name>Gunnar Wrobel</name><uri>http://www.blogger.com/profile/05751776969338923853</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11408879373635975321'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-998418780028044861.post-6355929803941485620</id><published>2007-12-06T10:08:00.000+01:00</published><updated>2007-12-19T09:27:58.097+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='news'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab2gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='groupware'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><category scheme='http://www.blogger.com/atom/ns#' term='project'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab2gentoonews'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab'/><title type='text'>K2G News: Update of the project site</title><content type='html'>The &lt;a href="http://www.gentoo.org/proj/en/kolab/"&gt;project site&lt;/a&gt; got a few updates and new links.

In addition a &lt;a href="http://www.ohloh.net/projects/9490?p=Kolab2Gentoo"&gt;Ohloh project summary&lt;/a&gt; has been created.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/998418780028044861-6355929803941485620?l=log.onthebrink.de' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.onthebrink.de/feeds/6355929803941485620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.onthebrink.de/2007/12/k2g-news-update-of-project-site.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/6355929803941485620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/6355929803941485620'/><link rel='alternate' type='text/html' href='http://log.onthebrink.de/2007/12/k2g-news-update-of-project-site.html' title='K2G News: Update of the project site'/><author><name>Gunnar Wrobel</name><uri>http://www.blogger.com/profile/05751776969338923853</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11408879373635975321'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-998418780028044861.post-818745145701986043</id><published>2007-12-06T08:56:00.000+01:00</published><updated>2007-12-19T09:34:31.986+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='horde'/><category scheme='http://www.blogger.com/atom/ns#' term='gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab2gentoo'/><category scheme='http://www.blogger.com/atom/ns#' term='groupware'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><category scheme='http://www.blogger.com/atom/ns#' term='kolab'/><title type='text'>K2G: Kolab2/Gentoo getting attention again</title><content type='html'>Finally the &lt;a href="http://www.gentoo.org/proj/en/kolab/"&gt;Kolab2Gentoo&lt;/a&gt; project gets some attention again. I started fixing some older bugs but the main part will be to prepare for 2.2 now.

I still hate the way the whole project is structured but there are too many places where massive improvements are needed. So I guess I have to be content with small progress.

The stuff that is currently on my mind concerning Kolab2/Gentoo-2.2:

&lt;ul&gt;
&lt;li&gt;Update to Horde-3.2&lt;/li&gt;
&lt;li&gt;Making the patched c-client and php packages recommended instead of required&lt;/li&gt;
&lt;li&gt;Switching to a specific cyrus-imapd-kolab package&lt;/li&gt;
&lt;li&gt;Template packages&lt;/li&gt;
&lt;/ul&gt;

And then there is the big, bad problem of the Kolab configuration concept that simply fails for Gentoo in its current form. The solution to that one will take even longer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/998418780028044861-818745145701986043?l=log.onthebrink.de' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.onthebrink.de/feeds/818745145701986043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.onthebrink.de/2007/12/finally-kolab2gentoo-project-gets-some.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/818745145701986043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/998418780028044861/posts/default/818745145701986043'/><link rel='alternate' type='text/html' href='http://log.onthebrink.de/2007/12/finally-kolab2gentoo-project-gets-some.html' title='K2G: Kolab2/Gentoo getting attention again'/><author><name>Gunnar Wrobel</name><uri>http://www.blogger.com/profile/05751776969338923853</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='11408879373635975321'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>