icinga

Icinga2 API client in Go
git clone https://git.olowe.co/icinga
Log | Files | Refs | README | LICENSE

commit 9ffce56b80990611dbb20ba6c4af4df4f9846140
parent 64e18a8d1ef9f178f91aed840a371f3785c4d188
Author: Oliver Lowe <o@olowe.co>
Date:   Wed, 26 Jan 2022 16:54:32 +1100

Properly encode spaces in filter expressions

This is a bit tricky. url.QueryEscape() encodes spaces in queries as
"+", but Icinga2 wants them as "%20".
A test case is included because this was kinda tricky to debug.

Diffstat:
Mhttp.go | 14+++++++++++---
Ahttp_test.go | 13+++++++++++++
Micinga_test.go | 2+-
3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/http.go b/http.go @@ -5,6 +5,7 @@ import ( "io" "net/http" "net/url" + "strings" ) const versionPrefix = "/v1" @@ -29,15 +30,22 @@ func NewRequest(method, url, username, password string, body io.Reader) (*http.R return req, nil } +// filterEncode url-encodes the filter expression expr in the required +// format to be included in a request. Notably, spaces need to be encoded +// as "%20", not "+" as returned by the url package. +func filterEncode(expr string) string { + v := url.Values{} + v.Set("filter", expr) + return strings.ReplaceAll(v.Encode(), "+", "%20") +} + func (c *Client) get(path, filter string) (*http.Response, error) { u, err := url.Parse("https://" + c.addr + versionPrefix + path) if err != nil { return nil, err } if filter != "" { - v := url.Values{} - v.Set("filter", filter) - u.RawQuery = v.Encode() + u.RawQuery = filterEncode(filter) } req, err := NewRequest(http.MethodGet, u.String(), c.username, c.password, nil) if err != nil { diff --git a/http_test.go b/http_test.go @@ -0,0 +1,13 @@ +package icinga + +import "testing" + +func TestFilterEncode(t *testing.T) { + expr := `match("*.example.com"), host.name) && "test" in host.groups` + want := "filter=match%28%22%2A.example.com%22%29%2C%20host.name%29%20%26%26%20%22test%22%20in%20host.groups" + got := filterEncode(expr) + if want != got { + t.Fail() + } + t.Logf("want %s, got %s", want, got) +} diff --git a/icinga_test.go b/icinga_test.go @@ -200,6 +200,6 @@ func TestNonExistentService(t *testing.T) { if err == nil { t.Fail() } - t.Logf("lookup %s: %v", name, err) + t.Log(err) t.Logf("%+v", service) }