Kumina | Blog

On our puppet module design

puppet

puppet

Most puppeteers seem to work for either one company or only deploy one type of service to different companies. You can notice this in the way they build their modules. Most people tend to create one module that contains everything that is needed for a service or application, since they only need to have it (mostly) the same. We at Kumina work for a lot of different companies and try to be as flexible as possible. This makes our module design a fair bit different than most others, in my experience. This post tries to explain some of the choices we’ve made with regards to module design.

We work at three different levels, which we gave separate names:

When designing our modules, we keep several guidelines in mind:

That looks like a fairly long list, but most of it seems rather logical once you’re working with it. These guidelines make sure that our entire team can quickly and easily work on each customer’s setup, where needed. Keeping the environments separate from each other also allows us to easily see the impact certain changes will make. In practise, most of the resources will be defined in the kbp layer. But the generic layer is still important, because we try to create an API-like approach the applications of the same service type. I’ve described how to do that a while ago on the Puppet mailinglist (I should probably write a blog post about that too, but not today). The main advantage of this being that you should be able to easily replace for example apache with nginx.

Using the above guidelines, setting up our webserver is simply a block like this:

node 'web.kumina.nl' inherits 'kumina_default' {
  include site::www_kumina_nl
  include site::www_twenty_five_nl
  include site::blog_kumina_nl
  include mail::incoming
}

And everything is setup as we need it. The class itself looks as follows (for example):

class site::www_kumina_nl {
  include kbp_httpd
  include site::common

  kbp_httpd::simple_site { "www.kumina.nl":
    ensure => 'present',
    documentroot => '/srv/www/www.kumina.nl/',
  }
}

class site::www_twenty_five_nl {
  include kbp_httpd
  include site::common
  include kbp_httpd::php
  include kbp_mysql

  kbp_httpd::simple_site { "www.twenty-five.nl":
    ensure => 'present',
    documentroot => '/srv/www/www.twenty-five.nl/',
  }

  kbp_mysql::db_with_user { "tf_interface":
    password_hash => 'very_secret',
  }
}

class site::blog_kumina_nl {
  include kbp_httpd
  include site::common
  include kbp_httpd::php
  include kbp_mysql

  kbp_httpd::simple_site { "blog.kumina.nl":
    ensure => 'present',
    documentroot => '/srv/www/blog.kumina.nl/',
  }

  kbp_mysql::db_with_user { "kumiblog":
    password_hash => 'very_secret',
  }
}

If we decide to ever move the blog to a separate server, we can simply do:

node 'web.kumina.nl' inherits 'kumina_default' {
  include site::www_kumina_nl
  include site::www_twenty_five_nl
  include mail::incoming
}

node 'blog.kumina.nl' inherits 'kumina_default' {
  include site::blog_kumina_nl
}

Aside from manually moving the data in the database, everything should work as expected. This allows us to easily move sites (or other applications) from one machine to another.

This way of building your modules either appeals because of the flexibility or seems a horribly inefficient use of your time. We find it’s a nice way to keep some order without losing too much flexibility.

Exit mobile version