setup settingstore

This commit is contained in:
Will Assis
2025-12-02 15:17:03 -03:00
parent 8212473330
commit 08e9908d27
2 changed files with 237 additions and 0 deletions
@@ -0,0 +1,95 @@
package resource
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/grafana/grafana/pkg/apimachinery/validation"
)
const (
settingsSection = "unified/settings"
)
type settingStore struct {
kv KV
}
type SettingKey struct {
Namespace string
Group string
Resource string
}
func (k SettingKey) String() string {
return fmt.Sprintf("%s/%s/%s", k.Group, k.Resource, k.Namespace)
}
func (k SettingKey) Validate() error {
if k.Namespace == "" {
return NewValidationError("namespace", k.Namespace, ErrNamespaceRequired)
}
if err := validation.IsValidGroup(k.Group); err != nil {
return NewValidationError("group", k.Group, err[0])
}
if err := validation.IsValidResource(k.Resource); err != nil {
return NewValidationError("resource", k.Resource, err[0])
}
return nil
}
type Setting struct {
Namespace string `json:"namespace"`
Group string `json:"group"`
Resource string `json:"resource"`
LastImportTime time.Time `json:"lastImportTime"`
}
func newSettingStore(kv KV) *settingStore {
return &settingStore{
kv: kv,
}
}
func (d *settingStore) Get(ctx context.Context, key SettingKey) (Setting, error) {
if err := key.Validate(); err != nil {
return Setting{}, fmt.Errorf("invalid setting key: %w", err)
}
reader, err := d.kv.Get(ctx, settingsSection, key.String())
if err != nil {
return Setting{}, err
}
defer func() { _ = reader.Close() }()
var setting Setting
if err = json.NewDecoder(reader).Decode(&setting); err != nil {
return Setting{}, err
}
return setting, nil
}
func (d *settingStore) Save(ctx context.Context, setting Setting) error {
settingKey := SettingKey{
Namespace: setting.Namespace,
Group: setting.Group,
Resource: setting.Resource,
}
if err := settingKey.Validate(); err != nil {
return fmt.Errorf("invalid settingKey key: %w", err)
}
writer, err := d.kv.Save(ctx, settingsSection, settingKey.String())
if err != nil {
return err
}
encoder := json.NewEncoder(writer)
if err := encoder.Encode(setting); err != nil {
_ = writer.Close()
return err
}
return writer.Close()
}
@@ -0,0 +1,142 @@
package resource
import (
"context"
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func setupTestSettingStore(t *testing.T) *settingStore {
db := setupTestBadgerDB(t)
t.Cleanup(func() {
err := db.Close()
require.NoError(t, err)
})
kv := NewBadgerKV(db)
return newSettingStore(kv)
}
func TestNewSettingStore(t *testing.T) {
store := setupTestSettingStore(t)
assert.NotNil(t, store.kv)
}
func TestSettingStore_SettingKey_String(t *testing.T) {
tests := []struct {
name string
settingKey SettingKey
expected string
}{
{
name: "basic event key",
settingKey: SettingKey{
Namespace: "default",
Group: "apps",
Resource: "resource",
},
expected: "apps/resource/default",
},
{
name: "empty namespace",
settingKey: SettingKey{
Namespace: "",
Group: "apps",
Resource: "resource",
},
expected: "apps/resource/",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := tt.settingKey.String()
assert.Equal(t, tt.expected, result)
})
}
}
func TestSettingStore_SettingKey_Validate(t *testing.T) {
tests := []struct {
name string
key SettingKey
error error
}{
{
name: "valid key",
key: SettingKey{
Namespace: "default",
Group: "apps",
Resource: "resource",
},
error: nil,
},
{
name: "empty namespace",
key: SettingKey{
Namespace: "",
Group: "apps",
Resource: "resource",
},
error: errors.New("namespace '' is invalid: namespace is required"),
},
{
name: "empty group",
key: SettingKey{
Namespace: "default",
Group: "",
Resource: "resource",
},
error: errors.New("group '' is invalid: group is too short"),
},
{
name: "empty resource",
key: SettingKey{
Namespace: "default",
Group: "apps",
Resource: "",
},
error: errors.New("resource '' is invalid: resource is too short"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.key.Validate()
if tt.error == nil {
assert.NoError(t, err)
} else {
assert.Error(t, err)
}
})
}
}
func TestSettingStore_Save_Get(t *testing.T) {
ctx := context.Background()
store := setupTestSettingStore(t)
setting := Setting{
Namespace: "default",
Group: "apps",
Resource: "resource",
LastImportTime: time.Now().Truncate(time.Microsecond),
}
err := store.Save(ctx, setting)
require.NoError(t, err)
settingKey := SettingKey{
Namespace: "default",
Group: "apps",
Resource: "resource",
}
retrievedSetting, err := store.Get(ctx, settingKey)
require.NoError(t, err)
assert.Equal(t, setting, retrievedSetting)
}