...

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

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

     1  // Copyright 2020 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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package event
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"net/http"
    20  	"strconv"
    21  
    22  	"github.com/gin-gonic/gin"
    23  	"github.com/jinzhu/gorm"
    24  
    25  	"github.com/chaos-mesh/chaos-mesh/pkg/apiserver/utils"
    26  	"github.com/chaos-mesh/chaos-mesh/pkg/config"
    27  	"github.com/chaos-mesh/chaos-mesh/pkg/core"
    28  )
    29  
    30  // Service defines a handler service for events.
    31  type Service struct {
    32  	conf    *config.ChaosDashboardConfig
    33  	archive core.ExperimentStore
    34  	event   core.EventStore
    35  }
    36  
    37  // NewService return an event service instance.
    38  func NewService(
    39  	conf *config.ChaosDashboardConfig,
    40  	archive core.ExperimentStore,
    41  	event core.EventStore,
    42  ) *Service {
    43  	return &Service{
    44  		conf:    conf,
    45  		archive: archive,
    46  		event:   event,
    47  	}
    48  }
    49  
    50  // Register mounts our HTTP handler on the mux.
    51  func Register(r *gin.RouterGroup, s *Service) {
    52  	endpoint := r.Group("/events")
    53  	endpoint.Use(utils.AuthRequired)
    54  
    55  	// TODO: add more api handlers
    56  	endpoint.GET("", s.listEvents)
    57  	endpoint.GET("/dry", s.listDryEvents)
    58  	endpoint.GET("/get", s.getEvent)
    59  }
    60  
    61  // @Summary Get the list of events from db.
    62  // @Description Get the list of events from db.
    63  // @Tags events
    64  // @Produce json
    65  // @Param podName query string false "The pod's name"
    66  // @Param podNamespace query string false "The pod's namespace"
    67  // @Param startTime query string false "The start time of events"
    68  // @Param endTime query string false "The end time of events"
    69  // @Param experimentName query string false "The name of the experiment"
    70  // @Param experimentNamespace query string false "The namespace of the experiment"
    71  // @Param uid query string false "The UID of the experiment"
    72  // @Param kind query string false "kind" Enums(PodChaos, IoChaos, NetworkChaos, TimeChaos, KernelChaos, StressChaos)
    73  // @Param limit query string false "The max length of events list"
    74  // @Success 200 {array} core.Event
    75  // @Router /events [get]
    76  // @Failure 500 {object} utils.APIError
    77  func (s *Service) listEvents(c *gin.Context) {
    78  	filter := core.Filter{
    79  		PodName:             c.Query("podName"),
    80  		PodNamespace:        c.Query("podNamespace"),
    81  		StartTimeStr:        c.Query("startTime"),
    82  		FinishTimeStr:       c.Query("finishTime"),
    83  		ExperimentName:      c.Query("experimentName"),
    84  		ExperimentNamespace: c.Query("namespace"),
    85  		UID:                 c.Query("uid"),
    86  		Kind:                c.Query("kind"),
    87  		LimitStr:            c.Query("limit"),
    88  	}
    89  
    90  	if filter.PodName != "" && filter.PodNamespace == "" {
    91  		c.Status(http.StatusInternalServerError)
    92  		_ = c.Error(utils.ErrInternalServer.WrapWithNoMessage(fmt.Errorf("when podName is not empty, podNamespace cannot be empty")))
    93  		return
    94  	}
    95  
    96  	eventList, err := s.event.ListByFilter(context.Background(), filter)
    97  	if err != nil {
    98  		c.Status(http.StatusInternalServerError)
    99  		_ = c.Error(utils.ErrInternalServer.WrapWithNoMessage(err))
   100  		return
   101  	}
   102  
   103  	c.JSON(http.StatusOK, eventList)
   104  }
   105  
   106  // @Summary Get the list of events without pod records from db.
   107  // @Description Get the list of events without pod records from db.
   108  // @Tags events
   109  // @Produce json
   110  // @Param startTime query string false "The start time of events"
   111  // @Param endTime query string false "The end time of events"
   112  // @Param experimentName query string false "The name of the experiment"
   113  // @Param experimentNamespace query string false "The namespace of the experiment"
   114  // @Param kind query string false "kind" Enums(PodChaos, IoChaos, NetworkChaos, TimeChaos, KernelChaos, StressChaos)
   115  // @Param limit query string false "The max length of events list"
   116  // @Success 200 {array} core.Event
   117  // @Router /events/dry [get]
   118  // @Failure 500 {object} utils.APIError
   119  func (s *Service) listDryEvents(c *gin.Context) {
   120  	filter := core.Filter{
   121  		StartTimeStr:        c.Query("startTime"),
   122  		FinishTimeStr:       c.Query("finishTime"),
   123  		ExperimentName:      c.Query("experimentName"),
   124  		ExperimentNamespace: c.Query("namespace"),
   125  		Kind:                c.Query("kind"),
   126  		LimitStr:            c.Query("limit"),
   127  	}
   128  
   129  	eventList, err := s.event.DryListByFilter(context.Background(), filter)
   130  	if err != nil {
   131  		c.Status(http.StatusInternalServerError)
   132  		_ = c.Error(utils.ErrInternalServer.WrapWithNoMessage(err))
   133  		return
   134  	}
   135  
   136  	c.JSON(http.StatusOK, eventList)
   137  }
   138  
   139  // @Summary Get the event from db by ID.
   140  // @Description Get the event from db by ID.
   141  // @Tags events
   142  // @Produce json
   143  // @Param id query uint true "The id of the event"
   144  // @Success 200 {object} core.Event
   145  // @Router /events/get [get]
   146  // @Failure 500 {object} utils.APIError
   147  func (s *Service) getEvent(c *gin.Context) {
   148  	idStr := c.Query("id")
   149  	namespace := c.Query("namespace")
   150  
   151  	if idStr == "" {
   152  		c.Status(http.StatusBadRequest)
   153  		_ = c.Error(utils.ErrInvalidRequest.New("id cannot be empty"))
   154  		return
   155  	}
   156  
   157  	id, err := strconv.Atoi(idStr)
   158  	if err != nil {
   159  		c.Status(http.StatusBadRequest)
   160  		_ = c.Error(utils.ErrInvalidRequest.New("the format of id is wrong"))
   161  		return
   162  	}
   163  
   164  	event, err := s.event.Find(context.Background(), uint(id))
   165  	if err != nil {
   166  		if gorm.IsRecordNotFoundError(err) {
   167  			c.Status(http.StatusInternalServerError)
   168  			_ = c.Error(utils.ErrInvalidRequest.New("the event is not found"))
   169  		} else {
   170  			c.Status(http.StatusInternalServerError)
   171  			_ = c.Error(utils.ErrInternalServer.NewWithNoMessage())
   172  		}
   173  		return
   174  	}
   175  
   176  	if len(namespace) != 0 && event.Namespace != namespace {
   177  		c.Status(http.StatusBadRequest)
   178  		_ = c.Error(utils.ErrInvalidRequest.New("event %s belong to namespace %s but not namespace %s", idStr, event.Namespace, namespace))
   179  		return
   180  	}
   181  
   182  	c.JSON(http.StatusOK, event)
   183  }
   184