Feature Friday #32: Doing math in policy with eval()

Posted by Nick Anderson
October 18, 2024

Ever need to do some math during policy evaluation?

Sometimes configuration settings are based on available resources. For example, what if you want to calculate the size of shared buffers to be 25% of your available memory?

Let’s write some policy.

First, we need to figure out how much memory we have. Let’s parse this out from /proc/meminfo:

bundle agent __main__
{
  vars:
      "d_meminfo"
        data => data_readstringarray( "/proc/meminfo",
                                      "",
                                      "(:|\s+)",
                                      inf, inf);

  reports:
    "$(with)" with => storejson( "d_meminfo[MemTotal]" );
}
R: [
  "",
  "65505464",
  "kB"
]

So, we have 65505464 kB of memory in total. Knowing that we can use eval() to calculate what 25% is.

bundle agent __main__
{
  vars:
      "d_meminfo"
        data => data_readstringarray( "/proc/meminfo",
                                      "",
                                      "(:|\s+)",
                                      inf, inf);
      "shared_buffer_percent" string => "25";
      "calculated_shared_buffers_kB"
        string => format( "%d",
                          eval( "$(d_meminfo[MemTotal][1]) * ($(shared_buffer_percent)/100)",
                                "math", "infix"));
  reports:
    "I calculated $(calculated_shared_buffers_kB)kB should be used for shared bufferes";
}
R: I calculated 16376366kB should be used for shared bufferes

eval() can also be used to test truthfulness.

bundle agent __main__
{
  vars:
      "d_meminfo"
        data => data_readstringarray( "/proc/meminfo",
                                      "",
                                      "(:|\s+)",
                                      inf, inf);
      "shared_buffer_percent" string => "25";
      "calculated_shared_buffers_kB"
        string => format( "%d",
                          eval( "$(d_meminfo[MemTotal][1]) * ($(shared_buffer_percent)/100)",
                                "math", "infix"));
  reports:
    "I calculated $(calculated_shared_buffers_kB)kB should be used for shared bufferes";
    "$(calculated_shared_buffers_kB) is < 50% of $(d_meminfo[MemTotal][1])"
      if => eval( "$(calculated_shared_buffers_kB) < ($(d_meminfo[MemTotal][1])/2)", "class" );
    "$(calculated_shared_buffers_kB) is 25% of $(d_meminfo[MemTotal][1])"
      if => eval( "$(calculated_shared_buffers_kB) == ($(d_meminfo[MemTotal][1])/4)", "class" );
}
R: I calculated 16376366kB should be used for shared bufferes
R: 16376366 is < 50% of 65505464
R: 16376366 is 25% of 65505464

Happy Friday! 🎉