[BUG] (or by design?) form_spec MonitoredHost doesn't work as expected

Checkmk version: 2.3.0p36.cee

I am trying to use the “form_spec MonitoredHost” in a rule set. The goal is to create a list of hosts and avoid empty entries in the list. This should be achieved with the following code (I think):

'HOST_LIST': DictElement(
    parameter_form=List(
        title=Title('Host List'),
        element_template=MonitoredHost(
            custom_validate=(LengthInRange(
                min_value=1,
                error_msg=Message('Field can not be empty')),
            ),
        ),
    ))

Unfortunately, nothing happens. When I try this with my own custom validation on the MonitoredHost, nothing happens either (even if the validation is configured to always throw an exception).

class ValidateMonitoredHost:
    def __init__(self, error_msg: Message | None = None) -> None:
        self.error_msg: Final = error_msg or (Message("Host can not be empty."))

    def __call__(self, value: str) -> None:
        raise ValidationError(self.error_msg)


'HOST_LIST': DictElement(
    parameter_form=List(
        title=Title('Host List'),
        element_template=MonitoredHost(
            custom_validate=(ValidateMonitoredHost(),),
        ),
    )),

It works at the List level. But then I encounter a new problem: The triggered exception clears (empties) ALL MonitoredHost fields, even in completely unrelated parts of the rule set :frowning:

class ValidateMonitoredHostList:
    def __init__(self, error_msg: Message | None = None) -> None:
        self.error_msg: Final = error_msg or (Message("Host list can not contain empty fields."))

    def __call__(self, value: Sequence[str]) -> None:
        if any(len(entry) == 0 for entry in value):
            raise ValidationError(self.error_msg)
            

'HOST_LIST': DictElement(
    parameter_form=List(
        title=Title('Host List'),
        custom_validate=(ValidateMonitoredHostList(),),
        element_template=MonitoredHost(),
    ))

So how can I create a list of monitored host in WATO without empty entrys?

Cheers
Thomas

PS: This also happens with MontoredServices.

This is the only code i found using the “MonitoredHost” with validation.

                                "match_hosts": DictElement(
                                    parameter_form=ListOfStrings(
                                        title=Title("Hosts"),
                                        string_spec=MonitoredHost(),
                                        custom_validate=[
                                            not_empty(
                                                error_msg=Message("Please add at least one host.")
                                            )
                                        ],
                                    ),
                                ),

The “not_empty” is only a predefined “LengthInRange” with some parameters.

It from this file.

I see, unfortunately, here the validation is not on the MonitoredHost but on the List (a bit like my last example, only here it checks for an empty list only - not for empty hosts) :frowning:

Did a bit digging my self:
MonitoredHosts is just a FormSepc with a different name (at least from this piece of code)

@dataclass(frozen=True, kw_only=True)
class MonitoredHost(FormSpec[str]):
    """Specifies a form selecting from a list of hosts configured in Checkmk"""

And here is the parent FormSepc (I just removed most of the comments). Nothing special either, except that it defines the custom_validate property. This should then also be available in the MonitoredHost form_spec. What I haven’t found yet is where (in the code) the validation function gets called :frowning:

ModelT = TypeVar("ModelT")

@dataclass(frozen=True, kw_only=True)
class FormSpec(Generic[ModelT]):
    """Common base class for FormSpecs.

    This encapsulates some properties that all form specs have in common.
    Even if the ``migrate`` and ``custom_validate`` arguments do not always
    make sense, all form specs have them for consistency.

    """

    title: Title | None = None
    """A human readable title."""
    help_text: Help | None = None
    """Description to help the user with the configuration."""
    migrate: Callable[[object], ModelT] | None = None
    """A function to change the value every time it is loaded into the form spec....
    """

    custom_validate: Sequence[Callable[[ModelT], object]] | None = None
    """Optional additional validators.

    After the validation of the specific form spec is successful, these function are executed.
    They must raise a ValidationError in case validation fails.
    The return value of the functions will not be used.
    """

Hi Thomas,

The triggered exception clears (empties) ALL MonitoredHost fields, even in completely unrelated parts of the rule set

I’ve just checked this part of the code. This bug is at least 4 years old, maybe a few years more..
The problem here is that MonitoredHost/MonitoredService uses Autocompleter input fields. (AjaxDropdownChoice)
These fields are unable to provide a list of valid choices in the complain phase. Reason: Its complicated…

I don’t think that I should dare to fix this bug. It might introduce some side effects.
Starting with 2.5 we will render the form specs as real form specs within our new VUE framework. This will make the problem disappear.

The problem with the missing validation errors will be dealt with by someone who is more knowledgeable/competent in this area.

Regards
Andreas

Hi Andreas,

thanks for the update. If I understand you right Werk #18966 will fix the missing validator of MonitoredHost/MonitoredService but not the clear all MonitoredHost fields if an validator is triggered, or not?

Cheers
Thomas

Yep

“Post must be a least 20 characters”

That’s a pity. I’ll test with 2.4.0p17 to see what really works…

@schnetz, @Rebekka
I tested what now works with 2.4.0p17. Yes, input validation for MonitoredHost/MonitoredService now works. Unfortunately, you cannot use it because you will lose all configured MonitoredHost/MonitoredService data if you run into any input data violation. The other option would be use no input validation at all in rules with MonitoredHost/MonitoredService form specs. As this might lead to inproper configured rules, this is also no good option.

Meaning without fixing

the first fix is of no use (to me) :frowning:

but thanks for looking into it
Thomas