[Alerting]: Use title instead of slug for retrieving the namespace (#32957)

* [Alerting]: Use title instead of slug for retrieving the namespace

* Apply suggestions from code review

Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
Sofia Papagiannaki 2021-04-14 12:02:50 +03:00 committed by GitHub
parent b0470c84a5
commit 8848d825e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 14 deletions

View File

@ -6,6 +6,8 @@ import "github.com/grafana/grafana/pkg/models"
type Store interface {
// ValidateDashboardBeforeSave validates a dashboard before save.
ValidateDashboardBeforeSave(dashboard *models.Dashboard, overwrite bool) (bool, error)
// GetFolderByTitle retrieves a dashboard by its title and is used by unified alerting
GetFolderByTitle(orgID int64, title string) (*models.Dashboard, error)
GetProvisionedDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error)
GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error)
SaveProvisionedDashboard(cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error)

View File

@ -16,7 +16,7 @@ type FolderService interface {
GetFolders(limit int64) ([]*models.Folder, error)
GetFolderByID(id int64) (*models.Folder, error)
GetFolderByUID(uid string) (*models.Folder, error)
GetFolderBySlug(slug string) (*models.Folder, error)
GetFolderByTitle(title string) (*models.Folder, error)
CreateFolder(title, uid string) (*models.Folder, error)
UpdateFolder(uid string, cmd *models.UpdateFolderCommand) error
DeleteFolder(uid string) (*models.Folder, error)
@ -97,9 +97,8 @@ func (dr *dashboardServiceImpl) GetFolderByUID(uid string) (*models.Folder, erro
return dashToFolder(dashFolder), nil
}
func (dr *dashboardServiceImpl) GetFolderBySlug(slug string) (*models.Folder, error) {
query := models.GetDashboardQuery{OrgId: dr.orgId, Slug: slug}
dashFolder, err := getFolder(query)
func (dr *dashboardServiceImpl) GetFolderByTitle(title string) (*models.Folder, error) {
dashFolder, err := dr.dashboardStore.GetFolderByTitle(dr.orgId, title)
if err != nil {
return nil, toFolderError(err)
}

View File

@ -23,7 +23,7 @@ type RulerSrv struct {
func (srv RulerSrv) RouteDeleteNamespaceRulesConfig(c *models.ReqContext) response.Response {
namespace := c.Params(":Namespace")
namespaceUID, err := srv.store.GetNamespaceUIDBySlug(namespace, c.SignedInUser.OrgId, c.SignedInUser)
namespaceUID, err := srv.store.GetNamespaceUIDByTitle(namespace, c.SignedInUser.OrgId, c.SignedInUser)
if err != nil {
return response.Error(http.StatusInternalServerError, fmt.Sprintf("failed to get namespace: %s", namespace), err)
}
@ -35,7 +35,7 @@ func (srv RulerSrv) RouteDeleteNamespaceRulesConfig(c *models.ReqContext) respon
func (srv RulerSrv) RouteDeleteRuleGroupConfig(c *models.ReqContext) response.Response {
namespace := c.Params(":Namespace")
namespaceUID, err := srv.store.GetNamespaceUIDBySlug(namespace, c.SignedInUser.OrgId, c.SignedInUser)
namespaceUID, err := srv.store.GetNamespaceUIDByTitle(namespace, c.SignedInUser.OrgId, c.SignedInUser)
if err != nil {
return response.Error(http.StatusInternalServerError, fmt.Sprintf("failed to get namespace: %s", namespace), err)
}
@ -48,7 +48,7 @@ func (srv RulerSrv) RouteDeleteRuleGroupConfig(c *models.ReqContext) response.Re
func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext) response.Response {
namespace := c.Params(":Namespace")
namespaceUID, err := srv.store.GetNamespaceUIDBySlug(namespace, c.SignedInUser.OrgId, c.SignedInUser)
namespaceUID, err := srv.store.GetNamespaceUIDByTitle(namespace, c.SignedInUser.OrgId, c.SignedInUser)
if err != nil {
return response.Error(http.StatusInternalServerError, fmt.Sprintf("failed to get namespace: %s", namespace), err)
}
@ -89,7 +89,7 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext) response.
func (srv RulerSrv) RouteGetRulegGroupConfig(c *models.ReqContext) response.Response {
namespace := c.Params(":Namespace")
namespaceUID, err := srv.store.GetNamespaceUIDBySlug(namespace, c.SignedInUser.OrgId, c.SignedInUser)
namespaceUID, err := srv.store.GetNamespaceUIDByTitle(namespace, c.SignedInUser.OrgId, c.SignedInUser)
if err != nil {
return response.Error(http.StatusInternalServerError, fmt.Sprintf("failed to get namespace: %s", namespace), err)
}
@ -175,7 +175,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response
func (srv RulerSrv) RoutePostNameRulesConfig(c *models.ReqContext, ruleGroupConfig apimodels.PostableRuleGroupConfig) response.Response {
namespace := c.Params(":Namespace")
namespaceUID, err := srv.store.GetNamespaceUIDBySlug(namespace, c.SignedInUser.OrgId, c.SignedInUser)
namespaceUID, err := srv.store.GetNamespaceUIDByTitle(namespace, c.SignedInUser.OrgId, c.SignedInUser)
if err != nil {
return response.Error(http.StatusInternalServerError, fmt.Sprintf("failed to get namespace: %s", namespace), err)
}

View File

@ -1,7 +1,7 @@
@grafanaRecipient = grafana
// should point to an existing folder named alerting
@namespace1 = alerting
@namespace1 = foo%20bar
// create group42 under unknown namespace - it should fail
POST http://admin:admin@localhost:3000/api/ruler/{{grafanaRecipient}}/api/v1/rules/unknown

View File

@ -43,7 +43,7 @@ type RuleStore interface {
GetOrgAlertRules(query *ngmodels.ListAlertRulesQuery) error
GetNamespaceAlertRules(query *ngmodels.ListNamespaceAlertRulesQuery) error
GetRuleGroupAlertRules(query *ngmodels.ListRuleGroupAlertRulesQuery) error
GetNamespaceUIDBySlug(string, int64, *models.SignedInUser) (string, error)
GetNamespaceUIDByTitle(string, int64, *models.SignedInUser) (string, error)
GetNamespaceByUID(string, int64, *models.SignedInUser) (string, error)
GetOrgRuleGroups(query *ngmodels.ListOrgRuleGroupsQuery) error
UpsertAlertRules([]UpsertRule) error
@ -310,10 +310,10 @@ func (st DBstore) GetRuleGroupAlertRules(query *ngmodels.ListRuleGroupAlertRules
})
}
// GetNamespaceUIDBySlug is a handler for retrieving namespace UID by its name.
func (st DBstore) GetNamespaceUIDBySlug(namespace string, orgID int64, user *models.SignedInUser) (string, error) {
// GetNamespaceUIDByTitle is a handler for retrieving a namespace UID by its title.
func (st DBstore) GetNamespaceUIDByTitle(namespace string, orgID int64, user *models.SignedInUser) (string, error) {
s := dashboards.NewFolderService(orgID, user, st.SQLStore)
folder, err := s.GetFolderBySlug(namespace)
folder, err := s.GetFolderByTitle(namespace)
if err != nil {
return "", err
}

View File

@ -202,6 +202,32 @@ func (ss *SQLStore) GetDashboard(id, orgID int64, uid, slug string) (*models.Das
return &dashboard, nil
}
// GetDashboardByTitle gets a dashboard by its title.
func (ss *SQLStore) GetFolderByTitle(orgID int64, title string) (*models.Dashboard, error) {
if title == "" {
return nil, models.ErrDashboardIdentifierNotSet
}
// there is a unique constraint on org_id, folder_id, title
// there are no nested folders so the parent folder id is always 0
dashboard := models.Dashboard{OrgId: orgID, FolderId: 0, Title: title}
has, err := ss.engine.Get(&dashboard)
if err != nil {
return nil, err
} else if !has {
return nil, models.ErrDashboardNotFound
}
// if there is a dashboard instead of a folder with that title
if !dashboard.IsFolder {
return nil, models.ErrDashboardNotFound
}
dashboard.SetId(dashboard.Id)
dashboard.SetUid(dashboard.Uid)
return &dashboard, nil
}
// TODO: Remove me
func GetDashboard(query *models.GetDashboardQuery) error {
if query.Id == 0 && len(query.Slug) == 0 && len(query.Uid) == 0 {