mirror of https://github.com/grafana/grafana
Schemas: Generate CRDs for core kinds (#62641)
Co-authored-by: sam boyer <sdboyer@grafana.com>pull/62715/head
parent
b95eda045a
commit
e70d623f90
@ -0,0 +1,61 @@ |
|||||||
|
package codegen |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"fmt" |
||||||
|
"path/filepath" |
||||||
|
|
||||||
|
"github.com/grafana/codejen" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys" |
||||||
|
) |
||||||
|
|
||||||
|
// CRDKindRegistryJenny generates a static registry of the CRD representations
|
||||||
|
// of core Grafana kinds, layered on top of the publicly consumable generated
|
||||||
|
// registry in pkg/corekinds.
|
||||||
|
//
|
||||||
|
// Path should be the relative path to the directory that will contain the
|
||||||
|
// generated registry.
|
||||||
|
func CRDKindRegistryJenny(path string) ManyToOne { |
||||||
|
return &crdregjenny{ |
||||||
|
path: path, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
type crdregjenny struct { |
||||||
|
path string |
||||||
|
} |
||||||
|
|
||||||
|
func (j *crdregjenny) JennyName() string { |
||||||
|
return "CRDKindRegistryJenny" |
||||||
|
} |
||||||
|
|
||||||
|
func (j *crdregjenny) Generate(kinds ...kindsys.Kind) (*codejen.File, error) { |
||||||
|
cores := make([]kindsys.Core, 0, len(kinds)) |
||||||
|
for _, d := range kinds { |
||||||
|
if corekind, is := d.(kindsys.Core); is { |
||||||
|
cores = append(cores, corekind) |
||||||
|
} |
||||||
|
} |
||||||
|
if len(cores) == 0 { |
||||||
|
return nil, nil |
||||||
|
} |
||||||
|
|
||||||
|
buf := new(bytes.Buffer) |
||||||
|
if err := tmpls.Lookup("core_crd_registry.tmpl").Execute(buf, tvars_kind_registry{ |
||||||
|
PackageName: "corecrd", |
||||||
|
KindPackagePrefix: filepath.ToSlash(filepath.Join("github.com/grafana/grafana", kindsys.GoCoreKindParentPath)), |
||||||
|
Kinds: cores, |
||||||
|
}); err != nil { |
||||||
|
return nil, fmt.Errorf("failed executing core crd registry template: %w", err) |
||||||
|
} |
||||||
|
|
||||||
|
b, err := postprocessGoFile(genGoFile{ |
||||||
|
path: j.path, |
||||||
|
in: buf.Bytes(), |
||||||
|
}) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
return codejen.NewFile(filepath.Join(j.path, "registry_gen.go"), b, j), nil |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
package codegen |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"fmt" |
||||||
|
"path/filepath" |
||||||
|
|
||||||
|
"github.com/grafana/codejen" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys" |
||||||
|
) |
||||||
|
|
||||||
|
// CRDTypesJenny generates the OpenAPI CRD representation for a core
|
||||||
|
// structured kind that is expected by Kubernetes controller machinery.
|
||||||
|
func CRDTypesJenny(path string) OneToOne { |
||||||
|
return crdTypesJenny{ |
||||||
|
parentpath: path, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
type crdTypesJenny struct { |
||||||
|
parentpath string |
||||||
|
} |
||||||
|
|
||||||
|
func (j crdTypesJenny) JennyName() string { |
||||||
|
return "CRDTypesJenny" |
||||||
|
} |
||||||
|
|
||||||
|
func (j crdTypesJenny) Generate(kind kindsys.Kind) (*codejen.File, error) { |
||||||
|
_, isCore := kind.(kindsys.Core) |
||||||
|
_, isCustom := kind.(kindsys.Core) |
||||||
|
if !(isCore || isCustom) { |
||||||
|
return nil, nil |
||||||
|
} |
||||||
|
|
||||||
|
buf := new(bytes.Buffer) |
||||||
|
if err := tmpls.Lookup("core_crd_types.tmpl").Execute(buf, kind); err != nil { |
||||||
|
return nil, fmt.Errorf("failed executing crd types template: %w", err) |
||||||
|
} |
||||||
|
|
||||||
|
name := kind.Props().Common().MachineName |
||||||
|
path := filepath.Join(j.parentpath, name, "crd", name+"_crd_gen.go") |
||||||
|
b, err := postprocessGoFile(genGoFile{ |
||||||
|
path: path, |
||||||
|
in: buf.Bytes(), |
||||||
|
}) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
return codejen.NewFile(path, b, j), nil |
||||||
|
} |
@ -0,0 +1,214 @@ |
|||||||
|
package codegen |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"fmt" |
||||||
|
"path/filepath" |
||||||
|
|
||||||
|
"cuelang.org/go/cue" |
||||||
|
"cuelang.org/go/cue/ast" |
||||||
|
"cuelang.org/go/encoding/openapi" |
||||||
|
cueyaml "cuelang.org/go/pkg/encoding/yaml" |
||||||
|
"github.com/grafana/codejen" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
"github.com/grafana/thema" |
||||||
|
goyaml "gopkg.in/yaml.v3" |
||||||
|
) |
||||||
|
|
||||||
|
// TODO this jenny is quite sloppy, having been quickly adapted from app-sdk. It needs love
|
||||||
|
|
||||||
|
// YamlCRDJenny generates a representation of a core structured kind in YAML CRD form.
|
||||||
|
func YamlCRDJenny(path string) OneToOne { |
||||||
|
return yamlCRDJenny{ |
||||||
|
parentpath: path, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
type yamlCRDJenny struct { |
||||||
|
parentpath string |
||||||
|
} |
||||||
|
|
||||||
|
func (yamlCRDJenny) JennyName() string { |
||||||
|
return "YamlCRDJenny" |
||||||
|
} |
||||||
|
|
||||||
|
func (j yamlCRDJenny) Generate(k kindsys.Kind) (*codejen.File, error) { |
||||||
|
kind, is := k.(kindsys.Core) |
||||||
|
if !is { |
||||||
|
return nil, nil |
||||||
|
} |
||||||
|
|
||||||
|
props := kind.Def().Properties |
||||||
|
lin := kind.Lineage() |
||||||
|
|
||||||
|
// We need to go through every schema, as they all have to be defined in the CRD
|
||||||
|
sch, err := lin.Schema(thema.SV(0, 0)) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
resource := customResourceDefinition{ |
||||||
|
APIVersion: "apiextensions.k8s.io/v1", |
||||||
|
Kind: "CustomResourceDefinition", |
||||||
|
Metadata: customResourceDefinitionMetadata{ |
||||||
|
Name: fmt.Sprintf("%s.%s", props.PluralMachineName, props.CRD.Group), |
||||||
|
}, |
||||||
|
Spec: k8ssys.CustomResourceDefinitionSpec{ |
||||||
|
Group: props.CRD.Group, |
||||||
|
Scope: props.CRD.Scope, |
||||||
|
Names: k8ssys.CustomResourceDefinitionSpecNames{ |
||||||
|
Kind: props.Name, |
||||||
|
Plural: props.PluralMachineName, |
||||||
|
}, |
||||||
|
Versions: make([]k8ssys.CustomResourceDefinitionSpecVersion, 0), |
||||||
|
}, |
||||||
|
} |
||||||
|
latest := lin.Latest().Version() |
||||||
|
|
||||||
|
for sch != nil { |
||||||
|
oapi, err := generateOpenAPI(sch, props) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
vstr := versionString(sch.Version()) |
||||||
|
if props.Maturity.Less(kindsys.MaturityStable) { |
||||||
|
vstr = "v0-0alpha1" |
||||||
|
} |
||||||
|
|
||||||
|
ver, err := valueToCRDSpecVersion(oapi, vstr, sch.Version() == latest) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
if props.CRD.DummySchema { |
||||||
|
ver.Schema = map[string]any{ |
||||||
|
"openAPIV3Schema": map[string]any{ |
||||||
|
"type": "object", |
||||||
|
"properties": map[string]any{ |
||||||
|
"spec": map[string]any{ |
||||||
|
"type": "object", |
||||||
|
"x-kubernetes-preserve-unknown-fields": true, |
||||||
|
}, |
||||||
|
}, |
||||||
|
"required": []any{ |
||||||
|
"spec", |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
resource.Spec.Versions = append(resource.Spec.Versions, ver) |
||||||
|
sch = sch.Successor() |
||||||
|
} |
||||||
|
contents, err := goyaml.Marshal(resource) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
if props.CRD.DummySchema { |
||||||
|
// Add a comment header for those with dummy schema
|
||||||
|
b := new(bytes.Buffer) |
||||||
|
fmt.Fprintf(b, "# This CRD is generated with an empty schema body because Grafana's\n# code generators currently produce OpenAPI that Kubernetes will not\n# accept, despite being valid.\n\n%s", string(contents)) |
||||||
|
contents = b.Bytes() |
||||||
|
} |
||||||
|
|
||||||
|
return codejen.NewFile(filepath.Join(j.parentpath, props.MachineName, "crd", props.MachineName+".crd.yml"), contents, j), nil |
||||||
|
} |
||||||
|
|
||||||
|
// customResourceDefinition differs from k8ssys.CustomResourceDefinition in that it doesn't use the metav1
|
||||||
|
// TypeMeta and ObjectMeta, as those do not contain YAML tags and get improperly serialized to YAML.
|
||||||
|
// Since we don't need to use it with the kubernetes go-client, we don't need the extra functionality attached.
|
||||||
|
//
|
||||||
|
//nolint:lll
|
||||||
|
type customResourceDefinition struct { |
||||||
|
Kind string `json:"kind,omitempty" yaml:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"` |
||||||
|
APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty" protobuf:"bytes,2,opt,name=apiVersion"` |
||||||
|
Metadata customResourceDefinitionMetadata `json:"metadata,omitempty" yaml:"metadata,omitempty"` |
||||||
|
Spec k8ssys.CustomResourceDefinitionSpec `json:"spec"` |
||||||
|
} |
||||||
|
|
||||||
|
type customResourceDefinitionMetadata struct { |
||||||
|
Name string `json:"name,omitempty" yaml:"name" protobuf:"bytes,1,opt,name=name"` |
||||||
|
// TODO: other fields as necessary for codegen
|
||||||
|
} |
||||||
|
|
||||||
|
type cueOpenAPIEncoded struct { |
||||||
|
Components cueOpenAPIEncodedComponents `json:"components"` |
||||||
|
} |
||||||
|
|
||||||
|
type cueOpenAPIEncodedComponents struct { |
||||||
|
Schemas map[string]any `json:"schemas"` |
||||||
|
} |
||||||
|
|
||||||
|
func valueToCRDSpecVersion(str string, name string, stored bool) (k8ssys.CustomResourceDefinitionSpecVersion, error) { |
||||||
|
// Decode the bytes back into an object where we can trim the openAPI clutter out
|
||||||
|
// and grab just the schema as a map[string]any (which is what k8s wants)
|
||||||
|
back := cueOpenAPIEncoded{} |
||||||
|
err := goyaml.Unmarshal([]byte(str), &back) |
||||||
|
if err != nil { |
||||||
|
return k8ssys.CustomResourceDefinitionSpecVersion{}, err |
||||||
|
} |
||||||
|
if len(back.Components.Schemas) != 1 { |
||||||
|
// There should only be one schema here...
|
||||||
|
// TODO: this may change with subresources--but subresources should have defined names
|
||||||
|
return k8ssys.CustomResourceDefinitionSpecVersion{}, fmt.Errorf("version %s has multiple schemas", name) |
||||||
|
} |
||||||
|
var def map[string]any |
||||||
|
for _, v := range back.Components.Schemas { |
||||||
|
ok := false |
||||||
|
def, ok = v.(map[string]any) |
||||||
|
if !ok { |
||||||
|
return k8ssys.CustomResourceDefinitionSpecVersion{}, |
||||||
|
fmt.Errorf("error generating openapi schema - generated schema has invalid type") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return k8ssys.CustomResourceDefinitionSpecVersion{ |
||||||
|
Name: name, |
||||||
|
Served: true, |
||||||
|
Storage: stored, |
||||||
|
Schema: map[string]any{ |
||||||
|
"openAPIV3Schema": map[string]any{ |
||||||
|
"properties": map[string]any{ |
||||||
|
"spec": def, |
||||||
|
}, |
||||||
|
"required": []any{ |
||||||
|
"spec", |
||||||
|
}, |
||||||
|
"type": "object", |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, nil |
||||||
|
} |
||||||
|
|
||||||
|
func versionString(version thema.SyntacticVersion) string { |
||||||
|
return fmt.Sprintf("v%d-%d", version[0], version[1]) |
||||||
|
} |
||||||
|
|
||||||
|
// Hoisting this out of thema until we resolve the proper approach there
|
||||||
|
func generateOpenAPI(sch thema.Schema, props kindsys.CoreProperties) (string, error) { |
||||||
|
ctx := sch.Underlying().Context() |
||||||
|
v := ctx.CompileString(fmt.Sprintf("#%s: _", props.Name)) |
||||||
|
defpath := cue.MakePath(cue.Def(props.Name)) |
||||||
|
defsch := v.FillPath(defpath, sch.Underlying()) |
||||||
|
|
||||||
|
cfg := &openapi.Config{ |
||||||
|
NameFunc: func(v cue.Value, path cue.Path) string { |
||||||
|
if path.String() == defpath.String() { |
||||||
|
return props.Name |
||||||
|
} |
||||||
|
return "" |
||||||
|
}, |
||||||
|
Info: ast.NewStruct( // doesn't matter, we're throwing it away
|
||||||
|
"title", ast.NewString(props.Name), |
||||||
|
"version", ast.NewString("0.0"), |
||||||
|
), |
||||||
|
} |
||||||
|
|
||||||
|
f, err := openapi.Generate(defsch, cfg) |
||||||
|
if err != nil { |
||||||
|
return "", err |
||||||
|
} |
||||||
|
|
||||||
|
return cueyaml.Marshal(sch.Lineage().Runtime().Context().BuildFile(f)) |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
package {{ .PackageName }} |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
"fmt" |
||||||
|
|
||||||
|
{{range .Kinds }} |
||||||
|
{{ .Props.MachineName }} "{{ $.KindPackagePrefix }}/{{ .Props.MachineName }}/crd"{{end}} |
||||||
|
"github.com/grafana/grafana/pkg/kindsys" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
"github.com/grafana/grafana/pkg/registry/corekind" |
||||||
|
"gopkg.in/yaml.v3" |
||||||
|
) |
||||||
|
|
||||||
|
// Registry is a list of all of Grafana's core structured kinds, wrapped in a |
||||||
|
// standard [k8ssys.CRD] interface that makes them usable for interactions |
||||||
|
// with certain Kubernetes controller and apimachinery libraries. |
||||||
|
// |
||||||
|
// There are two access methods: individually via literal named methods, or as |
||||||
|
// a slice returned from All() method. |
||||||
|
// |
||||||
|
// Prefer the individual named methods for use cases where the particular kind(s) |
||||||
|
// that are needed are known to the caller. Prefer All() when performing operations |
||||||
|
// generically across all kinds. |
||||||
|
type Registry struct { |
||||||
|
all [{{ len .Kinds }}]k8ssys.Kind |
||||||
|
} |
||||||
|
|
||||||
|
{{range $i, $k := .Kinds }} |
||||||
|
// {{ .Props.Name }} returns the [k8ssys.Kind] instance for the {{ .Props.Name }} kind. |
||||||
|
func (r *Registry) {{ .Props.Name }}() k8ssys.Kind { |
||||||
|
return r.all[{{ $i }}] |
||||||
|
} |
||||||
|
{{end}} |
||||||
|
|
||||||
|
func doNewRegistry(breg *corekind.Base) *Registry { |
||||||
|
var err error |
||||||
|
var b []byte |
||||||
|
var kk k8ssys.Kind |
||||||
|
reg := &Registry{} |
||||||
|
|
||||||
|
{{range $i, $k := .Kinds }} |
||||||
|
kk = k8ssys.Kind{ |
||||||
|
GrafanaKind: breg.{{ $k.Props.Name }}(), |
||||||
|
Object: &{{ $k.Props.MachineName }}.{{ $k.Props.Name }}{}, |
||||||
|
ObjectList: &{{ $k.Props.MachineName }}.{{ $k.Props.Name }}List{}, |
||||||
|
} |
||||||
|
// TODO Having the committed form on disk in YAML is worth doing this for now...but fix this silliness |
||||||
|
map{{ $i }} := make(map[string]any) |
||||||
|
err = yaml.Unmarshal({{ $k.Props.MachineName }}.CRDYaml, map{{ $i }}) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("generated CRD YAML for {{ $k.Props.Name }} failed to unmarshal: %s", err)) |
||||||
|
} |
||||||
|
b, err = json.Marshal(map{{ $i }}) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not re-marshal CRD JSON for {{ $k.Props.Name }}: %s", err)) |
||||||
|
} |
||||||
|
err = json.Unmarshal(b, &kk.Schema) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not unmarshal CRD JSON for {{ $k.Props.Name }}: %s", err)) |
||||||
|
} |
||||||
|
reg.all[{{ $i }}] = kk |
||||||
|
{{end}} |
||||||
|
|
||||||
|
return reg |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package crd |
||||||
|
|
||||||
|
import ( |
||||||
|
_ "embed" |
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/kinds/{{ .Props.MachineName }}" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
) |
||||||
|
|
||||||
|
// The CRD YAML representation of the {{ .Props.Name }} kind. |
||||||
|
// |
||||||
|
//go:embed {{ .Props.MachineName }}.crd.yml |
||||||
|
var CRDYaml []byte |
||||||
|
|
||||||
|
// {{ .Props.Name }} is the Go CRD representation of a single {{ .Props.Name }} object. |
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction. |
||||||
|
type {{ .Props.Name }} struct { |
||||||
|
k8ssys.Base[{{ .Props.MachineName }}.{{ .Props.Name }}] |
||||||
|
} |
||||||
|
|
||||||
|
// {{ .Props.Name }}List is the Go CRD representation of a list {{ .Props.Name }} objects. |
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction. |
||||||
|
type {{ .Props.Name }}List struct { |
||||||
|
k8ssys.ListBase[{{ .Props.MachineName }}.{{ .Props.Name }}] |
||||||
|
} |
@ -1,11 +1,11 @@ |
|||||||
// Code generated - EDITING IS FUTILE. DO NOT EDIT. |
{{ .Leader }} Code generated - EDITING IS FUTILE. DO NOT EDIT. |
||||||
// |
{{ .Leader }} |
||||||
// Generated by: |
{{ .Leader }} Generated by: |
||||||
// {{ .MainGenerator }} |
{{ .Leader }} {{ .MainGenerator }} |
||||||
// Using jennies: |
{{ .Leader }} Using jennies: |
||||||
{{- range .Using }} |
{{- range .Using }} |
||||||
// {{ .JennyName }} |
{{ $.Leader }} {{ .JennyName }} |
||||||
{{- end }} |
{{- end }} |
||||||
// |
{{ .Leader }} |
||||||
// Run 'make gen-cue' from repository root to regenerate. |
{{ .Leader }} Run 'make gen-cue' from repository root to regenerate. |
||||||
|
|
||||||
|
@ -0,0 +1,36 @@ |
|||||||
|
# Code generated - EDITING IS FUTILE. DO NOT EDIT. |
||||||
|
# |
||||||
|
# Generated by: |
||||||
|
# kinds/gen.go |
||||||
|
# Using jennies: |
||||||
|
# YamlCRDJenny |
||||||
|
# |
||||||
|
# Run 'make gen-cue' from repository root to regenerate. |
||||||
|
|
||||||
|
# This CRD is generated with an empty schema body because Grafana's |
||||||
|
# code generators currently produce OpenAPI that Kubernetes will not |
||||||
|
# accept, despite being valid. |
||||||
|
|
||||||
|
kind: CustomResourceDefinition |
||||||
|
apiVersion: apiextensions.k8s.io/v1 |
||||||
|
metadata: |
||||||
|
name: dashboards.dashboard.core.grafana.com |
||||||
|
spec: |
||||||
|
group: dashboard.core.grafana.com |
||||||
|
versions: |
||||||
|
- name: v0-0alpha1 |
||||||
|
served: true |
||||||
|
storage: true |
||||||
|
schema: |
||||||
|
openAPIV3Schema: |
||||||
|
properties: |
||||||
|
spec: |
||||||
|
type: object |
||||||
|
x-kubernetes-preserve-unknown-fields: true |
||||||
|
required: |
||||||
|
- spec |
||||||
|
type: object |
||||||
|
names: |
||||||
|
kind: Dashboard |
||||||
|
plural: dashboards |
||||||
|
scope: Namespaced |
@ -0,0 +1,34 @@ |
|||||||
|
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Generated by:
|
||||||
|
// kinds/gen.go
|
||||||
|
// Using jennies:
|
||||||
|
// CRDTypesJenny
|
||||||
|
//
|
||||||
|
// Run 'make gen-cue' from repository root to regenerate.
|
||||||
|
|
||||||
|
package crd |
||||||
|
|
||||||
|
import ( |
||||||
|
_ "embed" |
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/kinds/dashboard" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
) |
||||||
|
|
||||||
|
// The CRD YAML representation of the Dashboard kind.
|
||||||
|
//
|
||||||
|
//go:embed dashboard.crd.yml
|
||||||
|
var CRDYaml []byte |
||||||
|
|
||||||
|
// Dashboard is the Go CRD representation of a single Dashboard object.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type Dashboard struct { |
||||||
|
k8ssys.Base[dashboard.Dashboard] |
||||||
|
} |
||||||
|
|
||||||
|
// DashboardList is the Go CRD representation of a list Dashboard objects.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type DashboardList struct { |
||||||
|
k8ssys.ListBase[dashboard.Dashboard] |
||||||
|
} |
@ -0,0 +1,120 @@ |
|||||||
|
# Code generated - EDITING IS FUTILE. DO NOT EDIT. |
||||||
|
# |
||||||
|
# Generated by: |
||||||
|
# kinds/gen.go |
||||||
|
# Using jennies: |
||||||
|
# YamlCRDJenny |
||||||
|
# |
||||||
|
# Run 'make gen-cue' from repository root to regenerate. |
||||||
|
|
||||||
|
kind: CustomResourceDefinition |
||||||
|
apiVersion: apiextensions.k8s.io/v1 |
||||||
|
metadata: |
||||||
|
name: librarypanels.librarypanel.core.grafana.com |
||||||
|
spec: |
||||||
|
group: librarypanel.core.grafana.com |
||||||
|
versions: |
||||||
|
- name: v0-0alpha1 |
||||||
|
served: true |
||||||
|
storage: true |
||||||
|
schema: |
||||||
|
openAPIV3Schema: |
||||||
|
properties: |
||||||
|
spec: |
||||||
|
properties: |
||||||
|
description: |
||||||
|
description: Panel description |
||||||
|
type: string |
||||||
|
folderUid: |
||||||
|
description: Folder UID |
||||||
|
type: string |
||||||
|
meta: |
||||||
|
description: Object storage metadata |
||||||
|
properties: |
||||||
|
connectedDashboards: |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
created: |
||||||
|
type: string |
||||||
|
createdBy: |
||||||
|
properties: |
||||||
|
avatarUrl: |
||||||
|
type: string |
||||||
|
id: |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
name: |
||||||
|
type: string |
||||||
|
required: |
||||||
|
- id |
||||||
|
- name |
||||||
|
- avatarUrl |
||||||
|
type: object |
||||||
|
folderName: |
||||||
|
type: string |
||||||
|
folderUid: |
||||||
|
type: string |
||||||
|
updated: |
||||||
|
type: string |
||||||
|
updatedBy: |
||||||
|
properties: |
||||||
|
avatarUrl: |
||||||
|
type: string |
||||||
|
id: |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
name: |
||||||
|
type: string |
||||||
|
required: |
||||||
|
- id |
||||||
|
- name |
||||||
|
- avatarUrl |
||||||
|
type: object |
||||||
|
required: |
||||||
|
- folderName |
||||||
|
- folderUid |
||||||
|
- connectedDashboards |
||||||
|
- created |
||||||
|
- updated |
||||||
|
- createdBy |
||||||
|
- updatedBy |
||||||
|
type: object |
||||||
|
model: |
||||||
|
description: |- |
||||||
|
TODO: should be the same panel schema defined in dashboard |
||||||
|
Typescript: Omit<Panel, 'gridPos' | 'id' | 'libraryPanel'>; |
||||||
|
type: object |
||||||
|
name: |
||||||
|
description: Panel name (also saved in the model) |
||||||
|
minLength: 1 |
||||||
|
type: string |
||||||
|
schemaVersion: |
||||||
|
description: Dashboard version when this was saved (zero if unknown) |
||||||
|
maximum: 65535 |
||||||
|
minimum: 0 |
||||||
|
type: integer |
||||||
|
type: |
||||||
|
description: The panel type (from inside the model) |
||||||
|
minLength: 1 |
||||||
|
type: string |
||||||
|
uid: |
||||||
|
description: Library element UID |
||||||
|
type: string |
||||||
|
version: |
||||||
|
description: panel version, incremented each time the dashboard is updated. |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
required: |
||||||
|
- uid |
||||||
|
- name |
||||||
|
- type |
||||||
|
- version |
||||||
|
- model |
||||||
|
type: object |
||||||
|
required: |
||||||
|
- spec |
||||||
|
type: object |
||||||
|
names: |
||||||
|
kind: LibraryPanel |
||||||
|
plural: librarypanels |
||||||
|
scope: Namespaced |
@ -0,0 +1,34 @@ |
|||||||
|
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Generated by:
|
||||||
|
// kinds/gen.go
|
||||||
|
// Using jennies:
|
||||||
|
// CRDTypesJenny
|
||||||
|
//
|
||||||
|
// Run 'make gen-cue' from repository root to regenerate.
|
||||||
|
|
||||||
|
package crd |
||||||
|
|
||||||
|
import ( |
||||||
|
_ "embed" |
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/kinds/librarypanel" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
) |
||||||
|
|
||||||
|
// The CRD YAML representation of the LibraryPanel kind.
|
||||||
|
//
|
||||||
|
//go:embed librarypanel.crd.yml
|
||||||
|
var CRDYaml []byte |
||||||
|
|
||||||
|
// LibraryPanel is the Go CRD representation of a single LibraryPanel object.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type LibraryPanel struct { |
||||||
|
k8ssys.Base[librarypanel.LibraryPanel] |
||||||
|
} |
||||||
|
|
||||||
|
// LibraryPanelList is the Go CRD representation of a list LibraryPanel objects.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type LibraryPanelList struct { |
||||||
|
k8ssys.ListBase[librarypanel.LibraryPanel] |
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
# Code generated - EDITING IS FUTILE. DO NOT EDIT. |
||||||
|
# |
||||||
|
# Generated by: |
||||||
|
# kinds/gen.go |
||||||
|
# Using jennies: |
||||||
|
# YamlCRDJenny |
||||||
|
# |
||||||
|
# Run 'make gen-cue' from repository root to regenerate. |
||||||
|
|
||||||
|
kind: CustomResourceDefinition |
||||||
|
apiVersion: apiextensions.k8s.io/v1 |
||||||
|
metadata: |
||||||
|
name: playlists.playlist.core.grafana.com |
||||||
|
spec: |
||||||
|
group: playlist.core.grafana.com |
||||||
|
versions: |
||||||
|
- name: v0-0alpha1 |
||||||
|
served: true |
||||||
|
storage: true |
||||||
|
schema: |
||||||
|
openAPIV3Schema: |
||||||
|
properties: |
||||||
|
spec: |
||||||
|
properties: |
||||||
|
interval: |
||||||
|
default: 5m |
||||||
|
description: |- |
||||||
|
Interval sets the time between switching views in a playlist. |
||||||
|
FIXME: Is this based on a standardized format or what options are available? Can datemath be used? |
||||||
|
type: string |
||||||
|
items: |
||||||
|
description: |- |
||||||
|
The ordered list of items that the playlist will iterate over. |
||||||
|
FIXME! This should not be optional, but changing it makes the godegen awkward |
||||||
|
items: |
||||||
|
properties: |
||||||
|
title: |
||||||
|
description: Title is an unused property -- it will be removed in the future |
||||||
|
type: string |
||||||
|
type: |
||||||
|
description: Type of the item. |
||||||
|
enum: |
||||||
|
- dashboard_by_uid |
||||||
|
- dashboard_by_id |
||||||
|
- dashboard_by_tag |
||||||
|
type: string |
||||||
|
value: |
||||||
|
description: |- |
||||||
|
Value depends on type and describes the playlist item. |
||||||
|
|
||||||
|
- dashboard_by_id: The value is an internal numerical identifier set by Grafana. This |
||||||
|
is not portable as the numerical identifier is non-deterministic between different instances. |
||||||
|
Will be replaced by dashboard_by_uid in the future. (deprecated) |
||||||
|
- dashboard_by_tag: The value is a tag which is set on any number of dashboards. All |
||||||
|
dashboards behind the tag will be added to the playlist. |
||||||
|
- dashboard_by_uid: The value is the dashboard UID |
||||||
|
type: string |
||||||
|
required: |
||||||
|
- type |
||||||
|
- value |
||||||
|
type: object |
||||||
|
type: array |
||||||
|
name: |
||||||
|
description: Name of the playlist. |
||||||
|
type: string |
||||||
|
uid: |
||||||
|
description: |- |
||||||
|
Unique playlist identifier. Generated on creation, either by the |
||||||
|
creator of the playlist of by the application. |
||||||
|
type: string |
||||||
|
required: |
||||||
|
- uid |
||||||
|
- name |
||||||
|
- interval |
||||||
|
type: object |
||||||
|
required: |
||||||
|
- spec |
||||||
|
type: object |
||||||
|
names: |
||||||
|
kind: Playlist |
||||||
|
plural: playlists |
||||||
|
scope: Namespaced |
@ -0,0 +1,34 @@ |
|||||||
|
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Generated by:
|
||||||
|
// kinds/gen.go
|
||||||
|
// Using jennies:
|
||||||
|
// CRDTypesJenny
|
||||||
|
//
|
||||||
|
// Run 'make gen-cue' from repository root to regenerate.
|
||||||
|
|
||||||
|
package crd |
||||||
|
|
||||||
|
import ( |
||||||
|
_ "embed" |
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/kinds/playlist" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
) |
||||||
|
|
||||||
|
// The CRD YAML representation of the Playlist kind.
|
||||||
|
//
|
||||||
|
//go:embed playlist.crd.yml
|
||||||
|
var CRDYaml []byte |
||||||
|
|
||||||
|
// Playlist is the Go CRD representation of a single Playlist object.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type Playlist struct { |
||||||
|
k8ssys.Base[playlist.Playlist] |
||||||
|
} |
||||||
|
|
||||||
|
// PlaylistList is the Go CRD representation of a list Playlist objects.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type PlaylistList struct { |
||||||
|
k8ssys.ListBase[playlist.Playlist] |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
# Code generated - EDITING IS FUTILE. DO NOT EDIT. |
||||||
|
# |
||||||
|
# Generated by: |
||||||
|
# kinds/gen.go |
||||||
|
# Using jennies: |
||||||
|
# YamlCRDJenny |
||||||
|
# |
||||||
|
# Run 'make gen-cue' from repository root to regenerate. |
||||||
|
|
||||||
|
kind: CustomResourceDefinition |
||||||
|
apiVersion: apiextensions.k8s.io/v1 |
||||||
|
metadata: |
||||||
|
name: preferencess.preferences.core.grafana.com |
||||||
|
spec: |
||||||
|
group: preferences.core.grafana.com |
||||||
|
versions: |
||||||
|
- name: v0-0alpha1 |
||||||
|
served: true |
||||||
|
storage: true |
||||||
|
schema: |
||||||
|
openAPIV3Schema: |
||||||
|
properties: |
||||||
|
spec: |
||||||
|
properties: |
||||||
|
homeDashboardUID: |
||||||
|
description: UID for the home dashboard |
||||||
|
type: string |
||||||
|
language: |
||||||
|
description: Selected language (beta) |
||||||
|
type: string |
||||||
|
queryHistory: |
||||||
|
description: Explore query history preferences |
||||||
|
properties: |
||||||
|
homeTab: |
||||||
|
description: 'one of: '''' | ''query'' | ''starred'';' |
||||||
|
type: string |
||||||
|
type: object |
||||||
|
theme: |
||||||
|
description: light, dark, empty is default |
||||||
|
type: string |
||||||
|
timezone: |
||||||
|
description: |- |
||||||
|
The timezone selection |
||||||
|
TODO: this should use the timezone defined in common |
||||||
|
type: string |
||||||
|
weekStart: |
||||||
|
description: day of the week (sunday, monday, etc) |
||||||
|
type: string |
||||||
|
type: object |
||||||
|
required: |
||||||
|
- spec |
||||||
|
type: object |
||||||
|
names: |
||||||
|
kind: Preferences |
||||||
|
plural: preferencess |
||||||
|
scope: Namespaced |
@ -0,0 +1,34 @@ |
|||||||
|
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Generated by:
|
||||||
|
// kinds/gen.go
|
||||||
|
// Using jennies:
|
||||||
|
// CRDTypesJenny
|
||||||
|
//
|
||||||
|
// Run 'make gen-cue' from repository root to regenerate.
|
||||||
|
|
||||||
|
package crd |
||||||
|
|
||||||
|
import ( |
||||||
|
_ "embed" |
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/kinds/preferences" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
) |
||||||
|
|
||||||
|
// The CRD YAML representation of the Preferences kind.
|
||||||
|
//
|
||||||
|
//go:embed preferences.crd.yml
|
||||||
|
var CRDYaml []byte |
||||||
|
|
||||||
|
// Preferences is the Go CRD representation of a single Preferences object.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type Preferences struct { |
||||||
|
k8ssys.Base[preferences.Preferences] |
||||||
|
} |
||||||
|
|
||||||
|
// PreferencesList is the Go CRD representation of a list Preferences objects.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type PreferencesList struct { |
||||||
|
k8ssys.ListBase[preferences.Preferences] |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
# Code generated - EDITING IS FUTILE. DO NOT EDIT. |
||||||
|
# |
||||||
|
# Generated by: |
||||||
|
# kinds/gen.go |
||||||
|
# Using jennies: |
||||||
|
# YamlCRDJenny |
||||||
|
# |
||||||
|
# Run 'make gen-cue' from repository root to regenerate. |
||||||
|
|
||||||
|
kind: CustomResourceDefinition |
||||||
|
apiVersion: apiextensions.k8s.io/v1 |
||||||
|
metadata: |
||||||
|
name: publicdashboards.publicdashboard.core.grafana.com |
||||||
|
spec: |
||||||
|
group: publicdashboard.core.grafana.com |
||||||
|
versions: |
||||||
|
- name: v0-0alpha1 |
||||||
|
served: true |
||||||
|
storage: true |
||||||
|
schema: |
||||||
|
openAPIV3Schema: |
||||||
|
properties: |
||||||
|
spec: |
||||||
|
properties: |
||||||
|
accessToken: |
||||||
|
description: Unique public access token |
||||||
|
type: string |
||||||
|
annotationsEnabled: |
||||||
|
description: Flag that indicates if annotations are enabled |
||||||
|
type: boolean |
||||||
|
dashboardUid: |
||||||
|
description: Dashboard unique identifier referenced by this public dashboard |
||||||
|
type: string |
||||||
|
isEnabled: |
||||||
|
description: Flag that indicates if the public dashboard is enabled |
||||||
|
type: boolean |
||||||
|
timeSelectionEnabled: |
||||||
|
description: Flag that indicates if the time range picker is enabled |
||||||
|
type: boolean |
||||||
|
uid: |
||||||
|
description: Unique public dashboard identifier |
||||||
|
type: string |
||||||
|
required: |
||||||
|
- uid |
||||||
|
- dashboardUid |
||||||
|
- isEnabled |
||||||
|
- annotationsEnabled |
||||||
|
- timeSelectionEnabled |
||||||
|
type: object |
||||||
|
required: |
||||||
|
- spec |
||||||
|
type: object |
||||||
|
names: |
||||||
|
kind: PublicDashboard |
||||||
|
plural: publicdashboards |
||||||
|
scope: Namespaced |
@ -0,0 +1,34 @@ |
|||||||
|
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Generated by:
|
||||||
|
// kinds/gen.go
|
||||||
|
// Using jennies:
|
||||||
|
// CRDTypesJenny
|
||||||
|
//
|
||||||
|
// Run 'make gen-cue' from repository root to regenerate.
|
||||||
|
|
||||||
|
package crd |
||||||
|
|
||||||
|
import ( |
||||||
|
_ "embed" |
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/kinds/publicdashboard" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
) |
||||||
|
|
||||||
|
// The CRD YAML representation of the PublicDashboard kind.
|
||||||
|
//
|
||||||
|
//go:embed publicdashboard.crd.yml
|
||||||
|
var CRDYaml []byte |
||||||
|
|
||||||
|
// PublicDashboard is the Go CRD representation of a single PublicDashboard object.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type PublicDashboard struct { |
||||||
|
k8ssys.Base[publicdashboard.PublicDashboard] |
||||||
|
} |
||||||
|
|
||||||
|
// PublicDashboardList is the Go CRD representation of a list PublicDashboard objects.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type PublicDashboardList struct { |
||||||
|
k8ssys.ListBase[publicdashboard.PublicDashboard] |
||||||
|
} |
@ -0,0 +1,94 @@ |
|||||||
|
# Code generated - EDITING IS FUTILE. DO NOT EDIT. |
||||||
|
# |
||||||
|
# Generated by: |
||||||
|
# kinds/gen.go |
||||||
|
# Using jennies: |
||||||
|
# YamlCRDJenny |
||||||
|
# |
||||||
|
# Run 'make gen-cue' from repository root to regenerate. |
||||||
|
|
||||||
|
kind: CustomResourceDefinition |
||||||
|
apiVersion: apiextensions.k8s.io/v1 |
||||||
|
metadata: |
||||||
|
name: serviceaccounts.serviceaccount.core.grafana.com |
||||||
|
spec: |
||||||
|
group: serviceaccount.core.grafana.com |
||||||
|
versions: |
||||||
|
- name: v0-0alpha1 |
||||||
|
served: true |
||||||
|
storage: true |
||||||
|
schema: |
||||||
|
openAPIV3Schema: |
||||||
|
properties: |
||||||
|
spec: |
||||||
|
properties: |
||||||
|
accessControl: |
||||||
|
additionalProperties: |
||||||
|
type: boolean |
||||||
|
description: AccessControl metadata associated with a given resource. |
||||||
|
type: object |
||||||
|
avatarUrl: |
||||||
|
description: |- |
||||||
|
AvatarUrl is the service account's avatar URL. It allows the frontend to display a picture in front |
||||||
|
of the service account. |
||||||
|
type: string |
||||||
|
created: |
||||||
|
description: Created indicates when the service account was created. |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
id: |
||||||
|
description: ID is the unique identifier of the service account in the database. |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
isDisabled: |
||||||
|
description: IsDisabled indicates if the service account is disabled. |
||||||
|
type: boolean |
||||||
|
login: |
||||||
|
description: Login of the service account. |
||||||
|
type: string |
||||||
|
name: |
||||||
|
description: Name of the service account. |
||||||
|
type: string |
||||||
|
orgId: |
||||||
|
description: OrgId is the ID of an organisation the service account belongs to. |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
role: |
||||||
|
description: Role is the Grafana organization role of the service account which can be 'Viewer', 'Editor', 'Admin'. |
||||||
|
enum: |
||||||
|
- Admin |
||||||
|
- Editor |
||||||
|
- Viewer |
||||||
|
type: string |
||||||
|
teams: |
||||||
|
description: Teams is a list of teams the service account belongs to. |
||||||
|
items: |
||||||
|
type: string |
||||||
|
type: array |
||||||
|
tokens: |
||||||
|
description: |- |
||||||
|
Tokens is the number of active tokens for the service account. |
||||||
|
Tokens are used to authenticate the service account against Grafana. |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
updated: |
||||||
|
description: Updated indicates when the service account was updated. |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
required: |
||||||
|
- id |
||||||
|
- orgId |
||||||
|
- name |
||||||
|
- login |
||||||
|
- isDisabled |
||||||
|
- role |
||||||
|
- tokens |
||||||
|
- avatarUrl |
||||||
|
type: object |
||||||
|
required: |
||||||
|
- spec |
||||||
|
type: object |
||||||
|
names: |
||||||
|
kind: ServiceAccount |
||||||
|
plural: serviceaccounts |
||||||
|
scope: Namespaced |
@ -0,0 +1,34 @@ |
|||||||
|
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Generated by:
|
||||||
|
// kinds/gen.go
|
||||||
|
// Using jennies:
|
||||||
|
// CRDTypesJenny
|
||||||
|
//
|
||||||
|
// Run 'make gen-cue' from repository root to regenerate.
|
||||||
|
|
||||||
|
package crd |
||||||
|
|
||||||
|
import ( |
||||||
|
_ "embed" |
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/kinds/serviceaccount" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
) |
||||||
|
|
||||||
|
// The CRD YAML representation of the ServiceAccount kind.
|
||||||
|
//
|
||||||
|
//go:embed serviceaccount.crd.yml
|
||||||
|
var CRDYaml []byte |
||||||
|
|
||||||
|
// ServiceAccount is the Go CRD representation of a single ServiceAccount object.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type ServiceAccount struct { |
||||||
|
k8ssys.Base[serviceaccount.ServiceAccount] |
||||||
|
} |
||||||
|
|
||||||
|
// ServiceAccountList is the Go CRD representation of a list ServiceAccount objects.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type ServiceAccountList struct { |
||||||
|
k8ssys.ListBase[serviceaccount.ServiceAccount] |
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
# Code generated - EDITING IS FUTILE. DO NOT EDIT. |
||||||
|
# |
||||||
|
# Generated by: |
||||||
|
# kinds/gen.go |
||||||
|
# Using jennies: |
||||||
|
# YamlCRDJenny |
||||||
|
# |
||||||
|
# Run 'make gen-cue' from repository root to regenerate. |
||||||
|
|
||||||
|
kind: CustomResourceDefinition |
||||||
|
apiVersion: apiextensions.k8s.io/v1 |
||||||
|
metadata: |
||||||
|
name: teams.team.core.grafana.com |
||||||
|
spec: |
||||||
|
group: team.core.grafana.com |
||||||
|
versions: |
||||||
|
- name: v0-0alpha1 |
||||||
|
served: true |
||||||
|
storage: true |
||||||
|
schema: |
||||||
|
openAPIV3Schema: |
||||||
|
properties: |
||||||
|
spec: |
||||||
|
properties: |
||||||
|
accessControl: |
||||||
|
additionalProperties: |
||||||
|
type: boolean |
||||||
|
description: AccessControl metadata associated with a given resource. |
||||||
|
type: object |
||||||
|
avatarUrl: |
||||||
|
description: AvatarUrl is the team's avatar URL. |
||||||
|
type: string |
||||||
|
created: |
||||||
|
description: Created indicates when the team was created. |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
email: |
||||||
|
description: Email of the team. |
||||||
|
type: string |
||||||
|
memberCount: |
||||||
|
description: MemberCount is the number of the team members. |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
name: |
||||||
|
description: Name of the team. |
||||||
|
type: string |
||||||
|
orgId: |
||||||
|
description: OrgId is the ID of an organisation the team belongs to. |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
permission: |
||||||
|
description: TODO - it seems it's a team_member.permission, unlikely it should belong to the team kind |
||||||
|
enum: |
||||||
|
- 0 |
||||||
|
- 1 |
||||||
|
- 2 |
||||||
|
- 4 |
||||||
|
type: integer |
||||||
|
updated: |
||||||
|
description: Updated indicates when the team was updated. |
||||||
|
format: int64 |
||||||
|
type: integer |
||||||
|
required: |
||||||
|
- orgId |
||||||
|
- name |
||||||
|
- memberCount |
||||||
|
- permission |
||||||
|
- created |
||||||
|
- updated |
||||||
|
type: object |
||||||
|
required: |
||||||
|
- spec |
||||||
|
type: object |
||||||
|
names: |
||||||
|
kind: Team |
||||||
|
plural: teams |
||||||
|
scope: Namespaced |
@ -0,0 +1,34 @@ |
|||||||
|
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Generated by:
|
||||||
|
// kinds/gen.go
|
||||||
|
// Using jennies:
|
||||||
|
// CRDTypesJenny
|
||||||
|
//
|
||||||
|
// Run 'make gen-cue' from repository root to regenerate.
|
||||||
|
|
||||||
|
package crd |
||||||
|
|
||||||
|
import ( |
||||||
|
_ "embed" |
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/kinds/team" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
) |
||||||
|
|
||||||
|
// The CRD YAML representation of the Team kind.
|
||||||
|
//
|
||||||
|
//go:embed team.crd.yml
|
||||||
|
var CRDYaml []byte |
||||||
|
|
||||||
|
// Team is the Go CRD representation of a single Team object.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type Team struct { |
||||||
|
k8ssys.Base[team.Team] |
||||||
|
} |
||||||
|
|
||||||
|
// TeamList is the Go CRD representation of a list Team objects.
|
||||||
|
// It implements [runtime.Object], and is used in k8s scheme construction.
|
||||||
|
type TeamList struct { |
||||||
|
k8ssys.ListBase[team.Team] |
||||||
|
} |
@ -0,0 +1,154 @@ |
|||||||
|
package k8ssys |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"reflect" |
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/kindsys" |
||||||
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" |
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
||||||
|
"k8s.io/apimachinery/pkg/runtime" |
||||||
|
k8schema "k8s.io/apimachinery/pkg/runtime/schema" |
||||||
|
) |
||||||
|
|
||||||
|
type Kind struct { |
||||||
|
GrafanaKind kindsys.Kind |
||||||
|
Object runtime.Object // singular type
|
||||||
|
ObjectList runtime.Object // list type
|
||||||
|
Schema apiextensionsv1.CustomResourceDefinition |
||||||
|
} |
||||||
|
|
||||||
|
// TODO this could probably be done in CUE/framework
|
||||||
|
func (crd Kind) GVK() k8schema.GroupVersionKind { |
||||||
|
// TODO custom structured
|
||||||
|
props := crd.GrafanaKind.Props().(kindsys.CoreProperties) |
||||||
|
gvk := k8schema.GroupVersionKind{ |
||||||
|
Group: fmt.Sprintf("%s.core.grafana.com", props.MachineName), |
||||||
|
Kind: props.Name, |
||||||
|
} |
||||||
|
if props.Maturity.Less(kindsys.MaturityStable) { |
||||||
|
gvk.Version = "v0-0alpha1" |
||||||
|
} else { |
||||||
|
gvk.Version = fmt.Sprintf("v%d-%d", props.CurrentVersion[0], props.CurrentVersion[1]) |
||||||
|
} |
||||||
|
|
||||||
|
return gvk |
||||||
|
} |
||||||
|
|
||||||
|
// CustomResourceDefinitionList is the kubernetes-API-compliant representation of a list of CustomResourceDefinitions
|
||||||
|
type CustomResourceDefinitionList struct { |
||||||
|
ListBase[CustomResourceDefinition] |
||||||
|
} |
||||||
|
|
||||||
|
// CustomResourceDefinition is the kubernetes-API-compliant representation of a Custom Resource Definition
|
||||||
|
type CustomResourceDefinition struct { |
||||||
|
metav1.TypeMeta `json:",inline" yaml:",inline"` |
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"` |
||||||
|
Spec CustomResourceDefinitionSpec `json:"spec"` |
||||||
|
} |
||||||
|
|
||||||
|
// DeepCopyObject implements runtime.Object.
|
||||||
|
func (crd *CustomResourceDefinition) DeepCopyObject() runtime.Object { |
||||||
|
return DeepCopyObject(crd) |
||||||
|
} |
||||||
|
|
||||||
|
// CustomResourceDefinitionSpec is the body or spec of a kubernetes Custom Resource Definition
|
||||||
|
type CustomResourceDefinitionSpec struct { |
||||||
|
Group string `json:"group" yaml:"group"` |
||||||
|
Versions []CustomResourceDefinitionSpecVersion `json:"versions" yaml:"versions"` |
||||||
|
Names CustomResourceDefinitionSpecNames `json:"names" yaml:"names"` |
||||||
|
Scope string `json:"scope" yaml:"scope"` |
||||||
|
} |
||||||
|
|
||||||
|
// CustomResourceDefinitionSpecVersion is the representation of a specific version of a CRD, as part of the overall spec
|
||||||
|
type CustomResourceDefinitionSpecVersion struct { |
||||||
|
Name string `json:"name" yaml:"name"` |
||||||
|
Served bool `json:"served" yaml:"served"` |
||||||
|
Storage bool `json:"storage" yaml:"storage"` |
||||||
|
Schema map[string]any `json:"schema" yaml:"schema"` |
||||||
|
Subresources map[string]any `json:"subresources,omitempty" yaml:"subresources,omitempty"` |
||||||
|
} |
||||||
|
|
||||||
|
// CustomResourceDefinitionSpecNames is the struct representing the names (kind and plural) of a kubernetes CRD
|
||||||
|
type CustomResourceDefinitionSpecNames struct { |
||||||
|
Kind string `json:"kind" yaml:"kind"` |
||||||
|
Plural string `json:"plural" yaml:"plural"` |
||||||
|
} |
||||||
|
|
||||||
|
// Base is a struct which describes a basic CRD, and implements runtime.Object.
|
||||||
|
// SpecType should be the struct that represents the spec in the definition.
|
||||||
|
// It cannot be used on its own, as the name of the CRD in kubernetes must exactly match the name of struct.
|
||||||
|
// Instead, this struct can be used as a component of a new named struct, for examples:
|
||||||
|
//
|
||||||
|
// type MyCustomResource struct {
|
||||||
|
// crd.Base[MyCustomResourceSpec]
|
||||||
|
// }
|
||||||
|
type Base[SpecType any] struct { |
||||||
|
metav1.TypeMeta `json:",inline"` |
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"` |
||||||
|
Spec SpecType `json:"spec"` |
||||||
|
} |
||||||
|
|
||||||
|
// DeepCopyObject is implemented for Base so it will implement runtime.Object.
|
||||||
|
// DeepCopyObject here just calls crd.DeepCopyObject on itself.
|
||||||
|
func (b *Base[T]) DeepCopyObject() runtime.Object { |
||||||
|
return DeepCopyObject(b) |
||||||
|
} |
||||||
|
|
||||||
|
// ListBase is a struct which describes a list of CRDs, and implements runtime.Object.
|
||||||
|
// ItemType should be the CRD type being listed (NOT the model).
|
||||||
|
// It cannot be used on its own, as the struct name must exactly match `<name of kubernetes CRD>List`.
|
||||||
|
// Instead, this struct can be used as a component of a new named struct, for examples:
|
||||||
|
//
|
||||||
|
// type MyCustomResourceList struct {
|
||||||
|
// crd.Base[MyCustomResource]
|
||||||
|
// }
|
||||||
|
type ListBase[ItemType any] struct { |
||||||
|
metav1.TypeMeta `json:",inline"` |
||||||
|
metav1.ListMeta `json:"metadata"` |
||||||
|
Items []ItemType `json:"items"` |
||||||
|
} |
||||||
|
|
||||||
|
// DeepCopyObject is implemented for Base so it will implement runtime.Object.
|
||||||
|
// DeepCopyObject here just calls crd.DeepCopyObject on itself.
|
||||||
|
func (b *ListBase[T]) DeepCopyObject() runtime.Object { |
||||||
|
return DeepCopyObject(b) |
||||||
|
} |
||||||
|
|
||||||
|
// BaseStatus extends Base by including a Status subresource.
|
||||||
|
// This should be used if your kubernetes CRD includes the status subresource and you want to be able to view/modify it.
|
||||||
|
// Usage is identical to Base
|
||||||
|
type BaseStatus[SpecType, StatusType any] struct { |
||||||
|
metav1.TypeMeta `json:",inline"` |
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"` |
||||||
|
Spec SpecType `json:"spec"` |
||||||
|
Status StatusType `json:"status"` |
||||||
|
} |
||||||
|
|
||||||
|
// DeepCopyObject is implemented for Base so it will implement runtime.Object.
|
||||||
|
// DeepCopyObject here just calls crd.DeepCopyObject on itself.
|
||||||
|
func (b *BaseStatus[T, S]) DeepCopyObject() runtime.Object { |
||||||
|
return DeepCopyObject(b) |
||||||
|
} |
||||||
|
|
||||||
|
// DeepCopyObject is an implementation of the receiver method required for implementing runtime.Object.
|
||||||
|
// It should be used in your own runtime.Object implementations if you do not wish to implement custom behavior.
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// func (c *CustomObject) DeepCopyObject() runtime.Object {
|
||||||
|
// return crd.DeepCopyObject(c)
|
||||||
|
// }
|
||||||
|
func DeepCopyObject(in any) runtime.Object { |
||||||
|
val := reflect.ValueOf(in).Elem() |
||||||
|
|
||||||
|
cpy := reflect.New(val.Type()) |
||||||
|
cpy.Elem().Set(val) |
||||||
|
|
||||||
|
// Using the <obj>, <ok> for the type conversion ensures that it doesn't panic if it can't be converted
|
||||||
|
if obj, ok := cpy.Interface().(runtime.Object); ok { |
||||||
|
return obj |
||||||
|
} |
||||||
|
|
||||||
|
// TODO: better return than nil?
|
||||||
|
return nil |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package corecrd |
||||||
|
|
||||||
|
import ( |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
"github.com/grafana/grafana/pkg/registry/corekind" |
||||||
|
"github.com/grafana/thema" |
||||||
|
) |
||||||
|
|
||||||
|
// New constructs a new [Registry].
|
||||||
|
//
|
||||||
|
// All calling code within grafana/grafana is expected to use Grafana's
|
||||||
|
// singleton [thema.Runtime], returned from [cuectx.GrafanaThemaRuntime]. If nil
|
||||||
|
// is passed, the singleton will be used.
|
||||||
|
func New(rt *thema.Runtime) *Registry { |
||||||
|
breg := corekind.NewBase(rt) |
||||||
|
return doNewRegistry(breg) |
||||||
|
} |
||||||
|
|
||||||
|
// All returns a slice of all core Grafana CRDs in the registry.
|
||||||
|
//
|
||||||
|
// The returned slice is guaranteed to be alphabetically sorted by kind name.
|
||||||
|
func (r *Registry) All() []k8ssys.Kind { |
||||||
|
all := make([]k8ssys.Kind, len(r.all)) |
||||||
|
copy(all, r.all[:]) |
||||||
|
return all |
||||||
|
} |
@ -0,0 +1,231 @@ |
|||||||
|
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Generated by:
|
||||||
|
// kinds/gen.go
|
||||||
|
// Using jennies:
|
||||||
|
// CRDKindRegistryJenny
|
||||||
|
//
|
||||||
|
// Run 'make gen-cue' from repository root to regenerate.
|
||||||
|
|
||||||
|
package corecrd |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
"fmt" |
||||||
|
|
||||||
|
dashboard "github.com/grafana/grafana/pkg/kinds/dashboard/crd" |
||||||
|
librarypanel "github.com/grafana/grafana/pkg/kinds/librarypanel/crd" |
||||||
|
playlist "github.com/grafana/grafana/pkg/kinds/playlist/crd" |
||||||
|
preferences "github.com/grafana/grafana/pkg/kinds/preferences/crd" |
||||||
|
publicdashboard "github.com/grafana/grafana/pkg/kinds/publicdashboard/crd" |
||||||
|
serviceaccount "github.com/grafana/grafana/pkg/kinds/serviceaccount/crd" |
||||||
|
team "github.com/grafana/grafana/pkg/kinds/team/crd" |
||||||
|
"github.com/grafana/grafana/pkg/kindsys/k8ssys" |
||||||
|
"github.com/grafana/grafana/pkg/registry/corekind" |
||||||
|
"gopkg.in/yaml.v3" |
||||||
|
) |
||||||
|
|
||||||
|
// Registry is a list of all of Grafana's core structured kinds, wrapped in a
|
||||||
|
// standard [k8ssys.CRD] interface that makes them usable for interactions
|
||||||
|
// with certain Kubernetes controller and apimachinery libraries.
|
||||||
|
//
|
||||||
|
// There are two access methods: individually via literal named methods, or as
|
||||||
|
// a slice returned from All() method.
|
||||||
|
//
|
||||||
|
// Prefer the individual named methods for use cases where the particular kind(s)
|
||||||
|
// that are needed are known to the caller. Prefer All() when performing operations
|
||||||
|
// generically across all kinds.
|
||||||
|
type Registry struct { |
||||||
|
all [7]k8ssys.Kind |
||||||
|
} |
||||||
|
|
||||||
|
// Dashboard returns the [k8ssys.Kind] instance for the Dashboard kind.
|
||||||
|
func (r *Registry) Dashboard() k8ssys.Kind { |
||||||
|
return r.all[0] |
||||||
|
} |
||||||
|
|
||||||
|
// LibraryPanel returns the [k8ssys.Kind] instance for the LibraryPanel kind.
|
||||||
|
func (r *Registry) LibraryPanel() k8ssys.Kind { |
||||||
|
return r.all[1] |
||||||
|
} |
||||||
|
|
||||||
|
// Playlist returns the [k8ssys.Kind] instance for the Playlist kind.
|
||||||
|
func (r *Registry) Playlist() k8ssys.Kind { |
||||||
|
return r.all[2] |
||||||
|
} |
||||||
|
|
||||||
|
// Preferences returns the [k8ssys.Kind] instance for the Preferences kind.
|
||||||
|
func (r *Registry) Preferences() k8ssys.Kind { |
||||||
|
return r.all[3] |
||||||
|
} |
||||||
|
|
||||||
|
// PublicDashboard returns the [k8ssys.Kind] instance for the PublicDashboard kind.
|
||||||
|
func (r *Registry) PublicDashboard() k8ssys.Kind { |
||||||
|
return r.all[4] |
||||||
|
} |
||||||
|
|
||||||
|
// ServiceAccount returns the [k8ssys.Kind] instance for the ServiceAccount kind.
|
||||||
|
func (r *Registry) ServiceAccount() k8ssys.Kind { |
||||||
|
return r.all[5] |
||||||
|
} |
||||||
|
|
||||||
|
// Team returns the [k8ssys.Kind] instance for the Team kind.
|
||||||
|
func (r *Registry) Team() k8ssys.Kind { |
||||||
|
return r.all[6] |
||||||
|
} |
||||||
|
|
||||||
|
func doNewRegistry(breg *corekind.Base) *Registry { |
||||||
|
var err error |
||||||
|
var b []byte |
||||||
|
var kk k8ssys.Kind |
||||||
|
reg := &Registry{} |
||||||
|
|
||||||
|
kk = k8ssys.Kind{ |
||||||
|
GrafanaKind: breg.Dashboard(), |
||||||
|
Object: &dashboard.Dashboard{}, |
||||||
|
ObjectList: &dashboard.DashboardList{}, |
||||||
|
} |
||||||
|
// TODO Having the committed form on disk in YAML is worth doing this for now...but fix this silliness
|
||||||
|
map0 := make(map[string]any) |
||||||
|
err = yaml.Unmarshal(dashboard.CRDYaml, map0) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("generated CRD YAML for Dashboard failed to unmarshal: %s", err)) |
||||||
|
} |
||||||
|
b, err = json.Marshal(map0) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not re-marshal CRD JSON for Dashboard: %s", err)) |
||||||
|
} |
||||||
|
err = json.Unmarshal(b, &kk.Schema) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not unmarshal CRD JSON for Dashboard: %s", err)) |
||||||
|
} |
||||||
|
reg.all[0] = kk |
||||||
|
|
||||||
|
kk = k8ssys.Kind{ |
||||||
|
GrafanaKind: breg.LibraryPanel(), |
||||||
|
Object: &librarypanel.LibraryPanel{}, |
||||||
|
ObjectList: &librarypanel.LibraryPanelList{}, |
||||||
|
} |
||||||
|
// TODO Having the committed form on disk in YAML is worth doing this for now...but fix this silliness
|
||||||
|
map1 := make(map[string]any) |
||||||
|
err = yaml.Unmarshal(librarypanel.CRDYaml, map1) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("generated CRD YAML for LibraryPanel failed to unmarshal: %s", err)) |
||||||
|
} |
||||||
|
b, err = json.Marshal(map1) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not re-marshal CRD JSON for LibraryPanel: %s", err)) |
||||||
|
} |
||||||
|
err = json.Unmarshal(b, &kk.Schema) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not unmarshal CRD JSON for LibraryPanel: %s", err)) |
||||||
|
} |
||||||
|
reg.all[1] = kk |
||||||
|
|
||||||
|
kk = k8ssys.Kind{ |
||||||
|
GrafanaKind: breg.Playlist(), |
||||||
|
Object: &playlist.Playlist{}, |
||||||
|
ObjectList: &playlist.PlaylistList{}, |
||||||
|
} |
||||||
|
// TODO Having the committed form on disk in YAML is worth doing this for now...but fix this silliness
|
||||||
|
map2 := make(map[string]any) |
||||||
|
err = yaml.Unmarshal(playlist.CRDYaml, map2) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("generated CRD YAML for Playlist failed to unmarshal: %s", err)) |
||||||
|
} |
||||||
|
b, err = json.Marshal(map2) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not re-marshal CRD JSON for Playlist: %s", err)) |
||||||
|
} |
||||||
|
err = json.Unmarshal(b, &kk.Schema) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not unmarshal CRD JSON for Playlist: %s", err)) |
||||||
|
} |
||||||
|
reg.all[2] = kk |
||||||
|
|
||||||
|
kk = k8ssys.Kind{ |
||||||
|
GrafanaKind: breg.Preferences(), |
||||||
|
Object: &preferences.Preferences{}, |
||||||
|
ObjectList: &preferences.PreferencesList{}, |
||||||
|
} |
||||||
|
// TODO Having the committed form on disk in YAML is worth doing this for now...but fix this silliness
|
||||||
|
map3 := make(map[string]any) |
||||||
|
err = yaml.Unmarshal(preferences.CRDYaml, map3) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("generated CRD YAML for Preferences failed to unmarshal: %s", err)) |
||||||
|
} |
||||||
|
b, err = json.Marshal(map3) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not re-marshal CRD JSON for Preferences: %s", err)) |
||||||
|
} |
||||||
|
err = json.Unmarshal(b, &kk.Schema) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not unmarshal CRD JSON for Preferences: %s", err)) |
||||||
|
} |
||||||
|
reg.all[3] = kk |
||||||
|
|
||||||
|
kk = k8ssys.Kind{ |
||||||
|
GrafanaKind: breg.PublicDashboard(), |
||||||
|
Object: &publicdashboard.PublicDashboard{}, |
||||||
|
ObjectList: &publicdashboard.PublicDashboardList{}, |
||||||
|
} |
||||||
|
// TODO Having the committed form on disk in YAML is worth doing this for now...but fix this silliness
|
||||||
|
map4 := make(map[string]any) |
||||||
|
err = yaml.Unmarshal(publicdashboard.CRDYaml, map4) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("generated CRD YAML for PublicDashboard failed to unmarshal: %s", err)) |
||||||
|
} |
||||||
|
b, err = json.Marshal(map4) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not re-marshal CRD JSON for PublicDashboard: %s", err)) |
||||||
|
} |
||||||
|
err = json.Unmarshal(b, &kk.Schema) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not unmarshal CRD JSON for PublicDashboard: %s", err)) |
||||||
|
} |
||||||
|
reg.all[4] = kk |
||||||
|
|
||||||
|
kk = k8ssys.Kind{ |
||||||
|
GrafanaKind: breg.ServiceAccount(), |
||||||
|
Object: &serviceaccount.ServiceAccount{}, |
||||||
|
ObjectList: &serviceaccount.ServiceAccountList{}, |
||||||
|
} |
||||||
|
// TODO Having the committed form on disk in YAML is worth doing this for now...but fix this silliness
|
||||||
|
map5 := make(map[string]any) |
||||||
|
err = yaml.Unmarshal(serviceaccount.CRDYaml, map5) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("generated CRD YAML for ServiceAccount failed to unmarshal: %s", err)) |
||||||
|
} |
||||||
|
b, err = json.Marshal(map5) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not re-marshal CRD JSON for ServiceAccount: %s", err)) |
||||||
|
} |
||||||
|
err = json.Unmarshal(b, &kk.Schema) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not unmarshal CRD JSON for ServiceAccount: %s", err)) |
||||||
|
} |
||||||
|
reg.all[5] = kk |
||||||
|
|
||||||
|
kk = k8ssys.Kind{ |
||||||
|
GrafanaKind: breg.Team(), |
||||||
|
Object: &team.Team{}, |
||||||
|
ObjectList: &team.TeamList{}, |
||||||
|
} |
||||||
|
// TODO Having the committed form on disk in YAML is worth doing this for now...but fix this silliness
|
||||||
|
map6 := make(map[string]any) |
||||||
|
err = yaml.Unmarshal(team.CRDYaml, map6) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("generated CRD YAML for Team failed to unmarshal: %s", err)) |
||||||
|
} |
||||||
|
b, err = json.Marshal(map6) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not re-marshal CRD JSON for Team: %s", err)) |
||||||
|
} |
||||||
|
err = json.Unmarshal(b, &kk.Schema) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Sprintf("could not unmarshal CRD JSON for Team: %s", err)) |
||||||
|
} |
||||||
|
reg.all[6] = kk |
||||||
|
|
||||||
|
return reg |
||||||
|
} |
Loading…
Reference in new issue