Added endpoint for portal stats (#2891)

* added endpoint for portal stats

Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>
This commit is contained in:
Soumya Ghosh Dastidar 2021-06-14 09:39:01 +05:30 committed by GitHub
parent 98129e963a
commit 2913b0fcbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 142 additions and 17 deletions

View File

@ -2,8 +2,9 @@ package authorization
import (
"context"
"fmt"
"net/http"
"github.com/sirupsen/logrus"
)
type contextKey string
@ -30,8 +31,8 @@ func Middleware(handler http.Handler) http.Handler {
})
}
// RestMiddleware ...
func RestMiddleware(handler http.Handler) http.Handler {
// RestMiddlewareWithRole verifies jwt and checks if user has enough privilege to access route
func RestMiddlewareWithRole(handler http.Handler, roles []string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
jwt := ""
auth, err := r.Cookie(CookieName)
@ -40,14 +41,24 @@ func RestMiddleware(handler http.Handler) http.Handler {
} else if r.Header.Get("Authorization") != "" {
jwt = r.Header.Get("Authorization")
}
_, err = UserValidateJWT(jwt)
user, err := UserValidateJWT(jwt)
if err != nil {
fmt.Println("Error in Cookie: ", err)
logrus.WithError(err).Error("Invalid Auth Cookie")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Error verifying JWT token: " + err.Error()))
return
}
if len(roles) == 0 {
handler.ServeHTTP(w, r)
return
}
for _, role := range roles {
if role == user["role"] {
handler.ServeHTTP(w, r)
return
}
}
w.WriteHeader(http.StatusUnauthorized)
return
})
}

View File

@ -82,3 +82,17 @@ func GetClusterWithProjectID(projectID string, clusterType *string) ([]*Cluster,
return clusters, nil
}
// GetClusters returns all the clusters matching the query
func GetClusters(ctx context.Context, query bson.D) ([]*Cluster, error) {
var clusters []*Cluster
results, err := mongodb.Operator.List(ctx, mongodb.ClusterCollection, query)
if err != nil {
return []*Cluster{}, err
}
err = results.All(ctx, &clusters)
if err != nil {
return []*Cluster{}, err
}
return clusters, nil
}

View File

