Help with filters, please

Forgive me if I ask something that is too obvious. I have tried searching, but I don’t seem to find the docs I need. I’m trying to write a specific query, using a filter, but I can’t seem to get it right. This is what I want to achieve - I have a the same check, check_fs, running on a number of systems, and I want to get a list of the ones that are critical. I know how to find all services that are critical, but I want to find just the ones that match ‘check_fs’. I tried with:

curl -k -s -u mickey:mouse 'https://zenoss.hpc.ic.ac.uk:5665/v1/objects/services?filter=service.state==2&filter=match("*!check_fs",service.name)'
<h1>Bad Request</h1><p><pre>Invalid URL Query</pre></p>

And in fact, when I try the example in https://icinga.com/docs/icinga2/latest/doc/12-icinga2-api/#filters:

curl -k -s -u toot:TheresATrainsaComin 'https://zenoss.hpc.ic.ac.uk:5665/v1/objects/hosts?filter=match("cx1-100*",host.name)'
<h1>Bad Request</h1><p><pre>Invalid URL Query</pre></p>

Clearly, I’m not getting it right. Where do I get it wrong? And leading on from that, is there a document, page, tutorial that explains filters and joins in more detail?

Hi,

Url parameters need to be encoded, this includes special characters. Since this is not really a reliable way with advanced filters, we generally recommend to use X-HTTP-Method-Override: GET with a POST request. A POST request allows to send a request body while GET does not (by RFC).

By putting the filter key and value into a JSON body, you don’t need to urlencode things. Just ensure that it is valid JSON :slight_smile:

Also the initial query is not correct, you cannot pass the filter param two times or more. It needs to be a combined filter string with logical operators.

curl -k -s -u mickey:mouse -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST \
 'https://zenoss.hpc.ic.ac.uk:5665/v1/objects/services' \
 -d '{ "filter": "service.state==2 && match(\"*check_fs\",service.name)" }'

Also possible - filter vars, with just binding the values into the filter function defined. That avoids the additional quote escaping, and also can serve for programmatic ways - the filter parameter always is the same, only the filter_vars are modified for different API calls.

curl -k -s -u mickey:mouse -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST \
 'https://zenoss.hpc.ic.ac.uk:5665/v1/objects/services' \
 -d '{ "filter": "service.state==state && match(pattern,service.name)", "filter_vars": { "state": 2, "pattern": "*check_fs" } }'

Cheers,
Michael

1 Like

Thanks, as so many times before, that fixed my problem.

However, I want to put this into some python code, but it is teasing me:

$ cat icinga_report
#!/usr/bin/python

import requests
import json
import sys

if len(sys.argv)==3:
    state=int(sys.argv[1])
    service=sys.argv[2]
else:
    print 'Usage: icinga_report state service'
    sys.exit()

hdr={
    'Accept':'application/json',
    'X-HTTP-Method-Override':'GET'
}
aut=(
    'mickey',
    'mouse'
)   
url='https://zenoss.hpc.imperial.ac.uk:5665/v1/objects/services'
dat={
    'filter':'service.state==state && match(pattern,service.name)',
    'filter_vars':{
        'state':int('%d'%state),
        'pattern':'*%s'%service
    }
}

res=requests.post(
    url,
    headers=hdr,
    auth=aut,
    data=json.dumps(dat)
)

print res

This gives the following result:

$ ./icinga_report 2 checkmem
<Response [200]>

So, it works fine, but how do I get it to return the actual results?

res is an object returned from requests.post, and has certain getters and attributes. Examples on accessing them can be found in the docs for the Python example.

In fact, the REST API is something where I am one of the architects, this comes purely from our brains. It’s usage began to differ a bit from what we’ve designed and documented, especially that people would better adopt JSON encoded bodies than other things in the URL.

Helping users in here provides me with ideas to write howtos, or improve the documentation. Not everything will be documented though, there should always be room for discussions and own inspiration to try things out. Still, everything I’ll explain 10 times, gets documented sooner or later. The Url vs Body thing is one of them.

For now, I’ve revamped the docs a bit for 2.11 later this year: https://github.com/Icinga/icinga2/pull/7115

Cheers,
Michael

Sorry, you must think I’m really lazy; thank you for taking the time to reply, I really appreciate it. I’ll go and download the docs and study them. The API is one of the major strengths of icinga, I find - I’m also instrigued by the joins, although I still haven’t had time to study this at all.

1 Like

Hi,

no, I don’t think you are lazy. The thing is, when you don’t understand certain parts, others may struggle as well. Especially with the filter parts, this can become overly complex, even for the simplest questions. Since not everyone is a programmer, the docs should provide the simple steps but also the advanced ones.

Recently I’ve added a Golang client example, because that’s something I’ve learned in the past years. Powershell is on my list, making it easier for agents to send passive external check results.

And so that’s a learning curve for everyone :slight_smile:

Cheers,
Michael

Thank you for your kind of words. I think, about the filters, for a feature s powerful as that, it deserves a lot of good documentation. Some examples, of course, but for me, I would like to understand it more in depth, so also a reference to all keywords, operators, etc, and perhaps even something that goes into the ‘history’ and the thinking behind the way it works.

Actually, I have been a developer for nearly 30 years, but I haver seen Golang. Ah for the days of FORTRAN and COBOL…

1 Like

Well, that’s kind of a lego technic game here - the API filters use the same expression language as you know from assign where and this in turn again is everything you have within the DSL, documented inside the library and language reference chapters.

Agreed, this is very complex and hard to figure out. Our goal always was and is - don’t duplicate details if not essentially necessary. I know from certain feedback that also those reference chapters would need more details, and better usage examples. Still, I prefer to have community members asking questions and coming from this, one can find the best real world examples.

That being said, if you find out more about really cool filters, and language specifics, don’t hesitate to propose changes to the documentation. PRs on GitHub are always welcome, and the docs written in Markdown can be edited in nearly any editor these days, even on GitHub itself.

I know about Fortran and Cobol, but actually my first language was Turbo Pascal. The first real language where I created projects with, was C++ and VHDL though :slight_smile:

Cheers,
Michael