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:
parent
98129e963a
commit
2913b0fcbd
|
@ -2,8 +2,9 @@ package authorization
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type contextKey string
|
type contextKey string
|
||||||
|
@ -30,8 +31,8 @@ func Middleware(handler http.Handler) http.Handler {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestMiddleware ...
|
// RestMiddlewareWithRole verifies jwt and checks if user has enough privilege to access route
|
||||||
func RestMiddleware(handler http.Handler) http.Handler {
|
func RestMiddlewareWithRole(handler http.Handler, roles []string) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
jwt := ""
|
jwt := ""
|
||||||
auth, err := r.Cookie(CookieName)
|
auth, err := r.Cookie(CookieName)
|
||||||
|
@ -40,14 +41,24 @@ func RestMiddleware(handler http.Handler) http.Handler {
|
||||||
} else if r.Header.Get("Authorization") != "" {
|
} else if r.Header.Get("Authorization") != "" {
|
||||||
jwt = r.Header.Get("Authorization")
|
jwt = r.Header.Get("Authorization")
|
||||||
}
|
}
|
||||||
_, err = UserValidateJWT(jwt)
|
user, err := UserValidateJWT(jwt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error in Cookie: ", err)
|
logrus.WithError(err).Error("Invalid Auth Cookie")
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
w.Write([]byte("Error verifying JWT token: " + err.Error()))
|
w.Write([]byte("Error verifying JWT token: " + err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if len(roles) == 0 {
|
||||||
handler.ServeHTTP(w, r)
|
handler.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, role := range roles {
|
||||||
|
if role == user["role"] {
|
||||||
|
handler.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,3 +82,17 @@ func GetClusterWithProjectID(projectID string, clusterType *string) ([]*Cluster,
|
||||||
|
|
||||||
return clusters, nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,22 @@ func GetProject(ctx context.Context, query bson.D) (*Project, error) {
|
||||||
return project, err
|
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
|
// GetProjectsByUserID returns a project based on the userID
|
||||||
func GetProjectsByUserID(ctx context.Context, userID string) ([]Project, error) {
|
func GetProjectsByUserID(ctx context.Context, userID string) ([]Project, error) {
|
||||||
var projects []Project
|
var projects []Project
|
||||||
|
|
|
@ -59,8 +59,7 @@ func GetUserByUserID(ctx context.Context, userID string) (*User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUsers returns the list of users present in the project
|
// GetUsers returns the list of users present in the project
|
||||||
func GetUsers(ctx context.Context) ([]User, error) {
|
func GetUsers(ctx context.Context, query bson.D) ([]User, error) {
|
||||||
query := bson.D{{}}
|
|
||||||
result, err := mongodb.Operator.List(ctx, mongodb.UserCollection, query)
|
result, err := mongodb.Operator.List(ctx, mongodb.UserCollection, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print("Error getting users : ", err)
|
log.Print("Error getting users : ", err)
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -6,12 +6,12 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
|
||||||
|
|
||||||
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/graph/model"
|
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/graph/model"
|
||||||
dbOperationsUserManagement "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/usermanagement"
|
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"
|
dbSchemaUserManagement "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/usermanagement"
|
||||||
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/project"
|
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/project"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
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
|
// 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) {
|
func GetUsers(ctx context.Context) ([]*model.User, error) {
|
||||||
|
|
||||||
users, err := dbOperationsUserManagement.GetUsers(ctx)
|
users, err := dbOperationsUserManagement.GetUsers(ctx, bson.D{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,22 +7,21 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb"
|
|
||||||
|
|
||||||
"github.com/99designs/gqlgen/graphql/handler"
|
"github.com/99designs/gqlgen/graphql/handler"
|
||||||
"github.com/99designs/gqlgen/graphql/handler/extension"
|
"github.com/99designs/gqlgen/graphql/handler/extension"
|
||||||
"github.com/99designs/gqlgen/graphql/handler/transport"
|
"github.com/99designs/gqlgen/graphql/handler/transport"
|
||||||
"github.com/99designs/gqlgen/graphql/playground"
|
"github.com/99designs/gqlgen/graphql/playground"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/gorilla/websocket"
|
"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"
|
||||||
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/graph/generated"
|
"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/authorization"
|
||||||
|
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb"
|
||||||
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/file_handlers"
|
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/file_handlers"
|
||||||
gitOpsHandler "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/gitops/handler"
|
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/myhub"
|
||||||
|
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/stat"
|
||||||
|
"github.com/rs/cors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultPort = "8080"
|
const defaultPort = "8080"
|
||||||
|
@ -75,7 +74,8 @@ func main() {
|
||||||
router.Handle("/", playground.Handler("GraphQL playground", "/query"))
|
router.Handle("/", playground.Handler("GraphQL playground", "/query"))
|
||||||
router.Handle("/query", authorization.Middleware(srv))
|
router.Handle("/query", authorization.Middleware(srv))
|
||||||
router.HandleFunc("/file/{key}{path:.yaml}", file_handlers.FileHandler)
|
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.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
|
||||||
log.Fatal(http.ListenAndServe(":"+port, router))
|
log.Fatal(http.ListenAndServe(":"+port, router))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue