...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package apiserver
15
16 import (
17 "fmt"
18 "net/http"
19
20 "go.uber.org/fx"
21
22 "github.com/gin-contrib/pprof"
23 "github.com/gin-gonic/gin"
24 "github.com/gin-gonic/gin/binding"
25 "github.com/go-playground/validator/v10"
26
27 apiutils "github.com/chaos-mesh/chaos-mesh/pkg/apiserver/utils"
28 "github.com/chaos-mesh/chaos-mesh/pkg/apivalidator"
29 "github.com/chaos-mesh/chaos-mesh/pkg/config"
30 "github.com/chaos-mesh/chaos-mesh/pkg/swaggerserver"
31 "github.com/chaos-mesh/chaos-mesh/pkg/uiserver"
32 )
33
34 var (
35
36 Module = fx.Options(
37 fx.Provide(
38 newEngine,
39 newAPIRouter,
40 ),
41 handlerModule,
42 fx.Invoke(serverRegister),
43 )
44 )
45
46 func serverRegister(r *gin.Engine, conf *config.ChaosDashboardConfig) {
47 listenAddr := fmt.Sprintf("%s:%d", conf.ListenHost, conf.ListenPort)
48
49 go r.Run(listenAddr)
50 }
51
52 func newEngine() *gin.Engine {
53 r := gin.Default()
54
55
56 pprof.Register(r)
57
58 r.Use(apiutils.MWHandleErrors())
59
60 if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
61 v.RegisterValidation("NameValid", apivalidator.NameValid)
62 v.RegisterValidation("NamespaceSelectorsValid", apivalidator.NamespaceSelectorsValid)
63 v.RegisterValidation("MapSelectorsValid", apivalidator.MapSelectorsValid)
64 v.RegisterValidation("RequirementSelectorsValid", apivalidator.RequirementSelectorsValid)
65 v.RegisterValidation("PhaseSelectorsValid", apivalidator.PhaseSelectorsValid)
66 v.RegisterValidation("CronValid", apivalidator.CronValid)
67 v.RegisterValidation("DurationValid", apivalidator.DurationValid)
68 v.RegisterValidation("ValueValid", apivalidator.ValueValid)
69 v.RegisterValidation("PodsValid", apivalidator.PodsValid)
70 v.RegisterValidation("RequiredFieldEqual", apivalidator.RequiredFieldEqualValid, true)
71 }
72
73 moveToUIRoot := func(c *gin.Context) {
74 c.Redirect(http.StatusMovedPermanently, "/dashboard")
75 }
76
77 r.GET("/", moveToUIRoot)
78 ui := uiserver.AssetsFS()
79 if ui != nil {
80 newDashboardRouter(r, ui)
81 } else {
82 r.GET("/dashboard", func(c *gin.Context) {
83 c.String(http.StatusOK, "Dashboard UI is not built. Please run `UI=1 make`.")
84 })
85 }
86 r.NoRoute(moveToUIRoot)
87
88 return r
89 }
90
91 func newAPIRouter(r *gin.Engine) *gin.RouterGroup {
92 api := r.Group("/api")
93 {
94 api.GET("/swagger/*any", swaggerserver.Handler())
95 }
96
97 return api
98 }
99
100 func newDashboardRouter(r *gin.Engine, ui http.FileSystem) {
101 renderRequest := func(c *gin.Context) {
102 c.FileFromFS(c.Request.URL.Path, ui)
103 }
104
105 r.GET("/dashboard/*any", func(c *gin.Context) {
106 c.FileFromFS("/", ui)
107 })
108 r.GET("/static/*any", renderRequest)
109 r.GET("/favicon.ico", renderRequest)
110 }
111