I started to write this a few days ago in the thread, "In search of a 
CFEngine language specification (for 4.x)," but I've decided it deserves 
its own thread as it potentially applies just as much to future CFEngine 3 
releases.

P. Christeas wrote the following:

PC> But, as you said, problem is that many of the existing promise types 

PC> (implementations, that is) have arbitrary quirks in the way they are 
evaluated 

PC> and executed.


Indeed.


The theory is that one shouldn't have to worry about sequence when writing 
CFEngine 3 policy.  The reality is that one has to worry about sequence *MUCH, 
MUCH MORE* than when writing in any language wherein commands are simply 
executed one after another.


*Here is a real case study in CFEngine evaluation sequence.*


Consider the following three promises:


    [root@hub ~]# cat nameservers.cf

    bundle agent main {

        commands:

          any::

            "/bin/sed -f $(this.promise_dirname)/nameservers.sed 
/etc/resolv.conf"

              classes => kept_successful_command,

              module => "true";


        vars:

          DEBUG::

            "report_indices"

              slist => getindices("inventory_module.nameserver");


        reports:

          DEBUG::

            "Inventorying nameserver: 
'$(inventory_module.nameserver[$(report_indices)])'";

    }


    body classes kept_successful_command {

      # from standard library

      kept_returncodes => { "0" };

    }


Below is the Sed script referenced.  It converts the nameservers from the 
resolv.conf file into module protocol for CFEngine inventory.  (As a side 
note, this sort of text parsing is *extraordinarily* difficult/overcomplicated 
with pure CFEngine, but as I'm quite decent with POSIX text processing 
tools, this doesn't bother me too much.)


    [root@hub ~]# cat nameservers.sed 

    #!/bin/sed -f

    1i\

    ^context=inventory_module

    1i\

    ^meta=inventory,attribute_name=Nameservers

    /^nameserver[[:space:]]*/!d

    s///

    s/[[:space:]]*$//

    s/.*/=nameserver[&]=&/


Note the vars promise and reports promise in the bundle up above, written 
so we can see what CFEngine is adding to inventory.


Now, before going any further—do you see the error in the policy up above? 
 (If you do see it, it's possible you've been spending *way* too much 
debugging CFEngine's evaluation sequence.)  ;)


What do we get if we run this policy with the DEBUG class set?


    [root@hub ~]# cf-agent -KIC -DDEBUG -f ./nameservers.cf 

        info: Executing 'no timeout' ... '/bin/sed -f 
/root/./nameservers.sed /etc/resolv.conf'

        info: Command related to promiser '/bin/sed -f 
/root/./nameservers.sed /etc/resolv.conf' returned code defined as promise 
kept 0

        info: Completed execution of '/bin/sed -f /root/./nameservers.sed 
/etc/resolv.conf'

    R: Inventorying nameserver: '$(cf_null)'

    R: Inventorying nameserver: '10.0.2.3'

    [root@hub ~]# 

Why do we see cf_null?  We don't want cluttering up our inventory, do we?

Well actually, it doesn't show up in inventory.  Just in the debug 
reporting.  Try and see if you can work out why.

Then, a pop quiz (actually a trick question): Where will you add the 
depends_on attribute to avoid this noise in the debug reporting?

Now please notice that these extra two promises, added for the sole purpose 
of assisting with debugging the commands promise, *themselves* need quite a 
bit of debugging before they work as expected.

(Can anyone guess what's going on in the above code and what would have to 
be done to fix it?)  :)

--------

I posit that it would be *less* surprising and easier to learn (and to 
debug!) if CFEngine simply evaluated promises *in the sequence they are 
specified* in a bundle, unless overridden with "depends_on" attributes.

And actually, considering the great number of "isvariable()" calls I have 
had to add in a single bundle to ensure that production data didn't get 
polluted with unresolved variables, I think that passing unresolved 
variables as-is is a *serious* misfeature.  This is about the only "magic 
ordering" I would personally support: skip any promise that makes reference 
to an unresolved variable (just like most CFEngine function calls already 
do.)

Interested in the thoughts of the developers on these points.

Best,
--Mike Weilgart
Vertical Sysadmin, Inc.

-- 
You received this message because you are subscribed to the Google Groups 
"dev-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to dev-cfengine+unsubscr...@googlegroups.com.
To post to this group, send email to dev-cfengine@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/dev-cfengine/7f6d49ac-af68-4aa1-bc8c-7e62291cae64%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to