The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/kindsys/kindcats.cue

165 lines
6.0 KiB

package kindsys
import (
"strings"
"github.com/grafana/thema"
)
// A Kind specifies a type of Grafana resource.
//
// An instance of a Kind is called an entity. An entity is a sequence of bytes -
// for example, a JSON file or HTTP request body - that conforms to the
// constraints defined in a Kind, and enforced by Grafana's entity system.
//
// Once Grafana has determined a given byte sequence to be an
// instance of a known Kind, kind-specific behaviors can be applied,
// requests can be routed, events can be triggered, etc.
//
// Classes and objects in most programming languages are analogous:
// - #Kind is like a `class` keyword
// - 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,
// and CustomStructured.
#Kind: #Raw | #Composable | #CoreStructured | #CustomStructured
// properties shared between all kind categories.
_sharedKind: {
// name is the canonical name of a Kind, as expressed in PascalCase.
//
// To ensure names are generally portable and amenable for consumption
// in various mechanical tasks, name largely follows the relatively
// strict DNS label naming standard as defined in RFC 1123:
// - Contain at most 63 characters
// - Contain only lowercase alphanumeric characters or '-'
// - Start with an uppercase alphabetic character
// - End with an alphanumeric character
name: =~"^([A-Z][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])$"
// machineName is the case-normalized (lowercase) version of [name]. This
// version of the name is preferred for use in most mechanical contexts,
// as case normalization ensures that case-insensitive and case-sensitive
// checks will never disagree on uniqueness.
//
// In addition to lowercase normalization, dashes are transformed to underscores.
machineName: strings.ToLower(strings.Replace(name, "-", "_", -1))
// pluralName is the pluralized form of name. Defaults to name + "s".
pluralName: =~"^([A-Z][a-zA-Z0-9-]{0,61}[a-zA-Z])$" | *(name + "s")
// pluralMachineName is the pluralized form of [machineName]. The same case
// normalization and dash transformation is applied to [pluralName] as [machineName]
// applies to [name].
pluralMachineName: strings.ToLower(strings.Replace(pluralName, "-", "_", -1))
// lineageIsGroup indicates whether the lineage in this kind is "grouped". In a
// grouped lineage, each top-level field in the schema specifies a discrete
// object that is expected to exist in the wild
//
// This field is set at the framework level, and cannot be in the declaration of
// any individual kind.
//
// This is likely to eventually become a first-class property in Thema:
// https://github.com/grafana/thema/issues/62
lineageIsGroup: bool
maturity: #Maturity
// The kind system itself is not mature enough yet for any single
// kind to advance beyond "experimental"
// TODO allow more maturity stages once system is ready https://github.com/orgs/grafana/projects/133/views/8
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
// journey. Mature kinds still evolve, but with guarantees about compatibility.
#Maturity: "merged" | "experimental" | "stable" | "mature"
// Structured encompasses all three of the structured kind categories, in which
// a schema specifies validity rules for the byte sequence. These represent all
// the conventional types and functional resources in Grafana, such as
// dashboards and datasources.
//
// 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
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]
lineageIsGroup: false
// known TODOs
// - sanitize function
// - get summary
}
// TODO
#CustomStructured: {
#Structured
lineageIsGroup: false
...
}
// 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
// describe the structure of its queries, which is then composed into dashboards
// and alerting rules.
//
// Each Composable is an implementation of exactly one Slot, a shared meta-schema
// defined by Grafana itself that constrains the shape of schemas declared in
// that ComposableKind.
#Composable: S={
_sharedKind
form: "structured"
// TODO docs
// TODO unify this with the existing slots decls in pkg/framework/coremodel
slot: "Panel" | "Query" | "DSConfig"
// TODO unify this with the existing slots decls in pkg/framework/coremodel
lineageIsGroup: bool & [
if slot == "Panel" { true },
if slot == "DSConfig" { true },
if slot == "Query" { false },
][0]
// 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 }
}