mirror of https://github.com/grafana/grafana.git
inital backend suport for quotas. issue #321
Conflicts: conf/defaults.ini main.go pkg/services/sqlstore/migrations/migrations.go
This commit is contained in:
parent
96af2debfc
commit
9023171940
|
|
@ -253,4 +253,9 @@ exchange = grafana_events
|
|||
enabled = false
|
||||
path = /var/lib/grafana/dashboards
|
||||
|
||||
|
||||
[quota]
|
||||
user = 10
|
||||
dashboard = 100
|
||||
data_source = 10
|
||||
endpoint = 10
|
||||
collector = 10
|
||||
|
|
|
|||
3
main.go
3
main.go
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/grafana/grafana/pkg/log"
|
||||
"github.com/grafana/grafana/pkg/login"
|
||||
"github.com/grafana/grafana/pkg/metrics"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/eventpublisher"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
|
|
@ -56,6 +57,8 @@ func main() {
|
|||
eventpublisher.Init()
|
||||
plugins.Init()
|
||||
|
||||
models.InitQuotaDefaults()
|
||||
|
||||
if err := notifications.Init(); err != nil {
|
||||
log.Fatal(3, "Notification service failed to initialize", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ func Register(r *macaron.Macaron) {
|
|||
r.Post("/users", bind(m.AddOrgUserCommand{}), wrap(AddOrgUser))
|
||||
r.Patch("/users/:userId", bind(m.UpdateOrgUserCommand{}), wrap(UpdateOrgUser))
|
||||
r.Delete("/users/:userId", wrap(RemoveOrgUser))
|
||||
r.Get("/quotas", wrap(GetOrgQuotas))
|
||||
r.Put("/quotas/:target", bind(m.UpdateQuotaCmd{}), wrap(UpdateOrgQuota))
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
// auth api keys
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func GetOrgQuotas(c *middleware.Context) Response {
|
||||
query := m.GetQuotasQuery{OrgId: c.ParamsInt64(":orgId")}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Failed to get org quotas", err)
|
||||
}
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
func UpdateOrgQuota(c *middleware.Context, cmd m.UpdateQuotaCmd) Response {
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
cmd.Target = m.QuotaTarget(c.Params(":target"))
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return ApiError(500, "Failed to update org quotas", err)
|
||||
}
|
||||
return ApiSuccess("Organization quota updated")
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"time"
|
||||
)
|
||||
|
||||
type QuotaTarget string
|
||||
|
||||
const (
|
||||
QUOTA_USER QuotaTarget = "user" //SQL table to query. ie. "select count(*) from user where org_id=?"
|
||||
QUOTA_DATASOURCE QuotaTarget = "data_source"
|
||||
QUOTA_DASHBOARD QuotaTarget = "dashboard"
|
||||
QUOTA_ENDPOINT QuotaTarget = "endpoint"
|
||||
QUOTA_COLLECTOR QuotaTarget = "collector"
|
||||
)
|
||||
|
||||
// defaults are set from settings package.
|
||||
var DefaultQuotas map[QuotaTarget]int64
|
||||
|
||||
func InitQuotaDefaults() {
|
||||
// set global defaults.
|
||||
DefaultQuotas = make(map[QuotaTarget]int64)
|
||||
quota := setting.Cfg.Section("quota")
|
||||
DefaultQuotas[QUOTA_USER] = quota.Key("user").MustInt64(10)
|
||||
DefaultQuotas[QUOTA_DATASOURCE] = quota.Key("data_source").MustInt64(10)
|
||||
DefaultQuotas[QUOTA_DASHBOARD] = quota.Key("dashboard").MustInt64(10)
|
||||
DefaultQuotas[QUOTA_ENDPOINT] = quota.Key("endpoint").MustInt64(10)
|
||||
DefaultQuotas[QUOTA_COLLECTOR] = quota.Key("collector").MustInt64(10)
|
||||
}
|
||||
|
||||
type Quota struct {
|
||||
Id int64
|
||||
OrgId int64
|
||||
Target QuotaTarget
|
||||
Limit int64
|
||||
Created time.Time
|
||||
Updated time.Time
|
||||
}
|
||||
|
||||
type QuotaDTO struct {
|
||||
OrgId int64 `json:"org_id"`
|
||||
Target QuotaTarget `json:"target"`
|
||||
Limit int64 `json:"limit"`
|
||||
Used int64 `json:"used"`
|
||||
}
|
||||
|
||||
type GetQuotaByTargetQuery struct {
|
||||
Target QuotaTarget
|
||||
OrgId int64
|
||||
Result *QuotaDTO
|
||||
}
|
||||
|
||||
type GetQuotasQuery struct {
|
||||
OrgId int64
|
||||
Result []*QuotaDTO
|
||||
}
|
||||
|
||||
type UpdateQuotaCmd struct {
|
||||
Target QuotaTarget `json:"target"`
|
||||
Limit int64 `json:"limit"`
|
||||
OrgId int64 `json:"-"`
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ func AddMigrations(mg *Migrator) {
|
|||
addDataSourceMigration(mg)
|
||||
addApiKeyMigrations(mg)
|
||||
addDashboardSnapshotMigrations(mg)
|
||||
addQuotaMigration(mg)
|
||||
}
|
||||
|
||||
func addMigrationLogMigrations(mg *Migrator) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
. "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
)
|
||||
|
||||
func addQuotaMigration(mg *Migrator) {
|
||||
|
||||
var quotaV1 = Table{
|
||||
Name: "quota",
|
||||
Columns: []*Column{
|
||||
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
||||
{Name: "org_id", Type: DB_BigInt, Nullable: false},
|
||||
{Name: "target", Type: DB_NVarchar, Length: 255, Nullable: false},
|
||||
{Name: "limit", Type: DB_BigInt, Nullable: false},
|
||||
{Name: "created", Type: DB_DateTime, Nullable: false},
|
||||
{Name: "updated", Type: DB_DateTime, Nullable: false},
|
||||
},
|
||||
Indices: []*Index{
|
||||
{Cols: []string{"org_id", "target"}, Type: UniqueIndex},
|
||||
},
|
||||
}
|
||||
mg.AddMigration("create quota table v1", NewAddTableMigration(quotaV1))
|
||||
|
||||
//------- indexes ------------------
|
||||
addTableIndicesMigrations(mg, "v1", quotaV1)
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package sqlstore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
bus.AddHandler("sql", GetQuotaByTarget)
|
||||
bus.AddHandler("sql", GetQuotas)
|
||||
bus.AddHandler("sql", UpdateQuota)
|
||||
}
|
||||
|
||||
type targetCount struct {
|
||||
Count int64
|
||||
}
|
||||
|
||||
func GetQuotaByTarget(query *m.GetQuotaByTargetQuery) error {
|
||||
quota := m.Quota{
|
||||
Target: query.Target,
|
||||
OrgId: query.OrgId,
|
||||
}
|
||||
has, err := x.Get(quota)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if has == false {
|
||||
quota.Limit = m.DefaultQuotas[query.Target]
|
||||
}
|
||||
|
||||
//get quota used.
|
||||
rawSql := fmt.Sprintf("SELECT COUNT(*) as count from %s where org_id=?", string(query.Target))
|
||||
resp := make([]*targetCount, 0)
|
||||
if err := x.Sql(rawSql, query.OrgId).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query.Result = &m.QuotaDTO{
|
||||
Target: query.Target,
|
||||
Limit: quota.Limit,
|
||||
OrgId: query.OrgId,
|
||||
Used: resp[0].Count,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetQuotas(query *m.GetQuotasQuery) error {
|
||||
quotas := make([]*m.Quota, 0)
|
||||
sess := x.Table("quota")
|
||||
if err := sess.Where("org_id=?", query.OrgId).Find("as); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
seenTargets := make(map[m.QuotaTarget]bool)
|
||||
for _, q := range quotas {
|
||||
seenTargets[q.Target] = true
|
||||
}
|
||||
|
||||
for t, v := range m.DefaultQuotas {
|
||||
if _, ok := seenTargets[t]; !ok {
|
||||
quotas = append(quotas, &m.Quota{
|
||||
OrgId: query.OrgId,
|
||||
Target: t,
|
||||
Limit: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
result := make([]*m.QuotaDTO, len(quotas))
|
||||
for i, q := range quotas {
|
||||
//get quota used.
|
||||
rawSql := fmt.Sprintf("SELECT COUNT(*) as count from %s where org_id=?", string(q.Target))
|
||||
resp := make([]*targetCount, 0)
|
||||
if err := x.Sql(rawSql, q.OrgId).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
result[i] = &m.QuotaDTO{
|
||||
Target: q.Target,
|
||||
Limit: q.Limit,
|
||||
OrgId: q.OrgId,
|
||||
Used: resp[0].Count,
|
||||
}
|
||||
}
|
||||
query.Result = result
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateQuota(cmd *m.UpdateQuotaCmd) error {
|
||||
return nil
|
||||
}
|
||||
Loading…
Reference in New Issue