Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use YAML format as experiment description #1029

Merged
merged 31 commits into from
Oct 26, 2020
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
36d22d8
chore(init): renew editor
g1eny0ung Sep 25, 2020
d408fb4
chore: update
g1eny0ung Oct 9, 2020
4911302
fix: bugs
g1eny0ung Oct 10, 2020
8671e5f
Merge branch 'master' into feat/yaml-editor
g1eny0ung Oct 10, 2020
dfdc291
chore: update
g1eny0ung Oct 12, 2020
9be13c9
Merge branch 'master' into feat/yaml-editor
g1eny0ung Oct 12, 2020
e21f66a
fix: error
g1eny0ung Oct 12, 2020
3ee2971
fix: error
g1eny0ung Oct 12, 2020
cd84849
Merge branch 'master' into feat/yaml-editor
g1eny0ung Oct 12, 2020
a5da5a3
fix(try): ci
g1eny0ung Oct 12, 2020
4cbbb52
chore: diff to stdout
g1eny0ung Oct 12, 2020
209da8d
fix(debug): comment diff
g1eny0ung Oct 12, 2020
2de25fd
fix(debug): ci
g1eny0ung Oct 12, 2020
1ac6a98
chore: recover
g1eny0ung Oct 12, 2020
1009317
chore: update
g1eny0ung Oct 13, 2020
5cc08ad
Merge branch 'master' into feat/yaml-editor
g1eny0ung Oct 13, 2020
934322b
chore: update
g1eny0ung Oct 13, 2020
4b4b2c2
fix: yamlToExperiment
g1eny0ung Oct 13, 2020
3cede7f
Merge branch 'master' into feat/yaml-editor
g1eny0ung Oct 14, 2020
f777b24
fix: should set string when error occurred
g1eny0ung Oct 15, 2020
a8594fd
chore: update
g1eny0ung Oct 15, 2020
6e81d11
chore: change log style
g1eny0ung Oct 16, 2020
46dcdf6
Merge branch 'master' into feat/yaml-editor
g1eny0ung Oct 16, 2020
b214749
fix: typo
g1eny0ung Oct 16, 2020
06d6395
Merge branch 'feat/yaml-editor' of https://github.com/g1eny0ung/chaos…
g1eny0ung Oct 16, 2020
38e073c
Merge branch 'master' into feat/yaml-editor
g1eny0ung Oct 19, 2020
d9da6be
Merge branch 'master' into feat/yaml-editor
g1eny0ung Oct 21, 2020
49a29ea
Merge branch 'master' into feat/yaml-editor
g1eny0ung Oct 23, 2020
acdbef5
fix: no scheduler problem
g1eny0ung Oct 23, 2020
6c3a32e
Merge branch 'master' into feat/yaml-editor
ti-srebot Oct 26, 2020
4bcf249
Merge branch 'master' into feat/yaml-editor
ti-srebot Oct 26, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -34,6 +34,7 @@ require (
github.com/lib/pq v1.2.0 // indirect
github.com/mattn/go-runewidth v0.0.8 // indirect
github.com/mgechev/revive v1.0.2-0.20200225072153-6219ca02fffb
github.com/mitchellh/mapstructure v1.3.3
github.com/morikuni/aec v1.0.0 // indirect
github.com/onsi/ginkgo v1.12.0
github.com/onsi/gomega v1.9.0
Expand Down
9 changes: 2 additions & 7 deletions go.sum
Expand Up @@ -49,7 +49,6 @@ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIO
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
Expand All @@ -69,7 +68,6 @@ github.com/bazelbuild/rules_go v0.0.0-20190719190356-6dae44dc5cab/go.mod h1:MC23
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU=
github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs=
Expand Down Expand Up @@ -283,7 +281,6 @@ github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTM
github.com/go-playground/overalls v0.0.0-20180201144345-22ec1a223b7c/go.mod h1:UqxAgEOt89sCiXlrc/ycnx00LVvUO/eS8tMUkWX4R7w=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-playground/validator/v10 v10.3.0 h1:nZU+7q+yJoFmwvNgv/LnPUkwPal62+b2xXj0AU1Es7o=
github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
Expand Down Expand Up @@ -336,7 +333,6 @@ github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
Expand Down Expand Up @@ -476,7 +472,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
Expand Down Expand Up @@ -551,8 +546,9 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down Expand Up @@ -1024,7 +1020,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25 h1:Ev7yu1/f6+d+b3pi5vPdRPc6nNtP1umSfcWiEfRqv6I=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
Expand Down
251 changes: 251 additions & 0 deletions pkg/apiserver/archive/archive.go
@@ -0,0 +1,251 @@
// Copyright 2020 Chaos Mesh Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package archive

import (
"context"
"fmt"
"net/http"
"time"

"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"

"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
"github.com/chaos-mesh/chaos-mesh/pkg/apiserver/utils"
"github.com/chaos-mesh/chaos-mesh/pkg/core"
)

// Service defines a handler service for archive experiments.
type Service struct {
archive core.ExperimentStore
event core.EventStore
}

// NewService returns an archive experiment service instance.
func NewService(
archive core.ExperimentStore,
event core.EventStore,
) *Service {
return &Service{
archive: archive,
event: event,
}
}

// Register mounts our HTTP handler on the mux.
func Register(r *gin.RouterGroup, s *Service) {
endpoint := r.Group("/archives")

endpoint.GET("", s.list)
endpoint.GET("/detail", s.detail)
endpoint.GET("/report", s.report)
}

// Archive defines the basic information of an archive.
type Archive struct {
UID string `json:"uid"`
Kind string `json:"kind"`
Namespace string `json:"namespace"`
Name string `json:"name"`
Action string `json:"action"`
StartTime time.Time `json:"start_time"`
FinishTime time.Time `json:"finish_time"`
}

// Detail represents an archive instance.
type Detail struct {
Archive
YAML core.ExperimentYAMLDescription `json:"yaml"`
}

// Report defines the report of archive experiments.
type Report struct {
Meta *Archive `json:"meta"`
Events []*core.Event `json:"events"`
TotalTime string `json:"total_time"`
TotalFaultTime string `json:"total_fault_time"`
}

// @Summary Get archived chaos experiments.
// @Description Get archived chaos experiments.
// @Tags archives
// @Produce json
// @Param namespace query string false "namespace"
// @Param name query string false "name"
// @Param kind query string false "kind" Enums(PodChaos, IoChaos, NetworkChaos, TimeChaos, KernelChaos, StressChaos)
// @Success 200 {array} Archive
// @Router /archives [get]
// @Failure 500 {object} utils.APIError
func (s *Service) list(c *gin.Context) {
kind := c.Query("kind")
name := c.Query("name")
ns := c.Query("namespace")

data, err := s.archive.ListMeta(context.Background(), kind, ns, name, true)
if err != nil {
c.Status(http.StatusInternalServerError)
_ = c.Error(utils.ErrInternalServer.NewWithNoMessage())
return
}

archives := make([]Archive, 0)

for _, d := range data {
archives = append(archives, Archive{
UID: d.UID,
Kind: d.Kind,
Namespace: d.Namespace,
Name: d.Name,
Action: d.Action,
StartTime: d.StartTime,
FinishTime: d.FinishTime,
})
}

c.JSON(http.StatusOK, archives)
}

// @Summary Get the detail of an archived chaos experiment.
// @Description Get the detail of an archived chaos experiment.
// @Tags archives
// @Produce json
// @Param uid query string true "uid"
// @Success 200 {object} Detail
// @Router /archives/detail [get]
// @Failure 500 {object} utils.APIError
func (s *Service) detail(c *gin.Context) {
var (
err error
yaml core.ExperimentYAMLDescription
detail Detail
)
uid := c.Query("uid")

if uid == "" {
c.Status(http.StatusBadRequest)
_ = c.Error(utils.ErrInvalidRequest.New("uid cannot be empty"))
return
}

data, err := s.archive.FindByUID(context.Background(), uid)
if err != nil {
if !gorm.IsRecordNotFoundError(err) {
c.Status(http.StatusInternalServerError)
_ = c.Error(utils.ErrInternalServer.NewWithNoMessage())
} else {
c.Status(http.StatusInternalServerError)
_ = c.Error(utils.ErrInvalidRequest.New("the archive is not found"))
}
return
}

switch data.Kind {
case v1alpha1.KindPodChaos:
yaml, err = data.ParsePodChaos()
case v1alpha1.KindIoChaos:
yaml, err = data.ParseIOChaos()
case v1alpha1.KindNetworkChaos:
yaml, err = data.ParseNetworkChaos()
case v1alpha1.KindTimeChaos:
yaml, err = data.ParseTimeChaos()
case v1alpha1.KindKernelChaos:
yaml, err = data.ParseKernelChaos()
case v1alpha1.KindStressChaos:
yaml, err = data.ParseStressChaos()
default:
err = fmt.Errorf("kind %s is not support", data.Kind)
}
if err != nil {
c.Status(http.StatusInternalServerError)
_ = c.Error(utils.ErrInternalServer.WrapWithNoMessage(err))
return
}

detail = Detail{
Archive: Archive{
UID: data.UID,
Kind: data.Kind,
Name: data.Name,
Namespace: data.Namespace,
Action: data.Action,
StartTime: data.StartTime,
FinishTime: data.FinishTime,
},
YAML: yaml,
}

c.JSON(http.StatusOK, detail)
}

// @Summary Get the report of an archived chaos experiment.
// @Description Get the report of an archived chaos experiment.
// @Tags archives
// @Produce json
// @Param uid query string true "uid"
// @Success 200 {array} Report
// @Router /archives/report [get]
// @Failure 500 {object} utils.APIError
func (s *Service) report(c *gin.Context) {
var (
err error
report Report
)
uid := c.Query("uid")

if uid == "" {
c.Status(http.StatusBadRequest)
_ = c.Error(utils.ErrInvalidRequest.New("uid cannot be empty"))
return
}

meta, err := s.archive.FindMetaByUID(context.Background(), uid)
if err != nil {
if !gorm.IsRecordNotFoundError(err) {
c.Status(http.StatusInternalServerError)
_ = c.Error(utils.ErrInternalServer.NewWithNoMessage())
} else {
c.Status(http.StatusInternalServerError)
_ = c.Error(utils.ErrInvalidRequest.New("the archive is not found"))
}
return
}
report.Meta = &Archive{
UID: meta.UID,
Kind: meta.Kind,
Namespace: meta.Namespace,
Name: meta.Name,
Action: meta.Action,
StartTime: meta.StartTime,
FinishTime: meta.FinishTime,
}

report.Events, err = s.event.ListByUID(context.TODO(), uid)
if err != nil {
c.Status(http.StatusInternalServerError)
_ = c.Error(utils.ErrInternalServer.NewWithNoMessage())
return
}

report.TotalTime = report.Meta.FinishTime.Sub(report.Meta.StartTime).String()

timeNow := time.Now()
timeAfter := timeNow
for _, et := range report.Events {
timeAfter = timeAfter.Add(et.FinishTime.Sub(*et.StartTime))
}
report.TotalFaultTime = timeAfter.Sub(timeNow).String()

c.JSON(http.StatusOK, report)
}