grafana/pkg/kindsys/schema_interface.go
sam boyer 4db3b2fd5c
Kindsys: Remove defs, Slot->SchemaInterface (#61069)
* kindsys: Remove defs, Slot->SchemaInterface

* Remove excess file

* Fix up tests

* Regenerate kinds report

* Final bits of cleanup

* Stop complaining, linter

* Update pkg/kindsys/kindcat_composable.cue

Co-authored-by: Tania <yalyna.ts@gmail.com>

Co-authored-by: Tania <yalyna.ts@gmail.com>
2023-01-06 12:37:32 -05:00

122 lines
3.3 KiB
Go

package kindsys
import (
"fmt"
"sync"
"cuelang.org/go/cue"
"github.com/grafana/grafana/pkg/cuectx"
)
// SchemaInterface represents one of Grafana's named schema interfaces.
//
// Canonical definition of schema interfaces is done in CUE. Instances of
// this type simply represent that information in Go.
// TODO link to framework docs
type SchemaInterface struct {
name string
group bool
raw cue.Value
plugins []string
}
// Name returns the name of the SchemaInterface.
//
// The name is also used as the path at which a SchemaInterface lineage is defined in a
// plugin models.cue file.
func (s SchemaInterface) Name() string {
return s.name
}
// Interface returns the cue.Value representing the meta-schema that is the
// contract between core or custom kinds that compose the meta-schema, and the
// plugin-declared composable kinds that implement the meta-schema.
func (s SchemaInterface) Interface() cue.Value {
return s.raw.LookupPath(ip)
}
var ip = cue.ParsePath("interface")
// Should indicates whether the given plugin type is expected (but not required)
// to produce a composable kind that implements this SchemaInterface.
func (s SchemaInterface) Should(plugintype string) bool {
pt := plugintype
for _, t := range s.plugins {
if pt == t {
return true
}
}
return false
}
// IsGroup indicates whether the slot specifies a group lineage - one in which
// each top-level key represents a distinct schema for objects that are expected
// to exist in the wild, but objects corresponding to the root of the schema are not
// expected to exist.
func (s SchemaInterface) IsGroup() bool {
return s.group
}
func FindSchemaInterface(name string) (SchemaInterface, error) {
sl, has := SchemaInterfaces(nil)[name]
if !has {
return SchemaInterface{}, fmt.Errorf("unsupported slot: %s", name)
}
return sl, nil
}
var defaultIfaces map[string]SchemaInterface
var onceIfaces sync.Once
// SchemaInterfaces returns a map of all [SchemaInterface]s defined by
// Grafana's kindsys framework.
//
// All calling code within grafana/grafana is expected to use Grafana's
// singleton [cue.Context], returned from [cuectx.GrafanaCUEContext]. If nil is
// passed, the singleton will be used. This is a reasonable default for external
// code, as well.
//
// TODO link to framework docs
func SchemaInterfaces(ctx *cue.Context) map[string]SchemaInterface {
if ctx == nil || ctx == cuectx.GrafanaCUEContext() {
// Ensure framework is loaded, even if this func is called
// from an init() somewhere.
onceIfaces.Do(func() {
defaultIfaces = doSchemaInterfaces(nil)
})
return defaultIfaces
}
return doSchemaInterfaces(ctx)
}
func doSchemaInterfaces(ctx *cue.Context) map[string]SchemaInterface {
fw := CUEFramework(ctx)
defs := fw.LookupPath(cue.ParsePath("schemaInterfaces"))
if !defs.Exists() {
panic("schemaInterfaces key does not exist in kindsys framework")
}
type typ struct {
Name string `json:"name"`
PluginTypes []string `json:"pluginTypes"`
Group bool `json:"group"`
}
ifaces := make(map[string]SchemaInterface)
iter, _ := defs.Fields() //nolint:errcheck
for iter.Next() {
k := iter.Selector().String()
v := &typ{}
_ = iter.Value().Decode(&v) //nolint:errcheck,gosec
ifaces[k] = SchemaInterface{
name: v.Name,
plugins: v.PluginTypes,
group: v.Group,
raw: iter.Value(),
}
}
return ifaces
}