2021-09-09 11:25:22 -05:00
|
|
|
package notifier
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-11-28 08:34:45 -06:00
|
|
|
"encoding/base64"
|
2021-09-09 11:25:22 -05:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
|
|
|
|
2023-11-28 08:34:45 -06:00
|
|
|
"github.com/prometheus/alertmanager/cluster/clusterpb"
|
2021-09-09 11:25:22 -05:00
|
|
|
"github.com/stretchr/testify/require"
|
2023-10-12 07:43:10 -05:00
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/services/ngalert/tests/fakes"
|
2021-09-09 11:25:22 -05:00
|
|
|
)
|
|
|
|
|
2021-09-14 08:40:59 -05:00
|
|
|
func TestFileStore_FilepathFor_DirectoryNotExist(t *testing.T) {
|
2023-10-12 07:43:10 -05:00
|
|
|
store := fakes.NewFakeKVStore(t)
|
2021-09-14 08:40:59 -05:00
|
|
|
workingDir := filepath.Join(t.TempDir(), "notexistdir")
|
|
|
|
fs := NewFileStore(1, store, workingDir)
|
|
|
|
filekey := "silences"
|
|
|
|
filePath := filepath.Join(workingDir, filekey)
|
|
|
|
|
|
|
|
// With a file already on the database and the path does not exist yet, it creates the path,
|
|
|
|
// writes the file to disk, then returns the filepath.
|
|
|
|
{
|
|
|
|
require.NoError(t, store.Set(context.Background(), 1, KVNamespace, filekey, encode([]byte("silence1,silence3"))))
|
|
|
|
r, err := fs.FilepathFor(context.Background(), filekey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, filePath, r)
|
2022-08-10 08:37:51 -05:00
|
|
|
f, err := os.ReadFile(filepath.Clean(filePath))
|
2021-09-14 08:40:59 -05:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "silence1,silence3", string(f))
|
|
|
|
require.NoError(t, os.Remove(filePath))
|
|
|
|
require.NoError(t, store.Del(context.Background(), 1, KVNamespace, filekey))
|
|
|
|
}
|
|
|
|
}
|
2021-09-09 11:25:22 -05:00
|
|
|
func TestFileStore_FilepathFor(t *testing.T) {
|
2023-10-12 07:43:10 -05:00
|
|
|
store := fakes.NewFakeKVStore(t)
|
2021-09-09 11:25:22 -05:00
|
|
|
workingDir := t.TempDir()
|
|
|
|
fs := NewFileStore(1, store, workingDir)
|
|
|
|
filekey := "silences"
|
|
|
|
filePath := filepath.Join(workingDir, filekey)
|
|
|
|
|
|
|
|
// With a file already on disk, it returns the existing file's filepath and no modification to the original file.
|
|
|
|
{
|
|
|
|
require.NoError(t, os.WriteFile(filePath, []byte("silence1,silence2"), 0644))
|
|
|
|
r, err := fs.FilepathFor(context.Background(), filekey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, filePath, r)
|
2022-08-10 08:37:51 -05:00
|
|
|
f, err := os.ReadFile(filepath.Clean(filePath))
|
2021-09-09 11:25:22 -05:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "silence1,silence2", string(f))
|
|
|
|
require.NoError(t, os.Remove(filePath))
|
|
|
|
}
|
|
|
|
|
|
|
|
// With a file already on the database, it writes the file to disk and returns the filepath.
|
|
|
|
{
|
|
|
|
require.NoError(t, store.Set(context.Background(), 1, KVNamespace, filekey, encode([]byte("silence1,silence3"))))
|
|
|
|
r, err := fs.FilepathFor(context.Background(), filekey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, filePath, r)
|
2022-08-10 08:37:51 -05:00
|
|
|
f, err := os.ReadFile(filepath.Clean(filePath))
|
2021-09-09 11:25:22 -05:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "silence1,silence3", string(f))
|
|
|
|
require.NoError(t, os.Remove(filePath))
|
|
|
|
require.NoError(t, store.Del(context.Background(), 1, KVNamespace, filekey))
|
|
|
|
}
|
|
|
|
|
|
|
|
// With no file on disk or database, it returns the original filepath.
|
|
|
|
{
|
|
|
|
r, err := fs.FilepathFor(context.Background(), filekey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, filePath, r)
|
2022-08-10 08:37:51 -05:00
|
|
|
_, err = os.ReadFile(filepath.Clean(filePath))
|
2021-09-09 11:25:22 -05:00
|
|
|
require.Error(t, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-28 08:34:45 -06:00
|
|
|
func TestFileStore_GetFullState(t *testing.T) {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
t.Run("empty store", func(tt *testing.T) {
|
|
|
|
store := fakes.NewFakeKVStore(t)
|
|
|
|
fs := NewFileStore(1, store, workingDir)
|
|
|
|
_, err := fs.GetFullState(ctx, "silences", "notifications")
|
|
|
|
require.NotNil(tt, err)
|
|
|
|
require.Equal(tt, "no values for org 1", err.Error())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("no values for key", func(tt *testing.T) {
|
|
|
|
store := fakes.NewFakeKVStore(t)
|
|
|
|
require.NoError(t, store.Set(ctx, 1, "alertmanager", "test-key", "test-value"))
|
|
|
|
fs := NewFileStore(1, store, workingDir)
|
|
|
|
_, err := fs.GetFullState(ctx, "silences")
|
|
|
|
require.NotNil(tt, err)
|
|
|
|
require.Equal(tt, "no value found for key \"silences\"", err.Error())
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("non-empty values", func(tt *testing.T) {
|
|
|
|
store := fakes.NewFakeKVStore(t)
|
|
|
|
silences := []byte("test-silences")
|
|
|
|
nflog := []byte("test-notifications")
|
|
|
|
require.NoError(t, store.Set(ctx, 1, "alertmanager", "silences", base64.StdEncoding.EncodeToString(silences)))
|
|
|
|
require.NoError(t, store.Set(ctx, 1, "alertmanager", "notifications", base64.StdEncoding.EncodeToString(nflog)))
|
|
|
|
|
|
|
|
state := clusterpb.FullState{
|
|
|
|
Parts: []clusterpb.Part{
|
|
|
|
{Key: "silences", Data: silences},
|
|
|
|
{Key: "notifications", Data: nflog},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
b, err := state.Marshal()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
encodedFullState := base64.StdEncoding.EncodeToString(b)
|
|
|
|
|
|
|
|
fs := NewFileStore(1, store, workingDir)
|
|
|
|
|
|
|
|
got, err := fs.GetFullState(ctx, "silences", "notifications")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, encodedFullState, got)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-09-09 11:25:22 -05:00
|
|
|
func TestFileStore_Persist(t *testing.T) {
|
2023-10-12 07:43:10 -05:00
|
|
|
store := fakes.NewFakeKVStore(t)
|
2021-09-09 11:25:22 -05:00
|
|
|
state := &fakeState{data: "something to marshal"}
|
|
|
|
workingDir := t.TempDir()
|
|
|
|
fs := NewFileStore(1, store, workingDir)
|
|
|
|
filekey := "silences"
|
|
|
|
|
|
|
|
size, err := fs.Persist(context.Background(), filekey, state)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, int64(20), size)
|
2023-10-12 07:43:10 -05:00
|
|
|
store.Mtx.Lock()
|
|
|
|
require.Len(t, store.Store, 1)
|
|
|
|
store.Mtx.Unlock()
|
2021-09-09 11:25:22 -05:00
|
|
|
v, ok, err := store.Get(context.Background(), 1, KVNamespace, filekey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, ok)
|
|
|
|
b, err := decode(v)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "something to marshal", string(b))
|
|
|
|
}
|