mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Introduce coremodels framework (extracted from intent-api) (#47653)
* Copy over most of coremodel from intent-api branch * Fix import paths * Fix incorrect provider name * Add root compgen file, fixup componentroot.yaml * go mod tidy * Remove compgen for now * Add dashboard coremodel * Remove datasource coremodel, for now * Tweak comments on dashboard struct model * devenv: add dashboard testing directly * Fixup dashboard schema for openness, heatmap * Update Thema to tip * Fix wire/registry references * Fix hclog version
This commit is contained in:
1
pkg/framework/coremodel/helpers.go
Normal file
1
pkg/framework/coremodel/helpers.go
Normal file
@@ -0,0 +1 @@
|
||||
package coremodel
|
||||
25
pkg/framework/coremodel/interface.go
Normal file
25
pkg/framework/coremodel/interface.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package coremodel
|
||||
|
||||
import (
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
// Interface is the primary coremodel interface that must be implemented by all
|
||||
// Grafana coremodels. A coremodel is the foundational, canonical schema for
|
||||
// some known-at-compile-time Grafana object.
|
||||
//
|
||||
// Currently, all Coremodels are expressed as Thema lineages.
|
||||
type Interface interface {
|
||||
// Lineage should return the canonical Thema lineage for the coremodel.
|
||||
Lineage() thema.Lineage
|
||||
|
||||
// CurrentSchema should return the schema of the version that the Grafana backend
|
||||
// is currently written against. (While Grafana can accept data from all
|
||||
// older versions of the Thema schema, backend Go code is written against a
|
||||
// single version for simplicity)
|
||||
CurrentSchema() thema.Schema
|
||||
|
||||
// GoType should return a pointer to the Go struct type that corresponds to
|
||||
// the Current() schema.
|
||||
GoType() interface{}
|
||||
}
|
||||
78
pkg/framework/coremodel/registry.go
Normal file
78
pkg/framework/coremodel/registry.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package coremodel
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrModelAlreadyRegistered is returned when trying to register duplicate model to Registry.
|
||||
ErrModelAlreadyRegistered = errors.New("error registering duplicate model")
|
||||
)
|
||||
|
||||
// Registry is a registry of coremodel instances.
|
||||
type Registry struct {
|
||||
lock sync.RWMutex
|
||||
models []Interface
|
||||
modelIdx map[string]Interface
|
||||
}
|
||||
|
||||
// NewRegistry returns a new Registry with the provided coremodel instances.
|
||||
func NewRegistry(models ...Interface) (*Registry, error) {
|
||||
r := &Registry{
|
||||
models: make([]Interface, 0, len(models)),
|
||||
modelIdx: make(map[string]Interface, len(models)),
|
||||
}
|
||||
|
||||
if err := r.addModels(models); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Register adds coremodels to the Registry.
|
||||
func (r *Registry) Register(models ...Interface) error {
|
||||
return r.addModels(models)
|
||||
}
|
||||
|
||||
// List returns all coremodels registered in this Registry.
|
||||
func (r *Registry) List() []Interface {
|
||||
r.lock.RLock()
|
||||
defer r.lock.RUnlock()
|
||||
|
||||
return r.models
|
||||
}
|
||||
|
||||
func (r *Registry) addModels(models []Interface) error {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
// Update model index and return an error if trying to register a duplicate.
|
||||
for _, m := range models {
|
||||
k := m.Lineage().Name()
|
||||
|
||||
// Ensure assignability first. TODO will this blow up for dashboards?
|
||||
if err := thema.AssignableTo(m.CurrentSchema(), m.GoType()); err != nil {
|
||||
return fmt.Errorf("%s schema version %v not assignable to provided Go type: %w", k, m.CurrentSchema().Version(), err)
|
||||
}
|
||||
|
||||
if _, ok := r.modelIdx[k]; ok {
|
||||
return ErrModelAlreadyRegistered
|
||||
}
|
||||
|
||||
r.modelIdx[k] = m
|
||||
}
|
||||
|
||||
// Remake model list.
|
||||
// TODO: this can be more performant (proper resizing, maybe single loop with index building, etc.).
|
||||
r.models = r.models[:0]
|
||||
for _, m := range r.modelIdx {
|
||||
r.models = append(r.models, m)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
17
pkg/framework/coremodel/staticregistry/provide.go
Normal file
17
pkg/framework/coremodel/staticregistry/provide.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package staticregistry
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/coremodel/dashboard"
|
||||
"github.com/grafana/grafana/pkg/framework/coremodel"
|
||||
)
|
||||
|
||||
// ProvideRegistry provides a simple static Registry for coremodels.
|
||||
// Coremodels have to be manually added.
|
||||
// TODO dynamism
|
||||
func ProvideRegistry(
|
||||
dashboard *dashboard.Coremodel,
|
||||
) (*coremodel.Registry, error) {
|
||||
return coremodel.NewRegistry(
|
||||
dashboard,
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user