Details

Type: Knowledge acquisition

Status: Done

Priority: (None)

Resolution: Fixed

Affects Version/s: 3.12.2

Fix Version/s: 3.12.2

Component/s: Builtin functions

Labels:None
Description
The following policy does not behave in any fashion that I would expect.
body common control { bundlesequence => { main, strange, }; } bundle agent main { vars: any:: "random_number" int => randomint(1, 100); classes: any:: "number_checked_$(random_number)" scope => "namespace", expression => isgreaterthan($(random_number), 0); "number_chosen_above_50" expression => isgreaterthan($(random_number), 50); reports: any:: "Random number chosen is $(random_number)"; number_chosen_above_50:: "The number $(random_number) showed up after a number above 50"; } bundle agent strange { vars: any:: "random_high_numbers" slist => classesmatching("number_checked_.*"); reports: any:: "The numbers passed to isgreaterthan included $(random_high_numbers)"; }
Of course this is nondeterministic by nature, but the behavior of this policy cannot be understood or explained by existing documentation.
Here are some example runs:
# cfagent KIC f ./randomintdemo.cf R: Random number chosen is 25 R: The number 25 showed up after a number above 50 R: Random number chosen is 51 R: The number 51 showed up after a number above 50 R: Random number chosen is 42 R: The number 42 showed up after a number above 50 R: The numbers passed to isgreaterthan included number_checked_91 R: The numbers passed to isgreaterthan included number_checked_60 R: The numbers passed to isgreaterthan included number_checked_49
# cfagent KIC f ./randomintdemo.cf R: Random number chosen is 94 R: Random number chosen is 89 R: Random number chosen is 34 R: The numbers passed to isgreaterthan included number_checked_4 R: The numbers passed to isgreaterthan included number_checked_24 R: The numbers passed to isgreaterthan included number_checked_31
The numbers actually being passed to the isgreaterthan function are never shown by reporting on that same var. This implies that the vars promises are actually evaluated a second time in between when classes promises are evaluated and when reports promises are evaluated.
(This was encountered by someone I am teaching CFEngine policy writing to; he was playing with randomint function to understand the evaluation sequence and ended up more confused rather than understanding the documented sequence. I made the above policy as a cleaned up illustration of what he ran into.)
Attachments
Issue Links
 relates to

CFE2518 As a policy writer I would like to be able to explicitly avoid preevaluation so that the agent does not spend time on unnecessary things
 Open

CFE2168 CFEngine should log more information about what it's doing during the preevaluation stage
 Done

CFE445 cfpromises and cfagent run shell commands excessively in returnszero() execresult()
 Done