mirror of
https://github.com/grafana/grafana.git
synced 2024-12-02 05:29:42 -06:00
163 lines
4.9 KiB
Go
163 lines
4.9 KiB
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
|
)
|
|
|
|
const (
|
|
dsAction = "datasources:query"
|
|
dsResource = "datasources"
|
|
PermissionsPerRole = 10
|
|
UsersPerTeam = 10
|
|
permissionsPerDs = 100
|
|
)
|
|
|
|
func BenchmarkDSPermissions10_10(b *testing.B) { benchmarkDSPermissions(b, 10, 10) }
|
|
|
|
func BenchmarkDSPermissions10_100(b *testing.B) { benchmarkDSPermissions(b, 10, 100) }
|
|
|
|
func BenchmarkDSPermissions10_1000(b *testing.B) { benchmarkDSPermissions(b, 10, 1000) }
|
|
|
|
func BenchmarkDSPermissions100_10(b *testing.B) { benchmarkDSPermissions(b, 100, 10) }
|
|
|
|
func BenchmarkDSPermissions100_100(b *testing.B) { benchmarkDSPermissions(b, 100, 100) }
|
|
|
|
func BenchmarkDSPermissions100_1000(b *testing.B) { benchmarkDSPermissions(b, 100, 1000) }
|
|
|
|
func BenchmarkDSPermissions1000_10(b *testing.B) { benchmarkDSPermissions(b, 1000, 10) }
|
|
|
|
func BenchmarkDSPermissions1000_100(b *testing.B) { benchmarkDSPermissions(b, 1000, 100) }
|
|
|
|
func BenchmarkDSPermissions1000_1000(b *testing.B) { benchmarkDSPermissions(b, 1000, 1000) }
|
|
|
|
func benchmarkDSPermissions(b *testing.B, dsNum, usersNum int) {
|
|
ac, dataSources := setupResourceBenchmark(b, dsNum, usersNum)
|
|
// We don't want to measure DB initialization
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
getDSPermissions(b, ac, dataSources)
|
|
}
|
|
}
|
|
|
|
func getDSPermissions(b *testing.B, store *AccessControlStore, dataSources []int64) {
|
|
dsId := dataSources[0]
|
|
|
|
permissions, err := store.GetResourcesPermissions(context.Background(), accesscontrol.GlobalOrgID, types.GetResourcesPermissionsQuery{
|
|
Actions: []string{dsAction},
|
|
Resource: dsResource,
|
|
ResourceIDs: []string{strconv.Itoa(int(dsId))},
|
|
})
|
|
require.NoError(b, err)
|
|
assert.GreaterOrEqual(b, len(permissions), 2)
|
|
}
|
|
|
|
func setupResourceBenchmark(b *testing.B, dsNum, usersNum int) (*AccessControlStore, []int64) {
|
|
ac, sql := setupTestEnv(b)
|
|
dataSources := GenerateDatasourcePermissions(b, sql, ac, dsNum, usersNum, permissionsPerDs)
|
|
return ac, dataSources
|
|
}
|
|
|
|
func GenerateDatasourcePermissions(b *testing.B, db *sqlstore.SQLStore, ac *AccessControlStore, dsNum, usersNum, permissionsPerDs int) []int64 {
|
|
dataSources := make([]int64, 0)
|
|
for i := 0; i < dsNum; i++ {
|
|
addDSCommand := &models.AddDataSourceCommand{
|
|
OrgId: 0,
|
|
Name: fmt.Sprintf("ds_%d", i),
|
|
Type: models.DS_GRAPHITE,
|
|
Access: models.DS_ACCESS_DIRECT,
|
|
Url: "http://test",
|
|
}
|
|
|
|
_ = db.AddDataSource(context.Background(), addDSCommand)
|
|
dataSources = append(dataSources, addDSCommand.Result.Id)
|
|
}
|
|
|
|
userIds, teamIds := generateTeamsAndUsers(b, db, usersNum)
|
|
|
|
for _, dsID := range dataSources {
|
|
// Add DS permissions for the users
|
|
maxPermissions := int(math.Min(float64(permissionsPerDs), float64(len(userIds))))
|
|
for i := 0; i < maxPermissions; i++ {
|
|
_, err := ac.SetUserResourcePermission(
|
|
context.Background(),
|
|
accesscontrol.GlobalOrgID,
|
|
accesscontrol.User{ID: userIds[i]},
|
|
types.SetResourcePermissionCommand{
|
|
Actions: []string{dsAction},
|
|
Resource: dsResource,
|
|
ResourceID: strconv.Itoa(int(dsID)),
|
|
},
|
|
nil,
|
|
)
|
|
require.NoError(b, err)
|
|
}
|
|
|
|
// Add DS permissions for the teams
|
|
maxPermissions = int(math.Min(float64(permissionsPerDs), float64(len(teamIds))))
|
|
for i := 0; i < maxPermissions; i++ {
|
|
_, err := ac.SetTeamResourcePermission(
|
|
context.Background(),
|
|
accesscontrol.GlobalOrgID,
|
|
teamIds[i],
|
|
types.SetResourcePermissionCommand{
|
|
Actions: []string{"datasources:query"},
|
|
Resource: "datasources",
|
|
ResourceID: strconv.Itoa(int(dsID)),
|
|
},
|
|
nil,
|
|
)
|
|
require.NoError(b, err)
|
|
}
|
|
}
|
|
|
|
return dataSources
|
|
}
|
|
|
|
func generateTeamsAndUsers(b *testing.B, db *sqlstore.SQLStore, users int) ([]int64, []int64) {
|
|
numberOfTeams := int(math.Ceil(float64(users) / UsersPerTeam))
|
|
globalUserId := 0
|
|
|
|
userIds := make([]int64, 0)
|
|
teamIds := make([]int64, 0)
|
|
for i := 0; i < numberOfTeams; i++ {
|
|
// Create team
|
|
teamName := fmt.Sprintf("%s%v", "team", i)
|
|
teamEmail := fmt.Sprintf("%s@example.org", teamName)
|
|
team, err := db.CreateTeam(teamName, teamEmail, 1)
|
|
require.NoError(b, err)
|
|
teamId := team.Id
|
|
teamIds = append(teamIds, teamId)
|
|
|
|
// Create team users
|
|
for u := 0; u < UsersPerTeam; u++ {
|
|
userName := fmt.Sprintf("%s%v", "user", globalUserId)
|
|
userEmail := fmt.Sprintf("%s@example.org", userName)
|
|
createUserCmd := models.CreateUserCommand{Email: userEmail, Name: userName, Login: userName, OrgId: 1}
|
|
|
|
user, err := db.CreateUser(context.Background(), createUserCmd)
|
|
require.NoError(b, err)
|
|
userId := user.Id
|
|
globalUserId++
|
|
userIds = append(userIds, userId)
|
|
|
|
err = db.AddTeamMember(userId, 1, teamId, false, 1)
|
|
require.NoError(b, err)
|
|
}
|
|
}
|
|
|
|
return userIds, teamIds
|
|
}
|