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
[email protected]
https://cfengine.org/mailman/listinfo/help-cfengine