Forum: Cfengine Help
Subject: Classes scope and lifetime
Author: yrouxel
Link to topic: https://cfengine.com/forum/read.php?3,20511,20511#msg-20511

Hello,

I have a few questions about classes scope and lifetime.

Methods are a powerful tool of cf 3, that allow reuse. But to use them to their 
full power, we should be able to use all kinds of promise types in sub-bundles, 
and in particular variables and classes.
To illustrate my questions, I use the example below:


bundle agent A {

classes:

          "cA1" expression => "any";

methods:
       
           "foo"  usebundle => B("cA1");
}  


bundle agent B(arg1) {

 vars:
          "vB1" string => "blabla";

classes:
          "cB1" expression => "any";



}



Questions:

Q1)
Classes lifetime
Sub-bundles, which are plain bundles of their own, are not reentrant : If the 
sub-bundle B is called several times through methods calls, variables keep 
their value setted in previous calls, and classes setted are retained. This is 
rather awkward, as some of these variables/classes can be used only for the 
internal logic of the bundle B and their state should be reinitailized once the 
method call ends. 
For variables, there is a solution with policy:


bundle agent B(arg1) {

 vars:
          "vB1" string => "blabla",
                      policy => "overridable";
...
}



But for classes, their no such escape. the only way I found was to resort to a 
kind of unique naming of class for each call, possibly depending on the value 
of some arguments of the bundle B:


bundle agent B(arg1) {

vars:
          "class_uid" => canonify("$(arg1)");
 classes:
          "cB1_$(class_uid)" expression => "any";

}

This way, each each time bundle  B is called, internal classes have  new names. 
   
This does not seem very elegant to me. Is there is a better way ?

Q2)
Classes scope
It seems that classes are only visible in the bundle that defines them. In the 
example above, bundle B cannot see classe cA1 defined in bundle A and bundle A 
cannot see classe cB1 defined in B. This is a pity, as classes would be a great 
way to enable communication between bundle, especially between a bundle and the 
sub-bundles it calls, for example to "return" a status of the sub-bundle 
execution.

Is this use of sub-bunldes in contradiction withn CF philosophy (that is, there 
should not be "comunication" between bundles and sub-bundles), or I have missed 
something (that is, is there a way to "communicate" classes between bundles)?  

Incidentally, sub-bundle B can undefine classes defined in A, with the 
cancel_xxx attribute of the classes promise body. Using this fact, this is the 
only way I managed to set up a communication between  A and B. for instance:


bundle agent A {

classes:

          "file_nok" expression => "any";

methods:
       
           "foo"  usebundle => B("file1", "file_nok");

reports:
           file_nok::
                "ERROR";
           !file_nok::
                "OK";
}  


bundle agent B(file, nok_klass)  {

 vars:
          "params_left" int => countlinesmatching("XXX.*", "$(file)");

classes:
          error expression => isgreaterthan("$(params_left)", "0");
  
reports:
          error::
             "There is still some parameters left uninstanciated in the fiel 
$(file)";
          !error::
             ""
             classes => undefine("$(nok_klass)");

}

body classes undefine(klass)
{
 cancel_kept => {"$(klass)"};
 cancel_repaired => {"$(klass)"};
 }



The logic is this one: bundle B is used to verify files. Bundle A define an 
error class, that will be undefined by the bundle B if 
the file given in argument is ok. Then bundle A will report accordingly. 

Is this cancellation possibility a bug or a permanent feature?
It works, but this kind of "negative logic" is a bit clumsy to use. Is there a 
better way ?

Thanks for your help.

Regards

Yann rouxel

_______________________________________________
Help-cfengine mailing list
Help-cfengine@cfengine.org
https://cfengine.org/mailman/listinfo/help-cfengine

Reply via email to