diff --git a/api/ifaces/handlers.go b/api/ifaces/handlers.go index 36c94797c..aaf1dccc9 100644 --- a/api/ifaces/handlers.go +++ b/api/ifaces/handlers.go @@ -3,6 +3,7 @@ package ifaces import ( "net/http" + "context" "github.com/iron-io/functions/api/models" ) @@ -13,6 +14,9 @@ type SpecialHandler interface { // Each handler can modify the context here so when it gets passed along, it will use the new info. // Not using Gin's Context so we don't lock ourselves into Gin, this is a subset of the Gin context. type HandlerContext interface { + // Context return the context object + Context() context.Context + // Request returns the underlying http.Request object Request() *http.Request diff --git a/api/ifaces/listeners.go b/api/ifaces/listeners.go index 7c2479852..dfd27d188 100644 --- a/api/ifaces/listeners.go +++ b/api/ifaces/listeners.go @@ -6,9 +6,23 @@ import ( "github.com/iron-io/functions/api/models" ) -type AppListener interface { - // BeforeAppUpdate called right before storing App in the database +type AppCreateListener interface { + // BeforeAppCreate called right before creating App in the database + BeforeAppCreate(ctx context.Context, app *models.App) error + // AfterAppCreate called after creating App in the database + AfterAppCreate(ctx context.Context, app *models.App) error +} + +type AppUpdateListener interface { + // BeforeAppUpdate called right before updating App in the database BeforeAppUpdate(ctx context.Context, app *models.App) error - // AfterAppUpdate called after storing App in the database + // AfterAppUpdate called after updating App in the database AfterAppUpdate(ctx context.Context, app *models.App) error } + +type AppDeleteListener interface { + // BeforeAppDelete called right before deleting App in the database + BeforeAppDelete(ctx context.Context, appName string) error + // AfterAppDelete called after deleting App in the database + AfterAppDelete(ctx context.Context, appName string) error +} diff --git a/api/server/apps_create.go b/api/server/apps_create.go index 5a870cd66..d1b85a62b 100644 --- a/api/server/apps_create.go +++ b/api/server/apps_create.go @@ -34,7 +34,7 @@ func (s *Server) handleAppCreate(c *gin.Context) { return } - err = Api.FireBeforeAppUpdate(ctx, wapp.App) + err = Api.FireBeforeAppCreate(ctx, wapp.App) if err != nil { log.WithError(err).Errorln(models.ErrAppsCreate) c.JSON(http.StatusInternalServerError, simpleError(err)) @@ -48,7 +48,7 @@ func (s *Server) handleAppCreate(c *gin.Context) { return } - err = Api.FireAfterAppUpdate(ctx, wapp.App) + err = Api.FireAfterAppCreate(ctx, wapp.App) if err != nil { log.WithError(err).Errorln(models.ErrAppsCreate) c.JSON(http.StatusInternalServerError, simpleError(err)) diff --git a/api/server/apps_delete.go b/api/server/apps_delete.go index b7190f307..30ab926dc 100644 --- a/api/server/apps_delete.go +++ b/api/server/apps_delete.go @@ -28,11 +28,25 @@ func handleAppDelete(c *gin.Context) { return } - if err := Api.Datastore.RemoveApp(ctx, appName); err != nil { + err = Api.FireAfterAppDelete(ctx, appName) + if err != nil { + log.WithError(err).Errorln(models.ErrAppsRemoving) + c.JSON(http.StatusInternalServerError, simpleError(err)) + return + } + + if err = Api.Datastore.RemoveApp(ctx, appName); err != nil { log.WithError(err).Debug(models.ErrAppsRemoving) c.JSON(http.StatusInternalServerError, simpleError(models.ErrAppsRemoving)) return } + err = Api.FireAfterAppDelete(ctx, appName) + if err != nil { + log.WithError(err).Errorln(models.ErrAppsRemoving) + c.JSON(http.StatusInternalServerError, simpleError(err)) + return + } + c.JSON(http.StatusOK, gin.H{"message": "App deleted"}) } diff --git a/api/server/apps_update.go b/api/server/apps_update.go index c7def80ed..bb3925d84 100644 --- a/api/server/apps_update.go +++ b/api/server/apps_update.go @@ -29,6 +29,14 @@ func handleAppUpdate(c *gin.Context) { } wapp.App.Name = c.Param("app") + + err = Api.FireAfterAppUpdate(ctx, wapp.App) + if err != nil { + log.WithError(err).Errorln(models.ErrAppsUpdate) + c.JSON(http.StatusInternalServerError, simpleError(err)) + return + } + app, err := Api.Datastore.UpdateApp(ctx, wapp.App) if err != nil { log.WithError(err).Debug(models.ErrAppsUpdate) @@ -36,6 +44,13 @@ func handleAppUpdate(c *gin.Context) { return } + err = Api.FireAfterAppUpdate(ctx, wapp.App) + if err != nil { + log.WithError(err).Errorln(models.ErrAppsUpdate) + c.JSON(http.StatusInternalServerError, simpleError(err)) + return + } + wapp.App = app // Nothing to update right now in apps diff --git a/api/server/listeners.go b/api/server/listeners.go new file mode 100644 index 000000000..d63a1ce1d --- /dev/null +++ b/api/server/listeners.go @@ -0,0 +1,82 @@ +package server + +import ( + "context" + "github.com/iron-io/functions/api/ifaces" + "github.com/iron-io/functions/api/models" +) + +// AddAppCreateListener adds a listener that will be notified on App created. +func (s *Server) AddAppCreateListener(listener ifaces.AppCreateListener) { + s.AppCreateListeners = append(s.AppCreateListeners, listener) +} + +// AddAppUpdateListener adds a listener that will be notified on App updated. +func (s *Server) AddAppUpdateListener(listener ifaces.AppUpdateListener) { + s.AppUpdateListeners = append(s.AppUpdateListeners, listener) +} + +// AddAppDeleteListener adds a listener that will be notified on App deleted. +func (s *Server) AddAppDeleteListener(listener ifaces.AppDeleteListener) { + s.AppDeleteListeners = append(s.AppDeleteListeners, listener) +} + +func (s *Server) FireBeforeAppCreate(ctx context.Context, app *models.App) error { + for _, l := range s.AppCreateListeners { + err := l.BeforeAppCreate(ctx, app) + if err != nil { + return err + } + } + return nil +} + +func (s *Server) FireAfterAppCreate(ctx context.Context, app *models.App) error { + for _, l := range s.AppCreateListeners { + err := l.AfterAppCreate(ctx, app) + if err != nil { + return err + } + } + return nil +} + +func (s *Server) FireBeforeAppUpdate(ctx context.Context, app *models.App) error { + for _, l := range s.AppUpdateListeners { + err := l.BeforeAppUpdate(ctx, app) + if err != nil { + return err + } + } + return nil +} + +func (s *Server) FireAfterAppUpdate(ctx context.Context, app *models.App) error { + for _, l := range s.AppUpdateListeners { + err := l.AfterAppUpdate(ctx, app) + if err != nil { + return err + } + } + return nil +} + +func (s *Server) FireBeforeAppDelete(ctx context.Context, appName string) error { + for _, l := range s.AppDeleteListeners { + err := l.BeforeAppDelete(ctx, appName) + if err != nil { + return err + } + } + return nil +} + +func (s *Server) FireAfterAppDelete(ctx context.Context, appName string) error { + for _, l := range s.AppDeleteListeners { + err := l.AfterAppDelete(ctx, appName) + if err != nil { + return err + } + } + return nil +} diff --git a/api/server/server.go b/api/server/server.go index bc5c61273..a095a03ad 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -25,12 +25,14 @@ import ( var Api *Server type Server struct { - Runner *runner.Runner - Router *gin.Engine - MQ models.MessageQueue - AppListeners []ifaces.AppListener - SpecialHandlers []ifaces.SpecialHandler - Enqueue models.Enqueue + Runner *runner.Runner + Router *gin.Engine + MQ models.MessageQueue + AppCreateListeners []ifaces.AppCreateListener + AppUpdateListeners []ifaces.AppUpdateListener + AppDeleteListeners []ifaces.AppDeleteListener + SpecialHandlers []ifaces.SpecialHandler + Enqueue models.Enqueue tasks chan task.Request @@ -94,31 +96,6 @@ func (s *Server) primeCache(ctx context.Context) { logrus.Info("cached prime") } -// AddAppListener adds a listener that will be notified on App changes. -func (s *Server) AddAppListener(listener ifaces.AppListener) { - s.AppListeners = append(s.AppListeners, listener) -} - -func (s *Server) FireBeforeAppUpdate(ctx context.Context, app *models.App) error { - for _, l := range s.AppListeners { - err := l.BeforeAppUpdate(ctx, app) - if err != nil { - return err - } - } - return nil -} - -func (s *Server) FireAfterAppUpdate(ctx context.Context, app *models.App) error { - for _, l := range s.AppListeners { - err := l.AfterAppUpdate(ctx, app) - if err != nil { - return err - } - } - return nil -} - func (s *Server) AddSpecialHandler(handler ifaces.SpecialHandler) { s.SpecialHandlers = append(s.SpecialHandlers, handler) } diff --git a/api/server/special_handler_context.go b/api/server/special_handler_context.go index 3ae42728e..1ffd2b06b 100644 --- a/api/server/special_handler_context.go +++ b/api/server/special_handler_context.go @@ -3,6 +3,7 @@ package server import ( "net/http" + "context" "github.com/gin-gonic/gin" "github.com/iron-io/functions/api/models" ) @@ -12,6 +13,11 @@ type SpecialHandlerContext struct { ginContext *gin.Context } +func (c *SpecialHandlerContext) Context() context.Context { + ctx, _ := c.ginContext.Get("ctx") + return ctx.(context.Context) +} + func (c *SpecialHandlerContext) Request() *http.Request { return c.ginContext.Request }