On Mon, Jan 23, 2012 at 1:45 AM, Jos Houtman <j...@hyves.nl> wrote:
> I am looking for advice/best-practices on how to handle inter module 
> dependency's.

In general, I try and think of module dependencies and organization as
a matter of composition.  Discrete modules themselves should avoid
establishing relationships with other modules.  A module should,
however, be diligent about managing the internal relationships of the
classes and resources it defines.

Ideally, Puppet itself would be more opinionated about the
relationship of modules, and we're moving in that direction.  Kelsey
Alexander is working with Matt Robinson on things like #11979 [1]
which gets us on the path to managing dependencies automatically.  In
the meantime, I document and leave it up to the end user to create
another class that composes modules together.  With your example, I'd
do something like this as the end user.  As the module author, I'd try
and write mysql and ldap as if the other didn't exist.

node www1 {
  include site::dbserver
}

# <modulepath>/site/manifests/dbserver.pp
# This is what it means to be a database at the Acme.com site.
class site::dbserver {
  class { ldap: }
  -> class { mysql: }
}

[snip]


> Without stages we tried three ways of doing this:
> Creating a dependency chain between classes.
> Class['Ldap'] -> Class['Mysql'].
> This is very easy to do, but doesn't work if we inherit from Ldap,  say:
>  class ldap::server inherits ldap

In this situation I'd update the composition in the site module.  I'd
also avoid inheritance if at all possible, but that's another story
for another thread.

node www1 {
  include site::dbserver2
}

# <modulepath>/site/manifests/dbserver2.pp
# This is what it means to be a database at the Acme.com site.
class site::dbserver2 {
  class { 'ldap::server': }
  -> class { mysql: }
}

> The ordering between ldap::server and Mysql is not guaranteed.
> It also requires the maintainer of the ldap module to know about all modules
> that depend on ldap and update them if he decides to inherit. A task that is
> likely to be forgotten.

For these reasons I try and think of the whole thing as a composition
problem.  The things being composed, modules, should try and avoid
knowing implementation details about each other.

> Creating a dependency chains between resources in the modules, f.e.
> notify's.
> Every module that is part of an dependency defines an  notify{ 'endpoint': }
> and makes sure that everything within the module is executed before the
> notify.

This sounds a lot like the Anchor pattern [2].  Are you trying to
accomplish the same goal of classes encapsulating other classes in the
dependency graph?

> If we inherit from the base class, the overriding class is responsible for
> making sure that endpoint is still the last thing executed in this module.
> Making it more likely that the ordering of events will remain as we want it
> after a continued year of development.

Yep, really sounds like the anchor pattern [2].

> So after this rather longer email explaining our problem and some of the
> options we explored, how do you guys handle these kind of complex
> inter-module dependencies?

Not easily.  =)  The anchor pattern is a bug, certainly, and so is the
UX of having to manage dependencies so carefully and painfully.  The
good news is that we're actively working on it.  If you could update
any of the following bugs with your user stories and desires it will
help shape the solution.  11832, 12243, 12246, 12249, 12250, 12251,
12253, 12255, 12256, 12257, 12258, 12259, 12260,

[1] http://projects.puppetlabs.com/issues/11979
[2] http://projects.puppetlabs.com/projects/puppet/wiki/Anchor_Pattern

-- 
Jeff McCune

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Users" group.
To post to this group, send email to puppet-users@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.

Reply via email to