From 451346b40bce2bdfa91adf8185adb3648231e232 Mon Sep 17 00:00:00 2001 From: Yue Yang Date: Thu, 1 Jul 2021 16:49:25 +0800 Subject: [PATCH 1/4] chore(api): use direct routes Signed-off-by: Yue Yang --- Makefile | 10 +++--- cmd/chaos-dashboard/main.go | 16 +++++----- pkg/apiserver/archive/archive_test.go | 44 --------------------------- pkg/apiserver/server.go | 35 +++++++++------------ pkg/config/dashboard/dashboard.go | 5 ++- pkg/core/experiment.go | 22 ++++++-------- pkg/core/schedule.go | 22 ++++++-------- pkg/core/workflow.go | 12 ++++---- pkg/store/event/event.go | 26 +--------------- pkg/store/experiment/experiment.go | 4 +-- pkg/store/schedule/schedule.go | 4 +-- pkg/store/workflow/workflow.go | 3 +- ui/package.json | 2 +- ui/src/App.tsx | 2 +- 14 files changed, 62 insertions(+), 145 deletions(-) diff --git a/Makefile b/Makefile index bf76288292..7fddcc49ee 100644 --- a/Makefile +++ b/Makefile @@ -25,14 +25,14 @@ endif # Enable GO111MODULE=on explicitly, disable it with GO111MODULE=off when necessary. export GO111MODULE := on -GOOS := $(if $(GOOS),$(GOOS),"") +GOOS := $(if $(GOOS),$(GOOS),"") GOARCH := $(if $(GOARCH),$(GOARCH),"") GOENV := GO15VENDOREXPERIMENT="1" CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) -CGOENV := GO15VENDOREXPERIMENT="1" CGO_ENABLED=1 GOOS=$(GOOS) GOARCH=$(GOARCH) +CGOENV := GO15VENDOREXPERIMENT="1" CGO_ENABLED=1 GOOS=$(GOOS) GOARCH=$(GOARCH) GO := $(GOENV) go CGO := $(CGOENV) go GOTEST := TEST_USE_EXISTING_CLUSTER=false NO_PROXY="${NO_PROXY},testhost" go test -SHELL := bash +SHELL := bash PACKAGE_LIST := echo $$(go list ./... | grep -vE "chaos-mesh/test|pkg/ptrace|zz_generated|vendor") github.com/chaos-mesh/chaos-mesh/api/v1alpha1 @@ -115,8 +115,8 @@ endif ui: yarn_dependencies ifeq (${UI},1) - cd ui &&\ - yarn build + # cd ui &&\ + # yarn build hack/embed_ui_assets.sh endif diff --git a/cmd/chaos-dashboard/main.go b/cmd/chaos-dashboard/main.go index cbe36cc58c..d0ad287fab 100644 --- a/cmd/chaos-dashboard/main.go +++ b/cmd/chaos-dashboard/main.go @@ -38,7 +38,7 @@ import ( ) var ( - log = ctrl.Log.WithName("setup") + log = ctrl.Log.WithName("dashboard") ) var ( @@ -46,7 +46,7 @@ var ( ) // @title Chaos Mesh Dashboard API -// @version 1.2 +// @version 2.0 // @description Swagger docs for Chaos Mesh Dashboard. If you encounter any problems with API, please click on the issues link below to report bugs or questions. // @contact.name Issues @@ -66,25 +66,26 @@ func main() { } ctrl.SetLogger(zap.New(zap.UseDevMode(true))) + mainLog := log.WithName("main") - dashboardConfig, err := config.EnvironChaosDashboard() + dashboardConfig, err := config.GetChaosDashboardEnv() if err != nil { - log.Error(err, "main: invalid ChaosDashboardConfig") + mainLog.Error(err, "invalid ChaosDashboardConfig") os.Exit(1) } dashboardConfig.Version = version.Get().GitVersion persistTTLConfigParsed, err := config.ParsePersistTTLConfig(dashboardConfig.PersistTTL) if err != nil { - log.Error(err, "main: invalid PersistTTLConfig") + mainLog.Error(err, "invalid PersistTTLConfig") os.Exit(1) } - controllerRuntimeStopCh := ctrl.SetupSignalHandler() + ctrlRuntimeStopCh := ctrl.SetupSignalHandler() app := fx.New( fx.Provide( func() (<-chan struct{}, *config.ChaosDashboardConfig, *ttlcontroller.TTLconfig) { - return controllerRuntimeStopCh, dashboardConfig, persistTTLConfigParsed + return ctrlRuntimeStopCh, dashboardConfig, persistTTLConfigParsed }, dbstore.NewDBStore, collector.NewServer, @@ -97,5 +98,4 @@ func main() { ) app.Run() - <-controllerRuntimeStopCh } diff --git a/pkg/apiserver/archive/archive_test.go b/pkg/apiserver/archive/archive_test.go index 5e140a27fa..8ad5d8f43e 100644 --- a/pkg/apiserver/archive/archive_test.go +++ b/pkg/apiserver/archive/archive_test.go @@ -55,10 +55,6 @@ func (m *MockExperimentStore) ListMeta(ctx context.Context, kind, namespace, nam var err error if kind == "testKind" { expMeta := &core.ExperimentMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: "testUID", Kind: "testKind", Name: "testName", @@ -84,10 +80,6 @@ func (m *MockExperimentStore) FindByUID(ctx context.Context, UID string) (*core. jsonStr, _ := json.Marshal(chaos) res = &core.Experiment{ ExperimentMeta: core.ExperimentMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: UID, Kind: v1alpha1.KindPodChaos, Name: "testName", @@ -104,10 +96,6 @@ func (m *MockExperimentStore) FindByUID(ctx context.Context, UID string) (*core. jsonStr, _ := json.Marshal(chaos) res = &core.Experiment{ ExperimentMeta: core.ExperimentMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: UID, Kind: v1alpha1.KindIOChaos, Name: "testName", @@ -124,10 +112,6 @@ func (m *MockExperimentStore) FindByUID(ctx context.Context, UID string) (*core. jsonStr, _ := json.Marshal(chaos) res = &core.Experiment{ ExperimentMeta: core.ExperimentMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: UID, Kind: v1alpha1.KindNetworkChaos, Name: "testName", @@ -144,10 +128,6 @@ func (m *MockExperimentStore) FindByUID(ctx context.Context, UID string) (*core. jsonStr, _ := json.Marshal(chaos) res = &core.Experiment{ ExperimentMeta: core.ExperimentMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: UID, Kind: v1alpha1.KindTimeChaos, Name: "testName", @@ -164,10 +144,6 @@ func (m *MockExperimentStore) FindByUID(ctx context.Context, UID string) (*core. jsonStr, _ := json.Marshal(chaos) res = &core.Experiment{ ExperimentMeta: core.ExperimentMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: UID, Kind: v1alpha1.KindKernelChaos, Name: "testName", @@ -184,10 +160,6 @@ func (m *MockExperimentStore) FindByUID(ctx context.Context, UID string) (*core. jsonStr, _ := json.Marshal(chaos) res = &core.Experiment{ ExperimentMeta: core.ExperimentMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: UID, Kind: v1alpha1.KindStressChaos, Name: "testName", @@ -202,10 +174,6 @@ func (m *MockExperimentStore) FindByUID(ctx context.Context, UID string) (*core. case "testOtherChaos": res = &core.Experiment{ ExperimentMeta: core.ExperimentMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: UID, Kind: "OtherChaos", Name: "testName", @@ -231,10 +199,6 @@ func (m *MockExperimentStore) FindMetaByUID(ctx context.Context, UID string) (*c switch UID { case "tsetUID": res = &core.ExperimentMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: "testUID", Kind: "testKind", Name: "testName", @@ -281,10 +245,6 @@ func (m *MockScheduleStore) ListMeta(ctx context.Context, namespace, name string var err error if name == "testScheduleName" { schMeta := &core.ScheduleMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: "testUID", Kind: "testKind", Name: "testScheduleName", @@ -310,10 +270,6 @@ func (m *MockScheduleStore) FindByUID(ctx context.Context, UID string) (*core.Sc jsonStr, _ := json.Marshal(sch) res = &core.Schedule{ ScheduleMeta: core.ScheduleMeta{ - ID: 0, - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: nil, UID: UID, Kind: v1alpha1.KindPodChaos, Name: "testName", diff --git a/pkg/apiserver/server.go b/pkg/apiserver/server.go index 97f6ea4bf8..3361cd6646 100644 --- a/pkg/apiserver/server.go +++ b/pkg/apiserver/server.go @@ -49,7 +49,7 @@ func serverRegister(r *gin.Engine, conf *config.ChaosDashboardConfig) { go r.Run(listenAddr) } -func newEngine() *gin.Engine { +func newEngine(config *config.ChaosDashboardConfig) *gin.Engine { r := gin.Default() // default is "/debug/pprof/" @@ -70,20 +70,25 @@ func newEngine() *gin.Engine { v.RegisterValidation("RequiredFieldEqual", apivalidator.RequiredFieldEqualValid, true) } - moveToUIRoot := func(c *gin.Context) { - c.Redirect(http.StatusMovedPermanently, "/dashboard") - } - - r.GET("/", moveToUIRoot) ui := uiserver.AssetsFS() if ui != nil { - newDashboardRouter(r, ui) + r.GET("/", func(c *gin.Context) { + c.FileFromFS("/", ui) + }) + r.GET("/:foo/*bar", func(c *gin.Context) { + c.FileFromFS("/", ui) + }) + + renderStatic := func(c *gin.Context) { + c.FileFromFS(c.Request.URL.Path, ui) + } + r.GET("/static/*any", renderStatic) + r.GET("/favicon.ico", renderStatic) } else { - r.GET("/dashboard", func(c *gin.Context) { + r.GET("/", func(c *gin.Context) { c.String(http.StatusOK, "Dashboard UI is not built. Please run `UI=1 make`.") }) } - r.NoRoute(moveToUIRoot) return r } @@ -96,15 +101,3 @@ func newAPIRouter(r *gin.Engine) *gin.RouterGroup { return api } - -func newDashboardRouter(r *gin.Engine, ui http.FileSystem) { - renderRequest := func(c *gin.Context) { - c.FileFromFS(c.Request.URL.Path, ui) - } - - r.GET("/dashboard/*any", func(c *gin.Context) { - c.FileFromFS("/", ui) - }) - r.GET("/static/*any", renderRequest) - r.GET("/favicon.ico", renderRequest) -} diff --git a/pkg/config/dashboard/dashboard.go b/pkg/config/dashboard/dashboard.go index 1778b95dfd..f3f661bcc3 100644 --- a/pkg/config/dashboard/dashboard.go +++ b/pkg/config/dashboard/dashboard.go @@ -37,7 +37,6 @@ type ChaosDashboardConfig struct { // EnableFilterNamespace will filter namespace with annotation. Only the pods/containers in namespace // annotated with `chaos-mesh.org/inject=enabled` will be injected EnableFilterNamespace bool `envconfig:"ENABLE_FILTER_NAMESPACE" default:"false"` - // SecurityMode will use the token login by the user if set to true SecurityMode bool `envconfig:"SECURITY_MODE" default:"true" json:"security_mode"` DNSServerCreate bool `envconfig:"DNS_SERVER_CREATE" default:"false" json:"dns_server_create"` @@ -60,8 +59,8 @@ type DatabaseConfig struct { Secret string `envconfig:"DATABASE_SECRET"` } -// EnvironChaosDashboard returns the settings from the environment. -func EnvironChaosDashboard() (*ChaosDashboardConfig, error) { +// GetChaosDashboardEnv gets all env variables related to dashboard. +func GetChaosDashboardEnv() (*ChaosDashboardConfig, error) { cfg := ChaosDashboardConfig{} err := envconfig.Process("", &cfg) return &cfg, err diff --git a/pkg/core/experiment.go b/pkg/core/experiment.go index cf7c3ba815..b10e388a12 100644 --- a/pkg/core/experiment.go +++ b/pkg/core/experiment.go @@ -21,6 +21,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" + "github.com/jinzhu/gorm" ) // ExperimentStore defines operations for working with experiments. @@ -64,18 +65,15 @@ type Experiment struct { // ExperimentMeta defines the metadata of an experiment. Use in db. type ExperimentMeta struct { - ID uint `gorm:"primary_key" json:"id"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - DeletedAt *time.Time `sql:"index" json:"deleted_at"` - UID string `gorm:"index:uid" json:"uid"` - Kind string `json:"kind"` - Name string `json:"name"` - Namespace string `json:"namespace"` - Action string `json:"action"` - StartTime time.Time `json:"start_time"` - FinishTime time.Time `json:"finish_time"` - Archived bool `json:"archived"` + gorm.Model + UID string `gorm:"index:uid" json:"uid"` + Kind string `json:"kind"` + Name string `json:"name"` + Namespace string `json:"namespace"` + Action string `json:"action"` + StartTime time.Time `json:"start_time"` + FinishTime time.Time `json:"finish_time"` + Archived bool `json:"archived"` } // ExperimentInfo defines a form data of Experiment from API. diff --git a/pkg/core/schedule.go b/pkg/core/schedule.go index 2aed45c4a1..b48b281bba 100644 --- a/pkg/core/schedule.go +++ b/pkg/core/schedule.go @@ -18,6 +18,7 @@ import ( "time" "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" + "github.com/jinzhu/gorm" ) // ScheduleStore defines operations for working with schedules. @@ -61,18 +62,15 @@ type Schedule struct { // ScheduleMeta defines the metadata of a schedule instance. Use in db. type ScheduleMeta struct { - ID uint `gorm:"primary_key" json:"id"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - DeletedAt *time.Time `sql:"index" json:"deleted_at"` - UID string `gorm:"index:uid" json:"uid"` - Kind string `json:"kind"` - Name string `json:"name"` - Namespace string `json:"namespace"` - Action string `json:"action"` - StartTime time.Time `json:"start_time"` - FinishTime time.Time `json:"finish_time"` - Archived bool `json:"archived"` + gorm.Model + UID string `gorm:"index:schedule_uid" json:"uid"` + Kind string `json:"kind"` + Name string `json:"name"` + Namespace string `json:"namespace"` + Action string `json:"action"` + StartTime time.Time `json:"start_time"` + FinishTime time.Time `json:"finish_time"` + Archived bool `json:"archived"` } // ScheduleInfo defines a form data of schedule from API. diff --git a/pkg/core/workflow.go b/pkg/core/workflow.go index b62cd00c26..dffdb9cd18 100644 --- a/pkg/core/workflow.go +++ b/pkg/core/workflow.go @@ -19,6 +19,7 @@ import ( "strings" "time" + "github.com/jinzhu/gorm" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,15 +50,14 @@ const ( // WorkflowMeta defines the root structure of a workflow. type WorkflowMeta struct { - ID uint `gorm:"primary_key" json:"id"` - Namespace string `json:"namespace"` - Name string `json:"name"` - // the entry node name - Entry string `json:"entry"` + gorm.Model + UID string `gorm:"index:workflow_uid" json:"uid"` + Namespace string `json:"namespace"` + Name string `json:"name"` + Entry string `json:"entry"` // the entry node name CreatedAt string `json:"created_at"` EndTime string `json:"end_time"` Status WorkflowStatus `json:"status,omitempty"` - UID string `gorm:"index:uid" json:"uid"` Archived bool `json:"-"` } diff --git a/pkg/store/event/event.go b/pkg/store/event/event.go index 1bb87f3172..d7f30db806 100644 --- a/pkg/store/event/event.go +++ b/pkg/store/event/event.go @@ -21,20 +21,16 @@ import ( "time" "github.com/jinzhu/gorm" - ctrl "sigs.k8s.io/controller-runtime" "github.com/chaos-mesh/chaos-mesh/pkg/core" "github.com/chaos-mesh/chaos-mesh/pkg/store/dbstore" ) -var log = ctrl.Log.WithName("store/event") - // NewStore return a new EventStore. func NewStore(db *dbstore.DB) core.EventStore { db.AutoMigrate(&core.Event{}) - es := &eventStore{db} - return es + return &eventStore{db} } type eventStore struct { @@ -250,23 +246,3 @@ func constructQueryArgs(experimentName, experimentNamespace, uid, kind, createTi return query, args } - -func splitArray(arr []uint, num int) [][]uint { - max := int(len(arr)) - if max < num { - return nil - } - var segments = make([][]uint, 0) - quantity := max / num - end := int(0) - for i := int(1); i <= num; i++ { - point := i * quantity - if i != num { - segments = append(segments, arr[i-1+end:point]) - } else { - segments = append(segments, arr[i-1+end:]) - } - end = point - i - } - return segments -} diff --git a/pkg/store/experiment/experiment.go b/pkg/store/experiment/experiment.go index 12ce429cb0..29ea1261be 100644 --- a/pkg/store/experiment/experiment.go +++ b/pkg/store/experiment/experiment.go @@ -30,9 +30,7 @@ var log = ctrl.Log.WithName("store/experiment") func NewStore(db *dbstore.DB) core.ExperimentStore { db.AutoMigrate(&core.Experiment{}) - es := &experimentStore{db} - - return es + return &experimentStore{db} } // DeleteIncompleteExperiments call core.ExperimentStore.DeleteIncompleteExperiments to deletes all incomplete experiments. diff --git a/pkg/store/schedule/schedule.go b/pkg/store/schedule/schedule.go index eec6d033d4..57cbf75530 100644 --- a/pkg/store/schedule/schedule.go +++ b/pkg/store/schedule/schedule.go @@ -30,9 +30,7 @@ var log = ctrl.Log.WithName("store/schedule") func NewStore(db *dbstore.DB) core.ScheduleStore { db.AutoMigrate(&core.Schedule{}) - es := &ScheduleStore{db} - - return es + return &ScheduleStore{db} } // DeleteIncompleteSchedules call core.ScheduleStore.DeleteIncompleteSchedules to deletes all incomplete schedules. diff --git a/pkg/store/workflow/workflow.go b/pkg/store/workflow/workflow.go index 2da4873bca..e7a30622d6 100644 --- a/pkg/store/workflow/workflow.go +++ b/pkg/store/workflow/workflow.go @@ -28,7 +28,8 @@ type WorkflowStore struct { func NewStore(db *dbstore.DB) core.WorkflowStore { db.AutoMigrate(&core.WorkflowEntity{}) - return &WorkflowStore{db: db} + + return &WorkflowStore{db} } func (it *WorkflowStore) List(ctx context.Context, namespace, name string, archived bool) ([]*core.WorkflowEntity, error) { diff --git a/ui/package.json b/ui/package.json index 0843557dab..dc2a435599 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "chaos-mesh-dashboard", - "version": "1.0.0", + "version": "2.0.0", "description": "A Web UI for Chaos Mesh", "private": true, "dependencies": { diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 37996f41c3..0a3836d6eb 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -6,7 +6,7 @@ import store from './store' const App = () => ( - + From 71b6e7fe53e95755f863a953434d13f25d7784cd Mon Sep 17 00:00:00 2001 From: Yue Yang Date: Thu, 1 Jul 2021 17:23:49 +0800 Subject: [PATCH 2/4] fix: makefile Signed-off-by: Yue Yang --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 7fddcc49ee..bff5f5d3a1 100644 --- a/Makefile +++ b/Makefile @@ -115,8 +115,8 @@ endif ui: yarn_dependencies ifeq (${UI},1) - # cd ui &&\ - # yarn build + cd ui &&\ + yarn build hack/embed_ui_assets.sh endif From 4c5bd57e945df7a10dcb514fa2da817a1cb2ac86 Mon Sep 17 00:00:00 2001 From: Yue Yang Date: Thu, 1 Jul 2021 17:56:13 +0800 Subject: [PATCH 3/4] fix(ci): imports Signed-off-by: Yue Yang --- pkg/core/experiment.go | 3 ++- pkg/core/schedule.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/core/experiment.go b/pkg/core/experiment.go index b10e388a12..caf85c12a1 100644 --- a/pkg/core/experiment.go +++ b/pkg/core/experiment.go @@ -20,8 +20,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" "github.com/jinzhu/gorm" + + "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" ) // ExperimentStore defines operations for working with experiments. diff --git a/pkg/core/schedule.go b/pkg/core/schedule.go index b48b281bba..887370a194 100644 --- a/pkg/core/schedule.go +++ b/pkg/core/schedule.go @@ -17,8 +17,9 @@ import ( "context" "time" - "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" "github.com/jinzhu/gorm" + + "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" ) // ScheduleStore defines operations for working with schedules. From 52abcf8a9dde897bc74b4d7b26f1a84c40780e45 Mon Sep 17 00:00:00 2001 From: Yue Yang Date: Fri, 2 Jul 2021 16:28:02 +0800 Subject: [PATCH 4/4] chore: address comments Signed-off-by: Yue Yang --- pkg/apiserver/server.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/apiserver/server.go b/pkg/apiserver/server.go index 3361cd6646..42e80463f9 100644 --- a/pkg/apiserver/server.go +++ b/pkg/apiserver/server.go @@ -75,6 +75,9 @@ func newEngine(config *config.ChaosDashboardConfig) *gin.Engine { r.GET("/", func(c *gin.Context) { c.FileFromFS("/", ui) }) + // `/:foo/*bar` from https://en.wikipedia.org/wiki/Foobar, the name itself has no meaning. + // + // 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). r.GET("/:foo/*bar", func(c *gin.Context) { c.FileFromFS("/", ui) })