Alerting: Export and provisioning rules into subfolders (#77450)
* Folders: Optionally include fullpath in service responses * Alerting: Export folder fullpath instead of title * Escape separator in folder title * Add support for provisiong alret rules into subfolders * Use FolderService for creating folders during provisioning * Export WithFullpath() folder service function --------- Co-authored-by: Tania B <yalyna.ts@gmail.com> Co-authored-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com>
This commit is contained in:
co-authored by
Tania B
Yuri Tseretyan
parent
e1aedb65b3
commit
17ca61d7f8
@@ -98,6 +98,8 @@ func (d *DashboardFolderStoreImpl) GetFolderByUID(ctx context.Context, orgID int
|
||||
return dashboards.FromDashboard(&dashboard), nil
|
||||
}
|
||||
|
||||
// GetFolders returns all folders for the given orgID and UIDs.
|
||||
// If no UIDs are provided then all folders for the org are returned.
|
||||
func (d *DashboardFolderStoreImpl) GetFolders(ctx context.Context, orgID int64, uids []string) (map[string]*folder.Folder, error) {
|
||||
m := make(map[string]*folder.Folder, len(uids))
|
||||
if len(uids) == 0 {
|
||||
|
||||
@@ -34,6 +34,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
const FULLPATH_SEPARATOR = "/"
|
||||
|
||||
type Service struct {
|
||||
store store
|
||||
db db.DB
|
||||
@@ -1109,6 +1111,36 @@ func (s *Service) buildSaveDashboardCommand(ctx context.Context, dto *dashboards
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// SplitFullpath splits a string into an array of strings using the FULLPATH_SEPARATOR as the delimiter.
|
||||
// It handles escape characters by appending the separator and the new string if the current string ends with an escape character.
|
||||
// The resulting array does not contain empty strings.
|
||||
func SplitFullpath(s string) []string {
|
||||
splitStrings := strings.Split(s, FULLPATH_SEPARATOR)
|
||||
|
||||
result := make([]string, 0)
|
||||
current := ""
|
||||
|
||||
for _, str := range splitStrings {
|
||||
if strings.HasSuffix(current, "\\") {
|
||||
// If the current string ends with an escape character, append the separator and the new string
|
||||
current = current[:len(current)-1] + FULLPATH_SEPARATOR + str
|
||||
} else {
|
||||
// If the current string does not end with an escape character, append the current string to the result and start a new current string
|
||||
if current != "" {
|
||||
result = append(result, current)
|
||||
}
|
||||
current = str
|
||||
}
|
||||
}
|
||||
|
||||
// Append the last string to the result
|
||||
if current != "" {
|
||||
result = append(result, current)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// getGuardianForSavePermissionCheck returns the guardian to be used for checking permission of dashboard
|
||||
// It replaces deleted Dashboard.GetDashboardIdForSavePermissionCheck()
|
||||
func getGuardianForSavePermissionCheck(ctx context.Context, d *dashboards.Dashboard, user identity.Requester) (guardian.DashboardGuardian, error) {
|
||||
|
||||
@@ -2216,3 +2216,54 @@ func createRule(t *testing.T, store *ngstore.DBstore, folderUID, title string) *
|
||||
|
||||
return &rule
|
||||
}
|
||||
|
||||
func TestSplitFullpath(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "empty string",
|
||||
input: "",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
name: "root folder",
|
||||
input: "/",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
name: "single folder",
|
||||
input: "folder",
|
||||
expected: []string{"folder"},
|
||||
},
|
||||
{
|
||||
name: "single folder with leading slash",
|
||||
input: "/folder",
|
||||
expected: []string{"folder"},
|
||||
},
|
||||
{
|
||||
name: "nested folder",
|
||||
input: "folder/subfolder/subsubfolder",
|
||||
expected: []string{"folder", "subfolder", "subsubfolder"},
|
||||
},
|
||||
{
|
||||
name: "escaped slashes",
|
||||
input: "folder\\/with\\/slashes",
|
||||
expected: []string{"folder/with/slashes"},
|
||||
},
|
||||
{
|
||||
name: "nested folder with escaped slashes",
|
||||
input: "folder\\/with\\/slashes/subfolder\\/with\\/slashes",
|
||||
expected: []string{"folder/with/slashes", "subfolder/with/slashes"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual := SplitFullpath(tt.input)
|
||||
assert.Equal(t, tt.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user