Hi Chris,
Right, you should not attach multiple of the same attribute to the same promise. Perhaps we should make the parser disallow it all together because it's not an expected use.
I believe this example implements what you are looking for.
We define a new classes body my_set_some_extra_fancy_classes
, it takes 3 arguments where the third argument is an additional class to set when the promise is repaired.
Note, since we are setting promise_repaired
differently in my_set_some_extra_fancy_classes
than my_set_some_fancy_classes
we have to completely re-define it.
bundle agent __main__ {
commands: "/bin/true" handle => "some meaningful string"
, classes => my_set_some_extra_fancy_classes( "$(this.promiser)", "$(this.handle)", "some_class_to_handle_dependencies" ); "/bin/false" handle => "some meaningless string", classes => my_set_some_extra_fancy_classes( "$(this.promiser)", "$(this.handle)", "some_class_to_handle_dependencies" ); } body classes my_set_some_extra_fancy_classes( x, y, z) # @breif In addition to the classes set by `set_some_fancy_classes` define `z` when the promise is repaired { inherit_from => set_some_fancy_classes( $(x), $(y) ); promise_repaired => { "some_fancy_class_${x}_${y}_repaired", $(z) };
} body classes set_some_fancy_classes ( x, y) { promise_kept => { "some_fancy_class_${x}_${y}_kept" }; promise_repaired => { "some_fancy_class_${x}_${y}_repaired" }; repair_failed => { "some_fancy_class_${x}_${y}_notkept" }; repair_denied => { "some_fancy_class_${x}_${y}_notkept" }; repair_timeout => { "some_fancy_class_${x}_${y}_notkept" }; }
# cf-agent --no-lock --log-level info --show-evaluated-classes=some_ --file example.cf info: Executing 'no timeout' ... '/bin/true' info: Completed execution of '/bin/true' info: Executing 'no timeout' ... '/bin/false' error: Finished command related to promiser '/bin/false' -- an error occurred, returned 1 info: Completed execution of '/bin/false' Class name Meta tags some_class_to_handle_dependencies some_fancy_class__bin_false_some_meaningless_string_notkept some_fancy_class__bin_true_some_meaningful_string_repaired
Here I use --show-evaluated-classes
which lists the namespace scoped classes defined at the end of the agent run filtered for those starting with some_
. We can see that both some_class_to_handle_dependencies
and some_fancy_class__bin_true_some_meaningful_string_kept
get defined.
# cf-agent --no-lock --log-level info --show-evaluated-classes=some_ --file example.cf info: Executing 'no timeout' ... '/bin/true' info: Completed execution of '/bin/true' Class name Meta tags some_class_to_handle_dependencies some_fancy_class__bin_true_some_meaningful_string_kept
Xander Cage <christia...@itsv.at> writes:
wow, this qualifies as advanced sorcery :), await the owl with the hogwarts acceptance letter.
thank you
Great, glad you found it helpful. I can take that example and include it in the docs.
Xander Cage <christia...@itsv.at> writes:
seems the two body are not playing well together.
so, any idea whats going on?
Can you make it a standalone example, I don't have itsv_reporting
.
bundle agent __main__{ methods: "b005_reporting_output_test"; }
bundle agent b005_reporting_output_test { meta: "tags" slist => { "itsv" }; commands: "/bin/true" handle => "itsv_reporting_$(this.bundle)", classes => itsv_keeper_of_the_classes( "$(this.promiser)", "$(this.handle)", itsv_TEST_WORKFLOW_CLASS ), #classes => itsv_custom_classes( "$(this.promiser)", "$(this.handle)" ), action => itsv_reporting( "$(this.handle)", "$(this.promiser)", "ITSV Cfengine", "1" ); }
body classes itsv_custom_classes ( promiser, handle ) { promise_kept => { "${promiser}_handle_${handle}_kept" }; promise_repaired => { "${promiser}_handle_${handle}_repaired" }; repair_failed => { "${promiser}_handle_${handle}_notkept" }; repair_denied => { "${promiser}_handle_${handle}_notkept" }; repair_timeout => { "${promiser}_handle_${handle}_notkept" }; } body classes itsv_keeper_of_the_classes ( promiser, handle, workflow_class) # @brief: In addition to the classes set by "itsv_custom_classes", define
# "workflow_class" when the promise is repaired.
# # mainly used for keeping already existing classes in the policys when activating reporting. # see discussion: https://groups.google.com/g/help-cfengine/c/WpDuScsMxxI { inherit_from => itsv_custom_classes( $(promiser), $(handle) ); promise_repaired => { "${workflow_class}_repaired", $(workflow_class) }; }
/home/nickanderson/org/cfengine3-kSDomr:15:0: error: Undefined body itsv_reporting with type action
Xander Cage <christia...@itsv.at> writes:
itsv_TEST_WORKFLOW_CLASS is defined twice (with and without "_repaired" prefix), which does not correlate with the your example.
body classes itsv_keeper_of_the_classes
has promise_repaired
set to "promise_repaired => { "${workflow_class}_repaired", $(workflow_class) };
" which should define both with and without the suffix in the event of a repair, or have I confused myself here?
the class ( _bin_true_handle_itsv_reporting_b005_reporting_output_test_repaired) which should be inherited from the " itsv_custom_classes" body is missing.
body classes itsv_keeper_of_the_classes
defines promise_repaired overriding whatever was inherited. You need to add that class to the list of classes defined by promise_repaired like this:
bundle agent b005_reporting_output_test { meta: "tags" slist => { "itsv" }; commands: "/bin/true" handle => "itsv_reporting_$(this.bundle)", classes => itsv_keeper_of_the_classes( "$(this.promiser)", "$(this.handle)", itsv_TEST_WORKFLOW_CLASS ), #classes => itsv_custom_classes( "$(this.promiser)", "$(this.handle)" ), action => itsv_reporting( "$(this.handle)", "$(this.promiser)", "ITSV Cfengine", "1" ); }
body action itsv_reporting ( handle, promiser, promisee, if_elapsed ) # # officially stolen and carefully extracted from neil watsons ingenious delta reporting # { ifelapsed => "${if_elapsed}"; expireafter => "${if_elapsed}"; itsv_reporting:: log_kept => "${itsvrep_c.itsv_promise_log}"; log_repaired => "${itsvrep_c.itsv_promise_log}"; log_failed => "${itsvrep_c.itsv_promise_log}"; log_string => "${handle} ;; ${promiser} ;; ${promisee}"; }
body classes itsv_custom_classes ( promiser, handle ) { promise_kept => { "${promiser}_handle_${handle}_kept" }; promise_repaired => { "${promiser}_handle_${handle}_repaired" }; repair_failed => { "${promiser}_handle_${handle}_notkept" }; repair_denied => { "${promiser}_handle_${handle}_notkept" }; repair_timeout => { "${promiser}_handle_${handle}_notkept" }; } body classes itsv_keeper_of_the_classes ( promiser, handle, workflow_class) # @brief: In addition to the classes set by "itsv_custom_classes", define
# "workflow_class" when the promise is repaired.
# # mainly used for keeping already existing classes in the policys when activating reporting. # see discussion: https://groups.google.com/g/help-cfengine/c/WpDuScsMxxI { inherit_from => itsv_custom_classes( $(promiser), $(handle) ); promise_repaired => { "${workflow_class}_repaired"
, $(workflow_class),
"${promiser}_handle_${handle}_repaired" }
; # ⊂_ヽ # \\ # \(͡°͜ʖ͡°) # > ⌒ヽ # / へ\ # / / \\ # レ ノ ヽ_つ # / / # / /| # ( (ヽ # | |、\ # | 丿 \ ⌒) # | | ) / # ノ ) Lノ # (_/
} bundle agent __main__ { methods: "b005_reporting_output_test"; }
# cf-agent --no-lock --log-level info --show-evaluated-classes=.\*itsv.\* --file example.cf info: Executing 'no timeout' ... '/bin/true' info: Completed execution of '/bin/true' Class name Meta tags _bin_true_handle_itsv_reporting_b005_reporting_output_test_repaired itsv_TEST_WORKFLOW_CLASS itsv_TEST_WORKFLOW_CLASS_repaired
Off topic, I see you are taking some things from delta reporting. classfiltercsv()
may interest you.