Correlations: Add GetCorrelation(s) HTTP APIs (#52517)

* Correlations: Get Single correlations

* Correlations: Get all correlations for given source ds

* Correlations: Get all correlations

* add tests

* add DB indices

* fix lint errors

* remove skip from tests

* use DatasourceService in test
This commit is contained in:
Giordano Ricci
2022-08-11 16:58:11 +01:00
committed by GitHub
parent 8813cbfb62
commit c1b30c56c9
10 changed files with 917 additions and 3 deletions

View File

@@ -18,10 +18,17 @@ func (s *CorrelationsService) registerAPIEndpoints() {
uidScope := datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":uid"))
authorize := ac.Middleware(s.AccessControl)
s.RouteRegister.Get("/api/datasources/correlations", middleware.ReqSignedIn, authorize(ac.ReqViewer, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(s.getCorrelationsHandler))
s.RouteRegister.Group("/api/datasources/uid/:uid/correlations", func(entities routing.RouteRegister) {
entities.Get("/", middleware.ReqSignedIn, authorize(ac.ReqViewer, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(s.getCorrelationsBySourceUIDHandler))
entities.Post("/", middleware.ReqSignedIn, authorize(ac.ReqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.createHandler))
entities.Delete("/:correlationUID", middleware.ReqSignedIn, authorize(ac.ReqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.deleteHandler))
entities.Patch("/:correlationUID", middleware.ReqSignedIn, authorize(ac.ReqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.updateHandler))
entities.Group("/:correlationUID", func(entities routing.RouteRegister) {
entities.Get("/", middleware.ReqSignedIn, authorize(ac.ReqViewer, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(s.getCorrelationHandler))
entities.Delete("/", middleware.ReqSignedIn, authorize(ac.ReqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.deleteHandler))
entities.Patch("/", middleware.ReqSignedIn, authorize(ac.ReqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(s.updateHandler))
})
})
}
@@ -191,3 +198,125 @@ type UpdateCorrelationResponse struct {
// in: body
Body UpdateCorrelationResponseBody `json:"body"`
}
// swagger:route GET /datasources/uid/{sourceUID}/correlations/{correlationUID} correlations getCorrelation
//
// Gets a correlation.
//
// Responses:
// 200: getCorrelationResponse
// 401: unauthorisedError
// 404: notFoundError
// 500: internalServerError
func (s *CorrelationsService) getCorrelationHandler(c *models.ReqContext) response.Response {
query := GetCorrelationQuery{
UID: web.Params(c.Req)[":correlationUID"],
SourceUID: web.Params(c.Req)[":uid"],
OrgId: c.OrgId,
}
correlation, err := s.getCorrelation(c.Req.Context(), query)
if err != nil {
if errors.Is(err, ErrCorrelationNotFound) {
return response.Error(http.StatusNotFound, "Correlation not found", err)
}
if errors.Is(err, ErrSourceDataSourceDoesNotExists) {
return response.Error(http.StatusNotFound, "Source data source not found", err)
}
return response.Error(http.StatusInternalServerError, "Failed to update correlation", err)
}
return response.JSON(http.StatusOK, correlation)
}
// swagger:parameters getCorrelation
type GetCorrelationParams struct {
// in:path
// required:true
DatasourceUID string `json:"sourceUID"`
// in:path
// required:true
CorrelationUID string `json:"correlationUID"`
}
//swagger:response getCorrelationResponse
type GetCorrelationResponse struct {
// in: body
Body Correlation `json:"body"`
}
// swagger:route GET /datasources/uid/{sourceUID}/correlations correlations getCorrelationsBySourceUID
//
// Gets all correlations originating from the given data source.
//
// Responses:
// 200: getCorrelationsBySourceUIDResponse
// 401: unauthorisedError
// 404: notFoundError
// 500: internalServerError
func (s *CorrelationsService) getCorrelationsBySourceUIDHandler(c *models.ReqContext) response.Response {
query := GetCorrelationsBySourceUIDQuery{
SourceUID: web.Params(c.Req)[":uid"],
OrgId: c.OrgId,
}
correlations, err := s.getCorrelationsBySourceUID(c.Req.Context(), query)
if err != nil {
if errors.Is(err, ErrCorrelationNotFound) {
return response.Error(http.StatusNotFound, "No correlation found", err)
}
if errors.Is(err, ErrSourceDataSourceDoesNotExists) {
return response.Error(http.StatusNotFound, "Source data source not found", err)
}
return response.Error(http.StatusInternalServerError, "Failed to update correlation", err)
}
return response.JSON(http.StatusOK, correlations)
}
// swagger:parameters getCorrelationsBySourceUID
type GetCorrelationsBySourceUIDParams struct {
// in:path
// required:true
DatasourceUID string `json:"sourceUID"`
}
//swagger:response getCorrelationsBySourceUIDResponse
type GetCorrelationsBySourceUIDResponse struct {
// in: body
Body []Correlation `json:"body"`
}
// swagger:route GET /datasources/correlations correlations getCorrelations
//
// Gets all correlations.
//
// Responses:
// 200: getCorrelationsResponse
// 401: unauthorisedError
// 404: notFoundError
// 500: internalServerError
func (s *CorrelationsService) getCorrelationsHandler(c *models.ReqContext) response.Response {
query := GetCorrelationsQuery{
OrgId: c.OrgId,
}
correlations, err := s.getCorrelations(c.Req.Context(), query)
if err != nil {
if errors.Is(err, ErrCorrelationNotFound) {
return response.Error(http.StatusNotFound, "No correlation found", err)
}
return response.Error(http.StatusInternalServerError, "Failed to update correlation", err)
}
return response.JSON(http.StatusOK, correlations)
}
//swagger:response getCorrelationsResponse
type GetCorrelationsResponse struct {
// in: body
Body []Correlation `json:"body"`
}

View File

@@ -56,6 +56,18 @@ func (s CorrelationsService) UpdateCorrelation(ctx context.Context, cmd UpdateCo
return s.updateCorrelation(ctx, cmd)
}
func (s CorrelationsService) GetCorrelation(ctx context.Context, cmd GetCorrelationQuery) (Correlation, error) {
return s.getCorrelation(ctx, cmd)
}
func (s CorrelationsService) GetCorrelationsBySourceUID(ctx context.Context, cmd GetCorrelationsBySourceUIDQuery) ([]Correlation, error) {
return s.getCorrelationsBySourceUID(ctx, cmd)
}
func (s CorrelationsService) GetCorrelations(ctx context.Context, cmd GetCorrelationsQuery) ([]Correlation, error) {
return s.getCorrelations(ctx, cmd)
}
func (s CorrelationsService) DeleteCorrelationsBySourceUID(ctx context.Context, cmd DeleteCorrelationsBySourceUIDCommand) error {
return s.deleteCorrelationsBySourceUID(ctx, cmd)
}

View File

@@ -132,6 +132,90 @@ func (s CorrelationsService) updateCorrelation(ctx context.Context, cmd UpdateCo
return correlation, nil
}
func (s CorrelationsService) getCorrelation(ctx context.Context, cmd GetCorrelationQuery) (Correlation, error) {
correlation := Correlation{
UID: cmd.UID,
SourceUID: cmd.SourceUID,
}
err := s.SQLStore.WithTransactionalDbSession(ctx, func(session *sqlstore.DBSession) error {
query := &datasources.GetDataSourceQuery{
OrgId: cmd.OrgId,
Uid: cmd.SourceUID,
}
if err := s.DataSourceService.GetDataSource(ctx, query); err != nil {
return ErrSourceDataSourceDoesNotExists
}
found, err := session.Where("uid = ? AND source_uid = ?", correlation.UID, correlation.SourceUID).Get(&correlation)
if !found {
return ErrCorrelationNotFound
}
if err != nil {
return err
}
return err
})
if err != nil {
return Correlation{}, err
}
return correlation, nil
}
func (s CorrelationsService) getCorrelationsBySourceUID(ctx context.Context, cmd GetCorrelationsBySourceUIDQuery) ([]Correlation, error) {
correlationsCondiBean := Correlation{
SourceUID: cmd.SourceUID,
}
correlations := make([]Correlation, 0)
err := s.SQLStore.WithTransactionalDbSession(ctx, func(session *sqlstore.DBSession) error {
query := &datasources.GetDataSourceQuery{
OrgId: cmd.OrgId,
Uid: cmd.SourceUID,
}
if err := s.DataSourceService.GetDataSource(ctx, query); err != nil {
return ErrSourceDataSourceDoesNotExists
}
err := session.Find(&correlations, correlationsCondiBean)
if err != nil {
return err
}
return err
})
if err != nil {
return []Correlation{}, err
}
if len(correlations) == 0 {
return []Correlation{}, ErrCorrelationNotFound
}
return correlations, nil
}
func (s CorrelationsService) getCorrelations(ctx context.Context, cmd GetCorrelationsQuery) ([]Correlation, error) {
correlations := make([]Correlation, 0)
err := s.SQLStore.WithDbSession(ctx, func(session *sqlstore.DBSession) error {
return session.Select("correlation.*").Join("", "data_source", "correlation.source_uid = data_source.uid").Where("data_source.org_id = ?", cmd.OrgId).Find(&correlations)
})
if err != nil {
return []Correlation{}, err
}
if len(correlations) == 0 {
return []Correlation{}, ErrCorrelationNotFound
}
return correlations, nil
}
func (s CorrelationsService) deleteCorrelationsBySourceUID(ctx context.Context, cmd DeleteCorrelationsBySourceUIDCommand) error {
return s.SQLStore.WithDbSession(ctx, func(session *sqlstore.DBSession) error {
_, err := session.Delete(&Correlation{SourceUID: cmd.SourceUID})

View File

@@ -94,6 +94,26 @@ type UpdateCorrelationCommand struct {
Description *string `json:"description"`
}
// GetCorrelationQuery is the query to retrieve a single correlation
type GetCorrelationQuery struct {
// UID of the correlation
UID string `json:"-"`
// UID of the source data source
SourceUID string `json:"-"`
OrgId int64 `json:"-"`
}
// GetCorrelationsBySourceUIDQuery is the query to retrieve all correlations originating by the given Data Source
type GetCorrelationsBySourceUIDQuery struct {
SourceUID string `json:"-"`
OrgId int64 `json:"-"`
}
// GetCorrelationsQuery is the query to retrieve all correlations
type GetCorrelationsQuery struct {
OrgId int64 `json:"-"`
}
type DeleteCorrelationsBySourceUIDCommand struct {
SourceUID string
}