@ -41,6 +41,22 @@ func GetProject(ctx context.Context, query bson.D) (*Project, error) {
return project, err
}
// GetProjects takes a query parameter to retrieve the projects that match query
func GetProjects(ctx context.Context, query bson.D) ([]Project, error) {
results, err := mongodb.Operator.List(ctx, mongodb.ProjectCollection, query)
if err != nil {
return nil, err
}
var projects []Project
err = results.All(ctx, &projects)
if err != nil {
return nil, err
}
return projects, nil
}
// GetProjectsByUserID returns a project based on the userID
func GetProjectsByUserID(ctx context.Context, userID string) ([]Project, error) {
var projects []Project

View File

@ -59,8 +59,7 @@ func GetUserByUserID(ctx context.Context, userID string) (*User, error) {
}
// GetUsers returns the list of users present in the project
func GetUsers(ctx context.Context) ([]User, error) {
query := bson.D{{}}
func GetUsers(ctx context.Context, query bson.D) ([]User, error) {
result, err := mongodb.Operator.List(ctx, mongodb.UserCollection, query)
if err != nil {
log.Print("Error getting users : ", err)

View File

@ -0,0 +1,85 @@
package stat
import (
"encoding/json"
"net/http"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/cluster"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/project"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/usermanagement"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/workflow"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/utils"
"github.com/sirupsen/logrus"
"go.mongodb.org/mongo-driver/bson"
)
type AgentCount struct {
Namespaced int `json:"ns_scope"`
Cluster int `json:"cluster_scope"`
Total int `json:"total_count"`
}
type OverviewStat struct {
UserCount int `json:"user_count"`
ProjectCount int `json:"project_count"`
AgentCount AgentCount `json:"agent_count"`
WorkflowScheduleCount int `json:"schedule_count"`
WorkflowRunCount int `json:"run_count"`
}
//GetStats returns the portals overview
func GetStats(w http.ResponseWriter, r *http.Request) {
users, err := usermanagement.GetUsers(r.Context(), bson.D{})
if err != nil {
logrus.WithError(err).Errorf("failed to get users for stat")
utils.WriteHeaders(&w, http.StatusInternalServerError)
return
}
agentNS, err := cluster.GetClusters(r.Context(), bson.D{{"agent_scope", "namespace"}, {"is_removed", false}})
if err != nil {
logrus.WithError(err).Errorf("failed to get agents(ns) for stat")
utils.WriteHeaders(&w, http.StatusInternalServerError)
return
}
agents, err := cluster.GetClusters(r.Context(), bson.D{{"is_removed", false}})
if err != nil {
logrus.WithError(err).Errorf("failed to get agents for stat")
utils.WriteHeaders(&w, http.StatusInternalServerError)
return
}
projects, err := project.GetProjects(r.Context(), bson.D{})
if err != nil {
logrus.WithError(err).Errorf("failed to get projects for stat")
utils.WriteHeaders(&w, http.StatusInternalServerError)
return
}
workflows, err := workflow.GetWorkflows(bson.D{})
if err != nil {
logrus.WithError(err).Errorf("failed to get workflows for stat")
utils.WriteHeaders(&w, http.StatusInternalServerError)
return
}
runCount := 0
for _, workFlowInput := range workflows {
runCount += len(workFlowInput.WorkflowRuns)
}
overview := OverviewStat{
UserCount: len(users),
ProjectCount: len(projects),
WorkflowRunCount: runCount,
WorkflowScheduleCount: len(workflows),
AgentCount: AgentCount{
Namespaced: len(agentNS),
Total: len(agents),
Cluster: len(agents) - len(agentNS),
},
}
data, err := json.Marshal(overview)
if err != nil {
logrus.WithError(err).Errorf("failed to marshal stat")
utils.WriteHeaders(&w, http.StatusInternalServerError)
return
}
utils.WriteHeaders(&w, http.StatusOK)
w.Write(data)
}

View File

@ -6,12 +6,12 @@ import (
"log"
"time"
"go.mongodb.org/mongo-driver/mongo"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/graph/model"
dbOperationsUserManagement "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/usermanagement"
dbSchemaUserManagement "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/usermanagement"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/project"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
const (
@ -73,7 +73,7 @@ func GetUser(ctx context.Context, username string) (*model.User, error) {
// GetUsers queries the list of all the users from the DB and returns it in the appropriate format
func GetUsers(ctx context.Context) ([]*model.User, error) {
users, err := dbOperationsUserManagement.GetUsers(ctx)
users, err := dbOperationsUserManagement.GetUsers(ctx, bson.D{})
if err != nil {
return nil, err
}

View File

@ -7,22 +7,21 @@ import (
"runtime"
"time"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/handler/extension"
"github.com/99designs/gqlgen/graphql/handler/transport"
"github.com/99designs/gqlgen/graphql/playground"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
"github.com/rs/cors"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/graph"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/graph/generated"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/authorization"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/file_handlers"
gitOpsHandler "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/gitops/handler"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/myhub"
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/stat"
"github.com/rs/cors"
)
const defaultPort = "8080"
@ -75,7 +74,8 @@ func main() {
router.Handle("/", playground.Handler("GraphQL playground", "/query"))
router.Handle("/query", authorization.Middleware(srv))
router.HandleFunc("/file/{key}{path:.yaml}", file_handlers.FileHandler)
router.Handle("/icon/{ProjectID}/{HubName}/{ChartName}/{IconName}", authorization.RestMiddleware(myhub.GetIconHandler)).Methods("GET")
router.Handle("/icon/{ProjectID}/{HubName}/{ChartName}/{IconName}", authorization.RestMiddlewareWithRole(myhub.GetIconHandler, nil)).Methods("GET")
router.Handle("/stats", authorization.RestMiddlewareWithRole(http.HandlerFunc(stat.GetStats), []string{"admin"})).Methods("GET")
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
log.Fatal(http.ListenAndServe(":"+port, router))