Alerting: Support up to N fake images (#51111)

This commit is contained in:
George Robinson 2022-06-20 14:34:53 +01:00 committed by GitHub
parent e889dfdc5c
commit 18c3456d13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 46 deletions

View File

@ -27,7 +27,7 @@ func TestSensuGoNotifier(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
tmpl.ExternalURL = externalURL tmpl.ExternalURL = externalURL
images := newFakeImageStore() images := newFakeImageStore(2)
cases := []struct { cases := []struct {
name string name string
@ -44,7 +44,7 @@ func TestSensuGoNotifier(t *testing.T) {
{ {
Alert: model.Alert{ Alert: model.Alert{
Labels: model.LabelSet{"__alert_rule_uid__": "rule uid", "alertname": "alert1", "lbl1": "val1"}, Labels: model.LabelSet{"__alert_rule_uid__": "rule uid", "alertname": "alert1", "lbl1": "val1"},
Annotations: model.LabelSet{"ann1": "annv1", "__dashboardUid__": "abcd", "__panelId__": "efgh", "__alertScreenshotToken__": "test-image"}, Annotations: model.LabelSet{"ann1": "annv1", "__dashboardUid__": "abcd", "__panelId__": "efgh", "__alertScreenshotToken__": "test-image-1"},
}, },
}, },
}, },
@ -59,7 +59,7 @@ func TestSensuGoNotifier(t *testing.T) {
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
"name": "default", "name": "default",
"labels": map[string]string{ "labels": map[string]string{
"imageURL": "https://www.example.com/test-image.jpg", "imageURL": "https://www.example.com/test-image-1.jpg",
"ruleURL": "http://localhost/alerting/list", "ruleURL": "http://localhost/alerting/list",
}, },
}, },
@ -87,7 +87,7 @@ func TestSensuGoNotifier(t *testing.T) {
{ {
Alert: model.Alert{ Alert: model.Alert{
Labels: model.LabelSet{"__alert_rule_uid__": "rule uid", "alertname": "alert1", "lbl1": "val1"}, Labels: model.LabelSet{"__alert_rule_uid__": "rule uid", "alertname": "alert1", "lbl1": "val1"},
Annotations: model.LabelSet{"ann1": "annv1", "__alertScreenshotToken__": "test-image"}, Annotations: model.LabelSet{"ann1": "annv1", "__alertScreenshotToken__": "test-image-1"},
}, },
}, { }, {
Alert: model.Alert{ Alert: model.Alert{
@ -107,7 +107,7 @@ func TestSensuGoNotifier(t *testing.T) {
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
"name": "grafana_rule_0", "name": "grafana_rule_0",
"labels": map[string]string{ "labels": map[string]string{
"imageURL": "https://www.example.com/test-image.jpg", "imageURL": "https://www.example.com/test-image-1.jpg",
"ruleURL": "http://localhost/alerting/list", "ruleURL": "http://localhost/alerting/list",
}, },
}, },

View File

@ -3,6 +3,7 @@ package channels
import ( import (
"context" "context"
"encoding/base64" "encoding/base64"
"fmt"
"os" "os"
"testing" "testing"
"time" "time"
@ -11,10 +12,6 @@ import (
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models" ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
) )
// deleteFunc deletes the fake image.
// nolint:unused
type deleteFunc func()
type fakeImageStore struct { type fakeImageStore struct {
Images []*ngmodels.Image Images []*ngmodels.Image
} }
@ -29,63 +26,79 @@ func (f *fakeImageStore) GetImage(_ context.Context, token string) (*ngmodels.Im
return nil, ngmodels.ErrImageNotFound return nil, ngmodels.ErrImageNotFound
} }
// newFakeImageStore returns an image store with a test image. // newFakeImageStore returns an image store with N test images.
// The image has a token and a URL, but does not have a file on disk. // Each image has a token and a URL, but does not have a file on disk.
func newFakeImageStore() ImageStore { func newFakeImageStore(n int) ImageStore {
return &fakeImageStore{ s := fakeImageStore{}
Images: []*ngmodels.Image{ for i := 0; i < n; i++ {
{ s.Images = append(s.Images, &ngmodels.Image{
Token: "test-image", Token: fmt.Sprintf("test-image-%d", i),
URL: "https://www.example.com/test-image.jpg", URL: fmt.Sprintf("https://www.example.com/test-image-%d.jpg", 1),
CreatedAt: time.Now().UTC(), CreatedAt: time.Now().UTC(),
}, })
},
} }
return &s
} }
// newFakeImageStoreWithFile returns an image store with a test image. // newFakeImageStoreWithFile returns an image store with N test images.
// The image has a token, path and a URL, where the path is 1x1 transparent // Each image has a token, path and a URL, where the path is 1x1 transparent
// PNG on disk. The test should call deleteFunc to delete the image from disk // PNG on disk. The test should call deleteFunc to delete the images from disk
// at the end of the test. // at the end of the test.
// nolint:deadcode,unused // nolint:deadcode,unused
func newFakeImageStoreWithFile(t *testing.T) (ImageStore, deleteFunc) { func newFakeImageStoreWithFile(t *testing.T, n int) ImageStore {
var (
files []string
s fakeImageStore
)
t.Cleanup(func() {
// remove all files from disk
for _, f := range files {
if err := os.Remove(f); err != nil {
t.Logf("failed to delete file: %s", err)
}
}
})
for i := 0; i < n; i++ {
file, err := newTestImage()
if err != nil {
t.Fatalf("failed to create test image: %s", err)
}
files = append(files, file)
s.Images = append(s.Images, &ngmodels.Image{
Token: fmt.Sprintf("test-image-%d", i),
Path: file,
URL: fmt.Sprintf("https://www.example.com/test-image-%d", i),
CreatedAt: time.Now().UTC(),
})
}
return &s
}
// nolint:deadcode,unused
func newTestImage() (string, error) {
f, err := os.CreateTemp("", "test-image-*.png") f, err := os.CreateTemp("", "test-image-*.png")
if err != nil { if err != nil {
t.Fatalf("failed to create temp image: %s", err) return "", fmt.Errorf("failed to create temp image: %s", err)
} }
// 1x1 transparent PNG // 1x1 transparent PNG
b, err := base64.StdEncoding.DecodeString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=") b, err := base64.StdEncoding.DecodeString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=")
if err != nil { if err != nil {
t.Fatalf("failed to decode PNG data: %s", err) return f.Name(), fmt.Errorf("failed to decode PNG data: %s", err)
} }
if _, err := f.Write(b); err != nil { if _, err := f.Write(b); err != nil {
t.Fatalf("failed to write to file: %s", err) return f.Name(), fmt.Errorf("failed to write to file: %s", err)
} }
if err := f.Close(); err != nil { if err := f.Close(); err != nil {
t.Fatalf("failed to close file: %s", err) return f.Name(), fmt.Errorf("failed to close file: %s", err)
} }
fn := func() { return f.Name(), nil
if err := os.Remove(f.Name()); err != nil {
t.Fatalf("failed to delete file: %s", err)
}
}
store := &fakeImageStore{
Images: []*ngmodels.Image{
{
Token: "test-image",
Path: f.Name(),
URL: "https://www.example.com/test-image.jpg",
CreatedAt: time.Now().UTC(),
},
},
}
return store, fn
} }
// mockTimeNow replaces function timeNow to return constant time. // mockTimeNow replaces function timeNow to return constant time.