From cf03d1ea464e600a79dbd910c5ea44444dd62800 Mon Sep 17 00:00:00 2001 From: Raj Babu Das Date: Mon, 14 Mar 2022 13:11:22 +0530 Subject: [PATCH] Adding readiness routes to graphql-server and auth-server for readiness probes (#3495) * Adding probes Signed-off-by: rajdas98 * fix auth server for readiness endpoint Signed-off-by: rajdas98 * adding readiness route Signed-off-by: rajdas98 * revertg Signed-off-by: rajdas98 * revertg Signed-off-by: rajdas98 * changes Signed-off-by: rajdas98 * changes Signed-off-by: rajdas98 * changes Signed-off-by: rajdas98 --- USERS.md | 6 +- .../api/handlers/rest/misc_handlers.go | 71 ++++++++++ .../api/handlers/rest/user_handlers.go | 14 -- litmus-portal/authentication/api/main.go | 10 +- .../authentication/api/routes/misc_routers.go | 13 ++ .../authentication/api/routes/user_router.go | 1 - .../authentication/pkg/misc/repository.go | 46 ++++++ .../authentication/pkg/project/repository.go | 1 + .../pkg/services/application_service.go | 6 +- .../pkg/services/misc_service.go | 15 ++ .../authentication/pkg/user/repository.go | 2 + .../pkg/utils/mongo_database.go | 8 +- litmus-portal/graphql-server/go.sum | 11 -- .../pkg/database/mongodb/init.go | 10 +- .../pkg/database/mongodb/operations.go | 24 ++++ .../pkg/handlers/readiness_handler.go | 67 +++++++++ litmus-portal/graphql-server/server.go | 13 +- litmus-portal/namespaced-k8s-template.yml | 132 +++++++++--------- 18 files changed, 342 insertions(+), 108 deletions(-) create mode 100644 litmus-portal/authentication/api/handlers/rest/misc_handlers.go create mode 100644 litmus-portal/authentication/api/routes/misc_routers.go create mode 100644 litmus-portal/authentication/pkg/misc/repository.go create mode 100644 litmus-portal/authentication/pkg/services/misc_service.go create mode 100644 litmus-portal/graphql-server/pkg/handlers/readiness_handler.go diff --git a/USERS.md b/USERS.md index 3403e72e6fc..aad8f167b38 100644 --- a/USERS.md +++ b/USERS.md @@ -1,5 +1,5 @@ -This is a list of users that are using & benefited by LitmusChaos. Please send a PR to this file (along with details [here](./adopters/users)) -to add yourselves. +This is a list of users that are using & benefited by LitmusChaos. Please send a PR to this file (along with details [here](./adopters/users)) +to add yourselves. | User | Usecase | Details | @@ -10,4 +10,4 @@ to add yourselves. | [Bhaumik Shah](https://github.com/Bhaumik1802)|Use LitmusChaos for Kafka Resiliency on Dev/Staging|[My Story](adopters/users/Bhaumik_Shah.md)| | [Jayadeep KM](https://github.com/kmjayadeep)|Ensure reliability of microservices|[My Story](adopters/users/Jayadeep_KM.md)| | [Shantanu Deshpande](https://github.com/ishantanu)|Chaos Engineering Practice as SRE|[My Story](adopters/users/Shantanu_Deshpande.md)| -| [Omar Hanafi](https://github.com/oHanafi)|Performance Anomaly Detection in Cloud and Containerized Applications|Coming Soon!| +| [Omar Hanafi](https://github.com/oHanafi)|Performance Anomaly Detection in Cloud and Containerized Applications|Coming Soon!| \ No newline at end of file diff --git a/litmus-portal/authentication/api/handlers/rest/misc_handlers.go b/litmus-portal/authentication/api/handlers/rest/misc_handlers.go new file mode 100644 index 00000000000..ad7cf0cb503 --- /dev/null +++ b/litmus-portal/authentication/api/handlers/rest/misc_handlers.go @@ -0,0 +1,71 @@ +package rest + +import ( + "litmus/litmus-portal/authentication/pkg/entities" + "litmus/litmus-portal/authentication/pkg/services" + + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +func contains(s []string, str string) bool { + for _, v := range s { + if v == str { + return true + } + } + + return false +} + +type ReadinessAPIStatus struct { + DataBase string `json:"database"` + Collections string `json:"collections"` +} + +// Status will request users list and return, if successful, +// an http code 200 +func Status(service services.ApplicationService) gin.HandlerFunc { + return func(c *gin.Context) { + _, err := service.GetUsers() + if err != nil { + log.Error(err) + c.JSON(500, entities.APIStatus{"down"}) + return + } + c.JSON(200, entities.APIStatus{"up"}) + } +} + +func Readiness(service services.ApplicationService) gin.HandlerFunc { + return func(c *gin.Context) { + var ( + db_flag = "up" + col_flag = "up" + ) + + dbs, err := service.ListDataBase() + if !contains(dbs, "auth") { + db_flag = "down" + } + + if err != nil { + log.Error(err) + c.JSON(500, ReadinessAPIStatus{"down", "unknown"}) + return + } + + cols, err := service.ListCollection() + if !contains(cols, "project") || !contains(cols, "users") { + col_flag = "down" + } + + if err != nil { + log.Error(err) + c.JSON(500, ReadinessAPIStatus{db_flag, "down"}) + return + } + + c.JSON(200, ReadinessAPIStatus{db_flag, col_flag}) + } +} diff --git a/litmus-portal/authentication/api/handlers/rest/user_handlers.go b/litmus-portal/authentication/api/handlers/rest/user_handlers.go index a3adfcdd2d3..b1239861e68 100644 --- a/litmus-portal/authentication/api/handlers/rest/user_handlers.go +++ b/litmus-portal/authentication/api/handlers/rest/user_handlers.go @@ -14,20 +14,6 @@ import ( "golang.org/x/crypto/bcrypt" ) -// Status will request users list and return, if successful, -// an http code 200 -func Status(service services.ApplicationService) gin.HandlerFunc { - return func(c *gin.Context) { - _, err := service.GetUsers() - if err != nil { - log.Error(err) - c.JSON(500, entities.APIStatus{"down"}) - return - } - c.JSON(200, entities.APIStatus{"up"}) - } -} - func CreateUser(service services.ApplicationService) gin.HandlerFunc { return func(c *gin.Context) { userRole := c.MustGet("role").(string) diff --git a/litmus-portal/authentication/api/main.go b/litmus-portal/authentication/api/main.go index c0a052b270d..34d3945ea79 100644 --- a/litmus-portal/authentication/api/main.go +++ b/litmus-portal/authentication/api/main.go @@ -7,6 +7,7 @@ import ( grpcPresenter "litmus/litmus-portal/authentication/api/presenter/protos" "litmus/litmus-portal/authentication/api/routes" "litmus/litmus-portal/authentication/pkg/entities" + "litmus/litmus-portal/authentication/pkg/misc" "litmus/litmus-portal/authentication/pkg/project" "litmus/litmus-portal/authentication/pkg/services" "litmus/litmus-portal/authentication/pkg/user" @@ -53,11 +54,13 @@ func main() { flag.Parse() - db, err := utils.DatabaseConnection() + client, err := utils.MongoConnection() if err != nil { log.Fatal("database connection error $s", err) } + db := client.Database(utils.DBName) + // Creating User Collection err = utils.CreateCollection(utils.UserCollection, db) if err != nil { @@ -81,7 +84,9 @@ func main() { projectCollection := db.Collection(utils.ProjectCollection) projectRepo := project.NewRepo(projectCollection) - applicationService := services.NewService(userRepo, projectRepo, db) + miscRepo := misc.NewRepo(db, client) + + applicationService := services.NewService(userRepo, projectRepo, miscRepo, db) validatedAdminSetup(applicationService) @@ -145,6 +150,7 @@ func runRestServer(applicationService services.ApplicationService) { if utils.DexEnabled { routes.DexRouter(app, applicationService) } + routes.MiscRouter(app, applicationService) routes.UserRouter(app, applicationService) routes.ProjectRouter(app, applicationService) diff --git a/litmus-portal/authentication/api/routes/misc_routers.go b/litmus-portal/authentication/api/routes/misc_routers.go new file mode 100644 index 00000000000..78ef34da271 --- /dev/null +++ b/litmus-portal/authentication/api/routes/misc_routers.go @@ -0,0 +1,13 @@ +package routes + +import ( + "litmus/litmus-portal/authentication/api/handlers/rest" + "litmus/litmus-portal/authentication/pkg/services" + + "github.com/gin-gonic/gin" +) + +func MiscRouter(router *gin.Engine, service services.ApplicationService) { + router.GET("/status", rest.Status(service)) + router.GET("/readiness", rest.Readiness(service)) +} diff --git a/litmus-portal/authentication/api/routes/user_router.go b/litmus-portal/authentication/api/routes/user_router.go index 17dcacd8cc0..4de8e7597ab 100644 --- a/litmus-portal/authentication/api/routes/user_router.go +++ b/litmus-portal/authentication/api/routes/user_router.go @@ -10,7 +10,6 @@ import ( // UserRouter creates all the required routes for user authentications purposes. func UserRouter(router *gin.Engine, service services.ApplicationService) { - router.GET("/status", rest.Status(service)) router.POST("/login", rest.LoginUser(service)) router.Use(middleware.JwtMiddleware()) router.POST("/update/password", rest.UpdatePassword(service)) diff --git a/litmus-portal/authentication/pkg/misc/repository.go b/litmus-portal/authentication/pkg/misc/repository.go new file mode 100644 index 00000000000..1c60036f230 --- /dev/null +++ b/litmus-portal/authentication/pkg/misc/repository.go @@ -0,0 +1,46 @@ +package misc + +import ( + "context" + + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" +) + +//Repository holds the mongo database implementation of the Service +type Repository interface { + ListCollection() ([]string, error) + ListDataBase() ([]string, error) +} + +type repository struct { + DataBase *mongo.Database + Client *mongo.Client +} + +func (r repository) ListCollection() ([]string, error) { + var err error + cols, err := r.DataBase.ListCollectionNames(context.Background(), bson.D{}) + if err != nil { + return nil, err + } + + return cols, nil +} + +func (r repository) ListDataBase() ([]string, error) { + var err error + dbs, err := r.Client.ListDatabaseNames(context.Background(), bson.D{}) + if err != nil { + return nil, err + } + + return dbs, nil +} + +func NewRepo(db *mongo.Database, client *mongo.Client) Repository { + return &repository{ + DataBase: db, + Client: client, + } +} diff --git a/litmus-portal/authentication/pkg/project/repository.go b/litmus-portal/authentication/pkg/project/repository.go index 885c561343f..835242cf34c 100644 --- a/litmus-portal/authentication/pkg/project/repository.go +++ b/litmus-portal/authentication/pkg/project/repository.go @@ -36,6 +36,7 @@ type repository struct { // GetProject returns a project based on a query or filter value func (r repository) GetProjectByProjectID(projectID string) (*entities.Project, error) { var project = new(entities.Project) + findOneErr := r.Collection.FindOne(context.TODO(), bson.D{{"_id", projectID}}).Decode(&project) if findOneErr != nil { return nil, findOneErr diff --git a/litmus-portal/authentication/pkg/services/application_service.go b/litmus-portal/authentication/pkg/services/application_service.go index 7678af56dc7..5cfbd87604a 100644 --- a/litmus-portal/authentication/pkg/services/application_service.go +++ b/litmus-portal/authentication/pkg/services/application_service.go @@ -1,6 +1,7 @@ package services import ( + "litmus/litmus-portal/authentication/pkg/misc" "litmus/litmus-portal/authentication/pkg/project" "litmus/litmus-portal/authentication/pkg/user" @@ -11,19 +12,22 @@ type ApplicationService interface { userService projectService transactionService + miscService } type applicationService struct { userRepository user.Repository projectRepository project.Repository + miscRepository misc.Repository db *mongo.Database } // NewService creates a new instance of this service -func NewService(userRepo user.Repository, projectRepo project.Repository, db *mongo.Database) ApplicationService { +func NewService(userRepo user.Repository, projectRepo project.Repository, miscRepo misc.Repository, db *mongo.Database) ApplicationService { return &applicationService{ userRepository: userRepo, projectRepository: projectRepo, db: db, + miscRepository: miscRepo, } } diff --git a/litmus-portal/authentication/pkg/services/misc_service.go b/litmus-portal/authentication/pkg/services/misc_service.go new file mode 100644 index 00000000000..e2d9247da38 --- /dev/null +++ b/litmus-portal/authentication/pkg/services/misc_service.go @@ -0,0 +1,15 @@ +package services + +// Service creates a service for user authentication operations +type miscService interface { + ListCollection() ([]string, error) + ListDataBase() ([]string, error) +} + +func (a applicationService) ListCollection() ([]string, error) { + return a.miscRepository.ListCollection() +} + +func (a applicationService) ListDataBase() ([]string, error) { + return a.miscRepository.ListDataBase() +} diff --git a/litmus-portal/authentication/pkg/user/repository.go b/litmus-portal/authentication/pkg/user/repository.go index 517ecc88132..1b82256a37f 100644 --- a/litmus-portal/authentication/pkg/user/repository.go +++ b/litmus-portal/authentication/pkg/user/repository.go @@ -29,6 +29,8 @@ type Repository interface { type repository struct { Collection *mongo.Collection + DataBase *mongo.Database + Client *mongo.Client } // LoginUser helps to Login the user via OAuth, if user does not exists, creates a new user diff --git a/litmus-portal/authentication/pkg/utils/mongo_database.go b/litmus-portal/authentication/pkg/utils/mongo_database.go index 0b9e1dfc55b..acd7a545c76 100644 --- a/litmus-portal/authentication/pkg/utils/mongo_database.go +++ b/litmus-portal/authentication/pkg/utils/mongo_database.go @@ -11,8 +11,8 @@ import ( "go.mongodb.org/mongo-driver/mongo/options" ) -// DatabaseConnection creates a connection to the mongo database -func DatabaseConnection() (*mongo.Database, error) { +// MongoConnection creates a connection to the mongo +func MongoConnection() (*mongo.Client, error) { ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) mongoCredentials := options.Credential{ Username: DBUser, @@ -22,8 +22,8 @@ func DatabaseConnection() (*mongo.Database, error) { if err != nil { return nil, err } - db := client.Database(DBName) - return db, nil + + return client, nil } // CreateIndex creates a unique index for the given field in the collectionName diff --git a/litmus-portal/graphql-server/go.sum b/litmus-portal/graphql-server/go.sum index 11a56136c96..bcec1859db9 100644 --- a/litmus-portal/graphql-server/go.sum +++ b/litmus-portal/graphql-server/go.sum @@ -328,10 +328,8 @@ github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfc github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/prometheus-operator v0.34.0/go.mod h1:Li6rMllG/hYIyXfMuvUwhyC+hqwJVHdsDdP21hypT1M= github.com/coreos/rkt v1.30.0/go.mod h1:O634mlH6U7qk87poQifK6M2rsFNt+FyUTWNMnP1hF1U= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -1013,7 +1011,6 @@ github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQ github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/martinlindhe/base36 v1.0.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8= -github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg= github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -1314,9 +1311,7 @@ github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rubenv/sql-migrate v0.0.0-20191025130928-9355dd04f4b3/go.mod h1:WS0rl9eEliYI8DPnr3TOwz4439pay+qNgzJoVya/DmY= github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -1338,7 +1333,6 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= @@ -1445,9 +1439,7 @@ github.com/ultraware/funlen v0.0.1/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lP github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -1459,7 +1451,6 @@ github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/valyala/gozstd v1.7.0/go.mod h1:y5Ew47GLlP37EkTB+B4s7r6A5rdaeB7ftbl9zoYiIPQ= github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg= github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U= github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= @@ -1649,7 +1640,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1979,7 +1969,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6 h1:SIasE1FVIQOWz2GEAHFOmoW7xchJcqlucjSULTL0Ag4= golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/litmus-portal/graphql-server/pkg/database/mongodb/init.go b/litmus-portal/graphql-server/pkg/database/mongodb/init.go index 5b3f985ee7f..d21869478ec 100644 --- a/litmus-portal/graphql-server/pkg/database/mongodb/init.go +++ b/litmus-portal/graphql-server/pkg/database/mongodb/init.go @@ -30,7 +30,7 @@ const ( // MongoInterface requires a MongoClient that implements the Initialize method to create the Mongo DB client // and a initAllCollection method to initialize all DB Collections type MongoInterface interface { - Initialize() *MongoClient + Initialize(client *mongo.Client) *MongoClient initAllCollection() } @@ -74,8 +74,7 @@ var ( backgroundContext = context.Background() ) -// Initialize initializes database connection -func (m *MongoClient) Initialize() *MongoClient { +func MongoConnection() (*mongo.Client, error) { var ( dbServer = os.Getenv("DB_SERVER") dbUser = os.Getenv("DB_USER") @@ -107,6 +106,11 @@ func (m *MongoClient) Initialize() *MongoClient { logrus.Print("Connected To MongoDB") } + return client, nil +} + +// Initialize initializes database connection +func (m *MongoClient) Initialize(client *mongo.Client) *MongoClient { m.Database = client.Database(dbName) m.initAllCollection() return m diff --git a/litmus-portal/graphql-server/pkg/database/mongodb/operations.go b/litmus-portal/graphql-server/pkg/database/mongodb/operations.go index e22440ad38e..863b50216d7 100644 --- a/litmus-portal/graphql-server/pkg/database/mongodb/operations.go +++ b/litmus-portal/graphql-server/pkg/database/mongodb/operations.go @@ -22,6 +22,8 @@ type MongoOperator interface { CountDocuments(ctx context.Context, collectionType int, query bson.D, opts ...*options.CountOptions) (int64, error) Aggregate(ctx context.Context, collectionType int, pipeline interface{}, opts ...*options.AggregateOptions) (*mongo.Cursor, error) GetCollection(collectionType int) (*mongo.Collection, error) + ListCollection(ctx context.Context, mclient *mongo.Client) ([]string, error) + ListDataBase(ctx context.Context, mclient *mongo.Client) ([]string, error) } type MongoOperations struct{} @@ -37,10 +39,12 @@ func (m *MongoOperations) Create(ctx context.Context, collectionType int, docume if err != nil { return err } + _, err = collection.InsertOne(ctx, document) if err != nil { return err } + return nil } @@ -73,10 +77,12 @@ func (m *MongoOperations) List(ctx context.Context, collectionType int, query bs if err != nil { return nil, err } + result, err := collection.Find(ctx, query) if err != nil { return nil, err } + return result, nil } @@ -168,3 +174,21 @@ func (m *MongoOperations) Aggregate(ctx context.Context, collectionType int, pip func (m *MongoOperations) GetCollection(collectionType int) (*mongo.Collection, error) { return GetCollectionClient.getCollection(collectionType) } + +func (m *MongoOperations) ListDataBase(ctx context.Context, mclient *mongo.Client) ([]string, error) { + dbs, err := mclient.ListDatabaseNames(ctx, bson.D{}) + if err != nil { + return nil, err + } + + return dbs, nil +} + +func (m *MongoOperations) ListCollection(ctx context.Context, mclient *mongo.Client) ([]string, error) { + cols, err := mclient.Database("litmus").ListCollectionNames(ctx, bson.D{}) + if err != nil { + return nil, err + } + + return cols, nil +} diff --git a/litmus-portal/graphql-server/pkg/handlers/readiness_handler.go b/litmus-portal/graphql-server/pkg/handlers/readiness_handler.go new file mode 100644 index 00000000000..ce13ff6a2b5 --- /dev/null +++ b/litmus-portal/graphql-server/pkg/handlers/readiness_handler.go @@ -0,0 +1,67 @@ +package handlers + +import ( + "context" + "encoding/json" + "net/http" + + "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb" + "go.mongodb.org/mongo-driver/mongo" + + "github.com/litmuschaos/litmus/litmus-portal/graphql-server/utils" + "github.com/sirupsen/logrus" +) + +type ReadinessAPIStatus struct { + DataBase string `json:"database"` + Collections string `json:"collections"` +} + +func contains(s []string, str string) bool { + for _, v := range s { + if v == str { + return true + } + } + + return false +} + +func ReadinessHandler(handler http.Handler, mclient *mongo.Client) http.Handler { + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var ( + db_flag = "up" + col_flag = "up" + ) + + dbs, err := mongodb.Operator.ListDataBase(context.Background(), mclient) + if err != nil { + db_flag = "down" + } + + if !contains(dbs, "litmus") { + db_flag = "down" + } + + cols, err := mongodb.Operator.ListCollection(context.Background(), mclient) + if err != nil { + col_flag = "down" + } + + if !contains(cols, "gitops-collection") || !contains(cols, "server-config-collection") || !contains(cols, "workflow-collection") { + col_flag = "down" + } + + var status = ReadinessAPIStatus{Collections: col_flag, DataBase: db_flag} + statusByte, err := json.Marshal(status) + if err != nil { + logrus.Error(status) + utils.WriteHeaders(&w, 400) + } + + utils.WriteHeaders(&w, 200) + w.Write(statusByte) + }) + +} diff --git a/litmus-portal/graphql-server/server.go b/litmus-portal/graphql-server/server.go index b4f9a164c6b..67f2734b80d 100644 --- a/litmus-portal/graphql-server/server.go +++ b/litmus-portal/graphql-server/server.go @@ -113,8 +113,12 @@ func main() { rpcPort = utils.DefaultRPCPort } - // Initialize the mongo client - mongodb.Client = mongodb.Client.Initialize() + client, err := mongodb.MongoConnection() + if err != nil { + logrus.Fatal(err) + } + + mongodb.Client = mongodb.Client.Initialize(client) if err := validateVersion(); err != nil { logrus.Fatal(err) @@ -150,12 +154,15 @@ func main() { go myhub.RecurringHubSync() // go routine for syncing hubs for all users go gitOpsHandler.GitOpsSyncHandler(false) // routine to sync git repos for gitOps + // routers router.Handle("/", playground.Handler("GraphQL playground", "/query")) router.Handle("/query", authorization.Middleware(srv)) + router.Handle("/readiness", handlers.ReadinessHandler(srv, client)) + router.Handle("/icon/{ProjectID}/{HubName}/{ChartName}/{IconName}", authorization.RestMiddlewareWithRole(myhub.GetIconHandler, nil)).Methods("GET") + router.HandleFunc("/file/{key}{path:.yaml}", handlers.FileHandler) router.HandleFunc("/status", handlers.StatusHandler) - router.Handle("/icon/{ProjectID}/{HubName}/{ChartName}/{IconName}", authorization.RestMiddlewareWithRole(myhub.GetIconHandler, nil)).Methods("GET") logrus.Printf("connect to http://localhost:%s/ for GraphQL playground", httpPort) logrus.Fatal(http.ListenAndServe(":"+httpPort, router)) } diff --git a/litmus-portal/namespaced-k8s-template.yml b/litmus-portal/namespaced-k8s-template.yml index 252e77c7fa9..97744b10b1f 100644 --- a/litmus-portal/namespaced-k8s-template.yml +++ b/litmus-portal/namespaced-k8s-template.yml @@ -7,36 +7,36 @@ kind: Role metadata: name: argo-role-for-litmusportal-server rules: -- apiGroups: [""] - resources: [pods, pods/exec] - verbs: [create, get, list, watch, update, patch, delete] -- apiGroups: [""] - resources: [configmaps] - verbs: [get, watch, list] -- apiGroups: [""] - resources: [persistentvolumeclaims] - verbs: [create, delete] -- apiGroups: [argoproj.io] - resources: [workflows, workflows/finalizers] - verbs: [get, list, watch, update, patch, delete, create] -- apiGroups: [argoproj.io] - resources: [workflowtemplates, workflowtemplates/finalizers,workflowtasksets] - verbs: [get, list, watch] -- apiGroups: [""] - resources: [serviceaccounts] - verbs: [get, list] -- apiGroups: [""] - resources: [secrets] - verbs: [get] -- apiGroups: [argoproj.io] - resources: [cronworkflows, cronworkflows/finalizers] - verbs: [get, list, watch, update, patch, delete] -- apiGroups: [""] - resources: [events] - verbs: [create, patch] -- apiGroups: [policy] - resources: [poddisruptionbudgets] - verbs: [create, get, delete] + - apiGroups: [""] + resources: [pods, pods/exec] + verbs: [create, get, list, watch, update, patch, delete] + - apiGroups: [""] + resources: [configmaps] + verbs: [get, watch, list] + - apiGroups: [""] + resources: [persistentvolumeclaims] + verbs: [create, delete] + - apiGroups: [argoproj.io] + resources: [workflows, workflows/finalizers] + verbs: [get, list, watch, update, patch, delete, create] + - apiGroups: [argoproj.io] + resources: [workflowtemplates, workflowtemplates/finalizers,workflowtasksets] + verbs: [get, list, watch] + - apiGroups: [""] + resources: [serviceaccounts] + verbs: [get, list] + - apiGroups: [""] + resources: [secrets] + verbs: [get] + - apiGroups: [argoproj.io] + resources: [cronworkflows, cronworkflows/finalizers] + verbs: [get, list, watch, update, patch, delete] + - apiGroups: [""] + resources: [events] + verbs: [create, patch] + - apiGroups: [policy] + resources: [poddisruptionbudgets] + verbs: [create, get, delete] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding @@ -65,27 +65,27 @@ metadata: app.kubernetes.io/managed-by: kubectl name: litmus-namespace-scope-for-litmusportal-server rules: -- apiGroups: [""] - resources: [replicationcontrollers, secrets] - verbs: [get, list] -- apiGroups: [apps.openshift.io] - resources: [deploymentconfigs] - verbs: [get, list] -- apiGroups: [apps] - resources: [deployments, daemonsets, replicasets, statefulsets] - verbs: [get, list, update] -- apiGroups: [batch] - resources: [jobs] - verbs: [get, list, create, deletecollection] -- apiGroups: [argoproj.io] - resources: [rollouts] - verbs: [get, list] -- apiGroups: [""] - resources: [pods, pods/exec, configmaps, events, services] - verbs: [get, create, update, patch, delete, list, watch, deletecollection] -- apiGroups: [litmuschaos.io] - resources: [chaosengines, chaosexperiments, chaosresults] - verbs: [get, create, update, patch, delete, list, watch, deletecollection] + - apiGroups: [""] + resources: [replicationcontrollers, secrets] + verbs: [get, list] + - apiGroups: [apps.openshift.io] + resources: [deploymentconfigs] + verbs: [get, list] + - apiGroups: [apps] + resources: [deployments, daemonsets, replicasets, statefulsets] + verbs: [get, list, update] + - apiGroups: [batch] + resources: [jobs] + verbs: [get, list, create, deletecollection] + - apiGroups: [argoproj.io] + resources: [rollouts] + verbs: [get, list] + - apiGroups: [""] + resources: [pods, pods/exec, configmaps, events, services] + verbs: [get, create, update, patch, delete, list, watch, deletecollection] + - apiGroups: [litmuschaos.io] + resources: [chaosengines, chaosexperiments, chaosresults] + verbs: [get, create, update, patch, delete, list, watch, deletecollection] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding @@ -323,15 +323,15 @@ kind: Role metadata: name: event-tracker-role-for-litmusportal-server rules: -- apiGroups: [eventtracker.litmuschaos.io] - resources: [eventtrackerpolicies] - verbs: [create, delete, get, list, patch, update, watch] -- apiGroups: [eventtracker.litmuschaos.io] - resources: [eventtrackerpolicies/status] - verbs: [get, patch, update] -- apiGroups: ["", extensions, apps] - resources: [deployments, daemonsets, statefulsets, pods, configmaps] - verbs: [get, list, watch] + - apiGroups: [eventtracker.litmuschaos.io] + resources: [eventtrackerpolicies] + verbs: [create, delete, get, list, patch, update, watch] + - apiGroups: [eventtracker.litmuschaos.io] + resources: [eventtrackerpolicies/status] + verbs: [get, patch, update] + - apiGroups: ["", extensions, apps] + resources: [deployments, daemonsets, statefulsets, pods, configmaps] + verbs: [get, list, watch] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding @@ -557,7 +557,7 @@ spec: command: ["/bin/sh", "-c"] args: [ - "while [[ $(curl -sw '%{http_code}' http://mongo-service:27017 -o /dev/null) -ne 200 ]]; do sleep 5; echo 'Waiting for the MongoDB to be ready...'; done; echo 'Connection with MongoDB established'", + "while [[ $(curl -sw '%{http_code}' http://mongo-service:27017 -o /dev/null) -ne 200 ]]; do sleep 5; echo 'Waiting for the MongoDB to be ready...'; done; echo 'Connection with MongoDB established'", ] resources: requests: @@ -662,7 +662,7 @@ spec: targetPort: 3000 - name: auth-rpc-server port: 3030 - targetPort: 3030 + targetPort: 3030 selector: component: litmusportal-server --- @@ -689,7 +689,7 @@ spec: command: ["/bin/sh", "-c"] args: [ - "while [[ $(curl -sw '%{http_code}' http://mongo-service:27017 -o /dev/null) -ne 200 ]]; do sleep 5; echo 'Waiting for the MongoDB to be ready...'; done; echo 'Connection with MongoDB established'", + "while [[ $(curl -sw '%{http_code}' http://mongo-service:27017 -o /dev/null) -ne 200 ]]; do sleep 5; echo 'Waiting for the MongoDB to be ready...'; done; echo 'Connection with MongoDB established'", ] resources: requests: @@ -750,7 +750,7 @@ spec: targetPort: 3000 - name: auth-rpc-server port: 3030 - targetPort: 3030 + targetPort: 3030 selector: component: litmusportal-auth-server --- @@ -776,7 +776,7 @@ spec: - name: mongo image: litmuschaos/mongo:4.2.8 securityContext: -# runAsUser: 2000 + # runAsUser: 2000 allowPrivilegeEscalation: false args: ["--ipv6"] ports: @@ -840,4 +840,4 @@ spec: - port: 27017 targetPort: 27017 selector: - component: database + component: database \ No newline at end of file