help-cfengine
[Top][All Lists]
Advanced

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

Re: take action if line exists


From: Brendan Strejcek
Subject: Re: take action if line exists
Date: Thu, 3 Nov 2005 14:49:33 -0600
User-agent: Mutt/1.5.6+20040818i

Mark McCullough wrote:

> I've been finding myself more and more wanting to take an editfile
> action if and only if a line exists in a file. I know, I could
> hypothetically use LocateLineMatching

For fun, I tried to get this to work and I could not. This is what I
tried.

    editfiles:
        { /etc/group
            # If we can't find ^sys:, editfiles will abort
            # And we skip to CatchAbort and the class will not get defined
            LocateLineMatching "^sys:.*$"
            # If we proceed past LocateLineMatching, we know we are on ^sys
            # So we know it won't match ^foo$
            # And the class will get defined
            BeginGroupIfNoMatch "^foo$"
                DefineInGroup "found_sys_group_line"
            EndGroup
            CatchAbort
            # An example that should fail to define a class
            ResetSearch "1"
            LocateLineMatching "^foo:.*$"
            BeginGroupIfNoMatch "^foo$"
                DefineInGroup "found_foo_group_line"
            EndGroup
            CatchAbort
        }
    alerts:
        found_sys_group_line::
            "/etc/group has a line that matches ^sys:"
        found_foo_group_line::
            "/etc/group has a line that matches ^foo:"

Of DefineInGroup, the reference says: "Activate the following colon,
comma or dot-separated list of classes if the edit group is entered"
but I think it means "... and if edits are performed" because I see the
group being entered in the -v output, but no group is defined. I suppose
you could do something lame like inserting a comment line which you also
delete at the start of every run which would be technically convergent,
but ugly.

The above test also gives me: "DefineInGroup used outside edit-group"
though that does not seem to be the case. I was not testing this using
the most recent version of cfengine, so I don't know if it is a bug.

Using editfiles is not the way I would expect to do something like this
in cfengine, though it is probably they only action that gives you
convenient access to the contents of files. It seems like the correct
way to do actions based on the contents of files would require something
like an "examinefiles" action.

Even if it did work, that is a pretty hideous replacement for:

    classes:
        found_foo_group_line = (
            ReturnsZero(/bin/sh -c '
                ${grep_path} ^foo: /etc/group >/dev/null 2>&1'
            )
        )

I use this idiom often because it is less hassle than writing an
external module to define classes, and it keeps everything necessary to
solve a problem in a single file.

> I haven't figured out a reasonable method shy of using a class defined
> by a grep output to trigger this, and that becomes problematic for me
> when I go multi-platform. (Solaris requires /usr/xpg4/grep for grep
> -q, Linux has it internal, ...)

You can wrap the grep with a shell to get rid of the output, as I do
above. But the differing paths for similar functionaily problem is more
general. I bit this bullet a while ago. I maintain a fragment called
"os_specific_paths" that looks something like this:

    control:
        AllowRedefinitionOf = (
            cfengine_prefix
            cfagent_path
            cfexecd_path
            cfenvd_path
            cfkey_path
            cfservd_path
            find_path
            moduledirectory
            perl_path
            postfix_config
            rm_path
            ssh_config
            workdir
        )
    
        # Set defaults
        any::
            workdir         = ( /var/cfengine )
            cfengine_prefix = ( /usr/local )
            ssh_config      = ( /etc/ssh )
            postfix_config  = ( /etc/postfix )
            perl_path       = ( /usr/bin/perl )
            find_path       = ( /usr/bin/find )
            rm_path         = ( /bin/rm )
        openbsd::
            find_path       = ( /usr/local/bin/gfind )
        redhat::
            cfengine_prefix = ( /usr )
        debian::
            cfengine_prefix = ( /usr )
        debian_3_0::
            cfengine_prefix = ( /opt/cs-cfengine )
        debian_99::
            cfengine_prefix = ( /opt/cs-cfengine )
        linux_x86_64.debian_99::
            cfengine_prefix = ( /usr/local )
        sunos::
            cfengine_prefix = ( /opt/csw )
            perl_path       = ( /opt/csw/bin/perl )
        any::
            cfagent_path    = ( ${cfengine_prefix}/sbin/cfagent )
            cfexecd_path    = ( ${cfengine_prefix}/sbin/cfexecd )
            cfenvd_path     = ( ${cfengine_prefix}/sbin/cfenvd )
            cfkey_path      = ( ${cfengine_prefix}/sbin/cfkey )
            cfservd_path    = ( ${cfengine_prefix}/sbin/cfservd )
            moduledirectory = ( ${workdir}/modules )

It would probably be cleaner for shellcommands to have some concept of a
trusted path that you could set or append to just like PATH.

Best,
Brendan

--
Senior System Administrator
The University of Chicago
Department of Computer Science
http://www.cs.uchicago.edu/people/brendan




reply via email to

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