* Update thema to latest * Deal with s/Library/*Runtime/ * Commit new, working results of codegen * We like pointers now * Always take runtime arg for NewBase() * Sketchy handwavy pass at entity meta framework * Little nibbles * Update pkg/framework/coremodel/entityframework.cue Co-authored-by: Artur Wierzbicki <wierzbicki.artur.94@gmail.com> * Move file into new framework location * Introduce loaders, Go code * Complete rename to kind * Flesh out framework, add svg/dashboard examples * Cruft removal * Remove generated kind go files from gitignore * Refine maturity concept, add SlotKind * Update embed and go deps * Export PrefixWithGrafanaCUE * Make the loader actually work, holy crap * Many small tweaks to type.cue * Add Apache 2 licensing exceptions for kinds * Add new kinds dir, start of generator * Roll back to earlier oapi-codegen * Introduce new grafana-specific CUE loaders * Introduce new tidy code generators framework * Catch up kind framework with tinkering * Add slices for the generators * Add write/verify step to main generator * Many renames * Split up kind framework cue files * Use kind.Decl within generated kinds * Create kind.SomeDecl wrapper type to cache lineages * Better names again * Get one generated implemented, hopefully * Copy dashboard schema into new kind.cue * Small fixes to make the initial gen work * Put svg kind in its new home * Add generated Go dashboard type * More renames and cleanups * Add base kind registry and generator * Stop blacklisting *_gen.go files This is not the Go best practice, anyway. All we actually want to ignore for enterprise is generated wire files. * Change codegen output directories pkg/kind -> pkg/kinds pkg/registry/kindreg -> pkg/registry/corekind * Rename pkg/framework/kind to pkg/kindsys * Add core structured kind generator * Add plural and machine names to kind spec * Copy playlist over to kind system * Consolidate kindsys files * Add raw kind generator * Update CODEOWNERS for kind framework * Touch up comments a bit * More docs tweaks * Remove generated types to reduce noise for review * Split each generator into its own file * Rename Slot kind to Composable kind * Add handwavy types for customkind loading * Guard against init calls to framework loader * First pass at doc on extending the kind system * Improve attribute example in docs * Fix wire imports * Add basic TS types generator * Fix composable kind category def * No need for a separate file with generate directive * Catch dashboard schema up * Rename generator types to something saner and generic * Make version configurable in ts/go generators * Add CommonMeta to ease property access * Add kindsys prop indicating whether lineage is group * Put all kind categories back in a single file * Finish with kindsys group props * Refactor maturity progression per discussion - Replace "committed" with "merged" - All kindcats can use all maturity levels, at least for now * Convert ts veneer index generator to modular system * Move over to new jennywrites framework * Strip down old coremodel generator * Use public version of jennywrites * Pull latest thema * Commit generated Go types * Add header injection postprocessor * Move sdboyer/jennywrites to grafana/codejen * Tweak header output * Remove dashboard and playlist coremodels * Fix up backend dashboards devenv test * Fix TS import patterns to new gen filename * Update internal imports, remove coremodel registry * Fix compilation errors, wire generation * Export and replace the prefix dropper * More Go struct and field name changes * Last name fixes, hopefully * Fix lint errors * Last lint error Co-authored-by: Artur Wierzbicki <wierzbicki.artur.94@gmail.com>
5.0 KiB
Kind System
This package contains Grafana's kind system, which defines the rules that govern all Grafana kind declarations, including both core and plugin kinds. It contains many contracts on which public promises of backwards compatibility are made. All changes must be considered with care.
While this package is maintained by @grafana/grafana-as-code, contributions from others are a main goal! Any time you have the thought, "I wish this part of Grafana's codebase was consistent," rather than writing docs (that people will inevitably miss), it's worth seeing if you can express that consistency as a kindsys extension instead.
This document is the guide to extending kindsys. But first, we have to identify kindsys's key components.
Elements of kindsys
- CUE framework - the collection of .cue files in this directory,
pkg/kindsys. These are schemas that define how Kinds are declared. - Go framework - the Go package in this directory containing utilities for loading individual kind declarations, validating them against the CUE framework, and representing them consistently in Go.
- Code generators -
pkg/codegencontains the codegen framework. Individual generators (which take one or manypkg/kindsys.Decl, and produce a single file) each have apkg/codegen/generator_*.gofile. - Registries - generated lists of all or a well-defined subset of kinds that can be used in code.
pkg/registries/corekindis a registry of all corepkg/kindsys.Interfaceimplementations;packages/grafana-schema/src/index.gen.tsis 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:
- Core Structured - each child directory of
kinds/structured. - Raw - each child directory of
kinds/raw. - Composable - In Grafana core,
public/app/plugins/*/*/models.cuefiles. - Custom - No examples in Grafana core. See operator-app-sdk (TODO that repo is private; make it public, or point to public examples).
- Core Structured - each child directory of
The above are treated as similarly to stateless libraries - a layer beneath the main Grafana frontend and backend without dependencies on it (no storage, no API, no wire, etc.). This lack of dependencies, and their Apache v2 licensing, allow their use as libraries for external tools.
Extending kindsys
Extending the kind system generally involves:
- Introducing one or more new fields into the CUE framework
- Updating the Go framework to accommodate the new fields
- Updating the kind authoring and maturity planning docs to reflect the new extension
- (possibly) Writing one or more new code generators
- (possibly) Writing/refactoring some frontend code that depends on new codegen output
- (possibly) Writing/refactoring some backend code that depends on codegen output and/or the Go kind framework
- (possibly) Tweaking all existing kinds as-needed to accommodate the new extension
TODO detailed guide to the above steps
The above steps certainly aren't trivial. But they all come only after figuring out a way to solve the problem you want to solve in terms of the kind system and code generation in the first place.
TODO brief guide on how to think in codegen
Extensions not involving kind metadata
While the main path for extending kindsys is through adding metadata, there are some other ways of extending kindsys.
CUE attributes
CUE attributes provide additional information to kind tooling. They are suitable when it is necessary for a schema author to express additional information about a particular field or definition within a schema, without actually modifying the meaning of the schema. Two such known patterns are:
- Controlling nuanced behavior of code generators for some field or type. Example: @cuetsy attributes, which govern TS output
- Expressing some kind of structured TODO or WIP information on a field or type that can be easily analyzed and fed into other systems. Example: a kind marked at least
stablematurity may not have any@grafanamaturityattributes
In both of these cases, attributes are a tool for the individual kind author to convey something to downstream consumers of kind declarations. It is essential. While attributes allow consistency in how a particular task is accomplished, they leave when to apply the rule up to the judgment of the kind author.
Attributes occupy an awkward middle ground. They are more challenging to implement than standard kind framework properties, and less consistent than general codegen transformers while still imposing a cognitive burden on kind authors. They should be the last tool you reach for - but may be the only tool available when field-level schema metadata is required.
TODO create a general pattern for self-contained attribute parser/validators to follow
Codegen transformers
TODO actually write this - use Uid->UID as example