Help me understand formula hook idempotence

Nick Moffitt nick.moffitt at canonical.com
Sun Aug 21 19:59:24 UTC 2011


I am reading the example formulae in lp:ensemble at the moment, and
noticing a few things that confuse me.  I also see work going on in the
Principia repository, producing things like
http://bazaar.launchpad.net/~zulcss/principia/oneiric/nagios/trunk-1/view/head:/hooks/nagios-relation-changed
which appear to drag in some Python infrastructure in preference to
shell scripting, so perhaps it's just that the example formulae aren't
meant to be considered for production use.  

Either way, two things give me pause.

First, reading from:
http://bazaar.launchpad.net/~ensemble/ensemble/trunk/view/174.7.26/examples/mysql/hooks/install
> echo mysql-server-5.1 mysql-server/root_password password $PASSWORD | debconf-set-selections
> echo mysql-server-5.1 mysql-server/root_password_again password $PASSWORD | debconf-set-selections
> DEBIAN_FRONTEND=noninteractive apt-get -y install -qq mysql-server

How does this avoid races and conflicts?  What if some other formula
sets the root password?  How do you perform static analysis to prevent
collisions before a set of changes goes out?  In Puppet (the system I am
currently most familiar with) the --noop catalog compilation would raise
an error and prevent application, but I can't figure out how to trigger
any sort of --dry-run or --simulate options in ensemble.  

What do you do if mysql-server is already installed (perhaps via a
dependency) but not configured to your desires?  How do you prevent two
formulae from installing packages that have mutual conflicts/replaces
settings?  It seems impossible to predict how this hook will behave,
from my naïve reading.

Second, we also see in the above install hook:
> sed --in-place=old 's/127\.0\.0\.1/0.0.0.0/' /etc/mysql/my.cnf

This is what leads me to suspect that this example is not meant for
production use.  To my eye, the use of sed(1) sticks out as something of
an anti-pattern: the configuration management world has by and large
abandoned CFEngine's procedural-edit approaches, choosing instead to
reliably assert the complete state of system resources.  

This allows you to quickly reason about the resulting state in a way
that gives you confidence in your infrastructure, and ensures that it
only takes a single run on a production server to achieve correctness.
Furthermore, `sed -i` operations are order-dependent, which makes for an
entire category of headaches all on its own!

Puppet has support for Augeas, which is a more clever approach to
CFEngine-style edits: it allows you to assert individual sub-sections of
a file, and solves the order-dependence problem by raising errors for
conflicts.  But overall even Augeas is frowned upon.

The Puppet solution for piecemeal generation of files is called
"Concat", and it uses a technique somewhat analogous to dotdee but
without the inotify hooks (though I can't reliably comment on dotdee as
I haven't used it).

If you assemble a complete file from configuration management, you can
reason about the resulting state from a local branch very quickly
without needing to query running configuration state. For more of the
reasoning behind abandoning Augeas for general work, see the comment at
http://www.devco.net/archives/2010/02/19/building_files_from_fragments_with_puppet.php/comment-page-1#comment-5013
which begins "Augeas combined with Puppet is just in general an
anti-pattern in my opinion".

I'm still reading through the ensemble code and documentation, so please
accept my apologies if any of this is a simple failure to RTFM.

-- 
Nick Moffitt




More information about the Ensemble mailing list