help-cfengine
[Top][All Lists]
Advanced

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

List in copy and cross-action communication


From: Wil Cooley
Subject: List in copy and cross-action communication
Date: Thu, 21 Apr 2005 18:22:09 -0700

I'm finally moving my Postfix configuration into cfengine and in
considering how to manage the various database map files (virtual,
transport, etc, which need to be rebuilt when updated) I see a potential
for improvement in a couple of areas.  It would be very elegant to be
able to accomplish this with just one or two stanzas instead of two
stanzas for _each_ file, if doing it purely in cfengine.  My example
refers to 3 files, so that's six stanzas. although in reality there
would likely be more.

Let me start by saying that I do know how to do this as things are now,
so I'm not looking for specific advice, rather I'm daydreaming about
improvements.  (What I will do is to put the map files in a directory
and use a recursive copy of the source directory, and then run a
Makefile in a shellcommand.  That'll do as many files as I need in just
two stanzas, but it seems less elegant than it being totally self-
contained w/in cfengine.)

First, the copy of a list.  Given the current behavior of requiring the
full destination when a full source path is given, it's not possible
(that I've found, anyway) to use a list/array as the source of a copy.
The list is expanded as the source just fine, but the destination fails
with the usual "image exists but destination type is silly".

Consider something like this:

control:
  actionsequence = ( copy )
  postfix_maps = ( virtual:transport:canonical )

copy:
  ${source_directory}/${postfix_maps}
     dest=/etc/postfix/
     server=${cfserver}
     action=warn  # Better for testing
      # etc

As you might expect, changing the destination to
'dest=/etc/postfix/${postfix_maps}' doesn't work--The list does not
expand in this context and if it did it would probably expand to all
three for each source (making 9 copies, ending up maybe with the last
one being the right file).

I tried a little trickery by adding 'include=* rec=1', but cfengine was
on to my shenanigans and still complained.

There are a few ways around this that seem obvious to me:
  1. Allow the destination to be a directory by adding an option to the
copy action, e.g.: 'directory_destination_ok=true'.  I'm not keen on
adding yet another option that I'll constantly have to lookup in the
reference manual.  It also does not solve the problem of rebuilding the
maps, which I will to get to shortly.

  2. Add a special variable containing the current item in the list,
kinda like Make does with '$@', with some magic to allow you to retrieve
the basename of a file.  Then the above could look something like this
and still not have to relax the destination-is-not-a-directory rule:

copy:
  ${source_directory}/${postfix_maps}
     dest=/etc/postfix/${@}
     server=${cfserver}

Having that defined and accessible in the rest of the stanza leads to
several possibilities for the map rebuilding.

One option would be to be able to use the '${@}' (or whatever, I don't
care too much, this just seems like an obvious adaptation from Make) in
the 'define' parameter:

copy:
  ${source_directory}/${postfix_maps}
     dest=/etc/postfix/${@}
     server=${cfserver}
     define=postfix_${@}_needs_rebuild

Then shellcommands with the defined class:

shellcommands:
  postfix_virtual_needs_rebuild::
    "/usr/sbin/postmap /etc/postfix/virtual"

Still a lot of redundancy here--I'd need one shellcommands action for
every map file.

Another option would be to have some variables that could be associated
with defined classes; perhaps this is kinda ugly, but imagine that
'${@}' gets attached to the class where it is defined, perhaps building
up as a list?  Then you could have the copy just use
'define=postfix_map_needs_rebuild' and the associated shellcommands
action uses the '${@}' (which is expanded internally to be multiple
shellcommands), like this:

shellcommands:
  postfix_map_needs_rebuild::
    "/usr/sbin/postmap /etc/postfix/${@}"

The final option, which seems the most elegant to me (and that would
have lots of other applications), would to forego the classes altogether
and use shellcommands directly in the copy action:

copy:
  ${source_directory}/${postfix_maps}
     dest=/etc/postfix/${@}
     server=${cfserver}
     shellcommand="/usr/sbin/postmap /etc/postfix/${@}"
     # an "elseshellcommand" would be symmetric to the 'elsedefine'

Wil
-- 
Wil Cooley                                 wcooley@nakedape.cc
Naked Ape Consulting                        http://nakedape.cc
* * * * Linux, UNIX, Networking and Security Solutions * * * *

Attachment: signature.asc
Description: This is a digitally signed message part


reply via email to

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