store: P2R-10 schema for source-group + host-default hooks (migration 0010)
Adds pre_hook/post_hook BLOB columns to source_groups and pre_hook_default/post_hook_default to hosts. Bytes stored verbatim (AEAD encrypt/decrypt happens at the HTTP layer where the AEAD key lives). Round-trip tests cover set/clear semantics on both tables.
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
// hooks_test.go — covers the pre/post hook columns added in
|
||||
// migration 0010 (P2R-10): set + reload roundtrip on both
|
||||
// source_groups and hosts; nil clears the column.
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/oklog/ulid/v2"
|
||||
)
|
||||
|
||||
func newTestStore(t *testing.T) *Store {
|
||||
t.Helper()
|
||||
dir := t.TempDir()
|
||||
st, err := Open(context.Background(), filepath.Join(dir, "rm.db"))
|
||||
if err != nil {
|
||||
t.Fatalf("open store: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { _ = st.Close() })
|
||||
return st
|
||||
}
|
||||
|
||||
func makeHostInStore(t *testing.T, st *Store, name string) string {
|
||||
t.Helper()
|
||||
id := ulid.Make().String()
|
||||
if err := st.CreateHost(context.Background(), Host{
|
||||
ID: id, Name: name, OS: "linux", Arch: "amd64",
|
||||
EnrolledAt: time.Now().UTC(),
|
||||
}, "tokenhash-"+id, ""); err != nil {
|
||||
t.Fatalf("create host: %v", err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func TestSourceGroupHooksRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
st := newTestStore(t)
|
||||
hostID := makeHostInStore(t, st, "hooks-host")
|
||||
|
||||
g := &SourceGroup{
|
||||
ID: ulid.Make().String(), HostID: hostID, Name: "etc",
|
||||
PreHook: []byte("ENC-PRE"),
|
||||
PostHook: []byte("ENC-POST"),
|
||||
}
|
||||
if err := st.CreateSourceGroup(context.Background(), g); err != nil {
|
||||
t.Fatalf("create: %v", err)
|
||||
}
|
||||
got, err := st.GetSourceGroup(context.Background(), hostID, g.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("get: %v", err)
|
||||
}
|
||||
if string(got.PreHook) != "ENC-PRE" {
|
||||
t.Fatalf("PreHook: got %q, want ENC-PRE", got.PreHook)
|
||||
}
|
||||
if string(got.PostHook) != "ENC-POST" {
|
||||
t.Fatalf("PostHook: got %q, want ENC-POST", got.PostHook)
|
||||
}
|
||||
|
||||
// Update: clear PreHook, change PostHook.
|
||||
got.PreHook = nil
|
||||
got.PostHook = []byte("ENC-POST-2")
|
||||
if err := st.UpdateSourceGroup(context.Background(), got); err != nil {
|
||||
t.Fatalf("update: %v", err)
|
||||
}
|
||||
got, err = st.GetSourceGroup(context.Background(), hostID, g.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("get: %v", err)
|
||||
}
|
||||
if got.PreHook != nil {
|
||||
t.Fatalf("PreHook: want nil after clear, got %q", got.PreHook)
|
||||
}
|
||||
if string(got.PostHook) != "ENC-POST-2" {
|
||||
t.Fatalf("PostHook: got %q, want ENC-POST-2", got.PostHook)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostHookDefaultsRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
st := newTestStore(t)
|
||||
hostID := makeHostInStore(t, st, "host-hooks-host")
|
||||
|
||||
if err := st.SetHostHooks(context.Background(), hostID, []byte("PRE"), []byte("POST")); err != nil {
|
||||
t.Fatalf("set: %v", err)
|
||||
}
|
||||
h, err := st.GetHost(context.Background(), hostID)
|
||||
if err != nil {
|
||||
t.Fatalf("get: %v", err)
|
||||
}
|
||||
if string(h.PreHookDefault) != "PRE" || string(h.PostHookDefault) != "POST" {
|
||||
t.Fatalf("after set: pre=%q post=%q", h.PreHookDefault, h.PostHookDefault)
|
||||
}
|
||||
// Clear by passing nil.
|
||||
if err := st.SetHostHooks(context.Background(), hostID, nil, nil); err != nil {
|
||||
t.Fatalf("clear: %v", err)
|
||||
}
|
||||
h, err = st.GetHost(context.Background(), hostID)
|
||||
if err != nil {
|
||||
t.Fatalf("get: %v", err)
|
||||
}
|
||||
if h.PreHookDefault != nil || h.PostHookDefault != nil {
|
||||
t.Fatalf("after clear: pre=%v post=%v (want nil)", h.PreHookDefault, h.PostHookDefault)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user