Hostgroup apply rules with numeric criteria

Hi,

I try to create dynamic hostgroups with apply rules which should use numeric custom host vars as selection criteria, but it does not work as expected. The var is created with datatype number, hosts contain values like 17.3 or 25. I want to put hosts into the group where val >= x and val < y.

It seems that director creates strings for vales x & y (delimited by " ") within apply rules and so the rules are not working. It also seems that the comparator <= or >= is not allowed (maybe caused by string comparisation).

The rules created look like this in preview:
assign where (host.vars.location in [ "loc1", "loc2"] && (match("server*", host.vars.host_type) || match("client*", host.vars.host_type))) || (match("client*", host.vars.host_type) && host.vars.building == "building1" && host.vars.floor > "2")

IMHO the problem are the quotation marks. I played around to convert imported data to numbers, but
I’ve found only a converter from string to integer, but not from string to float/double/…
Icinga version 2.11.2-1, Director master (snapshot from Oct. 2019)

Are there any restrictions or tricks?
Or is it a bug?

Cheers
Manfred

Hi,

I’d say it is a missing feature. There’s only a String to int property modifier, https://github.com/Icinga/icingaweb2-module-director/blob/ecf56ff1a7e9bb175e7ea6fa930b8b6ef30d3d5e/library/Director/PropertyModifier/PropertyModifierToInt.php

Without having tested this, I’d say you can add a new file in that location called PropertyModifierToFloat.php based on the Int modifier with the following content:

<?php

namespace Icinga\Module\Director\PropertyModifier;

use Icinga\Module\Director\Hook\PropertyModifierHook;

class PropertyModifierToFloat extends PropertyModifierHook
{
    public function getName()
    {
        return 'Cast a string value to a Float';
    }

    public function transform($value)
    {
        if (is_float($value)) {
            return $value;
        }

        if (is_string($value)) {
            return (float) $value;
        }
    }
}

Then you’ll edit https://github.com/Icinga/icingaweb2-module-director/blob/a554596bd877997e7a9cb64fc400d984a6464cac/register-hooks.php and register the hook like this: (+ shows the added line).

+use Icinga\Module\Director\PropertyModifier\PropertyModifierToFloat;
use Icinga\Module\Director\PropertyModifier\PropertyModifierToInt;

and

+        PropertyModifierToFloat::class,
        PropertyModifierToInt::class,

If that works for you, please put everything into a new branch and create a PR for upstream :slight_smile:

Cheers,
Michael

3 Likes

Hi Michael,

your code works perfect, it solved the problem during import from DB to Icinga. :+1:

There was one remaining problem: the generation of the apply rules did not recognise floating number, currently it only detects digit/integer. This leads to the following rules:
(host.vars.int > 7) :white_check_mark:
(host.vars.float > “7.0”) :x:

I’ve edited https://github.com/Icinga/icingaweb2-module-director/blob/a554596bd877997e7a9cb64fc400d984a6464cac/library/Director/IcingaConfig/AssignRenderer.php and changed the number detection for apply rules - hope this will not have effects for other rules generated by this code:

-   if (ctype_digit($rawExpression)) {
+   if (is_numeric($rawExpression)) {

Now it works :smiley: !

Cheers,
Manfred

1 Like