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