diff --git a/database/sql/pools.go b/database/sql/pools.go index 01d1afc4..89500ed9 100644 --- a/database/sql/pools.go +++ b/database/sql/pools.go @@ -17,6 +17,7 @@ package sql import ( "context" "fmt" + "log/slog" "github.com/google/uuid" "github.com/pkg/errors" @@ -73,11 +74,16 @@ func (s *sqlDatabase) DeletePoolByID(_ context.Context, poolID string) (err erro return errors.Wrap(err, "fetching pool by ID") } - defer func() { + defer func(pool Pool) { if err == nil { - s.sendNotify(common.PoolEntityType, common.DeleteOperation, pool) + asParams, innerErr := s.sqlToCommonPool(pool) + if innerErr == nil { + s.sendNotify(common.PoolEntityType, common.DeleteOperation, asParams) + } else { + slog.With(slog.Any("error", innerErr)).ErrorContext(s.ctx, "error sending delete notification", "pool", poolID) + } } - }() + }(pool) if q := s.conn.Unscoped().Delete(&pool); q.Error != nil { return errors.Wrap(q.Error, "removing pool") diff --git a/database/watcher/watcher_store_test.go b/database/watcher/watcher_store_test.go index 895dab9d..fa82a339 100644 --- a/database/watcher/watcher_store_test.go +++ b/database/watcher/watcher_store_test.go @@ -19,6 +19,37 @@ type WatcherStoreTestSuite struct { ctx context.Context } +func (s *WatcherStoreTestSuite) TestControllerWatcher() { + consumer, err := watcher.RegisterConsumer( + s.ctx, "controller-test", + watcher.WithEntityTypeFilter(common.ControllerEntityType), + watcher.WithOperationTypeFilter(common.UpdateOperation), + ) + s.Require().NoError(err) + s.Require().NotNil(consumer) + s.T().Cleanup(func() { consumer.Close() }) + + metadataURL := "http://metadata.example.com" + updateParams := params.UpdateControllerParams{ + MetadataURL: &metadataURL, + } + + controller, err := s.store.UpdateController(updateParams) + s.Require().NoError(err) + s.Require().Equal(metadataURL, controller.MetadataURL) + + select { + case event := <-consumer.Watch(): + s.Require().Equal(common.ChangePayload{ + EntityType: common.ControllerEntityType, + Operation: common.UpdateOperation, + Payload: controller, + }, event) + case <-time.After(1 * time.Second): + s.T().Fatal("expected payload not received") + } +} + func (s *WatcherStoreTestSuite) TestEnterpriseWatcher() { consumer, err := watcher.RegisterConsumer( s.ctx, "enterprise-test", diff --git a/database/watcher/watcher_test.go b/database/watcher/watcher_test.go index 21d15093..6d1091ed 100644 --- a/database/watcher/watcher_test.go +++ b/database/watcher/watcher_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/pkg/errors" "github.com/stretchr/testify/suite" "github.com/cloudbase/garm/database" @@ -156,6 +157,18 @@ func (s *WatcherTestSuite) TestConsumetWithFilter() { } } +func maybeInitController(db common.Store) error { + if _, err := db.ControllerInfo(); err == nil { + return nil + } + + if _, err := db.InitController(); err != nil { + return errors.Wrap(err, "initializing controller") + } + + return nil +} + func TestWatcherTestSuite(t *testing.T) { // Watcher tests watcherSuite := &WatcherTestSuite{ @@ -171,6 +184,11 @@ func TestWatcherTestSuite(t *testing.T) { t.Fatalf("failed to create db connection: %s", err) } + err = maybeInitController(store) + if err != nil { + t.Fatalf("failed to init controller: %s", err) + } + adminCtx := garmTesting.ImpersonateAdminContext(ctx, store, t) watcherStoreSuite := &WatcherStoreTestSuite{ ctx: adminCtx,