mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
coremodels: Update to latest Thema with generics (#56602)
* Update thema to latest * Deal with s/Library/*Runtime/ * Commit new, working results of codegen
This commit is contained in:
parent
668cb25b82
commit
e5a6547a94
2
go.mod
2
go.mod
@ -58,7 +58,7 @@ require (
|
||||
github.com/grafana/grafana-aws-sdk v0.11.0
|
||||
github.com/grafana/grafana-azure-sdk-go v1.3.1
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.139.0
|
||||
github.com/grafana/thema v0.0.0-20220817114012-ebeee841c104
|
||||
github.com/grafana/thema v0.0.0-20220929145912-2c7c4a7bb20b
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
github.com/hashicorp/go-hclog v1.0.0
|
||||
github.com/hashicorp/go-plugin v1.4.3
|
||||
|
2
go.sum
2
go.sum
@ -1380,6 +1380,8 @@ github.com/grafana/saml v0.4.9-0.20220727151557-61cd9c9353fc h1:1PY8n+rXuBNr3r1J
|
||||
github.com/grafana/saml v0.4.9-0.20220727151557-61cd9c9353fc/go.mod h1:9Zh6dWPtB3MSzTRt8fIFH60Z351QQ+s7hCU3J/tTlA4=
|
||||
github.com/grafana/thema v0.0.0-20220817114012-ebeee841c104 h1:dYpwFYIChrMfpq3wDa/ZBxAbUGSW5NYmYBeSezhaoao=
|
||||
github.com/grafana/thema v0.0.0-20220817114012-ebeee841c104/go.mod h1:fCV1rqv6XRQg2GfIQ7pU9zdxd5fLRcEBCnrDVwlK+ZY=
|
||||
github.com/grafana/thema v0.0.0-20220929145912-2c7c4a7bb20b h1:OEGzlaj04LE6Eq7aGMOh0bCplGW5rXNeSSSwgamPBEY=
|
||||
github.com/grafana/thema v0.0.0-20220929145912-2c7c4a7bb20b/go.mod h1:i3/NX50sNrwsPSAQAj56ckjQTb4biaYG/6y+zyKgpb0=
|
||||
github.com/grafana/xorm v0.8.3-0.20220614223926-2fcda7565af6 h1:I9dh1MXGX0wGyxdV/Sl7+ugnki4Dfsy8lv2s5Yf887o=
|
||||
github.com/grafana/xorm v0.8.3-0.20220614223926-2fcda7565af6/go.mod h1:ZkJLEYLoVyg7amJK/5r779bHyzs2AU8f8VMiP6BM7uY=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
|
@ -301,8 +301,8 @@ var wireSet = wire.NewSet(
|
||||
authproxy.ProvideAuthProxy,
|
||||
statscollector.ProvideService,
|
||||
cmreg.CoremodelSet,
|
||||
cuectx.ProvideCUEContext,
|
||||
cuectx.ProvideThemaLibrary,
|
||||
cuectx.GrafanaCUEContext,
|
||||
cuectx.GrafanaThemaRuntime,
|
||||
csrf.ProvideCSRFFilter,
|
||||
ossaccesscontrol.ProvideTeamPermissions,
|
||||
wire.Bind(new(accesscontrol.TeamPermissionsService), new(*ossaccesscontrol.TeamPermissionsService)),
|
||||
|
@ -50,7 +50,7 @@ type CoremodelDeclaration struct {
|
||||
// This loading approach is intended primarily for use with code generators, or
|
||||
// other use cases external to grafana-server backend. For code within
|
||||
// grafana-server, prefer lineage loaders provided in e.g. pkg/coremodel/*.
|
||||
func ExtractLineage(path string, lib thema.Library) (*CoremodelDeclaration, error) {
|
||||
func ExtractLineage(path string, rt *thema.Runtime) (*CoremodelDeclaration, error) {
|
||||
if !filepath.IsAbs(path) {
|
||||
return nil, fmt.Errorf("must provide an absolute path, got %q", path)
|
||||
}
|
||||
@ -99,7 +99,7 @@ func ExtractLineage(path string, lib thema.Library) (*CoremodelDeclaration, erro
|
||||
panic(err)
|
||||
}
|
||||
ec.RelativePath = filepath.ToSlash(ec.RelativePath)
|
||||
ec.Lineage, err = cuectx.LoadGrafanaInstancesWithThema(filepath.Dir(ec.RelativePath), fs, lib)
|
||||
ec.Lineage, err = cuectx.LoadGrafanaInstancesWithThema(filepath.Dir(ec.RelativePath), fs, rt)
|
||||
if err != nil {
|
||||
return ec, err
|
||||
}
|
||||
@ -156,7 +156,7 @@ func (cd *CoremodelDeclaration) PathVersion() string {
|
||||
// The provided path must be a directory. Generated code files will be written
|
||||
// to that path. The final element of the path must match the Lineage.Name().
|
||||
func (cd *CoremodelDeclaration) GenerateGoCoremodel(path string) (WriteDiffer, error) {
|
||||
lin, lib := cd.Lineage, cd.Lineage.Library()
|
||||
lin, rt := cd.Lineage, cd.Lineage.Runtime()
|
||||
_, name := filepath.Split(path)
|
||||
if name != lin.Name() {
|
||||
return nil, fmt.Errorf("lineage name %q must match final element of path, got %q", lin.Name(), path)
|
||||
@ -168,7 +168,7 @@ func (cd *CoremodelDeclaration) GenerateGoCoremodel(path string) (WriteDiffer, e
|
||||
return nil, fmt.Errorf("thema openapi generation failed: %w", err)
|
||||
}
|
||||
|
||||
str, err := yaml.Marshal(lib.Context().BuildFile(f))
|
||||
str, err := yaml.Marshal(rt.Context().BuildFile(f))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cue-yaml marshaling failed: %w", err)
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func MapCUEImportToTS(path string) (string, error) {
|
||||
// Errors returned from [pfs.ParsePluginFS] are placed in the option map. Only
|
||||
// filesystem traversal and read errors will result in a non-nil second return
|
||||
// value.
|
||||
func ExtractPluginTrees(parent fs.FS, lib thema.Library) (map[string]PluginTreeOrErr, error) {
|
||||
func ExtractPluginTrees(parent fs.FS, rt *thema.Runtime) (map[string]PluginTreeOrErr, error) {
|
||||
ents, err := fs.ReadDir(parent, ".")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading fs root directory: %w", err)
|
||||
@ -78,7 +78,7 @@ func ExtractPluginTrees(parent fs.FS, lib thema.Library) (map[string]PluginTreeO
|
||||
}
|
||||
|
||||
var either PluginTreeOrErr
|
||||
if ptree, err := pfs.ParsePluginFS(sub, lib); err == nil {
|
||||
if ptree, err := pfs.ParsePluginFS(sub, rt); err == nil {
|
||||
either.Tree = (*PluginTree)(ptree)
|
||||
} else {
|
||||
either.Err = err
|
||||
@ -235,7 +235,7 @@ func genGoTypes(plug pfs.PluginInfo, path, subpath, prefix string) (WriteDiffer,
|
||||
wd := NewWriteDiffer()
|
||||
for slotname, lin := range plug.SlotImplementations() {
|
||||
lowslot := strings.ToLower(slotname)
|
||||
lib := lin.Library()
|
||||
rt := lin.Runtime()
|
||||
sch := thema.SchemaP(lin, thema.LatestVersion(lin))
|
||||
|
||||
// FIXME gotta hack this out of thema in order to deal with our custom imports :scream:
|
||||
@ -244,7 +244,7 @@ func genGoTypes(plug pfs.PluginInfo, path, subpath, prefix string) (WriteDiffer,
|
||||
return nil, fmt.Errorf("thema openapi generation failed: %w", err)
|
||||
}
|
||||
|
||||
str, err := yaml.Marshal(lib.Context().BuildFile(f))
|
||||
str, err := yaml.Marshal(rt.Context().BuildFile(f))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cue-yaml marshaling failed: %w", err)
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ var currentVersion = thema.SV({{ .LatestSeqv }}, {{ .LatestSchv }})
|
||||
{{- if .IsComposed }}//
|
||||
// This is the base variant of the schema. It does not include any composed
|
||||
// plugin schemas.{{ end }}
|
||||
func Lineage(lib thema.Library, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("pkg", "coremodel", "{{ .Name }}"), cueFS, lib, opts...)
|
||||
func Lineage(rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("pkg", "coremodel", "{{ .Name }}"), cueFS, rt, opts...)
|
||||
}
|
||||
|
||||
var _ thema.LineageFactory = Lineage
|
||||
@ -52,8 +52,8 @@ func (c *Coremodel) GoType() interface{} {
|
||||
// Note that this function does not cache, and initially loading a Thema lineage
|
||||
// can be expensive. As such, the Grafana backend should prefer to access this
|
||||
// coremodel through a registry (pkg/framework/coremodel/registry), which does cache.
|
||||
func New(lib thema.Library) (*Coremodel, error) {
|
||||
lin, err := Lineage(lib)
|
||||
func New(rt *thema.Runtime) (*Coremodel, error) {
|
||||
lin, err := Lineage(rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -42,12 +42,12 @@ func (b *Base) {{ .TitleName }}() *{{ .Name }}.Coremodel {
|
||||
}
|
||||
{{end}}
|
||||
|
||||
func doProvideBase(lib thema.Library) *Base {
|
||||
func doProvideBase(rt *thema.Runtime) *Base {
|
||||
var err error
|
||||
reg := &Base{}
|
||||
|
||||
{{range .Coremodels }}
|
||||
reg.{{ .Name }}, err = {{ .Name }}.New(lib)
|
||||
reg.{{ .Name }}, err = {{ .Name }}.New(rt)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error while initializing {{ .Name }} coremodel: %s", err))
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ var currentVersion{{ .SlotName }} = thema.SV({{ .LatestSeqv }}, {{ .LatestSchv }
|
||||
|
||||
// {{ .SlotName }}Lineage returns the Thema lineage for the {{ .PluginID }} {{ .PluginType }} plugin's
|
||||
// {{ .SlotName }} ["github.com/grafana/grafana/pkg/framework/coremodel".Slot] implementation.
|
||||
func {{ .SlotName }}Lineage(lib thema.Library, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("public", "app", "{{ .Name }}"), cueFS, lib, opts...)
|
||||
func {{ .SlotName }}Lineage(rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("public", "app", "{{ .Name }}"), cueFS, rt, opts...)
|
||||
}
|
||||
|
@ -19,14 +19,14 @@ var ptree *pfs.Tree
|
||||
var plugFS embed.FS
|
||||
|
||||
// PluginTree returns the plugin tree representing the statically analyzable contents of the {{ .PluginID }} plugin.
|
||||
func PluginTree(lib *thema.Library) *pfs.Tree {
|
||||
func PluginTree(rt *thema.Runtime) *pfs.Tree {
|
||||
var err error
|
||||
if lib == nil {
|
||||
if rt == nil || rt == cuectx.GrafanaThemaRuntime() {
|
||||
parseOnce.Do(func() {
|
||||
ptree, err = pfs.ParsePluginFS(plugFS, cuectx.ProvideThemaLibrary())
|
||||
ptree, err = pfs.ParsePluginFS(plugFS, cuectx.GrafanaThemaRuntime())
|
||||
})
|
||||
} else {
|
||||
ptree, err = pfs.ParsePluginFS(plugFS, cuectx.ProvideThemaLibrary())
|
||||
ptree, err = pfs.ParsePluginFS(plugFS, rt)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -40,8 +40,8 @@ func PluginTree(lib *thema.Library) *pfs.Tree {
|
||||
{{ $pluginfo := . }}{{ range $slot := .SlotImpls }}
|
||||
// {{ .SlotName }}Lineage returns the Thema lineage for the {{ $pluginfo.PluginID }} {{ $pluginfo.PluginType }} plugin's
|
||||
// {{ .SlotName }} ["github.com/grafana/grafana/pkg/framework/coremodel".Slot] implementation.
|
||||
func {{ .SlotName }}Lineage(lib *thema.Library, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
t := PluginTree(lib)
|
||||
func {{ .SlotName }}Lineage(rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
t := PluginTree(rt)
|
||||
lin, has := t.RootPlugin().SlotImplementations()["{{ .SlotName }}"]
|
||||
if !has {
|
||||
panic("unreachable: lineage for {{ .SlotName }} does not exist, but code is only generated for existing lineages")
|
||||
|
@ -10,22 +10,22 @@ import (
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
func makeTreeOrPanic(path string, pkgname string, lib thema.Library) *pfs.Tree {
|
||||
func makeTreeOrPanic(path string, pkgname string, rt *thema.Runtime) *pfs.Tree {
|
||||
sub, err := fs.Sub(grafana.CueSchemaFS, path)
|
||||
if err != nil {
|
||||
panic("could not create fs sub to " + path)
|
||||
}
|
||||
tree, err := pfs.ParsePluginFS(sub, lib)
|
||||
tree, err := pfs.ParsePluginFS(sub, rt)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error parsing plugin metadata for %s: %s", pkgname, err))
|
||||
}
|
||||
return tree
|
||||
}
|
||||
|
||||
func coreTreeList(lib thema.Library) pfs.TreeList{
|
||||
func coreTreeList(rt *thema.Runtime) pfs.TreeList{
|
||||
return pfs.TreeList{
|
||||
{{- range .Plugins }}
|
||||
makeTreeOrPanic("{{ .Path }}", "{{ .PkgName }}", lib),
|
||||
makeTreeOrPanic("{{ .Path }}", "{{ .PkgName }}", rt),
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
{{ if .NoAlias }}{{ .PkgName }} {{end}}"{{ .Path }}"{{ end }}
|
||||
)
|
||||
|
||||
func coreTreeLoaders() []func(*thema.Library) *pfs.Tree{
|
||||
return []func(*thema.Library) *pfs.Tree{
|
||||
func coreTreeLoaders() []func(*thema.Runtime) *pfs.Tree{
|
||||
return []func(*thema.Runtime) *pfs.Tree{
|
||||
{{- range .Plugins }}
|
||||
{{ .PkgName }}.PluginTree,{{ end }}
|
||||
}
|
||||
|
@ -1018,8 +1018,8 @@ var currentVersion = thema.SV(0, 0)
|
||||
// The lineage is the canonical specification of the current dashboard schema,
|
||||
// all prior schema versions, and the mappings that allow migration between
|
||||
// schema versions.
|
||||
func Lineage(lib thema.Library, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("pkg", "coremodel", "dashboard"), cueFS, lib, opts...)
|
||||
func Lineage(rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("pkg", "coremodel", "dashboard"), cueFS, rt, opts...)
|
||||
}
|
||||
|
||||
var _ thema.LineageFactory = Lineage
|
||||
@ -1052,8 +1052,8 @@ func (c *Coremodel) GoType() interface{} {
|
||||
// Note that this function does not cache, and initially loading a Thema lineage
|
||||
// can be expensive. As such, the Grafana backend should prefer to access this
|
||||
// coremodel through a registry (pkg/framework/coremodel/registry), which does cache.
|
||||
func New(lib thema.Library) (*Coremodel, error) {
|
||||
lin, err := Lineage(lib)
|
||||
func New(rt *thema.Runtime) (*Coremodel, error) {
|
||||
lin, err := Lineage(rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ func TestDevenvDashboardValidity(t *testing.T) {
|
||||
|
||||
m, err := themaTestableDashboards(os.DirFS(path))
|
||||
require.NoError(t, err)
|
||||
cm, err := dashboard.New(cuectx.ProvideThemaLibrary())
|
||||
cm, err := dashboard.New(cuectx.GrafanaThemaRuntime())
|
||||
require.NoError(t, err)
|
||||
|
||||
for path, b := range m {
|
||||
|
@ -90,8 +90,8 @@ var currentVersion = thema.SV(0, 0)
|
||||
// The lineage is the canonical specification of the current playlist schema,
|
||||
// all prior schema versions, and the mappings that allow migration between
|
||||
// schema versions.
|
||||
func Lineage(lib thema.Library, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("pkg", "coremodel", "playlist"), cueFS, lib, opts...)
|
||||
func Lineage(rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("pkg", "coremodel", "playlist"), cueFS, rt, opts...)
|
||||
}
|
||||
|
||||
var _ thema.LineageFactory = Lineage
|
||||
@ -124,8 +124,8 @@ func (c *Coremodel) GoType() interface{} {
|
||||
// Note that this function does not cache, and initially loading a Thema lineage
|
||||
// can be expensive. As such, the Grafana backend should prefer to access this
|
||||
// coremodel through a registry (pkg/framework/coremodel/registry), which does cache.
|
||||
func New(lib thema.Library) (*Coremodel, error) {
|
||||
lin, err := Lineage(lib)
|
||||
func New(rt *thema.Runtime) (*Coremodel, error) {
|
||||
lin, err := Lineage(rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -560,8 +560,8 @@ var currentVersion = thema.SV(0, 0)
|
||||
// The lineage is the canonical specification of the current pluginmeta schema,
|
||||
// all prior schema versions, and the mappings that allow migration between
|
||||
// schema versions.
|
||||
func Lineage(lib thema.Library, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("pkg", "coremodel", "pluginmeta"), cueFS, lib, opts...)
|
||||
func Lineage(rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("pkg", "coremodel", "pluginmeta"), cueFS, rt, opts...)
|
||||
}
|
||||
|
||||
var _ thema.LineageFactory = Lineage
|
||||
@ -594,8 +594,8 @@ func (c *Coremodel) GoType() interface{} {
|
||||
// Note that this function does not cache, and initially loading a Thema lineage
|
||||
// can be expensive. As such, the Grafana backend should prefer to access this
|
||||
// coremodel through a registry (pkg/framework/coremodel/registry), which does cache.
|
||||
func New(lib thema.Library) (*Coremodel, error) {
|
||||
lin, err := Lineage(lib)
|
||||
func New(rt *thema.Runtime) (*Coremodel, error) {
|
||||
lin, err := Lineage(rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Package cuectx provides a single, central CUE context (runtime) and Thema
|
||||
// library that can be used uniformly across Grafana, and related helper
|
||||
// functions for loading Thema lineages.
|
||||
// Package cuectx provides a single, central ["cuelang.org/go/cue".Context] and
|
||||
// ["github.com/grafana/thema".Runtime] that can be used uniformly across
|
||||
// Grafana, and related helper functions for loading Thema lineages.
|
||||
|
||||
package cuectx
|
||||
|
||||
@ -12,21 +12,27 @@ import (
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"github.com/grafana/thema"
|
||||
"github.com/grafana/thema/kernel"
|
||||
"github.com/grafana/thema/load"
|
||||
"github.com/grafana/thema/vmux"
|
||||
)
|
||||
|
||||
var ctx = cuecontext.New()
|
||||
var lib = thema.NewLibrary(ctx)
|
||||
var rt = thema.NewRuntime(ctx)
|
||||
|
||||
// ProvideCUEContext is a wire service provider of a central cue.Context.
|
||||
func ProvideCUEContext() *cue.Context {
|
||||
// GrafanaCUEContext returns Grafana's singleton instance of [cue.Context].
|
||||
//
|
||||
// All code within grafana/grafana that needs a *cue.Context should get it
|
||||
// from this function, when one was not otherwise provided.
|
||||
func GrafanaCUEContext() *cue.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
// ProvideThemaLibrary is a wire service provider of a central thema.Library.
|
||||
func ProvideThemaLibrary() thema.Library {
|
||||
return lib
|
||||
// GrafanaThemaRuntime returns Grafana's singleton instance of [thema.Runtime].
|
||||
//
|
||||
// All code within grafana/grafana that needs a *thema.Runtime should get it
|
||||
// from this function, when one was not otherwise provided.
|
||||
func GrafanaThemaRuntime() *thema.Runtime {
|
||||
return rt
|
||||
}
|
||||
|
||||
// JSONtoCUE attempts to decode the given []byte into a cue.Value, relying on
|
||||
@ -37,10 +43,10 @@ func ProvideThemaLibrary() thema.Library {
|
||||
// returned cue.Value.
|
||||
//
|
||||
// This is a convenience function for one-off JSON decoding. It's wasteful to
|
||||
// call it repeatedly. Most use cases use cases should probably prefer making
|
||||
// call it repeatedly. Most use cases should probably prefer making
|
||||
// their own Thema/CUE decoders.
|
||||
func JSONtoCUE(path string, b []byte) (cue.Value, error) {
|
||||
return kernel.NewJSONDecoder(path)(ctx, b)
|
||||
return vmux.NewJSONEndec(path).Decode(ctx, b)
|
||||
}
|
||||
|
||||
// LoadGrafanaInstancesWithThema loads CUE files containing a lineage
|
||||
@ -54,7 +60,7 @@ func JSONtoCUE(path string, b []byte) (cue.Value, error) {
|
||||
// More details on underlying behavior can be found in the docs for github.com/grafana/thema/load.InstancesWithThema.
|
||||
//
|
||||
// TODO this approach is complicated and confusing, refactor to something understandable
|
||||
func LoadGrafanaInstancesWithThema(path string, cueFS fs.FS, lib thema.Library, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
func LoadGrafanaInstancesWithThema(path string, cueFS fs.FS, rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
prefix := filepath.FromSlash(path)
|
||||
fs, err := prefixWithGrafanaCUE(prefix, cueFS)
|
||||
if err != nil {
|
||||
@ -68,9 +74,9 @@ func LoadGrafanaInstancesWithThema(path string, cueFS fs.FS, lib thema.Library,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
val := lib.Context().BuildInstance(inst)
|
||||
val := rt.Context().BuildInstance(inst)
|
||||
|
||||
lin, err := thema.BindLineage(val, lib, opts...)
|
||||
lin, err := thema.BindLineage(val, rt, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -20,11 +20,10 @@ import (
|
||||
"github.com/grafana/cuetsy/ts"
|
||||
"github.com/grafana/cuetsy/ts/ast"
|
||||
gcgen "github.com/grafana/grafana/pkg/codegen"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
var lib = thema.NewLibrary(cuecontext.New())
|
||||
|
||||
const sep = string(filepath.Separator)
|
||||
|
||||
var tsroot, cmroot, groot string
|
||||
@ -46,6 +45,7 @@ func init() {
|
||||
// Generate Go and Typescript implementations for all coremodels, and populate the
|
||||
// coremodel static registry.
|
||||
func main() {
|
||||
rt := cuectx.GrafanaThemaRuntime()
|
||||
if len(os.Args) > 1 {
|
||||
fmt.Fprintf(os.Stderr, "coremodel code generator does not currently accept any arguments\n, got %q", os.Args)
|
||||
os.Exit(1)
|
||||
@ -60,7 +60,7 @@ func main() {
|
||||
var lins []*gcgen.CoremodelDeclaration
|
||||
for _, item := range items {
|
||||
if item.IsDir() {
|
||||
lin, err := gcgen.ExtractLineage(filepath.Join(cmroot, item.Name(), "coremodel.cue"), lib)
|
||||
lin, err := gcgen.ExtractLineage(filepath.Join(cmroot, item.Name(), "coremodel.cue"), rt)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "could not process coremodel dir %s: %s\n", filepath.Join(cmroot, item.Name()), err)
|
||||
os.Exit(1)
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/load"
|
||||
"github.com/grafana/thema/kernel"
|
||||
tload "github.com/grafana/thema/load"
|
||||
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
@ -24,7 +23,7 @@ var defaultFramework cue.Value
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
defaultFramework, err = doLoadFrameworkCUE(cuectx.ProvideCUEContext())
|
||||
defaultFramework, err = doLoadFrameworkCUE(cuectx.GrafanaCUEContext())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -106,81 +105,3 @@ func CUEFrameworkWithContext(ctx *cue.Context) cue.Value {
|
||||
v, _ := doLoadFrameworkCUE(ctx) // nolint:errcheck
|
||||
return v
|
||||
}
|
||||
|
||||
// Mux takes a coremodel and returns a Thema version muxer that, given a byte
|
||||
// slice containing any version of schema for that coremodel, will translate it
|
||||
// to the Interface.CurrentSchema() version, and optionally decode it onto the
|
||||
// Interface.GoType().
|
||||
//
|
||||
// By default, JSON decoding will be used, and the filename given to any input
|
||||
// bytes (shown in errors, which may be user-facing) will be
|
||||
// "<name>.<encoding>", e.g. dashboard.json.
|
||||
func Mux(cm Interface, opts ...MuxOption) kernel.InputKernel {
|
||||
c := &muxConfig{}
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
|
||||
cfg := kernel.InputKernelConfig{
|
||||
Typ: cm.GoType(),
|
||||
Lineage: cm.Lineage(),
|
||||
To: cm.CurrentSchema().Version(),
|
||||
}
|
||||
|
||||
switch c.decodetyp {
|
||||
case "", "json": // json by default
|
||||
if c.filename == "" {
|
||||
c.filename = fmt.Sprintf("%s.json", cm.Lineage().Name())
|
||||
}
|
||||
cfg.Loader = kernel.NewJSONDecoder(c.filename)
|
||||
case "yaml":
|
||||
if c.filename == "" {
|
||||
c.filename = fmt.Sprintf("%s.yaml", cm.Lineage().Name())
|
||||
}
|
||||
cfg.Loader = kernel.NewYAMLDecoder(c.filename)
|
||||
default:
|
||||
panic("")
|
||||
}
|
||||
|
||||
mux, err := kernel.NewInputKernel(cfg)
|
||||
if err != nil {
|
||||
// Barring a fundamental bug in Thema's schema->Go type assignability checker or
|
||||
// a direct attempt by a Grafana dev to get around the invariants of coremodel codegen,
|
||||
// this should be unreachable. (And even the latter case should be caught elsewhere
|
||||
// by tests).
|
||||
panic(err)
|
||||
}
|
||||
return mux
|
||||
}
|
||||
|
||||
// A MuxOption defines options that may be specified only at initial
|
||||
// construction of a Lineage via BindLineage.
|
||||
type MuxOption muxOption
|
||||
|
||||
// Internal representation of MuxOption.
|
||||
type muxOption func(c *muxConfig)
|
||||
|
||||
type muxConfig struct {
|
||||
filename string
|
||||
decodetyp string
|
||||
}
|
||||
|
||||
// YAML indicates that the resulting Mux should look for YAML in input bytes,
|
||||
// rather than the default JSON.
|
||||
func YAML() MuxOption {
|
||||
return func(c *muxConfig) {
|
||||
c.decodetyp = "yaml"
|
||||
}
|
||||
}
|
||||
|
||||
// Filename specifies the filename that is given to input bytes passing through
|
||||
// the mux.
|
||||
//
|
||||
// The filename has no impact on mux behavior, but is used in user-facing error
|
||||
// output, such as schema validation failures. Thus, it is recommended to pick a
|
||||
// name that will make sense in the context a user is expected to see the error.
|
||||
func Filename(name string) MuxOption {
|
||||
return func(c *muxConfig) {
|
||||
c.filename = name
|
||||
}
|
||||
}
|
||||
|
@ -17,19 +17,20 @@ var CoremodelSet = wire.NewSet(
|
||||
// NewBase provides a registry of all coremodels, without any composition of
|
||||
// plugin-defined schemas.
|
||||
//
|
||||
// The returned registry will use the default Grafana thema.Library, defined in
|
||||
// pkg/cuectx. If you need control over the thema.Library used by the coremodel
|
||||
// lineages, use NewBaseWithLib instead.
|
||||
// The returned registry will use Grafana's singleton [thema.Runtime],
|
||||
// returned from [cuectx.GrafanaThemaRuntime].
|
||||
func NewBase() *Base {
|
||||
return provideBase(nil)
|
||||
}
|
||||
|
||||
// NewBaseWithLib is the same as NewBase, but allows control over the
|
||||
// thema.Library used to initialize the underlying coremodels.
|
||||
// NewBaseWithRuntime is the same as NewBase, but allows control over the
|
||||
// [thema.Runtime] used to initialize the underlying coremodels.
|
||||
//
|
||||
// Prefer NewBase unless you absolutely need this control.
|
||||
func NewBaseWithLib(lib thema.Library) *Base {
|
||||
return provideBase(&lib)
|
||||
//
|
||||
// TODO it's OK to export this if it's ever actually needed
|
||||
func NewBaseWithRuntime(rt *thema.Runtime) *Base {
|
||||
return provideBase(rt)
|
||||
}
|
||||
|
||||
var (
|
||||
@ -37,15 +38,15 @@ var (
|
||||
defaultBase *Base
|
||||
)
|
||||
|
||||
func provideBase(lib *thema.Library) *Base {
|
||||
if lib == nil {
|
||||
func provideBase(rt *thema.Runtime) *Base {
|
||||
if rt == nil {
|
||||
baseOnce.Do(func() {
|
||||
defaultBase = doProvideBase(cuectx.ProvideThemaLibrary())
|
||||
defaultBase = doProvideBase(cuectx.GrafanaThemaRuntime())
|
||||
})
|
||||
return defaultBase
|
||||
}
|
||||
|
||||
return doProvideBase(*lib)
|
||||
return doProvideBase(rt)
|
||||
}
|
||||
|
||||
// All returns a slice of all registered coremodels.
|
||||
|
@ -57,23 +57,23 @@ func (b *Base) Pluginmeta() *pluginmeta.Coremodel {
|
||||
return b.pluginmeta
|
||||
}
|
||||
|
||||
func doProvideBase(lib thema.Library) *Base {
|
||||
func doProvideBase(rt *thema.Runtime) *Base {
|
||||
var err error
|
||||
reg := &Base{}
|
||||
|
||||
reg.dashboard, err = dashboard.New(lib)
|
||||
reg.dashboard, err = dashboard.New(rt)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error while initializing dashboard coremodel: %s", err))
|
||||
}
|
||||
reg.all = append(reg.all, reg.dashboard)
|
||||
|
||||
reg.playlist, err = playlist.New(lib)
|
||||
reg.playlist, err = playlist.New(rt)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error while initializing playlist coremodel: %s", err))
|
||||
}
|
||||
reg.all = append(reg.all, reg.playlist)
|
||||
|
||||
reg.pluginmeta, err = pluginmeta.New(lib)
|
||||
reg.pluginmeta, err = pluginmeta.New(rt)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error while initializing pluginmeta coremodel: %s", err))
|
||||
}
|
||||
|
@ -27,61 +27,61 @@ import (
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
func makeTreeOrPanic(path string, pkgname string, lib thema.Library) *pfs.Tree {
|
||||
func makeTreeOrPanic(path string, pkgname string, rt *thema.Runtime) *pfs.Tree {
|
||||
sub, err := fs.Sub(grafana.CueSchemaFS, path)
|
||||
if err != nil {
|
||||
panic("could not create fs sub to " + path)
|
||||
}
|
||||
tree, err := pfs.ParsePluginFS(sub, lib)
|
||||
tree, err := pfs.ParsePluginFS(sub, rt)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error parsing plugin metadata for %s: %s", pkgname, err))
|
||||
}
|
||||
return tree
|
||||
}
|
||||
|
||||
func coreTreeList(lib thema.Library) pfs.TreeList {
|
||||
func coreTreeList(rt *thema.Runtime) pfs.TreeList {
|
||||
return pfs.TreeList{
|
||||
makeTreeOrPanic("public/app/plugins/datasource/alertmanager", "alertmanager", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/cloud-monitoring", "stackdriver", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/cloudwatch", "cloudwatch", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/dashboard", "dashboard", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/elasticsearch", "elasticsearch", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/grafana", "grafana", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/grafana-azure-monitor-datasource", "grafana_azure_monitor_datasource", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/graphite", "graphite", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/jaeger", "jaeger", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/loki", "loki", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/mssql", "mssql", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/mysql", "mysql", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/postgres", "postgres", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/prometheus", "prometheus", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/tempo", "tempo", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/testdata", "testdata", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/zipkin", "zipkin", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/alertGroups", "alertGroups", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/alertlist", "alertlist", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/annolist", "annolist", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/barchart", "barchart", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/bargauge", "bargauge", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/dashlist", "dashlist", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/debug", "debug", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/flamegraph", "flamegraph", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/gauge", "gauge", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/geomap", "geomap", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/gettingstarted", "gettingstarted", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/graph", "graph", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/histogram", "histogram", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/icon", "icon", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/live", "live", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/logs", "logs", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/news", "news", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/nodeGraph", "nodeGraph", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/piechart", "piechart", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/stat", "stat", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/table-old", "table_old", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/text", "text", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/traces", "traces", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/welcome", "welcome", lib),
|
||||
makeTreeOrPanic("public/app/plugins/panel/xychart", "xychart", lib),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/alertmanager", "alertmanager", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/cloud-monitoring", "stackdriver", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/cloudwatch", "cloudwatch", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/dashboard", "dashboard", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/elasticsearch", "elasticsearch", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/grafana", "grafana", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/grafana-azure-monitor-datasource", "grafana_azure_monitor_datasource", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/graphite", "graphite", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/jaeger", "jaeger", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/loki", "loki", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/mssql", "mssql", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/mysql", "mysql", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/postgres", "postgres", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/prometheus", "prometheus", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/tempo", "tempo", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/testdata", "testdata", rt),
|
||||
makeTreeOrPanic("public/app/plugins/datasource/zipkin", "zipkin", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/alertGroups", "alertGroups", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/alertlist", "alertlist", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/annolist", "annolist", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/barchart", "barchart", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/bargauge", "bargauge", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/dashlist", "dashlist", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/debug", "debug", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/flamegraph", "flamegraph", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/gauge", "gauge", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/geomap", "geomap", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/gettingstarted", "gettingstarted", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/graph", "graph", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/histogram", "histogram", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/icon", "icon", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/live", "live", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/logs", "logs", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/news", "news", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/nodeGraph", "nodeGraph", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/piechart", "piechart", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/stat", "stat", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/table-old", "table_old", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/text", "text", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/traces", "traces", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/welcome", "welcome", rt),
|
||||
makeTreeOrPanic("public/app/plugins/panel/xychart", "xychart", rt),
|
||||
}
|
||||
}
|
||||
|
@ -15,16 +15,16 @@ var coreOnce sync.Once
|
||||
// in the current version of Grafana.
|
||||
//
|
||||
// Go code within the grafana codebase should only ever call this with nil.
|
||||
func New(lib *thema.Library) pfs.TreeList {
|
||||
func New(rt *thema.Runtime) pfs.TreeList {
|
||||
var tl pfs.TreeList
|
||||
if lib == nil {
|
||||
if rt == nil {
|
||||
coreOnce.Do(func() {
|
||||
coreTrees = coreTreeList(cuectx.ProvideThemaLibrary())
|
||||
coreTrees = coreTreeList(cuectx.GrafanaThemaRuntime())
|
||||
})
|
||||
tl = make(pfs.TreeList, len(coreTrees))
|
||||
copy(tl, coreTrees)
|
||||
} else {
|
||||
return coreTreeList(*lib)
|
||||
return coreTreeList(rt)
|
||||
}
|
||||
return tl
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ import (
|
||||
"cuelang.org/go/cue/parser"
|
||||
"github.com/grafana/grafana"
|
||||
"github.com/grafana/grafana/pkg/coremodel/pluginmeta"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"github.com/grafana/grafana/pkg/framework/coremodel"
|
||||
"github.com/grafana/grafana/pkg/framework/coremodel/registry"
|
||||
"github.com/grafana/thema"
|
||||
"github.com/grafana/thema/kernel"
|
||||
"github.com/grafana/thema/load"
|
||||
"github.com/grafana/thema/vmux"
|
||||
"github.com/yalue/merged_fs"
|
||||
)
|
||||
|
||||
@ -51,11 +51,9 @@ type slotandname struct {
|
||||
|
||||
var allslots []slotandname
|
||||
|
||||
var plugmux kernel.InputKernel
|
||||
|
||||
// TODO re-enable after go1.18
|
||||
// var tsch thema.TypedSchema[pluginmeta.Model]
|
||||
// var plugmux vmux.ValueMux[pluginmeta.Model]
|
||||
var tsch thema.TypedSchema[*pluginmeta.Model]
|
||||
var plugmux vmux.ValueMux[*pluginmeta.Model]
|
||||
|
||||
func init() {
|
||||
var all []string
|
||||
@ -78,13 +76,6 @@ func init() {
|
||||
|
||||
var muxonce sync.Once
|
||||
|
||||
func loadMux() kernel.InputKernel {
|
||||
muxonce.Do(func() {
|
||||
plugmux = coremodel.Mux(registry.NewBase().Pluginmeta(), coremodel.Filename("plugin.json"))
|
||||
})
|
||||
return plugmux
|
||||
}
|
||||
|
||||
// This used to be in init(), but that creates a risk for codegen.
|
||||
//
|
||||
// thema.BindType ensures that Go type and Thema schema are aligned. If we were
|
||||
@ -102,19 +93,22 @@ func loadMux() kernel.InputKernel {
|
||||
// called as needed to get our muxer, and internally relies on a sync.Once to avoid
|
||||
// repeated processing of thema.BindType.
|
||||
// TODO mux loading is easily generalizable in pkg/f/coremodel, shouldn't need one-off
|
||||
// TODO switch to this generic signature after go1.18
|
||||
// func loadMux() (thema.TypedSchema[pluginmeta.Model], vmux.ValueMux[pluginmeta.Model]) {
|
||||
// muxonce.Do(func() {
|
||||
// var err error
|
||||
// var t pluginmeta.Model
|
||||
// tsch, err = thema.BindType[pluginmeta.Model](pm.CurrentSchema(), t)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// plugmux = vmux.NewValueMux(tsch, vmux.NewJSONEndec("plugin.json"))
|
||||
// })
|
||||
// return tsch, plugmux
|
||||
// }
|
||||
func loadMux() (thema.TypedSchema[*pluginmeta.Model], vmux.ValueMux[*pluginmeta.Model]) {
|
||||
muxonce.Do(func() {
|
||||
var err error
|
||||
t := new(pluginmeta.Model)
|
||||
pm, err := pluginmeta.New(cuectx.GrafanaThemaRuntime())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tsch, err = thema.BindType[*pluginmeta.Model](pm.CurrentSchema(), t)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
plugmux = vmux.NewValueMux(tsch, vmux.NewJSONEndec("plugin.json"))
|
||||
})
|
||||
return tsch, plugmux
|
||||
}
|
||||
|
||||
// Tree represents the contents of a plugin filesystem tree.
|
||||
type Tree struct {
|
||||
@ -190,13 +184,12 @@ func (pi PluginInfo) Meta() pluginmeta.Model {
|
||||
// It does not descend into subdirectories to search for additional plugin.json
|
||||
// files.
|
||||
// TODO no descent is ok for core plugins, but won't cut it in general
|
||||
func ParsePluginFS(f fs.FS, lib thema.Library) (*Tree, error) {
|
||||
func ParsePluginFS(f fs.FS, rt *thema.Runtime) (*Tree, error) {
|
||||
if f == nil {
|
||||
return nil, ErrEmptyFS
|
||||
}
|
||||
// _, mux := loadMux()
|
||||
mux := loadMux()
|
||||
ctx := lib.Context()
|
||||
_, mux := loadMux()
|
||||
ctx := rt.Context()
|
||||
|
||||
b, err := fs.ReadFile(f, "plugin.json")
|
||||
if err != nil {
|
||||
@ -216,13 +209,14 @@ func ParsePluginFS(f fs.FS, lib thema.Library) (*Tree, error) {
|
||||
|
||||
// Pass the raw bytes into the muxer, get the populated Model type out that we want.
|
||||
// TODO stop ignoring second return. (for now, lacunas are a WIP and can't occur until there's >1 schema in the pluginmeta lineage)
|
||||
metaany, _, err := mux.Converge(b)
|
||||
// metaany, _, err := mux(b)
|
||||
pmeta, _, err := mux(b)
|
||||
if err != nil {
|
||||
// TODO more nuanced error handling by class of Thema failure
|
||||
// return nil, fmt.Errorf("plugin.json was invalid: %w", err)
|
||||
return nil, ewrap(err, ErrInvalidRootFile)
|
||||
}
|
||||
r.meta = *metaany.(*pluginmeta.Model)
|
||||
r.meta = *pmeta
|
||||
|
||||
if modbyt, err := fs.ReadFile(f, "models.cue"); err == nil {
|
||||
// TODO introduce layered CUE dependency-injecting loader
|
||||
@ -260,7 +254,7 @@ func ParsePluginFS(f fs.FS, lib thema.Library) (*Tree, error) {
|
||||
}
|
||||
for _, s := range allslots {
|
||||
iv := val.LookupPath(cue.ParsePath(s.slot.Name()))
|
||||
lin, err := bindSlotLineage(iv, s.slot, r.meta, lib)
|
||||
lin, err := bindSlotLineage(iv, s.slot, r.meta, rt)
|
||||
if lin != nil {
|
||||
r.slotimpls[s.slot.Name()] = lin
|
||||
}
|
||||
@ -273,7 +267,7 @@ func ParsePluginFS(f fs.FS, lib thema.Library) (*Tree, error) {
|
||||
return tree, nil
|
||||
}
|
||||
|
||||
func bindSlotLineage(v cue.Value, s *coremodel.Slot, meta pluginmeta.Model, lib thema.Library, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
func bindSlotLineage(v cue.Value, s *coremodel.Slot, meta pluginmeta.Model, rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
accept, required := s.ForPluginType(string(meta.Type))
|
||||
exists := v.Exists()
|
||||
|
||||
@ -292,8 +286,8 @@ func bindSlotLineage(v cue.Value, s *coremodel.Slot, meta pluginmeta.Model, lib
|
||||
}
|
||||
|
||||
// TODO make this opt real in thema, then uncomment to enforce joinSchema
|
||||
// lin, err := thema.BindLineage(iv, lib, thema.SatisfiesJoinSchema(s.MetaSchema()))
|
||||
lin, err := thema.BindLineage(v, lib, opts...)
|
||||
// lin, err := thema.BindLineage(iv, rt, thema.SatisfiesJoinSchema(s.MetaSchema()))
|
||||
lin, err := thema.BindLineage(v, rt, opts...)
|
||||
if err != nil {
|
||||
return nil, ewrap(fmt.Errorf("%s: invalid thema lineage for slot %s: %w", meta.Id, s.Name(), err), ErrInvalidLineage)
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ func TestParseTreeTestdata(t *testing.T) {
|
||||
tab[ent.Name()] = tst
|
||||
}
|
||||
|
||||
lib := cuectx.ProvideThemaLibrary()
|
||||
lib := cuectx.GrafanaThemaRuntime()
|
||||
for name, otst := range tab {
|
||||
tst := otst // otherwise var is shadowed within func by looping
|
||||
t.Run(name, func(t *testing.T) {
|
||||
@ -256,7 +256,7 @@ func TestParseTreeZips(t *testing.T) {
|
||||
tab[ent.Name()] = tst
|
||||
}
|
||||
|
||||
lib := cuectx.ProvideThemaLibrary()
|
||||
lib := cuectx.GrafanaThemaRuntime()
|
||||
for name, otst := range tab {
|
||||
tst := otst // otherwise var is shadowed within func by looping
|
||||
t.Run(name, func(t *testing.T) {
|
||||
|
@ -330,8 +330,8 @@ var wireBasicSet = wire.NewSet(
|
||||
authproxy.ProvideAuthProxy,
|
||||
statscollector.ProvideService,
|
||||
cmreg.CoremodelSet,
|
||||
cuectx.ProvideCUEContext,
|
||||
cuectx.ProvideThemaLibrary,
|
||||
cuectx.GrafanaCUEContext,
|
||||
cuectx.GrafanaThemaRuntime,
|
||||
csrf.ProvideCSRFFilter,
|
||||
ossaccesscontrol.ProvideTeamPermissions,
|
||||
wire.Bind(new(accesscontrol.TeamPermissionsService), new(*ossaccesscontrol.TeamPermissionsService)),
|
||||
|
@ -48,7 +48,7 @@ func main() {
|
||||
groot := filepath.Join(sep, filepath.Join(grootp[:len(grootp)-3]...))
|
||||
|
||||
wd := codegen.NewWriteDiffer()
|
||||
lib := cuectx.ProvideThemaLibrary()
|
||||
lib := cuectx.GrafanaThemaRuntime()
|
||||
|
||||
type ptreepath struct {
|
||||
Path string
|
||||
|
Loading…
Reference in New Issue
Block a user