Kindsys: Remove Raw kind category (#60992)

* Remove Raw references

* Remove more raws

* Re-generate files

* Remove raw folder from veneer

* Fix import

* Fix lint

* Bring back raw folder in grafana-schema

* Another lint

* Remove use of "Structured" word in kinds

* Delete unused function and remove some structured words

* Bunch more removals of structured name

Co-authored-by: sam boyer <sdboyer@grafana.com>
pull/61068/head
Selene 3 years ago committed by GitHub
parent db369fc5b2
commit 8f29450594
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      embed.go
  2. 4
      kinds/constraint.cue
  3. 0
      kinds/dashboard/dashboard_kind.cue
  4. 39
      kinds/gen.go
  5. 0
      kinds/playlist/playlist_kind.cue
  6. 4
      kinds/raw/svg/svg_kind.cue
  7. 8
      kinds/structured/constraint.cue
  8. 0
      kinds/team/team_kind.cue
  9. 23
      pkg/codegen/generators.go
  10. 10
      pkg/codegen/jenny_basecorereg.go
  11. 26
      pkg/codegen/jenny_corekind.go
  12. 3
      pkg/codegen/jenny_eachmajor.go
  13. 68
      pkg/codegen/jenny_rawkind.go
  14. 4
      pkg/codegen/jenny_tsveneerindex.go
  15. 3
      pkg/codegen/latest_jenny.go
  16. 2
      pkg/codegen/tmpl.go
  17. 12
      pkg/codegen/tmpl/kind_core.tmpl
  18. 57
      pkg/codegen/tmpl/kind_raw.tmpl
  19. 12
      pkg/codegen/tmpl/kind_registry.tmpl
  20. 14
      pkg/kinds/dashboard/dashboard_kind_gen.go
  21. 14
      pkg/kinds/playlist/playlist_kind_gen.go
  22. 64
      pkg/kinds/svg/svg_kind_gen.go
  23. 14
      pkg/kinds/team/team_kind_gen.go
  24. 3
      pkg/kindsys/EXTENDING.md
  25. 14
      pkg/kindsys/kind.go
  26. 15
      pkg/kindsys/kindcat_custom.cue
  27. 85
      pkg/kindsys/kindcats.cue
  28. 46
      pkg/kindsys/kindmetas.go
  29. 58
      pkg/kindsys/load.go
  30. 12
      pkg/kindsys/report.go
  31. 13
      pkg/kindsys/report.json
  32. 2
      pkg/plugins/manager/testdata/disallowed-cue-import/models.cue
  33. 35
      pkg/registry/corekind/base.go
  34. 28
      pkg/registry/corekind/base_gen.go

@ -6,5 +6,5 @@ import (
// CueSchemaFS embeds all schema-related CUE files in the Grafana project. // CueSchemaFS embeds all schema-related CUE files in the Grafana project.
// //
//go:embed cue.mod/module.cue kinds/*/*.cue kinds/*/*/*.cue packages/grafana-schema/src/schema/*.cue public/app/plugins/*/*/*.cue public/app/plugins/*/*/plugin.json pkg/kindsys/*.cue pkg/plugins/plugindef/*.cue //go:embed cue.mod/module.cue kinds/*.cue kinds/*/*.cue packages/grafana-schema/src/schema/*.cue public/app/plugins/*/*/*.cue public/app/plugins/*/*/plugin.json pkg/kindsys/*.cue pkg/plugins/plugindef/*.cue
var CueSchemaFS embed.FS var CueSchemaFS embed.FS

@ -3,5 +3,5 @@ package kind
import "github.com/grafana/grafana/pkg/kindsys" import "github.com/grafana/grafana/pkg/kindsys"
// In each child directory, the set of .cue files with 'package kind' // In each child directory, the set of .cue files with 'package kind'
// must be an instance of kindsys.#Raw - a declaration of a raw kind. // must be an instance of kindsys.#Core - a declaration of a core kind.
kindsys.#Raw kindsys.#Core

@ -28,7 +28,7 @@ func main() {
} }
// Core kinds composite code generator. Produces all generated code in // Core kinds composite code generator. Produces all generated code in
// grafana/grafana that derives from raw and structured core kinds. // grafana/grafana that derives from core kinds.
coreKindsGen := codejen.JennyListWithNamer(func(decl *codegen.DeclForGen) string { coreKindsGen := codejen.JennyListWithNamer(func(decl *codegen.DeclForGen) string {
return decl.Properties.Common().MachineName return decl.Properties.Common().MachineName
}) })
@ -36,8 +36,7 @@ func main() {
// All the jennies that comprise the core kinds generator pipeline // All the jennies that comprise the core kinds generator pipeline
coreKindsGen.Append( coreKindsGen.Append(
codegen.LatestJenny(kindsys.GoCoreKindParentPath, codegen.GoTypesJenny{}), codegen.LatestJenny(kindsys.GoCoreKindParentPath, codegen.GoTypesJenny{}),
codegen.CoreStructuredKindJenny(kindsys.GoCoreKindParentPath, nil), codegen.CoreKindJenny(kindsys.GoCoreKindParentPath, nil),
codegen.RawKindJenny(kindsys.GoCoreKindParentPath, nil),
codegen.BaseCoreRegistryJenny(filepath.Join("pkg", "registry", "corekind"), kindsys.GoCoreKindParentPath), codegen.BaseCoreRegistryJenny(filepath.Join("pkg", "registry", "corekind"), kindsys.GoCoreKindParentPath),
codegen.LatestMajorsOrXJenny(kindsys.TSCoreKindParentPath, codegen.TSTypesJenny{}), codegen.LatestMajorsOrXJenny(kindsys.TSCoreKindParentPath, codegen.TSTypesJenny{}),
codegen.TSVeneerIndexJenny(filepath.Join("packages", "grafana-schema", "src")), codegen.TSVeneerIndexJenny(filepath.Join("packages", "grafana-schema", "src")),
@ -55,15 +54,14 @@ func main() {
rt := cuectx.GrafanaThemaRuntime() rt := cuectx.GrafanaThemaRuntime()
var all []*codegen.DeclForGen var all []*codegen.DeclForGen
// structured kinddirs first f := os.DirFS(filepath.Join(groot, kindsys.CoreDeclParentPath))
f := os.DirFS(filepath.Join(groot, kindsys.CoreStructuredDeclParentPath)) kinddirs := elsedie(fs.ReadDir(f, "."))("error reading core kind fs root directory")
kinddirs := elsedie(fs.ReadDir(f, "."))("error reading structured fs root directory")
for _, ent := range kinddirs { for _, ent := range kinddirs {
if !ent.IsDir() { if !ent.IsDir() {
continue continue
} }
rel := filepath.Join(kindsys.CoreStructuredDeclParentPath, ent.Name()) rel := filepath.Join(kindsys.CoreDeclParentPath, ent.Name())
decl, err := kindsys.LoadCoreKind[kindsys.CoreStructuredProperties](rel, rt.Context(), nil) decl, err := kindsys.LoadCoreKind(rel, rt.Context(), nil)
if err != nil { if err != nil {
die(fmt.Errorf("%s is not a valid kind: %s", rel, errors.Details(err, nil))) die(fmt.Errorf("%s is not a valid kind: %s", rel, errors.Details(err, nil)))
} }
@ -74,25 +72,6 @@ func main() {
all = append(all, elsedie(codegen.ForGen(rt, decl.Some()))(rel)) all = append(all, elsedie(codegen.ForGen(rt, decl.Some()))(rel))
} }
// now raw kinddirs
f = os.DirFS(filepath.Join(groot, kindsys.RawDeclParentPath))
kinddirs = elsedie(fs.ReadDir(f, "."))("error reading raw fs root directory")
for _, ent := range kinddirs {
if !ent.IsDir() {
continue
}
rel := filepath.Join(kindsys.RawDeclParentPath, ent.Name())
decl, err := kindsys.LoadCoreKind[kindsys.RawProperties](rel, rt.Context(), nil)
if err != nil {
die(fmt.Errorf("%s is not a valid kind: %s", rel, errors.Details(err, nil)))
}
if decl.Properties.MachineName != ent.Name() {
die(fmt.Errorf("%s: kind's machine name (%s) must equal parent dir name (%s)", rel, decl.Properties.Name, ent.Name()))
}
dfg, _ := codegen.ForGen(nil, decl.Some())
all = append(all, dfg)
}
sort.Slice(all, func(i, j int) bool { sort.Slice(all, func(i, j int) bool {
return nameFor(all[i].Properties) < nameFor(all[j].Properties) return nameFor(all[i].Properties) < nameFor(all[j].Properties)
}) })
@ -113,11 +92,9 @@ func main() {
func nameFor(m kindsys.SomeKindProperties) string { func nameFor(m kindsys.SomeKindProperties) string {
switch x := m.(type) { switch x := m.(type) {
case kindsys.RawProperties: case kindsys.CoreProperties:
return x.Name
case kindsys.CoreStructuredProperties:
return x.Name return x.Name
case kindsys.CustomStructuredProperties: case kindsys.CustomProperties:
return x.Name return x.Name
case kindsys.ComposableProperties: case kindsys.ComposableProperties:
return x.Name return x.Name

@ -1,4 +0,0 @@
package kind
name: "SVG"
extensions: ["svg"]

@ -1,8 +0,0 @@
package kind
import "github.com/grafana/grafana/pkg/kindsys"
// In each child directory, the set of .cue files with 'package kind'
// must be an instance of kindsys.#CoreStructured - a declaration of a
// structured kind.
kindsys.#CoreStructured

@ -29,29 +29,6 @@ func ForGen(rt *thema.Runtime, decl *kindsys.SomeDecl) (*DeclForGen, error) {
}, nil }, nil
} }
// RawForGen produces a [DeclForGen] from a [kindsys.Raw] kind.
//
// Useful for grafana-external code generators, which depend on the Kind
// representation in registries produced by grafana core (such as
// ["github.com/grafana/grafana/pkg/registry/corekind".NewBase]).
func RawForGen(k kindsys.Raw) *DeclForGen {
return &DeclForGen{
SomeDecl: k.Decl().Some(),
}
}
// StructuredForGen produces a [DeclForGen] from a [kindsys.Structured] kind.
//
// Useful for grafana-external code generators, which depend on the Kind
// representation in registries produced by grafana core (such as
// ["github.com/grafana/grafana/pkg/registry/corekind".NewBase]).
func StructuredForGen(k kindsys.Structured) *DeclForGen {
return &DeclForGen{
SomeDecl: k.Decl().Some(),
lin: k.Lineage(),
}
}
// DeclForGen wraps [kindsys.SomeDecl] to provide trivial caching of // DeclForGen wraps [kindsys.SomeDecl] to provide trivial caching of
// the lineage declared by the kind (nil for raw kinds). // the lineage declared by the kind (nil for raw kinds).
type DeclForGen struct { type DeclForGen struct {

@ -32,17 +32,9 @@ func (gen *genBaseRegistry) JennyName() string {
} }
func (gen *genBaseRegistry) Generate(decls ...*DeclForGen) (*codejen.File, error) { func (gen *genBaseRegistry) Generate(decls ...*DeclForGen) (*codejen.File, error) {
var numRaw int
for _, k := range decls {
if k.IsRaw() {
numRaw++
}
}
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := tmpls.Lookup("kind_registry.tmpl").Execute(buf, tvars_kind_registry{ if err := tmpls.Lookup("kind_registry.tmpl").Execute(buf, tvars_kind_registry{
NumRaw: numRaw, NumStructured: len(decls),
NumStructured: len(decls) - numRaw,
PackageName: filepath.Base(gen.path), PackageName: filepath.Base(gen.path),
KindPackagePrefix: filepath.ToSlash(filepath.Join("github.com/grafana/grafana", gen.kindrelroot)), KindPackagePrefix: filepath.ToSlash(filepath.Join("github.com/grafana/grafana", gen.kindrelroot)),
Kinds: decls, Kinds: decls,

@ -8,14 +8,14 @@ import (
"github.com/grafana/codejen" "github.com/grafana/codejen"
) )
// CoreStructuredKindJenny generates the implementation of // CoreKindJenny generates the implementation of [kindsys.Core] for the provided
// [kindsys.Structured] for the provided kind declaration. // kind declaration.
// //
// gokindsdir should be the relative path to the parent directory that contains // gokindsdir should be the relative path to the parent directory that contains
// all generated kinds. // all generated kinds.
// //
// This generator only has output for core structured kinds. // This generator only has output for core structured kinds.
func CoreStructuredKindJenny(gokindsdir string, cfg *CoreStructuredKindGeneratorConfig) OneToOne { func CoreKindJenny(gokindsdir string, cfg *CoreStructuredKindGeneratorConfig) OneToOne {
if cfg == nil { if cfg == nil {
cfg = new(CoreStructuredKindGeneratorConfig) cfg = new(CoreStructuredKindGeneratorConfig)
} }
@ -25,39 +25,39 @@ func CoreStructuredKindJenny(gokindsdir string, cfg *CoreStructuredKindGenerator
} }
} }
return &genCoreStructuredKind{ return &coreKindJenny{
gokindsdir: gokindsdir, gokindsdir: gokindsdir,
cfg: cfg, cfg: cfg,
} }
} }
// CoreStructuredKindGeneratorConfig holds configuration options for [CoreStructuredKindJenny]. // CoreStructuredKindGeneratorConfig holds configuration options for [CoreKindJenny].
type CoreStructuredKindGeneratorConfig struct { type CoreStructuredKindGeneratorConfig struct {
// GenDirName returns the name of the directory in which the file should be // GenDirName returns the name of the directory in which the file should be
// generated. Defaults to DeclForGen.Lineage().Name() if nil. // generated. Defaults to DeclForGen.Lineage().Name() if nil.
GenDirName func(*DeclForGen) string GenDirName func(*DeclForGen) string
} }
type genCoreStructuredKind struct { type coreKindJenny struct {
gokindsdir string gokindsdir string
cfg *CoreStructuredKindGeneratorConfig cfg *CoreStructuredKindGeneratorConfig
} }
var _ OneToOne = &genCoreStructuredKind{} var _ OneToOne = &coreKindJenny{}
func (gen *genCoreStructuredKind) JennyName() string { func (gen *coreKindJenny) JennyName() string {
return "CoreStructuredKindJenny" return "CoreKindJenny"
} }
func (gen *genCoreStructuredKind) Generate(decl *DeclForGen) (*codejen.File, error) { func (gen *coreKindJenny) Generate(decl *DeclForGen) (*codejen.File, error) {
if !decl.IsCoreStructured() { if !decl.IsCore() {
return nil, nil return nil, nil
} }
path := filepath.Join(gen.gokindsdir, gen.cfg.GenDirName(decl), decl.Properties.Common().MachineName+"_kind_gen.go") path := filepath.Join(gen.gokindsdir, gen.cfg.GenDirName(decl), decl.Properties.Common().MachineName+"_kind_gen.go")
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := tmpls.Lookup("kind_corestructured.tmpl").Execute(buf, decl); err != nil { if err := tmpls.Lookup("kind_core.tmpl").Execute(buf, decl); err != nil {
return nil, fmt.Errorf("failed executing kind_corestructured template for %s: %w", path, err) return nil, fmt.Errorf("failed executing kind_core template for %s: %w", path, err)
} }
b, err := postprocessGoFile(genGoFile{ b, err := postprocessGoFile(genGoFile{
path: path, path: path,

@ -30,9 +30,6 @@ func (j *lmox) JennyName() string {
} }
func (j *lmox) Generate(decl *DeclForGen) (codejen.Files, error) { func (j *lmox) Generate(decl *DeclForGen) (codejen.Files, error) {
if decl.IsRaw() {
return nil, nil
}
comm := decl.Properties.Common() comm := decl.Properties.Common()
sfg := SchemaForGen{ sfg := SchemaForGen{
Name: comm.Name, Name: comm.Name,

@ -1,68 +0,0 @@
package codegen
import (
"bytes"
"fmt"
"path/filepath"
"github.com/grafana/codejen"
)
// RawKindJenny generates the implementation of [kindsys.Raw] for the
// provided kind declaration.
//
// gokindsdir should be the relative path to the parent directory that contains
// all generated kinds.
//
// This generator only has output for raw kinds.
func RawKindJenny(gokindsdir string, cfg *RawKindGeneratorConfig) OneToOne {
if cfg == nil {
cfg = new(RawKindGeneratorConfig)
}
if cfg.GenDirName == nil {
cfg.GenDirName = func(decl *DeclForGen) string {
return decl.Properties.Common().MachineName
}
}
return &genRawKind{
gokindsdir: gokindsdir,
cfg: cfg,
}
}
type genRawKind struct {
gokindsdir string
cfg *RawKindGeneratorConfig
}
type RawKindGeneratorConfig struct {
// GenDirName returns the name of the directory in which the file should be
// generated. Defaults to DeclForGen.Lineage().Name() if nil.
GenDirName func(*DeclForGen) string
}
func (gen *genRawKind) JennyName() string {
return "RawKindJenny"
}
func (gen *genRawKind) Generate(decl *DeclForGen) (*codejen.File, error) {
if !decl.IsRaw() {
return nil, nil
}
path := filepath.Join(gen.gokindsdir, gen.cfg.GenDirName(decl), decl.Properties.Common().MachineName+"_kind_gen.go")
buf := new(bytes.Buffer)
if err := tmpls.Lookup("kind_raw.tmpl").Execute(buf, decl); err != nil {
return nil, fmt.Errorf("failed executing kind_raw template for %s: %w", path, err)
}
b, err := postprocessGoFile(genGoFile{
path: path,
in: buf.Bytes(),
})
if err != nil {
return nil, err
}
return codejen.NewFile(path, b, gen), nil
}

@ -42,10 +42,6 @@ func (gen *genTSVeneerIndex) JennyName() string {
func (gen *genTSVeneerIndex) Generate(decls ...*DeclForGen) (*codejen.File, error) { func (gen *genTSVeneerIndex) Generate(decls ...*DeclForGen) (*codejen.File, error) {
tsf := new(ast.File) tsf := new(ast.File)
for _, decl := range decls { for _, decl := range decls {
if decl.IsRaw() {
continue
}
sch := decl.Lineage().Latest() sch := decl.Lineage().Latest()
f, err := typescript.GenerateTypes(sch, &typescript.TypeConfig{ f, err := typescript.GenerateTypes(sch, &typescript.TypeConfig{
RootName: decl.Properties.Common().Name, RootName: decl.Properties.Common().Name,

@ -32,9 +32,6 @@ func (j *latestj) JennyName() string {
} }
func (j *latestj) Generate(decl *DeclForGen) (*codejen.File, error) { func (j *latestj) Generate(decl *DeclForGen) (*codejen.File, error) {
if decl.IsRaw() {
return nil, nil
}
comm := decl.Properties.Common() comm := decl.Properties.Common()
sfg := SchemaForGen{ sfg := SchemaForGen{
Name: comm.Name, Name: comm.Name,

@ -38,7 +38,7 @@ type (
} }
tvars_kind_registry struct { tvars_kind_registry struct {
// Header tvars_autogen_header // Header tvars_autogen_header
NumRaw, NumStructured int NumStructured int
PackageName string PackageName string
KindPackagePrefix string KindPackagePrefix string
Kinds []*DeclForGen Kinds []*DeclForGen

@ -10,22 +10,22 @@ import (
// directory containing the .cue files in which this kind is declared. Necessary // directory containing the .cue files in which this kind is declared. Necessary
// for runtime errors related to the declaration and/or lineage to provide // for runtime errors related to the declaration and/or lineage to provide
// a real path to the correct .cue file. // a real path to the correct .cue file.
const rootrel string = "kinds/structured/{{ .Properties.MachineName }}" const rootrel string = "kinds/{{ .Properties.MachineName }}"
// TODO standard generated docs // TODO standard generated docs
type Kind struct { type Kind struct {
lin thema.ConvergentLineage[*{{ .Properties.Name }}] lin thema.ConvergentLineage[*{{ .Properties.Name }}]
jcodec vmux.Codec jcodec vmux.Codec
valmux vmux.ValueMux[*{{ .Properties.Name }}] valmux vmux.ValueMux[*{{ .Properties.Name }}]
decl kindsys.Decl[kindsys.CoreStructuredProperties] decl kindsys.Decl[kindsys.CoreProperties]
} }
// type guard // type guard
var _ kindsys.Structured = &Kind{} var _ kindsys.Core = &Kind{}
// TODO standard generated docs // TODO standard generated docs
func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) { func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) {
decl, err := kindsys.LoadCoreKind[kindsys.CoreStructuredProperties](rootrel, rt.Context(), nil) decl, err := kindsys.LoadCoreKind(rootrel, rt.Context(), nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -91,12 +91,12 @@ func (k *Kind) Maturity() kindsys.Maturity {
// Decl returns the [kindsys.Decl] containing both CUE and Go representations of the // Decl returns the [kindsys.Decl] containing both CUE and Go representations of the
// {{ .Properties.MachineName }} declaration in .cue files. // {{ .Properties.MachineName }} declaration in .cue files.
func (k *Kind) Decl() *kindsys.Decl[kindsys.CoreStructuredProperties] { func (k *Kind) Decl() *kindsys.Decl[kindsys.CoreProperties] {
d := k.decl d := k.decl
return &d return &d
} }
// Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreStructuredProperties], // Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreProperties],
// representing the static properties declared in the {{ .Properties.MachineName }} kind. // representing the static properties declared in the {{ .Properties.MachineName }} kind.
// //
// This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface]. // This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface].

@ -1,57 +0,0 @@
package {{ .Properties.MachineName }}
import (
"github.com/grafana/grafana/pkg/kindsys"
"github.com/grafana/thema"
"github.com/grafana/thema/vmux"
)
// TODO standard generated docs
type Kind struct {
decl kindsys.Decl[kindsys.RawProperties]
}
// type guard
var _ kindsys.Raw = &Kind{}
// TODO standard generated docs
func NewKind() (*Kind, error) {
decl, err := kindsys.LoadCoreKind[kindsys.RawProperties]("kinds/raw/{{ .Properties.MachineName }}", nil, nil)
if err != nil {
return nil, err
}
return &Kind{
decl: *decl,
}, nil
}
// TODO standard generated docs
func (k *Kind) Name() string {
return "{{ .Properties.Name }}"
}
// TODO standard generated docs
func (k *Kind) MachineName() string {
return "{{ .Properties.MachineName }}"
}
// TODO standard generated docs
func (k *Kind) Maturity() kindsys.Maturity {
return k.decl.Properties.Maturity
}
// Decl returns the [kindsys.Decl] containing both CUE and Go representations of the
// {{ .Properties.MachineName }} declaration in .cue files.
func (k *Kind) Decl() *kindsys.Decl[kindsys.RawProperties] {
d := k.decl
return &d
}
// Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.RawProperties],
// representing the static properties declared in the {{ .Properties.MachineName }} kind.
//
// This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface].
func (k *Kind) Props() kindsys.SomeKindProperties {
return k.decl.Properties
}

@ -22,8 +22,7 @@ import (
// Prefer All*() methods when performing operations generically across all kinds. // Prefer All*() methods when performing operations generically across all kinds.
// For example, a validation HTTP middleware for any kind-schematized object type. // For example, a validation HTTP middleware for any kind-schematized object type.
type Base struct { type Base struct {
all []kindsys.Interface all []kindsys.Core
numRaw, numStructured int
{{- range .Kinds }} {{- range .Kinds }}
{{ .Properties.MachineName }} *{{ .Properties.MachineName }}.Kind{{end}} {{ .Properties.MachineName }} *{{ .Properties.MachineName }}.Kind{{end}}
} }
@ -31,7 +30,7 @@ type Base struct {
// type guards // type guards
var ( var (
{{- range .Kinds }} {{- range .Kinds }}
_ kindsys.{{ if .IsRaw }}Raw{{ else }}Structured{{ end }} = &{{ .Properties.MachineName }}.Kind{}{{end}} _ kindsys.Core = &{{ .Properties.MachineName }}.Kind{}{{end}}
) )
{{range .Kinds }} {{range .Kinds }}
@ -43,13 +42,10 @@ func (b *Base) {{ .Properties.Name }}() *{{ .Properties.MachineName }}.Kind {
func doNewBase(rt *thema.Runtime) *Base { func doNewBase(rt *thema.Runtime) *Base {
var err error var err error
reg := &Base{ reg := &Base{}
numRaw: {{ .NumRaw }},
numStructured: {{ .NumStructured }},
}
{{range .Kinds }} {{range .Kinds }}
reg.{{ .Properties.MachineName }}, err = {{ .Properties.MachineName }}.NewKind({{ if .IsCoreStructured }}rt{{ end }}) reg.{{ .Properties.MachineName }}, err = {{ .Properties.MachineName }}.NewKind(rt)
if err != nil { if err != nil {
panic(fmt.Sprintf("error while initializing the {{ .Properties.MachineName }} Kind: %s", err)) panic(fmt.Sprintf("error while initializing the {{ .Properties.MachineName }} Kind: %s", err))
} }

@ -3,7 +3,7 @@
// Generated by: // Generated by:
// kinds/gen.go // kinds/gen.go
// Using jennies: // Using jennies:
// CoreStructuredKindJenny // CoreKindJenny
// //
// Run 'make gen-cue' from repository root to regenerate. // Run 'make gen-cue' from repository root to regenerate.
@ -19,22 +19,22 @@ import (
// directory containing the .cue files in which this kind is declared. Necessary // directory containing the .cue files in which this kind is declared. Necessary
// for runtime errors related to the declaration and/or lineage to provide // for runtime errors related to the declaration and/or lineage to provide
// a real path to the correct .cue file. // a real path to the correct .cue file.
const rootrel string = "kinds/structured/dashboard" const rootrel string = "kinds/dashboard"
// TODO standard generated docs // TODO standard generated docs
type Kind struct { type Kind struct {
lin thema.ConvergentLineage[*Dashboard] lin thema.ConvergentLineage[*Dashboard]
jcodec vmux.Codec jcodec vmux.Codec
valmux vmux.ValueMux[*Dashboard] valmux vmux.ValueMux[*Dashboard]
decl kindsys.Decl[kindsys.CoreStructuredProperties] decl kindsys.Decl[kindsys.CoreProperties]
} }
// type guard // type guard
var _ kindsys.Structured = &Kind{} var _ kindsys.Core = &Kind{}
// TODO standard generated docs // TODO standard generated docs
func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) { func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) {
decl, err := kindsys.LoadCoreKind[kindsys.CoreStructuredProperties](rootrel, rt.Context(), nil) decl, err := kindsys.LoadCoreKind(rootrel, rt.Context(), nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -100,12 +100,12 @@ func (k *Kind) Maturity() kindsys.Maturity {
// Decl returns the [kindsys.Decl] containing both CUE and Go representations of the // Decl returns the [kindsys.Decl] containing both CUE and Go representations of the
// dashboard declaration in .cue files. // dashboard declaration in .cue files.
func (k *Kind) Decl() *kindsys.Decl[kindsys.CoreStructuredProperties] { func (k *Kind) Decl() *kindsys.Decl[kindsys.CoreProperties] {
d := k.decl d := k.decl
return &d return &d
} }
// Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreStructuredProperties], // Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreProperties],
// representing the static properties declared in the dashboard kind. // representing the static properties declared in the dashboard kind.
// //
// This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface]. // This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface].

@ -3,7 +3,7 @@
// Generated by: // Generated by:
// kinds/gen.go // kinds/gen.go
// Using jennies: // Using jennies:
// CoreStructuredKindJenny // CoreKindJenny
// //
// Run 'make gen-cue' from repository root to regenerate. // Run 'make gen-cue' from repository root to regenerate.
@ -19,22 +19,22 @@ import (
// directory containing the .cue files in which this kind is declared. Necessary // directory containing the .cue files in which this kind is declared. Necessary
// for runtime errors related to the declaration and/or lineage to provide // for runtime errors related to the declaration and/or lineage to provide
// a real path to the correct .cue file. // a real path to the correct .cue file.
const rootrel string = "kinds/structured/playlist" const rootrel string = "kinds/playlist"
// TODO standard generated docs // TODO standard generated docs
type Kind struct { type Kind struct {
lin thema.ConvergentLineage[*Playlist] lin thema.ConvergentLineage[*Playlist]
jcodec vmux.Codec jcodec vmux.Codec
valmux vmux.ValueMux[*Playlist] valmux vmux.ValueMux[*Playlist]
decl kindsys.Decl[kindsys.CoreStructuredProperties] decl kindsys.Decl[kindsys.CoreProperties]
} }
// type guard // type guard
var _ kindsys.Structured = &Kind{} var _ kindsys.Core = &Kind{}
// TODO standard generated docs // TODO standard generated docs
func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) { func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) {
decl, err := kindsys.LoadCoreKind[kindsys.CoreStructuredProperties](rootrel, rt.Context(), nil) decl, err := kindsys.LoadCoreKind(rootrel, rt.Context(), nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -100,12 +100,12 @@ func (k *Kind) Maturity() kindsys.Maturity {
// Decl returns the [kindsys.Decl] containing both CUE and Go representations of the // Decl returns the [kindsys.Decl] containing both CUE and Go representations of the
// playlist declaration in .cue files. // playlist declaration in .cue files.
func (k *Kind) Decl() *kindsys.Decl[kindsys.CoreStructuredProperties] { func (k *Kind) Decl() *kindsys.Decl[kindsys.CoreProperties] {
d := k.decl d := k.decl
return &d return &d
} }
// Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreStructuredProperties], // Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreProperties],
// representing the static properties declared in the playlist kind. // representing the static properties declared in the playlist kind.
// //
// This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface]. // This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface].

@ -1,64 +0,0 @@
// THIS FILE IS GENERATED. EDITING IS FUTILE.
//
// Generated by:
// kinds/gen.go
// Using jennies:
// RawKindJenny
//
// Run 'make gen-cue' from repository root to regenerate.
package svg
import (
"github.com/grafana/grafana/pkg/kindsys"
)
// TODO standard generated docs
type Kind struct {
decl kindsys.Decl[kindsys.RawProperties]
}
// type guard
var _ kindsys.Raw = &Kind{}
// TODO standard generated docs
func NewKind() (*Kind, error) {
decl, err := kindsys.LoadCoreKind[kindsys.RawProperties]("kinds/raw/svg", nil, nil)
if err != nil {
return nil, err
}
return &Kind{
decl: *decl,
}, nil
}
// TODO standard generated docs
func (k *Kind) Name() string {
return "SVG"
}
// TODO standard generated docs
func (k *Kind) MachineName() string {
return "svg"
}
// TODO standard generated docs
func (k *Kind) Maturity() kindsys.Maturity {
return k.decl.Properties.Maturity
}
// Decl returns the [kindsys.Decl] containing both CUE and Go representations of the
// svg declaration in .cue files.
func (k *Kind) Decl() *kindsys.Decl[kindsys.RawProperties] {
d := k.decl
return &d
}
// Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.RawProperties],
// representing the static properties declared in the svg kind.
//
// This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface].
func (k *Kind) Props() kindsys.SomeKindProperties {
return k.decl.Properties
}

@ -3,7 +3,7 @@
// Generated by: // Generated by:
// kinds/gen.go // kinds/gen.go
// Using jennies: // Using jennies:
// CoreStructuredKindJenny // CoreKindJenny
// //
// Run 'make gen-cue' from repository root to regenerate. // Run 'make gen-cue' from repository root to regenerate.
@ -19,22 +19,22 @@ import (
// directory containing the .cue files in which this kind is declared. Necessary // directory containing the .cue files in which this kind is declared. Necessary
// for runtime errors related to the declaration and/or lineage to provide // for runtime errors related to the declaration and/or lineage to provide
// a real path to the correct .cue file. // a real path to the correct .cue file.
const rootrel string = "kinds/structured/team" const rootrel string = "kinds/team"
// TODO standard generated docs // TODO standard generated docs
type Kind struct { type Kind struct {
lin thema.ConvergentLineage[*Team] lin thema.ConvergentLineage[*Team]
jcodec vmux.Codec jcodec vmux.Codec
valmux vmux.ValueMux[*Team] valmux vmux.ValueMux[*Team]
decl kindsys.Decl[kindsys.CoreStructuredProperties] decl kindsys.Decl[kindsys.CoreProperties]
} }
// type guard // type guard
var _ kindsys.Structured = &Kind{} var _ kindsys.Core = &Kind{}
// TODO standard generated docs // TODO standard generated docs
func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) { func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) {
decl, err := kindsys.LoadCoreKind[kindsys.CoreStructuredProperties](rootrel, rt.Context(), nil) decl, err := kindsys.LoadCoreKind(rootrel, rt.Context(), nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -100,12 +100,12 @@ func (k *Kind) Maturity() kindsys.Maturity {
// Decl returns the [kindsys.Decl] containing both CUE and Go representations of the // Decl returns the [kindsys.Decl] containing both CUE and Go representations of the
// team declaration in .cue files. // team declaration in .cue files.
func (k *Kind) Decl() *kindsys.Decl[kindsys.CoreStructuredProperties] { func (k *Kind) Decl() *kindsys.Decl[kindsys.CoreProperties] {
d := k.decl d := k.decl
return &d return &d
} }
// Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreStructuredProperties], // Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreProperties],
// representing the static properties declared in the team kind. // representing the static properties declared in the team kind.
// //
// This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface]. // This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface].

@ -13,8 +13,7 @@ This document is the guide to extending kindsys. But first, we have to identify
* **Code generators** - written using the `github.com/grafana/codejen` framework, which applies the [single responsibility principle](https://en.wikipedia.org/wiki/Single-responsibility_principle) to code generation, allowing us to compose modular code generators. Each jenny - a modular generator with a single responsibility - is declared as a `pkg/codegen/jenny_*.go` file. * **Code generators** - written using the `github.com/grafana/codejen` framework, which applies the [single responsibility principle](https://en.wikipedia.org/wiki/Single-responsibility_principle) to code generation, allowing us to compose modular code generators. Each jenny - a modular generator with a single responsibility - is declared as a `pkg/codegen/jenny_*.go` file.
* **Registries** - generated lists of all or a well-defined subset of kinds that can be used in code. `pkg/registries/corekind` is a registry of all core `pkg/kindsys.Interface` implementations; `packages/grafana-schema/src/index.gen.ts` is a registry of all the TypeScript types generated from the current versions of each kind's schema. * **Registries** - generated lists of all or a well-defined subset of kinds that can be used in code. `pkg/registries/corekind` is a registry of all core `pkg/kindsys.Interface` implementations; `packages/grafana-schema/src/index.gen.ts` is a registry of all the TypeScript types generated from the current versions of each kind's schema.
* **Kind declarations** - the declarations of individual kinds. By kind category: * **Kind declarations** - the declarations of individual kinds. By kind category:
* **Core Structured** - each child directory of `kinds/structured`. * **Core** - each child directory of `kinds`.
* **Raw** - each child directory of `kinds/raw`.
* **Composable** - In Grafana core, `public/app/plugins/*/*/models.cue` files. * **Composable** - In Grafana core, `public/app/plugins/*/*/models.cue` files.
* **Custom** - No examples in Grafana core. See [operator-app-sdk](https://github.com/grafana/operator-app-sdk) (TODO that repo is private; make it public, or point to public examples). * **Custom** - No examples in Grafana core. See [operator-app-sdk](https://github.com/grafana/operator-app-sdk) (TODO that repo is private; make it public, or point to public examples).

@ -67,22 +67,14 @@ type Interface interface {
Maturity() Maturity // TODO unclear if we want maturity for raw kinds Maturity() Maturity // TODO unclear if we want maturity for raw kinds
} }
// TODO docs type Core interface {
type Raw interface {
Interface
// TODO docs
Decl() *Decl[RawProperties]
}
type Structured interface {
Interface Interface
// TODO docs // TODO docs
Lineage() thema.Lineage Lineage() thema.Lineage
// TODO docs // TODO docs
Decl() *Decl[CoreStructuredProperties] // TODO figure out how to reconcile this interface with CustomStructuredProperties Decl() *Decl[CoreProperties] // TODO figure out how to reconcile this interface with CustomProperties
} }
// type Composable interface { // type Composable interface {
@ -92,5 +84,5 @@ type Structured interface {
// Lineage() thema.Lineage // Lineage() thema.Lineage
// //
// // TODO docs // // TODO docs
// Properties() CoreStructuredProperties // TODO figure out how to reconcile this interface with CustomStructuredProperties // Properties() CoreProperties // TODO figure out how to reconcile this interface with CustomProperties
// } // }

@ -1,15 +1,16 @@
package kindsys package kindsys
// CustomStructured specifies the Kind category for plugin-defined arbitrary types. // Custom specifies the kind category for plugin-defined arbitrary types.
// Custom kinds have the same purpose as CoreStructured kinds, differing only in // Custom kinds have the same purpose as Core kinds, differing only in
// that they are declared by external plugins rather than in Grafana core. As such, // that they are declared by external plugins rather than in Grafana core. As such,
// this specification is kept closely aligned with the CoreStructured kind. // this specification is kept closely aligned with the Core kind.
// //
// Grafana provides Kubernetes apiserver-shaped APIs for interacting with custom kinds - // Grafana provides Kubernetes apiserver-shaped HTTP APIs for interacting with custom
// The same API patterns (and clients) used to interact with CustomResources. // kinds - the same API patterns (and clients) used to interact with k8s CustomResources.
#CustomStructured: { #Custom: S={
#Structured _sharedKind
lineage: { name: S.machineName }
lineageIsGroup: false lineageIsGroup: false
... ...
} }

@ -6,25 +6,23 @@ import (
"github.com/grafana/thema" "github.com/grafana/thema"
) )
// A Kind specifies a type of Grafana resource. // A Kind is a specification for a type of object that Grafana knows
// how to work with. Each kind definition contains a schema, and some
// declarative metadata and constraints.
// //
// An instance of a Kind is called an entity. An entity is a sequence of bytes - // An instance of a kind is called a resource. Resources are a sequence of
// for example, a JSON file or HTTP request body - that conforms to the // bytes - for example, a JSON file or HTTP request body - that conforms
// constraints defined in a Kind, and enforced by Grafana's entity system. // to the schemas and other constraints defined in a Kind.
// //
// Once Grafana has determined a given byte sequence to be an // Once Grafana has determined a given byte sequence to be an
// instance of a known Kind, kind-specific behaviors can be applied, // instance of a known Kind, kind-specific behaviors can be applied,
// requests can be routed, events can be triggered, etc. // requests can be routed, events can be triggered, etc.
// //
// Classes and objects in most programming languages are analogous: // Grafana's kinds are similar to Kubernetes CustomResourceDefinitions.
// - #Kind is like a `class` keyword // Grafana provides a standard mechanism for representing its kinds as CRDs.
// - Each declaration of #Kind is like a class declaration
// - Byte sequences are like arguments to the class constructor
// - Entities are like objects - what's returned from the constructor
// //
// There are four categories of kinds: Raw, Composable, CoreStructured, // There are three categories of kinds: Core, Custom, and Composable.
// and CustomStructured. #Kind: #Composable | #Core | #Custom
#Kind: #Raw | #Composable | #CoreStructured | #CustomStructured
// properties shared between all kind categories. // properties shared between all kind categories.
_sharedKind: { _sharedKind: {
@ -66,69 +64,37 @@ _sharedKind: {
// https://github.com/grafana/thema/issues/62 // https://github.com/grafana/thema/issues/62
lineageIsGroup: bool lineageIsGroup: bool
// lineage is the Thema lineage containing all the schemas that have existed for this kind.
lineage: thema.#Lineage
// currentVersion is computed to be the syntactic version number of the latest
// schema in lineage.
currentVersion: thema.#SyntacticVersion & (thema.#LatestVersion & {lin: lineage}).out
maturity: #Maturity maturity: #Maturity
// The kind system itself is not mature enough yet for any single // The kind system itself is not mature enough yet for any single
// kind to advance beyond "experimental" // kind to advance beyond "experimental"
// TODO allow more maturity stages once system is ready https://github.com/orgs/grafana/projects/133/views/8 // TODO allow more maturity stages once system is ready https://github.com/orgs/grafana/projects/133/views/8
maturity: *"merged" | "experimental" maturity: *"merged" | "experimental"
// form indicates whether the kind has a schema ("structured") or not ("raw")
form: "structured" | "raw"
} }
// Maturity indicates the how far a given kind declaration is in its initial // Maturity indicates the how far a given kind declaration is in its initial
// journey. Mature kinds still evolve, but with guarantees about compatibility. // journey. Mature kinds still evolve, but with guarantees about compatibility.
#Maturity: "merged" | "experimental" | "stable" | "mature" #Maturity: "merged" | "experimental" | "stable" | "mature"
// Structured encompasses all three of the structured kind categories, in which // Core specifies the kind category for core-defined arbitrary types.
// a schema specifies validity rules for the byte sequence. These represent all // Familiar types and functional resources in Grafana, such as dashboards and
// the conventional types and functional resources in Grafana, such as // and datasources, are represented as core kinds.
// dashboards and datasources. #Core: S=close({
//
// Structured kinds may be defined either by Grafana itself (#CoreStructured),
// or by plugins (#CustomStructured). Plugin-defined kinds have a slightly
// reduced set of capabilities, due to the constraints imposed by them being run
// in separate processes, and the risks arising from executing code from
// potentially untrusted third parties.
#Structured: S={
_sharedKind _sharedKind
form: "structured"
// lineage is the Thema lineage containing all the schemas that have existed for this kind.
// It is required that lineage.name is the same as the [machineName].
lineage: thema.#Lineage & { name: S.machineName }
currentVersion: thema.#SyntacticVersion & (thema.#LatestVersion & {lin: lineage}).out
}
// Raw is a category of Kind that specifies handling for a raw file,
// like an image, or an svg or parquet file. Grafana mostly acts as asset storage for raw
// kinds: the byte sequence is a black box to Grafana, and type is determined
// through metadata such as file extension.
#Raw: {
_sharedKind
form: "raw"
// TODO docs
extensions?: [...string]
lineage: { name: S.machineName }
lineageIsGroup: false lineageIsGroup: false
})
// known TODOs // Composable is a category of kind that provides schema elements for
// - sanitize function // composition into Core and Custom kinds. Grafana plugins
// - get summary
}
// TODO
#CoreStructured: {
#Structured
lineageIsGroup: false
}
// Composable is a category of structured kind that provides schema elements for
// composition into CoreStructured and CustomStructured kinds. Grafana plugins
// provide composable kinds; for example, a datasource plugin provides one to // provide composable kinds; for example, a datasource plugin provides one to
// describe the structure of its queries, which is then composed into dashboards // describe the structure of its queries, which is then composed into dashboards
// and alerting rules. // and alerting rules.
@ -138,7 +104,6 @@ _sharedKind: {
// that ComposableKind. // that ComposableKind.
#Composable: S={ #Composable: S={
_sharedKind _sharedKind
form: "structured"
// TODO docs // TODO docs
// TODO unify this with the existing slots decls in pkg/framework/coremodel // TODO unify this with the existing slots decls in pkg/framework/coremodel

@ -12,49 +12,33 @@ type CommonProperties struct {
Maturity Maturity `json:"maturity"` Maturity Maturity `json:"maturity"`
} }
// RawProperties represents the static properties in a #Raw kind declaration that are // CoreProperties represents the static properties in the declaration of a
// trivially representable with basic Go types. // #Core kind that are representable with basic Go types. This
//
// When a .cue #Raw declaration is loaded through the standard [LoadCoreKind],
// func, it is fully validated and populated according to all rules specified
// in CUE for #Raw kinds.
type RawProperties struct {
CommonProperties
Extensions []string `json:"extensions"`
}
func (m RawProperties) _private() {}
func (m RawProperties) Common() CommonProperties {
return m.CommonProperties
}
// CoreStructuredProperties represents the static properties in the declaration of a
// #CoreStructured kind that are representable with basic Go types. This
// excludes Thema schemas. // excludes Thema schemas.
// //
// When a .cue #CoreStructured declaration is loaded through the standard [LoadCoreKind], // When a .cue #Core declaration is loaded through the standard [LoadCoreKind],
// func, it is fully validated and populated according to all rules specified // func, it is fully validated and populated according to all rules specified
// in CUE for #CoreStructured kinds. // in CUE for #Core kinds.
type CoreStructuredProperties struct { type CoreProperties struct {
CommonProperties CommonProperties
CurrentVersion thema.SyntacticVersion `json:"currentVersion"` CurrentVersion thema.SyntacticVersion `json:"currentVersion"`
} }
func (m CoreStructuredProperties) _private() {} func (m CoreProperties) _private() {}
func (m CoreStructuredProperties) Common() CommonProperties { func (m CoreProperties) Common() CommonProperties {
return m.CommonProperties return m.CommonProperties
} }
// CustomStructuredProperties represents the static properties in the declaration of a // CustomProperties represents the static properties in the declaration of a
// #CustomStructured kind that are representable with basic Go types. This // #Custom kind that are representable with basic Go types. This
// excludes Thema schemas. // excludes Thema schemas.
type CustomStructuredProperties struct { type CustomProperties struct {
CommonProperties CommonProperties
CurrentVersion thema.SyntacticVersion `json:"currentVersion"` CurrentVersion thema.SyntacticVersion `json:"currentVersion"`
} }
func (m CustomStructuredProperties) _private() {} func (m CustomProperties) _private() {}
func (m CustomStructuredProperties) Common() CommonProperties { func (m CustomProperties) Common() CommonProperties {
return m.CommonProperties return m.CommonProperties
} }
@ -72,8 +56,8 @@ func (m ComposableProperties) Common() CommonProperties {
} }
// SomeKindProperties is an interface type to abstract over the different kind // SomeKindProperties is an interface type to abstract over the different kind
// property struct types: [RawProperties], [CoreStructuredProperties], // property struct types: [CoreProperties], [CustomProperties],
// [CustomStructuredProperties], [ComposableProperties]. // [ComposableProperties].
// //
// It is the traditional interface counterpart to the generic type constraint // It is the traditional interface counterpart to the generic type constraint
// KindProperties. // KindProperties.
@ -85,5 +69,5 @@ type SomeKindProperties interface {
// KindProperties is a type parameter that comprises the base possible set of // KindProperties is a type parameter that comprises the base possible set of
// kind metadata configurations. // kind metadata configurations.
type KindProperties interface { type KindProperties interface {
RawProperties | CoreStructuredProperties | CustomStructuredProperties | ComposableProperties CoreProperties | CustomProperties | ComposableProperties
} }

@ -12,19 +12,10 @@ import (
"github.com/grafana/thema" "github.com/grafana/thema"
) )
// DeclParentPath is the path, relative to the repository root, where // CoreDeclParentPath is the path, relative to the repository root, where
// each child directory is expected to contain directories with .cue files,
// declaring one kind.
var DeclParentPath = "kinds"
// CoreStructuredDeclParentPath is the path, relative to the repository root, where
// each child directory is expected to contain .cue files declaring one // each child directory is expected to contain .cue files declaring one
// CoreStructured kind. // Core kind.
var CoreStructuredDeclParentPath = filepath.Join(DeclParentPath, "structured") var CoreDeclParentPath = "kinds"
// RawDeclParentPath is the path, relative to the repository root, where each child
// directory is expected to contain .cue files declaring one Raw kind.
var RawDeclParentPath = filepath.Join(DeclParentPath, "raw")
// GoCoreKindParentPath is the path, relative to the repository root, to the directory // GoCoreKindParentPath is the path, relative to the repository root, to the directory
// containing one directory per kind, full of generated Go kind output: types and bindings. // containing one directory per kind, full of generated Go kind output: types and bindings.
@ -99,12 +90,10 @@ func ToKindMeta[T KindProperties](v cue.Value) (T, error) {
anyprops := any(*props).(SomeKindProperties) anyprops := any(*props).(SomeKindProperties)
switch anyprops.(type) { switch anyprops.(type) {
case RawProperties: case CoreProperties:
kdef = fw.LookupPath(cue.MakePath(cue.Def("Raw"))) kdef = fw.LookupPath(cue.MakePath(cue.Def("Core")))
case CoreStructuredProperties: case CustomProperties:
kdef = fw.LookupPath(cue.MakePath(cue.Def("CoreStructured"))) kdef = fw.LookupPath(cue.MakePath(cue.Def("Custom")))
case CustomStructuredProperties:
kdef = fw.LookupPath(cue.MakePath(cue.Def("CustomStructured")))
case ComposableProperties: case ComposableProperties:
kdef = fw.LookupPath(cue.MakePath(cue.Def("Composable"))) kdef = fw.LookupPath(cue.MakePath(cue.Def("Composable")))
default: default:
@ -136,8 +125,7 @@ type SomeDecl struct {
Properties SomeKindProperties Properties SomeKindProperties
} }
// BindKindLineage binds the lineage for the kind declaration. nil, nil is returned // BindKindLineage binds the lineage for the kind declaration.
// for raw kinds.
// //
// For kinds with a corresponding Go type, it is left to the caller to associate // For kinds with a corresponding Go type, it is left to the caller to associate
// that Go type with the lineage returned from this function by a call to [thema.BindType]. // that Go type with the lineage returned from this function by a call to [thema.BindType].
@ -146,30 +134,22 @@ func (decl *SomeDecl) BindKindLineage(rt *thema.Runtime, opts ...thema.BindOptio
rt = cuectx.GrafanaThemaRuntime() rt = cuectx.GrafanaThemaRuntime()
} }
switch decl.Properties.(type) { switch decl.Properties.(type) {
case RawProperties: case CoreProperties, CustomProperties, ComposableProperties:
return nil, nil
case CoreStructuredProperties, CustomStructuredProperties, ComposableProperties:
return thema.BindLineage(decl.V.LookupPath(cue.MakePath(cue.Str("lineage"))), rt, opts...) return thema.BindLineage(decl.V.LookupPath(cue.MakePath(cue.Str("lineage"))), rt, opts...)
default: default:
panic("unreachable") panic("unreachable")
} }
} }
// IsRaw indicates whether the represented kind is a raw kind. // IsCore indicates whether the represented kind is a core kind.
func (decl *SomeDecl) IsRaw() bool { func (decl *SomeDecl) IsCore() bool {
_, is := decl.Properties.(RawProperties) _, is := decl.Properties.(CoreProperties)
return is
}
// IsCoreStructured indicates whether the represented kind is a core structured kind.
func (decl *SomeDecl) IsCoreStructured() bool {
_, is := decl.Properties.(CoreStructuredProperties)
return is return is
} }
// IsCustomStructured indicates whether the represented kind is a custom structured kind. // IsCustom indicates whether the represented kind is a custom kind.
func (decl *SomeDecl) IsCustomStructured() bool { func (decl *SomeDecl) IsCustom() bool {
_, is := decl.Properties.(CustomStructuredProperties) _, is := decl.Properties.(CustomProperties)
return is return is
} }
@ -204,7 +184,7 @@ func (decl *Decl[T]) Some() *SomeDecl {
// //
// declpath is the path to the directory containing the core kind declaration, // declpath is the path to the directory containing the core kind declaration,
// relative to the grafana/grafana root. For example, dashboards are in // relative to the grafana/grafana root. For example, dashboards are in
// "kinds/structured/dashboard". // "kinds/dashboard".
// //
// The .cue file bytes containing the core kind declaration will be retrieved // The .cue file bytes containing the core kind declaration will be retrieved
// from the central embedded FS, [grafana.CueSchemaFS]. If desired (e.g. for // from the central embedded FS, [grafana.CueSchemaFS]. If desired (e.g. for
@ -215,15 +195,15 @@ func (decl *Decl[T]) Some() *SomeDecl {
// This is a low-level function, primarily intended for use in code generation. // This is a low-level function, primarily intended for use in code generation.
// For representations of core kinds that are useful in Go programs at runtime, // For representations of core kinds that are useful in Go programs at runtime,
// see ["github.com/grafana/grafana/pkg/registry/corekind"]. // see ["github.com/grafana/grafana/pkg/registry/corekind"].
func LoadCoreKind[T RawProperties | CoreStructuredProperties](declpath string, ctx *cue.Context, overlay fs.FS) (*Decl[T], error) { func LoadCoreKind(declpath string, ctx *cue.Context, overlay fs.FS) (*Decl[CoreProperties], error) {
vk, err := cuectx.BuildGrafanaInstance(ctx, declpath, "kind", overlay) vk, err := cuectx.BuildGrafanaInstance(ctx, declpath, "kind", overlay)
if err != nil { if err != nil {
return nil, err return nil, err
} }
decl := &Decl[T]{ decl := &Decl[CoreProperties]{
V: vk, V: vk,
} }
decl.Properties, err = ToKindMeta[T](vk) decl.Properties, err = ToKindMeta[CoreProperties](vk)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -54,15 +54,13 @@ var plannedCoreKinds = []string{
} }
type KindStateReport struct { type KindStateReport struct {
Core []kindsys.CoreStructuredProperties `json:"core"` Core []kindsys.CoreProperties `json:"core"`
Raw []kindsys.RawProperties `json:"raw"`
Composable []kindsys.ComposableProperties `json:"composable"` Composable []kindsys.ComposableProperties `json:"composable"`
} }
func emptyKindStateReport() KindStateReport { func emptyKindStateReport() KindStateReport {
return KindStateReport{ return KindStateReport{
Core: make([]kindsys.CoreStructuredProperties, 0), Core: make([]kindsys.CoreProperties, 0),
Raw: make([]kindsys.RawProperties, 0),
Composable: make([]kindsys.ComposableProperties, 0), Composable: make([]kindsys.ComposableProperties, 0),
} }
} }
@ -75,10 +73,8 @@ func buildKindStateReport() KindStateReport {
for _, k := range b.All() { for _, k := range b.All() {
seen[k.Props().Common().Name] = true seen[k.Props().Common().Name] = true
switch props := k.Props().(type) { switch props := k.Props().(type) {
case kindsys.CoreStructuredProperties: case kindsys.CoreProperties:
r.Core = append(r.Core, props) r.Core = append(r.Core, props)
case kindsys.RawProperties:
r.Raw = append(r.Raw, props)
} }
} }
@ -86,7 +82,7 @@ func buildKindStateReport() KindStateReport {
if seen[kn] { if seen[kn] {
continue continue
} }
r.Core = append(r.Core, kindsys.CoreStructuredProperties{ r.Core = append(r.Core, kindsys.CoreProperties{
CommonProperties: kindsys.CommonProperties{ CommonProperties: kindsys.CommonProperties{
Name: kn, Name: kn,
PluralName: kn + "s", PluralName: kn + "s",

@ -133,19 +133,6 @@
] ]
} }
], ],
"raw": [
{
"name": "SVG",
"pluralName": "SVGs",
"machineName": "svg",
"pluralMachineName": "svgs",
"lineageIsGroup": false,
"maturity": "merged",
"extensions": [
"svg"
]
}
],
"composable": [ "composable": [
{ {
"name": "AlertGroups-Panel", "name": "AlertGroups-Panel",

@ -2,7 +2,7 @@ package grafanaplugin
import ( import (
"github.com/grafana/thema" "github.com/grafana/thema"
"github.com/grafana/grafana/kinds/structured/dashboard:kind" "github.com/grafana/grafana/kinds/dashboard:kind"
) )
_dummy: coremodel.slots _dummy: coremodel.slots

@ -37,40 +37,11 @@ func NewBase(rt *thema.Runtime) *Base {
return doNewBase(rt) return doNewBase(rt)
} }
// All returns a slice of the [kindsys.Interface] instances corresponding to all // All returns a slice of [kindsys.Core] containing all core Grafana kinds.
// core raw and structured kinds.
// //
// The returned slice is sorted lexicographically by kind machine name. // The returned slice is sorted lexicographically by kind machine name.
func (b *Base) All() []kindsys.Interface { func (b *Base) All() []kindsys.Core {
ret := make([]kindsys.Interface, len(b.all)) ret := make([]kindsys.Core, len(b.all))
copy(ret, b.all) copy(ret, b.all)
return ret return ret
} }
// AllRaw returns a slice of the [kindsys.Raw] instances for all raw kinds.
//
// The returned slice is sorted lexicographically by kind machine name.
func (b *Base) AllRaw() []kindsys.Raw {
ret := make([]kindsys.Raw, 0, b.numRaw)
for _, k := range b.all {
if rk, is := k.(kindsys.Raw); is {
ret = append(ret, rk)
}
}
return ret
}
// AllStructured returns a slice of the [kindsys.Structured] instances for
// all core structured kinds.
//
// The returned slice is sorted lexicographically by kind machine name.
func (b *Base) AllStructured() []kindsys.Structured {
ret := make([]kindsys.Structured, 0, b.numStructured)
for _, k := range b.all {
if rk, is := k.(kindsys.Structured); is {
ret = append(ret, rk)
}
}
return ret
}

@ -14,7 +14,6 @@ import (
"github.com/grafana/grafana/pkg/kinds/dashboard" "github.com/grafana/grafana/pkg/kinds/dashboard"
"github.com/grafana/grafana/pkg/kinds/playlist" "github.com/grafana/grafana/pkg/kinds/playlist"
"github.com/grafana/grafana/pkg/kinds/svg"
"github.com/grafana/grafana/pkg/kinds/team" "github.com/grafana/grafana/pkg/kinds/team"
"github.com/grafana/grafana/pkg/kindsys" "github.com/grafana/grafana/pkg/kindsys"
"github.com/grafana/thema" "github.com/grafana/thema"
@ -31,20 +30,17 @@ import (
// Prefer All*() methods when performing operations generically across all kinds. // Prefer All*() methods when performing operations generically across all kinds.
// For example, a validation HTTP middleware for any kind-schematized object type. // For example, a validation HTTP middleware for any kind-schematized object type.
type Base struct { type Base struct {
all []kindsys.Interface all []kindsys.Core
numRaw, numStructured int
dashboard *dashboard.Kind dashboard *dashboard.Kind
playlist *playlist.Kind playlist *playlist.Kind
svg *svg.Kind
team *team.Kind team *team.Kind
} }
// type guards // type guards
var ( var (
_ kindsys.Structured = &dashboard.Kind{} _ kindsys.Core = &dashboard.Kind{}
_ kindsys.Structured = &playlist.Kind{} _ kindsys.Core = &playlist.Kind{}
_ kindsys.Raw = &svg.Kind{} _ kindsys.Core = &team.Kind{}
_ kindsys.Structured = &team.Kind{}
) )
// Dashboard returns the [kindsys.Interface] implementation for the dashboard kind. // Dashboard returns the [kindsys.Interface] implementation for the dashboard kind.
@ -57,11 +53,6 @@ func (b *Base) Playlist() *playlist.Kind {
return b.playlist return b.playlist
} }
// SVG returns the [kindsys.Interface] implementation for the svg kind.
func (b *Base) SVG() *svg.Kind {
return b.svg
}
// Team returns the [kindsys.Interface] implementation for the team kind. // Team returns the [kindsys.Interface] implementation for the team kind.
func (b *Base) Team() *team.Kind { func (b *Base) Team() *team.Kind {
return b.team return b.team
@ -69,10 +60,7 @@ func (b *Base) Team() *team.Kind {
func doNewBase(rt *thema.Runtime) *Base { func doNewBase(rt *thema.Runtime) *Base {
var err error var err error
reg := &Base{ reg := &Base{}
numRaw: 1,
numStructured: 3,
}
reg.dashboard, err = dashboard.NewKind(rt) reg.dashboard, err = dashboard.NewKind(rt)
if err != nil { if err != nil {
@ -86,12 +74,6 @@ func doNewBase(rt *thema.Runtime) *Base {
} }
reg.all = append(reg.all, reg.playlist) reg.all = append(reg.all, reg.playlist)
reg.svg, err = svg.NewKind()
if err != nil {
panic(fmt.Sprintf("error while initializing the svg Kind: %s", err))
}
reg.all = append(reg.all, reg.svg)
reg.team, err = team.NewKind(rt) reg.team, err = team.NewKind(rt)
if err != nil { if err != nil {
panic(fmt.Sprintf("error while initializing the team Kind: %s", err)) panic(fmt.Sprintf("error while initializing the team Kind: %s", err))

Loading…
Cancel
Save