fix(backend): simplify version probes

This commit is contained in:
Łukasz Mierzwa
2020-10-30 16:51:59 +00:00
committed by Łukasz Mierzwa
parent 6d2092f2b7
commit 6a67d5ba8e
10 changed files with 204 additions and 60 deletions

View File

@@ -97,10 +97,6 @@ func handlePostRequest(alertmanager *alertmanager.Alertmanager, h http.Handler)
}
ver := alertmanager.Version()
if ver == "" {
ver = "999.0"
}
m, err := mapper.GetSilenceMapper(ver)
if err != nil {
log.Error().Err(err).

View File

@@ -2,6 +2,7 @@ package main
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"net/http"
@@ -378,15 +379,7 @@ func TestProxyUserRewrite(t *testing.T) {
{ "isRegex": false, "name": "alertname", "value": "Fake Alert" },
{ "isRegex": true, "name": "foo", "value": "(bar|baz)" }
]}`,
proxyRequestBody: `{
"comment": "comment",
"createdBy": "username",
"startsAt": "2000-02-01T00:00:00.000Z",
"endsAt": "2000-02-01T00:02:03.000Z",
"matchers": [
{ "isRegex": false, "name": "alertname", "value": "Fake Alert" },
{ "isRegex": true, "name": "foo", "value": "(bar|baz)" }
]}`,
proxyRequestBody: `{"comment":"comment","createdBy":"","endsAt":"2000-02-01T00:02:03.000Z","matchers":[{"isRegex":false,"name":"alertname","value":"Fake Alert"},{"isRegex":true,"name":"foo","value":"(bar|baz)"}],"startsAt":"2000-02-01T00:00:00.000Z"}`,
},
{
name: "basicAuth, correct credentials, invalid JSON",
@@ -513,6 +506,7 @@ func TestProxyUserRewrite(t *testing.T) {
t.Logf("Testing alerts using mock files from Alertmanager %s", version)
config.Config.Listen.Prefix = "/"
config.Config.Authentication.Enabled = true
config.Config.Authentication.Header.Name = testCase.headerName
config.Config.Authentication.Header.ValueRegex = testCase.headerRe
config.Config.Authentication.BasicAuth.Users = testCase.basicAuthUsers
@@ -1215,3 +1209,106 @@ func TestProxySilenceACL(t *testing.T) {
})
}
}
type errReader int
func (errReader) Read(p []byte) (n int, err error) {
return 0, errors.New("request read error")
}
func TestProxyRequestReadFailure(t *testing.T) {
for _, version := range mock.ListAllMocks() {
t.Logf("Testing alerts using mock files from Alertmanager %s", version)
config.Config.Listen.Prefix = "/"
config.Config.Authentication.Header.Name = ""
config.Config.Authentication.BasicAuth.Users = []config.AuthenticationUser{}
r := testRouter()
setupRouter(r)
am, err := alertmanager.NewAlertmanager(
"cluster",
"proxyRead",
"http://localhost",
alertmanager.WithRequestTimeout(time.Second*5),
alertmanager.WithProxy(true),
)
if err != nil {
t.Error(err)
}
setupRouterProxyHandlers(r, am)
req := httptest.NewRequest("POST", "/proxy/alertmanager/proxyRead/api/v2/silences", errReader(0))
resp := newCloseNotifyingRecorder()
r.ServeHTTP(resp, req)
if resp.Code != 500 {
t.Errorf("Got response code %d instead of 500", resp.Code)
}
gotBody, _ := ioutil.ReadAll(resp.Body)
if string(gotBody) != "request read error\n" {
t.Errorf("Body mismatch:\n%s", gotBody)
}
}
}
func TestProxyRequestToUnsupportedAlertmanager(t *testing.T) {
zerolog.SetGlobalLevel(zerolog.FatalLevel)
httpmock.Activate()
defer httpmock.DeactivateAndReset()
config.Config.Listen.Prefix = "/"
config.Config.Authentication.Header.Name = ""
config.Config.Authentication.BasicAuth.Users = []config.AuthenticationUser{}
r := testRouter()
setupRouter(r)
am, err := alertmanager.NewAlertmanager(
"cluster",
"proxyToUnsupported",
"http://localhost",
alertmanager.WithRequestTimeout(time.Second*5),
alertmanager.WithProxy(true),
)
if err != nil {
t.Error(err)
}
setupRouterProxyHandlers(r, am)
apiCache = cache.New(cache.NoExpiration, 10*time.Second)
httpmock.Reset()
httpmock.RegisterResponder("GET", "http://localhost/metrics", httpmock.NewStringResponder(200, `alertmanager_build_info{version="0.1.0"} 1
`))
httpmock.RegisterResponder("GET", "http://localhost/api/v2/status", httpmock.NewStringResponder(200, `{
"cluster": {
"name": "BBBBBBBBBBBBBBBBBBBBBBBBBB",
"peers": [],
"status": "ready"
}
}`))
httpmock.RegisterResponder("POST", "http://localhost/api/v2/silences", httpmock.NewStringResponder(200, "{}"))
httpmock.RegisterResponder("GET", "http://localhost/api/v2/silences", httpmock.NewStringResponder(200, "[]"))
httpmock.RegisterResponder("GET", "http://localhost/api/v2/alerts/groups", httpmock.NewStringResponder(200, "[]"))
_ = am.Pull()
if ver := am.Version(); ver != "0.1.0" {
t.Errorf("Got wrong version: %q", ver)
return
}
req := httptest.NewRequest("POST", "/proxy/alertmanager/proxyToUnsupported/api/v2/silences", ioutil.NopCloser(bytes.NewBufferString(`{}`)))
resp := newCloseNotifyingRecorder()
r.ServeHTTP(resp, req)
if resp.Code != 500 {
t.Errorf("Got response code %d instead of 500", resp.Code)
}
gotBody, _ := ioutil.ReadAll(resp.Body)
if string(gotBody) != "can't find silence mapper for Alertmanager 0.1.0\n" {
t.Errorf("Body mismatch:\n%s", gotBody)
}
}

View File

@@ -1113,12 +1113,14 @@ func TestUpstreamStatus(t *testing.T) {
{
uri: "http://ha1.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.20.0"} 1`,
body: `alertmanager_build_info{version="0.20.0"} 1
`,
},
{
uri: "http://ha2.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.19.0"} 1`,
body: `alertmanager_build_info{version="0.19.0"} 1
`,
},
{
uri: "http://ha1.example.com/api/v2/status",
@@ -1256,12 +1258,14 @@ func TestUpstreamStatus(t *testing.T) {
{
uri: "http://ha1.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.20.0"} 1`,
body: `alertmanager_build_info{version="0.20.0"} 1
`,
},
{
uri: "http://ha2.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.19.0"} 1`,
body: `alertmanager_build_info{version="0.19.0"} 1
`,
},
{
uri: "http://ha1.example.com/api/v2/status",
@@ -1397,12 +1401,14 @@ func TestUpstreamStatus(t *testing.T) {
{
uri: "http://ha1.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.20.0"} 1`,
body: `alertmanager_build_info{version="0.20.0"} 1
`,
},
{
uri: "http://ha2.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.19.0"} 1`,
body: `alertmanager_build_info{version="0.19.0"} 1
`,
},
{
uri: "http://ha1.example.com/api/v2/status",
@@ -1532,12 +1538,14 @@ func TestUpstreamStatus(t *testing.T) {
{
uri: "http://ha1.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.20.0"} 1`,
body: `alertmanager_build_info{version="0.20.0"} 1
`,
},
{
uri: "http://ha2.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.19.0"} 1`,
body: `alertmanager_build_info{version="0.19.0"} 1
`,
},
{
uri: "http://ha1.example.com/api/v2/status",
@@ -1666,12 +1674,14 @@ func TestUpstreamStatus(t *testing.T) {
{
uri: "http://broken1.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.20.0"} 1`,
body: `alertmanager_build_info{version="0.20.0"} 1
`,
},
{
uri: "http://broken2.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.20.0"} 1`,
body: `alertmanager_build_info{version="0.20.0"} 1
`,
},
{
uri: "http://broken1.example.com/api/v2/status",
@@ -1812,7 +1822,8 @@ func TestUpstreamStatus(t *testing.T) {
{
uri: "http://ha2.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.21.0"} 1`,
body: `alertmanager_build_info{version="0.21.0"} 1
`,
},
{
uri: "http://ha1.example.com/api/v2/status",
@@ -1922,7 +1933,7 @@ func TestUpstreamStatus(t *testing.T) {
Headers: map[string]string{},
CORSCredentials: "omit",
Error: "",
Version: "0.20.0",
Version: "",
Cluster: "Errors",
ClusterMembers: []string{"ha1", "ha2"},
},
@@ -1934,7 +1945,7 @@ func TestUpstreamStatus(t *testing.T) {
Headers: map[string]string{},
CORSCredentials: "omit",
Error: "json: cannot unmarshal array into Go value of type string",
Version: "0.19.0",
Version: "0.21.0",
Cluster: "Errors",
ClusterMembers: []string{"ha1", "ha2"},
},
@@ -1950,7 +1961,8 @@ func TestUpstreamStatus(t *testing.T) {
{
uri: "http://ha1.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.20.0"} 1`,
body: `alertmanager_build_info{version="0.20.0"} 1
`,
},
{
uri: "http://ha2.example.com/metrics",
@@ -1960,7 +1972,8 @@ func TestUpstreamStatus(t *testing.T) {
{
uri: "http://single.example.com/metrics",
code: 200,
body: `alertmanager_build_info{version="0.21.0"} 1`,
body: `alertmanager_build_info{version="0.21.0"} 1
`,
},
{
uri: "http://ha1.example.com/api/v2/status",
@@ -2124,24 +2137,31 @@ func TestUpstreamStatus(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.Name, func(t *testing.T) {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
httpmock.Activate()
defer httpmock.DeactivateAndReset()
for _, m := range testCase.mocks {
httpmock.RegisterResponder("GET", m.uri, httpmock.NewStringResponder(m.code, m.body))
}
config.Config.Listen.Prefix = "/"
config.Config.Authentication.Header.Name = ""
config.Config.Authentication.BasicAuth.Users = []config.AuthenticationUser{}
apiCache = cache.New(cache.NoExpiration, 10*time.Second)
alertmanager.UnregisterAll()
mockConfig()
config.Config.Alertmanager.Servers = testCase.upstreams
err := setupUpstreams()
if err != nil {
t.Error(err)
}
zerolog.SetGlobalLevel(zerolog.FatalLevel)
pullFromAlertmanager()
r := testRouter()
setupRouter(r)
httpmock.Reset()
for _, m := range testCase.mocks {
httpmock.RegisterResponder("GET", m.uri, httpmock.NewStringResponder(m.code, m.body))
}
pullFromAlertmanager()
req := httptest.NewRequest("GET", "/alerts.json?q=@receiver=by-cluster-service&q=alertname=HTTP_Probe_Failed&q=instance=web1", nil)
resp := httptest.NewRecorder()
r.ServeHTTP(resp, req)