[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Editfiles Considered Harmful (was: Re: Complex Editfiles Examples)

From: Luke A. Kanies
Subject: Re: Editfiles Considered Harmful (was: Re: Complex Editfiles Examples)
Date: Thu, 4 Dec 2003 11:36:41 -0600 (CST)

I definitely agree with Eric here.  Although I use editfiles for small
cases, I find it to be so prone to error that it's not usable for more
complicated things.  Add an extra space to your AppendIfNoSuchLine?  Yay,
now you have two cron jobs.  This type of problem is definitely an issue
of cfengine not understanding the semantics behind the work it's doing.

However, I also do my best not to copy files around.  Once you get to the
point where you've got more than one version of a type of file, you're
usually asking for trouble.  For instance, if you're copying resolv.conf
around, and you've got four or five versions, then you're in deep trouble
when it comes time to change them and you need to change all of them.

I find the best solution is to write a module to just generate the file
from scratch.  I'm working on an overall framework optimized for
generating files, although I have not made much progress so far.  Usually,
though, it's pretty easy.  I've successfully generated inetd.conf,
/etc/services, resolv.conf, and a few others, and they're all pretty
straightforward.  I've got some examples in the latest ISconf 3 tarballs
(available at

I constantly have to wrestle with this question, and the answer usually
goes through this basic progression:

1) Don't manage the file at all
2) Use editfiles to do very simplistic changes (one or two lines)
3) Centralize all of the files into a few unique files
4) Write a module to generate the appropriate file for every system

So I usually end up using editfiles a bit, and there's a lot of research
between steps 2 and 3.  For instance, to be able to generate inetd.conf, I
had to pull every inetd.conf file on the network and use those to generate
a list of every possible inetd entry and then a cfengine config that
matched the right entries with a given host.  I stored the entries in an
external data file, and used (sorry Mark) perl to combine them; it looked
something like this:

# perl data file; easy to read
$VAR1 = {
  sadmind => {
        'wait' => 'wait',
        'endpoint' => 'tli',
        'command' => 'sadmind -S 2',
        'binary' => '/usr/sbin/sadmind',
        'protocol' => 'rpc/udp',
        'uid' => 'root',
        'name' => '100232/10'

# cfengine config

  AllowRedefinitionOf = ( inetd_svcs )

  inetd_svcs = ( "" ) # you have to do this

  host1:: inetd_svcs = ( "${inetd_svcs} telnet" )
  host2:: inetd_svcs = ( "${inetd_svcs} ftp" )

  actionsequence = ( "module:inetd ${inetd_svcs}" )


And I've had a lot of success with that.  All the complex work is done
outside of cfengine (i.e., all of the abstraction) but you can still use
cfengine to make decisions about what to enable where.  Then your module
just maps the name back to the data entry.  This module is available in
the above mentioned ISconf tarball, along with one to create


A diplomat is a man who can convince his wife she'd look stout in a fur

reply via email to

[Prev in Thread] Current Thread [Next in Thread]