...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/dashboard/apiserver/server.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/dashboard/apiserver

     1  // Copyright 2021 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  
    16  package apiserver
    17  
    18  import (
    19  	"fmt"
    20  	"net"
    21  	"net/http"
    22  
    23  	"github.com/gin-contrib/pprof"
    24  	"github.com/gin-gonic/gin"
    25  	"github.com/gin-gonic/gin/binding"
    26  	"github.com/go-playground/validator/v10"
    27  	"go.uber.org/fx"
    28  
    29  	config "github.com/chaos-mesh/chaos-mesh/pkg/config/dashboard"
    30  	"github.com/chaos-mesh/chaos-mesh/pkg/dashboard/apivalidator"
    31  	"github.com/chaos-mesh/chaos-mesh/pkg/dashboard/swaggerserver"
    32  	"github.com/chaos-mesh/chaos-mesh/pkg/dashboard/uiserver"
    33  )
    34  
    35  var (
    36  	// Module includes the providers (gin engine and api router) and the registers.
    37  	Module = fx.Options(
    38  		fx.Provide(
    39  			newEngine,
    40  			newAPIRouter,
    41  		),
    42  		handlerModule,
    43  		fx.Invoke(register),
    44  	)
    45  )
    46  
    47  func register(r *gin.Engine, conf *config.ChaosDashboardConfig) {
    48  	listenAddr := net.JoinHostPort(conf.ListenHost, fmt.Sprintf("%d", conf.ListenPort))
    49  
    50  	go r.Run(listenAddr)
    51  }
    52  
    53  func newEngine(config *config.ChaosDashboardConfig) *gin.Engine {
    54  	r := gin.Default()
    55  
    56  	// default is "/debug/pprof"
    57  	pprof.Register(r)
    58  
    59  	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
    60  		v.RegisterValidation("NameValid", apivalidator.NameValid)
    61  		v.RegisterValidation("NamespaceSelectorsValid", apivalidator.NamespaceSelectorsValid)
    62  		v.RegisterValidation("MapSelectorsValid", apivalidator.MapSelectorsValid)
    63  		v.RegisterValidation("RequirementSelectorsValid", apivalidator.RequirementSelectorsValid)
    64  		v.RegisterValidation("PhaseSelectorsValid", apivalidator.PhaseSelectorsValid)
    65  		v.RegisterValidation("CronValid", apivalidator.CronValid)
    66  		v.RegisterValidation("DurationValid", apivalidator.DurationValid)
    67  		v.RegisterValidation("ValueValid", apivalidator.ValueValid)
    68  		v.RegisterValidation("PodsValid", apivalidator.PodsValid)
    69  		v.RegisterValidation("RequiredFieldEqual", apivalidator.RequiredFieldEqualValid, true)
    70  	}
    71  
    72  	ui := uiserver.AssetsFS()
    73  	if ui != nil {
    74  		r.GET("/", func(c *gin.Context) {
    75  			c.FileFromFS("/", ui)
    76  		})
    77  		// `/:foo/*bar` from https://en.wikipedia.org/wiki/Foobar, the name itself has no meaning.
    78  		//
    79  		// This handle just internally redirects all no-exact routes to the root directory of static files because the UI is a single page application and only has one entry (index.html).
    80  		r.GET("/:foo", func(c *gin.Context) {
    81  			c.FileFromFS("/", ui)
    82  		})
    83  		r.GET("/:foo/*bar", func(c *gin.Context) {
    84  			c.FileFromFS("/", ui)
    85  		})
    86  
    87  		renderStatic := func(c *gin.Context) {
    88  			c.FileFromFS(c.Request.URL.Path, ui)
    89  		}
    90  		r.GET("/static/*any", renderStatic)
    91  		r.GET("/favicon.ico", renderStatic)
    92  	} else {
    93  		r.GET("/", func(c *gin.Context) {
    94  			c.String(http.StatusOK, `Dashboard UI is not built.
    95  Please run UI=1 make.
    96  Run UI=1 make images/chaos-dashboard/bin/chaos-dashboard if you only want to build dashboard only.
    97  (Note: If you only want to build the binary in local, pass IN_DOCKER=1)`)
    98  		})
    99  	}
   100  
   101  	return r
   102  }
   103  
   104  func newAPIRouter(r *gin.Engine) *gin.RouterGroup {
   105  	api := r.Group("/api")
   106  
   107  	api.GET("/swagger/*any", swaggerserver.Handler)
   108  
   109  	return api
   110  }
   111