mirror of
https://github.com/prymitive/karma
synced 2026-05-05 03:16:51 +00:00
Fixes #190. With this feature unsee can be configured to proxy requests to selected Alertmanager instances, if it's enabled unsee silence form will send a request via unsee rather than directly. This allows users to manage silences in environments where they have access to unsee but not to Alertmanager. Only silences endpoints on Alertmanager API are proxied.
122 lines
3.4 KiB
Go
122 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/cloudflare/unsee/internal/alertmanager"
|
|
|
|
httpmock "gopkg.in/jarcoal/httpmock.v1"
|
|
)
|
|
|
|
// httptest.NewRecorder() doesn't implement http.CloseNotifier
|
|
type closeNotifyingRecorder struct {
|
|
*httptest.ResponseRecorder
|
|
closed chan bool
|
|
}
|
|
|
|
func newCloseNotifyingRecorder() *closeNotifyingRecorder {
|
|
return &closeNotifyingRecorder{
|
|
httptest.NewRecorder(),
|
|
make(chan bool, 1),
|
|
}
|
|
}
|
|
|
|
func (c *closeNotifyingRecorder) close() {
|
|
c.closed <- true
|
|
}
|
|
|
|
func (c *closeNotifyingRecorder) CloseNotify() <-chan bool {
|
|
return c.closed
|
|
}
|
|
|
|
type proxyTest struct {
|
|
method string
|
|
localPath string
|
|
upstreamURI string
|
|
code int
|
|
response string
|
|
}
|
|
|
|
var proxyTests = []proxyTest{
|
|
// valid alertmanager and methods
|
|
proxyTest{
|
|
method: "POST",
|
|
localPath: "/proxy/alertmanager/dummy/api/v1/silences",
|
|
upstreamURI: "http://localhost:9093/api/v1/silences",
|
|
code: 200,
|
|
response: "{\"status\":\"success\",\"data\":{\"silenceId\":\"d8a61ca8-ee2e-4076-999f-276f1e986bf3\"}}",
|
|
},
|
|
proxyTest{
|
|
method: "DELETE",
|
|
localPath: "/proxy/alertmanager/dummy/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
|
|
upstreamURI: "http://localhost:9093/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
|
|
code: 200,
|
|
response: "{\"status\":\"success\"}",
|
|
},
|
|
// invalid alertmanager name
|
|
proxyTest{
|
|
method: "POST",
|
|
localPath: "/proxy/alertmanager/INVALID/api/v1/silences",
|
|
upstreamURI: "",
|
|
code: 404,
|
|
response: "404 page not found",
|
|
},
|
|
proxyTest{
|
|
method: "DELETE",
|
|
localPath: "/proxy/alertmanager/INVALID/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
|
|
upstreamURI: "http://localhost:9093/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
|
|
code: 404,
|
|
response: "404 page not found",
|
|
},
|
|
// valid alertmanager name, but invalid method
|
|
proxyTest{
|
|
method: "GET",
|
|
localPath: "/proxy/alertmanager/dummy/api/v1/silences",
|
|
upstreamURI: "",
|
|
code: 404,
|
|
response: "404 page not found",
|
|
},
|
|
proxyTest{
|
|
method: "GET",
|
|
localPath: "/proxy/alertmanager/dummy/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
|
|
upstreamURI: "http://localhost:9093/api/v1/silence/d8a61ca8-ee2e-4076-999f-276f1e986bf3",
|
|
code: 404,
|
|
response: "404 page not found",
|
|
},
|
|
}
|
|
|
|
func TestProxy(t *testing.T) {
|
|
r := ginTestEngine()
|
|
setupRouterProxyHandlers(r, &alertmanager.Alertmanager{
|
|
URI: "http://localhost:9093",
|
|
Timeout: time.Second * 5,
|
|
Name: "dummy",
|
|
ProxyRequests: true,
|
|
})
|
|
|
|
httpmock.Activate()
|
|
defer httpmock.DeactivateAndReset()
|
|
|
|
for _, testCase := range proxyTests {
|
|
httpmock.Reset()
|
|
if testCase.upstreamURI != "" {
|
|
httpmock.RegisterResponder(testCase.method, testCase.upstreamURI, httpmock.NewStringResponder(testCase.code, testCase.response))
|
|
}
|
|
req, _ := http.NewRequest(testCase.method, testCase.localPath, nil)
|
|
resp := newCloseNotifyingRecorder()
|
|
r.ServeHTTP(resp, req)
|
|
if resp.Code != testCase.code {
|
|
t.Errorf("%s %s proxied to %s returned status %d while %d was expected",
|
|
testCase.method, testCase.localPath, testCase.upstreamURI, resp.Code, testCase.code)
|
|
}
|
|
body := resp.Body.String()
|
|
if body != testCase.response {
|
|
t.Errorf("%s %s proxied to %s returned content '%s' while '%s' was expected",
|
|
testCase.method, testCase.localPath, testCase.upstreamURI, body, testCase.response)
|
|
}
|
|
}
|
|
}
|