grafana/pkg/services/schemaloader/schemaloader.go
ying-jeanne 227c8403b5
Fix the disjuction of panels (#39412)
[As code] Correct trim apply defaults when import/export dashboards
2021-10-06 11:39:23 +02:00

145 lines
3.4 KiB
Go

package schemaloader
import (
"encoding/json"
"fmt"
"github.com/grafana/grafana"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/schema"
"github.com/grafana/grafana/pkg/schema/load"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/setting"
)
const ServiceName = "SchemaLoader"
var baseLoadPath load.BaseLoadPaths = load.BaseLoadPaths{
BaseCueFS: grafana.CoreSchema,
DistPluginCueFS: grafana.PluginSchema,
}
type RenderUser struct {
OrgID int64
UserID int64
OrgRole string
}
func ProvideService(cfg *setting.Cfg) (*SchemaLoaderService, error) {
dashFam, err := load.BaseDashboardFamily(baseLoadPath)
if err != nil {
return nil, fmt.Errorf("failed to load dashboard cue schema from path %q: %w", baseLoadPath, err)
}
s := &SchemaLoaderService{
Cfg: cfg,
DashFamily: dashFam,
log: log.New("schemaloader"),
}
return s, nil
}
type SchemaLoaderService struct {
log log.Logger
DashFamily schema.VersionedCueSchema
Cfg *setting.Cfg
}
func (rs *SchemaLoaderService) IsDisabled() bool {
if rs.Cfg == nil {
return true
}
return !rs.Cfg.IsTrimDefaultsEnabled()
}
func (rs *SchemaLoaderService) DashboardApplyDefaults(input *simplejson.Json) (*simplejson.Json, error) {
val, _ := input.Map()
val = removeNils(val)
data, _ := json.Marshal(val)
dsSchema := schema.Find(rs.DashFamily, schema.Latest())
result, err := schema.ApplyDefaults(schema.Resource{Value: data}, dsSchema.CUE())
if err != nil {
return input, err
}
output, err := simplejson.NewJson([]byte(result.Value.(string)))
if err != nil {
return input, err
}
return output, nil
}
func (rs *SchemaLoaderService) DashboardTrimDefaults(input simplejson.Json) (simplejson.Json, error) {
val, _ := input.Map()
val = removeNils(val)
data, _ := json.Marshal(val)
dsSchema, err := schema.SearchAndValidate(rs.DashFamily, string(data))
if err != nil {
return input, err
}
result, err := schema.TrimDefaults(schema.Resource{Value: data}, dsSchema.CUE())
if err != nil {
return input, err
}
output, err := simplejson.NewJson([]byte(result.Value.(string)))
if err != nil {
return input, err
}
return *output, nil
}
func removeNils(initialMap map[string]interface{}) map[string]interface{} {
withoutNils := map[string]interface{}{}
for key, value := range initialMap {
_, ok := value.(map[string]interface{})
if ok {
value = removeNils(value.(map[string]interface{}))
withoutNils[key] = value
continue
}
_, ok = value.([]interface{})
if ok {
value = removeNilArray(value.([]interface{}))
withoutNils[key] = value
continue
}
if value != nil {
if val, ok := value.(string); ok {
if val == "" {
continue
}
}
withoutNils[key] = value
}
}
return withoutNils
}
func removeNilArray(initialArray []interface{}) []interface{} {
withoutNils := []interface{}{}
for _, value := range initialArray {
_, ok := value.(map[string]interface{})
if ok {
value = removeNils(value.(map[string]interface{}))
withoutNils = append(withoutNils, value)
continue
}
_, ok = value.([]interface{})
if ok {
value = removeNilArray(value.([]interface{}))
withoutNils = append(withoutNils, value)
continue
}
if value != nil {
if val, ok := value.(string); ok {
if val == "" {
continue
}
}
withoutNils = append(withoutNils, value)
}
}
return withoutNils
}