grafana/pkg/framework/coremodel/slot.go

104 lines
3.1 KiB
Go
Raw Normal View History

plugins: New static scanner and validator, with Thema slot support (#53754) * coremodels: Convert plugin-metadata schema to a coremodel * Newer cuetsy; try quoting field name * Add slot definitions * Start sketching out pfs package * Rerun codegen with fixes, new cuetsy * Catch up dashboard with new cuetsy * Update to go1.18 * Use new vmuxers in thema * Add slot system in Go * Draft finished implementation of pfs * Collapse slot pkg into coremodel dir; add PluginInfo * Add the mux type on top of kernel * Refactor plugin generator for extensibility * Change models.cue package, numerous debugs * Bring new output to parity with old * Remove old plugin generation logic * Misc tweaking * Reintroduce generation of shared schemas * Drop back to go1.17 * Add globbing to tsconfig exclude * Introduce pfs test on existing testdata * Make most existing testdata tests pass with pfs * coremodels: Convert plugin-metadata schema to a coremodel * Newer cuetsy; try quoting field name * Add APIType control concept, regen pluginmeta * Use proper numeric types for schema fields * Make pluginmeta schema follow Go type breakdown * More decomposition into distinct types * Add test case for no plugin.json file * Fix missing ref to #Dependencies * Remove generated TS for pluginmeta * Update dependencies, rearrange go.mod * Regenerate without Model prefix * Use updated thema loader; this is now runnable * Skip app plugin with weird include * Make plugin tree extractor reusable * Split out slot lineage load/validate logic * Add myriad tests for new plugin validation failures * Add test for zip fixtures * One last run of codegen * Proper delinting * Ensure validation order is deterministic * Let there actually be sorting * Undo reliance on builtIn field (#54009) * undo builtIn reliance * fix tests Co-authored-by: Will Browne <wbrowne@users.noreply.github.com>
2022-08-22 11:11:45 -05:00
package coremodel
import (
"cuelang.org/go/cue"
)
// Slot represents one of Grafana's named Thema composition slot definitions.
type Slot struct {
name string
raw cue.Value
plugins map[string]bool
}
// Name returns the name of the Slot. The name is also used as the path at which
// a Slot lineage is defined in a plugin models.cue file.
func (s Slot) Name() string {
return s.name
}
// MetaSchema returns the meta-schema that is the contract between coremodels
// that compose the Slot, and plugins that implement it.
func (s Slot) MetaSchema() cue.Value {
return s.raw
}
// ForPluginType indicates whether for this Slot, plugins of the given type may
// provide a slot implementation (first return value), and for those types that
// may, whether they must produce one (second return value).
//
// Expected values here are those in the set of
// ["github.com/grafana/grafana/pkg/coremodel/pluginmeta".Type], though passing
// a string not in that set will harmlessly return {false, false}. That type is
// not used here to avoid import cycles.
//
// Note that, at least for now, plugins are not required to provide any slot
// implementations, and do so by simply not containing a models.cue file.
// Consequently, the "must" return value here is best understood as, "IF a
// plugin provides a models.cue file, it MUST contain an implementation of this
// slot."
func (s Slot) ForPluginType(plugintype string) (may, must bool) {
must, may = s.plugins[plugintype]
return
}
// 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 Slot) IsGroup() bool {
// TODO rely on first-class Thema properties for this, one they exist - https://github.com/grafana/thema/issues/62
switch s.name {
case "Panel", "DSOptions":
return true
case "Query":
return false
default:
panic("unreachable - unknown slot name " + s.name)
}
}
plugins: New static scanner and validator, with Thema slot support (#53754) * coremodels: Convert plugin-metadata schema to a coremodel * Newer cuetsy; try quoting field name * Add slot definitions * Start sketching out pfs package * Rerun codegen with fixes, new cuetsy * Catch up dashboard with new cuetsy * Update to go1.18 * Use new vmuxers in thema * Add slot system in Go * Draft finished implementation of pfs * Collapse slot pkg into coremodel dir; add PluginInfo * Add the mux type on top of kernel * Refactor plugin generator for extensibility * Change models.cue package, numerous debugs * Bring new output to parity with old * Remove old plugin generation logic * Misc tweaking * Reintroduce generation of shared schemas * Drop back to go1.17 * Add globbing to tsconfig exclude * Introduce pfs test on existing testdata * Make most existing testdata tests pass with pfs * coremodels: Convert plugin-metadata schema to a coremodel * Newer cuetsy; try quoting field name * Add APIType control concept, regen pluginmeta * Use proper numeric types for schema fields * Make pluginmeta schema follow Go type breakdown * More decomposition into distinct types * Add test case for no plugin.json file * Fix missing ref to #Dependencies * Remove generated TS for pluginmeta * Update dependencies, rearrange go.mod * Regenerate without Model prefix * Use updated thema loader; this is now runnable * Skip app plugin with weird include * Make plugin tree extractor reusable * Split out slot lineage load/validate logic * Add myriad tests for new plugin validation failures * Add test for zip fixtures * One last run of codegen * Proper delinting * Ensure validation order is deterministic * Let there actually be sorting * Undo reliance on builtIn field (#54009) * undo builtIn reliance * fix tests Co-authored-by: Will Browne <wbrowne@users.noreply.github.com>
2022-08-22 11:11:45 -05:00
func AllSlots() map[string]*Slot {
fw := CUEFramework()
slots := make(map[string]*Slot)
// Ignore err, can only happen if we change structure of fw files, and all we'd
// do is panic and that's what the next line will do anyway. Same for similar ignored
// errors later in this func
iter, _ := fw.LookupPath(cue.ParsePath("pluginTypeMetaSchema")).Fields(cue.Optional(true))
type nameopt struct {
name string
req bool
}
plugslots := make(map[string][]nameopt)
for iter.Next() {
plugin := iter.Selector().String()
iiter, _ := iter.Value().Fields(cue.Optional(true))
for iiter.Next() {
slotname := iiter.Selector().String()
plugslots[slotname] = append(plugslots[slotname], nameopt{
name: plugin,
req: !iiter.IsOptional(),
})
}
}
iter, _ = fw.LookupPath(cue.ParsePath("slots")).Fields(cue.Optional(true))
for iter.Next() {
n := iter.Selector().String()
sl := Slot{
name: n,
raw: iter.Value(),
plugins: make(map[string]bool),
}
for _, no := range plugslots[n] {
sl.plugins[no.name] = no.req
}
slots[n] = &sl
}
return slots
}