From 8524e8019586658241a15ccb44a14b193900543c Mon Sep 17 00:00:00 2001 From: Clivern Date: Wed, 14 Jul 2021 14:14:07 +0200 Subject: [PATCH] init --- README.md | 6 - cmd/server.go | 116 +++++++++++++----- config.dist.yml | 6 - config.prod.yml | 6 - core/component/balancer.go | 12 +- core/controller/api_auth_data.go | 89 +++----------- core/controller/auth_methods.go | 87 ++----------- core/controller/basic_auth_data.go | 89 +++----------- core/controller/endpoint.go | 6 +- .../{helpers.go => global_context.go} | 32 ++--- core/controller/health.go | 6 +- core/controller/oauth_data.go | 31 +++++ core/controller/ready.go | 37 ++++++ core/controller/reverse_proxy.go | 27 +--- core/service/redis.go | 22 +++- 15 files changed, 248 insertions(+), 324 deletions(-) rename core/controller/{helpers.go => global_context.go} (74%) create mode 100644 core/controller/ready.go diff --git a/README.md b/README.md index 50b8c43..060ffa9 100644 --- a/README.md +++ b/README.md @@ -86,12 +86,6 @@ app: api: key: ${HELMET_API_KEY:-6c68b836-6f8e-465e-b59f-89c1db53afca} - # Runtime, Requests/Response and Helmet Metrics - metrics: - prometheus: - # Route for the metrics endpoint - endpoint: ${HELMET_METRICS_PROM_ENDPOINT:-/_metrics} - # Application Database database: # Database driver (sqlite3, mysql) diff --git a/cmd/server.go b/cmd/server.go index 21b1470..116508d 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -18,6 +18,7 @@ import ( "github.com/spacewalkio/helmet/core/component" "github.com/spacewalkio/helmet/core/controller" "github.com/spacewalkio/helmet/core/module" + "github.com/spacewalkio/helmet/core/service" "github.com/drone/envsubst" "github.com/labstack/echo-contrib/prometheus" @@ -117,22 +118,25 @@ var serverCmd = &cobra.Command{ log.SetFormatter(&log.TextFormatter{}) } - // Init DB Connection - db := module.Database{} - err = db.AutoConnect() + context := &controller.GlobalContext{ + Database: &module.Database{}, + Cache: service.GetDefaultRedisDriver(), + } + + err = context.GetDatabase().AutoConnect() if err != nil { panic(err.Error()) } // Migrate Database - success := db.Migrate() + success := context.GetDatabase().Migrate() if !success { panic("Error! Unable to migrate database tables.") } - defer db.Close() + defer context.GetDatabase().Close() viper.SetDefault("config", config) @@ -153,17 +157,11 @@ var serverCmd = &cobra.Command{ p := prometheus.NewPrometheus(viper.GetString("app.name"), nil) p.Use(e) - helpers := controller.Helpers{} - balancer, err := helpers.GetBalancer() - - if err != nil { - panic(fmt.Sprintf("Error while loading configs: %s", err.Error())) - } - e.GET("/favicon.ico", func(c echo.Context) error { return c.String(http.StatusNoContent, "") }) + // API GW Management API e1 := e.Group("/_api/v1") { e1.Use(middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{ @@ -181,37 +179,93 @@ var serverCmd = &cobra.Command{ })) // List Endpoints - e1.GET("/endpoint", controller.GetEndpoints) + e1.GET("/endpoint", func(c echo.Context) error { + return controller.GetEndpoints(c, context) + }) // Auth Methods CRUD - e1.GET("/auth/method", controller.GetAuthMethods) - e1.GET("/auth/method/:id", controller.GetAuthMethod) - e1.DELETE("/auth/method/:id", controller.DeleteAuthMethod) - e1.POST("/auth/method", controller.CreateAuthMethod) - e1.PUT("/auth/method/:id", controller.UpdateAuthMethod) + e1.GET("/auth/method", func(c echo.Context) error { + return controller.GetAuthMethods(c, context) + }) + e1.GET("/auth/method/:id", func(c echo.Context) error { + return controller.GetAuthMethod(c, context) + }) + e1.DELETE("/auth/method/:id", func(c echo.Context) error { + return controller.DeleteAuthMethod(c, context) + }) + e1.POST("/auth/method", func(c echo.Context) error { + return controller.CreateAuthMethod(c, context) + }) + e1.PUT("/auth/method/:id", func(c echo.Context) error { + return controller.UpdateAuthMethod(c, context) + }) // API Keys CRUD - e1.GET("/auth/key", controller.GetKeysBasedAuthData) - e1.GET("/auth/key/:id", controller.GetKeyBasedAuthData) - e1.DELETE("/auth/key/:id", controller.DeleteKeyBasedAuthData) - e1.POST("/auth/key", controller.CreateKeyBasedAuthData) - e1.PUT("/auth/key/:id", controller.UpdateKeyBasedAuthData) + e1.GET("/auth/key", func(c echo.Context) error { + return controller.GetKeysBasedAuthData(c, context) + }) + e1.GET("/auth/key/:id", func(c echo.Context) error { + return controller.GetKeyBasedAuthData(c, context) + }) + e1.DELETE("/auth/key/:id", func(c echo.Context) error { + return controller.DeleteKeyBasedAuthData(c, context) + }) + e1.POST("/auth/key", func(c echo.Context) error { + return controller.CreateKeyBasedAuthData(c, context) + }) + e1.PUT("/auth/key/:id", func(c echo.Context) error { + return controller.UpdateKeyBasedAuthData(c, context) + }) // Basic Auth CRUD - e1.GET("/auth/basic", controller.GetBasicAuthItems) - e1.GET("/auth/basic/:id", controller.GetBasicAuthData) - e1.DELETE("/auth/basic/:id", controller.DeleteBasicAuthData) - e1.POST("/auth/basic", controller.CreateBasicAuthData) - e1.PUT("/auth/basic/:id", controller.UpdateBasicAuthData) + e1.GET("/auth/basic", func(c echo.Context) error { + return controller.GetBasicAuthItems(c, context) + }) + e1.GET("/auth/basic/:id", func(c echo.Context) error { + return controller.GetBasicAuthData(c, context) + }) + e1.DELETE("/auth/basic/:id", func(c echo.Context) error { + return controller.DeleteBasicAuthData(c, context) + }) + e1.POST("/auth/basic", func(c echo.Context) error { + return controller.CreateBasicAuthData(c, context) + }) + e1.PUT("/auth/basic/:id", func(c echo.Context) error { + return controller.UpdateBasicAuthData(c, context) + }) + + // OAuth CRUD + e1.GET("/auth/oauth", func(c echo.Context) error { + return controller.GetOAuthItems(c, context) + }) + e1.GET("/auth/oauth/:id", func(c echo.Context) error { + return controller.GetOAuthData(c, context) + }) + e1.DELETE("/auth/oauth/:id", func(c echo.Context) error { + return controller.DeleteOAuthData(c, context) + }) + e1.POST("/auth/oauth", func(c echo.Context) error { + return controller.CreateOAuthData(c, context) + }) + e1.PUT("/auth/oauth/:id", func(c echo.Context) error { + return controller.UpdateOAuthData(c, context) + }) } - e.GET("/_me", controller.Me) + e.GET("/_me", func(c echo.Context) error { + return controller.Me(c, context) + }) // API GW Health - e.GET("/_health", controller.Health) + e.GET("/_health", func(c echo.Context) error { + return controller.Health(c, context) + }) + e.GET("/_ready", func(c echo.Context) error { + return controller.Ready(c, context) + }) e.Any("/*", func(c echo.Context) error { - return controller.ReverseProxy(c, balancer) + return controller.ReverseProxy(c, context) }) var runerr error diff --git a/config.dist.yml b/config.dist.yml index 1b98c88..461afa7 100644 --- a/config.dist.yml +++ b/config.dist.yml @@ -21,12 +21,6 @@ app: api: key: ${HELMET_API_KEY:-6c68b836-6f8e-465e-b59f-89c1db53afca} - # Runtime, Requests/Response and Helmet Metrics - metrics: - prometheus: - # Route for the metrics endpoint - endpoint: ${HELMET_METRICS_PROM_ENDPOINT:-/_metrics} - # Application Database database: # Database driver (sqlite3, mysql) diff --git a/config.prod.yml b/config.prod.yml index c4e4a8b..aa35070 100644 --- a/config.prod.yml +++ b/config.prod.yml @@ -21,12 +21,6 @@ app: api: key: ${HELMET_API_KEY:-6c68b836-6f8e-465e-b59f-89c1db53afca} - # Runtime, Requests/Response and Helmet Metrics - metrics: - prometheus: - # Route for the metrics endpoint - endpoint: ${HELMET_METRICS_PROM_ENDPOINT:-/_metrics} - # Application Database database: # Database driver (sqlite3, mysql) diff --git a/core/component/balancer.go b/core/component/balancer.go index 32e7b19..0a09dff 100644 --- a/core/component/balancer.go +++ b/core/component/balancer.go @@ -43,15 +43,23 @@ type RoundRobinBalancer struct { // NewRandomBalancer returns a random proxy balancer. func NewRandomBalancer(targets []*Target) Balancer { - b := &RandomBalancer{CommonBalancer: new(CommonBalancer)} + b := &RandomBalancer{ + CommonBalancer: new(CommonBalancer), + } + b.targets = targets + return b } // NewRoundRobinBalancer returns a round-robin proxy balancer. func NewRoundRobinBalancer(targets []*Target) Balancer { - b := &RoundRobinBalancer{CommonBalancer: new(CommonBalancer)} + b := &RoundRobinBalancer{ + CommonBalancer: new(CommonBalancer), + } + b.targets = targets + return b } diff --git a/core/controller/api_auth_data.go b/core/controller/api_auth_data.go index 9325f15..d2da436 100644 --- a/core/controller/api_auth_data.go +++ b/core/controller/api_auth_data.go @@ -12,26 +12,13 @@ import ( "github.com/spacewalkio/helmet/core/component" "github.com/spacewalkio/helmet/core/model" - "github.com/spacewalkio/helmet/core/module" "github.com/labstack/echo/v4" log "github.com/sirupsen/logrus" ) // CreateKeyBasedAuthData controller -func CreateKeyBasedAuthData(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - +func CreateKeyBasedAuthData(c echo.Context, gc *GlobalContext) error { data, _ := ioutil.ReadAll(c.Request().Body) key := &model.KeyBasedAuthData{} @@ -58,7 +45,7 @@ func CreateKeyBasedAuthData(c echo.Context) error { }) } - method := helpers.DB().GetAuthMethodByID(key.AuthMethodID) + method := gc.GetDatabase().GetAuthMethodByID(key.AuthMethodID) if method.ID < 1 { log.WithFields(log.Fields{ @@ -68,28 +55,16 @@ func CreateKeyBasedAuthData(c echo.Context) error { return c.NoContent(http.StatusNotFound) } - key = helpers.DB().CreateKeyBasedAuthData(key) + key = gc.GetDatabase().CreateKeyBasedAuthData(key) return c.JSON(http.StatusCreated, key) } // GetKeyBasedAuthData controller -func GetKeyBasedAuthData(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - +func GetKeyBasedAuthData(c echo.Context, gc *GlobalContext) error { id, _ := strconv.Atoi(c.Param("id")) - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - key := helpers.DB().GetKeyBasedAuthDataByID(id) + key := gc.GetDatabase().GetKeyBasedAuthDataByID(id) if key.ID < 1 { log.WithFields(log.Fields{ @@ -107,20 +82,8 @@ func GetKeyBasedAuthData(c echo.Context) error { } // GetKeysBasedAuthData controller -func GetKeysBasedAuthData(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - keys := helpers.DB().GetKeyBasedAuthItems() +func GetKeysBasedAuthData(c echo.Context, gc *GlobalContext) error { + keys := gc.GetDatabase().GetKeyBasedAuthItems() log.Info(`Get api keys`) @@ -128,22 +91,10 @@ func GetKeysBasedAuthData(c echo.Context) error { } // DeleteKeyBasedAuthData controller -func DeleteKeyBasedAuthData(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - +func DeleteKeyBasedAuthData(c echo.Context, gc *GlobalContext) error { id, _ := strconv.Atoi(c.Param("id")) - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - key := helpers.DB().GetKeyBasedAuthDataByID(id) + key := gc.GetDatabase().GetKeyBasedAuthDataByID(id) if key.ID < 1 { log.WithFields(log.Fields{ @@ -157,28 +108,16 @@ func DeleteKeyBasedAuthData(c echo.Context) error { "id": id, }).Info(`Deleting an API key`) - helpers.DB().DeleteKeyBasedAuthDataByID(key.ID) + gc.GetDatabase().DeleteKeyBasedAuthDataByID(key.ID) return c.NoContent(http.StatusNoContent) } // UpdateKeyBasedAuthData controller -func UpdateKeyBasedAuthData(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - +func UpdateKeyBasedAuthData(c echo.Context, gc *GlobalContext) error { id, _ := strconv.Atoi(c.Param("id")) - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - key := helpers.DB().GetKeyBasedAuthDataByID(id) + key := gc.GetDatabase().GetKeyBasedAuthDataByID(id) if key.ID < 1 { log.WithFields(log.Fields{ @@ -212,7 +151,7 @@ func UpdateKeyBasedAuthData(c echo.Context) error { }) } - method := helpers.DB().GetAuthMethodByID(key.AuthMethodID) + method := gc.GetDatabase().GetAuthMethodByID(key.AuthMethodID) if method.ID < 1 { log.WithFields(log.Fields{ @@ -222,7 +161,7 @@ func UpdateKeyBasedAuthData(c echo.Context) error { return c.NoContent(http.StatusNotFound) } - helpers.DB().UpdateKeyBasedAuthDataByID(&key) + gc.GetDatabase().UpdateKeyBasedAuthDataByID(&key) return c.JSON(http.StatusOK, key) } diff --git a/core/controller/auth_methods.go b/core/controller/auth_methods.go index 4d5120d..490fb08 100644 --- a/core/controller/auth_methods.go +++ b/core/controller/auth_methods.go @@ -11,14 +11,13 @@ import ( "strconv" "github.com/spacewalkio/helmet/core/model" - "github.com/spacewalkio/helmet/core/module" "github.com/labstack/echo/v4" log "github.com/sirupsen/logrus" ) // Me controller -func Me(c echo.Context) error { +func Me(c echo.Context, gc *GlobalContext) error { log.WithFields(log.Fields{ "status": "ok", }).Info(`Create auth method`) @@ -29,19 +28,7 @@ func Me(c echo.Context) error { } // CreateAuthMethod controller -func CreateAuthMethod(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - +func CreateAuthMethod(c echo.Context, gc *GlobalContext) error { data, _ := ioutil.ReadAll(c.Request().Body) method := &model.AuthMethod{} @@ -64,28 +51,16 @@ func CreateAuthMethod(c echo.Context) error { }) } - method = helpers.DB().CreateAuthMethod(method) + method = gc.GetDatabase().CreateAuthMethod(method) return c.JSON(http.StatusCreated, method) } // GetAuthMethod controller -func GetAuthMethod(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - +func GetAuthMethod(c echo.Context, gc *GlobalContext) error { id, _ := strconv.Atoi(c.Param("id")) - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - method := helpers.DB().GetAuthMethodByID(id) + method := gc.GetDatabase().GetAuthMethodByID(id) if method.ID < 1 { log.WithFields(log.Fields{ @@ -103,43 +78,19 @@ func GetAuthMethod(c echo.Context) error { } // GetAuthMethods controller -func GetAuthMethods(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - +func GetAuthMethods(c echo.Context, gc *GlobalContext) error { log.Info(`Get auth methods`) - methods := helpers.DB().GetAuthMethods() + methods := gc.GetDatabase().GetAuthMethods() return c.JSON(http.StatusOK, methods) } // DeleteAuthMethod controller -func DeleteAuthMethod(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - +func DeleteAuthMethod(c echo.Context, gc *GlobalContext) error { id, _ := strconv.Atoi(c.Param("id")) - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - method := helpers.DB().GetAuthMethodByID(id) + method := gc.GetDatabase().GetAuthMethodByID(id) if method.ID < 1 { log.WithFields(log.Fields{ @@ -153,28 +104,16 @@ func DeleteAuthMethod(c echo.Context) error { "id": id, }).Info(`Deleting an auth method`) - helpers.DB().DeleteAuthMethodByID(method.ID) + gc.GetDatabase().DeleteAuthMethodByID(method.ID) return c.NoContent(http.StatusNoContent) } // UpdateAuthMethod controller -func UpdateAuthMethod(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - +func UpdateAuthMethod(c echo.Context, gc *GlobalContext) error { id, _ := strconv.Atoi(c.Param("id")) - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - method := helpers.DB().GetAuthMethodByID(id) + method := gc.GetDatabase().GetAuthMethodByID(id) if method.ID < 1 { log.WithFields(log.Fields{ @@ -210,7 +149,7 @@ func UpdateAuthMethod(c echo.Context) error { "id": id, }).Info(`Update an auth method`) - helpers.DB().UpdateAuthMethodByID(&method) + gc.GetDatabase().UpdateAuthMethodByID(&method) return c.JSON(http.StatusCreated, method) } diff --git a/core/controller/basic_auth_data.go b/core/controller/basic_auth_data.go index a261a2b..81df0f7 100644 --- a/core/controller/basic_auth_data.go +++ b/core/controller/basic_auth_data.go @@ -12,26 +12,13 @@ import ( "github.com/spacewalkio/helmet/core/component" "github.com/spacewalkio/helmet/core/model" - "github.com/spacewalkio/helmet/core/module" "github.com/labstack/echo/v4" log "github.com/sirupsen/logrus" ) // CreateBasicAuthData controller -func CreateBasicAuthData(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - +func CreateBasicAuthData(c echo.Context, gc *GlobalContext) error { data, _ := ioutil.ReadAll(c.Request().Body) key := &model.BasicAuthData{} @@ -62,7 +49,7 @@ func CreateBasicAuthData(c echo.Context) error { }) } - method := helpers.DB().GetAuthMethodByID(key.AuthMethodID) + method := gc.GetDatabase().GetAuthMethodByID(key.AuthMethodID) if method.ID < 1 { log.WithFields(log.Fields{ @@ -72,28 +59,16 @@ func CreateBasicAuthData(c echo.Context) error { return c.NoContent(http.StatusNotFound) } - key = helpers.DB().CreateBasicAuthData(key) + key = gc.GetDatabase().CreateBasicAuthData(key) return c.JSON(http.StatusCreated, key) } // GetBasicAuthData controller -func GetBasicAuthData(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - +func GetBasicAuthData(c echo.Context, gc *GlobalContext) error { id, _ := strconv.Atoi(c.Param("id")) - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - key := helpers.DB().GetBasicAuthDataByID(id) + key := gc.GetDatabase().GetBasicAuthDataByID(id) if key.ID < 1 { log.WithFields(log.Fields{ @@ -111,20 +86,8 @@ func GetBasicAuthData(c echo.Context) error { } // GetBasicAuthItems controller -func GetBasicAuthItems(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - items := helpers.DB().GetBasicAuthItems() +func GetBasicAuthItems(c echo.Context, gc *GlobalContext) error { + items := gc.GetDatabase().GetBasicAuthItems() log.Info(`Get basic auth items`) @@ -132,22 +95,10 @@ func GetBasicAuthItems(c echo.Context) error { } // DeleteBasicAuthData controller -func DeleteBasicAuthData(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - +func DeleteBasicAuthData(c echo.Context, gc *GlobalContext) error { id, _ := strconv.Atoi(c.Param("id")) - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - key := helpers.DB().GetBasicAuthDataByID(id) + key := gc.GetDatabase().GetBasicAuthDataByID(id) if key.ID < 1 { log.WithFields(log.Fields{ @@ -161,28 +112,16 @@ func DeleteBasicAuthData(c echo.Context) error { "id": id, }).Info(`Deleting a basic auth key`) - helpers.DB().DeleteBasicAuthDataByID(key.ID) + gc.GetDatabase().DeleteBasicAuthDataByID(key.ID) return c.NoContent(http.StatusNoContent) } // UpdateBasicAuthData controller -func UpdateBasicAuthData(c echo.Context) error { - helpers := &Helpers{Database: &module.Database{}} - +func UpdateBasicAuthData(c echo.Context, gc *GlobalContext) error { id, _ := strconv.Atoi(c.Param("id")) - if err := helpers.DatabaseConnect(); err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Failure while connecting database`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - - key := helpers.DB().GetBasicAuthDataByID(id) + key := gc.GetDatabase().GetBasicAuthDataByID(id) if key.ID < 1 { log.WithFields(log.Fields{ @@ -220,7 +159,7 @@ func UpdateBasicAuthData(c echo.Context) error { }) } - method := helpers.DB().GetAuthMethodByID(key.AuthMethodID) + method := gc.GetDatabase().GetAuthMethodByID(key.AuthMethodID) if method.ID < 1 { log.WithFields(log.Fields{ @@ -230,7 +169,7 @@ func UpdateBasicAuthData(c echo.Context) error { return c.NoContent(http.StatusNotFound) } - helpers.DB().UpdateBasicAuthDataByID(&key) + gc.GetDatabase().UpdateBasicAuthDataByID(&key) return c.JSON(http.StatusOK, key) } diff --git a/core/controller/endpoint.go b/core/controller/endpoint.go index 60aae0e..528e4e5 100644 --- a/core/controller/endpoint.go +++ b/core/controller/endpoint.go @@ -12,10 +12,8 @@ import ( ) // GetEndpoints controller -func GetEndpoints(c echo.Context) error { - helpers := &Helpers{} - - configs, err := helpers.GetConfigs() +func GetEndpoints(c echo.Context, gc *GlobalContext) error { + configs, err := gc.GetConfigs() if err != nil { log.WithFields(log.Fields{ diff --git a/core/controller/helpers.go b/core/controller/global_context.go similarity index 74% rename from core/controller/helpers.go rename to core/controller/global_context.go index dce55ff..cfbb778 100644 --- a/core/controller/helpers.go +++ b/core/controller/global_context.go @@ -10,32 +10,19 @@ import ( "github.com/spacewalkio/helmet/core/component" "github.com/spacewalkio/helmet/core/model" "github.com/spacewalkio/helmet/core/module" + "github.com/spacewalkio/helmet/core/service" "github.com/spf13/viper" ) -// Helpers type -type Helpers struct { +// GlobalContext type +type GlobalContext struct { Database *module.Database -} - -// DB connect to database -func (h *Helpers) DB() *module.Database { - return h.Database -} - -// DatabaseConnect connect to database -func (h *Helpers) DatabaseConnect() error { - return h.Database.AutoConnect() -} - -// Close closed database connections -func (h *Helpers) Close() { - h.Database.Close() + Cache *service.Redis } // GetConfigs gets a config instance -func (h *Helpers) GetConfigs() (*model.Configs, error) { +func (c *GlobalContext) GetConfigs() (*model.Configs, error) { configs := &model.Configs{} data, err := ioutil.ReadFile(viper.GetString("config")) @@ -54,10 +41,10 @@ func (h *Helpers) GetConfigs() (*model.Configs, error) { } // GetBalancer gets load balancer -func (h *Helpers) GetBalancer() (map[string]component.Balancer, error) { +func (c *GlobalContext) GetBalancer() (map[string]component.Balancer, error) { result := make(map[string]component.Balancer) - configs, err := h.GetConfigs() + configs, err := c.GetConfigs() if err != nil { return result, err @@ -88,3 +75,8 @@ func (h *Helpers) GetBalancer() (map[string]component.Balancer, error) { return result, nil } + +// GetDatabase gets a database connection +func (c *GlobalContext) GetDatabase() *module.Database { + return c.Database +} diff --git a/core/controller/health.go b/core/controller/health.go index 7476f4b..bd6d7f9 100644 --- a/core/controller/health.go +++ b/core/controller/health.go @@ -12,12 +12,12 @@ import ( ) // Health controller -func Health(c echo.Context) error { +func Health(c echo.Context, gc *GlobalContext) error { log.WithFields(log.Fields{ - "status": "ok", + "status": "i am ok", }).Info(`Health check`) return c.JSON(http.StatusOK, map[string]interface{}{ - "status": "ok", + "status": "i am ok", }) } diff --git a/core/controller/oauth_data.go b/core/controller/oauth_data.go index 9345946..ad9a406 100644 --- a/core/controller/oauth_data.go +++ b/core/controller/oauth_data.go @@ -3,3 +3,34 @@ // license that can be found in the LICENSE file. package controller + +import ( + "net/http" + + "github.com/labstack/echo/v4" +) + +// CreateOAuthData controller +func CreateOAuthData(c echo.Context, gc *GlobalContext) error { + return c.NoContent(http.StatusNoContent) +} + +// GetOAuthData controller +func GetOAuthData(c echo.Context, gc *GlobalContext) error { + return c.NoContent(http.StatusNoContent) +} + +// GetOAuthItems controller +func GetOAuthItems(c echo.Context, gc *GlobalContext) error { + return c.NoContent(http.StatusNoContent) +} + +// DeleteOAuthData controller +func DeleteOAuthData(c echo.Context, gc *GlobalContext) error { + return c.NoContent(http.StatusNoContent) +} + +// UpdateOAuthData controller +func UpdateOAuthData(c echo.Context, gc *GlobalContext) error { + return c.NoContent(http.StatusNoContent) +} diff --git a/core/controller/ready.go b/core/controller/ready.go new file mode 100644 index 0000000..724d29a --- /dev/null +++ b/core/controller/ready.go @@ -0,0 +1,37 @@ +// Copyright 2021 Clivern. All rights reserved. +// Use of this source code is governed by the MIT +// license that can be found in the LICENSE file. + +package controller + +import ( + "net/http" + + "github.com/labstack/echo/v4" + log "github.com/sirupsen/logrus" +) + +// Ready controller +func Ready(c echo.Context, gc *GlobalContext) error { + err := gc.GetDatabase().Ping() + + if err == nil { + log.WithFields(log.Fields{ + "status": "i am ok", + }).Info(`Ready check`) + + return c.JSON(http.StatusOK, map[string]interface{}{ + "status": "i am ok", + }) + } + + log.WithFields(log.Fields{ + "status": "i am not ok", + "error": err.Error(), + }).Info(`Ready check`) + + return c.JSON(http.StatusInternalServerError, map[string]interface{}{ + "status": "i am not ok", + "error": err.Error(), + }) +} diff --git a/core/controller/reverse_proxy.go b/core/controller/reverse_proxy.go index c08f9e4..6f27f1a 100644 --- a/core/controller/reverse_proxy.go +++ b/core/controller/reverse_proxy.go @@ -8,30 +8,13 @@ import ( "net/http" "github.com/spacewalkio/helmet/core/component" - "github.com/spacewalkio/helmet/core/module" "github.com/labstack/echo/v4" log "github.com/sirupsen/logrus" ) // ReverseProxy controller -func ReverseProxy(c echo.Context, balancer map[string]component.Balancer) error { - helpers := &Helpers{ - Database: &module.Database{}, - } - - err := helpers.DatabaseConnect() - - if err != nil { - log.WithFields(log.Fields{ - "error": err.Error(), - }).Error(`Internal server error`) - - return c.NoContent(http.StatusInternalServerError) - } - - defer helpers.Close() - +func ReverseProxy(c echo.Context, gc *GlobalContext) error { log.WithFields(log.Fields{ "path": c.Request().URL.Path, "query_param": c.Request().URL.RawQuery, @@ -42,7 +25,7 @@ func ReverseProxy(c echo.Context, balancer map[string]component.Balancer) error // Fetch the endpoint // -------------------- router := component.NewRouter() - configs, err := helpers.GetConfigs() + configs, err := gc.GetConfigs() if err != nil { log.WithFields(log.Fields{ @@ -90,8 +73,8 @@ func ReverseProxy(c echo.Context, balancer map[string]component.Balancer) error // --------------------------------- // Validate the Request Credentials // --------------------------------- - apiMethod := &component.KeyBasedAuthMethod{Database: helpers.DB()} - basicMethod := &component.BasicAuthMethod{Database: helpers.DB()} + apiMethod := &component.KeyBasedAuthMethod{Database: gc.GetDatabase()} + basicMethod := &component.BasicAuthMethod{Database: gc.GetDatabase()} meta := "" name := "" @@ -134,6 +117,8 @@ func ReverseProxy(c echo.Context, balancer map[string]component.Balancer) error // ------------------------------------- // Redirect The Request to The Upstream // ------------------------------------- + balancer, _ := gc.GetBalancer() + remote := router.BuildRemote( balancer[endpoint.Name].Next().URL, endpoint.Proxy.ListenPath, diff --git a/core/service/redis.go b/core/service/redis.go index ab8d820..60549bf 100644 --- a/core/service/redis.go +++ b/core/service/redis.go @@ -5,9 +5,11 @@ package service import ( + "errors" "time" "github.com/go-redis/redis" + "github.com/spf13/viper" ) // Redis driver @@ -25,7 +27,7 @@ type Message struct { } // NewRedisDriver create a new instance -func NewRedisDriver(addr string, password string, db int) *Redis { +func NewRedisDriver(addr, password string, db int) *Redis { return &Redis{ Addr: addr, Password: password, @@ -33,8 +35,22 @@ func NewRedisDriver(addr string, password string, db int) *Redis { } } +// GetDefaultRedisDriver create a new instance +func GetDefaultRedisDriver() *Redis { + return NewRedisDriver( + viper.GetString("app.key_store.redis.address"), + viper.GetString("app.key_store.redis.password"), + viper.GetInt("app.key_store.redis.database"), + ) +} + // Connect establish a redis connection func (r *Redis) Connect() error { + // If connected, skip + if r.Ping() == nil { + return nil + } + r.Client = redis.NewClient(&redis.Options{ Addr: r.Addr, Password: r.Password, @@ -54,6 +70,10 @@ func (r *Redis) Connect() error { // Ping checks the redis connection func (r *Redis) Ping() error { + if r.Client == nil { + return errors.New("Connection not established yet") + } + _, err := r.Client.Ping().Result() if err != nil {